mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-15 14:27:29 +00:00
Added the option for both intermediate and output shaders to use only a portion of the input/output texture; made an attempt to pick an appropriate proportion in order to align signal sampling with the colour subcarrier.
This commit is contained in:
@@ -381,11 +381,40 @@ void OpenGLOutputBuilder::set_timing_uniforms()
|
|||||||
extends = true;
|
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_;
|
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);
|
float output_width = ((float)colour_cycle_numerator_ * 4.0f) / (float)(colour_cycle_denominator_ * IntermediateBufferWidth);
|
||||||
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(composite_separation_filter_program_)
|
||||||
if(rgb_filter_shader_program_) rgb_filter_shader_program_->set_filter_coefficients(cycles_per_line_, (float)input_frequency_ * 0.5f);
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,7 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_shader(const char *
|
|||||||
"uniform float extension;"
|
"uniform float extension;"
|
||||||
"uniform %s texID;"
|
"uniform %s texID;"
|
||||||
"uniform float offsets[5];"
|
"uniform float offsets[5];"
|
||||||
|
"uniform vec2 widthScalers;"
|
||||||
|
|
||||||
"out vec2 phaseAndAmplitudeVarying;"
|
"out vec2 phaseAndAmplitudeVarying;"
|
||||||
"out vec2 inputPositionsVarying[11];"
|
"out vec2 inputPositionsVarying[11];"
|
||||||
@@ -59,8 +60,8 @@ std::unique_ptr<IntermediateShader> 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;
|
// 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;
|
// outputPosition.x is either outputStart.x or ends.y;
|
||||||
// .ys are inputStart.y and outputStart.y respectively
|
// .ys are inputStart.y and outputStart.y respectively
|
||||||
"vec2 inputPosition = vec2(mix(inputStart.x, ends.x, extent), inputStart.y);"
|
"vec2 inputPosition = vec2(mix(inputStart.x, ends.x, extent)*widthScalers[0], inputStart.y);"
|
||||||
"vec2 outputPosition = vec2(mix(outputStart.x, ends.y, extent), outputStart.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
|
// 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);"
|
"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("lumaChromaToRGB", 3, false, toRGB);
|
||||||
set_uniform_matrix("rgbToLumaChroma", 3, false, fromRGB);
|
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);
|
||||||
|
}
|
||||||
|
@@ -88,6 +88,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
void set_colour_conversion_matrices(float *fromRGB, float *toRGB);
|
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:
|
private:
|
||||||
static std::unique_ptr<IntermediateShader> make_shader(const char *fragment_shader, bool use_usampler, bool input_is_inputPosition);
|
static std::unique_ptr<IntermediateShader> make_shader(const char *fragment_shader, bool use_usampler, bool input_is_inputPosition);
|
||||||
};
|
};
|
||||||
|
@@ -38,6 +38,7 @@ std::unique_ptr<OutputShader> OutputShader::make_shader(const char *fragment_met
|
|||||||
"uniform vec2 positionConversion;"
|
"uniform vec2 positionConversion;"
|
||||||
"uniform vec2 scanNormal;"
|
"uniform vec2 scanNormal;"
|
||||||
"uniform %s texID;"
|
"uniform %s texID;"
|
||||||
|
"uniform float inputScaler;"
|
||||||
|
|
||||||
"out float lateralVarying;"
|
"out float lateralVarying;"
|
||||||
"out vec2 srcCoordinatesVarying;"
|
"out vec2 srcCoordinatesVarying;"
|
||||||
@@ -54,7 +55,7 @@ std::unique_ptr<OutputShader> OutputShader::make_shader(const char *fragment_met
|
|||||||
"vec2 vSrcCoordinates = vec2(x, vertical.y);"
|
"vec2 vSrcCoordinates = vec2(x, vertical.y);"
|
||||||
"ivec2 textureSize = textureSize(texID, 0);"
|
"ivec2 textureSize = textureSize(texID, 0);"
|
||||||
"iSrcCoordinatesVarying = vSrcCoordinates;"
|
"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 vPosition = vec2(x, vertical.x);"
|
||||||
"vec2 floatingPosition = (vPosition / positionConversion) + lateral * scanNormal;"
|
"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("scanNormal", scan_normal[0], scan_normal[1]);
|
||||||
set_uniform("positionConversion", (GLfloat)horizontal_scan_period, (GLfloat)vertical_scan_period / (GLfloat)vertical_period_divider);
|
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);
|
||||||
|
}
|
||||||
|
@@ -58,6 +58,12 @@ public:
|
|||||||
to occur upon the next `bind`.
|
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);
|
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
void Shader::set_uniform(const std::string &name, GLfloat value1, GLfloat value2)
|
||||||
{
|
{
|
||||||
enqueue_function([name, value1, value2, this] {
|
enqueue_function([name, value1, value2, this] {
|
||||||
glUniform2f(location(), value1, value2);
|
GLint location = location();
|
||||||
|
glUniform2f(location, value1, value2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user