Files
2026-07-13 13:13:17 +08:00

119 lines
3.5 KiB
HLSL

cbuffer ParamConstants : register(b0)
{
float StepCount;
float Bias;
float Offset;
float HighlightIndex;
float4 Highlight;
float SmoothRadius;
float Repeat;
float UseSuperSampling;
}
cbuffer Resolution : register(b1)
{
float TargetWidth;
float TargetHeight;
}
struct vsOutput
{
float4 position : SV_POSITION;
float2 texCoord : TEXCOORD;
};
Texture2D<float4> ImageA : register(t0);
Texture2D<float4> RampImageA : register(t1);
sampler texSampler : register(s0);
float mod(float x, float y)
{
return ((x) - (y)*floor((x) / (y)));
}
int modi(int x, int y)
{
return x >= 0 ? (x % y)
: y - (-x % -y);
}
float Bias2(float x, float bias)
{
return x / ((1 / bias - 2) * (1 - x) + 1);
}
static float spreadFactor = (1 + 1 / (StepCount - 1)); // Saturate modulo to complete gradient width
float4 ComputeColor(float2 uv)
{
float4 orgColor = ImageA.Sample(texSampler, uv);
float gray = saturate((orgColor.r + orgColor.g + orgColor.b) / 3);
float biased = Bias2(gray, Bias);
float c = biased + Offset / StepCount;
float modulo = Repeat > 0.5 ? mod(c, 1)
: saturate(c);
int index = (int)(modulo * StepCount);
float main = index / (StepCount - 1);
float remainder = (modulo - main) * StepCount + main;
// Attempt to have a smooth transition at outer colors
if (Repeat > 0.5)
{
float modulo2 = Repeat > 0.5 ? mod(c - 0.01 + 1 / StepCount, 1)
: saturate(c);
int index2 = (int)(modulo2 * StepCount);
float main2 = index2 / (StepCount - 1);
float r = 100;
float edge = saturate(abs(gray - 0.5) * 2 * r - r + 1);
float offsetMod = mod(Offset - 0.01, 1);
float newEdge = lerp(main, main2, offsetMod);
main = lerp(main, newEdge, edge);
}
bool isHighlight = index == modi((int)HighlightIndex, (int)StepCount);
float4 rampColor = RampImageA.Sample(texSampler, float2(main, 0.5 / 2));
// float4 mainRampColor = isHighlight ? Highlight : rampColor;
float4 mainRampColor = isHighlight
? lerp(rampColor, Highlight, Highlight.a)
: rampColor;
// A legacy implementation that was using ramp color for alpha of highlight areas
// This turned out to be limiting for highlights on transparent ramps.
// float4 mainRampColor = isHighlight ? float4(lerp(rampColor.rgb, Highlight.rgb, Highlight.a), rampColor.a)
// : rampColor;
float4 edgeRampColor = RampImageA.Sample(texSampler, float2(remainder, 1.5 / 2));
float a = clamp(mainRampColor.a + edgeRampColor.a - mainRampColor.a * edgeRampColor.a, 0, 1);
float3 rgb = (1.0 - edgeRampColor.a) * mainRampColor.rgb + edgeRampColor.a * edgeRampColor.rgb;
return float4(rgb, a);
}
float4 psMain(vsOutput psInput) : SV_TARGET
{
float2 p = psInput.texCoord;
if (UseSuperSampling > 0.5)
{
float4 offsets[2];
offsets[0] = float4(-0.375, 0.125, 0.125, 0.375);
offsets[1] = float4(0.375, -0.125, -0.125, -0.375);
float2 sxy = float2(TargetWidth, TargetHeight);
return (ComputeColor(p + offsets[0].xy / sxy) +
ComputeColor(p + offsets[0].zw / sxy) +
ComputeColor(p + offsets[1].xy / sxy) +
ComputeColor(p + offsets[1].zw / sxy)) /
4;
}
else
{
return ComputeColor(p);
}
}