From a70198a5fb532f1b5826bcc0a318c1d68291c0c4 Mon Sep 17 00:00:00 2001 From: ImJezze Date: Sun, 3 May 2015 14:41:05 +0200 Subject: HLSL shader improvements - changed shadow mask implementation, shadow count XY now represent the number of pixel the shadow UV sized tiles will take on the screen - implemented rotation of the shadow mask texture depending on the default landscape or portrait view of the screen - removed prescale and pixel border of the shadow mask texture - added option to change the shadow UV offset, to reduce the color bleeding of the shadow mask - adjusted presets to work with the changed mask implementation - reduced defocus offset - improved downsampling for better blurring - improved alignment of bloom layers (raster and vector) - applied bloom effect to the render output of screenshot and AVI recording - changed curvature effect to fit screen size - changed scanlines to be not rendered into bloom layers - changed shadow mask to be not rendered into bloom layers - changed color floor to not light the bloom layers - changed shadow mask to not dark the color floor - added image vignetting simulation and option - added round screen corner simulation and option - added screen light reflection simulation and option - made usage of unused brightness offset (additive) - removed unused pincushion option - removed duplicate shadow count Y options - removed artwork/adapture.png - added artwork/adapture-grill.png - added artwork/shadow-mask.png - added artwork/slot-mask.png - added hlsl/simple.fx - removed unused shaders::blit() function - added shaders::screen_pass() function, which handles the (raster-)rendering on screen, into screenshot and AVI recording - added effect:set_bool() function --- hlsl/bloom.fx | 85 +++++++++---- hlsl/downsample.fx | 47 +++++-- hlsl/focus.fx | 42 ++++-- hlsl/post.fx | 365 ++++++++++++++++++++++++++++++++++++++++++----------- hlsl/simple.fx | 91 +++++++++++++ 5 files changed, 500 insertions(+), 130 deletions(-) create mode 100644 hlsl/simple.fx (limited to 'hlsl') diff --git a/hlsl/bloom.fx b/hlsl/bloom.fx index 69cc930c357..00353498b92 100644 --- a/hlsl/bloom.fx +++ b/hlsl/bloom.fx @@ -16,7 +16,7 @@ texture DiffuseK; sampler DiffuseSampler0 = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -27,7 +27,7 @@ sampler DiffuseSampler0 = sampler_state sampler DiffuseSampler1 = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -38,7 +38,7 @@ sampler DiffuseSampler1 = sampler_state sampler DiffuseSampler2 = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -49,7 +49,7 @@ sampler DiffuseSampler2 = sampler_state sampler DiffuseSampler3 = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -60,7 +60,7 @@ sampler DiffuseSampler3 = sampler_state sampler DiffuseSampler4 = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -71,7 +71,7 @@ sampler DiffuseSampler4 = sampler_state sampler DiffuseSampler5 = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -82,7 +82,7 @@ sampler DiffuseSampler5 = sampler_state sampler DiffuseSampler6 = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -93,7 +93,7 @@ sampler DiffuseSampler6 = sampler_state sampler DiffuseSampler7 = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -104,7 +104,7 @@ sampler DiffuseSampler7 = sampler_state sampler DiffuseSampler8 = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -115,7 +115,7 @@ sampler DiffuseSampler8 = sampler_state sampler DiffuseSampler9 = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -126,7 +126,7 @@ sampler DiffuseSampler9 = sampler_state sampler DiffuseSamplerA = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -156,7 +156,6 @@ struct VS_INPUT float3 Position : POSITION; float4 Color : COLOR0; float2 TexCoord : TEXCOORD0; - float2 Unused : TEXCOORD1; }; struct PS_INPUT @@ -174,7 +173,10 @@ struct PS_INPUT // Bloom Vertex Shader //----------------------------------------------------------------------------- -uniform float2 TargetSize; +uniform float2 ScreenDims; + +uniform float2 Prescale = float2(8.0f, 8.0f); + uniform float4 Level01Size; uniform float4 Level23Size; uniform float4 Level45Size; @@ -182,22 +184,43 @@ uniform float4 Level67Size; uniform float4 Level89Size; uniform float2 LevelASize; +uniform bool PrepareVector = false; + VS_OUTPUT vs_main(VS_INPUT Input) { VS_OUTPUT Output = (VS_OUTPUT)0; - + + float2 ScreenDimsTexel = 1.0f / ScreenDims; + + float2 HalfPrescale = Prescale * 0.5f; + Output.Position = float4(Input.Position.xyz, 1.0f); - Output.Position.xy /= TargetSize; + Output.Position.xy /= ScreenDims; Output.Position.y = 1.0f - Output.Position.y; - Output.Position.xy -= float2(0.5f, 0.5f); - Output.Position.xy *= float2(2.0f, 2.0f); + Output.Position.xy -= 0.5f; + Output.Position.xy *= 2.0f; + Output.Color = Input.Color; - Output.TexCoord01 = Input.Position.xyxy / TargetSize.xyxy - 0.5f / Level01Size; - Output.TexCoord23 = Input.Position.xyxy / TargetSize.xyxy - 0.5f / Level23Size; - Output.TexCoord45 = Input.Position.xyxy / TargetSize.xyxy - 0.5f / Level45Size; - Output.TexCoord67 = Input.Position.xyxy / TargetSize.xyxy - 0.5f / Level67Size; - Output.TexCoord89 = Input.Position.xyxy / TargetSize.xyxy - 0.5f / Level89Size; - Output.TexCoordA = Input.Position.xy / TargetSize - 0.5f / LevelASize; + + // Vector graphics is not prescaled it has the size of the screen + if (PrepareVector) + { + Output.TexCoord01 = Input.Position.xyxy / ScreenDims.xyxy + 1.0f / Level01Size; + Output.TexCoord23 = Input.Position.xyxy / ScreenDims.xyxy + 1.0f / Level23Size; + Output.TexCoord45 = Input.Position.xyxy / ScreenDims.xyxy + 1.0f / Level45Size; + Output.TexCoord67 = Input.Position.xyxy / ScreenDims.xyxy + 1.0f / Level67Size; + Output.TexCoord89 = Input.Position.xyxy / ScreenDims.xyxy + 1.0f / Level89Size; + Output.TexCoordA = Input.Position.xy / ScreenDims.xy + 1.0f / LevelASize; + } + else + { + Output.TexCoord01 = Input.Position.xyxy / ScreenDims.xyxy + HalfPrescale.xyxy / Level01Size; + Output.TexCoord23 = Input.Position.xyxy / ScreenDims.xyxy + HalfPrescale.xyxy / Level23Size; + Output.TexCoord45 = Input.Position.xyxy / ScreenDims.xyxy + HalfPrescale.xyxy / Level45Size; + Output.TexCoord67 = Input.Position.xyxy / ScreenDims.xyxy + HalfPrescale.xyxy / Level67Size; + Output.TexCoord89 = Input.Position.xyxy / ScreenDims.xyxy + HalfPrescale.xyxy / Level89Size; + Output.TexCoordA = Input.Position.xy / ScreenDims.xy + HalfPrescale.xy / LevelASize; + } return Output; } @@ -236,8 +259,18 @@ float4 ps_main(PS_INPUT Input) : COLOR texel9 = texel9 * Level89AWeight.y; texelA = texelA * Level89AWeight.z; - float4 sum = float4(texel0 + texel1 + texel2 + texel3 + texel4 + - texel5 + texel6 + texel7 + texel8 + texel9 + texelA, 1.0f); + float4 sum = float4( + texel0 + + texel1 + + texel2 + + texel3 + + texel4 + + texel5 + + texel6 + + texel7 + + texel8 + + texel9 + + texelA, 1.0f); return sum; } @@ -264,6 +297,6 @@ technique TestTechnique Sampler[10] = ; // 2x2 VertexShader = compile vs_3_0 vs_main(); - PixelShader = compile ps_3_0 ps_main(); + PixelShader = compile ps_3_0 ps_main(); } } diff --git a/hlsl/downsample.fx b/hlsl/downsample.fx index 8d073e4cdb0..cabe6b0bcde 100644 --- a/hlsl/downsample.fx +++ b/hlsl/downsample.fx @@ -6,7 +6,7 @@ texture DiffuseTexture; sampler DiffuseSampler = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -32,7 +32,6 @@ struct VS_INPUT float3 Position : POSITION; float4 Color : COLOR0; float2 TexCoord : TEXCOORD0; - float2 Unused : TEXCOORD1; }; struct PS_INPUT @@ -46,26 +45,46 @@ struct PS_INPUT // Downsample Vertex Shader //----------------------------------------------------------------------------- -uniform float2 ScreenSize; +uniform float2 ScreenDims; uniform float2 TargetSize; + +uniform float2 Prescale = float2(8.0f, 8.0f); + uniform float BloomRescale; +uniform bool PrepareVector = false; + VS_OUTPUT vs_main(VS_INPUT Input) { VS_OUTPUT Output = (VS_OUTPUT)0; - + + float2 TargetTexelSize = 1.0f / TargetSize; + Output.Position = float4(Input.Position.xyz, 1.0f); - Output.Position.xy /= ScreenSize; + Output.Position.xy /= ScreenDims; Output.Position.y = 1.0f - Output.Position.y; Output.Position.xy -= 0.5f; Output.Position.xy *= 2.0f; + Output.Color = Input.Color; - float2 InvTargetSize = 1.0f / TargetSize; - float2 TexCoord = Input.Position.xy / ScreenSize; - Output.TexCoord01.xy = TexCoord + float2(0.5f, 0.5f) * InvTargetSize; - Output.TexCoord01.zw = TexCoord + float2(1.5f, 0.5f) * InvTargetSize; - Output.TexCoord23.xy = TexCoord + float2(0.5f, 1.5f) * InvTargetSize; - Output.TexCoord23.zw = TexCoord + float2(1.5f, 1.5f) * InvTargetSize; + + float2 TexCoord = Input.Position.xy / ScreenDims; + + // Vector graphics is not prescaled it has the size of the screen + if (PrepareVector) + { + Output.TexCoord01.xy = TexCoord + float2(-0.5f, -0.5f) * TargetTexelSize; + Output.TexCoord01.zw = TexCoord + float2( 0.5f, -0.5f) * TargetTexelSize; + Output.TexCoord23.xy = TexCoord + float2(-0.5f, 0.5f) * TargetTexelSize; + Output.TexCoord23.zw = TexCoord + float2( 0.5f, 0.5f) * TargetTexelSize; + } + else + { + Output.TexCoord01.xy = TexCoord + float2(-0.5f, -0.5f) * TargetTexelSize * Prescale; + Output.TexCoord01.zw = TexCoord + float2( 0.5f, -0.5f) * TargetTexelSize * Prescale; + Output.TexCoord23.xy = TexCoord + float2(-0.5f, 0.5f) * TargetTexelSize * Prescale; + Output.TexCoord23.zw = TexCoord + float2( 0.5f, 0.5f) * TargetTexelSize * Prescale; + } return Output; } @@ -80,7 +99,9 @@ float4 ps_main(PS_INPUT Input) : COLOR float4 texel1 = tex2D(DiffuseSampler, Input.TexCoord01.zw); float4 texel2 = tex2D(DiffuseSampler, Input.TexCoord23.xy); float4 texel3 = tex2D(DiffuseSampler, Input.TexCoord23.zw); - float4 outTexel = (texel0 + texel1 + texel2 + texel3) * BloomRescale; + + float4 outTexel = (texel0 + texel1 + texel2 + texel3) / 4.0 * BloomRescale; + return float4(outTexel.rgb, 1.0f); } @@ -97,6 +118,6 @@ technique TestTechnique Sampler[0] = ; VertexShader = compile vs_2_0 vs_main(); - PixelShader = compile ps_2_0 ps_main(); + PixelShader = compile ps_2_0 ps_main(); } } diff --git a/hlsl/focus.fx b/hlsl/focus.fx index 6cb8cbdc56f..0e0c64a43c0 100644 --- a/hlsl/focus.fx +++ b/hlsl/focus.fx @@ -6,7 +6,7 @@ texture Diffuse; sampler DiffuseSampler = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -59,8 +59,11 @@ struct PS_INPUT //----------------------------------------------------------------------------- uniform float2 ScreenDims; + uniform float2 Defocus = float2(0.0f, 0.0f); +uniform float2 Prescale = float2(8.0f, 8.0f); + float2 Coord0Offset = float2( 0.0f, 0.0f); float2 Coord1Offset = float2(-0.2f, -0.6f); float2 Coord2Offset = float2( 0.4f, -0.4f); @@ -73,24 +76,31 @@ float2 Coord7Offset = float2(-0.6f, -0.4f); VS_OUTPUT vs_main(VS_INPUT Input) { VS_OUTPUT Output = (VS_OUTPUT)0; - + + float2 ScreenTexelDims = 1.0f / ScreenDims; + Output.Position = float4(Input.Position.xyz, 1.0f); Output.Position.xy /= ScreenDims; Output.Position.y = 1.0f - Output.Position.y; Output.Position.xy -= 0.5f; - Output.Position *= float4(2.0f, 2.0f, 1.0f, 1.0f); - Output.Color = Input.Color; + Output.Position.xy *= 2.0f; + + // todo: there is an offset which can be noticed at lower prescale in high-resolution + float2 FocusPrescaleOffset = ScreenTexelDims / Prescale; - float2 InvTexSize = 1.0f / ScreenDims; float2 TexCoord = Input.TexCoord; - Output.TexCoord0 = TexCoord + Coord0Offset * InvTexSize * Defocus; - Output.TexCoord1 = TexCoord + Coord1Offset * InvTexSize * Defocus; - Output.TexCoord2 = TexCoord + Coord2Offset * InvTexSize * Defocus; - Output.TexCoord3 = TexCoord + Coord3Offset * InvTexSize * Defocus; - Output.TexCoord4 = TexCoord + Coord4Offset * InvTexSize * Defocus; - Output.TexCoord5 = TexCoord + Coord5Offset * InvTexSize * Defocus; - Output.TexCoord6 = TexCoord + Coord6Offset * InvTexSize * Defocus; - Output.TexCoord7 = TexCoord + Coord7Offset * InvTexSize * Defocus; + TexCoord += FocusPrescaleOffset; + + Output.TexCoord0 = TexCoord + Coord0Offset * ScreenTexelDims * Defocus; + Output.TexCoord1 = TexCoord + Coord1Offset * ScreenTexelDims * Defocus; + Output.TexCoord2 = TexCoord + Coord2Offset * ScreenTexelDims * Defocus; + Output.TexCoord3 = TexCoord + Coord3Offset * ScreenTexelDims * Defocus; + Output.TexCoord4 = TexCoord + Coord4Offset * ScreenTexelDims * Defocus; + Output.TexCoord5 = TexCoord + Coord5Offset * ScreenTexelDims * Defocus; + Output.TexCoord6 = TexCoord + Coord6Offset * ScreenTexelDims * Defocus; + Output.TexCoord7 = TexCoord + Coord7Offset * ScreenTexelDims * Defocus; + + Output.Color = Input.Color; return Output; } @@ -114,6 +124,10 @@ float4 ps_main(PS_INPUT Input) : COLOR blurred = lerp(d0.rgb, blurred, 1.0f); return float4(blurred, d0.a); + + // float4 texel = tex2D(DiffuseSampler, Input.TexCoord0); + + // return float4(texel.rgb, 1.0f); } //----------------------------------------------------------------------------- @@ -129,6 +143,6 @@ technique TestTechnique Sampler[0] = ; VertexShader = compile vs_2_0 vs_main(); - PixelShader = compile ps_2_0 ps_main(); + PixelShader = compile ps_2_0 ps_main(); } } diff --git a/hlsl/post.fx b/hlsl/post.fx index 89a92fd6969..07b0aa92dbb 100644 --- a/hlsl/post.fx +++ b/hlsl/post.fx @@ -6,7 +6,7 @@ texture DiffuseTexture; sampler DiffuseSampler = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -19,7 +19,7 @@ texture ShadowTexture; sampler ShadowSampler = sampler_state { - Texture = ; + Texture = ; MipFilter = LINEAR; MinFilter = LINEAR; MagFilter = LINEAR; @@ -32,46 +32,70 @@ sampler ShadowSampler = sampler_state // Vertex Definitions //----------------------------------------------------------------------------- -struct VS_OUTPUT +struct VS_INPUT { float4 Position : POSITION; float4 Color : COLOR0; float2 TexCoord : TEXCOORD0; }; -struct VS_INPUT +struct VS_OUTPUT { float4 Position : POSITION; float4 Color : COLOR0; float2 TexCoord : TEXCOORD0; - float2 Unused : TEXCOORD1; + float2 ScreenCoord : TEXCOORD1; }; struct PS_INPUT { float4 Color : COLOR0; float2 TexCoord : TEXCOORD0; + float2 ScreenCoord : TEXCOORD1; }; //----------------------------------------------------------------------------- // Scanline & Shadowmask Vertex Shader //----------------------------------------------------------------------------- -uniform float2 ScreenDims; -uniform float2 SourceDims; -uniform float2 SourceRect; +uniform float2 ScreenDims; // size of the window or fullscreen +uniform float2 ScreenRatio = float2(1.0f, 3.0f / 4.0f); + +uniform float2 SourceDims; // size of the texture in power-of-two size +uniform float2 SourceRect; // size of the uv rectangle + +uniform float2 ShadowDims = float2(32.0f, 32.0f); // size of the shadow texture (extended to power-of-two size) +uniform float2 ShadowUVOffset = float2(0.0f, 0.0f); + +uniform float2 Prescale = float2(8.0f, 8.0f); + +uniform bool OrientationSwapXY = false; // false landscape, true portrait +uniform bool PrepareBloom = false; // disables some effects for rendering bloom textures VS_OUTPUT vs_main(VS_INPUT Input) { VS_OUTPUT Output = (VS_OUTPUT)0; - + + float2 ScreenTexelDims = 1.0f / ScreenDims; + float2 SourceTexelDims = 1.0f / SourceDims; + + // todo: calculate offset + float2 ScreenCoordPrescaleOffset = 0.0f; + ScreenCoordPrescaleOffset += ShadowUVOffset; + + Output.ScreenCoord = Input.Position; + Output.ScreenCoord += ScreenCoordPrescaleOffset; + Output.Position = float4(Input.Position.xyz, 1.0f); Output.Position.xy /= ScreenDims; - Output.Position.y = 1.0f - Output.Position.y; - Output.Position.xy -= 0.5f; - Output.Position *= float4(2.0f, 2.0f, 1.0f, 1.0f); + Output.Position.y = 1.0f - Output.Position.y; // flip y + Output.Position.xy -= 0.5f; // center + Output.Position.xy *= 2.0f; // zoom + + Output.TexCoord = Input.TexCoord; + Output.TexCoord -= SourceTexelDims * 0.5f; + Output.Color = Input.Color; - Output.TexCoord = Input.TexCoord + 0.5f / SourceDims; return Output; } @@ -80,90 +104,277 @@ VS_OUTPUT vs_main(VS_INPUT Input) // Post-Processing Pixel Shader //----------------------------------------------------------------------------- -uniform float PI = 3.14159265f; - -uniform float PincushionAmount = 0.00f; -uniform float CurvatureAmount = 0.08f; - uniform float ScanlineAlpha = 1.0f; uniform float ScanlineScale = 1.0f; uniform float ScanlineBrightScale = 1.0f; uniform float ScanlineBrightOffset = 1.0f; uniform float ScanlineOffset = 1.0f; -uniform float ScanlineHeight = 0.5f; +uniform float ScanlineHeight = 1.0f; + +uniform float CurvatureAmount = 0.0f; +uniform float RoundCornerAmount = 0.0f; +uniform float VignettingAmount = 0.0f; +uniform float ReflectionAmount = 0.0f; uniform float ShadowAlpha = 0.0f; -uniform float2 ShadowCount = float2(320.0f, 240.0f); -uniform float2 ShadowUV = float2(0.375f, 0.375f); -uniform float2 ShadowDims = float2(8.0f, 8.0f); +uniform float2 ShadowCount = float2(6.0f, 6.0f); +uniform float2 ShadowUV = float2(0.25f, 0.25f); uniform float3 Power = float3(1.0f, 1.0f, 1.0f); uniform float3 Floor = float3(0.0f, 0.0f, 0.0f); +static const float Epsilon = 1.0e-7f; +static const float PI = 3.1415927f; +static const float E = 2.7182817f; +static const float Gelfond = 23.140692f; // e^pi (Gelfond constant) +static const float GelfondSchneider = 2.6651442f; // 2^sqrt(2) (Gelfond–Schneider constant) + +float nextPowerOfTwo(float n) +{ + return pow(2, floor(log2(n) / log2(2)) + 1); +} + +// stackoverflow.com/questions/5149544/can-i-generate-a-random-number-inside-a-pixel-shader/ +float random(float2 seed) +{ + // irrationals for pseudo randomness + float2 i = float2(Gelfond, GelfondSchneider); + + return frac(cos(dot(seed, i)) * 123456.0f); +} + +// dinodini.wordpress.com/2010/04/05/normalized-tunable-sigmoid-functions/ +float normalizedSigmoid(float n, float k) +{ + // valid for n and k in range of -1.0 and 1.0 + return (n - n * k) / (k - abs(n) * 2.0f * k + 1); +} + +float GetNoiseFactor(float n, float random) +{ + // smaller n become more noisy + return 1.0f + random * max(0.0f, 0.25f * pow(E, -4 * n)); +} + +float GetVignetteFactor(float2 coord, float amount) +{ + float2 VignetteCoord = coord; + + float VignetteBlur = amount * 2.0f; + + // 0.5 full screen fitting circle + float VignetteRadius = 1.0f - amount * 0.5f; + float Vignette = smoothstep(VignetteRadius, VignetteRadius - VignetteBlur, length(VignetteCoord)); + + // reduce strength to 50% + Vignette = lerp(1.0, 1.0 * Vignette, 0.5f); + + return saturate(Vignette); +} + +float GetSpotAddend(float2 coord, float amount) +{ + float2 SpotCoord = coord; + SpotCoord += OrientationSwapXY + ? float2(-0.25f, -0.25f) * ScreenRatio // upper right quadrant + : float2(-0.25f, 0.25f) * ScreenRatio; // upper right quadrant + + float SpotBlur = amount; + + // 0.5 full screen fitting circle + float SpotRadius = amount * 0.75f; + float Spot = smoothstep(SpotRadius, SpotRadius - SpotBlur, length(SpotCoord)); + + float SigmoidSpot = normalizedSigmoid(Spot, 0.75) * amount; + + // increase strength by 100% + SigmoidSpot = SigmoidSpot * 2.0f; + + return saturate(SigmoidSpot); +} + +// www.iquilezles.org/www/articles/distfunctions/distfunctions.htm +float RoundBox(float2 p, float2 b, float r) +{ + return length(max(abs(p) - b + r, 0.0f)) - r; +} + +float GetRoundCornerFactor(float2 coord, float amount) +{ + float2 HalfSourceDims = SourceDims * 0.5f; + float2 SourceTexelDims = 1.0f / SourceDims; + + float2 RoundCoord = coord; + + // bug: offset and scale correction (due to miss-aligned fullscreen quad) + RoundCoord *= (1.0f + SourceTexelDims * ScreenRatio * 2.0f); + RoundCoord -= SourceTexelDims * ScreenRatio; + + // hint: roundness correction (base on the default ratio of 4:3) + RoundCoord *= SourceDims / ScreenRatio; + + float radius = amount * 50.0f; + + // compute box + float box = RoundBox(RoundCoord.xy, HalfSourceDims / ScreenRatio, radius); + + float solidBorder = smoothstep(1.0f, 0.5f, box); + + // apply blur + float blur = 1.0f / max(2.0f, amount * 100.0f); // blur amount + box *= blur * 2.0f; // blur stength + box += 1.0f - pow(blur * 0.5f, 0.5f); // blur offset + + float blurBorder = smoothstep(1.0f, 0.5f, box); + + float border = solidBorder * (blurBorder + 0.5f); + + return saturate(border); +} + float4 ps_main(PS_INPUT Input) : COLOR { + float2 ScreenTexelDims = 1.0f / ScreenDims; + float2 UsedArea = 1.0f / SourceRect; float2 HalfRect = SourceRect * 0.5f; - float2 R2 = 1.0f / pow(length(UsedArea), 2.0f); - // -- Screen Pincushion Calculation -- - float2 PinUnitCoord = Input.TexCoord * UsedArea * 2.0f - 1.0f; - float PincushionR2 = pow(length(PinUnitCoord), 2.0f) * R2; - float2 PincushionCurve = PinUnitCoord * PincushionAmount * PincushionR2; + + // Screen Curvature + float2 CurvatureUnitCoord = Input.TexCoord * (UsedArea * 2.0f) - 1.0f; + float2 CurvatureCurve = + CurvatureAmount * 0.25f + * CurvatureUnitCoord + * pow(length(CurvatureUnitCoord), 2.0f) + / pow(length(UsedArea), 2.0f); + float2 CurvatureZoom = 1.0f - (CurvatureAmount * 0.25f) * (UsedArea * 0.5f); + + float2 ScreenCoord = Input.ScreenCoord / ScreenDims; + ScreenCoord -= HalfRect; + ScreenCoord *= CurvatureZoom; // zoom + ScreenCoord += HalfRect; + ScreenCoord += CurvatureCurve; // distortion + float2 BaseCoord = Input.TexCoord; - float2 ScanCoord = BaseCoord - 0.5f / ScreenDims; - BaseCoord -= HalfRect; - BaseCoord *= 1.0f - PincushionAmount * UsedArea * 0.2f; // Warning: Magic constant + BaseCoord *= CurvatureZoom; // zoom BaseCoord += HalfRect; - BaseCoord += PincushionCurve; - - ScanCoord -= HalfRect; - ScanCoord *= 1.0f - PincushionAmount * UsedArea * 0.2f; // Warning: Magic constant - ScanCoord += HalfRect; - ScanCoord += PincushionCurve; - - float2 CurveClipUnitCoord = Input.TexCoord * UsedArea * 2.0f - 1.0f; - float CurvatureClipR2 = pow(length(CurveClipUnitCoord), 2.0f) * R2; - float2 CurvatureClipCurve = CurveClipUnitCoord * CurvatureAmount * CurvatureClipR2; - float2 ScreenClipCoord = Input.TexCoord; - ScreenClipCoord -= HalfRect; - ScreenClipCoord *= 1.0f - CurvatureAmount * UsedArea * 0.2f; // Warning: Magic constant - ScreenClipCoord += HalfRect; - ScreenClipCoord += CurvatureClipCurve; - - // RGB Pincushion Calculation - float3 PincushionCurveX = PinUnitCoord.x * PincushionAmount * PincushionR2; - float3 PincushionCurveY = PinUnitCoord.y * PincushionAmount * PincushionR2; - - float4 BaseTexel = tex2D(DiffuseSampler, BaseCoord); - - // -- Alpha Clipping (1px border in drawd3d does not work for some reason) -- - clip((BaseCoord < 1.0f / SourceDims) ? -1 : 1); - clip((BaseCoord > (SourceRect + 1.0f / SourceDims)) ? -1 : 1); - - // -- Scanline Simulation -- - float InnerSine = ScanCoord.y * SourceDims.y * ScanlineScale; - float ScanBrightMod = sin(InnerSine * PI + ScanlineOffset * SourceDims.y); - float3 ScanBrightness = lerp(1.0f, (pow(ScanBrightMod * ScanBrightMod, ScanlineHeight) * ScanlineBrightScale + 1.0f) * 0.5f, ScanlineAlpha); - float3 Scanned = BaseTexel.rgb * ScanBrightness; - - // -- Color Compression (increasing the floor of the signal without affecting the ceiling) -- - Scanned = Floor + (1.0f - Floor) * Scanned; - - // Shadow mask - // Note: This is broken right now and needs fixed - float2 ShadowFrac = frac(BaseCoord * ShadowCount); - float2 ShadowCoord = ShadowFrac * ShadowUV + 0.5f / ShadowDims; - float3 ShadowTexel = lerp(1.0f, tex2D(ShadowSampler, ShadowCoord).rgb, ShadowAlpha); + BaseCoord += CurvatureCurve; // distortion + + float2 BaseCoordCentered = Input.TexCoord; + BaseCoordCentered -= HalfRect; + BaseCoordCentered *= CurvatureZoom; // zoom + BaseCoordCentered += CurvatureCurve; // distortion + + // float2 BaseAreaRatioCoord = BaseCoord; + // BaseAreaRatioCoord *= UsedArea * ScreenRatio; + + float2 BaseAreaRatioCoordCentered = BaseCoordCentered; + BaseAreaRatioCoordCentered *= UsedArea * ScreenRatio; + + // float2 BaseAreaCoord = BaseCoord; + // BaseAreaCoord *= UsedArea; + + float2 BaseAreaCoordCentered = BaseCoordCentered; + BaseAreaCoordCentered *= UsedArea; + + // Alpha Clipping (1px border in drawd3d does not work for some reason) + clip(BaseCoord < ScreenTexelDims ? -1 : 1); + clip(BaseCoord > SourceRect + ScreenTexelDims ? -1 : 1); + + float4 BaseColor = tex2D(DiffuseSampler, BaseCoord); + BaseColor.a = 1.0f; + + // Vignetting Simulation (may affect bloom) + float2 VignetteCoord = BaseAreaRatioCoordCentered; + + float VignetteFactor = GetVignetteFactor(VignetteCoord, VignettingAmount); + BaseColor.rgb *= VignetteFactor; + + // Mask Simulation (may not affect bloom) + if (!PrepareBloom) + { + float2 ShadowTexelDims = 1.0f / ShadowDims; + ShadowTexelDims = OrientationSwapXY + ? ShadowTexelDims.yx + : ShadowTexelDims.xy; - // -- Final Pixel -- - float4 Output = float4(Scanned * ShadowTexel, BaseTexel.a) * Input.Color; + float2 shadowUV = ShadowUV; + shadowUV = OrientationSwapXY + ? shadowUV.yx + : shadowUV.xy; - Output.r = pow(Output.r, Power.r); - Output.g = pow(Output.g, Power.g); - Output.b = pow(Output.b, Power.b); + float2 screenCoord = ScreenCoord; + screenCoord = OrientationSwapXY + ? screenCoord.yx + : screenCoord.xy; + + float2 shadowTile = (ScreenTexelDims * ShadowCount); + shadowTile = OrientationSwapXY + ? shadowTile.yx + : shadowTile.xy; + + float2 ShadowFrac = frac(screenCoord / shadowTile); + float2 ShadowCoord = (ShadowFrac * shadowUV); + ShadowCoord += ShadowTexelDims * 0.5f; // half texel offset + ShadowCoord = OrientationSwapXY + ? ShadowCoord.yx + : ShadowCoord.xy; + + float3 ShadowColor = tex2D(ShadowSampler, ShadowCoord).rgb; + ShadowColor = lerp(1.0f, ShadowColor, ShadowAlpha); + + BaseColor.rgb *= ShadowColor; + } + + // Color Compression (may not affect bloom) + if (!PrepareBloom) + { + // increasing the floor of the signal without affecting the ceiling + BaseColor.rgb = Floor + (1.0f - Floor) * BaseColor.rgb; + } + + // Color Power (may affect bloom) + BaseColor.r = pow(BaseColor.r, Power.r); + BaseColor.g = pow(BaseColor.g, Power.g); + BaseColor.b = pow(BaseColor.b, Power.b); + + // Scanline Simulation (may not affect bloom) + if (!PrepareBloom) + { + // todo: there is an offset which can be noticed at lower prescale in high-resolution + float2 ScanlinePrescaleOffset = 0.0f; + + float InnerSine = BaseCoordCentered.y * ScanlineScale * SourceDims.y; + float ScanJitter = ScanlineOffset * SourceDims.y; + float ScanBrightMod = sin(InnerSine * PI + ScanJitter + ScanlinePrescaleOffset); + float3 ScanColor = lerp(1.0f, (pow(ScanBrightMod * ScanBrightMod, ScanlineHeight) * ScanlineBrightScale + 1.0f + ScanlineBrightOffset) * 0.5f, ScanlineAlpha); + + BaseColor.rgb *= ScanColor; + } + + // Output + float4 Output = BaseColor * Input.Color; Output.a = 1.0f; + // Light Reflection Simulation (may not affect bloom) + if (!PrepareBloom) + { + float3 LightColor = float3(1.0f, 0.90f, 0.80f); + + float2 SpotCoord = BaseAreaRatioCoordCentered; + float2 NoiseCoord = BaseAreaRatioCoordCentered; + + float SpotAddend = GetSpotAddend(SpotCoord, ReflectionAmount); + float NoiseFactor = GetNoiseFactor(SpotAddend, random(NoiseCoord)); + Output.rgb += SpotAddend * NoiseFactor * LightColor; + } + + // Round Corners Simulation (may affect bloom) + float2 RoundCornerCoord = BaseAreaCoordCentered; + + float roundCornerFactor = GetRoundCornerFactor(RoundCornerCoord, RoundCornerAmount); + Output.rgb *= roundCornerFactor; + return Output; } @@ -180,6 +391,6 @@ technique ScanMaskTechnique //Sampler[0] = ; VertexShader = compile vs_3_0 vs_main(); - PixelShader = compile ps_3_0 ps_main(); + PixelShader = compile ps_3_0 ps_main(); } -} +} \ No newline at end of file diff --git a/hlsl/simple.fx b/hlsl/simple.fx new file mode 100644 index 00000000000..9f510ea9c73 --- /dev/null +++ b/hlsl/simple.fx @@ -0,0 +1,91 @@ +//----------------------------------------------------------------------------- +// Effect File Variables +//----------------------------------------------------------------------------- + +texture DiffuseTexture; + +sampler DiffuseSampler = sampler_state +{ + Texture = ; + MipFilter = LINEAR; + MinFilter = LINEAR; + MagFilter = LINEAR; + AddressU = CLAMP; + AddressV = CLAMP; + AddressW = CLAMP; +}; + +//----------------------------------------------------------------------------- +// Vertex Definitions +//----------------------------------------------------------------------------- + +struct VS_OUTPUT +{ + float4 Position : POSITION; + float4 Color : COLOR0; + float2 TexCoord : TEXCOORD0; +}; + +struct VS_INPUT +{ + float3 Position : POSITION; + float4 Color : COLOR0; + float2 TexCoord : TEXCOORD0; +}; + +struct PS_INPUT +{ + float4 Color : COLOR0; + float2 TexCoord : TEXCOORD0; +}; + +//----------------------------------------------------------------------------- +// Simple Vertex Shader +//----------------------------------------------------------------------------- + +uniform float2 ScreenDims; + +VS_OUTPUT vs_main(VS_INPUT Input) +{ + VS_OUTPUT Output = (VS_OUTPUT)0; + + Output.Position = float4(Input.Position.xyz, 1.0f); + Output.Position.xy /= ScreenDims; + Output.Position.y = 1.0f - Output.Position.y; // flip y + Output.Position.xy -= 0.5f; // center + Output.Position.xy *= 2.0f; // zoom + + Output.TexCoord = Input.Position.xy / ScreenDims; + + Output.Color = Input.Color; + + return Output; +} + +//----------------------------------------------------------------------------- +// Simple Pixel Shader +//----------------------------------------------------------------------------- + +float4 ps_main(PS_INPUT Input) : COLOR +{ + float4 texel = tex2D(DiffuseSampler, Input.TexCoord); + + return float4(texel.rgb, 1.0f); +} + +//----------------------------------------------------------------------------- +// Simple Effect +//----------------------------------------------------------------------------- + +technique TestTechnique +{ + pass Pass0 + { + Lighting = FALSE; + + Sampler[0] = ; + + VertexShader = compile vs_2_0 vs_main(); + PixelShader = compile ps_2_0 ps_main(); + } +} -- cgit v1.2.3-70-g09d2