mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-18 01:30:56 +00:00
Starts towards a flattening of the intermediate video processing.
Immediate issue: using x position to index into a bitmap sampled at the input data rate doesn't allow for the disconnection between input rate and output speed provided by the flywheels.
This commit is contained in:
parent
fd0ffc7085
commit
46d756d298
@ -47,8 +47,8 @@ GLuint Shader::compile_shader(const std::string &source, GLenum type) {
|
|||||||
|
|
||||||
Shader::Shader(const std::string &vertex_shader, const std::string &fragment_shader, const std::vector<AttributeBinding> &attribute_bindings) {
|
Shader::Shader(const std::string &vertex_shader, const std::string &fragment_shader, const std::vector<AttributeBinding> &attribute_bindings) {
|
||||||
shader_program_ = glCreateProgram();
|
shader_program_ = glCreateProgram();
|
||||||
GLuint vertex = compile_shader(vertex_shader, GL_VERTEX_SHADER);
|
const GLuint vertex = compile_shader(vertex_shader, GL_VERTEX_SHADER);
|
||||||
GLuint fragment = compile_shader(fragment_shader, GL_FRAGMENT_SHADER);
|
const GLuint fragment = compile_shader(fragment_shader, GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
glAttachShader(shader_program_, vertex);
|
glAttachShader(shader_program_, vertex);
|
||||||
glAttachShader(shader_program_, fragment);
|
glAttachShader(shader_program_, fragment);
|
||||||
@ -60,17 +60,18 @@ Shader::Shader(const std::string &vertex_shader, const std::string &fragment_sha
|
|||||||
glLinkProgram(shader_program_);
|
glLinkProgram(shader_program_);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
GLint logLength;
|
||||||
|
glGetProgramiv(shader_program_, GL_INFO_LOG_LENGTH, &logLength);
|
||||||
|
if(logLength > 0) {
|
||||||
|
GLchar *log = new GLchar[static_cast<std::size_t>(logLength)];
|
||||||
|
glGetProgramInfoLog(shader_program_, logLength, &logLength, log);
|
||||||
|
printf("Link log:\n%s\n", log);
|
||||||
|
delete[] log;
|
||||||
|
}
|
||||||
|
|
||||||
GLint didLink = 0;
|
GLint didLink = 0;
|
||||||
glGetProgramiv(shader_program_, GL_LINK_STATUS, &didLink);
|
glGetProgramiv(shader_program_, GL_LINK_STATUS, &didLink);
|
||||||
if(didLink == GL_FALSE) {
|
if(didLink == GL_FALSE) {
|
||||||
GLint logLength;
|
|
||||||
glGetProgramiv(shader_program_, GL_INFO_LOG_LENGTH, &logLength);
|
|
||||||
if(logLength > 0) {
|
|
||||||
GLchar *log = new GLchar[static_cast<std::size_t>(logLength)];
|
|
||||||
glGetProgramInfoLog(shader_program_, logLength, &logLength, log);
|
|
||||||
printf("Link log:\n%s\n", log);
|
|
||||||
delete[] log;
|
|
||||||
}
|
|
||||||
throw ProgramLinkageError;
|
throw ProgramLinkageError;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,10 +14,10 @@ using namespace Outputs::Display::OpenGL;
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// The texture unit from which to source input data.
|
/// The texture unit from which to source input data.
|
||||||
constexpr GLenum SourceDataTextureUnit = GL_TEXTURE0;
|
constexpr GLenum SourceDataTextureUnit = GL_TEXTURE1;
|
||||||
|
|
||||||
/// The texture unit which contains raw line-by-line composite, S-Video or RGB data.
|
/// The texture unit which contains raw line-by-line composite, S-Video or RGB data.
|
||||||
constexpr GLenum UnprocessedLineBufferTextureUnit = GL_TEXTURE1;
|
constexpr GLenum UnprocessedLineBufferTextureUnit = GL_TEXTURE3;
|
||||||
|
|
||||||
/// The texture unit that contains the current display.
|
/// The texture unit that contains the current display.
|
||||||
constexpr GLenum AccumulationTextureUnit = GL_TEXTURE2;
|
constexpr GLenum AccumulationTextureUnit = GL_TEXTURE2;
|
||||||
@ -288,7 +288,7 @@ void ScanTarget::setup_pipeline() {
|
|||||||
// lose any detail when combining the input.
|
// lose any detail when combining the input.
|
||||||
processing_width_ = modals_.cycles_per_line / modals_.clocks_per_pixel_greatest_common_divisor;
|
processing_width_ = modals_.cycles_per_line / modals_.clocks_per_pixel_greatest_common_divisor;
|
||||||
|
|
||||||
// Establish an output shader. TODO: add gamma correction here.
|
// Establish an output shader. TODO: add proper decoding and gamma correction here.
|
||||||
output_shader_.reset(new Shader(
|
output_shader_.reset(new Shader(
|
||||||
glsl_globals(ShaderType::Line) + glsl_default_vertex_shader(ShaderType::Line),
|
glsl_globals(ShaderType::Line) + glsl_default_vertex_shader(ShaderType::Line),
|
||||||
"#version 150\n"
|
"#version 150\n"
|
||||||
@ -312,8 +312,24 @@ void ScanTarget::setup_pipeline() {
|
|||||||
output_shader_->set_uniform("size", modals_.visible_area.size.width, modals_.visible_area.size.height);
|
output_shader_->set_uniform("size", modals_.visible_area.size.width, modals_.visible_area.size.height);
|
||||||
output_shader_->set_uniform("textureName", GLint(UnprocessedLineBufferTextureUnit - GL_TEXTURE0));
|
output_shader_->set_uniform("textureName", GLint(UnprocessedLineBufferTextureUnit - GL_TEXTURE0));
|
||||||
|
|
||||||
|
// switch(modals_.composite_colour_space) {
|
||||||
|
// case ColourSpace::YIQ: {
|
||||||
|
// const GLfloat rgbToYIQ[] = {0.299f, 0.596f, 0.211f, 0.587f, -0.274f, -0.523f, 0.114f, -0.322f, 0.312f};
|
||||||
|
// const GLfloat yiqToRGB[] = {1.0f, 1.0f, 1.0f, 0.956f, -0.272f, -1.106f, 0.621f, -0.647f, 1.703f};
|
||||||
|
// shader->set_uniform_matrix("lumaChromaToRGB", 3, false, yiqToRGB);
|
||||||
|
// shader->set_uniform_matrix("rgbToLumaChroma", 3, false, rgbToYIQ);
|
||||||
|
// } break;
|
||||||
|
//
|
||||||
|
// case ColourSpace::YUV: {
|
||||||
|
// const GLfloat rgbToYUV[] = {0.299f, -0.14713f, 0.615f, 0.587f, -0.28886f, -0.51499f, 0.114f, 0.436f, -0.10001f};
|
||||||
|
// const GLfloat yuvToRGB[] = {1.0f, 1.0f, 1.0f, 0.0f, -0.39465f, 2.03211f, 1.13983f, -0.58060f, 0.0f};
|
||||||
|
// shader->set_uniform_matrix("lumaChromaToRGB", 3, false, yuvToRGB);
|
||||||
|
// shader->set_uniform_matrix("rgbToLumaChroma", 3, false, rgbToYUV);
|
||||||
|
// } break;
|
||||||
|
// }
|
||||||
|
|
||||||
// Establish an input shader.
|
// Establish an input shader.
|
||||||
input_shader_ = composition_shader();
|
input_shader_ = composition_shader(modals_.input_data_type);
|
||||||
glBindVertexArray(scan_vertex_array_);
|
glBindVertexArray(scan_vertex_array_);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, scan_buffer_name_);
|
glBindBuffer(GL_ARRAY_BUFFER, scan_buffer_name_);
|
||||||
enable_vertex_attributes(ShaderType::InputScan, *input_shader_);
|
enable_vertex_attributes(ShaderType::InputScan, *input_shader_);
|
||||||
@ -492,7 +508,7 @@ void ScanTarget::draw(bool synchronous, int output_width, int output_height) {
|
|||||||
// Enable blending and stenciling, and ensure spans increment the stencil buffer.
|
// Enable blending and stenciling, and ensure spans increment the stencil buffer.
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glEnable(GL_STENCIL_TEST);
|
glEnable(GL_STENCIL_TEST);
|
||||||
glStencilFunc(GL_EQUAL, 0, GLuint(-1));
|
glStencilFunc(GL_EQUAL, 0, GLuint(~0));
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
||||||
|
|
||||||
// Prepare to output lines.
|
// Prepare to output lines.
|
||||||
|
@ -179,7 +179,7 @@ class ScanTarget: public Outputs::Display::ScanTarget {
|
|||||||
std::unique_ptr<Shader> input_shader_;
|
std::unique_ptr<Shader> input_shader_;
|
||||||
std::unique_ptr<Shader> output_shader_;
|
std::unique_ptr<Shader> output_shader_;
|
||||||
|
|
||||||
static std::unique_ptr<Shader> composition_shader();
|
static std::unique_ptr<Shader> composition_shader(InputDataType input_data_type);
|
||||||
static std::unique_ptr<Shader> conversion_shader(InputDataType input_data_type, DisplayType display_type, int colour_cycle_numerator, int colour_cycle_denominator, int processing_width);
|
static std::unique_ptr<Shader> conversion_shader(InputDataType input_data_type, DisplayType display_type, int colour_cycle_numerator, int colour_cycle_denominator, int processing_width);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ std::string ScanTarget::glsl_default_vertex_shader(ShaderType type) {
|
|||||||
if(type == ShaderType::InputScan) {
|
if(type == ShaderType::InputScan) {
|
||||||
result +=
|
result +=
|
||||||
"out vec2 textureCoordinate;"
|
"out vec2 textureCoordinate;"
|
||||||
"uniform sampler2D textureName;";
|
"uniform usampler2D textureName;";
|
||||||
} else {
|
} else {
|
||||||
result +=
|
result +=
|
||||||
"out vec2 textureCoordinates[15];"
|
"out vec2 textureCoordinates[15];"
|
||||||
@ -240,7 +240,7 @@ void ScanTarget::enable_vertex_attributes(ShaderType type, Shader &target) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Shader> ScanTarget::composition_shader() {
|
std::unique_ptr<Shader> ScanTarget::composition_shader(InputDataType input_data_type) {
|
||||||
/* std::string fragment_shader =
|
/* std::string fragment_shader =
|
||||||
"#version 150\n"
|
"#version 150\n"
|
||||||
|
|
||||||
@ -350,21 +350,50 @@ std::unique_ptr<Shader> ScanTarget::composition_shader() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
const std::string fragment_shader =
|
std::string fragment_shader =
|
||||||
"#version 150\n"
|
"#version 150\n"
|
||||||
|
|
||||||
"in vec2 textureCoordinate;"
|
|
||||||
"out vec4 fragColour;"
|
"out vec4 fragColour;"
|
||||||
|
"in vec2 textureCoordinate;"
|
||||||
|
|
||||||
"uniform sampler2D textureName;"
|
"uniform usampler2D textureName;"
|
||||||
|
|
||||||
"void main(void) {"
|
"void main(void) {";
|
||||||
"fragColour = vec4(1.0) - texture(textureName, textureCoordinate);"
|
|
||||||
"}";
|
switch(input_data_type) {
|
||||||
|
case InputDataType::Luminance1:
|
||||||
|
fragment_shader += "fragColour = texture(textureName, textureCoordinate).rrrr;";
|
||||||
|
break;
|
||||||
|
case InputDataType::Luminance8:
|
||||||
|
fragment_shader += "fragColour = texture(textureName, textureCoordinate).rrrr / vec4(255.0);";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputDataType::PhaseLinkedLuminance8:
|
||||||
|
case InputDataType::Luminance8Phase8:
|
||||||
|
case InputDataType::Red8Green8Blue8:
|
||||||
|
fragment_shader += "fragColour = texture(textureName, textureCoordinate) / vec4(255.0);";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputDataType::Red1Green1Blue1:
|
||||||
|
fragment_shader += "fragColour = vec4(texture(textureName, textureCoordinate).rrr & uvec3(4u, 2u, 1u), 1.0);";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputDataType::Red2Green2Blue2:
|
||||||
|
fragment_shader +=
|
||||||
|
"uint textureValue = texture(textureName, textureCoordinate).r;"
|
||||||
|
"fragColour = vec4(float((textureValue >> 4) & 3u), float((textureValue >> 2) & 3u), float(textureValue & 3u), 3.0) / 3.0;";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InputDataType::Red4Green4Blue4:
|
||||||
|
fragment_shader +=
|
||||||
|
"uvec2 textureValue = texture(textureName, textureCoordinate).rg;"
|
||||||
|
"fragColour = vec4(float(textureValue.r) / 15.0, float(textureValue.g & 240u) / 240.0, float(textureValue.g & 15u) / 15.0, 1.0);";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return std::unique_ptr<Shader>(new Shader(
|
return std::unique_ptr<Shader>(new Shader(
|
||||||
glsl_globals(ShaderType::InputScan) + glsl_default_vertex_shader(ShaderType::InputScan),
|
glsl_globals(ShaderType::InputScan) + glsl_default_vertex_shader(ShaderType::InputScan),
|
||||||
fragment_shader,
|
fragment_shader + "}",
|
||||||
attribute_bindings(ShaderType::InputScan)
|
attribute_bindings(ShaderType::InputScan)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user