diff --git a/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm b/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm index 038743842..29f39ed98 100644 --- a/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm +++ b/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm @@ -359,8 +359,9 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; #endif // Build the composition pipeline if one is in use. - const bool isSVideoOutput = modals.display_type == Outputs::Display::DisplayType::SVideo; if(_isUsingCompositionPipeline) { + const bool isSVideoOutput = modals.display_type == Outputs::Display::DisplayType::SVideo; + pipelineDescriptor.colorAttachments[0].pixelFormat = _compositionTexture.pixelFormat; pipelineDescriptor.vertexFunction = [library newFunctionWithName:@"scanToComposition"]; pipelineDescriptor.fragmentFunction = @@ -374,7 +375,7 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; _compositionRenderPass.colorAttachments[0].storeAction = MTLStoreActionStore; _compositionRenderPass.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.5, 0.5, 1.0); - simd::float3 *const firCoefficients = uniforms()->firCoefficients; + auto *const firCoefficients = uniforms()->firCoefficients; const float cyclesPerLine = float(modals.cycles_per_line); const float colourCyclesPerLine = float(modals.colour_cycle_numerator) / float(modals.colour_cycle_denominator); @@ -386,7 +387,7 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; firCoefficients[7].x = 1.0f; } else { // In composite, filter luminance gently. - SignalProcessing::FIRFilter luminancefilter(15, cyclesPerLine, 0.0f, colourCyclesPerLine * 0.75f); + SignalProcessing::FIRFilter luminancefilter(15, cyclesPerLine, 0.0f, colourCyclesPerLine * 0.5f); const auto calculatedCoefficients = luminancefilter.get_coefficients(); for(size_t c = 0; c < 8; ++c) { firCoefficients[c].x = calculatedCoefficients[c]; @@ -394,7 +395,7 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; } // Whether S-Video or composite, apply the same relatively strong filter to colour channels. - SignalProcessing::FIRFilter chrominancefilter(15, cyclesPerLine, 0.0f, colourCyclesPerLine * 0.33f); + SignalProcessing::FIRFilter chrominancefilter(15, cyclesPerLine, 0.0f, colourCyclesPerLine * 0.5f); const auto calculatedCoefficients = chrominancefilter.get_coefficients(); for(size_t c = 0; c < 8; ++c) { firCoefficients[c].y = firCoefficients[c].z = calculatedCoefficients[c]; diff --git a/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal b/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal index 0e699eb84..bcfb85d5b 100644 --- a/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal +++ b/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal @@ -123,23 +123,23 @@ template SourceInterpolator toDisplay( float(inputs[instanceID].endPoints[0].compositeAngle), float(inputs[instanceID].endPoints[1].compositeAngle), float((vertexID&2) >> 1) - ) / 32.0; + ) / 32.0f; // Hence determine this quad's real shape, using vertexID to pick a corner. // position2d is now in the range [0, 1]. - float2 position2d = start + (float(vertexID&2) * 0.5) * tangent + (float(vertexID&1) - 0.5) * normal * uniforms.lineWidth; + float2 position2d = start + (float(vertexID&2) * 0.5f) * tangent + (float(vertexID&1) - 0.5f) * normal * uniforms.lineWidth; // Apply the requested offset and zoom, to map the desired area to the range [0, 1]. position2d = (position2d + uniforms.offset) * uniforms.zoom; // Remap from [0, 1] to Metal's [-1, 1] and then apply the aspect ratio correction. - position2d = (position2d * float2(2.0, -2.0) + float2(-1.0, 1.0)) * float2(uniforms.aspectRatioMultiplier, 1.0); + position2d = (position2d * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f)) * float2(uniforms.aspectRatioMultiplier, 1.0f); output.position = float4( position2d, - 0.0, - 1.0 + 0.0f, + 1.0f ); output.textureCoordinates = textureLocation(&inputs[instanceID], float((vertexID&2) >> 1)); @@ -175,14 +175,14 @@ vertex SourceInterpolator scanToComposition( constant Uniforms &uniforms [[buffe // Populate result as if direct texture access were available. result.position.x = mix(scans[instanceID].endPoints[0].cyclesSinceRetrace, scans[instanceID].endPoints[1].cyclesSinceRetrace, float(vertexID)); result.position.y = scans[instanceID].line; - result.position.zw = float2(0.0, 1.0); + result.position.zw = float2(0.0f, 1.0f); result.textureCoordinates.x = mix(scans[instanceID].endPoints[0].dataOffset, scans[instanceID].endPoints[1].dataOffset, float(vertexID)); result.textureCoordinates.y = scans[instanceID].dataY; result.colourPhase = 3.141592654f * mix( float(scans[instanceID].endPoints[0].compositeAngle), float(scans[instanceID].endPoints[1].compositeAngle), float(vertexID) - ) / 32.0; + ) / 32.0f; result.colourAmplitude = float(scans[instanceID].compositeAmplitude) / 255.0f; // Map position into eye space, allowing for target texture dimensions. @@ -221,7 +221,13 @@ fragment float4 compositeSampleLuminance8Phase8(SourceInterpolator vert [[stage_ const auto luminancePhase = texture.sample(standardSampler, vert.textureCoordinates).rg; const float phaseOffset = 3.141592654 * 4.0 * luminancePhase.g; const float rawChroma = step(luminancePhase.g, 0.75) * cos(vert.colourPhase + phaseOffset); - return float4(float3(mix(luminancePhase.r, rawChroma, vert.colourAmplitude)), 1.0f); + const float level = mix(luminancePhase.r, rawChroma, vert.colourAmplitude); + return float4( + level, + 0.5 + 0.5*level*cos(vert.colourPhase), + 0.5 + 0.5*level*sin(vert.colourPhase), + 1.0 + ); } // All the RGB formats can produce RGB, composite or S-Video. @@ -258,10 +264,10 @@ float3 convertRed1Green1Blue1(SourceInterpolator vert, texture2d texture \ fragment float4 svideoSample##name(SourceInterpolator vert [[stage_in]], texture2d texture [[texture(0)]], constant Uniforms &uniforms [[buffer(0)]]) { \ const auto colour = uniforms.fromRGB * convert##name(vert, texture); \ - const float2 colourSubcarrier = float2(sin(vert.colourPhase), cos(vert.colourPhase))*0.5 + float2(0.5); \ + const float2 colourSubcarrier = float2(cos(vert.colourPhase), sin(vert.colourPhase)); \ return float4( \ colour.r, \ - dot(colour.gb, colourSubcarrier), \ + dot(colour.gb, colourSubcarrier)*0.5 + 0.5, \ 0.0, \ 1.0 \ ); \ @@ -269,12 +275,12 @@ float3 convertRed1Green1Blue1(SourceInterpolator vert, texture2d texture \ fragment float4 compositeSample##name(SourceInterpolator vert [[stage_in]], texture2d texture [[texture(0)]], constant Uniforms &uniforms [[buffer(0)]]) { \ const auto colour = uniforms.fromRGB * convert##name(vert, texture); \ - const float2 colourSubcarrier = float2(sin(vert.colourPhase), cos(vert.colourPhase)); \ + const float2 colourSubcarrier = float2(cos(vert.colourPhase), sin(vert.colourPhase)); \ const float level = mix(colour.r, dot(colour.gb, colourSubcarrier), vert.colourAmplitude); \ return float4( \ level, \ - 0.5 + 0.5*level*sin(vert.colourPhase),\ 0.5 + 0.5*level*cos(vert.colourPhase),\ + 0.5 + 0.5*level*sin(vert.colourPhase),\ 1.0 \ ); \ } @@ -322,7 +328,7 @@ fragment float4 clearFragment() { // MARK: - Conversion fragment shaders fragment float4 filterFragment(SourceInterpolator vert [[stage_in]], texture2d texture [[texture(0)]], constant Uniforms &uniforms [[buffer(0)]]) { -#define Sample(x) texture.sample(standardSampler, vert.textureCoordinates + float2(x, 0.0)).rgb +#define Sample(x) texture.sample(standardSampler, vert.textureCoordinates + float2(x, 0.0f)).rgb const float3 rawSamples[] = { Sample(-7), Sample(-6), Sample(-5), Sample(-4), Sample(-3), Sample(-2), Sample(-1), Sample(0), @@ -342,5 +348,5 @@ fragment float4 filterFragment(SourceInterpolator vert [[stage_in]], texture2d