mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +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:
parent
f2b8b26bc4
commit
7d60df9075
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ std::unique_ptr<IntermediateShader> 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> 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);
|
||||
}
|
||||
|
@ -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<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 scanNormal;"
|
||||
"uniform %s texID;"
|
||||
"uniform float inputScaler;"
|
||||
|
||||
"out float lateralVarying;"
|
||||
"out vec2 srcCoordinatesVarying;"
|
||||
@ -54,7 +55,7 @@ std::unique_ptr<OutputShader> 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);
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user