mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +00:00
Reintroduces basic filtering for RGB mode (and introduces it for monochrome composite).
This commit is contained in:
parent
cd055a0298
commit
68c5474e36
@ -535,6 +535,7 @@ void ScanTarget::draw(bool synchronous, int output_width, int output_height) {
|
||||
const int framebuffer_height = std::min(output_height, 1080);
|
||||
const int proportional_width = (framebuffer_height * 4) / 3;
|
||||
if(!accumulation_texture_ || ( /* !synchronous && */ (accumulation_texture_->get_width() != proportional_width || accumulation_texture_->get_height() != framebuffer_height))) {
|
||||
set_sampling_window(proportional_width, framebuffer_height, *output_shader_);
|
||||
std::unique_ptr<OpenGL::TextureTarget> new_framebuffer(
|
||||
new TextureTarget(
|
||||
GLsizei(proportional_width),
|
||||
|
@ -219,6 +219,8 @@ class ScanTarget: public Outputs::Display::ScanTarget {
|
||||
*/
|
||||
std::unique_ptr<Shader> qam_separation_shader() const;
|
||||
|
||||
void set_sampling_window(int output_Width, int output_height, Shader &target);
|
||||
|
||||
std::string sampling_function() const;
|
||||
};
|
||||
|
||||
|
@ -14,7 +14,7 @@ using namespace Outputs::Display::OpenGL;
|
||||
|
||||
// MARK: - State setup for compiled shaders.
|
||||
|
||||
void Outputs::Display::OpenGL::ScanTarget::set_uniforms(ShaderType type, Shader &target) const {
|
||||
void ScanTarget::set_uniforms(ShaderType type, Shader &target) const {
|
||||
// Slightly over-amping rowHeight here is a cheap way to make sure that lines
|
||||
// converge even allowing for the fact that they may not be spaced by exactly
|
||||
// the expected distance. Cf. the stencil-powered logic for making sure all
|
||||
@ -56,6 +56,21 @@ void Outputs::Display::OpenGL::ScanTarget::set_uniforms(ShaderType type, Shader
|
||||
}
|
||||
}
|
||||
|
||||
void ScanTarget::set_sampling_window(int output_width, int output_height, Shader &target) {
|
||||
if(modals_.display_type != DisplayType::CompositeColour && modals_.display_type != DisplayType::SVideo) {
|
||||
const float one_pixel_width = float(output_width) * modals_.visible_area.size.width / float(modals_.cycles_per_line);
|
||||
const float clocks_per_angle = float(modals_.cycles_per_line) * float(modals_.colour_cycle_denominator) / float(modals_.colour_cycle_numerator);
|
||||
GLfloat texture_offsets[4];
|
||||
GLfloat angles[4];
|
||||
for(int c = 0; c < 4; ++c) {
|
||||
texture_offsets[c] = ((one_pixel_width * float(c)) / 3.0f) - (one_pixel_width * 0.5f);
|
||||
angles[c] = GLfloat((texture_offsets[c] / clocks_per_angle) * 2.0f * M_PI);
|
||||
}
|
||||
target.set_uniform("textureCoordinateOffsets", 1, 4, texture_offsets);
|
||||
target.set_uniform("compositeAngleOffsets", 4, 1, angles);
|
||||
}
|
||||
}
|
||||
|
||||
void ScanTarget::enable_vertex_attributes(ShaderType type, Shader &target) {
|
||||
#define rt_offset_of(field, source) (reinterpret_cast<uint8_t *>(&source.field) - reinterpret_cast<uint8_t *>(&source))
|
||||
// test_scan and test_line are here so that the byte offsets that need to be
|
||||
@ -267,7 +282,9 @@ std::unique_ptr<Shader> ScanTarget::conversion_shader() const {
|
||||
"uniform sampler2D textureName;"
|
||||
"uniform sampler2D qamTextureName;"
|
||||
"uniform vec2 origin;"
|
||||
"uniform vec2 size;";
|
||||
"uniform vec2 size;"
|
||||
|
||||
"uniform float textureCoordinateOffsets[4];";
|
||||
|
||||
std::string fragment_shader =
|
||||
"#version 150\n"
|
||||
@ -283,7 +300,6 @@ std::unique_ptr<Shader> ScanTarget::conversion_shader() const {
|
||||
"out float compositeAmplitude;"
|
||||
"out float oneOverCompositeAmplitude;"
|
||||
|
||||
"uniform float textureCoordinateOffsets[4];"
|
||||
"uniform float angleOffsets[4];";
|
||||
fragment_shader +=
|
||||
"in float compositeAngle;"
|
||||
@ -293,11 +309,11 @@ std::unique_ptr<Shader> ScanTarget::conversion_shader() const {
|
||||
"uniform vec4 compositeAngleOffsets;";
|
||||
}
|
||||
|
||||
switch(modals_.display_type){
|
||||
switch(modals_.display_type) {
|
||||
case DisplayType::RGB:
|
||||
case DisplayType::CompositeMonochrome:
|
||||
vertex_shader += "out vec2 textureCoordinate;";
|
||||
fragment_shader += "in vec2 textureCoordinate;";
|
||||
vertex_shader += "out vec2 textureCoordinates[4];";
|
||||
fragment_shader += "in vec2 textureCoordinates[4];";
|
||||
break;
|
||||
|
||||
case DisplayType::SVideo:
|
||||
@ -337,16 +353,14 @@ std::unique_ptr<Shader> ScanTarget::conversion_shader() const {
|
||||
"oneOverCompositeAmplitude = mix(0.0, 255.0 / lineCompositeAmplitude, step(0.01, lineCompositeAmplitude));";
|
||||
}
|
||||
|
||||
// For RGB and monochrome composite, generate the single texture coordinate; otherwise generate either three
|
||||
// or four depending on the type of decoding to apply.
|
||||
switch(modals_.display_type) {
|
||||
case DisplayType::RGB:
|
||||
case DisplayType::CompositeMonochrome:
|
||||
case DisplayType::SVideo:
|
||||
vertex_shader +=
|
||||
"textureCoordinate = vec2(mix(startClock, endClock, lateral), lineY + 0.5) / textureSize(textureName, 0);";
|
||||
break;
|
||||
|
||||
case DisplayType::RGB:
|
||||
case DisplayType::CompositeMonochrome:
|
||||
case DisplayType::CompositeColour:
|
||||
vertex_shader +=
|
||||
"float centreClock = mix(startClock, endClock, lateral);"
|
||||
@ -384,10 +398,6 @@ std::unique_ptr<Shader> ScanTarget::conversion_shader() const {
|
||||
"vec3 fragColour3;";
|
||||
|
||||
switch(modals_.display_type) {
|
||||
case DisplayType::RGB:
|
||||
fragment_shader += "fragColour3 = textureLod(textureName, textureCoordinate, 0).rgb;";
|
||||
break;
|
||||
|
||||
case DisplayType::SVideo:
|
||||
fragment_shader +=
|
||||
// Sample the S-Video stream once, to obtain luminance.
|
||||
@ -420,7 +430,7 @@ std::unique_ptr<Shader> ScanTarget::conversion_shader() const {
|
||||
|
||||
// Compute a luminance for use if there's no colour information, now, before
|
||||
// modifying samples.
|
||||
"float mono_luminance = dot(samples, vec4(0.15, 0.35, 0.35, 0.15));" // TODO: figure out proper coefficients.
|
||||
"float mono_luminance = dot(samples, vec4(0.15, 0.35, 0.35, 0.15));"
|
||||
|
||||
// Take the average to calculate luminance, then subtract that from all four samples to
|
||||
// give chrominance.
|
||||
@ -444,7 +454,26 @@ std::unique_ptr<Shader> ScanTarget::conversion_shader() const {
|
||||
break;
|
||||
|
||||
case DisplayType::CompositeMonochrome:
|
||||
fragment_shader += "fragColour3 = vec3(composite_sample(textureCoordinate, compositeAngle));";
|
||||
fragment_shader +=
|
||||
"vec4 angles = compositeAngle + compositeAngleOffsets;"
|
||||
"vec4 samples = vec4("
|
||||
"composite_sample(textureCoordinates[0], angles.x),"
|
||||
"composite_sample(textureCoordinates[1], angles.y),"
|
||||
"composite_sample(textureCoordinates[2], angles.z),"
|
||||
"composite_sample(textureCoordinates[3], angles.w)"
|
||||
");"
|
||||
"fragColour3 = vec3(dot(samples, vec4(0.15, 0.35, 0.35, 0.25)));";
|
||||
break;
|
||||
|
||||
case DisplayType::RGB:
|
||||
fragment_shader +=
|
||||
"vec3 samples[4] = vec3[4]("
|
||||
"textureLod(textureName, textureCoordinates[0], 0).rgb,"
|
||||
"textureLod(textureName, textureCoordinates[1], 0).rgb,"
|
||||
"textureLod(textureName, textureCoordinates[2], 0).rgb,"
|
||||
"textureLod(textureName, textureCoordinates[3], 0).rgb"
|
||||
");"
|
||||
"fragColour3 = samples[0]*0.15 + samples[1]*0.35 + samples[2]*0.35 + samples[2]*0.15;";
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user