diff --git a/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm b/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm index 9f43ff1fc..fefee56f8 100644 --- a/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm +++ b/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm @@ -553,8 +553,7 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; sourceToDisplay = recentre * sourceToDisplay; } - // Convert from the internal [0, 1] to centred [-1, 1] (i.e. Metal's eye coordinates, though also appropriate - // for the zooming step that follows). + // Convert from the internal [0, 1] to centred [-1, 1]. { simd::float3x3 convertToEye; convertToEye.columns[0][0] = 2.0f; @@ -565,9 +564,8 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; sourceToDisplay = convertToEye * sourceToDisplay; } - // Determine the correct zoom level. This is a combination of (i) the necessary horizontal stretch to produce a proper - // aspect ratio; and (ii) the necessary zoom from there to either fit the visible area width or height as per a decision - // on letterboxing or pillarboxing. + // Determine correct zoom, combining (i) the necessary horizontal stretch for aspect ratio; and + // (ii) the necessary zoom to fit either the visible area width or height. const float aspectRatioStretch = float(modals.aspect_ratio / _viewAspectRatio); const float fitWidthZoom = 1.0f / (float(modals.visible_area.size.width) * aspectRatioStretch); const float fitHeightZoom = 1.0f / float(modals.visible_area.size.height); diff --git a/Outputs/OpenGL/ScanTarget.cpp b/Outputs/OpenGL/ScanTarget.cpp index ce4263c0c..f1a00d128 100644 --- a/Outputs/OpenGL/ScanTarget.cpp +++ b/Outputs/OpenGL/ScanTarget.cpp @@ -148,7 +148,6 @@ void ScanTarget::setup_pipeline() { qam_separation_shader_ = qam_separation_shader(); enable_vertex_attributes(ShaderType::QAMSeparation, *qam_separation_shader_); - set_uniforms(ShaderType::QAMSeparation, *qam_separation_shader_); qam_separation_shader_->set_uniform("textureName", GLint(UnprocessedLineBufferTextureUnit - GL_TEXTURE0)); } else { qam_chroma_texture_.reset(); @@ -164,6 +163,10 @@ void ScanTarget::setup_pipeline() { output_shader_->set_uniform("qamTextureName", GLint(QAMChromaTextureUnit - GL_TEXTURE0)); } + if(qam_separation_shader_) { + set_uniforms(ShaderType::QAMSeparation, *qam_separation_shader_); + } + // Visible area is in terms of proportions of the whole; scale according to the aspect ratio and an assumption // that the output area is 4:3. auto adjusted_rect = modals.visible_area; diff --git a/Outputs/OpenGL/ScanTargetGLSLFragments.cpp b/Outputs/OpenGL/ScanTargetGLSLFragments.cpp index 74c80aa07..aa008d09b 100644 --- a/Outputs/OpenGL/ScanTargetGLSLFragments.cpp +++ b/Outputs/OpenGL/ScanTargetGLSLFragments.cpp @@ -273,54 +273,58 @@ std::unique_ptr ScanTarget::conversion_shader() const { // // If the display type is S-Video, generate three textureCoordinates, at // -45, 0, +45. - std::string vertex_shader = - "#version 150\n" + std::string vertex_shader = R"glsl( + #version 150 - "uniform vec2 scale;" - "uniform float rowHeight;" + uniform vec2 scale; + uniform float rowHeight; - "in vec2 startPoint;" - "in vec2 endPoint;" + in vec2 startPoint; + in vec2 endPoint; - "in float startClock;" - "in float startCompositeAngle;" - "in float endClock;" - "in float endCompositeAngle;" + in float startClock; + in float startCompositeAngle; + in float endClock; + in float endCompositeAngle; - "in float lineY;" - "in float lineCompositeAmplitude;" + in float lineY; + in float lineCompositeAmplitude; - "uniform sampler2D textureName;" - "uniform sampler2D qamTextureName;" - "uniform vec2 origin;" - "uniform vec2 size;" + uniform sampler2D textureName; + uniform sampler2D qamTextureName; + uniform vec2 origin; + uniform vec2 size; - "uniform float textureCoordinateOffsets[4];" - "out vec2 textureCoordinates[4];"; + uniform float textureCoordinateOffsets[4]; + out vec2 textureCoordinates[4]; + )glsl"; - std::string fragment_shader = - "#version 150\n" + std::string fragment_shader = R"glsl( + #version 150 - "uniform sampler2D textureName;" - "uniform sampler2D qamTextureName;" + uniform sampler2D textureName; + uniform sampler2D qamTextureName; - "in vec2 textureCoordinates[4];" + in vec2 textureCoordinates[4]; - "out vec4 fragColour;"; + out vec4 fragColour; + )glsl"; if(modals.display_type != DisplayType::RGB) { - vertex_shader += - "out float compositeAngle;" - "out float compositeAmplitude;" - "out float oneOverCompositeAmplitude;" + vertex_shader += R"glsl( + out float compositeAngle; + out float compositeAmplitude; + out float oneOverCompositeAmplitude; - "uniform float angleOffsets[4];"; - fragment_shader += - "in float compositeAngle;" - "in float compositeAmplitude;" - "in float oneOverCompositeAmplitude;" + uniform float angleOffsets[4]; + )glsl"; + fragment_shader += R"glsl( + in float compositeAngle; + in float compositeAmplitude; + in float oneOverCompositeAmplitude; - "uniform vec4 compositeAngleOffsets;"; + uniform vec4 compositeAngleOffsets; + )glsl"; } if(modals.display_type == DisplayType::SVideo || modals.display_type == DisplayType::CompositeColour) { @@ -329,38 +333,42 @@ std::unique_ptr ScanTarget::conversion_shader() const { } // Add the code to generate a proper output position; this applies to all display types. - vertex_shader += - "void main(void) {" - "float lateral = float(gl_VertexID & 1);" - "float longitudinal = float((gl_VertexID & 2) >> 1);" - "vec2 centrePoint = mix(startPoint, vec2(endPoint.x, startPoint.y), lateral) / scale;" - "vec2 height = normalize(vec2(endPoint.x, startPoint.y) - startPoint).yx * (longitudinal - 0.5) * rowHeight;" - "vec2 eyePosition = vec2(-1.0, 1.0) + vec2(2.0, -2.0) * (((centrePoint + height) / size) - origin);" - "gl_Position = vec4(eyePosition, 0.0, 1.0);"; + vertex_shader += R"glsl( + void main(void) { + float lateral = float(gl_VertexID & 1); + float longitudinal = float((gl_VertexID & 2) >> 1); + vec2 centrePoint = mix(startPoint, vec2(endPoint.x, startPoint.y), lateral) / scale; + vec2 height = normalize(vec2(endPoint.x, startPoint.y) - startPoint).yx * (longitudinal - 0.5) * rowHeight; + vec2 eyePosition = vec2(-1.0, 1.0) + vec2(2.0, -2.0) * (((centrePoint + height) - origin) / size); + gl_Position = vec4(eyePosition, 0.0, 1.0); + )glsl"; // For everything other than RGB, calculate the two composite outputs. if(modals.display_type != DisplayType::RGB) { - vertex_shader += - "compositeAngle = (mix(startCompositeAngle, endCompositeAngle, lateral) / 32.0) * 3.141592654;" - "compositeAmplitude = lineCompositeAmplitude / 255.0;" - "oneOverCompositeAmplitude = mix(0.0, 255.0 / lineCompositeAmplitude, step(0.95, lineCompositeAmplitude));"; + vertex_shader += R"glsl( + compositeAngle = (mix(startCompositeAngle, endCompositeAngle, lateral) / 32.0) * 3.141592654; + compositeAmplitude = lineCompositeAmplitude / 255.0; + oneOverCompositeAmplitude = mix(0.0, 255.0 / lineCompositeAmplitude, step(0.95, lineCompositeAmplitude)); + )glsl"; } - vertex_shader += - "float centreClock = mix(startClock, endClock, lateral);" - "textureCoordinates[0] = vec2(centreClock + textureCoordinateOffsets[0], lineY + 0.5) / textureSize(textureName, 0);" - "textureCoordinates[1] = vec2(centreClock + textureCoordinateOffsets[1], lineY + 0.5) / textureSize(textureName, 0);" - "textureCoordinates[2] = vec2(centreClock + textureCoordinateOffsets[2], lineY + 0.5) / textureSize(textureName, 0);" - "textureCoordinates[3] = vec2(centreClock + textureCoordinateOffsets[3], lineY + 0.5) / textureSize(textureName, 0);"; + vertex_shader += R"glsl( + float centreClock = mix(startClock, endClock, lateral); + textureCoordinates[0] = vec2(centreClock + textureCoordinateOffsets[0], lineY + 0.5) / textureSize(textureName, 0); + textureCoordinates[1] = vec2(centreClock + textureCoordinateOffsets[1], lineY + 0.5) / textureSize(textureName, 0); + textureCoordinates[2] = vec2(centreClock + textureCoordinateOffsets[2], lineY + 0.5) / textureSize(textureName, 0); + textureCoordinates[3] = vec2(centreClock + textureCoordinateOffsets[3], lineY + 0.5) / textureSize(textureName, 0); + )glsl"; if((modals.display_type == DisplayType::SVideo) || (modals.display_type == DisplayType::CompositeColour)) { - vertex_shader += - "float centreCompositeAngle = abs(mix(startCompositeAngle, endCompositeAngle, lateral)) * 4.0 / 64.0;" - "centreCompositeAngle = floor(centreCompositeAngle);" - "qamTextureCoordinates[0] = vec2(centreCompositeAngle - 1.5, lineY + 0.5) / textureSize(textureName, 0);" - "qamTextureCoordinates[1] = vec2(centreCompositeAngle - 0.5, lineY + 0.5) / textureSize(textureName, 0);" - "qamTextureCoordinates[2] = vec2(centreCompositeAngle + 0.5, lineY + 0.5) / textureSize(textureName, 0);" - "qamTextureCoordinates[3] = vec2(centreCompositeAngle + 1.5, lineY + 0.5) / textureSize(textureName, 0);"; + vertex_shader += R"glsl( + float centreCompositeAngle = abs(mix(startCompositeAngle, endCompositeAngle, lateral)) * 4.0 / 64.0; + centreCompositeAngle = floor(centreCompositeAngle); + qamTextureCoordinates[0] = vec2(centreCompositeAngle - 1.5, lineY + 0.5) / textureSize(textureName, 0); + qamTextureCoordinates[1] = vec2(centreCompositeAngle - 0.5, lineY + 0.5) / textureSize(textureName, 0); + qamTextureCoordinates[2] = vec2(centreCompositeAngle + 0.5, lineY + 0.5) / textureSize(textureName, 0); + qamTextureCoordinates[3] = vec2(centreCompositeAngle + 1.5, lineY + 0.5) / textureSize(textureName, 0); + )glsl"; } vertex_shader += "}"; @@ -381,7 +389,7 @@ std::unique_ptr ScanTarget::conversion_shader() const { switch(modals.display_type) { case DisplayType::CompositeColour: - fragment_shader += R"x( + fragment_shader += R"glsl( vec4 angles = compositeAngle + compositeAngleOffsets; // Sample four times over, at proper angle offsets. @@ -416,7 +424,7 @@ std::unique_ptr ScanTarget::conversion_shader() const { // Apply a colour space conversion to get RGB. fragColour3 = lumaChromaToRGB * vec3(luminance / (1.0 - compositeAmplitude), channels); } - )x"; + )glsl"; break; case DisplayType::CompositeMonochrome: @@ -492,8 +500,8 @@ std::unique_ptr ScanTarget::conversion_shader() const { std::unique_ptr ScanTarget::composition_shader() const { const auto modals = BufferingScanTarget::modals(); - const std::string vertex_shader = - R"x(#version 150 + const std::string vertex_shader = R"glsl( + #version 150 in float startDataX; in float startClock; @@ -515,7 +523,7 @@ std::unique_ptr ScanTarget::composition_shader() const { vec2 eyePosition = vec2(mix(startClock, endClock, lateral), lineY + longitudinal) / vec2(2048.0, 2048.0); gl_Position = vec4(eyePosition*2.0 - vec2(1.0), 0.0, 1.0); } - )x"; + )glsl"; std::string fragment_shader = R"x(#version 150