1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-06 01:28:57 +00:00

Made attempt to introduce final filtering stage and output.

This commit is contained in:
Thomas Harte 2016-04-22 19:15:59 -04:00
parent 23311d633b
commit 95639f1189
2 changed files with 99 additions and 55 deletions

View File

@ -255,9 +255,10 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
};
OpenGL::Shader *shaders[] = {
composite_input_shader_program.get(),
composite_y_filter_shader_program.get()
composite_y_filter_shader_program.get(),
composite_chrominance_filter_shader_program.get()
};
for(int stage = 0; stage < 2; stage++)
for(int stage = 0; stage < 3; stage++)
{
// switch to the initial texture
targets[stage]->bind_framebuffer();
@ -532,7 +533,8 @@ char *OpenGLOutputBuilder::get_y_filter_fragment_shader()
"0.0"
")"
");"
"vec2 quadrature = vec2(sin(phaseVarying), cos(phaseVarying)) * 0.5;"
"vec2 quadrature = vec2(sin(phaseVarying), cos(phaseVarying)) * vec2(0.5);"
"float luminance = "
"dot(vec3("
"dot(samples[0], weights[0]),"
@ -540,10 +542,70 @@ char *OpenGLOutputBuilder::get_y_filter_fragment_shader()
"dot(samples[2], weights[2])"
"), vec3(1.0));"
"float chrominance = (samples[1].y - luminance) / amplitudeVarying;"
"fragColour = vec3(luminance, vec2(0.5) + chrominance * quadrature );"
"fragColour = vec3(luminance, vec2(0.5) + (chrominance * quadrature));"
"}");
}
char *OpenGLOutputBuilder::get_chrominance_filter_fragment_shader()
{
return strdup(
"#version 150\n"
"in float phaseVarying;"
"in float amplitudeVarying;"
"in vec2 inputPositionsVarying[11];"
"uniform vec4 weights[3];"
"out vec3 fragColour;"
"uniform sampler2D texID;"
"void main(void)"
"{"
// "fragColour = texture(texID, inputPositionsVarying[5]).rgb;"
"vec3 centreSample = texture(texID, inputPositionsVarying[5]).rgb;"
"vec2 samples[] = vec2[]("
"texture(texID, inputPositionsVarying[0]).gb,"
"texture(texID, inputPositionsVarying[1]).gb,"
"texture(texID, inputPositionsVarying[2]).gb,"
"texture(texID, inputPositionsVarying[3]).gb,"
"texture(texID, inputPositionsVarying[4]).gb,"
"centreSample.gb,"
"texture(texID, inputPositionsVarying[6]).gb,"
"texture(texID, inputPositionsVarying[7]).gb,"
"texture(texID, inputPositionsVarying[8]).gb,"
"texture(texID, inputPositionsVarying[9]).gb,"
"texture(texID, inputPositionsVarying[10]).gb"
");"
"vec4 channel1[3] = vec4[]("
"vec4(samples[0].r, samples[1].r, samples[2].r, samples[3].r),"
"vec4(samples[4].r, samples[5].r, samples[6].r, samples[7].r),"
"vec4(samples[8].r, samples[9].r, samples[10].r, 0.0)"
");"
"vec4 channel2[3] = vec4[]("
"vec4(samples[0].g, samples[1].g, samples[2].g, samples[3].g),"
"vec4(samples[4].g, samples[5].g, samples[6].g, samples[7].g),"
"vec4(samples[8].g, samples[9].g, samples[10].g, 0.0)"
");"
"fragColour = vec3(centreSample.r,"
"dot(vec3("
"dot(channel1[0], weights[0]),"
"dot(channel1[1], weights[1]),"
"dot(channel1[2], weights[2])"
"), vec3(1.0, 1.0, 1.0)),"
"dot(vec3("
"dot(channel1[0], weights[0]),"
"dot(channel1[1], weights[1]),"
"dot(channel1[2], weights[2])"
"), vec3(1.0, 1.0, 1.0))"
");"
"}");
}
#pragma mark - Intermediate vertex shaders (i.e. from intermediate line layout to intermediate line layout)
#pragma mark - Output vertex shader
@ -593,7 +655,7 @@ char *OpenGLOutputBuilder::get_output_vertex_shader(const char *header)
"iSrcCoordinatesVarying = srcCoordinates;"
"srcCoordinatesVarying = vec2(srcCoordinates.x / textureSize.x, (srcCoordinates.y + 0.5) / textureSize.y);"
"float age = (timestampBase[int(lateralAndTimestampBaseOffset.y)] - timestamp) / ticksPerFrame;"
"alpha = exp(-age*0.5) + 0.2;"
"alpha = 15.0*exp(-age*3.0);" //+ 0.2
"vec2 floatingPosition = (position / positionConversion) + lateralAndTimestampBaseOffset.x * scanNormal;"
"vec2 mappedPosition = (floatingPosition - boundsOrigin) / boundsSize;"
@ -616,13 +678,20 @@ char *OpenGLOutputBuilder::get_composite_output_vertex_shader()
char *OpenGLOutputBuilder::get_rgb_output_fragment_shader()
{
return get_output_fragment_shader(_rgb_shader, "uniform usampler2D texID;", "rgb_sample(texID, srcCoordinatesVarying, iSrcCoordinatesVarying)");
return get_output_fragment_shader(_rgb_shader, "uniform usampler2D texID;",
"vec3 colour = rgb_sample(texID, srcCoordinatesVarying, iSrcCoordinatesVarying);");
}
char *OpenGLOutputBuilder::get_composite_output_fragment_shader()
{
// "const mat3 yuvToRGB = mat3(1.0, 1.0, 1.0, 0.0, -0.39465, 2.03211, 1.13983, -0.58060, 0.0);"
return get_output_fragment_shader("", "uniform sampler2D texID;", "texture(texID, srcCoordinatesVarying).rgb");
return get_output_fragment_shader("",
"uniform sampler2D texID;"
"const mat3 yuvToRGB = mat3(1.0, 1.0, 1.0, 0.0, -0.39465, 2.03211, 1.13983, -0.58060, 0.0);",
"vec3 srcColour = texture(texID, srcCoordinatesVarying).rgb;"
"vec3 yuvColour = vec3(srcColour.r, (srcColour.gb - vec2(0.5, 0.5)) * vec2(2.0, 2.0));"
"vec3 colour = yuvToRGB * yuvColour; "
);
}
char *OpenGLOutputBuilder::get_output_fragment_shader(const char *sampling_function, const char *header, const char *fragColour_function)
@ -644,7 +713,8 @@ char *OpenGLOutputBuilder::get_output_fragment_shader(const char *sampling_funct
"%s\n"
"void main(void)"
"{"
"fragColour = vec4(%s, clamp(alpha, 0.0, 1.0)*sin(lateralVarying));"
"\n%s\n"
"fragColour = vec4(colour, clamp(alpha, 0.0, 1.0)*sin(lateralVarying));"
"}",
header, sampling_function, fragColour_function);
@ -655,6 +725,9 @@ char *OpenGLOutputBuilder::get_output_fragment_shader(const char *sampling_funct
std::unique_ptr<OpenGL::Shader> OpenGLOutputBuilder::prepare_intermediate_shader(const char *input_position, const char *header, char *fragment_shader, GLenum texture_unit, bool extends)
{
// TODO: at the minute, allowing extensions seems to throw the colour phase out of whack between encoding and decoding. Figure out why.
extends = false;
std::unique_ptr<OpenGL::Shader> shader;
char *vertex_shader = get_input_vertex_shader(input_position, header);
if(vertex_shader && fragment_shader)
@ -693,13 +766,22 @@ void OpenGLOutputBuilder::prepare_composite_input_shader()
composite_input_shader_program = prepare_intermediate_shader("inputPosition", "uniform usampler2D texID;", get_input_fragment_shader(), source_data_texture_unit, false);
float colour_subcarrier_frequency = (float)_colour_cycle_numerator / (float)_colour_cycle_denominator;
SignalProcessing::FIRFilter luminance_filter(11, _cycles_per_line, 0.0f, colour_subcarrier_frequency - 50, SignalProcessing::FIRFilter::DefaultAttenuation);
composite_y_filter_shader_program = prepare_intermediate_shader("outputPosition", "uniform sampler2D texID;", get_y_filter_fragment_shader(), composite_texture_unit, true);
composite_y_filter_shader_program->bind();
GLint weightsUniform = composite_y_filter_shader_program->get_uniform_location("weights");
GLint weightsUniform;
float weights[12];
composite_y_filter_shader_program = prepare_intermediate_shader("outputPosition", "uniform sampler2D texID;", get_y_filter_fragment_shader(), composite_texture_unit, true);
SignalProcessing::FIRFilter luminance_filter(11, _cycles_per_line, 0.0f, colour_subcarrier_frequency - 50, SignalProcessing::FIRFilter::DefaultAttenuation);
composite_y_filter_shader_program->bind();
weightsUniform = composite_y_filter_shader_program->get_uniform_location("weights");
luminance_filter.get_coefficients(weights);
glUniform4fv(weightsUniform, 3, weights);
composite_chrominance_filter_shader_program = prepare_intermediate_shader("outputPosition", "uniform sampler2D texID;", get_chrominance_filter_fragment_shader(), filtered_y_texture_unit, false);
SignalProcessing::FIRFilter chrominance_filter(11, _cycles_per_line, 0.0f, colour_subcarrier_frequency * 0.5f, SignalProcessing::FIRFilter::DefaultAttenuation);
composite_chrominance_filter_shader_program->bind();
weightsUniform = composite_chrominance_filter_shader_program->get_uniform_location("weights");
chrominance_filter.get_coefficients(weights);
glUniform4fv(weightsUniform, 3, weights);
}
void OpenGLOutputBuilder::prepare_source_vertex_array()
@ -727,46 +809,6 @@ void OpenGLOutputBuilder::prepare_source_vertex_array()
}
}
/*void OpenGLOutputBuilder::prepare_output_shader(char *fragment_shader)
{
char *vertex_shader = get_output_vertex_shader();
if(vertex_shader && fragment_shader)
{
_openGL_state->rgb_shader_program = std::unique_ptr<OpenGL::Shader>(new OpenGL::Shader(vertex_shader, fragment_shader));
_openGL_state->rgb_shader_program->bind();
_openGL_state->windowSizeUniform = _openGL_state->rgb_shader_program->get_uniform_location("windowSize");
_openGL_state->boundsSizeUniform = _openGL_state->rgb_shader_program->get_uniform_location("boundsSize");
_openGL_state->boundsOriginUniform = _openGL_state->rgb_shader_program->get_uniform_location("boundsOrigin");
_openGL_state->timestampBaseUniform = _openGL_state->rgb_shader_program->get_uniform_location("timestampBase");
GLint texIDUniform = _openGL_state->rgb_shader_program->get_uniform_location("texID");
GLint shadowMaskTexIDUniform = _openGL_state->rgb_shader_program->get_uniform_location("shadowMaskTexID");
GLint textureSizeUniform = _openGL_state->rgb_shader_program->get_uniform_location("textureSize");
GLint ticksPerFrameUniform = _openGL_state->rgb_shader_program->get_uniform_location("ticksPerFrame");
GLint scanNormalUniform = _openGL_state->rgb_shader_program->get_uniform_location("scanNormal");
GLint positionConversionUniform = _openGL_state->rgb_shader_program->get_uniform_location("positionConversion");
glUniform1i(texIDUniform, first_supplied_buffer_texture_unit);
glUniform1i(shadowMaskTexIDUniform, 1);
glUniform2f(textureSizeUniform, CRTInputBufferBuilderWidth, CRTInputBufferBuilderHeight);
glUniform1f(ticksPerFrameUniform, (GLfloat)(_cycles_per_line * _height_of_display));
glUniform2f(positionConversionUniform, _horizontal_flywheel->get_scan_period(), _vertical_flywheel->get_scan_period() / (unsigned int)_vertical_flywheel_output_divider);
float scan_angle = atan2f(1.0f / (float)_height_of_display, 1.0f);
float scan_normal[] = { -sinf(scan_angle), cosf(scan_angle)};
float multiplier = (float)_horizontal_flywheel->get_standard_period() / ((float)_height_of_display * (float)_horizontal_flywheel->get_scan_period());
scan_normal[0] *= multiplier;
scan_normal[1] *= multiplier;
glUniform2f(scanNormalUniform, scan_normal[0], scan_normal[1]);
}
free(vertex_shader);
free(fragment_shader);
}*/
std::unique_ptr<OpenGL::Shader> OpenGLOutputBuilder::prepare_output_shader(char *vertex_shader, char *fragment_shader, GLint source_texture_unit)
{
std::unique_ptr<OpenGL::Shader> shader_program;
@ -819,7 +861,7 @@ void OpenGLOutputBuilder::prepare_rgb_output_shader()
void OpenGLOutputBuilder::prepare_composite_output_shader()
{
composite_output_shader_program = prepare_output_shader(get_composite_output_vertex_shader(), get_composite_output_fragment_shader(), filtered_y_texture_unit);
composite_output_shader_program = prepare_output_shader(get_composite_output_vertex_shader(), get_composite_output_fragment_shader(), filtered_texture_unit);
}
void OpenGLOutputBuilder::prepare_output_vertex_array()

View File

@ -75,10 +75,12 @@ class OpenGLOutputBuilder {
char *get_input_vertex_shader(const char *input_position, const char *header);
char *get_input_fragment_shader();
char *get_y_filter_fragment_shader();
char *get_chrominance_filter_fragment_shader();
std::unique_ptr<OpenGL::Shader> rgb_shader_program;
std::unique_ptr<OpenGL::Shader> composite_input_shader_program, composite_y_filter_shader_program, composite_output_shader_program;
std::unique_ptr<OpenGL::Shader> composite_input_shader_program, composite_y_filter_shader_program, composite_chrominance_filter_shader_program, composite_output_shader_program;
GLuint output_array_buffer, output_vertex_array;
GLuint source_array_buffer, source_vertex_array;