1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-23 20:29:42 +00:00

Settles, at least for now, on 15-tap notch filtering.

This commit is contained in:
Thomas Harte 2018-11-26 22:34:31 -05:00
parent 61a63a673c
commit d45c2a1f28
3 changed files with 78 additions and 55 deletions

View File

@ -69,7 +69,7 @@ template <typename T> void ScanTarget::allocate_buffer(const T &array, GLuint &b
}
ScanTarget::ScanTarget() :
unprocessed_line_texture_(LineBufferWidth, LineBufferHeight, UnprocessedLineBufferTextureUnit, GL_LINEAR, false),
unprocessed_line_texture_(LineBufferWidth, LineBufferHeight, UnprocessedLineBufferTextureUnit, GL_NEAREST, false),
full_display_rectangle_(-1.0f, -1.0f, 2.0f, 2.0f) {
// Ensure proper initialisation of the two atomic pointer sets.
@ -152,12 +152,14 @@ void ScanTarget::set_modals(Modals modals) {
if(modals_.display_type == DisplayType::CompositeColour) {
pipeline_stages_.emplace_back(
composite_to_svideo_shader(modals_.colour_cycle_numerator, modals_.colour_cycle_denominator, processing_width_).release(),
SVideoLineBufferTextureUnit);
SVideoLineBufferTextureUnit,
GL_NEAREST);
}
if(modals_.display_type == DisplayType::SVideo || modals_.display_type == DisplayType::CompositeColour) {
pipeline_stages_.emplace_back(
svideo_to_rgb_shader(modals_.colour_cycle_numerator, modals_.colour_cycle_denominator, processing_width_).release(),
(modals_.display_type == DisplayType::CompositeColour) ? RGBLineBufferTextureUnit : SVideoLineBufferTextureUnit);
(modals_.display_type == DisplayType::CompositeColour) ? RGBLineBufferTextureUnit : SVideoLineBufferTextureUnit,
GL_NEAREST);
}
glBindVertexArray(scan_vertex_array_);

View File

@ -14,6 +14,8 @@
#include "Primitives/TextureTarget.hpp"
#include "Primitives/Rectangle.hpp"
#include "../../SignalProcessing/FIRFilter.hpp"
#include <array>
#include <atomic>
#include <cstdint>
@ -179,12 +181,12 @@ class ScanTarget: public Outputs::Display::ScanTarget {
static std::unique_ptr<Shader> input_shader(InputDataType input_data_type, DisplayType display_type);
static std::unique_ptr<Shader> composite_to_svideo_shader(int colour_cycle_numerator, int colour_cycle_denominator, int processing_width);
static std::unique_ptr<Shader> svideo_to_rgb_shader(int colour_cycle_numerator, int colour_cycle_denominator, int processing_width);
static std::vector<float> coefficients_for_filter(int colour_cycle_numerator, int colour_cycle_denominator, int processing_width, float multiple_of_colour_clock);
static SignalProcessing::FIRFilter colour_filter(int colour_cycle_numerator, int colour_cycle_denominator, int processing_width, float low_cutoff, float high_cutoff);
struct PipelineStage {
PipelineStage(Shader *shader, GLenum texture_unit) :
PipelineStage(Shader *shader, GLenum texture_unit, GLint magnification_filter) :
shader(shader),
target(LineBufferWidth, LineBufferHeight, texture_unit, GL_LINEAR, false) {}
target(LineBufferWidth, LineBufferHeight, texture_unit, magnification_filter, false) {}
std::unique_ptr<Shader> shader;
TextureTarget target;

View File

@ -8,8 +8,6 @@
#include "ScanTarget.hpp"
#include "../../SignalProcessing/FIRFilter.hpp"
using namespace Outputs::Display::OpenGL;
std::string ScanTarget::glsl_globals(ShaderType type) {
@ -95,10 +93,10 @@ std::string ScanTarget::glsl_default_vertex_shader(ShaderType type) {
"uniform usampler2D textureName;";
} else {
result +=
"out vec2 textureCoordinates[11];"
"out vec2 combCoordinates[2];"
"out vec2 textureCoordinates[15];"
"uniform sampler2D textureName;"
"uniform float combOffset;";
"uniform float edgeExpansion;";
}
result +=
@ -122,20 +120,25 @@ std::string ScanTarget::glsl_default_vertex_shader(ShaderType type) {
"vec2 eyePosition = (sourcePosition + vec2(0.0, longitudinal - 0.5)) / vec2(scale.x, 2048.0);"
"sourcePosition /= vec2(scale.x, 2048.0);"
"textureCoordinates[0] = sourcePosition + vec2(-5.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[1] = sourcePosition + vec2(-4.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[2] = sourcePosition + vec2(-3.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[3] = sourcePosition + vec2(-2.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[4] = sourcePosition + vec2(-1.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[5] = sourcePosition;"
"textureCoordinates[6] = sourcePosition + vec2(1.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[7] = sourcePosition + vec2(2.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[8] = sourcePosition + vec2(3.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[9] = sourcePosition + vec2(4.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[10] = sourcePosition + vec2(5.0, 0.0) / textureSize(textureName, 0);"
"vec2 expansion = vec2(2.0*lateral*edgeExpansion - edgeExpansion, 0.0) / textureSize(textureName, 0);"
"eyePosition = eyePosition + expansion;"
"sourcePosition = sourcePosition + expansion;"
"combCoordinates[0] = sourcePosition - vec2(combOffset, 0.0);"
"combCoordinates[1] = sourcePosition + vec2(combOffset, 0.0);"
"textureCoordinates[0] = sourcePosition + vec2(-7.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[1] = sourcePosition + vec2(-6.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[2] = sourcePosition + vec2(-5.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[3] = sourcePosition + vec2(-4.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[4] = sourcePosition + vec2(-3.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[5] = sourcePosition + vec2(-2.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[6] = sourcePosition + vec2(-1.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[7] = sourcePosition;"
"textureCoordinates[8] = sourcePosition + vec2(1.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[9] = sourcePosition + vec2(2.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[10] = sourcePosition + vec2(3.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[11] = sourcePosition + vec2(4.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[12] = sourcePosition + vec2(5.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[13] = sourcePosition + vec2(6.0, 0.0) / textureSize(textureName, 0);"
"textureCoordinates[14] = sourcePosition + vec2(7.0, 0.0) / textureSize(textureName, 0);"
"eyePosition = eyePosition;";
}
@ -340,10 +343,9 @@ std::unique_ptr<Shader> ScanTarget::input_shader(InputDataType input_data_type,
));
}
std::vector<float> ScanTarget::coefficients_for_filter(int colour_cycle_numerator, int colour_cycle_denominator, int processing_width, float multiple_of_colour_clock) {
SignalProcessing::FIRFilter ScanTarget::colour_filter(int colour_cycle_numerator, int colour_cycle_denominator, int processing_width, float low_cutoff, float high_cutoff) {
const float cycles_per_expanded_line = (float(colour_cycle_numerator) / float(colour_cycle_denominator)) / (float(processing_width) / float(LineBufferWidth));
const SignalProcessing::FIRFilter filter(11, float(LineBufferWidth), 0.0f, cycles_per_expanded_line * multiple_of_colour_clock);
return filter.get_coefficients();
return SignalProcessing::FIRFilter(15, float(LineBufferWidth), cycles_per_expanded_line * low_cutoff, cycles_per_expanded_line * high_cutoff);
}
std::unique_ptr<Shader> ScanTarget::svideo_to_rgb_shader(int colour_cycle_numerator, int colour_cycle_denominator, int processing_width) {
@ -358,15 +360,15 @@ std::unique_ptr<Shader> ScanTarget::svideo_to_rgb_shader(int colour_cycle_numera
glsl_globals(ShaderType::ProcessedScan) + glsl_default_vertex_shader(ShaderType::ProcessedScan),
"#version 150\n"
"in vec2 textureCoordinates[11];"
"uniform vec4 chromaWeights[3];"
"uniform vec4 lumaWeights[3];"
"in vec2 textureCoordinates[15];"
"uniform vec4 chromaWeights[4];"
"uniform vec4 lumaWeights[4];"
"uniform sampler2D textureName;"
"uniform mat3 lumaChromaToRGB;"
"out vec3 fragColour;"
"void main() {"
"vec3 samples[11] = vec3[11]("
"vec3 samples[15] = vec3[15]("
"texture(textureName, textureCoordinates[0]).rgb,"
"texture(textureName, textureCoordinates[1]).rgb,"
"texture(textureName, textureCoordinates[2]).rgb,"
@ -377,39 +379,48 @@ std::unique_ptr<Shader> ScanTarget::svideo_to_rgb_shader(int colour_cycle_numera
"texture(textureName, textureCoordinates[7]).rgb,"
"texture(textureName, textureCoordinates[8]).rgb,"
"texture(textureName, textureCoordinates[9]).rgb,"
"texture(textureName, textureCoordinates[10]).rgb"
"texture(textureName, textureCoordinates[10]).rgb,"
"texture(textureName, textureCoordinates[11]).rgb,"
"texture(textureName, textureCoordinates[12]).rgb,"
"texture(textureName, textureCoordinates[13]).rgb,"
"texture(textureName, textureCoordinates[14]).rgb"
");"
"vec4 samples0[3] = vec4[3]("
"vec4 samples0[4] = vec4[4]("
"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(samples[8].r, samples[9].r, samples[10].r, samples[11].r),"
"vec4(samples[12].r, samples[13].r, samples[14].r, 0.0)"
");"
"vec4 samples1[3] = vec4[3]("
"vec4 samples1[4] = vec4[4]("
"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)"
"vec4(samples[8].g, samples[9].g, samples[10].g, samples[11].g),"
"vec4(samples[12].g, samples[13].g, samples[14].g, 0.0)"
");"
"vec4 samples2[3] = vec4[3]("
"vec4 samples2[4] = vec4[4]("
"vec4(samples[0].b, samples[1].b, samples[2].b, samples[3].b),"
"vec4(samples[4].b, samples[5].b, samples[6].b, samples[7].b),"
"vec4(samples[8].b, samples[9].b, samples[10].b, 0.0)"
"vec4(samples[8].b, samples[9].b, samples[10].b, samples[11].b),"
"vec4(samples[12].b, samples[13].b, samples[14].b, 0.0)"
");"
"float channel0 = dot(lumaWeights[0], samples0[0]) + dot(lumaWeights[1], samples0[1]) + dot(lumaWeights[2], samples0[2]);"
"float channel1 = dot(chromaWeights[0], samples1[0]) + dot(chromaWeights[1], samples1[1]) + dot(chromaWeights[2], samples1[2]);"
"float channel2 = dot(chromaWeights[0], samples2[0]) + dot(chromaWeights[1], samples2[1]) + dot(chromaWeights[2], samples2[2]);"
"float channel0 = dot(lumaWeights[0], samples0[0]) + dot(lumaWeights[1], samples0[1]) + dot(lumaWeights[2], samples0[2]) + dot(lumaWeights[3], samples0[3]);"
"float channel1 = dot(chromaWeights[0], samples1[0]) + dot(chromaWeights[1], samples1[1]) + dot(chromaWeights[2], samples1[2]) + dot(chromaWeights[3], samples1[3]);"
"float channel2 = dot(chromaWeights[0], samples2[0]) + dot(chromaWeights[1], samples2[1]) + dot(chromaWeights[2], samples2[2]) + dot(chromaWeights[3], samples2[3]);"
"vec2 chroma = vec2(channel1, channel2)*2.0 - vec2(1.0);"
"fragColour = lumaChromaToRGB * vec3(channel0, chroma);"
"}",
attribute_bindings(ShaderType::ProcessedScan)
));
auto chroma_coefficients = coefficients_for_filter(colour_cycle_numerator, colour_cycle_denominator, processing_width, 0.25f);
auto chroma_coefficients = colour_filter(colour_cycle_numerator, colour_cycle_denominator, processing_width, 0.0f, 0.25f).get_coefficients();
chroma_coefficients.push_back(0.0f);
shader->set_uniform("chromaWeights", 4, 3, chroma_coefficients.data());
shader->set_uniform("chromaWeights", 4, 4, chroma_coefficients.data());
auto luma_coefficients = coefficients_for_filter(colour_cycle_numerator, colour_cycle_denominator, processing_width, 0.5f);
auto luma_coefficients = colour_filter(colour_cycle_numerator, colour_cycle_denominator, processing_width, 0.0f, 0.15f).get_coefficients();
luma_coefficients.push_back(0.0f);
shader->set_uniform("lumaWeights", 4, 3, luma_coefficients.data());
shader->set_uniform("lumaWeights", 4, 4, luma_coefficients.data());
shader->set_uniform("edgeExpansion", 0);
return shader;
}
@ -419,28 +430,36 @@ std::unique_ptr<Shader> ScanTarget::composite_to_svideo_shader(int colour_cycle_
glsl_globals(ShaderType::ProcessedScan) + glsl_default_vertex_shader(ShaderType::ProcessedScan),
"#version 150\n"
"in vec2 textureCoordinates[11];"
"in vec2 combCoordinates[2];"
"in vec2 textureCoordinates[15];"
"in float compositeAngle;"
"in float oneOverCompositeAmplitude;"
"uniform vec4 textureWeights[3];"
"uniform vec4 lumaWeights[4];"
"uniform sampler2D textureName;"
"out vec3 fragColour;"
"void main() {"
"float luma = mix(texture(textureName, combCoordinates[0]).r, texture(textureName, combCoordinates[1]).r, 0.5);"
"float centre = texture(textureName, textureCoordinates[5]).r;"
"vec4 samples[4] = vec4[4]("
"vec4(texture(textureName, textureCoordinates[0]).r, texture(textureName, textureCoordinates[1]).r, texture(textureName, textureCoordinates[2]).r, texture(textureName, textureCoordinates[3]).r),"
"vec4(texture(textureName, textureCoordinates[4]).r, texture(textureName, textureCoordinates[5]).r, texture(textureName, textureCoordinates[6]).r, texture(textureName, textureCoordinates[7]).r),"
"vec4(texture(textureName, textureCoordinates[8]).r, texture(textureName, textureCoordinates[9]).r, texture(textureName, textureCoordinates[10]).r, texture(textureName, textureCoordinates[11]).r),"
"vec4(texture(textureName, textureCoordinates[12]).r, texture(textureName, textureCoordinates[13]).r, texture(textureName, textureCoordinates[14]).r, 0.0)"
");"
"float luma = dot(lumaWeights[0], samples[0]) + dot(lumaWeights[1], samples[1]) + dot(lumaWeights[2], samples[2]) + dot(lumaWeights[3], samples[3]);"
"vec2 quadrature = vec2(cos(compositeAngle), sin(compositeAngle));"
"vec2 chroma = ((centre - luma) * oneOverCompositeAmplitude)*quadrature;"
"fragColour = vec3(luma, chroma*0.5 + vec2(0.5));"
"vec2 chroma = ((samples[1].a - luma) * oneOverCompositeAmplitude)*quadrature;"
"fragColour = vec3(samples[1].a, chroma*0.5 + vec2(0.5));"
"}",
attribute_bindings(ShaderType::ProcessedScan)
));
const float cycles_per_expanded_line = (float(colour_cycle_numerator) / float(colour_cycle_denominator)) / (float(processing_width) / float(LineBufferWidth));
float quarter_distancce = 0.25f / cycles_per_expanded_line;
shader->set_uniform("combOffset", quarter_distancce);
auto luma_low = colour_filter(colour_cycle_numerator, colour_cycle_denominator, processing_width, 0.0f, 0.9f);
auto luma_coefficients = luma_low.get_coefficients();
luma_coefficients.push_back(0.0f);
shader->set_uniform("lumaWeights", 4, 4, luma_coefficients.data());
shader->set_uniform("edgeExpansion", 0);
return shader;
}