mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 23:52:26 +00:00
Tries: separate filters for chroma and luma, plus a post-separation sharpen filter on the latter.
This commit is contained in:
parent
6efd8782fe
commit
0288a1974b
@ -99,7 +99,7 @@ struct Uniforms {
|
|||||||
float zoom;
|
float zoom;
|
||||||
simd::float2 offset;
|
simd::float2 offset;
|
||||||
simd::float3 chromaCoefficients[8];
|
simd::float3 chromaCoefficients[8];
|
||||||
float lumaCoefficients[8];
|
simd::float2 lumaCoefficients[8];
|
||||||
float radiansPerPixel;
|
float radiansPerPixel;
|
||||||
float cyclesMultiplier;
|
float cyclesMultiplier;
|
||||||
};
|
};
|
||||||
@ -580,23 +580,39 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
|
|||||||
}
|
}
|
||||||
chromaCoefficients[7].x = 1.0f;
|
chromaCoefficients[7].x = 1.0f;
|
||||||
|
|
||||||
// Luminance is under-filtered during the separation phase in order not to subtract too much from chrominance;
|
// Luminance will be very soft as a result of the separation phase; apply a sharpen filter to try to undo that.
|
||||||
// therefore an additional filtering is applied here.
|
|
||||||
if(!isSVideoOutput) {
|
if(!isSVideoOutput) {
|
||||||
SignalProcessing::FIRFilter luminancefilter(15, float(_lineBufferPixelsPerLine), 0.0f, colourCyclesPerLine * 0.8f);
|
constexpr float sharpen[] = {
|
||||||
const auto calculatedLumaCoefficients = luminancefilter.get_coefficients();
|
0.0042115543f,
|
||||||
|
0.0f,
|
||||||
|
-0.0641804263f,
|
||||||
|
-0.252418578f,
|
||||||
|
-0.589709163f,
|
||||||
|
0.987914681f,
|
||||||
|
0.627704679f,
|
||||||
|
-0.426862389f,
|
||||||
|
0.627704679f
|
||||||
|
};
|
||||||
for(size_t c = 0; c < 8; ++c) {
|
for(size_t c = 0; c < 8; ++c) {
|
||||||
chromaCoefficients[c].x = calculatedLumaCoefficients[c];
|
chromaCoefficients[c].x = sharpen[c];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the luminance separation filter.
|
// Generate the luminance separation filter.
|
||||||
{
|
{
|
||||||
|
// TODO: support separate high-low filters for chroma and luma, rather than treating that as purely subtractive.
|
||||||
|
|
||||||
auto *const luminanceCoefficients = uniforms()->lumaCoefficients;
|
auto *const luminanceCoefficients = uniforms()->lumaCoefficients;
|
||||||
SignalProcessing::FIRFilter luminancefilter(15, float(_lineBufferPixelsPerLine), 0.0f, colourCyclesPerLine);
|
SignalProcessing::FIRFilter lumaPart(15, float(_lineBufferPixelsPerLine), 0.0f, colourCyclesPerLine * 0.5f);
|
||||||
const auto calculatedCoefficients = luminancefilter.get_coefficients();
|
SignalProcessing::FIRFilter chromaPart(15, float(_lineBufferPixelsPerLine), 0.0f, colourCyclesPerLine * 1.1f);
|
||||||
memcpy(luminanceCoefficients, calculatedCoefficients.data(), sizeof(float)*8);
|
|
||||||
|
const auto lumaCoefficients = lumaPart.get_coefficients();
|
||||||
|
const auto chromaCoefficients = chromaPart.get_coefficients();
|
||||||
|
for(size_t c = 0; c < 8; ++c) {
|
||||||
|
luminanceCoefficients[c].x = lumaCoefficients[c];
|
||||||
|
luminanceCoefficients[c].y = chromaCoefficients[c];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store radians per pixel. TODO: is this now orphaned? Should I keep it anyway?
|
// Store radians per pixel. TODO: is this now orphaned? Should I keep it anyway?
|
||||||
|
@ -38,7 +38,7 @@ struct Uniforms {
|
|||||||
|
|
||||||
// Describes the FIR filter in use for luma filtering; also 15 coefficients
|
// Describes the FIR filter in use for luma filtering; also 15 coefficients
|
||||||
// symmetrical around the centre.
|
// symmetrical around the centre.
|
||||||
float lumaCoefficients[8];
|
float2 lumaCoefficients[8];
|
||||||
|
|
||||||
// Maps from pixel offsets into the composition buffer to angular difference.
|
// Maps from pixel offsets into the composition buffer to angular difference.
|
||||||
float radiansPerPixel;
|
float radiansPerPixel;
|
||||||
@ -416,26 +416,26 @@ kernel void separateLumaKernel( texture2d<float, access::read> inTexture [[textu
|
|||||||
constant Uniforms &uniforms [[buffer(0)]],
|
constant Uniforms &uniforms [[buffer(0)]],
|
||||||
constant int &offset [[buffer(1)]]) {
|
constant int &offset [[buffer(1)]]) {
|
||||||
const float4 centreSample = inTexture.read(gid + uint2(7, offset));
|
const float4 centreSample = inTexture.read(gid + uint2(7, offset));
|
||||||
const float rawSamples[] = {
|
const float2 rawSamples[] = {
|
||||||
inTexture.read(gid + uint2(0, offset)).r,
|
inTexture.read(gid + uint2(0, offset)).rr,
|
||||||
inTexture.read(gid + uint2(1, offset)).r,
|
inTexture.read(gid + uint2(1, offset)).rr,
|
||||||
inTexture.read(gid + uint2(2, offset)).r,
|
inTexture.read(gid + uint2(2, offset)).rr,
|
||||||
inTexture.read(gid + uint2(3, offset)).r,
|
inTexture.read(gid + uint2(3, offset)).rr,
|
||||||
inTexture.read(gid + uint2(4, offset)).r,
|
inTexture.read(gid + uint2(4, offset)).rr,
|
||||||
inTexture.read(gid + uint2(5, offset)).r,
|
inTexture.read(gid + uint2(5, offset)).rr,
|
||||||
inTexture.read(gid + uint2(6, offset)).r,
|
inTexture.read(gid + uint2(6, offset)).rr,
|
||||||
centreSample.r,
|
centreSample.rr,
|
||||||
inTexture.read(gid + uint2(8, offset)).r,
|
inTexture.read(gid + uint2(8, offset)).rr,
|
||||||
inTexture.read(gid + uint2(9, offset)).r,
|
inTexture.read(gid + uint2(9, offset)).rr,
|
||||||
inTexture.read(gid + uint2(10, offset)).r,
|
inTexture.read(gid + uint2(10, offset)).rr,
|
||||||
inTexture.read(gid + uint2(11, offset)).r,
|
inTexture.read(gid + uint2(11, offset)).rr,
|
||||||
inTexture.read(gid + uint2(12, offset)).r,
|
inTexture.read(gid + uint2(12, offset)).rr,
|
||||||
inTexture.read(gid + uint2(13, offset)).r,
|
inTexture.read(gid + uint2(13, offset)).rr,
|
||||||
inTexture.read(gid + uint2(14, offset)).r,
|
inTexture.read(gid + uint2(14, offset)).rr,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define Sample(x, y) uniforms.lumaCoefficients[y] * rawSamples[x]
|
#define Sample(x, y) uniforms.lumaCoefficients[y] * rawSamples[x]
|
||||||
const float luminance =
|
const float2 luminance =
|
||||||
Sample(0, 0) + Sample(1, 1) + Sample(2, 2) + Sample(3, 3) + Sample(4, 4) + Sample(5, 5) + Sample(6, 6) +
|
Sample(0, 0) + Sample(1, 1) + Sample(2, 2) + Sample(3, 3) + Sample(4, 4) + Sample(5, 5) + Sample(6, 6) +
|
||||||
Sample(7, 7) +
|
Sample(7, 7) +
|
||||||
Sample(8, 6) + Sample(9, 5) + Sample(10, 4) + Sample(11, 3) + Sample(12, 2) + Sample(13, 1) + Sample(14, 0);
|
Sample(8, 6) + Sample(9, 5) + Sample(10, 4) + Sample(11, 3) + Sample(12, 2) + Sample(13, 1) + Sample(14, 0);
|
||||||
@ -444,8 +444,8 @@ kernel void separateLumaKernel( texture2d<float, access::read> inTexture [[textu
|
|||||||
// TODO: determine why centreSample.a doesn't seem to be giving the real composite amplitude, and stop
|
// TODO: determine why centreSample.a doesn't seem to be giving the real composite amplitude, and stop
|
||||||
// hard-coding 0.15f and 7.0f below.
|
// hard-coding 0.15f and 7.0f below.
|
||||||
outTexture.write(float4(
|
outTexture.write(float4(
|
||||||
luminance / (1.0f - 0.15f),
|
luminance.r / (1.0f - 0.15f),
|
||||||
(centreSample.gb - float2(0.5f)) * (centreSample.r - luminance) * 28.0f + float2(0.5f),
|
(centreSample.gb - float2(0.5f)) * (centreSample.r - luminance.g) * 28.0f + float2(0.5f),
|
||||||
1.0f
|
1.0f
|
||||||
),
|
),
|
||||||
gid + uint2(7, offset));
|
gid + uint2(7, offset));
|
||||||
|
Loading…
Reference in New Issue
Block a user