From 46172167c9ed4884d92da5df588cbcc92c4a7ac2 Mon Sep 17 00:00:00 2001 From: hunterk Date: Thu, 27 Apr 2017 10:38:48 -0500 Subject: [PATCH] add crtsim shader --- crt/crtsim.slangp | 22 ++++ crt/shaders/crtsim/artifacts.png | Bin 0 -> 3351 bytes crt/shaders/crtsim/composite.slang | 153 +++++++++++++++++++++++ crt/shaders/crtsim/crtbase.h | 70 +++++++++++ crt/shaders/crtsim/frame.slang | 115 +++++++++++++++++ crt/shaders/crtsim/mask.png | Bin 0 -> 3299 bytes crt/shaders/crtsim/post-downsample.slang | 86 +++++++++++++ crt/shaders/crtsim/post-upsample.slang | 86 +++++++++++++ crt/shaders/crtsim/present.slang | 100 +++++++++++++++ crt/shaders/crtsim/screen.slang | 100 +++++++++++++++ 10 files changed, 732 insertions(+) create mode 100644 crt/crtsim.slangp create mode 100644 crt/shaders/crtsim/artifacts.png create mode 100644 crt/shaders/crtsim/composite.slang create mode 100644 crt/shaders/crtsim/crtbase.h create mode 100644 crt/shaders/crtsim/frame.slang create mode 100644 crt/shaders/crtsim/mask.png create mode 100644 crt/shaders/crtsim/post-downsample.slang create mode 100644 crt/shaders/crtsim/post-upsample.slang create mode 100644 crt/shaders/crtsim/present.slang create mode 100644 crt/shaders/crtsim/screen.slang diff --git a/crt/crtsim.slangp b/crt/crtsim.slangp new file mode 100644 index 0000000..e3ac685 --- /dev/null +++ b/crt/crtsim.slangp @@ -0,0 +1,22 @@ +shaders = 5 + +shader0 = shaders/crtsim/composite.slang +filter_linear0 = false + +shader1 = shaders/crtsim/screen.slang +alias1 = CRTPASS + +shader2 = shaders/crtsim/post-downsample.slang +filter_linear2 = true + +shader3 = shaders/crtsim/post-upsample.slang +filter_linear3 = true + +shader4 = shaders/crtsim/present.slang +filter_linear4 = true + +textures = "NTSCArtifactSampler;shadowMaskSampler" +NTSCArtifactSampler = "shaders/crtsim/artifacts.png" +NTSCArtifactSampler_linear = true +shadowMaskSampler = "shaders/crtsim/mask.png" +shadowMaskSampler_linear = true \ No newline at end of file diff --git a/crt/shaders/crtsim/artifacts.png b/crt/shaders/crtsim/artifacts.png new file mode 100644 index 0000000000000000000000000000000000000000..d3990174b6a0f0f7e57a922ab69ff7f48f967d68 GIT binary patch literal 3351 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 literal 0 HcmV?d00001 diff --git a/crt/shaders/crtsim/composite.slang b/crt/shaders/crtsim/composite.slang new file mode 100644 index 0000000..dbb3b41 --- /dev/null +++ b/crt/shaders/crtsim/composite.slang @@ -0,0 +1,153 @@ +#version 450 + +////////////////////////////////////////////////////////////////////////// +// +// CC0 1.0 Universal (CC0 1.0) +// Public Domain Dedication +// +// To the extent possible under law, J. Kyle Pittman has waived all +// copyright and related or neighboring rights to this implementation +// of CRT simulation. This work is published from the United States. +// +// For more information, please visit +// https://creativecommons.org/publicdomain/zero/1.0/ +// +////////////////////////////////////////////////////////////////////////// + +// This is the second step of the CRT simulation process, +// after the ntsc.fx shader has transformed the RGB values with a lookup table. +// This is where we apply effects "inside the screen," including spatial and temporal bleeding, +// an unsharp mask to simulate overshoot/undershoot, NTSC artifacts, and so on. + +#define RcpScrWidth vec2(params.SourceSize.x, 0.0) +#define RcpScrHeight vec2(0.0, params.SourceSize.w) + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; + float Tuning_Sharp; // typically [0,1], defines the weighting of the sharpness taps + float Tuning_Persistence_R; // typically [0,1] per channel, defines the total blending of previous frame values + float Tuning_Persistence_G; + float Tuning_Persistence_B; + float Tuning_Bleed; // typically [0,1], defines the blending of L/R values with center value from prevous frame + float Tuning_Artifacts; // typically [0,1], defines the weighting of NTSC scanline artifacts (not physically accurate by any means) + float NTSCLerp; // Defines an interpolation between the two NTSC filter states. Typically would be 0 or 1 for vsynced 60 fps gameplay or 0.5 for unsynced, but can be whatever. + float NTSCArtifactScale; + float animate_artifacts; +} params; + +#pragma parameter Tuning_Sharp "Composite Sharp" 0.2 0.0 1.0 0.05 +#pragma parameter Tuning_Persistence_R "Red Persistence" 0.065 0.0 1.0 0.01 +#pragma parameter Tuning_Persistence_G "Green Persistence" 0.05 0.0 1.0 0.01 +#pragma parameter Tuning_Persistence_B "Blue Persistence" 0.05 0.0 1.0 0.01 +#pragma parameter Tuning_Bleed "Composite Bleed" 0.5 0.0 1.0 0.05 +#pragma parameter Tuning_Artifacts "Composite Artifacts" 0.5 0.0 1.0 0.05 +#pragma parameter NTSCLerp "NTSC Artifacts" 1.0 0.0 1.0 1.0 +#pragma parameter NTSCArtifactScale "NTSC Artifact Scale" 200.0 0.0 1000.0 5.0 +#pragma parameter animate_artifacts "Animate NTSC Artifacts" 1.0 0.0 1.0 1.0 + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +// Weight for applying an unsharp mask at a distance of 1, 2, or 3 pixels from changes in luma. +// The sign of each weight changes in order to alternately simulate overshooting and undershooting. +const float SharpWeight[3] = +{ + 1.0, -0.3162277, 0.1 +}; + +// Calculate luma for an RGB value. +float Brightness(vec4 InVal) +{ + return dot(InVal, vec4(0.299, 0.587, 0.114, 0.0)); +} + +#pragma stage vertex +// Passthrough vertex shader. Nothing interesting here. +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D PassFeedback0; +#define prevFrameSampler PassFeedback0 +layout(set = 0, binding = 3) uniform sampler2D Source; +#define curFrameSampler Source +layout(set = 0, binding = 4) uniform sampler2D NTSCArtifactSampler; + +#define lerp(a, b, c) mix(a, b, c) +#define tex2D(a, b) texture(a, b) +#define half4 vec4 +#define half2 vec2 +#define half float +#define saturate(c) clamp(c, 0.0, 1.0) + +void main() +{ + half2 scanuv = vec2(fract(vTexCoord * 1.0001 * params.SourceSize.xy / params.NTSCArtifactScale)); + half4 NTSCArtifact1 = tex2D(NTSCArtifactSampler, scanuv); + half4 NTSCArtifact2 = tex2D(NTSCArtifactSampler, scanuv + vec2(0.0, 1.0 / params.SourceSize.y)); + half4 NTSCArtifact = lerp(NTSCArtifact1, NTSCArtifact2, 1.0 - params.NTSCLerp); + + float artifacting = (params.animate_artifacts > 0.5) ? mod(params.FrameCount, 2.0) : 1.0; + half2 LeftUV = vTexCoord - vec2(artifacting / params.SourceSize.x, 0.0);//RcpScrWidth; + half2 RightUV = vTexCoord + vec2(artifacting / params.SourceSize.x, 0.0);//RcpScrWidth; + + half4 Cur_Left = tex2D(curFrameSampler, LeftUV); + half4 Cur_Local = tex2D(curFrameSampler, vTexCoord); + half4 Cur_Right = tex2D(curFrameSampler, RightUV); + + half4 TunedNTSC = NTSCArtifact * params.Tuning_Artifacts; + + // Note: The "persistence" and "bleed" parameters have some overlap, but they are not redundant. + // "Persistence" affects bleeding AND trails. (Scales the sum of the previous value and its scaled neighbors.) + // "Bleed" only affects bleeding. (Scaling of neighboring previous values.) + + half4 Prev_Left = tex2D(prevFrameSampler, LeftUV); + half4 Prev_Local = tex2D(prevFrameSampler, vTexCoord); + half4 Prev_Right = tex2D(prevFrameSampler, RightUV); + + // Apply NTSC artifacts based on differences in luma between local pixel and neighbors.. + Cur_Local = + saturate(Cur_Local + + (((Cur_Left - Cur_Local) + (Cur_Right - Cur_Local)) * TunedNTSC)); + + half curBrt = Brightness(Cur_Local); + half offset = 0.; + + // Step left and right looking for changes in luma that would produce a ring or halo on this pixel due to undershooting/overshooting. + // (Note: It would probably be more accurate to look at changes in luma between pixels at a distance of N and N+1, + // as opposed to 0 and N as done here, but this works pretty well and is a little cheaper.) + for (int i = 0; i < 3; ++i) + { + half2 StepSize = (half2(1.0/256.0,0) * (float(i + 1))); + half4 neighborleft = tex2D(curFrameSampler, vTexCoord - StepSize); + half4 neighborright = tex2D(curFrameSampler, vTexCoord + StepSize); + + half NBrtL = Brightness(neighborleft); + half NBrtR = Brightness(neighborright); + offset += ((((curBrt - NBrtL) + (curBrt - NBrtR))) * SharpWeight[i]); + } + + // Apply the NTSC artifacts to the unsharp offset as well. + Cur_Local = saturate(Cur_Local + (offset * params.Tuning_Sharp * lerp(ivec4(1,1,1,1), NTSCArtifact, params.Tuning_Artifacts))); + + vec4 Tuning_Persistence = vec4(params.Tuning_Persistence_R, params.Tuning_Persistence_G, params.Tuning_Persistence_B, 1.0); + // Take the max here because adding is overkill; bleeding should only brighten up dark areas, not blow out the whole screen. + Cur_Local = saturate(max(Cur_Local, Tuning_Persistence * (10.0 / (1.0 + (2.0 * params.Tuning_Bleed))) * (Prev_Local + ((Prev_Left + Prev_Right) * params.Tuning_Bleed)))); + + FragColor = vec4(Cur_Local); +} \ No newline at end of file diff --git a/crt/shaders/crtsim/crtbase.h b/crt/shaders/crtsim/crtbase.h new file mode 100644 index 0000000..f6205fc --- /dev/null +++ b/crt/shaders/crtsim/crtbase.h @@ -0,0 +1,70 @@ +layout(push_constant) uniform Push +{ + float CRTMask_Scale; +// float CRTMask_Offset_X; +// float CRTMask_Offset_Y; +// float Tuning_Overscan; +// float Tuning_Dimming; + float Tuning_Satur; +// float Tuning_ReflScalar; +// float Tuning_Barrel; + float Tuning_Mask_Brightness; + float Tuning_Mask_Opacity; +// float Tuning_Diff_Brightness; +// float Tuning_Spec_Brightness; +// float Tuning_Spec_Power; +// float Tuning_Fres_Brightness; +// float Tuning_LightPos_R; +// float Tuning_LightPos_G; +// float Tuning_LightPos_B; +} params; + +#pragma parameter CRTMask_Scale "CRT Mask Scale" 1.0 0.0 10.0 0.5 +//#pragma parameter CRTMask_Offset_X "CRT Mask Offset X" 0.0 0.0 1.0 0.05 +//#pragma parameter CRTMask_Offset_Y "CRT Mask Offset Y" 0.0 0.0 1.0 0.05 +//#pragma parameter Tuning_Overscan "Overscan" 0.95 0.0 1.0 0.05 +//#pragma parameter Tuning_Dimming "Dimming" 0.0 0.0 1.0 0.05 +#pragma parameter Tuning_Satur "Saturation" 1.0 0.0 1.0 0.05 +//#pragma parameter Tuning_ReflScalar "Reflection" 0.0 0.0 1.0 0.05 +//#pragma parameter Tuning_Barrel "Barrel Distortion" 0.25 0.0 1.0 0.05 +#pragma parameter Tuning_Mask_Brightness "Mask Brightness" 0.5 0.0 1.0 0.05 +#pragma parameter Tuning_Mask_Opacity "Mask Opacity" 0.3 0.0 1.0 0.05 +//#pragma parameter Tuning_Diff_Brightness "Diff Brightness" 0.5 0.0 1.0 0.05 +//#pragma parameter Tuning_Spec_Brightness "Spec Brightness" 0.5 0.0 1.0 0.05 +//#pragma parameter Tuning_Fres_Brightness "Fres Brightness" 0.5 0.0 1.0 0.05 +//#pragma parameter Tuning_LightPos_R "Light Position R" 1.0 0.0 1.0 0.05 +//#pragma parameter Tuning_LightPos_G "Light Position G" 1.0 0.0 1.0 0.05 +//#pragma parameter Tuning_LightPos_B "Light Position B" 1.0 0.0 1.0 0.05 + +#define CRTMask_Offset vec2(params.CRTMask_Offset_X, params.CRTMask_Offset_Y) + +half4 SampleCRT(sampler2D shadowMaskSampler, sampler2D compFrameSampler, half2 uv) +{ + half2 ScaledUV = uv; +// ScaledUV *= UVScalar; +// ScaledUV += UVOffset; + + half2 scanuv = vec2(fract(uv * global.SourceSize.xy / params.CRTMask_Scale)); + vec4 phosphor_grid; + half3 scantex = tex2D(shadowMaskSampler, scanuv).rgb; + + scantex += params.Tuning_Mask_Brightness; // adding looks better + scantex = lerp(ivec3(1,1,1), scantex, params.Tuning_Mask_Opacity); +/* // commenting this to move to present shader + // Apply overscan after scanline sampling is done. + half2 overscanuv = (ScaledUV * params.Tuning_Overscan) - ((params.Tuning_Overscan - 1.0) * 0.5); + + // Curve UVs for composite texture inwards to garble things a bit. + overscanuv = overscanuv - half2(0.5,0.5); + half rsq = (overscanuv.x*overscanuv.x) + (overscanuv.y*overscanuv.y); + overscanuv = overscanuv + (overscanuv * (params.Tuning_Barrel * rsq)) + half2(0.5,0.5); +*/ + half2 overscanuv = uv; + half3 comptex = tex2D(compFrameSampler, overscanuv).rgb; + + half4 emissive = half4(comptex * scantex, 1); + half desat = dot(half4(0.299, 0.587, 0.114, 0.0), emissive); + emissive = lerp(half4(desat,desat,desat,1), emissive, params.Tuning_Satur); + + return emissive; +} \ No newline at end of file diff --git a/crt/shaders/crtsim/frame.slang b/crt/shaders/crtsim/frame.slang new file mode 100644 index 0000000..5a46d4c --- /dev/null +++ b/crt/shaders/crtsim/frame.slang @@ -0,0 +1,115 @@ +#version 450 + +////////////////////////////////////////////////////////////////////////// +// +// CC0 1.0 Universal (CC0 1.0) +// Public Domain Dedication +// +// To the extent possible under law, J. Kyle Pittman has waived all +// copyright and related or neighboring rights to this implementation +// of CRT simulation. This work is published from the United States. +// +// For more information, please visit +// https://creativecommons.org/publicdomain/zero/1.0/ +// +////////////////////////////////////////////////////////////////////////// + +#define half4 vec4 +#define half3 vec3 +#define half2 vec2 +#define half float +#define lerp(a, b, c) mix(a, b, c) +#define tex2D(a, b) texture(a, b) +#define mul(a, b) (b * a) +#define saturate(c) clamp(c, 0.0, 1.0) + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; + float FrameColor_R; + float FrameColor_G; + float FrameColor_B; +} global; + +#pragma parameter FrameColor_R "Frame Color R" 1.0 0.0 1.0 0.05 +#pragma parameter FrameColor_G "Frame Color G" 1.0 0.0 1.0 0.05 +#pragma parameter FrameColor_B "Frame Color B" 1.0 0.0 1.0 0.05 + +#include "crtbase.h" + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; +//layout(location = 1) out vec3 norm; +//layout(location = 2) out vec3 camDir; +//layout(location = 3) out vec3 lightDir; +//layout(location = 4) out float blend; + +//mat4x4 wvpMat = global.MVP; +//mat4x4 worldMat = global.MVP; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; + /* + // This is really unnecessary since it SHOULD always be identity, but whatever... + half3 worldPos = mul(half4(Position.xyz, 1.0), worldMat).xyz; + + // Don't normalize this pre-pixel shader + camDir = camPos - worldPos; + lightDir = params.Tuning_LightPos - worldPos; + */ +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +//layout(location = 1) in vec3 norm; +//layout(location = 2) in vec3 camDir; +//layout(location = 3) in vec3 lightDir; +//layout(location = 4) in float blend; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; +layout(set = 0, binding = 3) uniform sampler2D shadowMaskSampler; + +void main() +{ + /* + half3 norm = normalize(norm); + + half3 camDir = normalize(camDir); + half3 lightDir = normalize(lightDir); + + half diffuse = saturate(dot(norm, lightDir)); + + half3 worldUp = half3(0.,0.,1.); + half hemi = dot(norm, worldUp) * 0.5 + 0.5; + hemi = hemi * 0.4 + 0.3; // [0.3,0.7] range + + vec4 Tuning_FrameColor = vec4(global.FrameColor_R, global.FrameColor_G, global.FrameColor_B, 1.0); + half4 colordiff = Tuning_FrameColor * (diffuse + hemi) * params.Tuning_Diff_Brightness; + + half3 halfVec = normalize(lightDir + camDir); + half spec = saturate(dot(norm, halfVec)); + spec = pow(spec, Tuning_Spec_Power); + half4 colorspec = half4(0.25, 0.25, 0.25, 1.) * spec * params.Tuning_Spec_Brightness; + + half4 emissive = SampleCRT(shadowMaskSampler, Source, vTexCoord); + + colorspec += (emissive * blend * Tuning_ReflScalar); + + half fres = 1.0 - dot(camDir, norm); + fres = (fres*fres) * Tuning_Fres_Brightness; + half4 colorfres = half4(0.15, 0.15, 0.15, 1.) * fres; + + half4 nearfinal = (colorfres + colordiff + colorspec); + + FragColor = (nearfinal * lerp(ivec4(1,1,1,1), color, Tuning_Dimming)); + */ + FragColor = vec4(SampleCRT(shadowMaskSampler, Source, vTexCoord)); +} \ No newline at end of file diff --git a/crt/shaders/crtsim/mask.png b/crt/shaders/crtsim/mask.png new file mode 100644 index 0000000000000000000000000000000000000000..e786f5b8dd46ea216d7901df6193d0d6974ed448 GIT binary patch literal 3299 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 hv|gXqLZ= 0.5) ? vTexCoord : overscanuv; + PreBloom = (global.mask_toggle > 0.5) ? SampleCRT(shadowMaskSampler, CRTPASS, overscanuv) : texture(CRTPASS, overscanuv); + + vec4 Blurred = texture(Source, overscanuv); + FragColor = vec4(PreBloom + (ColorPow(Blurred, global.BloomPower) * global.BloomScalar));//vec4(mix(PreBloom, Blurred, global.mixfactor)); +} \ No newline at end of file diff --git a/crt/shaders/crtsim/screen.slang b/crt/shaders/crtsim/screen.slang new file mode 100644 index 0000000..cac0a4f --- /dev/null +++ b/crt/shaders/crtsim/screen.slang @@ -0,0 +1,100 @@ +#version 450 + +////////////////////////////////////////////////////////////////////////// +// +// CC0 1.0 Universal (CC0 1.0) +// Public Domain Dedication +// +// To the extent possible under law, J. Kyle Pittman has waived all +// copyright and related or neighboring rights to this implementation +// of CRT simulation. This work is published from the United States. +// +// For more information, please visit +// https://creativecommons.org/publicdomain/zero/1.0/ +// +////////////////////////////////////////////////////////////////////////// + +#define half4 vec4 +#define half3 vec3 +#define half2 vec2 +#define half float +#define lerp(a, b, c) mix(a, b, c) +#define tex2D(a, b) texture(a, b) +#define mul(a, b) (b * a) +#define saturate(c) clamp(c, 0.0, 1.0) + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} global; + +#include "crtbase.h" + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; +//layout(location = 1) out vec3 norm; +//layout(location = 2) out vec3 camDir; +//layout(location = 3) out vec3 lightDir; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; + +/* +// Going head and getting this stuff ready but not hooking anything up yet + mat3x3 wMat3 = mat3x3(worldMat[0].xyz, worldMat[1].xyz, worldMat[2].xyz); + mat3x3 invWorldRot = transpose(wMat3); + + // Don't normalize this pre-pixel shader + camDir = mul(camPos - worldPos, invWorldRot); + vec3 Tuning_lightPos = vec3(params.Tuning_lightPos_R, params.Tuning_lightPos_G, params.Tuning_lightPos_B); + lightDir = mul(Tuning_LightPos - worldPos, invWorldRot) +*/ +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +//layout(location = 1) in vec3 norm; +//layout(location = 2) in vec3 camDir; +//layout(location = 3) in vec3 lightDir; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; +layout(set = 0, binding = 3) uniform sampler2D shadowMaskSampler; + +void main() +{ + /* + half3 norm = normalize(norm); + + half3 camDir = normalize(camDir); + half3 lightDir = normalize(lightDir); + + half3 refl = reflect(camDir, norm); + + half diffuse = saturate(dot(norm, lightDir)); + half4 colordiff = half4(0.175, 0.15, 0.2, 1.) * diffuse * params.Tuning_Diff_Brightness; + + half3 halfVec = normalize(lightDir + camDir); + half spec = saturate(dot(norm, halfVec)); + spec = pow(spec, params.Tuning_Spec_Power); + half4 colorspec = half4(0.25, 0.25, 0.25, 1.) * spec * params.Tuning_Spec_Brightness; + + half fres = 1.0 - dot(camDir, norm); + fres = (fres*fres) * params.Tuning_Fres_Brightness; + half4 colorfres = half4(0.45, 0.4, 0.5, 1.) * fres; + + half4 emissive = SampleCRT(shadowMaskSampler, Source, vTexCoord); + + half4 nearfinal = colorfres + colordiff + colorspec + emissive; + + FragColor = (nearfinal * lerp(ivec4(1,1,1,1), color, params.Tuning_Dimming)); //TODO: not sure what 'color' would be here + */ + FragColor = vec4(SampleCRT(shadowMaskSampler, Source, vTexCoord)); +} \ No newline at end of file