diff options
author | 2011-05-18 00:35:16 +0000 | |
---|---|---|
committer | 2011-05-18 00:35:16 +0000 | |
commit | 2820e314518e822aab30587a817f0266787ff4a4 (patch) | |
tree | 1eca7ad6f4ff8bb8f9d65a55a230fd492d662b8f /hlsl/post.fx | |
parent | 09cc8833fb7a53c72c125b2b310f95bfe2413682 (diff) |
HLSL Updates [Ryan Holtz, Bat Country Entertainment]
- Potential fix for some crashing reported by John IV
- Split color convolution and deconvergence into separate shaders for potential GPU savings down the line
- Added light and heavy variants of the color convolution shader, the former with YIQ colorspace removed
- Re-worked defocus to occur prior to shadow mask application, as it would be on a real monitor.
- Removed Edge Detection, as it was just for fun and can easily be added in by users if desired.
- Split "pincushion" into "Pincushion" and "Screen Curvature", the former affecting the only the displayed image and the latter only affecting the shadow mask.
Diffstat (limited to 'hlsl/post.fx')
-rw-r--r-- | hlsl/post.fx | 236 |
1 files changed, 51 insertions, 185 deletions
diff --git a/hlsl/post.fx b/hlsl/post.fx index 50e779c31f2..fa2082e6591 100644 --- a/hlsl/post.fx +++ b/hlsl/post.fx @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// Post-Processing Effect +// Scanline & Shadowmask Effect //----------------------------------------------------------------------------- texture Diffuse; @@ -38,9 +38,6 @@ struct VS_OUTPUT float4 Color : COLOR0; float2 TexCoord : TEXCOORD0; float2 ExtraInfo : TEXCOORD1; - float3 CoordX : TEXCOORD2; - float3 CoordY : TEXCOORD3; - float2 ShadowCoord : TEXCOORD4; }; struct VS_INPUT @@ -56,22 +53,12 @@ struct PS_INPUT float4 Color : COLOR0; float2 TexCoord : TEXCOORD0; float2 ExtraInfo : TEXCOORD1; - float3 CoordX : TEXCOORD2; - float3 CoordY : TEXCOORD3; - float2 ShadowCoord : TEXCOORD4; }; //----------------------------------------------------------------------------- -// Post-Processing Vertex Shader +// Scanline & Shadowmask Vertex Shader //----------------------------------------------------------------------------- -uniform float RedConvergeX; -uniform float RedConvergeY; -uniform float GrnConvergeX; -uniform float GrnConvergeY; -uniform float BluConvergeX; -uniform float BluConvergeY; - uniform float TargetWidth; uniform float TargetHeight; @@ -81,19 +68,10 @@ uniform float RawHeight; uniform float WidthRatio; uniform float HeightRatio; -uniform float RedRadialConvergeX; -uniform float RedRadialConvergeY; -uniform float GrnRadialConvergeX; -uniform float GrnRadialConvergeY; -uniform float BluRadialConvergeX; -uniform float BluRadialConvergeY; - VS_OUTPUT vs_main(VS_INPUT Input) { VS_OUTPUT Output = (VS_OUTPUT)0; - float2 invDims = float2(1.0f / RawWidth, 1.0f / RawHeight); - float2 Ratios = float2(1.0f / WidthRatio, 1.0f / HeightRatio); Output.Position = float4(Input.Position.xyz, 1.0f); Output.Position.x /= TargetWidth; Output.Position.y /= TargetHeight; @@ -102,18 +80,11 @@ VS_OUTPUT vs_main(VS_INPUT Input) Output.Position.y -= 0.5f; Output.Position *= float4(2.0f, 2.0f, 1.0f, 1.0f); Output.Color = Input.Color; - Output.TexCoord = Input.TexCoord;//(Input.TexCoord - float2(0.5f, 0.5f)) / 8.0f + float2(0.25f, 0.25f); + float2 InvTexSize = float2(1.0f / TargetWidth, 1.0f / TargetHeight); + float2 TexCoord = (Input.Position.xy * InvTexSize) / float2(WidthRatio, HeightRatio); + Output.TexCoord = TexCoord;//(Input.TexCoord - float2(0.5f, 0.5f)) / 8.0f + float2(0.25f, 0.25f); Output.ExtraInfo = Input.ExtraInfo; - Output.CoordX.x = ((((Output.TexCoord.x / Ratios.x) - 0.5f)) * (1.0f + RedRadialConvergeX / RawWidth) + 0.5f) * Ratios.x + RedConvergeX * invDims.x; - Output.CoordX.y = ((((Output.TexCoord.x / Ratios.x) - 0.5f)) * (1.0f + GrnRadialConvergeX / RawWidth) + 0.5f) * Ratios.x + GrnConvergeX * invDims.x; - Output.CoordX.z = ((((Output.TexCoord.x / Ratios.x) - 0.5f)) * (1.0f + BluRadialConvergeX / RawWidth) + 0.5f) * Ratios.x + GrnConvergeX * invDims.x; - - Output.CoordY.x = ((((Output.TexCoord.y / Ratios.y) - 0.5f)) * (1.0f + RedRadialConvergeY / RawHeight) + 0.5f) * Ratios.y + RedConvergeY * invDims.y; - Output.CoordY.y = ((((Output.TexCoord.y / Ratios.y) - 0.5f)) * (1.0f + GrnRadialConvergeY / RawHeight) + 0.5f) * Ratios.y + BluConvergeY * invDims.y; - Output.CoordY.z = ((((Output.TexCoord.y / Ratios.y) - 0.5f)) * (1.0f + BluRadialConvergeY / RawHeight) + 0.5f) * Ratios.y + BluConvergeY * invDims.y; - - Output.ShadowCoord = Output.TexCoord * float2(RawWidth, RawHeight); return Output; } @@ -123,8 +94,8 @@ VS_OUTPUT vs_main(VS_INPUT Input) uniform float PI = 3.14159265f; -uniform float PincushionAmountX = 0.1f; -uniform float PincushionAmountY = 0.1f; +uniform float PincushionAmount = 0.00f; +uniform float CurvatureAmount = 0.08f; uniform float ScanlineAmount = 1.0f; uniform float ScanlineScale = 1.0f; @@ -132,65 +103,12 @@ uniform float ScanlineBrightScale = 1.0f; uniform float ScanlineBrightOffset = 1.0f; uniform float ScanlineOffset = 1.0f; -uniform float RedFromRed = 1.0f; -uniform float RedFromGrn = 0.0f; -uniform float RedFromBlu = 0.0f; -uniform float GrnFromRed = 0.0f; -uniform float GrnFromGrn = 1.0f; -uniform float GrnFromBlu = 0.0f; -uniform float BluFromRed = 0.0f; -uniform float BluFromGrn = 0.0f; -uniform float BluFromBlu = 1.0f; - -uniform float YfromY = 1.0f; -uniform float YfromI = 0.0f; -uniform float YfromQ = 0.0f; -uniform float IfromY = 0.0f; -uniform float IfromI = 1.0f; -uniform float IfromQ = 0.0f; -uniform float QfromY = 0.0f; -uniform float QfromI = 0.0f; -uniform float QfromQ = 1.0f; - -uniform float RedOffset = 0.0f; -uniform float GrnOffset = 0.0f; -uniform float BluOffset = 0.0f; - -uniform float RedScale = 1.0f; -uniform float GrnScale = 1.0f; -uniform float BluScale = 1.0f; - -uniform float RedFloor = 0.0f; -uniform float GrnFloor = 0.0f; -uniform float BluFloor = 0.0f; - -uniform float Saturation = 1.0f; - -uniform float YScale = 1.0f; -uniform float IScale = 1.0f; -uniform float QScale = 1.0f; -uniform float YOffset = 0.0f; -uniform float IOffset = 0.0f; -uniform float QOffset = 0.0f; - -uniform float RedPower = 2.2f; -uniform float GrnPower = 2.2f; -uniform float BluPower = 2.2f; - -uniform float EdgeDetectScale = 1.0f; -uniform float EdgeToBaseRatio = 0.0f; - -uniform float SubsampleLength = 3.0f; - -uniform float CurrFrame = 0.0f; -uniform float CrawlWidth = 3.0f; -uniform float CrawlHeight = 3.0f; -uniform float CrawlRate = 3.0f; - uniform float UseShadow = 0.0f; uniform float ShadowBrightness = 1.0f; uniform float ShadowPixelSizeX = 3.0f; uniform float ShadowPixelSizeY = 3.0f; +uniform float ShadowMaskSizeX = 3.0f; +uniform float ShadowMaskSizeY = 3.0f; uniform float ShadowU = 0.375f; uniform float ShadowV = 0.375f; uniform float ShadowWidth = 8.0f; @@ -201,105 +119,53 @@ float4 ps_main(PS_INPUT Input) : COLOR float2 Ratios = float2(WidthRatio, HeightRatio); // -- Screen Pincushion Calculation -- - float2 UnitCoord = Input.TexCoord * Ratios * 2.0f - 1.0f; - - float PincushionR2 = pow(length(UnitCoord),2.0f) / pow(length(Ratios), 2.0f); - float2 PincushionCurve = UnitCoord * PincushionAmountX * PincushionR2; - float2 BaseCoord = Input.TexCoord + PincushionCurve; + float2 PinViewpointOffset = float2(0.0f, 0.0f); + float2 PinUnitCoord = (Input.TexCoord + PinViewpointOffset) * Ratios * 2.0f - 1.0f; + float PincushionR2 = pow(length(PinUnitCoord), 2.0f) / pow(length(Ratios), 2.0f); + float2 PincushionCurve = PinUnitCoord * PincushionAmount * PincushionR2; + float2 BaseCoord = Input.TexCoord; + BaseCoord -= 0.5f / Ratios; + BaseCoord *= 1.0f - PincushionAmount * Ratios * 0.2f; // Warning: Magic constant + BaseCoord += 0.5f / Ratios; + BaseCoord += PincushionCurve; + + float2 CurveViewpointOffset = float2(0.2f, 0.0f); + float2 CurveUnitCoord = (Input.TexCoord + CurveViewpointOffset) * 2.0f - 1.0f; + float CurvatureR2 = pow(length(CurveUnitCoord),2.0f) / pow(length(Ratios), 2.0f); + float2 CurvatureCurve = CurveUnitCoord * CurvatureAmount * CurvatureR2; + float2 ScreenCurveCoord = Input.TexCoord + CurvatureCurve; + + float2 CurveClipUnitCoord = Input.TexCoord * Ratios * 2.0f - 1.0f; + float CurvatureClipR2 = pow(length(CurveClipUnitCoord),2.0f) / pow(length(Ratios), 2.0f); + float2 CurvatureClipCurve = CurveClipUnitCoord * CurvatureAmount * CurvatureClipR2; + float2 ScreenClipCoord = Input.TexCoord; + ScreenClipCoord -= 0.5f / Ratios; + ScreenClipCoord *= 1.0f - CurvatureAmount * Ratios * 0.2f; // Warning: Magic constant + ScreenClipCoord += 0.5f / Ratios; + ScreenClipCoord += CurvatureClipCurve; // RGB Pincushion Calculation - float3 PincushionCurveX = UnitCoord.x * PincushionAmountX * PincushionR2; - float3 PincushionCurveY = UnitCoord.y * PincushionAmountX * PincushionR2; + float3 PincushionCurveX = PinUnitCoord.x * PincushionAmount * PincushionR2; + float3 PincushionCurveY = PinUnitCoord.y * PincushionAmount * PincushionR2; - float4 BaseTexel = tex2D(DiffuseSampler, BaseCoord); + float4 BaseTexel = tex2D(DiffuseSampler, BaseCoord * Ratios); // -- Alpha Clipping (1px border in drawd3d does not work for some reason) -- - clip((BaseCoord.x < 2.0f / RawWidth) ? -1 : 1); - clip((BaseCoord.y < 1.0f / RawHeight) ? -1 : 1); - clip((BaseCoord.x > (2.0f / WidthRatio - 2.0f / RawWidth)) ? -1 : 1); - clip((BaseCoord.y > 1.0f / HeightRatio) ? -1 : 1); - - // -- Chroma Subsampling & RGB Deconvergence -- - float3 CoordX = Input.CoordX + PincushionCurveX; - float3 CoordY = Input.CoordY + PincushionCurveY; - float RedTexel = tex2D(DiffuseSampler, float2(CoordX.x, CoordY.x)).r; - float GrnTexel = tex2D(DiffuseSampler, float2(CoordX.y, CoordY.y)).g; - float BluTexel = tex2D(DiffuseSampler, float2(CoordX.z, CoordY.z)).b; - - float ChromaSubsampleWidth = RawWidth / SubsampleLength; - float LumaSubsampleWidth = RawWidth / SubsampleLength; // For now - float3 YFrac = frac((CoordY * RawHeight) / CrawlHeight); - float3 CrawlPercent = frac(CurrFrame / CrawlRate + (YFrac - frac(YFrac * CrawlWidth) / CrawlWidth)) * CrawlWidth; - float3 ChromaCoordX = Input.CoordX + CrawlPercent / RawWidth; - float3 ChannelFrac = frac((ChromaCoordX + PincushionCurveX) * ChromaSubsampleWidth); - ChromaCoordX = ((ChromaCoordX + PincushionCurveX) * ChromaSubsampleWidth - ChannelFrac) / ChromaSubsampleWidth + ChannelFrac / (ChromaSubsampleWidth * 2.0f); - float3 ChromaCoordY = Input.CoordY + PincushionCurveY; - - float3 BaseTexelRight = tex2D(DiffuseSampler, BaseCoord + float2(1.0f / TargetWidth, 0.0f)).rgb; - float3 BaseTexelUpper = tex2D(DiffuseSampler, BaseCoord + float2(0.0f, 1.0f / TargetHeight)).rgb; - - float3 UpperDifference = abs(BaseTexel.rgb - BaseTexelUpper); - float3 RightDifference = abs(BaseTexel.rgb - BaseTexelRight); - float3 EdgeDifference = (UpperDifference + RightDifference) * EdgeDetectScale; - - float RedChromaTexel = tex2D(DiffuseSampler, float2(ChromaCoordX.x, ChromaCoordY.x)).r; - float GrnChromaTexel = tex2D(DiffuseSampler, float2(ChromaCoordX.y, ChromaCoordY.y)).g; - float BluChromaTexel = tex2D(DiffuseSampler, float2(ChromaCoordX.z, ChromaCoordY.z)).b; - - float3 ChromaTexel = float3(RedChromaTexel, GrnChromaTexel, BluChromaTexel); - float3 LumaTexel = float3(RedTexel, GrnTexel, BluTexel); - - // -- RGB Tint & Shift -- - float ShiftedRed = dot(LumaTexel, float3(RedFromRed, RedFromGrn, RedFromBlu)); - float ShiftedGrn = dot(LumaTexel, float3(GrnFromRed, GrnFromGrn, GrnFromBlu)); - float ShiftedBlu = dot(LumaTexel, float3(BluFromRed, BluFromGrn, BluFromBlu)); - float ShiftedRedChroma = dot(ChromaTexel, float3(RedFromRed, RedFromGrn, RedFromBlu)); - float ShiftedGrnChroma = dot(ChromaTexel, float3(GrnFromRed, GrnFromGrn, GrnFromBlu)); - float ShiftedBluChroma = dot(ChromaTexel, float3(BluFromRed, BluFromGrn, BluFromBlu)); - float EdgeRed = dot(EdgeDifference, float3(RedFromRed, RedFromGrn, RedFromBlu)); - float EdgeGrn = dot(EdgeDifference, float3(GrnFromRed, GrnFromGrn, GrnFromBlu)); - float EdgeBlu = dot(EdgeDifference, float3(BluFromRed, BluFromGrn, BluFromBlu)); - - // -- RGB Offset & Scale -- - float3 OutTexelLuma = float3(ShiftedRed, ShiftedGrn, ShiftedBlu) * float3(RedScale, GrnScale, BluScale) + float3(RedOffset, GrnOffset, BluOffset); - float3 OutTexelChroma = float3(ShiftedRedChroma, ShiftedGrnChroma, ShiftedBluChroma) * float3(RedScale, GrnScale, BluScale) + float3(RedOffset, GrnOffset, BluOffset); - - // -- Saturation -- - float OutLumaLuma = dot(OutTexelLuma, float3(0.3f, 0.59f, 0.11f)); - float3 OutChromaLuma = OutTexelLuma - float3(OutLumaLuma, OutLumaLuma, OutLumaLuma); - float3 SaturatedLuma = OutLumaLuma + OutChromaLuma * Saturation; - - float OutLumaChroma = dot(OutTexelChroma, float3(0.3f, 0.59f, 0.11f)); - float3 OutChromaChroma = OutTexelChroma - float3(OutLumaChroma, OutLumaChroma, OutLumaChroma); - float3 SaturatedChroma = OutLumaChroma + OutChromaChroma * Saturation; - - // -- YIQ Convolution -- - float Y = dot(SaturatedLuma, float3(0.299f, 0.587f, 0.114f)); - float I = dot(SaturatedChroma, float3(0.595716f, -0.274453f, -0.321263f)); - float Q = dot(SaturatedChroma, float3(0.211456f, -0.522591f, 0.311135f)); - Y = dot(float3(Y, I, Q), float3(YfromY, YfromI, YfromQ)); - I = dot(float3(Y, I, Q), float3(IfromY, IfromI, IfromQ)); - Q = dot(float3(Y, I, Q), float3(QfromY, QfromI, QfromQ)); - float3 OutYIQ = float3(Y, I, Q) * float3(YScale, IScale, QScale) + float3(YOffset, IOffset, QOffset); - float3 OutRGB = float3(dot(OutYIQ, float3(1.0f, 0.9563f, 0.6210f)), dot(OutYIQ, float3(1.0f, -0.2721f, -0.6474f)), dot(OutYIQ, float3(1.0f, -1.1070f, 1.7046f))); - - OutRGB = lerp(OutRGB, float3(EdgeRed, EdgeGrn, EdgeBlu), EdgeToBaseRatio); - - float3 Power = float3(RedPower, GrnPower, BluPower); - OutRGB = pow(OutRGB, Power); - - // -- Color Compression (increasing the floor of the signal without affecting the ceiling) -- - float3 Floor = float3(RedFloor, GrnFloor, BluFloor); - OutRGB = Floor + (1.0f - Floor) * OutRGB; + clip((ScreenClipCoord.x < 1.0f / TargetWidth) ? -1 : 1); + clip((ScreenClipCoord.y < 3.0f / TargetHeight) ? -1 : 1); + clip((ScreenClipCoord.x > 1.0f / WidthRatio) ? -1 : 1); + clip((ScreenClipCoord.y > 1.0f / HeightRatio) ? -1 : 1); // -- Scanline Simulation -- - float3 ScanBrightness = lerp(1.0f, abs(sin(((CoordY * RawHeight * ScanlineScale) * PI + ScanlineOffset * RawHeight))) * ScanlineBrightScale + ScanlineBrightOffset, ScanlineAmount); - float3 Scanned = OutRGB * ScanBrightness; - - float2 ShadowCoord = BaseCoord * float2(RawWidth, RawHeight); - float ShadowCoordX = frac(ShadowCoord.x / ShadowPixelSizeX) * ShadowU + 1.0f / ShadowWidth; - float ShadowCoordY = frac(ShadowCoord.y / ShadowPixelSizeY) * ShadowV + 1.0f / ShadowHeight; - float3 ShadowTexel = lerp(1.0f, tex2D(ShadowSampler, float2(ShadowCoordX, ShadowCoordY)), UseShadow); + float3 ScanBrightness = lerp(1.0f, abs(sin(((BaseCoord.y * Ratios.y * RawHeight * ScanlineScale) * PI + ScanlineOffset * RawHeight))) * ScanlineBrightScale + ScanlineBrightOffset, ScanlineAmount); + float3 Scanned = BaseTexel.rgb * ScanBrightness; + + float2 ShadowDims = float2(ShadowWidth, ShadowHeight); + float2 ShadowUV = float2(ShadowU, ShadowV); + float2 ShadowMaskSize = float2(ShadowMaskSizeX, ShadowMaskSizeY); + float2 ShadowFrac = frac(ScreenCurveCoord * ShadowMaskSize * Ratios * 0.5f); + float2 ShadowCoord = ShadowFrac * ShadowUV + 2.5f / ShadowDims; + float3 ShadowTexel = lerp(1.0f, tex2D(ShadowSampler, ShadowCoord), UseShadow); // -- Final Pixel -- float4 Output = lerp(Input.Color, float4(Scanned * lerp(1.0f, ShadowTexel * 1.25f, ShadowBrightness), BaseTexel.a) * Input.Color, Input.ExtraInfo.x); @@ -308,10 +174,10 @@ float4 ps_main(PS_INPUT Input) : COLOR } //----------------------------------------------------------------------------- -// Post-Processing Effect +// Scanline & Shadowmask Effect //----------------------------------------------------------------------------- -technique TestTechnique +technique ScanMaskTechnique { pass Pass0 { |