diff --git a/package/Shaders/ISAlphaBlend.hlsl b/package/Shaders/ISAlphaBlend.hlsl new file mode 100644 index 000000000..e7d771a19 --- /dev/null +++ b/package/Shaders/ISAlphaBlend.hlsl @@ -0,0 +1,83 @@ +#include "Common/DummyVSTexCoord.hlsl" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState TintMask0Sampler : register(s0); +SamplerState TintMask1Sampler : register(s1); +SamplerState TintMask2Sampler : register(s2); +SamplerState TintMask3Sampler : register(s3); +SamplerState TintMask4Sampler : register(s4); +SamplerState TintMask5Sampler : register(s5); +SamplerState TintMask6Sampler : register(s6); +SamplerState TintMask7Sampler : register(s7); +SamplerState TintMask8Sampler : register(s8); +SamplerState TintMask9Sampler : register(s9); +SamplerState TintMask10Sampler : register(s10); +SamplerState TintMask11Sampler : register(s11); +SamplerState TintMask12Sampler : register(s12); +SamplerState TintMask13Sampler : register(s13); +SamplerState TintMask14Sampler : register(s14); +SamplerState TintMask15Sampler : register(s15); + +Texture2D TintMask0Tex : register(t0); +Texture2D TintMask1Tex : register(t1); +Texture2D TintMask2Tex : register(t2); +Texture2D TintMask3Tex : register(t3); +Texture2D TintMask4Tex : register(t4); +Texture2D TintMask5Tex : register(t5); +Texture2D TintMask6Tex : register(t6); +Texture2D TintMask7Tex : register(t7); +Texture2D TintMask8Tex : register(t8); +Texture2D TintMask9Tex : register(t9); +Texture2D TintMask10Tex : register(t10); +Texture2D TintMask11Tex : register(t11); +Texture2D TintMask12Tex : register(t12); +Texture2D TintMask13Tex : register(t13); +Texture2D TintMask14Tex : register(t14); +Texture2D TintMask15Tex : register(t15); + +cbuffer PerGeometry : register(b2) +{ + float4 Color[16] : packoffset(c0); +}; + +float3 BlendAlpha(Texture2D tintMaskTex, SamplerState tintMaskSamplerState, float2 texCoord, float4 blendColor, float3 color) +{ + float tintMask = tintMaskTex.Sample(tintMaskSamplerState, texCoord).x; + return blendColor.xyz * (1 - tintMask * blendColor.w) + (blendColor.w * tintMask) * color; +} + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float3 color = 0.5.xxx; + + color = BlendAlpha(TintMask0Tex, TintMask0Sampler, input.TexCoord, Color[0], color); + color = BlendAlpha(TintMask1Tex, TintMask1Sampler, input.TexCoord, Color[1], color); + color = BlendAlpha(TintMask2Tex, TintMask2Sampler, input.TexCoord, Color[2], color); + color = BlendAlpha(TintMask3Tex, TintMask3Sampler, input.TexCoord, Color[3], color); + color = BlendAlpha(TintMask4Tex, TintMask4Sampler, input.TexCoord, Color[4], color); + color = BlendAlpha(TintMask5Tex, TintMask5Sampler, input.TexCoord, Color[5], color); + color = BlendAlpha(TintMask6Tex, TintMask6Sampler, input.TexCoord, Color[6], color); + color = BlendAlpha(TintMask7Tex, TintMask7Sampler, input.TexCoord, Color[7], color); + color = BlendAlpha(TintMask8Tex, TintMask8Sampler, input.TexCoord, Color[8], color); + color = BlendAlpha(TintMask9Tex, TintMask9Sampler, input.TexCoord, Color[9], color); + color = BlendAlpha(TintMask10Tex, TintMask10Sampler, input.TexCoord, Color[10], color); + color = BlendAlpha(TintMask11Tex, TintMask11Sampler, input.TexCoord, Color[11], color); + color = BlendAlpha(TintMask12Tex, TintMask12Sampler, input.TexCoord, Color[12], color); + color = BlendAlpha(TintMask13Tex, TintMask13Sampler, input.TexCoord, Color[13], color); + color = BlendAlpha(TintMask14Tex, TintMask14Sampler, input.TexCoord, Color[14], color); + color = BlendAlpha(TintMask15Tex, TintMask15Sampler, input.TexCoord, Color[15], color); + + psout.Color = float4(color, 1); + + return psout; +} +#endif diff --git a/package/Shaders/ISApplyReflections.hlsl b/package/Shaders/ISApplyReflections.hlsl new file mode 100644 index 000000000..950c7c71c --- /dev/null +++ b/package/Shaders/ISApplyReflections.hlsl @@ -0,0 +1,45 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float3 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState SSRSourceSampler : register(s0); +SamplerState WaterMaskSampler : register(s1); +SamplerState MainBufferSampler : register(s2); + +Texture2D SSRSourceTex : register(t0); +Texture2D WaterMaskTex : register(t1); +Texture2D MainBufferTex : register(t2); + +cbuffer PerGeometry : register(b2) +{ + float4 SSRParams : packoffset(c0); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float2 adjustedScreenPosition = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord.xy); + + float2 waterMask = WaterMaskTex.SampleLevel(WaterMaskSampler, adjustedScreenPosition, 0).zw; + float3 mainColor = MainBufferTex.Sample(MainBufferSampler, adjustedScreenPosition).xyz; + + float3 colorOffset = 0.0.xxx; + if (waterMask.x >= 1e-5 && waterMask.y > 1e-5) { + float4 ssrSourceColor = SSRSourceTex.Sample(SSRSourceSampler, adjustedScreenPosition); + colorOffset = clamp(SSRParams.x * (ssrSourceColor.xyz * ssrSourceColor.w), + 0, SSRParams.y * mainColor); + } + + psout.Color = colorOffset + mainColor; + + return psout; +} +#endif diff --git a/package/Shaders/ISBasicCopy.hlsl b/package/Shaders/ISBasicCopy.hlsl new file mode 100644 index 000000000..6c90726e8 --- /dev/null +++ b/package/Shaders/ISBasicCopy.hlsl @@ -0,0 +1,24 @@ +#include "Common/DummyVSTexCoord.hlsl" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState SourceSampler : register(s0); + +Texture2D SourceTex : register(t0); + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float4 srcColor = SourceTex.Sample(SourceSampler, input.TexCoord); + psout.Color = srcColor; + + return psout; +} +#endif diff --git a/package/Shaders/ISBlur.hlsl b/package/Shaders/ISBlur.hlsl new file mode 100644 index 000000000..9c665aca2 --- /dev/null +++ b/package/Shaders/ISBlur.hlsl @@ -0,0 +1,63 @@ +#include "Common/Color.hlsli" +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState ImageSampler : register(s0); +SamplerState AvgLumSampler : register(s1); + +Texture2D ImageTex : register(t0); +Texture2D AvgLumTex : register(t1); + +cbuffer PerGeometry : register(b2) +{ + float4 BlurBrightPass : packoffset(c0); + float4 BlurScale : packoffset(c1); + float BlurRadius : packoffset(c2); + float4 BlurOffsets[16] : packoffset(c3); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float4 color = 0.0.xxxx; + + float blurRadius = BLUR_RADIUS; + float2 blurScale = BlurScale.zw; +# if BLUR_RADIUS == 0 + blurRadius = BlurRadius; +# endif +# if BLUR_RADIUS == 0 || defined(BLUR_NON_HDR) + blurScale = 1.0.xx; +# endif + + for (int blurIndex = 0; blurIndex < blurRadius; ++blurIndex) { + float2 screenPosition = BlurOffsets[blurIndex].xy + input.TexCoord.xy; + if (BlurScale.x < 0.5) { + screenPosition = GetDynamicResolutionAdjustedScreenPosition(screenPosition); + } + float4 imageColor = ImageTex.Sample(ImageSampler, screenPosition) * float4(blurScale.yyy, 1); +# if defined(BLUR_BRIGHT_PASS) + imageColor = BlurBrightPass.y * max(0.0.xxxx, -BlurBrightPass.x + imageColor); +# endif + color += imageColor * BlurOffsets[blurIndex].z; + } + +# if defined(BLUR_BRIGHT_PASS) + float avgLum = RGBToLuminance(AvgLumTex.Sample(AvgLumSampler, input.TexCoord.xy).xyz); + color.w = avgLum; +# endif + + psout.Color = color * float4(blurScale.xxx, 1); + + return psout; +} +#endif diff --git a/package/Shaders/ISCompositeLensFlareVolumetricLighting.hlsl b/package/Shaders/ISCompositeLensFlareVolumetricLighting.hlsl new file mode 100644 index 000000000..740027b67 --- /dev/null +++ b/package/Shaders/ISCompositeLensFlareVolumetricLighting.hlsl @@ -0,0 +1,44 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float3 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState VLSourceSampler : register(s0); +SamplerState LFSourceSampler : register(s1); + +Texture2D VLSourceTex : register(t0); +Texture2D LFSourceTex : register(t1); + +cbuffer PerGeometry : register(b2) +{ + float4 VolumetricLightingColor : packoffset(c0); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float3 color = 0.0.xxx; + +# if defined(VOLUMETRIC_LIGHTING) + float2 screenPosition = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); + float volumetricLightingPower = VLSourceTex.Sample(VLSourceSampler, screenPosition).x; + color += VolumetricLightingColor.xyz * volumetricLightingPower; +# endif + +# if defined(LENS_FLARE) + float3 lensFlareColor = LFSourceTex.Sample(LFSourceSampler, input.TexCoord).xyz; + color += lensFlareColor; +# endif + + psout.Color = color; + + return psout; +} +#endif diff --git a/package/Shaders/ISCopy.hlsl b/package/Shaders/ISCopy.hlsl new file mode 100644 index 000000000..36616cb06 --- /dev/null +++ b/package/Shaders/ISCopy.hlsl @@ -0,0 +1,45 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState ImageSampler : register(s0); + +Texture2D ImageTex : register(t0); + +cbuffer PerGeometry : register(b2) +{ + float4 RotationMatrix : packoffset(c0); + float4 ColorSelect : packoffset(c1); + float4 ScaleBias : packoffset(c2); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + +# if !defined(DYNAMIC_FETCH_DISABLED) + float2 screenPosition = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); +# else + float2 screenPosition = input.TexCoord; +# endif + + float4 color = ImageTex.Sample(ImageSampler, screenPosition); + +# if defined(GRAY_SCALE) + color = float4(dot(color, ColorSelect).xxx, color.w); +# elif defined(TEXTURE_MASK) + color.w = 1 - color.x; +# endif + + psout.Color = color; + + return psout; +} +#endif diff --git a/package/Shaders/ISDebugSnow.hlsl b/package/Shaders/ISDebugSnow.hlsl new file mode 100644 index 000000000..a867bcebb --- /dev/null +++ b/package/Shaders/ISDebugSnow.hlsl @@ -0,0 +1,28 @@ +#include "Common/DummyVSTexCoord.hlsl" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState snowAlphaSpecSampler : register(s0); +SamplerState sceneSampler : register(s1); + +Texture2D snowAlphaSpecTex : register(t0); +Texture2D sceneTex : register(t1); + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float snowAlphaSpec = snowAlphaSpecTex.Sample(snowAlphaSpecSampler, input.TexCoord).y; + float4 sceneColor = sceneTex.Sample(sceneSampler, input.TexCoord); + + psout.Color = sceneColor + float4(snowAlphaSpec, 0, 0, 1); + + return psout; +} +#endif diff --git a/package/Shaders/ISDepthOfField.hlsl b/package/Shaders/ISDepthOfField.hlsl new file mode 100644 index 000000000..2d6c8bb19 --- /dev/null +++ b/package/Shaders/ISDepthOfField.hlsl @@ -0,0 +1,147 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState ImageSampler : register(s0); +SamplerState BlurredSampler : register(s1); +SamplerState DepthSampler : register(s2); +SamplerState AvgDepthSampler : register(s3); +SamplerState MaskSampler : register(s4); + +Texture2D ImageTex : register(t0); +Texture2D BlurredTex : register(t1); +Texture2D DepthTex : register(t2); +Texture2D AvgDepthTex : register(t3); +Texture2D MaskTex : register(t4); + +cbuffer PerGeometry : register(b2) +{ + float4 invScreenRes : packoffset(c0); // inverse render target width and height in xy + float4 params : packoffset(c1); // DOF near range in x, far range in y + float4 params2 : packoffset(c2); // DOF near blur in x, far blur in w + float4 params3 : packoffset(c3); // 1 / (far - near) in z, near / (far - near) in w + float4 params4 : packoffset(c4); + float4 params5 : packoffset(c5); + float4 params6 : packoffset(c6); + float4 params7 : packoffset(c7); +}; + +void CheckOffsetDepth(float2 center, float2 offset, inout float crossSection, + inout float totalDepth) +{ + float depth = DepthTex + .Sample(DepthSampler, GetDynamicResolutionAdjustedScreenPosition( + invScreenRes.xy * offset + center)) + .x; + + float crossSectionDelta = 0; + if (depth > 0.999998987) { + crossSectionDelta = (1. / 9.); + } + crossSection += crossSectionDelta; + totalDepth += depth; +} + +float GetFinalDepth(float depth, float near, float far) +{ + return (2 * near * far) / ((far + near) - (depth * 2 - 1) * (far - near)); +} + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float2 adjustedTexCoord = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); + + float3 imageColor = ImageTex.Sample(ImageSampler, adjustedTexCoord).xyz; + float3 blurColor = BlurredTex.Sample(BlurredSampler, adjustedTexCoord).xyz; + + float mask = 1; + float4 dofParams = params; + float4 dofParams2 = params2; +# if defined(MASKED) + mask = MaskTex.Sample(MaskSampler, adjustedTexCoord).x; + dofParams = lerp(params, params6, mask); + dofParams2 = lerp(params2, params7, mask); +# endif + + float2 dofBlurRange = float2(dofParams2.x, dofParams.x); + float focusDistance = dofParams.y; + +# if !defined(MASKED) + if (params3.z > 0) { + focusDistance = AvgDepthTex.Sample(AvgDepthSampler, 0).x; + float depthFactor = saturate(focusDistance * params3.z - params3.w); + dofBlurRange = lerp(float2(params2.x, params.x), float2(params2.w, params.y), depthFactor); + } +# endif + + float depthCC = + DepthTex.Sample(DepthSampler, GetDynamicResolutionAdjustedScreenPosition(input.TexCoord)).x; + + float crossSection = 0; + float avgDepth = depthCC; + bool isTooDeep = false; + if (dofParams2.w != 0 && depthCC > 0.999998987) { + crossSection = 1. / 9.; + float totalDepth = depthCC; + CheckOffsetDepth(input.TexCoord, float2(-3, -3), crossSection, totalDepth); + CheckOffsetDepth(input.TexCoord, float2(-3, 0), crossSection, totalDepth); + CheckOffsetDepth(input.TexCoord, float2(-3, 3), crossSection, totalDepth); + CheckOffsetDepth(input.TexCoord, float2(3, -3), crossSection, totalDepth); + CheckOffsetDepth(input.TexCoord, float2(3, 0), crossSection, totalDepth); + CheckOffsetDepth(input.TexCoord, float2(3, 3), crossSection, totalDepth); + CheckOffsetDepth(input.TexCoord, float2(0, -3), crossSection, totalDepth); + CheckOffsetDepth(input.TexCoord, float2(0, 3), crossSection, totalDepth); + + avgDepth = totalDepth / 9; + isTooDeep = avgDepth > 0.999998987; + } + + float blurFactor = 0; + float finalDepth = avgDepth; + if (!isTooDeep && avgDepth > 1e-5) { + float depth, near, far; + if (avgDepth <= 0.01) { + depth = 100 * avgDepth; + near = params3.x; + far = params3.y; + } else { + depth = 1.01 * avgDepth - 0.01; + near = dofParams.z; + far = dofParams.w; + } + finalDepth = GetFinalDepth(depth, near, far); + + float dofStrength = 0; +# if defined(DISTANT_BLUR) + dofStrength = (finalDepth - focusDistance) / dofBlurRange.y; +# elif defined(DOF) + if ((focusDistance > finalDepth || mask == 0) && dofParams2.y != 0) { + dofStrength = (focusDistance - finalDepth) / dofBlurRange.y; + } else if (finalDepth > focusDistance && dofParams2.z != 0) { + dofStrength = (finalDepth - focusDistance) / dofBlurRange.y; + } +# endif + + blurFactor = saturate(dofStrength) * (dofBlurRange.x * (1 - 0.5 * crossSection)); + } + + float3 finalColor = lerp(imageColor, blurColor, blurFactor); +# if defined(FOGGED) + float fogFactor = (params4.w * saturate((finalDepth - params5.y) / (params5.x - params5.y))) * mask; + finalColor = lerp(finalColor, params4.xyz, fogFactor); +# endif + + psout.Color = float4(finalColor, 1); + + return psout; +} +#endif diff --git a/package/Shaders/ISDoubleVision.hlsl b/package/Shaders/ISDoubleVision.hlsl new file mode 100644 index 000000000..a5685ffcb --- /dev/null +++ b/package/Shaders/ISDoubleVision.hlsl @@ -0,0 +1,52 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState Src0Sampler : register(s0); +SamplerState Src1Sampler : register(s1); + +Texture2D Src0Tex : register(t0); +Texture2D Src1Tex : register(t1); + +cbuffer PerGeometry : register(b2) +{ + float4 blurParams : packoffset(c0); + float4 doubleVisParams : packoffset(c1); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float2 texCoord0 = float2(max(0, -doubleVisParams.x + input.TexCoord.x), + max(-doubleVisParams.y + input.TexCoord.y, 1 - doubleVisParams.w)); + float2 adjustedTexCoord0 = GetDynamicResolutionAdjustedScreenPosition(texCoord0); + float3 src0Color0 = Src0Tex.Sample(Src0Sampler, adjustedTexCoord0).xyz; + + float2 texCoord1 = float2(min(doubleVisParams.z, doubleVisParams.x + input.TexCoord.x), + min(1, doubleVisParams.y + input.TexCoord.y)); + float2 adjustedTexCoord1 = GetDynamicResolutionAdjustedScreenPosition(texCoord1); + float3 src0Color1 = Src0Tex.Sample(Src0Sampler, adjustedTexCoord1).xyz; + + float2 adjustedTexCoord2 = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); + float3 src1Color = Src1Tex.Sample(Src1Sampler, adjustedTexCoord2).xyz; + + float src1Factor = min(1, + blurParams.z * + length(float2(2 * ((doubleVisParams.z / doubleVisParams.w) * (input.TexCoord.x - 0.5)), + 2 * (input.TexCoord.y - 0.5)))); + + float3 color = 0.5 * ((1 - src1Factor) * (src0Color0 + src0Color1)) + src1Factor * src1Color; + + psout.Color = float4(color, 1); + + return psout; +} +#endif diff --git a/package/Shaders/ISDownsample.hlsl b/package/Shaders/ISDownsample.hlsl new file mode 100644 index 000000000..8164cdc14 --- /dev/null +++ b/package/Shaders/ISDownsample.hlsl @@ -0,0 +1,67 @@ +#include "Common/Color.hlsli" +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState SourceSampler : register(s0); +SamplerState PreviousFrameSourceSampler : register(s1); +SamplerState MotionVectorsSampler : register(s2); + +Texture2D SourceTex : register(t0); +Texture2D PreviousFrameSourceTex : register(t1); +Texture2D MotionVectorsTex : register(t2); + +cbuffer PerGeometry : register(b2) +{ + float2 TexelSize : packoffset(c0); + float SamplesCount : packoffset(c0.z); + bool CompensateJittering : packoffset(c0.w); + float4 OffsetsAndWeights[16] : packoffset(c1); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float4 downsampledColor = 0; + float luminance = 0; + for (uint sampleIndex = 0; sampleIndex < asuint(SamplesCount); ++sampleIndex) { + float2 texCoord = OffsetsAndWeights[sampleIndex].xy * TexelSize.xy + input.TexCoord; +# if defined(IGNORE_BRIGHTEST) + texCoord = GetDynamicResolutionAdjustedScreenPosition(texCoord); +# endif + float4 sourceColor = SourceTex.Sample(SourceSampler, texCoord); +# if defined(IGNORE_BRIGHTEST) + downsampledColor += sourceColor; +# else + float sampleLuminance = RGBToLuminanceAlternative(sourceColor.xyz); + if (sampleLuminance > luminance) { + downsampledColor = sourceColor; + luminance = sampleLuminance; + } +# endif + } +# if defined(IGNORE_BRIGHTEST) + psout.Color = downsampledColor / asuint(SamplesCount); +# else + if (CompensateJittering) { + float2 adjustedTexCoord = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); + float2 motion = MotionVectorsTex.Sample(MotionVectorsSampler, adjustedTexCoord).xy; + float4 previousFrameColor = + PreviousFrameSourceTex.Sample(PreviousFrameSourceSampler, input.TexCoord + motion).xyzw; + psout.Color = 0.5 * (previousFrameColor + downsampledColor); + } else { + psout.Color = downsampledColor; + } +# endif + + return psout; +} +#endif diff --git a/package/Shaders/ISExp.hlsl b/package/Shaders/ISExp.hlsl new file mode 100644 index 000000000..0866d69e8 --- /dev/null +++ b/package/Shaders/ISExp.hlsl @@ -0,0 +1,29 @@ +#include "Common/DummyVSTexCoord.hlsl" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState OriginalSampler : register(s0); + +Texture2D OriginalTex : register(t0); + +cbuffer PerGeometry : register(b2) +{ + float Params : packoffset(c0); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float srcValue = OriginalTex.Sample(OriginalSampler, input.TexCoord).x; + psout.Color = exp2(1.44269502 * Params * srcValue); + + return psout; +} +#endif diff --git a/package/Shaders/ISHDR.hlsl b/package/Shaders/ISHDR.hlsl new file mode 100644 index 000000000..756e08374 --- /dev/null +++ b/package/Shaders/ISHDR.hlsl @@ -0,0 +1,123 @@ +#include "Common/Color.hlsli" +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState ImageSampler : register(s0); +# if defined(DOWNSAMPLE) +SamplerState AdaptSampler : register(s1); +# elif defined(TONEMAP) +SamplerState BlendSampler : register(s1); +# endif +SamplerState AvgSampler : register(s2); + +Texture2D ImageTex : register(t0); +# if defined(DOWNSAMPLE) +Texture2D AdaptTex : register(t1); +# elif defined(TONEMAP) +Texture2D BlendTex : register(t1); +# endif +Texture2D AvgTex : register(t2); + +cbuffer PerGeometry : register(b2) +{ + float4 Flags : packoffset(c0); + float4 TimingData : packoffset(c1); + float4 Param : packoffset(c2); + float4 Cinematic : packoffset(c3); + float4 Tint : packoffset(c4); + float4 Fade : packoffset(c5); + float4 BlurScale : packoffset(c6); + float4 BlurOffsets[16] : packoffset(c7); +}; + +float GetTonemapFactorReinhard(float luminance) +{ + return (luminance * (luminance * Param.y + 1)) / (luminance + 1); +} + +float GetTonemapFactorHejlBurgessDawson(float luminance) +{ + float tmp = max(0, luminance - 0.004); + return Param.y * + pow(((tmp * 6.2 + 0.5) * tmp) / (tmp * (tmp * 6.2 + 1.7) + 0.06), GammaCorrectionValue); +} + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + +# if defined(DOWNSAMPLE) + float3 downsampledColor = 0; + for (int sampleIndex = 0; sampleIndex < SAMPLES_COUNT; ++sampleIndex) { + float2 texCoord = BlurOffsets[sampleIndex].xy * BlurScale.xy + input.TexCoord; + if (Flags.x > 0.5) { + texCoord = GetDynamicResolutionAdjustedScreenPosition(texCoord); + } + float3 imageColor = ImageTex.Sample(ImageSampler, texCoord).xyz; +# if defined(LUM) + imageColor = imageColor.x; +# elif defined(RGB2LUM) + imageColor = RGBToLuminance(imageColor); +# endif + downsampledColor += imageColor * BlurOffsets[sampleIndex].z; + } +# if defined(LIGHT_ADAPT) + float2 adaptValue = AdaptTex.Sample(AdaptSampler, input.TexCoord).xy; + if (isnan(downsampledColor.x) || isnan(downsampledColor.y) || isnan(downsampledColor.z)) { + downsampledColor.xy = adaptValue; + } else { + float2 adaptDelta = downsampledColor.xy - adaptValue; + downsampledColor.xy = + sign(adaptDelta) * clamp(abs(Param.wz * adaptDelta), 0.00390625, abs(adaptDelta)) + + adaptValue; + } +# endif + psout.Color = float4(downsampledColor, BlurScale.z); + +# elif defined(TONEMAP) + float2 adjustedTexCoord = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); + float3 blendColor = BlendTex.Sample(BlendSampler, adjustedTexCoord).xyz; + float3 imageColor = 0; + if (Flags.x > 0.5) { + imageColor = ImageTex.Sample(ImageSampler, adjustedTexCoord).xyz; + } else { + imageColor = ImageTex.Sample(ImageSampler, input.TexCoord).xyz; + } + float2 avgValue = AvgTex.Sample(AvgSampler, input.TexCoord).xy; + + float luminance = max(1e-5, RGBToLuminance(blendColor)); + float exposureAdjustedLuminance = (avgValue.y / avgValue.x) * luminance; + float blendFactor; + if (Param.z > 0.5) { + blendFactor = GetTonemapFactorHejlBurgessDawson(exposureAdjustedLuminance); + } else { + blendFactor = GetTonemapFactorReinhard(exposureAdjustedLuminance); + } + + float3 blendedColor = + blendColor * (blendFactor / luminance) + saturate(Param.x - blendFactor) * imageColor; + float blendedLuminance = RGBToLuminance(blendedColor); + + float4 linearColor = lerp(avgValue.x, + Cinematic.w * lerp(lerp(blendedLuminance, float4(blendedColor, 1), Cinematic.x), + blendedLuminance * Tint, Tint.w), + Cinematic.z); + float4 srgbColor = float4(ToSRGBColor(saturate(linearColor.xyz)), linearColor.w); +# if defined(FADE) + srgbColor = lerp(srgbColor, Fade, Fade.w); +# endif + psout.Color = srgbColor; + +# endif + + return psout; +} +#endif diff --git a/package/Shaders/ISIBLensFlare.hlsl b/package/Shaders/ISIBLensFlare.hlsl new file mode 100644 index 000000000..ee242c692 --- /dev/null +++ b/package/Shaders/ISIBLensFlare.hlsl @@ -0,0 +1,68 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState DownScaledBlurredHDRSampler : register(s0); +SamplerState RampsSampler : register(s1); +SamplerState MasksSampler : register(s2); + +Texture2D DownScaledBlurredHDRTex : register(t0); +Texture2D RampsTex : register(t1); +Texture2D MasksTex : register(t2); + +cbuffer PerGeometry : register(b2) +{ + float lensCount : packoffset(c0.x); + float flareDispersal : packoffset(c0.y); + float lightsRangeDownshift : packoffset(c0.z); + float invLightsRangeDownshift : packoffset(c0.w); + float lateralRepeat : packoffset(c1.x); + float channelsDistortionRed : packoffset(c1.y); + float channelsDistortionGreen : packoffset(c1.z); + float channelsDistortionBlue : packoffset(c1.w); + float texelOffsetX : packoffset(c2.x); + float texelOffsetY : packoffset(c2.y); + float haloFetch : packoffset(c2.z); + float haloWidthPow : packoffset(c2.w); + float dynamicSource : packoffset(c3.x); + float globalIntensity : packoffset(c3.y); +}; + +float4 GetSampleColor(float2 texCoord) +{ + float4 color = DownScaledBlurredHDRTex.Sample(DownScaledBlurredHDRSampler, texCoord); + if (saturate(color.x - lightsRangeDownshift) + saturate(color.y - lightsRangeDownshift) + + saturate(color.z - lightsRangeDownshift) <= + 0) { + return 0; + } + return saturate(color); +} + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float4 lensColor = 0; + for (int sampleIndex = -asint(lateralRepeat); sampleIndex <= asint(lateralRepeat); ++sampleIndex) { + float4 sampleColor; + if (dynamicSource > 0.5) { + sampleColor = GetSampleColor(GetDynamicResolutionAdjustedScreenPosition( + input.TexCoord + float2(texelOffsetX * sampleIndex, 0))); + } else { + sampleColor = GetSampleColor(input.TexCoord + float2(texelOffsetX * sampleIndex, 0)); + } + lensColor += sampleColor; + } + psout.Color = globalIntensity * lensColor; + + return psout; +} +#endif diff --git a/package/Shaders/ISLightingComposite.hlsl b/package/Shaders/ISLightingComposite.hlsl new file mode 100644 index 000000000..7a180d183 --- /dev/null +++ b/package/Shaders/ISLightingComposite.hlsl @@ -0,0 +1,73 @@ +#include "Common/DummyVSTexCoord.hlsl" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState AlbedoSampler : register(s0); +SamplerState DiffuseSampler : register(s1); +SamplerState SpecularSampler : register(s2); +SamplerState SAOSampler : register(s3); +SamplerState FogSampler : register(s4); +SamplerState DirDiffuseSampler : register(s5); +SamplerState DirSpecularSampler : register(s6); +SamplerState ShadowMaskSampler : register(s7); + +Texture2D AlbedoTex : register(t0); +Texture2D DiffuseTex : register(t1); +Texture2D SpecularTex : register(t2); +Texture2D SAOTex : register(t3); +Texture2D FogTex : register(t4); +Texture2D DirDiffuseTex : register(t5); +Texture2D DirSpecularTex : register(t6); +Texture2D ShadowMaskTex : register(t7); + +cbuffer PerGeometry : register(b2) +{ + float4 FogParam : packoffset(c0); + float4 FogNearColor : packoffset(c1); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float4 diffuse = DiffuseTex.Sample(DiffuseSampler, input.TexCoord); + float4 specular = SpecularTex.Sample(SpecularSampler, input.TexCoord); + float4 albedo = AlbedoTex.Sample(AlbedoSampler, input.TexCoord); + +# if !defined(NO_DIRECTIONAL_LIGHT) + float4 dirDiffuse = DirDiffuseTex.Sample(DirDiffuseSampler, input.TexCoord); + float4 dirSpecular = DirSpecularTex.Sample(DirSpecularSampler, input.TexCoord); +# else + float4 dirDiffuse = 0; + float4 dirSpecular = 0; +# endif + +# if !defined(MENU) + float shadowMask = ShadowMaskTex.Sample(ShadowMaskSampler, input.TexCoord).x; + float sao = SAOTex.Sample(SAOSampler, input.TexCoord).x; +# else + float shadowMask = 1; + float sao = 1; +# endif + + float4 preFog = (diffuse * sao + shadowMask * dirDiffuse) * albedo + + (specular * sao + dirSpecular * shadowMask); + + float4 fog = FogTex.Sample(FogSampler, input.TexCoord); + + if (fog.x + fog.y + fog.z + fog.w != 0) { + psout.Color = + float4(saturate(FogNearColor.w * lerp(preFog.xyz, fog.xyz, fog.w)), saturate(preFog.w)); + } else { + psout.Color = preFog; + } + + return psout; +} +#endif diff --git a/package/Shaders/ISLocalMap.hlsl b/package/Shaders/ISLocalMap.hlsl new file mode 100644 index 000000000..3f7879081 --- /dev/null +++ b/package/Shaders/ISLocalMap.hlsl @@ -0,0 +1,61 @@ +#include "Common/Color.hlsli" +#include "Common/DummyVSTexCoord.hlsl" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState ImageSampler : register(s0); + +Texture2D ImageTex : register(t0); + +cbuffer PerGeometry : register(b2) +{ + float4 TexelSize : packoffset(c0); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float3 weight = float3(0.5, 0.25, 1); + float3 colorLR = 0; + float3 colorBT = 0; + [unroll] for (int j = -1; j <= 1; ++j) + { + [unroll] for (int i = -1; i <= 1; ++i) + { + if (i == 0 && j == 0) { + continue; + } + + float3 currentColor = + ImageTex.Sample(ImageSampler, input.TexCoord + float2(i * TexelSize.x, j * TexelSize.y)) + .xyz; + + float centerMul = 1; + if (i == 0 || j == 0) { + centerMul = 2; + } + + colorLR += -i * (centerMul * weight) * currentColor; + colorBT += -j * (centerMul * weight) * currentColor; + } + } + + float4 colorCC = ImageTex.Sample(ImageSampler, input.TexCoord); + float luminance = RGBToLuminanceAlternative(colorCC.xyz); + + float alpha = (dot(4 * (pow(colorLR, 2) + pow(colorBT, 2)), 1.75) + luminance) * (1 - colorCC.w); + float2 edgeFadeFactor = 1 - pow(2 * abs(input.TexCoord - 0.5), 5); + + psout.Color.xyz = 1.04 * luminance; + psout.Color.w = alpha * edgeFadeFactor.x * edgeFadeFactor.y; + + return psout; +} +#endif diff --git a/package/Shaders/ISMap.hlsl b/package/Shaders/ISMap.hlsl new file mode 100644 index 000000000..631f056fc --- /dev/null +++ b/package/Shaders/ISMap.hlsl @@ -0,0 +1,55 @@ +#include "Common/DummyVSTexCoord.hlsl" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState Src0Sampler : register(s0); + +Texture2D Src0Tex : register(t0); + +cbuffer PerGeometry : register(b2) +{ + float4 CameraPos : packoffset(c0); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float4 colorLR = 0; + float4 colorBT = 0; + [unroll] for (int j = -1; j <= 1; ++j) + { + [unroll] for (int i = -1; i <= 1; ++i) + { + if (i == 0 && j == 0) { + continue; + } + + float4 currentColor = + Src0Tex + .Sample(Src0Sampler, input.TexCoord + float2(i * CameraPos.x, j * CameraPos.y)); + + float centerMul = 1; + if (i == 0 || j == 0) { + centerMul = 2; + } + + colorLR += -i * centerMul * currentColor; + colorBT += -j * centerMul * currentColor; + } + } + float4 convolved = pow(colorLR, 2) + pow(colorBT, 2); + + float3 mapColor = min(0.275, dot(float3(0.2, 0.2, 0.15), convolved.xyz) + min(0.1, 10 * convolved.w).xxx); + psout.Color.xyz = mapColor; + psout.Color.w = 2 * dot(1, mapColor.zzz); + + return psout; +} +#endif diff --git a/package/Shaders/ISNoise.hlsl b/package/Shaders/ISNoise.hlsl new file mode 100644 index 000000000..74db0528e --- /dev/null +++ b/package/Shaders/ISNoise.hlsl @@ -0,0 +1,103 @@ +struct VS_INPUT +{ + float4 Position : POSITION0; + float2 TexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 Position : POSITION0; + float2 TexCoord : TEXCOORD0; +}; + +#ifdef VSHADER +cbuffer PerGeometry : register(b2) +{ + float4 GeometryOffset : packoffset(c0); +}; + +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT vsout; + + vsout.Position.xy = input.Position.xy - GeometryOffset.xy * float2(2, -2); + vsout.Position.zw = input.Position.zw; + vsout.TexCoord = input.TexCoord.xy; + + return vsout; +} +#endif + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState NoiseMapSampler : register(s0); + +Texture2D NoiseMapTex : register(t0); + +cbuffer PerGeometry : register(b2) +{ + float2 fTexScroll0 : packoffset(c0.x); + float2 fTexScroll1 : packoffset(c0.z); + float2 fTexScroll2 : packoffset(c1.x); + float2 fNoiseScale : packoffset(c1.z); + float3 fTexScale : packoffset(c2); + float3 fAmplitude : packoffset(c3); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + +# if defined(NORMALMAP) + + float offset = 0.00390625; + float valueRL = 0; + float valueTB = 0; + [unroll] for (int i = -1; i <= 1; ++i) + { + [unroll] for (int j = -1; j <= 1; ++j) + { + if (i == 0 && j == 0) { + continue; + } + + float currentValue = abs( + NoiseMapTex.Sample(NoiseMapSampler, input.TexCoord + float2(i * offset, j * offset)) + .x); + + float centerMul = 1; + if (i == 0 || j == 0) { + centerMul = 2; + } + + valueRL += i * (fNoiseScale.x * centerMul) * currentValue; + valueTB += j * (fNoiseScale.x * centerMul) * currentValue; + } + } + + psout.Color.xyz = normalize(float3(-valueRL, valueTB, 1)) * 0.5 + 0.5; + psout.Color.w = abs(NoiseMapTex.Sample(NoiseMapSampler, input.TexCoord).y); + +# elif defined(SCROLL_AND_BLEND) + float noise1 = + fAmplitude.x * + (NoiseMapTex.Sample(NoiseMapSampler, input.TexCoord * fTexScale.x + fTexScroll0).z * 2 - 1); + float noise2 = + fAmplitude.y * + (NoiseMapTex.Sample(NoiseMapSampler, input.TexCoord * fTexScale.y + fTexScroll1).y * 2 - 1); + float noise3 = + fAmplitude.z * + (NoiseMapTex.Sample(NoiseMapSampler, input.TexCoord * fTexScale.z + fTexScroll2).x * 2 - 1); + + psout.Color = float4(saturate((noise1 + noise2 + noise3) * 0.5 + 0.5), 0, 0, 1); +# endif + + return psout; +} +#endif diff --git a/package/Shaders/ISRadialBlur.hlsl b/package/Shaders/ISRadialBlur.hlsl new file mode 100644 index 000000000..a2931e17b --- /dev/null +++ b/package/Shaders/ISRadialBlur.hlsl @@ -0,0 +1,55 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState ImageSampler : register(s0); + +Texture2D ImageTex : register(t0); + +cbuffer PerGeometry : register(b2) +{ + float4 Params : packoffset(c0); + float4 Center : packoffset(c1); +}; + +float GetCircleParam(float centerDistance, float param1, float param2) +{ + float circleDistance = max(0, centerDistance - param1); + float result = 0; + if (circleDistance > 0) { + result = Params.x * (1 - 1 / (param2 * circleDistance + 1)); + } + return result; +} + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float2 offset = Center.xy - input.TexCoord; + float centerDistance = length(offset); + float2 sampleDelta = + 0.5 * (normalize(offset) * max(0, GetCircleParam(centerDistance, Params.z, Params.y) - + GetCircleParam(centerDistance, Center.z, Params.w))); + + float4 color = 0; + for (float sampleIndex = -SAMPLES_COUNT; sampleIndex <= SAMPLES_COUNT; ++sampleIndex) { + float2 texCoord = input.TexCoord + sampleDelta * sampleIndex; + float2 adjustedTexCoord = GetDynamicResolutionAdjustedScreenPosition(texCoord); + float4 currentColor = ImageTex.SampleLevel(ImageSampler, adjustedTexCoord, 0); + color += currentColor; + } + color *= (1. / (2. * SAMPLES_COUNT + 1.)); + + psout.Color = color; + + return psout; +} +#endif diff --git a/package/Shaders/ISRefraction.hlsl b/package/Shaders/ISRefraction.hlsl new file mode 100644 index 000000000..8fc2b5d1c --- /dev/null +++ b/package/Shaders/ISRefraction.hlsl @@ -0,0 +1,55 @@ +#include "Common/Color.hlsli" +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState Src0Sampler : register(s0); +SamplerState Src1Sampler : register(s1); + +Texture2D Src0Tex : register(t0); +Texture2D Src1Tex : register(t1); + +cbuffer PerGeometry : register(b2) +{ + float4 Tint : packoffset(c0); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float2 adjustedTexCoord = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); + + float4 src1 = Src1Tex.Sample(Src1Sampler, adjustedTexCoord); + float4 src00 = Src0Tex.Sample(Src0Sampler, adjustedTexCoord); + + float2 texCoord10 = input.TexCoord + float2(1, -1) * (2 * (0.05 * src1.z) * (src1.xy - 0.5)); + float2 texCoord11 = texCoord10 > 0.85 ? lerp(texCoord10, 0.85, 0.78) : texCoord10; + texCoord11 = texCoord10 < 0.15 ? lerp(texCoord10, 0.15, 0.78) : texCoord11; + + float2 texCoord1 = lerp(texCoord10, texCoord11, src1.z); + float2 adjustedTexCoord1 = GetDynamicResolutionAdjustedScreenPosition(texCoord1); + + float unk1 = Src1Tex.Sample(Src1Sampler, adjustedTexCoord1).w; + float4 src01 = Src0Tex.Sample(Src0Sampler, adjustedTexCoord1); + float4 src0 = unk1 != 0 ? src01 : src00; + + if (src1.w > 0.8 && src1.w < 1) { + psout.Color.xyz = + (1 - Tint.w) * src0.xyz + Tint.xyz * (Tint.w * RGBToLuminance2(src01.xyz)); + } else { + psout.Color.xyz = src0.xyz; + } + + psout.Color.w = src0.w; + + return psout; +} +#endif diff --git a/package/Shaders/ISSAOBlur.hlsl b/package/Shaders/ISSAOBlur.hlsl new file mode 100644 index 000000000..5a1331ea1 --- /dev/null +++ b/package/Shaders/ISSAOBlur.hlsl @@ -0,0 +1,98 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState sourceSampler : register(s0); + +Texture2D sourceTex : register(t0); + +cbuffer PerGeometry : register(b2) +{ + float4 g_ScreenInfos : packoffset(c0); +}; + +float GetBlurredComponent(float3 color) +{ +# if defined(AXIS_H) + return color.x; +# elif defined(AXIS_V) + return color.y; +# endif +} + +float2 GetNonBlurredComponents(float3 color) +{ +# if defined(AXIS_H) + return color.yz; +# elif defined(AXIS_V) + return color.xz; +# endif +} + +float3 SetBlurredComponent(float3 color, float blurredComponent) +{ +# if defined(AXIS_H) + return float3(blurredComponent, color.yz); +# elif defined(AXIS_V) + return float3(color.x, blurredComponent, color.z); +# endif +} + +float GetBlurFactor(float3 color) +{ + return dot(GetNonBlurredComponents(color), float2(0.996108949, 0.00389105058)); +} + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + const uint sampleCount = 7; +# if defined(AXIS_H) + const float2 texCoordOffsets[] = { + float2(0, 0), float2(-6, -0), float2(-4, -0), float2(-2, -0), float2(2, 0), float2(4, 0), float2(6, 0) + }; +# elif defined(AXIS_V) + const float2 texCoordOffsets[] = { + float2(0, 0), float2(-0, -6), float2(-0, -4), float2(-0, -2), float2(0, 2), float2(0, 4), float2(0, 6) + }; +# endif + float3 offsetColors[sampleCount]; + [unroll] for (uint sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex) + { + float2 offsetTexCoord = g_ScreenInfos.zw * texCoordOffsets[sampleIndex] + input.TexCoord; + float2 adjustedOffsetTexCoord = GetDynamicResolutionAdjustedScreenPosition(offsetTexCoord); + offsetColors[sampleIndex] = sourceTex.Sample(sourceSampler, adjustedOffsetTexCoord).xyz; + } + + float3 centralColor = offsetColors[0]; + float centralBlurFactor = GetBlurFactor(centralColor); + if (centralBlurFactor == 1.0) { + psout.Color = float4(SetBlurredComponent(centralColor, 0), 0); + return psout; + } + + float weight = 0; + float weightedComponent = 0; + const float blurParameters[] = { 0.153170004, 0.392902017, 0.422649026, 0.444893003, 0.444893003, 0.422649026, 0.392902017 }; + [unroll] for (uint offsetIndex = 0; offsetIndex < sampleCount; ++offsetIndex) + { + float3 offsetColor = offsetColors[offsetIndex]; + float blurFactor = GetBlurFactor(offsetColor); + float offsetWeight = blurParameters[offsetIndex] * max(0, 1 - 2000 * abs(blurFactor - centralBlurFactor)); + weightedComponent += offsetWeight * GetBlurredComponent(offsetColor); + weight += offsetWeight; + } + + psout.Color = float4(SetBlurredComponent(offsetColors[0], weightedComponent / (1e-4 + weight)), 0); + + return psout; +} +#endif diff --git a/package/Shaders/ISSAOCameraZ.hlsl b/package/Shaders/ISSAOCameraZ.hlsl new file mode 100644 index 000000000..d7b561f59 --- /dev/null +++ b/package/Shaders/ISSAOCameraZ.hlsl @@ -0,0 +1,33 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float ClippedDepth : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState DepthSampler : register(s0); + +Texture2D DepthTex : register(t0); + +cbuffer PerGeometry : register(b2) +{ + float4 g_ClipInfos : packoffset(c0); + float4 g_ScreenInfos : packoffset(c1); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float2 screenPosition = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); + float4 depth = DepthTex.Sample(DepthSampler, screenPosition).x; + + psout.ClippedDepth = clamp(g_ClipInfos.x / (g_ClipInfos.y * depth + g_ClipInfos.z), 0, g_ClipInfos.w); + + return psout; +} +#endif diff --git a/package/Shaders/ISSAOComposite.hlsl b/package/Shaders/ISSAOComposite.hlsl new file mode 100644 index 000000000..861fed309 --- /dev/null +++ b/package/Shaders/ISSAOComposite.hlsl @@ -0,0 +1,205 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState sourceSampler : register(s0); +SamplerState SAOSampler : register(s1); +SamplerState depthSampler : register(s2); +SamplerState NormalsSSRMaskSampler : register(s3); +SamplerState snowSpecAlphaSampler : register(s4); +SamplerState shadowMaskSampler : register(s5); +SamplerState SSRSourceSampler : register(s6); + +Texture2D sourceTex : register(t0); +Texture2D SAOTex : register(t1); +Texture2D depthTex : register(t2); +Texture2D NormalsSSRMaskTex : register(t3); +Texture2D snowSpecAlphaTex : register(t4); +Texture2D shadowMaskTex : register(t5); +Texture2D SSRSourceTex : register(t6); + +cbuffer PerGeometry : register(b2) +{ + float4 FogParam : packoffset(c0); + float4 FogNearColor : packoffset(c1); + float4 FogFarColor : packoffset(c2); + float4 CameraNearFar : packoffset(c3); + float4 LightDirection : packoffset(c4); + float4 EyePosition : packoffset(c5); // bEnableImprovedSnow in w + float4 SparklesParameters1 : packoffset(c6); // fSparklesIntensity in x, fSpecularSparklesIntensity in y, fSparklesSpecularPower in z, fSparklesDensity or fSparklesDensity - 0.5 if bUsePrecomputedNoise in w + float4 SparklesParameters2 : packoffset(c7); // fSparklesSize or fSparklesSize + 1 if bUsePrecomputedNoise in x, fNonSpecularSparklesIntensity in y, bToggleSparkles in z, bSparklesOnly in w + float4 SparklesParameters3 : packoffset(c8); // bDeactivateAOOnSnow in x, fSparklesMaxDistance in y, bUsePrecomputedNoise in z + float4 SparklesParameters4 : packoffset(c9); // fShadowSparkleIntensity in x, fSnowSparklesColorR in y, fSnowSparklesColorG in z, fSnowSparklesColorB in w + float4 SSRParams : packoffset(c10); +}; + +float3 FastMod(float3 x, float divisor) +{ + return x - floor(x / divisor) * divisor; +} + +float4 FastMod(float4 x, float divisor) +{ + return x - floor(x / divisor) * divisor; +} + +float4 Permute(float4 x) +{ + return FastMod((x * 34.0 + 1.0) * x, 289); +} + +float4 TaylorInvSqrt(float4 r) +{ + return 1.79284291400159 - 0.85373472095314 * r; +} + +float SimplexNoise(float3 v) +{ + // First corner + float3 i = floor(v + dot(v, 1.0 / 3.0)); + float3 x0 = v - i + dot(i, 1.0 / 6.0); + + // Other corners + float3 g = step(x0.yzx, x0.xyz); + float3 l = 1.0 - g; + float3 i1 = min(g.xyz, l.zxy); + float3 i2 = max(g.xyz, l.zxy); + + float3 x1 = x0 - i1 + 1.0 / 6.0; + float3 x2 = x0 - i2 + 1.0 / 3.0; + float3 x3 = x0 - 0.5; + + // Permutations + i = FastMod(i, 289); + float4 p = Permute(Permute(Permute( + i.z + float4(0.0, i1.z, i2.z, 1.0)) + + i.y + float4(0.0, i1.y, i2.y, 1.0)) + + i.x + float4(0.0, i1.x, i2.x, 1.0)); + + // Gradients: 7x7 points over a square, mapped onto an octahedron. + // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) + const float n = 7; + + float4 j = FastMod(p, n * n); + + float4 x_ = floor(j / n); + float4 y_ = FastMod(j, n); + + float4 x = x_ * (2 / n) + (1 / (2 * n) - 1); + float4 y = y_ * (2 / n) + (1 / (2 * n) - 1); + float4 h = 1.0 - abs(x) - abs(y); + + float4 b0 = float4(x.xy, y.xy); + float4 b1 = float4(x.zw, y.zw); + + float4 s0 = floor(b0) * 2.0 + 1.0; + float4 s1 = floor(b1) * 2.0 + 1.0; + float4 sh = -step(h, 0); + + float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; + float4 a1 = b1.xzyw + s1.xzyw * sh.zzww; + + float3 p0 = float3(a0.xy, h.x); + float3 p1 = float3(a0.zw, h.y); + float3 p2 = float3(a1.xy, h.z); + float3 p3 = float3(a1.zw, h.w); + + // Normalise gradients + float4 norm = TaylorInvSqrt(float4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + + // Mix final noise value + float4 m = max(0.6 - float4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0); + return 42.0 * dot(pow(m, 4), float4(dot(p0, x0), dot(p1, x1), + dot(p2, x2), dot(p3, x3))); +} + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float2 screenPosition = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); + float ao = SAOTex.Sample(SAOSampler, screenPosition).x; + float4 sourceColor = sourceTex.SampleLevel(sourceSampler, screenPosition, 0); + + float4 composedColor = sourceColor; + + if (0.5 < SSRParams.z) { + float2 ssrMask = NormalsSSRMaskTex.SampleLevel(NormalsSSRMaskSampler, screenPosition, 0).zw; + float4 ssr = SSRSourceTex.Sample(SSRSourceSampler, screenPosition); + + float3 ssrInput = 0; + if (1e-5 >= ssrMask.x && 1e-5 < ssrMask.y) { + ssrInput = min(SSRParams.y * sourceColor.xyz, max(0, SSRParams.x * (ssr.xyz * ssr.w))); + } + composedColor.xyz += ssrInput; + } + + float snowMask = 0; + if (EyePosition.w != 0) { + float2 specSnow = snowSpecAlphaTex.Sample(snowSpecAlphaSampler, screenPosition).xy; + composedColor.xyz += specSnow.x * specSnow.y; + snowMask = specSnow.y; + } + +# if defined(APPLY_SAO) + if (EyePosition.w != 0 && 1e-5 < snowMask) { + ao = min(1, SparklesParameters3.x + ao); + } + composedColor.xyz *= ao; +# endif + + float depth = depthTex.SampleLevel(depthSampler, screenPosition, 0).x; + +# if defined(APPLY_FOG) + float fogDistanceFactor = (2 * CameraNearFar.x * CameraNearFar.y) / ((CameraNearFar.y + CameraNearFar.x) - (2 * (1.01 * depth - 0.01) - 1) * (CameraNearFar.y - CameraNearFar.x)); + float fogFactor = min(FogParam.w, pow(saturate(fogDistanceFactor * FogParam.y - FogParam.x), FogParam.z)); + float3 fogColor = lerp(FogNearColor.xyz, FogFarColor.xyz, fogFactor); + if (depth < 1) { + composedColor.xyz = FogNearColor.w * lerp(composedColor.xyz, fogColor, fogFactor); + } +# endif + + float sparklesInput = 0; + if (EyePosition.w != 0 && snowMask != 0 && 1e-5 < SparklesParameters2.z) { + float shadowMask = shadowMaskTex.SampleLevel(shadowMaskSampler, screenPosition, 0).x; + + float4 vsPosition = float4(2 * input.TexCoord.x - 1, 1 - 2 * input.TexCoord.y, depth, 1); + + float4 csPosition = mul(CameraViewProjInverse[0], vsPosition); + csPosition.xyz /= csPosition.w; + csPosition.xyz += CameraPosAdjust[0].xyz; + + float3 noiseSeed = 0.07 * (SparklesParameters2.x * csPosition.xyz); + float noiseValue = 0.5 * (SimplexNoise(noiseSeed) + 1); + float sparklesSpecular = pow(abs(noiseValue * saturate(rcp(noiseValue))), SparklesParameters1.z); + + float sparklesAttenuation = 1 - smoothstep(0, 1, length(csPosition.xyz - EyePosition.xyz) / SparklesParameters3.y); + + float sparklesShadowing = lerp(shadowMask, 1, SparklesParameters4.x); + + sparklesInput = SparklesParameters1.x * sparklesSpecular * step(SparklesParameters1.w, sparklesSpecular); + sparklesInput *= sparklesShadowing; + sparklesInput *= sparklesAttenuation; + } + sparklesInput *= snowMask; + float4 sparklesColor = float4(SparklesParameters4.yzw * sparklesInput, sparklesInput); + + composedColor *= 1 - SparklesParameters2.w; + composedColor += sparklesColor; + + psout.Color = saturate(composedColor); + + return psout; +} +#endif diff --git a/package/Shaders/ISSAOMinify.hlsl b/package/Shaders/ISSAOMinify.hlsl new file mode 100644 index 000000000..3e4cf8431 --- /dev/null +++ b/package/Shaders/ISSAOMinify.hlsl @@ -0,0 +1,64 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState sourceSampler : register(s0); + +Texture2D sourceTex : register(t0); + +cbuffer PerGeometry : register(b2) +{ + float4 g_RenderTargetResolution : packoffset(c0); + float4 g_ContrastParams : packoffset(c1); + float g_UseDynamicSampling : packoffset(c2); +}; + +float2 GetMinifiedTexCoord(float2 texCoord) +{ + return ((float2)(((int2)(g_RenderTargetResolution.yx * texCoord.yx) & 1) ^ 1) * 2 - 1) * + g_RenderTargetResolution.zw + + texCoord; +} + +static const float ContrastValues[] = { 0.300000, 0.400000, + 0.500000, 0.400000, 0.300000, 0.400000, + 2.000000, 2.500000, 2.000000, 0.400000, + 0.500000, 2.500000, 3.500000, 2.500000, + 0.500000, 0.400000, 2.000000, 2.500000, + 2.000000, 0.400000, 0.300000, 0.400000, + 0.500000, 0.400000, 0.300000 }; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float2 finalTexCoord; + if (asuint(g_UseDynamicSampling) > 0) { + float2 drAdjustedTexCoord = DynamicResolutionParams1.xy * input.TexCoord; + float2 minifiedTexCoord = GetMinifiedTexCoord(drAdjustedTexCoord); + finalTexCoord = clamp(minifiedTexCoord, 0, + DynamicResolutionParams1.xy - float2(CameraPreviousPosAdjust[0].w, 0)); + } else { + finalTexCoord = GetMinifiedTexCoord(input.TexCoord); + } + + float4 color = sourceTex.Sample(sourceSampler, finalTexCoord); + +# if defined(CONTRAST) + int contrastIndex = (int)(5 * input.TexCoord.x) + (int)(5 * input.TexCoord.y) * 5; + float contrastFactor = ContrastValues[contrastIndex] * g_ContrastParams.x; + color *= contrastFactor; +# endif + + psout.Color = color; + + return psout; +} +#endif diff --git a/package/Shaders/ISSILComposite.hlsl b/package/Shaders/ISSILComposite.hlsl new file mode 100644 index 000000000..bcb24c64d --- /dev/null +++ b/package/Shaders/ISSILComposite.hlsl @@ -0,0 +1,29 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState sourceSampler : register(s0); +SamplerState IndLightingSampler : register(s1); + +Texture2D sourceTex : register(t0); +Texture2D IndLightingTex : register(t1); + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float4 sourceColor = sourceTex.Sample(sourceSampler, input.TexCoord); + float4 ilColor = IndLightingTex.Sample(IndLightingSampler, input.TexCoord); + + psout.Color = sourceColor + ilColor; + + return psout; +} +#endif diff --git a/package/Shaders/ISSimpleColor.hlsl b/package/Shaders/ISSimpleColor.hlsl new file mode 100644 index 000000000..1072a633a --- /dev/null +++ b/package/Shaders/ISSimpleColor.hlsl @@ -0,0 +1,50 @@ +#if defined(DISPLAY_DEPTH) +# include "Common/DummyVSTexCoord.hlsl" +#elif defined(SIMPLE_COLOR) +# include "Common/DummyVS.hlsl" +#endif + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState DepthSampler : register(s0); +SamplerState uintStencilSampler : register(s1); + +Texture2D DepthTex : register(t0); +Texture2D uintStencilTex : register(t1); + +cbuffer PerGeometry : register(b2) +{ + float4 Color : packoffset(c0); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + +# if defined(DISPLAY_DEPTH) + float depth; + if (1e-5 < Color.z) { + uint2 dimensions; + uint numberOfLevels; + uintStencilTex.GetDimensions(0, dimensions.x, dimensions.y, numberOfLevels); + float3 location = float3(input.TexCoord * dimensions, 0); + depth = uintStencilTex.Load(location).x; + } else { + depth = DepthTex.SampleLevel(DepthSampler, input.TexCoord, 0).x; + } + float screenDepth = saturate((-Color.x + depth) / (Color.y - Color.x)); + psout.Color.xyz = (screenDepth * -2 + 3) * (screenDepth * screenDepth); + psout.Color.w = 1; +# elif defined(SIMPLE_COLOR) + psout.Color = Color; +# endif + + return psout; +} +#endif diff --git a/package/Shaders/ISSnowSSS.hlsl b/package/Shaders/ISSnowSSS.hlsl new file mode 100644 index 000000000..cf99a54a4 --- /dev/null +++ b/package/Shaders/ISSnowSSS.hlsl @@ -0,0 +1,74 @@ +#include "Common/Color.hlsli" +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float3 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState depthSampler : register(s0); +SamplerState snowDiffuseSampler : register(s1); +SamplerState snowAlphaSpecSampler : register(s2); + +Texture2D depthTex : register(t0); +Texture2D snowDiffuseTex : register(t1); +Texture2D snowAlphaSpecTex : register(t2); + +cbuffer PerGeometry : register(b2) +{ + float4 g_SSSDarkColor : packoffset(c0); // fSnowSSSColorR in x, fSnowSSSColorG in y, fSnowSSSColorB in z, fSnowSSSDarkColorIntensity in w + float4 g_SSSParameters : packoffset(c1); // fSnowSSSStrength in x, fSnowSSSDepthDiff in y +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + const float4 iterationParameters[] = { { 0.784728, 0.669086, 0.560479, 0 }, + { 0.000051, 0.000185, 0.004717, -2.000000 }, + { 0.000842, 0.002820, 0.019283, -1.280000 }, + { 0.006437, 0.013100, 0.036390, -0.720000 }, + { 0.020926, 0.035861, 0.082190, -0.320000 }, + { 0.079380, 0.113491, 0.077180, -0.080000 }, + { 0.079380, 0.113491, 0.077180, 0.080000 }, + { 0.020926, 0.035861, 0.082190, 0.320000 }, + { 0.006437, 0.013100, 0.036390, 0.720000 }, + { 0.000842, 0.002820, 0.019283, 1.280000 }, + { 0.000051, 0.000185, 0.004717, 2.000000 } }; + + float2 screenPosition = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); + float snowMask = snowAlphaSpecTex.Sample(snowAlphaSpecSampler, screenPosition).y; + float3 sourceColor = snowDiffuseTex.SampleLevel(snowDiffuseSampler, screenPosition, 0).xyz; + + if (1e-5 >= snowMask) { + psout.Color = sourceColor; + return psout; + } + + float depth = depthTex.SampleLevel(depthSampler, screenPosition, 0).x; + + float3 sssColor = float3(0.784727991, 0.669085979, 0.560478985) * sourceColor; + float2 texCoordStep = float2(0.078125, 0.13889) * g_SSSParameters.x / depth; + float depthDiffFactor = 0.1 * g_SSSParameters.y; + for (uint iterationIndex = 1; iterationIndex < 11; ++iterationIndex) { + float2 iterationTexCoord = iterationParameters[iterationIndex].w * texCoordStep + input.TexCoord; + float2 adjustedIterationTexCoord = GetDynamicResolutionAdjustedScreenPosition(iterationTexCoord); + float3 iterationSourceColor = snowDiffuseTex.SampleLevel(snowDiffuseSampler, adjustedIterationTexCoord, 0).xyz; + float iterationDepth = depthTex.SampleLevel(depthSampler, adjustedIterationTexCoord, 0).x; + float iterationDiffuseFactor = min(1, depthDiffFactor * abs(depth - iterationDepth)); + + sssColor += iterationParameters[iterationIndex].xyz * lerp(iterationSourceColor, sourceColor, iterationDiffuseFactor); + } + float sssLuminance = RGBToLuminanceAlternative(sssColor); + float3 darkColor = max(0, lerp(g_SSSDarkColor.xyz * g_SSSDarkColor.w, sourceColor, sssLuminance)); + float3 snowColor = lerp(darkColor, sssColor, sssLuminance); + + psout.Color = lerp(sourceColor, snowColor, snowMask); + + return psout; +} +#endif diff --git a/package/Shaders/ISUpsampleDynamicResolution.hlsl b/package/Shaders/ISUpsampleDynamicResolution.hlsl new file mode 100644 index 000000000..6e69cabdd --- /dev/null +++ b/package/Shaders/ISUpsampleDynamicResolution.hlsl @@ -0,0 +1,29 @@ +#include "Common/DummyVSTexCoord.hlsl" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState sourceSampler : register(s0); + +Texture2D sourceTex : register(t0); + +cbuffer PerGeometry : register(b2) +{ + float4 g_UpsampleParameters : packoffset(c0); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float2 upsampleTexCoord = min(g_UpsampleParameters.zw, g_UpsampleParameters.xy * input.TexCoord); + psout.Color = sourceTex.Sample(sourceSampler, upsampleTexCoord).xyzw; + + return psout; +} +#endif diff --git a/package/Shaders/ISVolumetricLighting.hlsl b/package/Shaders/ISVolumetricLighting.hlsl new file mode 100644 index 000000000..1f1c9362e --- /dev/null +++ b/package/Shaders/ISVolumetricLighting.hlsl @@ -0,0 +1,34 @@ +#include "Common/DummyVSTexCoord.hlsl" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState DepthSampler : register(s0); +SamplerState ShadowMapSampler : register(s1); + +Texture2D DepthTex : register(t0); +Texture2D ShadowMapTex : register(t1); + +cbuffer PerGeometry : register(b2) +{ + float4 g_ViewProj[4] : packoffset(c0); + float4 g_InvViewProj[4] : packoffset(c4); + float4 g_ShadowSampleParam : packoffset(c8); + float4 ShadowMapProj[6] : packoffset(c9); + float4 LightColor_Intensity : packoffset(c15); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + psout.Color = float4(LightColor_Intensity.w * LightColor_Intensity.xyz, LightColor_Intensity.w); + + return psout; +} +#endif diff --git a/package/Shaders/ISWaterBlend.hlsl b/package/Shaders/ISWaterBlend.hlsl new file mode 100644 index 000000000..8d734485d --- /dev/null +++ b/package/Shaders/ISWaterBlend.hlsl @@ -0,0 +1,71 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float3 Color : SV_Target0; + float4 Color1 : SV_Target1; +}; + +#if defined(PSHADER) +SamplerState sourceSampler : register(s0); +SamplerState waterHistorySampler : register(s1); +SamplerState motionBufferSampler : register(s2); +SamplerState depthBufferSampler : register(s3); +SamplerState waterMaskSampler : register(s4); + +Texture2D sourceTex : register(t0); +Texture2D waterHistoryTex : register(t1); +Texture2D motionBufferTex : register(t2); +Texture2D depthBufferTex : register(t3); +Texture2D waterMaskTex : register(t4); + +cbuffer PerGeometry : register(b2) +{ + float4 NearFar_Menu_DistanceFactor : packoffset(c0); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float2 adjustedScreenPosition = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); + float waterMask = waterMaskTex.Sample(waterMaskSampler, adjustedScreenPosition).z; + if (waterMask < 1e-4) { + discard; + } + + float3 sourceColor = sourceTex.Sample(sourceSampler, adjustedScreenPosition).xyz; + float2 motion = motionBufferTex.Sample(motionBufferSampler, adjustedScreenPosition).xy; + float2 motionScreenPosition = input.TexCoord + motion; + float2 motionAdjustedScreenPosition = + GetPreviousDynamicResolutionAdjustedScreenPosition(motionScreenPosition); + float4 waterHistory = + waterHistoryTex.Sample(waterHistorySampler, motionAdjustedScreenPosition).xyzw; + + float3 finalColor = sourceColor; + if (motionScreenPosition.x >= 0 && motionScreenPosition.y >= 0 && motionScreenPosition.x <= 1 && + motionScreenPosition.y <= 1 && waterHistory.w == 1) { + float historyFactor = 0.95; + if (NearFar_Menu_DistanceFactor.z == 0) { + float depth = depthBufferTex.Sample(depthBufferSampler, adjustedScreenPosition).x; + float distanceFactor = clamp(250 * ((-NearFar_Menu_DistanceFactor.x + + (2 * NearFar_Menu_DistanceFactor.x * NearFar_Menu_DistanceFactor.y) / + (-(depth * 2 - 1) * + (NearFar_Menu_DistanceFactor.y - NearFar_Menu_DistanceFactor.x) + + (NearFar_Menu_DistanceFactor.y + NearFar_Menu_DistanceFactor.x))) / + (NearFar_Menu_DistanceFactor.y - NearFar_Menu_DistanceFactor.x)), + 0.1, 0.95); + historyFactor = NearFar_Menu_DistanceFactor.w * (distanceFactor * (waterMask * -0.85 + 0.95)); + } + finalColor = lerp(sourceColor, waterHistory.xyz, historyFactor); + } + + psout.Color1 = float4(finalColor, 1); + psout.Color = finalColor; + + return psout; +} +#endif diff --git a/package/Shaders/ISWaterDisplacement.hlsl b/package/Shaders/ISWaterDisplacement.hlsl new file mode 100644 index 000000000..449a41618 --- /dev/null +++ b/package/Shaders/ISWaterDisplacement.hlsl @@ -0,0 +1,162 @@ +#if defined(SMOOTH_HEIGHTMAP) || defined(RAIN_HEIGHTMAP) || defined(WADING_HEIGHTMAP) +# define HEIGHTMAP +#endif + +struct VS_INPUT +{ + float4 Position : POSITION0; + float2 TexCoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION0; + float2 TexCoord : TEXCOORD0; +#if defined(HEIGHTMAP) + float2 TexCoord1 : TEXCOORD1; + float2 TexCoord2 : TEXCOORD2; + float2 TexCoord3 : TEXCOORD3; + float2 TexCoord4 : TEXCOORD4; +#endif +}; + +#ifdef VSHADER +VS_OUTPUT main(VS_INPUT input) +{ + VS_OUTPUT vsout; + + vsout.Position = float4(input.Position.xyz, 1); + vsout.TexCoord = input.TexCoord.xy; +# if defined(HEIGHTMAP) + vsout.TexCoord1 = input.TexCoord.xy + float2(-0.0009765625, -0.0009765625); + vsout.TexCoord2 = input.TexCoord.xy + float2(-0.0009765625, 0.0009765625); + vsout.TexCoord3 = input.TexCoord.xy + float2(0.0009765625, -0.0009765625); + vsout.TexCoord4 = input.TexCoord.xy + float2(0.0009765625, 0.0009765625); +# endif + + return vsout; +} +#endif + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +# if defined(BLEND_HEIGHTMAPS) +SamplerState HeightMap01Sampler : register(s0); +SamplerState HeightMap02Sampler : register(s1); +# elif defined(NORMALS) +SamplerState DisplaceMapSampler : register(s0); +# elif defined(TEX_OFFSET) +SamplerState DisplaySamplerSampler : register(s0); +# elif defined(HEIGHTMAP) +SamplerState HeightMapSampler : register(s0); +# endif + +# if defined(BLEND_HEIGHTMAPS) +Texture2D HeightMap01Tex : register(t0); +Texture2D HeightMap02Tex : register(t1); +# elif defined(NORMALS) +Texture2D DisplaceMapTex : register(t0); +# elif defined(TEX_OFFSET) +Texture2D DisplaySamplerTex : register(t0); +# elif defined(HEIGHTMAP) +Texture2D HeightMapTex : register(t0); +# endif + +cbuffer PerGeometry : register(b2) +{ + float Time : packoffset(c0.x); + float BlendAmount : packoffset(c0.y); + float2 TextureOffset : packoffset(c0.z); + float fDamp : packoffset(c1.x); + float3 RainVars : packoffset(c1.y); + float4 WadingVars : packoffset(c2.x); +}; + +# if defined(NORMALS) +float GetDisplacementNormalValue(float2 texCoord) +{ + float displaceValue = DisplaceMapTex.Sample(DisplaceMapSampler, texCoord).x; + return fDamp * pow(abs(displaceValue), 7); +} +# endif + +# if defined(HEIGHTMAP) +float4 GetHeight(PS_INPUT input, uniform float3 Vars) +{ + float2 height = HeightMapTex.Sample(HeightMapSampler, input.TexCoord).xy; + float heightLB = HeightMapTex.Sample(HeightMapSampler, input.TexCoord1).x; + float heightLT = HeightMapTex.Sample(HeightMapSampler, input.TexCoord2).x; + float heightRB = HeightMapTex.Sample(HeightMapSampler, input.TexCoord3).x; + float heightRT = HeightMapTex.Sample(HeightMapSampler, input.TexCoord4).x; + + float heightDispersion = -height.x * 4 + (heightLB + heightLT + heightRB + heightRT); + float tmp1 = Vars.x * heightDispersion + (height.y - 0.5); + float heightLR = heightLB + heightLT - heightRB - heightRT; + float heightBT = heightLB - heightLT + heightRB - heightRT; + return 0.5 + float4(max(-1, Vars.z * float2(Vars.y * tmp1 + (height.x - 0.5), tmp1)), 0.5 * float2(heightLR, heightBT)); +} +# endif + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + +# if defined(BLEND_HEIGHTMAPS) + float height01 = HeightMap01Tex.Sample(HeightMap01Sampler, input.TexCoord).x; + float height02 = HeightMap02Tex.Sample(HeightMap02Sampler, input.TexCoord).x; + + psout.Color.xyz = lerp((0.8 / fDamp) * abs(height01), abs(height02), BlendAmount); + psout.Color.w = 1; +# elif defined(CLEAR_SIMULATION) + psout.Color = 0.5; +# elif defined(NORMALS) + + float offset = 0.001953125; + float valueRL = 0; + float valueTB = 0; + [unroll] for (int i = -1; i <= 1; ++i) + { + [unroll] for (int j = -1; j <= 1; ++j) + { + if (i == 0 && j == 0) { + continue; + } + + float currentValue = GetDisplacementNormalValue(input.TexCoord + float2(i * offset, j * offset)); + + float centerMul = 1; + if (i == 0 || j == 0) { + centerMul = 2; + } + + valueRL += i * centerMul * currentValue; + valueTB += j * centerMul * currentValue; + } + } + + psout.Color = float4(normalize(float3(-valueRL, valueTB, 1)), 1) * 0.5 + 0.5; + +# elif defined(RAIN_RIPPLE) || defined(WADING_RIPPLE) + psout.Color = float4(1, 0.5, 0.5, 0.5); +# elif defined(TEX_OFFSET) + float lerpFactor = saturate(10 * (-0.4 + length(input.TexCoord - 0.5))); + float4 displayColor = DisplaySamplerTex.Sample(DisplaySamplerSampler, TextureOffset + input.TexCoord); + psout.Color.xy = displayColor.xy; + psout.Color.zw = lerp(displayColor.zw, 0.5, lerpFactor); +# elif defined(SMOOTH_HEIGHTMAP) + psout.Color = HeightMapTex.Sample(HeightMapSampler, input.TexCoord); +# elif defined(RAIN_HEIGHTMAP) + psout.Color = GetHeight(input, RainVars); +# elif defined(WADING_HEIGHTMAP) + psout.Color = GetHeight(input, WadingVars); +# endif + + return psout; +} +#endif diff --git a/package/Shaders/ISWaterFlow.hlsl b/package/Shaders/ISWaterFlow.hlsl new file mode 100644 index 000000000..abdf41ec4 --- /dev/null +++ b/package/Shaders/ISWaterFlow.hlsl @@ -0,0 +1,44 @@ +#include "Common/DummyVSTexCoord.hlsl" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState FlowmapSampler : register(s0); + +Texture2D FlowmapTex : register(t0); + +cbuffer PerGeometry : register(b2) +{ + float2 CellOffset : packoffset(c0.x); + float2 LastCenter : packoffset(c0.z); + float2 Center : packoffset(c1.x); + float Radius : packoffset(c1.z); + float Magnitude : packoffset(c1.w); + float Strength : packoffset(c2.x); + float Falloff : packoffset(c2.y); + float Scale : packoffset(c2.z); + float2 FlowVector : packoffset(c3); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float centerDistance = length(Center - frac(float2(-CellOffset.x + input.TexCoord.x, CellOffset.y + input.TexCoord.y))); + float4 flowmapValue = FlowmapTex.Sample(FlowmapSampler, input.TexCoord); + if (centerDistance < Radius) { + float flowStrength = Strength * (1 - pow(centerDistance / Radius, 4)); + flowmapValue.xy = normalize(normalize(flowmapValue.xy * 2 - 1) + flowStrength * FlowVector) * 0.5 + 0.5; + flowmapValue.z = saturate(Scale * flowStrength + flowmapValue.z); + flowmapValue.w = max(0.1, min(1, 0.002 * (flowmapValue.w * 500 + Magnitude * flowStrength))); + } + psout.Color = flowmapValue; + + return psout; +} +#endif diff --git a/package/Shaders/ISWorldMap.hlsl b/package/Shaders/ISWorldMap.hlsl new file mode 100644 index 000000000..f269427a6 --- /dev/null +++ b/package/Shaders/ISWorldMap.hlsl @@ -0,0 +1,59 @@ +#include "Common/DummyVSTexCoord.hlsl" +#include "Common/FrameBuffer.hlsli" + +typedef VS_OUTPUT PS_INPUT; + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +#if defined(PSHADER) +SamplerState ImageSampler : register(s0); +SamplerState DepthSampler : register(s1); + +Texture2D ImageTex : register(t0); +Texture2D DepthTex : register(t1); + +cbuffer PerGeometry : register(b2) +{ + float4 CameraParams : packoffset(c0); + float4 DepthParams : packoffset(c1); + float4 TexelSize : packoffset(c2); +}; + +PS_OUTPUT main(PS_INPUT input) +{ + PS_OUTPUT psout; + + float2 adjustedTexCoord = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord); + + float depth = DepthTex.Sample(DepthSampler, adjustedTexCoord).x; + + float depthFactor = DepthParams.w / ((1 - depth) * DepthParams.z + DepthParams.y); + float offsetDelta = min(TexelSize.y, TexelSize.z * abs(depthFactor - TexelSize.x)); +# if defined(NO_SKY_BLUR) + if (1 - depth <= 1e-4) { + offsetDelta = 0; + } +# endif + if (depthFactor < TexelSize.x) { + offsetDelta *= TexelSize.w; + } + float2 startOffset = input.TexCoord - 3 * (CameraParams.xy * offsetDelta); + + float4 color = 0; + for (int i = 0; i < 7; ++i) { + for (int j = 0; j < 7; ++j) { + float2 currentTexCoord = GetDynamicResolutionAdjustedScreenPosition( + startOffset + CameraParams.xy * offsetDelta * float2(i, j)); + float4 currentColor = ImageTex.Sample(ImageSampler, currentTexCoord); + color += currentColor; + } + } + + psout.Color = 0.0204081628 * color; + + return psout; +} +#endif diff --git a/src/ShaderCache.cpp b/src/ShaderCache.cpp index f50e88abb..de8968366 100644 --- a/src/ShaderCache.cpp +++ b/src/ShaderCache.cpp @@ -622,6 +622,188 @@ namespace SIE defines[0] = { nullptr, nullptr }; } + static void GetImagespaceShaderDefines(uint32_t descriptor, D3D_SHADER_MACRO* defines) + { + using enum RE::ImageSpaceManager::ImageSpaceEffectEnum; + + const auto descEnum = + static_cast(descriptor); + if ((descriptor >= static_cast(ISBlur3) && + descriptor <= static_cast(ISBrightPassBlur15)) || + descEnum == ISBlur) { + if (descEnum == ISBlur) { + defines[0] = { "BLUR_RADIUS", "0" }; + ++defines; + } else { + static constexpr std::array blurRadiusDefines = { { "3", "5", + "7", "9", "11", "13", "15" } }; + const size_t blurRadius = static_cast( + (descriptor - static_cast(ISBlur3)) % blurRadiusDefines.size()); + defines[0] = { "BLUR_RADIUS", blurRadiusDefines[blurRadius] }; + ++defines; + const size_t blurType = static_cast( + (descriptor - static_cast(ISBlur3)) / blurRadiusDefines.size()); + if (blurType == 1) { + defines[0] = { "BLUR_NON_HDR", nullptr }; + ++defines; + } else if (blurType == 2) { + defines[0] = { "BLUR_BRIGHT_PASS", nullptr }; + ++defines; + } + } + } else if (descEnum == ISDisplayDepth) { + defines[0] = { "DISPLAY_DEPTH", nullptr }; + ++defines; + } else if (descEnum == ISSimpleColor) { + defines[0] = { "SIMPLE_COLOR", nullptr }; + ++defines; + } else if (descEnum == ISCopyDynamicFetchDisabled) { + defines[0] = { "DYNAMIC_FETCH_DISABLED", nullptr }; + ++defines; + } else if (descEnum == ISCopyGrayScale) { + defines[0] = { "GRAY_SCALE", nullptr }; + ++defines; + } else if (descEnum == ISCopyTextureMask) { + defines[0] = { "TEXTURE_MASK", nullptr }; + ++defines; + } else if (descEnum == ISCompositeLensFlare) { + defines[0] = { "VOLUMETRIC_LIGHTING", nullptr }; + ++defines; + } else if (descEnum == ISCompositeVolumetricLighting) { + defines[0] = { "LENS_FLARE", nullptr }; + ++defines; + } else if (descEnum == ISCompositeLensFlareVolumetricLighting) { + defines[0] = { "VOLUMETRIC_LIGHTING", nullptr }; + ++defines; + defines[0] = { "LENS_FLARE", nullptr }; + ++defines; + } else if (descriptor >= static_cast(ISDepthOfField) && + descriptor <= static_cast(ISDistantBlurMaskedFogged)) { + if (descriptor >= static_cast(ISDepthOfField) && + descriptor <= static_cast(ISDepthOfFieldMaskedFogged)) + + { + defines[0] = { "DOF", nullptr }; + ++defines; + } else { + defines[0] = { "DISTANT_BLUR", nullptr }; + ++defines; + } + if (descEnum != ISDepthOfField && descEnum != ISDistantBlur) { + defines[0] = { "FOGGED", nullptr }; + ++defines; + } + if (descEnum == ISDepthOfFieldMaskedFogged || descEnum == ISDistantBlurMaskedFogged) { + defines[0] = { "MASKED", nullptr }; + ++defines; + } + } else if (descEnum == ISDownsampleIgnoreBrightest) { + defines[0] = { "IGNORE_BRIGHTEST", nullptr }; + ++defines; + } else if (descEnum == ISHDRTonemapBlendCinematic) { + defines[0] = { "TONEMAP", nullptr }; + ++defines; + } else if (descEnum == ISHDRTonemapBlendCinematicFade) { + defines[0] = { "TONEMAP", nullptr }; + ++defines; + defines[0] = { "FADE", nullptr }; + ++defines; + } else if (descriptor >= static_cast(ISHDRDownSample16) && + descriptor <= static_cast(ISHDRDownSample16LightAdapt)) { + defines[0] = { "DOWNSAMPLE", nullptr }; + ++defines; + if (descEnum == ISHDRDownSample16 || descEnum == ISHDRDownSample16Lum || + descEnum == ISHDRDownSample16LightAdapt || + descEnum == ISHDRDownSample16LumClamp) { + defines[0] = { "SAMPLES_COUNT", "16" }; + ++defines; + } else { + defines[0] = { "SAMPLES_COUNT", "4" }; + ++defines; + } + if (descEnum == ISHDRDownSample4RGB2Lum) { + defines[0] = { "RGB2LUM", nullptr }; + ++defines; + } else if (descEnum == ISHDRDownSample16Lum || descEnum == ISHDRDownSample16LumClamp) { + defines[0] = { "LUM", nullptr }; + ++defines; + } else if (descEnum == ISHDRDownSample16LightAdapt || + descEnum == ISHDRDownSample4LightAdapt) { + defines[0] = { "LIGHT_ADAPT", nullptr }; + ++defines; + } + } else if (descEnum == ISLightingCompositeMenu) { + defines[0] = { "MENU", nullptr }; + ++defines; + } else if (descEnum == ISLightingCompositeNoDirectionalLight) { + defines[0] = { "NO_DIRECTIONAL_LIGHT", nullptr }; + ++defines; + } else if (descEnum == ISWaterBlendHeightmaps) { + defines[0] = { "BLEND_HEIGHTMAPS", nullptr }; + ++defines; + } else if (descEnum == ISWaterDisplacementClearSimulation) { + defines[0] = { "CLEAR_SIMULATION", nullptr }; + ++defines; + } else if (descEnum == ISWaterDisplacementNormals) { + defines[0] = { "NORMALS", nullptr }; + ++defines; + } else if (descEnum == ISWaterDisplacementRainRipple) { + defines[0] = { "RAIN_RIPPLE", nullptr }; + ++defines; + } else if (descEnum == ISWaterDisplacementTexOffset) { + defines[0] = { "TEX_OFFSET", nullptr }; + ++defines; + } else if (descEnum == ISWaterSmoothHeightmap) { + defines[0] = { "SMOOTH_HEIGHTMAP", nullptr }; + ++defines; + } else if (descEnum == ISWaterRainHeightmap) { + defines[0] = { "RAIN_HEIGHTMAP", nullptr }; + ++defines; + } else if (descEnum == ISWaterWadingHeightmap) { + defines[0] = { "WADING_HEIGHTMAP", nullptr }; + ++defines; + } else if (descEnum == ISWorldMapNoSkyBlur) { + defines[0] = { "NO_SKY_BLUR", nullptr }; + ++defines; + } else if (descEnum == ISMinifyContrast) { + defines[0] = { "CONTRAST", nullptr }; + ++defines; + } else if (descEnum == ISNoiseNormalmap) { + defines[0] = { "NORMALMAP", nullptr }; + ++defines; + } else if (descEnum == ISNoiseScrollAndBlend) { + defines[0] = { "SCROLL_AND_BLEND", nullptr }; + ++defines; + } else if (descEnum == ISRadialBlur) { + defines[0] = { "SAMPLES_COUNT", "2" }; + ++defines; + } else if (descEnum == ISRadialBlurHigh) { + defines[0] = { "SAMPLES_COUNT", "10" }; + ++defines; + } else if (descEnum == ISRadialBlurMedium) { + defines[0] = { "SAMPLES_COUNT", "6" }; + ++defines; + } else if (descEnum == ISSAOCompositeSAO) { + defines[0] = { "APPLY_SAO", nullptr }; + ++defines; + } else if (descEnum == ISSAOCompositeFog) { + defines[0] = { "APPLY_FOG", nullptr }; + ++defines; + } else if (descEnum == ISSAOCompositeSAOFog) { + defines[0] = { "APPLY_SAO", nullptr }; + ++defines; + defines[0] = { "APPLY_FOG", nullptr }; + ++defines; + } else if (descEnum == ISSAOBlurH) { + defines[0] = { "AXIS_H", nullptr }; + ++defines; + } else if (descEnum == ISSAOBlurV) { + defines[0] = { "AXIS_V", nullptr }; + ++defines; + } + defines[0] = { nullptr, nullptr }; + } + static void GetShaderDefines(RE::BSShader::Type type, uint32_t descriptor, D3D_SHADER_MACRO* defines) { @@ -638,6 +820,9 @@ namespace SIE case RE::BSShader::Type::BloodSplatter: GetBloodSplaterShaderDefines(descriptor, defines); break; + case RE::BSShader::Type::ImageSpace: + GetImagespaceShaderDefines(descriptor, defines); + break; case RE::BSShader::Type::Lighting: GetLightingShaderDefines(descriptor, defines); break; @@ -1046,18 +1231,37 @@ namespace SIE return result; } - static int32_t GetVariableIndex(ShaderClass shaderClass, RE::BSShader::Type shaderType, const char* name) + static int32_t GetVariableIndex(ShaderClass shaderClass, const RE::BSShader& shader, const char* name) { - static auto variableNames = GetVariableIndices(); + if (shader.shaderType == RE::BSShader::Type::ImageSpace) { + const auto& imagespaceShader = static_cast(shader); + + if (shaderClass == ShaderClass::Vertex) { + for (size_t nameIndex = 0; nameIndex < imagespaceShader.vsConstantNames.size(); + ++nameIndex) { + if (std::string_view(imagespaceShader.vsConstantNames[static_cast(nameIndex)].c_str()) == + name) { + return static_cast(nameIndex); + } + } + } else if (shaderClass == ShaderClass::Pixel) { + for (size_t nameIndex = 0; nameIndex < imagespaceShader.psConstantNames.size(); ++nameIndex) { + if (std::string_view(imagespaceShader.psConstantNames[static_cast(nameIndex)].c_str()) == name) { + return static_cast(nameIndex); + } + } + } + } else { + static auto variableNames = GetVariableIndices(); - const auto& names = - variableNames[static_cast(shaderType)][static_cast(shaderClass)]; - auto it = names.find(name); - if (it == names.cend()) { - return -1; + const auto& names = variableNames[static_cast(shader.shaderType.get())] + [static_cast(shaderClass)]; + auto it = names.find(name); + if (it != names.cend()) { + return it->second; + } } - - return it->second; + return -1; } static std::string MergeDefinesString(std::array& defines, bool a_sort = false) @@ -1095,12 +1299,12 @@ namespace SIE std::array& bufferSizes, std::array& constantOffsets, uint64_t& vertexDesc, - ShaderClass shaderClass, RE::BSShader::Type shaderType, uint32_t descriptor) + ShaderClass shaderClass, uint32_t descriptor, const RE::BSShader& shader) { D3D11_SHADER_DESC desc; if (FAILED(reflector.GetDesc(&desc))) { logger::error("Failed to get shader descriptor for {} shader {}::{}", - magic_enum::enum_name(shaderClass), magic_enum::enum_name(shaderType), + magic_enum::enum_name(shaderClass), magic_enum::enum_name(shader.shaderType.get()), descriptor); return; } @@ -1115,7 +1319,7 @@ namespace SIE logger::error( "Failed to get input parameter {} descriptor for {} shader {}::{}", inputIndex, magic_enum::enum_name(shaderClass), - magic_enum::enum_name(shaderType), + magic_enum::enum_name(shader.shaderType.get()), descriptor); } else { std::string_view semanticName = inputDesc.SemanticName; @@ -1166,7 +1370,7 @@ namespace SIE if (bufferReflector == nullptr) { logger::trace("Buffer {} not found for {} shader {}::{}", bufferName, magic_enum::enum_name(shaderClass), - magic_enum::enum_name(shaderType), + magic_enum::enum_name(shader.shaderType.get()), descriptor); return; } @@ -1175,7 +1379,7 @@ namespace SIE if (FAILED(bufferReflector->GetDesc(&bufferDesc))) { logger::trace("Failed to get buffer {} descriptor for {} shader {}::{}", bufferName, magic_enum::enum_name(shaderClass), - magic_enum::enum_name(shaderType), + magic_enum::enum_name(shader.shaderType.get()), descriptor); return; } @@ -1186,21 +1390,61 @@ namespace SIE D3D11_SHADER_VARIABLE_DESC varDesc; if (FAILED(var->GetDesc(&varDesc))) { logger::trace("Failed to get variable descriptor for {} shader {}::{}", - magic_enum::enum_name(shaderClass), magic_enum::enum_name(shaderType), + magic_enum::enum_name(shaderClass), magic_enum::enum_name(shader.shaderType.get()), descriptor); continue; } const auto variableIndex = - GetVariableIndex(shaderClass, shaderType, varDesc.Name); - if (variableIndex != -1) { + GetVariableIndex(shaderClass, shader, varDesc.Name); + const bool variableFound = variableIndex != -1; + if (variableFound) { constantOffsets[variableIndex] = (int8_t)(varDesc.StartOffset / 4); } else { logger::trace("Unknown variable name {} in {} shader {}::{}", varDesc.Name, magic_enum::enum_name(shaderClass), - magic_enum::enum_name(shaderType), + magic_enum::enum_name(shader.shaderType.get()), descriptor); } + + if (shader.shaderType == RE::BSShader::Type::ImageSpace) { + D3D11_SHADER_TYPE_DESC varTypeDesc; + var->GetType()->GetDesc(&varTypeDesc); + if (varTypeDesc.Elements > 0) { + if (!variableFound) { + const std::string arrayName = + std::format("{}[{}]", varDesc.Name, varTypeDesc.Elements); + const auto variableArrayIndex = + GetVariableIndex(shaderClass, shader, arrayName.c_str()); + if (variableArrayIndex != -1) { + constantOffsets[variableArrayIndex] = static_cast(varDesc.StartOffset / 4); + } else { + logger::error("Unknown variable name {} in {} shader {}::{}", + arrayName, magic_enum::enum_name(shaderClass), + magic_enum::enum_name(shader.shaderType.get()), descriptor); + } + } else { + const auto elementSize = varDesc.Size / varTypeDesc.Elements; + for (uint32_t arrayIndex = 1; arrayIndex < varTypeDesc.Elements; + ++arrayIndex) { + const std::string varName = + std::format("{}[{}]", varDesc.Name, arrayIndex); + const auto variableArrayElementIndex = + GetVariableIndex(shaderClass, shader, varName.c_str()); + if (variableArrayElementIndex != -1) { + constantOffsets[variableArrayElementIndex] = + static_cast((varDesc.StartOffset + elementSize * arrayIndex) / 4); + } else { + logger::error( + "Unknown variable name {} in {} shader {}::{}", varName, + magic_enum::enum_name(shaderClass), + magic_enum::enum_name(shader.shaderType.get()), + descriptor); + } + } + } + } + } } bufferSize = ((bufferDesc.Size + 15) & ~15) / 16; @@ -1305,7 +1549,10 @@ namespace SIE defines[lastIndex] = { nullptr, nullptr }; // do final entry GetShaderDefines(type, descriptor, &defines[lastIndex]); - const std::wstring path = GetShaderPath(shader.fxpFilename); + const std::wstring path = GetShaderPath( + shader.shaderType == RE::BSShader::Type::ImageSpace ? + std::string_view(static_cast(shader).originalShaderName.c_str()) : + shader.fxpFilename); std::string strPath; std::transform(path.begin(), path.end(), std::back_inserter(strPath), [](wchar_t c) { @@ -1388,7 +1635,7 @@ namespace SIE } std::unique_ptr CreateVertexShader(ID3DBlob& shaderData, - RE::BSShader::Type type, uint32_t descriptor) + const RE::BSShader& shader, uint32_t descriptor) { static const auto device = REL::Relocation(RE::Offset::D3D11Device); static const auto perTechniqueBuffersArray = @@ -1413,7 +1660,7 @@ namespace SIE const auto reflectionResult = D3DReflect(shaderData.GetBufferPointer(), shaderData.GetBufferSize(), IID_PPV_ARGS(&reflector)); if (FAILED(reflectionResult)) { - logger::error("Failed to reflect vertex shader {}::{}", magic_enum::enum_name(type), + logger::error("Failed to reflect vertex shader {}::{}", magic_enum::enum_name(shader.shaderType.get()), descriptor); } else { std::array bufferSizes = { 0, 0, 0 }; @@ -1422,7 +1669,7 @@ namespace SIE std::fill(newShader->constantTable.begin(), newShader->constantTable.end(), 0); #pragma warning(pop) ReflectConstantBuffers(*reflector.Get(), bufferSizes, newShader->constantTable, newShader->shaderDesc, - ShaderClass::Vertex, type, descriptor); + ShaderClass::Vertex, descriptor, shader); if (bufferSizes[0] != 0) { newShader->constantBuffers[0].buffer = (REX::W32::ID3D11Buffer*)perTechniqueBuffersArray.get()[bufferSizes[0]]; @@ -1450,7 +1697,7 @@ namespace SIE } std::unique_ptr CreatePixelShader(ID3DBlob& shaderData, - RE::BSShader::Type type, uint32_t descriptor) + const RE::BSShader& shader, uint32_t descriptor) { static const auto device = REL::Relocation(RE::Offset::D3D11Device); static const auto perTechniqueBuffersArray = @@ -1468,7 +1715,7 @@ namespace SIE const auto reflectionResult = D3DReflect(shaderData.GetBufferPointer(), shaderData.GetBufferSize(), IID_PPV_ARGS(&reflector)); if (FAILED(reflectionResult)) { - logger::error("Failed to reflect vertex shader {}::{}", magic_enum::enum_name(type), + logger::error("Failed to reflect vertex shader {}::{}", magic_enum::enum_name(shader.shaderType.get()), descriptor); } else { std::array bufferSizes = { 0, 0, 0 }; @@ -1479,7 +1726,7 @@ namespace SIE uint64_t dummy; ReflectConstantBuffers(*reflector.Get(), bufferSizes, newShader->constantTable, dummy, - ShaderClass::Pixel, type, descriptor); + ShaderClass::Pixel, descriptor, shader); if (bufferSizes[0] != 0) { newShader->constantBuffers[0].buffer = (REX::W32::ID3D11Buffer*)perTechniqueBuffersArray.get()[bufferSizes[0]]; @@ -1505,6 +1752,146 @@ namespace SIE return newShader; } + + static bool GetImagespaceShaderDescriptor(const RE::BSImagespaceShader& imagespaceShader, uint32_t& descriptor) + { + using enum RE::ImageSpaceManager::ImageSpaceEffectEnum; + + static const std::unordered_map descriptors{ + { "BSImagespaceShaderISBlur", static_cast(ISBlur) }, + { "BSImagespaceShaderBlur3", static_cast(ISBlur3) }, + { "BSImagespaceShaderBlur5", static_cast(ISBlur5) }, + { "BSImagespaceShaderBlur7", static_cast(ISBlur7) }, + { "BSImagespaceShaderBlur9", static_cast(ISBlur9) }, + { "BSImagespaceShaderBlur11", static_cast(ISBlur11) }, + { "BSImagespaceShaderBlur13", static_cast(ISBlur13) }, + { "BSImagespaceShaderBlur15", static_cast(ISBlur15) }, + { "BSImagespaceShaderBrightPassBlur3", static_cast(ISBrightPassBlur3) }, + { "BSImagespaceShaderBrightPassBlur5", static_cast(ISBrightPassBlur5) }, + { "BSImagespaceShaderBrightPassBlur7", static_cast(ISBrightPassBlur7) }, + { "BSImagespaceShaderBrightPassBlur9", static_cast(ISBrightPassBlur9) }, + { "BSImagespaceShaderBrightPassBlur11", static_cast(ISBrightPassBlur11) }, + { "BSImagespaceShaderBrightPassBlur13", static_cast(ISBrightPassBlur13) }, + { "BSImagespaceShaderBrightPassBlur15", static_cast(ISBrightPassBlur15) }, + { "BSImagespaceShaderNonHDRBlur3", static_cast(ISNonHDRBlur3) }, + { "BSImagespaceShaderNonHDRBlur5", static_cast(ISNonHDRBlur5) }, + { "BSImagespaceShaderNonHDRBlur7", static_cast(ISNonHDRBlur7) }, + { "BSImagespaceShaderNonHDRBlur9", static_cast(ISNonHDRBlur9) }, + { "BSImagespaceShaderNonHDRBlur11", static_cast(ISNonHDRBlur11) }, + { "BSImagespaceShaderNonHDRBlur13", static_cast(ISNonHDRBlur13) }, + { "BSImagespaceShaderNonHDRBlur15", static_cast(ISNonHDRBlur15) }, + { "BSImagespaceShaderISBasicCopy", static_cast(ISBasicCopy) }, + { "BSImagespaceShaderISSimpleColor", static_cast(ISSimpleColor) }, + { "BSImagespaceShaderApplyReflections", static_cast(ISApplyReflections) }, + { "BSImagespaceShaderISExp", static_cast(ISExp) }, + { "BSImagespaceShaderISDisplayDepth", static_cast(ISDisplayDepth) }, + { "BSImagespaceShaderAlphaBlend", static_cast(ISAlphaBlend) }, + { "BSImagespaceShaderWaterFlow", static_cast(ISWaterFlow) }, + { "BSImagespaceShaderISWaterBlend", static_cast(ISWaterBlend) }, + { "BSImagespaceShaderGreyScale", static_cast(ISCopyGrayScale) }, + { "BSImagespaceShaderCopy", static_cast(ISCopy) }, + { "BSImagespaceShaderCopyScaleBias", static_cast(ISCopyScaleBias) }, + { "BSImagespaceShaderCopyCustomViewport", + static_cast(ISCopyCustomViewport) }, + { "BSImagespaceShaderCopyTextureMask", static_cast(ISCopyTextureMask) }, + { "BSImagespaceShaderCopyDynamicFetchDisabled", + static_cast(ISCopyDynamicFetchDisabled) }, + { "BSImagespaceShaderISCompositeVolumetricLighting", + static_cast(ISCompositeVolumetricLighting) }, + { "BSImagespaceShaderISCompositeLensFlare", + static_cast(ISCompositeLensFlare) }, + { "BSImagespaceShaderISCompositeLensFlareVolumetricLighting", + static_cast(ISCompositeLensFlareVolumetricLighting) }, + { "BSImagespaceShaderISDebugSnow", static_cast(ISDebugSnow) }, + { "BSImagespaceShaderDepthOfField", static_cast(ISDepthOfField) }, + { "BSImagespaceShaderDepthOfFieldFogged", + static_cast(ISDepthOfFieldFogged) }, + { "BSImagespaceShaderDepthOfFieldMaskedFogged", + static_cast(ISDepthOfFieldMaskedFogged) }, + { "BSImagespaceShaderDistantBlur", static_cast(ISDistantBlur) }, + { "BSImagespaceShaderDistantBlurFogged", + static_cast(ISDistantBlurFogged) }, + { "BSImagespaceShaderDistantBlurMaskedFogged", + static_cast(ISDistantBlurMaskedFogged) }, + { "BSImagespaceShaderDoubleVision", static_cast(ISDoubleVision) }, + { "BSImagespaceShaderISDownsample", static_cast(ISDownsample) }, + { "BSImagespaceShaderISDownsampleIgnoreBrightest", + static_cast(ISDownsampleIgnoreBrightest) }, + { "BSImagespaceShaderISUpsampleDynamicResolution", + static_cast(ISUpsampleDynamicResolution) }, + { "BSImageSpaceShaderVolumetricLighting", + static_cast(ISVolumetricLighting) }, + { "BSImagespaceShaderHDRDownSample4", static_cast(ISHDRDownSample4) }, + { "BSImagespaceShaderHDRDownSample4LightAdapt", + static_cast(ISHDRDownSample4LightAdapt) }, + { "BSImagespaceShaderHDRDownSample4LumClamp", + static_cast(ISHDRDownSample4LumClamp) }, + { "BSImagespaceShaderHDRDownSample4RGB2Lum", + static_cast(ISHDRDownSample4RGB2Lum) }, + { "BSImagespaceShaderHDRDownSample16", static_cast(ISHDRDownSample16) }, + { "BSImagespaceShaderHDRDownSample16LightAdapt", + static_cast(ISHDRDownSample16LightAdapt) }, + { "BSImagespaceShaderHDRDownSample16Lum", + static_cast(ISHDRDownSample16Lum) }, + { "BSImagespaceShaderHDRDownSample16LumClamp", + static_cast(ISHDRDownSample16LumClamp) }, + { "BSImagespaceShaderHDRTonemapBlendCinematic", + static_cast(ISHDRTonemapBlendCinematic) }, + { "BSImagespaceShaderHDRTonemapBlendCinematicFade", + static_cast(ISHDRTonemapBlendCinematicFade) }, + { "BSImagespaceShaderISIBLensFlares", static_cast(ISIBLensFlares) }, + { "BSImagespaceShaderISLightingComposite", + static_cast(ISLightingComposite) }, + { "BSImagespaceShaderISLightingCompositeMenu", + static_cast(ISLightingCompositeMenu) }, + { "BSImagespaceShaderISLightingCompositeNoDirectionalLight", + static_cast(ISLightingCompositeNoDirectionalLight) }, + { "BSImagespaceShaderLocalMap", static_cast(ISLocalMap) }, + { "BSISWaterBlendHeightmaps", static_cast(ISWaterBlendHeightmaps) }, + { "BSISWaterDisplacementClearSimulation", + static_cast(ISWaterDisplacementClearSimulation) }, + { "BSISWaterDisplacementNormals", + static_cast(ISWaterDisplacementNormals) }, + { "BSISWaterDisplacementRainRipple", + static_cast(ISWaterDisplacementRainRipple) }, + { "BSISWaterDisplacementTexOffset", + static_cast(ISWaterDisplacementTexOffset) }, + { "BSISWaterWadingHeightmap", static_cast(ISWaterWadingHeightmap) }, + { "BSISWaterRainHeightmap", static_cast(ISWaterRainHeightmap) }, + { "BSISWaterSmoothHeightmap", static_cast(ISWaterSmoothHeightmap) }, + { "BSISWaterWadingHeightmap", static_cast(ISWaterWadingHeightmap) }, + { "BSImagespaceShaderMap", static_cast(ISMap) }, + { "BSImagespaceShaderMap", static_cast(ISMap) }, + { "BSImagespaceShaderWorldMap", static_cast(ISWorldMap) }, + { "BSImagespaceShaderWorldMapNoSkyBlur", + static_cast(ISWorldMapNoSkyBlur) }, + { "BSImagespaceShaderISMinify", static_cast(ISMinify) }, + { "BSImagespaceShaderISMinifyContrast", static_cast(ISMinifyContrast) }, + { "BSImagespaceShaderNoiseNormalmap", static_cast(ISNoiseNormalmap) }, + { "BSImagespaceShaderNoiseScrollAndBlend", + static_cast(ISNoiseScrollAndBlend) }, + { "BSImagespaceShaderRadialBlur", + static_cast(ISRadialBlur) }, + { "BSImagespaceShaderRadialBlurHigh", static_cast(ISRadialBlurHigh) }, + { "BSImagespaceShaderRadialBlurMedium", static_cast(ISRadialBlurMedium) }, + { "BSImagespaceShaderRefraction", static_cast(ISRefraction) }, + { "BSImagespaceShaderISSAOCompositeSAO", static_cast(ISSAOCompositeSAO) }, + { "BSImagespaceShaderISSAOCompositeFog", static_cast(ISSAOCompositeFog) }, + { "BSImagespaceShaderISSAOCompositeSAOFog", static_cast(ISSAOCompositeSAOFog) }, + { "BSImagespaceShaderISSAOCameraZ", static_cast(ISSAOCameraZ) }, + { "BSImagespaceShaderISSILComposite", static_cast(ISSILComposite) }, + { "BSImagespaceShaderISSnowSSS", static_cast(ISSnowSSS) }, + { "BSImagespaceShaderISSAOBlurH", static_cast(ISSAOBlurH) }, + { "BSImagespaceShaderISSAOBlurV", static_cast(ISSAOBlurV) }, + }; + + auto it = descriptors.find(imagespaceShader.name.c_str()); + if (it == descriptors.cend()) { + return false; + } + descriptor = it->second; + return true; + } } RE::BSGraphics::VertexShader* ShaderCache::GetVertexShader(const RE::BSShader& shader, @@ -1517,6 +1904,13 @@ namespace SIE } } + if (shader.shaderType == RE::BSShader::Type::ImageSpace) { + const auto& isShader = static_cast(shader); + if (!SShaderCache::GetImagespaceShaderDescriptor(isShader, descriptor)) { + return nullptr; + } + } + auto state = State::GetSingleton(); if (!((ShaderCache::IsSupportedShader(shader) || state->IsDeveloperMode() && state->IsShaderEnabled(shader)) && state->enableVShaders)) { return nullptr; @@ -1564,6 +1958,13 @@ namespace SIE return nullptr; } + if (shader.shaderType == RE::BSShader::Type::ImageSpace) { + const auto& isShader = static_cast(shader); + if (!SShaderCache::GetImagespaceShaderDescriptor(isShader, descriptor)) { + return nullptr; + } + } + auto key = SIE::SShaderCache::GetShaderString(ShaderClass::Pixel, shader, descriptor, true); if (blockedKeyIndex != -1 && !blockedKey.empty() && key == blockedKey) { if (std::find(blockedIDs.begin(), blockedIDs.end(), descriptor) == blockedIDs.end()) { @@ -1893,7 +2294,7 @@ namespace SIE SShaderCache::CompileShader(ShaderClass::Vertex, shader, descriptor, isDiskCache)) { static const auto device = REL::Relocation(RE::Offset::D3D11Device); - auto newShader = SShaderCache::CreateVertexShader(*shaderBlob, shader.shaderType.get(), + auto newShader = SShaderCache::CreateVertexShader(*shaderBlob, shader, descriptor); std::lock_guard lockGuard(vertexShadersMutex); @@ -1922,7 +2323,7 @@ namespace SIE SShaderCache::CompileShader(ShaderClass::Pixel, shader, descriptor, isDiskCache)) { static const auto device = REL::Relocation(RE::Offset::D3D11Device); - auto newShader = SShaderCache::CreatePixelShader(*shaderBlob, shader.shaderType.get(), + auto newShader = SShaderCache::CreatePixelShader(*shaderBlob, shader, descriptor); std::lock_guard lockGuard(pixelShadersMutex); diff --git a/src/ShaderCache.h b/src/ShaderCache.h index 39135de26..ad1ac9b87 100644 --- a/src/ShaderCache.h +++ b/src/ShaderCache.h @@ -114,7 +114,8 @@ namespace SIE type == RE::BSShader::Type::Particle || type == RE::BSShader::Type::Water || type == RE::BSShader::Type::Effect || - type == RE::BSShader::Type::Utility; + type == RE::BSShader::Type::Utility || + type == RE::BSShader::Type::ImageSpace; return type == RE::BSShader::Type::Lighting || type == RE::BSShader::Type::BloodSplatter || type == RE::BSShader::Type::DistantTree ||