diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp index 6296b3e61..6ad598b9f 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.cpp +++ b/Outputs/CRT/Internals/CRTOpenGL.cpp @@ -381,11 +381,40 @@ void OpenGLOutputBuilder::set_timing_uniforms() extends = true; } - if(output_shader_program_) output_shader_program_->set_timing(height_of_display_, cycles_per_line_, horizontal_scan_period_, vertical_scan_period_, vertical_period_divider_); - float colour_subcarrier_frequency = (float)colour_cycle_numerator_ / (float)colour_cycle_denominator_; - if(composite_separation_filter_program_) composite_separation_filter_program_->set_separation_frequency(cycles_per_line_, colour_subcarrier_frequency); - if(composite_y_filter_shader_program_) composite_y_filter_shader_program_->set_filter_coefficients(cycles_per_line_, colour_subcarrier_frequency * 0.25f); - if(composite_chrominance_filter_shader_program_) composite_chrominance_filter_shader_program_->set_filter_coefficients(cycles_per_line_, colour_subcarrier_frequency * 0.5f); - if(rgb_filter_shader_program_) rgb_filter_shader_program_->set_filter_coefficients(cycles_per_line_, (float)input_frequency_ * 0.5f); + float output_width = ((float)colour_cycle_numerator_ * 4.0f) / (float)(colour_cycle_denominator_ * IntermediateBufferWidth); + + if(composite_separation_filter_program_) + { + composite_separation_filter_program_->set_width_scalers(output_width, output_width); + composite_separation_filter_program_->set_separation_frequency(cycles_per_line_, colour_subcarrier_frequency); + } + if(composite_y_filter_shader_program_) + { + composite_y_filter_shader_program_->set_width_scalers(output_width, output_width); + composite_y_filter_shader_program_->set_filter_coefficients(cycles_per_line_, colour_subcarrier_frequency * 0.25f); + } + if(composite_chrominance_filter_shader_program_) + { + composite_chrominance_filter_shader_program_->set_width_scalers(output_width, output_width); + composite_chrominance_filter_shader_program_->set_filter_coefficients(cycles_per_line_, colour_subcarrier_frequency * 0.5f); + } + if(rgb_filter_shader_program_) + { + rgb_filter_shader_program_->set_width_scalers(output_width, output_width); + rgb_filter_shader_program_->set_filter_coefficients(cycles_per_line_, (float)input_frequency_ * 0.5f); + } + if(output_shader_program_) + { + output_shader_program_->set_input_width_scaler(output_width); + output_shader_program_->set_timing(height_of_display_, cycles_per_line_, horizontal_scan_period_, vertical_scan_period_, vertical_period_divider_); + } + if(composite_input_shader_program_) + { + composite_input_shader_program_->set_width_scalers(1.0f, output_width); + } + if(rgb_input_shader_program_) + { + rgb_input_shader_program_->set_width_scalers(1.0f, output_width); + } } diff --git a/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp b/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp index efabbf7d5..abc21433a 100644 --- a/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp +++ b/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp @@ -45,6 +45,7 @@ std::unique_ptr IntermediateShader::make_shader(const char * "uniform float extension;" "uniform %s texID;" "uniform float offsets[5];" + "uniform vec2 widthScalers;" "out vec2 phaseAndAmplitudeVarying;" "out vec2 inputPositionsVarying[11];" @@ -59,8 +60,8 @@ std::unique_ptr IntermediateShader::make_shader(const char * // inputPosition.x is either inputStart.x or ends.x, depending on whether it is on the left or the right; // outputPosition.x is either outputStart.x or ends.y; // .ys are inputStart.y and outputStart.y respectively - "vec2 inputPosition = vec2(mix(inputStart.x, ends.x, extent), inputStart.y);" - "vec2 outputPosition = vec2(mix(outputStart.x, ends.y, extent), outputStart.y);" + "vec2 inputPosition = vec2(mix(inputStart.x, ends.x, extent)*widthScalers[0], inputStart.y);" + "vec2 outputPosition = vec2(mix(outputStart.x, ends.y, extent)*widthScalers[1], outputStart.y);" // extension is the amount to extend both the input and output by to add a full colour cycle at each end "vec2 extensionVector = vec2(extension, 0.0) * 2.0 * (extent - 0.5);" @@ -477,3 +478,8 @@ void IntermediateShader::set_colour_conversion_matrices(float *fromRGB, float *t set_uniform_matrix("lumaChromaToRGB", 3, false, toRGB); set_uniform_matrix("rgbToLumaChroma", 3, false, fromRGB); } + +void IntermediateShader::set_width_scalers(float input_scaler, float output_scaler) +{ + set_uniform("widthScalers", input_scaler, output_scaler); +} diff --git a/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp b/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp index a419da8be..63402fb88 100644 --- a/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp +++ b/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp @@ -88,6 +88,12 @@ public: */ void set_colour_conversion_matrices(float *fromRGB, float *toRGB); + /*! + Sets the proportions of the input and output areas that should be considered the whole width — 1.0 means use all available + space, 0.5 means use half, etc. + */ + void set_width_scalers(float input_scaler, float output_scaler); + private: static std::unique_ptr make_shader(const char *fragment_shader, bool use_usampler, bool input_is_inputPosition); }; diff --git a/Outputs/CRT/Internals/Shaders/OutputShader.cpp b/Outputs/CRT/Internals/Shaders/OutputShader.cpp index e139c954d..86f0f928c 100644 --- a/Outputs/CRT/Internals/Shaders/OutputShader.cpp +++ b/Outputs/CRT/Internals/Shaders/OutputShader.cpp @@ -38,6 +38,7 @@ std::unique_ptr OutputShader::make_shader(const char *fragment_met "uniform vec2 positionConversion;" "uniform vec2 scanNormal;" "uniform %s texID;" + "uniform float inputScaler;" "out float lateralVarying;" "out vec2 srcCoordinatesVarying;" @@ -54,7 +55,7 @@ std::unique_ptr OutputShader::make_shader(const char *fragment_met "vec2 vSrcCoordinates = vec2(x, vertical.y);" "ivec2 textureSize = textureSize(texID, 0);" "iSrcCoordinatesVarying = vSrcCoordinates;" - "srcCoordinatesVarying = vec2(vSrcCoordinates.x / textureSize.x, (vSrcCoordinates.y + 0.5) / textureSize.y);" + "srcCoordinatesVarying = vec2(inputScaler * vSrcCoordinates.x / textureSize.x, (vSrcCoordinates.y + 0.5) / textureSize.y);" "vec2 vPosition = vec2(x, vertical.x);" "vec2 floatingPosition = (vPosition / positionConversion) + lateral * scanNormal;" @@ -117,3 +118,8 @@ void OutputShader::set_timing(unsigned int height_of_display, unsigned int cycle set_uniform("scanNormal", scan_normal[0], scan_normal[1]); set_uniform("positionConversion", (GLfloat)horizontal_scan_period, (GLfloat)vertical_scan_period / (GLfloat)vertical_period_divider); } + +void OutputShader::set_input_width_scaler(float input_scaler) +{ + set_uniform("inputScaler", input_scaler); +} diff --git a/Outputs/CRT/Internals/Shaders/OutputShader.hpp b/Outputs/CRT/Internals/Shaders/OutputShader.hpp index 9b4b7db39..44f4ec041 100644 --- a/Outputs/CRT/Internals/Shaders/OutputShader.hpp +++ b/Outputs/CRT/Internals/Shaders/OutputShader.hpp @@ -58,6 +58,12 @@ public: to occur upon the next `bind`. */ void set_timing(unsigned int height_of_display, unsigned int cycles_per_line, unsigned int horizontal_scan_period, unsigned int vertical_scan_period, unsigned int vertical_period_divider); + + /*! + Sets the proportion of the input area that should be considered the whole width — 1.0 means use all available + space, 0.5 means use half, etc. + */ + void set_input_width_scaler(float input_scaler); }; } diff --git a/Outputs/CRT/Internals/Shaders/Shader.cpp b/Outputs/CRT/Internals/Shaders/Shader.cpp index df96c14ab..15b8bb43c 100644 --- a/Outputs/CRT/Internals/Shaders/Shader.cpp +++ b/Outputs/CRT/Internals/Shaders/Shader.cpp @@ -156,7 +156,8 @@ void Shader::set_uniform(const std::string &name, GLint value1, GLint value2) void Shader::set_uniform(const std::string &name, GLfloat value1, GLfloat value2) { enqueue_function([name, value1, value2, this] { - glUniform2f(location(), value1, value2); + GLint location = location(); + glUniform2f(location, value1, value2); }); }