From 339ed1a6651765f7f6d20112900e32dc69dad675 Mon Sep 17 00:00:00 2001 From: Tim <15017472+doodlum@users.noreply.github.com> Date: Tue, 11 Jul 2023 00:22:43 +0100 Subject: [PATCH 01/14] VR grass: Fixed eyes, added point lights --- features/Grass Lighting/Shaders/RunGrass.hlsl | 274 +++++++++++------- src/Features/Clustered.cpp | 53 ++-- src/Features/Clustered.h | 8 +- src/Features/GrassLighting.cpp | 28 +- src/Features/GrassLighting.h | 4 +- 5 files changed, 224 insertions(+), 143 deletions(-) diff --git a/features/Grass Lighting/Shaders/RunGrass.hlsl b/features/Grass Lighting/Shaders/RunGrass.hlsl index e384fac73..34fb73b73 100644 --- a/features/Grass Lighting/Shaders/RunGrass.hlsl +++ b/features/Grass Lighting/Shaders/RunGrass.hlsl @@ -8,6 +8,7 @@ struct VS_INPUT float4 InstanceData2 : TEXCOORD5; float4 InstanceData3 : TEXCOORD6; float4 InstanceData4 : TEXCOORD7; + uint InstanceID : SV_InstanceID0; }; struct VS_OUTPUT @@ -15,63 +16,48 @@ struct VS_OUTPUT float4 HPosition : SV_POSITION0; float4 VertexColor : COLOR0; float3 TexCoord : TEXCOORD0; - float3 ViewSpacePosition : TEXCOORD1; + float3 ViewSpacePosition : TEXCOORD2; #if defined(RENDER_DEPTH) - float2 Depth : TEXCOORD2; + float2 Depth : TEXCOORD3; #endif float4 WorldPosition : POSITION1; float4 PreviousWorldPosition : POSITION2; - float3 ViewDirectionVec : POSITION3; float3 VertexNormal : POSITION4; + float o7 : SV_ClipDistance0; + float p7 : SV_CullDistance0; }; -cbuffer PerGeometry : register(b2) +#ifdef VSHADER + +cbuffer cb7 : register(b7) { - row_major float4x4 WorldViewProj : packoffset(c0); - row_major float4x4 WorldView : packoffset(c4); - row_major float4x4 World : packoffset(c8); - row_major float4x4 PreviousWorld : packoffset(c12); - float4 FogNearColor : packoffset(c16); - float3 WindVector : packoffset(c17); - float WindTimer : packoffset(c17.w); - float3 DirLightDirection : packoffset(c18); - float PreviousWindTimer : packoffset(c18.w); - float3 DirLightColor : packoffset(c19); - float AlphaParam1 : packoffset(c19.w); - float3 AmbientColor : packoffset(c20); - float AlphaParam2 : packoffset(c20.w); - float3 ScaleMask : packoffset(c21); - float ShadowClampValue : packoffset(c21.w); + float4 cb7[1]; } -cbuffer PerFrame : register(b3) +cbuffer cb8 : register(b8) { - float4 EyePosition; - row_major float3x4 DirectionalAmbient; - float SunlightScale; - float Glossiness; - float SpecularStrength; - float SubsurfaceScatteringAmount; - bool EnableDirLightFix; - bool EnablePointLights; - float pad0; - float pad1; + float4 cb8[240]; } -#ifdef VSHADER - -#ifdef GRASS_COLLISION - #include "RunGrass\\GrassCollision.hlsli" -#endif - -cbuffer cb7 : register(b7) +cbuffer PerGeometry : register(b2) { - float4 cb7[1]; + float4 cb2[32] : packoffset(c0); + float4 FogNearColor : packoffset(c32); + float3 WindVector : packoffset(c33); + float WindTimer : packoffset(c33.w); + float3 DirLightDirection : packoffset(c34); + float PreviousWindTimer : packoffset(c34.w); + float3 DirLightColor : packoffset(c35); + float AlphaParam1 : packoffset(c35.w); + float3 AmbientColor : packoffset(c36); + float AlphaParam2 : packoffset(c36.w); + float3 ScaleMask : packoffset(c37); + float ShadowClampValue : packoffset(c37.w); } -cbuffer cb8 : register(b8) +cbuffer cb13 : register(b13) { - float4 cb8[240]; + float4 cb13[3]; } #define M_PI 3.1415925 // PI @@ -113,22 +99,35 @@ VS_OUTPUT main(VS_INPUT input) { VS_OUTPUT vsout; + float4 r0,r1,r2,r3,r4,r5,r6; + uint4 bitmask, uiDest; + float4 fDest; + + r0.x = (int)input.InstanceID & 1; + r0.x = (uint)r0.x; + r0.x = cb13[0].y * r0.x; + r0.x = (uint)r0.x; + r0.z = (uint)r0.x << 2; + r0.y = (uint)r0.x << 2; + float3x3 world3x3 = float3x3(input.InstanceData2.xyz, input.InstanceData3.xyz, float3(input.InstanceData4.x, input.InstanceData2.w, input.InstanceData3.w)); float4 msPosition = GetMSPosition(input, WindTimer, world3x3); -#ifdef GRASS_COLLISION - float3 displacement = GetDisplacedPosition(msPosition.xyz, input.Color.w); - msPosition.xyz += displacement; -#endif - - float4 projSpacePosition = mul(WorldViewProj, msPosition); - vsout.HPosition = projSpacePosition; + float4 projSpacePosition; + projSpacePosition.x = dot(cb2[r0.z+0].xyzw, msPosition.xyzw); + projSpacePosition.y = dot(cb2[r0.z+1].xyzw, msPosition.xyzw); + projSpacePosition.z = dot(cb2[r0.z+2].xyzw, msPosition.xyzw); + projSpacePosition.w = dot(cb2[r0.z+3].xyzw, msPosition.xyzw); #if defined(RENDER_DEPTH) vsout.Depth = projSpacePosition.zw; #endif + float3 instanceNormal = float3(input.InstanceData2.z, input.InstanceData3.zw); + float dirLightAngle = dot(DirLightDirection.xyz, instanceNormal); + float3 diffuseMultiplier = input.InstanceData1.www * input.Color.xyz * saturate(dirLightAngle.xxx); + float perInstanceFade = dot(cb8[(asuint(cb7[0].x) >> 2)].xyzw, M_IdentityMatrix[(asint(cb7[0].x) & 3)].xyzw); float distanceFade = 1 - saturate((length(projSpacePosition.xyz) - AlphaParam1) / AlphaParam2); @@ -139,18 +138,38 @@ VS_OUTPUT main(VS_INPUT input) vsout.TexCoord.xy = input.TexCoord.xy; vsout.TexCoord.z = FogNearColor.w; - vsout.ViewSpacePosition = mul(WorldView, msPosition).xyz; - vsout.WorldPosition = mul(World, msPosition); + vsout.WorldPosition.x = dot(cb2[r0.z+16].xyzw, msPosition.xyzw); + vsout.WorldPosition.y = dot(cb2[r0.z+17].xyzw, msPosition.xyzw); + vsout.WorldPosition.z = dot(cb2[r0.z+18].xyzw, msPosition.xyzw); + vsout.WorldPosition.w = dot(cb2[r0.z+19].xyzw, msPosition.xyzw); float4 previousMsPosition = GetMSPosition(input, PreviousWindTimer, world3x3); + + vsout.PreviousWorldPosition.x = dot(cb2[r0.z+24].xyzw, previousMsPosition.xyzw); + vsout.PreviousWorldPosition.y = dot(cb2[r0.z+25].xyzw, previousMsPosition.xyzw); + vsout.PreviousWorldPosition.z = dot(cb2[r0.z+26].xyzw, previousMsPosition.xyzw); + vsout.PreviousWorldPosition.w = dot(cb2[r0.z+27].xyzw, previousMsPosition.xyzw); + + vsout.ViewSpacePosition.x = dot(cb2[r0.z+8].xyzw, msPosition.xyzw); + vsout.ViewSpacePosition.y = dot(cb2[r0.z+9].xyzw, msPosition.xyzw); + vsout.ViewSpacePosition.z = dot(cb2[r0.z+10].xyzw, msPosition.xyzw); + + if (0 < cb13[0].y) { + r0.yz = dot(projSpacePosition, cb13[r0.x+1].xyzw); + } else { + r0.yz = float2(1,1); + } + + r0.w = 2 + -cb13[0].y; + r0.x = dot(cb13[0].zw, M_IdentityMatrix[r0.x+0].xy); + r0.xw = r0.xw * projSpacePosition.wx; + r0.x = cb13[0].y * r0.x; -#ifdef GRASS_COLLISION - previousMsPosition.xyz += displacement; -#endif - - vsout.PreviousWorldPosition = mul(PreviousWorld, previousMsPosition); + vsout.HPosition.x = r0.w * 0.5 + r0.x; + vsout.HPosition.yzw = projSpacePosition.yzw; - vsout.ViewDirectionVec.xyz = EyePosition.xyz - vsout.WorldPosition.xyz; + vsout.o7.x = r0.z; + vsout.p7.x = r0.y; // Vertex normal needs to be transformed to world-space for lighting calculations. float3 vertexNormal = input.Normal.xyz * 2.0 - 1.0; @@ -181,43 +200,55 @@ SamplerState SampShadowMaskSampler : register(s1); Texture2D TexBaseSampler : register(t0); Texture2D TexShadowMaskSampler : register(t1); -cbuffer AlphaTestRefCB : register(b11) -{ - float AlphaTestRefRS : packoffset(c0); +cbuffer AlphaTestRefCB : register(b13) +{ + float AlphaTestRefRS : packoffset(c0); } -cbuffer PerFrame : register(b12) +cbuffer cb0 : register(b0) { - row_major float4x4 ViewMatrix : packoffset(c0); - row_major float4x4 ProjMatrix : packoffset(c4); - row_major float4x4 ViewProjMatrix : packoffset(c8); - row_major float4x4 ViewProjMatrixUnjittered : packoffset(c12); - row_major float4x4 PreviousViewProjMatrixUnjittered : packoffset(c16); - row_major float4x4 InvProjMatrixUnjittered : packoffset(c20); - row_major float4x4 ProjMatrixUnjittered : packoffset(c24); - row_major float4x4 InvViewMatrix : packoffset(c28); - row_major float4x4 InvViewProjMatrix : packoffset(c32); - row_major float4x4 InvProjMatrix : packoffset(c36); - float4 CurrentPosAdjust : packoffset(c40); - float4 PreviousPosAdjust : packoffset(c41); - // notes: FirstPersonY seems 1.0 regardless of third/first person, could be LE legacy stuff - float4 GammaInvX_FirstPersonY_AlphaPassZ_CreationKitW : packoffset(c42); - float4 DynamicRes_WidthX_HeightY_PreviousWidthZ_PreviousHeightW : packoffset(c43); - float4 DynamicRes_InvWidthX_InvHeightY_WidthClampZ_HeightClampW : packoffset(c44); + float4 cb0[10]; } -struct StructuredLight +struct PerEye { - float4 color; - float4 positionWS; - float4 positionVS; - float radius; - bool shadow; - float mask; - bool active; + row_major float4x4 ScreenProj; + row_major float4x4 PreviousScreenProj; }; -StructuredBuffer lights : register(t17); +cbuffer cb12 : register(b12) +{ + float4 cb12[87]; +} + +cbuffer PerGeometry : register(b2) +{ + float4 cb2[32] : packoffset(c0); + float4 FogNearColor : packoffset(c32); + float3 WindVector : packoffset(c33); + float WindTimer : packoffset(c33.w); + float3 DirLightDirection : packoffset(c34); + float PreviousWindTimer : packoffset(c34.w); + float3 DirLightColor : packoffset(c35); + float AlphaParam1 : packoffset(c35.w); + float3 AmbientColor : packoffset(c36); + float AlphaParam2 : packoffset(c36.w); + float3 ScaleMask : packoffset(c37); + float ShadowClampValue : packoffset(c37.w); +} + +cbuffer PerFrame : register(b3) +{ + float4 EyePosition[2]; + row_major float3x4 DirectionalAmbient; + float SunlightScale; + float Glossiness; + float SpecularStrength; + float SubsurfaceScatteringAmount; + bool EnableDirLightFix; + bool EnablePointLights; + float pad[2]; +} float GetSoftLightMultiplier(float angle, float strength) { @@ -263,9 +294,18 @@ float3x3 CalculateTBN(float3 N, float3 p, float2 uv) return float3x3(T * invmax, B * invmax, N); } -#if defined(SCREEN_SPACE_SHADOWS) - #include "ScreenSpaceShadows/ShadowsPS.hlsli" -#endif +struct StructuredLight +{ + float4 color; + float4 positionWS[2]; + float radius; + bool shadow; + float mask; + bool active; +}; + +StructuredBuffer lights : register(t17); + PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) { @@ -288,6 +328,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) #if defined(RENDER_DEPTH) || defined(DO_ALPHA_TEST) float diffuseAlpha = input.VertexColor.w * baseColor.w; + if ((diffuseAlpha - AlphaTestRefRS) < 0) { discard; @@ -299,16 +340,37 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) psout.PS.xyz = input.Depth.xxx / input.Depth.yyy; psout.PS.w = diffuseAlpha; #else - float4 specColor = complex ? TexBaseSampler.Sample(SampBaseSampler, float2(input.TexCoord.x, 0.5 + input.TexCoord.y * 0.5)) : 1; float4 shadowColor = TexShadowMaskSampler.Load(int3(input.HPosition.xy, 0)); - float4 screenPosition = mul(ViewProjMatrixUnjittered, input.WorldPosition); - screenPosition.xy = screenPosition.xy / screenPosition.ww; - float4 previousScreenPosition = mul(PreviousViewProjMatrixUnjittered, input.PreviousWorldPosition); - previousScreenPosition.xy = previousScreenPosition.xy / previousScreenPosition.ww; - float2 screenMotionVector = float2(-0.5, 0.5) * (screenPosition.xy - previousScreenPosition.xy); + // Albedo + // float diffuseFraction = lerp(sunShadowMask, 1, input.AmbientColor.w); + // float3 diffuseColor = input.DiffuseColor.xyz * baseColor.xyz; + // float3 ambientColor = input.AmbientColor.xyz * baseColor.xyz; + // psout.Albedo.xyz = input.TexCoord.zzz * (diffuseColor * diffuseFraction + ambientColor); + // psout.Albedo.w = 1; + + float stereoUV = input.HPosition.x * cb0[2].xy + cb0[2].zw; + stereoUV = stereoUV * cb12[86].x; + + uint eyeIndex = (stereoUV >= 0.5) ? 1 : 0; + uint eyeOffset = eyeIndex; + uint bitmask; + bitmask = ((~(-1 << 1)) << 2) & 0xffffffff; eyeOffset = (((uint)eyeOffset<< 2) & bitmask) | ((uint)0 & ~bitmask); + + float3 screenPosition; + screenPosition.x = dot(cb12[eyeOffset+24].xyzw, input.WorldPosition); + screenPosition.y = dot(cb12[eyeOffset+25].xyzw, input.WorldPosition); + screenPosition.z = dot(cb12[eyeOffset+27].xyzw, input.WorldPosition); + screenPosition.xy = screenPosition.xy / screenPosition.zz; + + float3 previousScreenPosition; + previousScreenPosition.x = dot(cb12[eyeOffset+32].xyzw, input.PreviousWorldPosition); + previousScreenPosition.y = dot(cb12[eyeOffset+33].xyzw, input.PreviousWorldPosition); + previousScreenPosition.z = dot(cb12[eyeOffset+35].xyzw, input.PreviousWorldPosition); + previousScreenPosition.xy = previousScreenPosition.xy / previousScreenPosition.zz; + float2 screenMotionVector = float2(-0.5, 0.5) * (screenPosition.xy - previousScreenPosition.xy); psout.MotionVectors = screenMotionVector; float3 ddx = ddx_coarse(input.ViewSpacePosition); @@ -318,10 +380,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) psout.Normal.xy = float2(0.5, 0.5) + normal.xy / normalScale; psout.Normal.zw = float2(0, 0); - float3 viewDirection = normalize(input.ViewDirectionVec); float3 worldNormal = normalize(input.VertexNormal); - // Swaps direction of the backfaces otherwise they seem to get lit from the wrong direction. + // // Swaps direction of the backfaces otherwise they seem to get lit from the wrong direction. if (!frontFace) worldNormal.xyz = -worldNormal.xyz; if (complex) { @@ -330,7 +391,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) normalColor.xy = -normalColor.xy; // world-space -> tangent-space -> world-space. // This is because we don't have pre-computed tangents. - worldNormal.xyz = normalize(mul(normalColor.xyz, CalculateTBN(worldNormal.xyz, -viewDirection, input.TexCoord.xy))); + worldNormal.xyz = normalize(mul(normalColor.xyz, CalculateTBN(worldNormal.xyz, input.WorldPosition.xyz, input.TexCoord.xy))); } float3 dirLightColor = DirLightColor.xyz; @@ -341,12 +402,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) dirLightColor *= shadowColor.x; -#if defined(SCREEN_SPACE_SHADOWS) - float dirLightSShadow = PrepassScreenSpaceShadows(input.WorldPosition); - dirLightColor *= dirLightSShadow; -#endif - - float3 diffuseColor = 0; float3 specularColor = 0; @@ -358,6 +413,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) lightsDiffuseColor += dirDiffuseColor; + float3 viewDirection = normalize(-input.WorldPosition.xyz); + // Generated texture to simulate light transport. // Numerous attempts were made to use a more interesting algorithm however they were mostly fruitless. float3 subsurfaceColor = baseColor.xyz; @@ -373,30 +430,30 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) lightsSpecularColor += subsurfaceColor * GetLightSpecularInput(-DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz, Glossiness); } - float shadow = 1; - if (EnablePointLights) { + uint counter = 0; uint light_count, dummy; lights.GetDimensions(light_count, dummy); for (uint light_index = 0; light_index < light_count; light_index++) { StructuredLight light = lights[light_index]; if (light.active) { - float3 lightDirection = light.positionWS.xyz - input.WorldPosition.xyz; + float3 lightDirection = light.positionWS[eyeIndex].xyz - input.WorldPosition.xyz; float lightDist = length(lightDirection); float intensityFactor = saturate(lightDist / light.radius); float intensityMultiplier = 1 - intensityFactor * intensityFactor; if (intensityMultiplier) { + counter++; float3 lightColor = light.color.xyz; if (light.shadow) { lightColor *= shadowColor[light.mask]; } - + float3 normalizedLightDirection = normalize(lightDirection); float lightAngle = dot(worldNormal.xyz, normalizedLightDirection.xyz); - float3 lightDiffuseColor = lightColor * saturate(lightAngle.xxx); + float3 lightDiffuseColor = lightColor * saturate(lightAngle.xxx); lightDiffuseColor += subsurfaceColor * lightColor * GetSoftLightMultiplier(lightAngle, SubsurfaceScatteringAmount); lightDiffuseColor += subsurfaceColor * lightColor * saturate(-lightAngle) * SubsurfaceScatteringAmount; @@ -429,6 +486,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) psout.Albedo.w = 1; #endif + return psout; } -#endif \ No newline at end of file +#endif diff --git a/src/Features/Clustered.cpp b/src/Features/Clustered.cpp index f56ac0b94..d575f1119 100644 --- a/src/Features/Clustered.cpp +++ b/src/Features/Clustered.cpp @@ -57,27 +57,40 @@ void Clustered::UpdateLights() color.z = dimmer * niLight->GetLightRuntimeData().diffuse.blue; light.color = XMLoadFloat3(&color); - RE::NiPoint3 eyePosition{}; + + if (REL::Module::IsVR()) { - // find center of eye position - eyePosition = state->GetVRRuntimeData().posAdjust.getEye() + state->GetVRRuntimeData().posAdjust.getEye(1); - eyePosition /= 2; - } else - eyePosition = state->GetRuntimeData().posAdjust.getEye(); - - worldPos = worldPos - eyePosition; - logger::trace("Set {}light {} at ({} {} {}) because of eye ({} {} {})", bsShadowLight ? "shadow" : "", niLight->name, worldPos.x, worldPos.y, worldPos.z, - eyePosition.x, eyePosition.y, eyePosition.z); - - DirectX::XMFLOAT3 position{}; - position.x = worldPos.x; - position.y = worldPos.y; - position.z = worldPos.z; - light.positionWS = XMLoadFloat3(&position); - if (!REL::Module::IsVR()) - light.positionVS = XMVector3TransformCoord(light.positionWS, state->GetRuntimeData().cameraData.getEye().viewMat); - else - light.positionVS = XMVector3TransformCoord(light.positionWS, state->GetVRRuntimeData().cameraData.getEye().viewMat); + DirectX::XMFLOAT3 position{}; + + worldPos = worldPos - state->GetVRRuntimeData().posAdjust.getEye(); + + position.x = worldPos.x; + position.y = worldPos.y; + position.z = worldPos.z; + light.positionWS = XMLoadFloat3(&position); + + worldPos = niLight->world.translate; + + worldPos = worldPos - state->GetVRRuntimeData().posAdjust.getEye(1); + + position.x = worldPos.x; + position.y = worldPos.y; + position.z = worldPos.z; + light.positionWS2 = XMLoadFloat3(&position); + } else { + DirectX::XMFLOAT3 position{}; + + worldPos = worldPos - state->GetVRRuntimeData().posAdjust.getEye(); + + position.x = worldPos.x; + position.y = worldPos.y; + position.z = worldPos.z; + light.positionWS = XMLoadFloat3(&position); + } + + //logger::trace("Set {}light {} at ({} {} {}) because of eye ({} {} {})", bsShadowLight ? "shadow" : "", niLight->name, worldPos.x, worldPos.y, worldPos.z, + // eyePosition.x, eyePosition.y, eyePosition.z); + light.radius = niLight->GetLightRuntimeData().radius.x; light.active = true; diff --git a/src/Features/Clustered.h b/src/Features/Clustered.h index 2fc03d4c0..f77844765 100644 --- a/src/Features/Clustered.h +++ b/src/Features/Clustered.h @@ -18,15 +18,15 @@ class Clustered return &render; } - struct LightSData + struct alignas(16) LightSData { DirectX::XMVECTOR color; DirectX::XMVECTOR positionWS; - DirectX::XMVECTOR positionVS; + DirectX::XMVECTOR positionWS2; float radius; - bool shadow; + uint32_t shadow; float mask; - bool active; + uint32_t active; }; bool rendered = false; diff --git a/src/Features/GrassLighting.cpp b/src/Features/GrassLighting.cpp index 159f362a7..929d17737 100644 --- a/src/Features/GrassLighting.cpp +++ b/src/Features/GrassLighting.cpp @@ -69,16 +69,26 @@ void GrassLighting::ModifyGrass(const RE::BSShader*, const uint32_t descriptor) auto& position = accumulator->GetRuntimeData().eyePosition; auto state = RE::BSGraphics::RendererShadowState::GetSingleton(); - RE::NiPoint3 eyePosition{}; + if (REL::Module::IsVR()) { - // find center of eye position - eyePosition = state->GetVRRuntimeData().posAdjust.getEye() + state->GetVRRuntimeData().posAdjust.getEye(1); - eyePosition /= 2; - } else - eyePosition = state->GetRuntimeData().posAdjust.getEye(); - perFrameData.EyePosition.x = position.x - eyePosition.x; - perFrameData.EyePosition.y = position.y - eyePosition.y; - perFrameData.EyePosition.z = position.z - eyePosition.z; + RE::NiPoint3 eyePosition = state->GetVRRuntimeData().posAdjust.getEye(); + + perFrameData.EyePosition.x = position.x - eyePosition.x; + perFrameData.EyePosition.y = position.y - eyePosition.y; + perFrameData.EyePosition.z = position.z - eyePosition.z; + + eyePosition = state->GetVRRuntimeData().posAdjust.getEye(1); + perFrameData.EyePosition2.x = position.x - eyePosition.x; + perFrameData.EyePosition2.y = position.y - eyePosition.y; + perFrameData.EyePosition2.z = position.z - eyePosition.z; + } else { + RE::NiPoint3 eyePosition = state->GetRuntimeData().posAdjust.getEye(); + + perFrameData.EyePosition.x = position.x - eyePosition.x; + perFrameData.EyePosition.y = position.y - eyePosition.y; + perFrameData.EyePosition.z = position.z - eyePosition.z; + + } auto manager = RE::ImageSpaceManager::GetSingleton(); perFrameData.SunlightScale = manager->data.baseData.hdr.sunlightScale; diff --git a/src/Features/GrassLighting.h b/src/Features/GrassLighting.h index d4785906e..7f21195b9 100644 --- a/src/Features/GrassLighting.h +++ b/src/Features/GrassLighting.h @@ -26,11 +26,11 @@ struct GrassLighting : Feature struct alignas(16) PerFrame { DirectX::XMFLOAT4 EyePosition; + DirectX::XMFLOAT4 EyePosition2; DirectX::XMFLOAT3X4 DirectionalAmbient; float SunlightScale; Settings Settings; - float pad0; - float pad1; + float pad[2]; }; Settings settings; From 8268c600ccafc9670d2795b223c0130b62d98c9c Mon Sep 17 00:00:00 2001 From: Tim <15017472+doodlum@users.noreply.github.com> Date: Tue, 11 Jul 2023 00:22:59 +0100 Subject: [PATCH 02/14] Separated features list for flatrim and VR --- src/Feature.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Feature.cpp b/src/Feature.cpp index 83e232183..4c876a202 100644 --- a/src/Feature.cpp +++ b/src/Feature.cpp @@ -77,5 +77,10 @@ const std::vector& Feature::GetFeatureList() ExtendedMaterials::GetSingleton(), WaterBlending::GetSingleton() }; - return features; + + static std::vector featuresVR = { + GrassLighting::GetSingleton() + }; + + return REL::Module::IsVR() ? featuresVR : features; } \ No newline at end of file From 9ce5b4d3d4c7fa502030bb6850848a2ed8c88db5 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Tue, 11 Jul 2023 01:51:10 -0700 Subject: [PATCH 03/14] Add VR preprocessor def for GrassShader This is an initial attempt to combine flat and VR grasshaders. However, the flat code does not appear to work and still needs to be fixed. --- features/Grass Lighting/Shaders/RunGrass.hlsl | 322 +++++++++++++----- src/Features/Clustered.cpp | 38 +-- src/Features/Clustered.h | 3 +- src/Features/GrassLighting.cpp | 79 +++-- src/Features/GrassLighting.h | 12 + src/ShaderCache.cpp | 4 + 6 files changed, 301 insertions(+), 157 deletions(-) diff --git a/features/Grass Lighting/Shaders/RunGrass.hlsl b/features/Grass Lighting/Shaders/RunGrass.hlsl index 34fb73b73..0602b982d 100644 --- a/features/Grass Lighting/Shaders/RunGrass.hlsl +++ b/features/Grass Lighting/Shaders/RunGrass.hlsl @@ -8,7 +8,10 @@ struct VS_INPUT float4 InstanceData2 : TEXCOORD5; float4 InstanceData3 : TEXCOORD6; float4 InstanceData4 : TEXCOORD7; - uint InstanceID : SV_InstanceID0; +#ifdef VR + uint InstanceID: SV_INSTANCEID; +#endif // VR + }; struct VS_OUTPUT @@ -16,49 +19,106 @@ struct VS_OUTPUT float4 HPosition : SV_POSITION0; float4 VertexColor : COLOR0; float3 TexCoord : TEXCOORD0; - float3 ViewSpacePosition : TEXCOORD2; + float3 ViewSpacePosition : +#if !defined(VR) + TEXCOORD1; +#else + TEXCOORD2; +#endif // !VR #if defined(RENDER_DEPTH) - float2 Depth : TEXCOORD3; -#endif + float2 Depth : +#if !defined(VR) + TEXCOORD2; +#else + TEXCOORD3; +#endif // !VR +#endif // RENDER_DEPTH float4 WorldPosition : POSITION1; float4 PreviousWorldPosition : POSITION2; +#if !defined(VR) + float3 ViewDirectionVec : POSITION3; +#endif // !VR float3 VertexNormal : POSITION4; - float o7 : SV_ClipDistance0; - float p7 : SV_CullDistance0; +#ifdef VR + float ClipDistance : SV_ClipDistance0; + float CullDistance : SV_CullDistance0; +#endif // !VR }; -#ifdef VSHADER - -cbuffer cb7 : register(b7) +// Constant Buffers (Flat and VR) +cbuffer PerGeometry : register(b2) { - float4 cb7[1]; +#if !defined(VR) + row_major float4x4 WorldViewProj : packoffset(c0); + row_major float4x4 WorldView : packoffset(c4); + row_major float4x4 World : packoffset(c8); + row_major float4x4 PreviousWorld : packoffset(c12); + float4 FogNearColor : packoffset(c16); + float3 WindVector : packoffset(c17); + float WindTimer : packoffset(c17.w); + float3 DirLightDirection : packoffset(c18); + float PreviousWindTimer : packoffset(c18.w); + float3 DirLightColor : packoffset(c19); + float AlphaParam1 : packoffset(c19.w); + float3 AmbientColor : packoffset(c20); + float AlphaParam2 : packoffset(c20.w); + float3 ScaleMask : packoffset(c21); + float ShadowClampValue : packoffset(c21.w); +#else + float4 cb2[32] : packoffset(c0); + float4 FogNearColor : packoffset(c32); + float3 WindVector : packoffset(c33); + float WindTimer : packoffset(c33.w); + float3 DirLightDirection : packoffset(c34); + float PreviousWindTimer : packoffset(c34.w); + float3 DirLightColor : packoffset(c35); + float AlphaParam1 : packoffset(c35.w); + float3 AmbientColor : packoffset(c36); + float AlphaParam2 : packoffset(c36.w); + float3 ScaleMask : packoffset(c37); + float ShadowClampValue : packoffset(c37.w); +#endif // !VR } -cbuffer cb8 : register(b8) +cbuffer PerFrame : register(b3) { - float4 cb8[240]; +#if !defined(VR) + float4 EyePosition; +#else + float4 EyePosition[2]; +#endif //!VR + row_major float3x4 DirectionalAmbient; + float SunlightScale; + float Glossiness; + float SpecularStrength; + float SubsurfaceScatteringAmount; + bool EnableDirLightFix; + bool EnablePointLights; + float pad[2]; } -cbuffer PerGeometry : register(b2) +#ifdef VSHADER + +#ifdef GRASS_COLLISION + #include "RunGrass\\GrassCollision.hlsli" +#endif + +cbuffer cb7 : register(b7) +{ + float4 cb7[1]; +} + +cbuffer cb8 : register(b8) { - float4 cb2[32] : packoffset(c0); - float4 FogNearColor : packoffset(c32); - float3 WindVector : packoffset(c33); - float WindTimer : packoffset(c33.w); - float3 DirLightDirection : packoffset(c34); - float PreviousWindTimer : packoffset(c34.w); - float3 DirLightColor : packoffset(c35); - float AlphaParam1 : packoffset(c35.w); - float3 AmbientColor : packoffset(c36); - float AlphaParam2 : packoffset(c36.w); - float3 ScaleMask : packoffset(c37); - float ShadowClampValue : packoffset(c37.w); + float4 cb8[240]; } +#ifdef VR cbuffer cb13 : register(b13) { float4 cb13[3]; } +#endif // VR #define M_PI 3.1415925 // PI #define M_2PI 6.283185 // PI * 2 @@ -99,6 +159,20 @@ VS_OUTPUT main(VS_INPUT input) { VS_OUTPUT vsout; +#ifdef VR +/* +https://docs.google.com/presentation/d/19x9XDjUvkW_9gsfsMQzt3hZbRNziVsoCEHOn4AercAc/htmlpresent +This section looks like this code +Matrix WorldToEyeClipMatrix[2] // computed from SDK +Vector4 EyeClipEdge[2]={(-1,0,0,1), (1,0,0,1)} +float EyeOffsetScale[2]={0.5,-0.5} +uint eyeIndex = instanceID & 1 // use low bit as eye index. +Vector4 clipPos = worldPos * WorldToEyeClipMatrix[eyeIndex] +cullDistanceOut.x = clipDistanceOut.x = clipPos · EyeClipEdge[eyeIndex] +clipPos.x *= 0.5; // shrink to half of the screen +clipPos.x += EyeOffsetScale[eyeIndex] * clipPos.w; // scoot left or right. +clipPositionOut = clipPos +*/ float4 r0,r1,r2,r3,r4,r5,r6; uint4 bitmask, uiDest; float4 fDest; @@ -109,25 +183,37 @@ VS_OUTPUT main(VS_INPUT input) r0.x = (uint)r0.x; r0.z = (uint)r0.x << 2; r0.y = (uint)r0.x << 2; +#endif // VR float3x3 world3x3 = float3x3(input.InstanceData2.xyz, input.InstanceData3.xyz, float3(input.InstanceData4.x, input.InstanceData2.w, input.InstanceData3.w)); float4 msPosition = GetMSPosition(input, WindTimer, world3x3); +#ifdef GRASS_COLLISION + float3 displacement = GetDisplacedPosition(msPosition.xyz, input.Color.w); + msPosition.xyz += displacement; +#endif + +#if !defined(VR) + float4 projSpacePosition = mul(WorldViewProj, msPosition); + vsout.HPosition = projSpacePosition; +#else float4 projSpacePosition; projSpacePosition.x = dot(cb2[r0.z+0].xyzw, msPosition.xyzw); projSpacePosition.y = dot(cb2[r0.z+1].xyzw, msPosition.xyzw); projSpacePosition.z = dot(cb2[r0.z+2].xyzw, msPosition.xyzw); projSpacePosition.w = dot(cb2[r0.z+3].xyzw, msPosition.xyzw); +#endif // !VR #if defined(RENDER_DEPTH) vsout.Depth = projSpacePosition.zw; -#endif +#endif // RENDER_DEPTH +#ifdef VR float3 instanceNormal = float3(input.InstanceData2.z, input.InstanceData3.zw); float dirLightAngle = dot(DirLightDirection.xyz, instanceNormal); float3 diffuseMultiplier = input.InstanceData1.www * input.Color.xyz * saturate(dirLightAngle.xxx); - +#endif // VR float perInstanceFade = dot(cb8[(asuint(cb7[0].x) >> 2)].xyzw, M_IdentityMatrix[(asint(cb7[0].x) & 3)].xyzw); float distanceFade = 1 - saturate((length(projSpacePosition.xyz) - AlphaParam1) / AlphaParam2); @@ -138,28 +224,55 @@ VS_OUTPUT main(VS_INPUT input) vsout.TexCoord.xy = input.TexCoord.xy; vsout.TexCoord.z = FogNearColor.w; +#if !defined(VR) + vsout.ViewSpacePosition = mul(WorldView, msPosition).xyz; + vsout.WorldPosition = mul(World, msPosition); +#else + vsout.ViewSpacePosition.x = dot(cb2[r0.z+8].xyzw, msPosition.xyzw); + vsout.ViewSpacePosition.y = dot(cb2[r0.z+9].xyzw, msPosition.xyzw); + vsout.ViewSpacePosition.z = dot(cb2[r0.z+10].xyzw, msPosition.xyzw); + vsout.WorldPosition.x = dot(cb2[r0.z+16].xyzw, msPosition.xyzw); vsout.WorldPosition.y = dot(cb2[r0.z+17].xyzw, msPosition.xyzw); vsout.WorldPosition.z = dot(cb2[r0.z+18].xyzw, msPosition.xyzw); vsout.WorldPosition.w = dot(cb2[r0.z+19].xyzw, msPosition.xyzw); +#endif // !VR float4 previousMsPosition = GetMSPosition(input, PreviousWindTimer, world3x3); - + +#ifdef GRASS_COLLISION + previousMsPosition.xyz += displacement; +#endif // GRASS_COLLISION + +#if !defined(VR) + vsout.PreviousWorldPosition = mul(PreviousWorld, previousMsPosition); + + vsout.ViewDirectionVec.xyz = EyePosition.xyz - vsout.WorldPosition.xyz; +#else vsout.PreviousWorldPosition.x = dot(cb2[r0.z+24].xyzw, previousMsPosition.xyzw); vsout.PreviousWorldPosition.y = dot(cb2[r0.z+25].xyzw, previousMsPosition.xyzw); vsout.PreviousWorldPosition.z = dot(cb2[r0.z+26].xyzw, previousMsPosition.xyzw); vsout.PreviousWorldPosition.w = dot(cb2[r0.z+27].xyzw, previousMsPosition.xyzw); - vsout.ViewSpacePosition.x = dot(cb2[r0.z+8].xyzw, msPosition.xyzw); - vsout.ViewSpacePosition.y = dot(cb2[r0.z+9].xyzw, msPosition.xyzw); - vsout.ViewSpacePosition.z = dot(cb2[r0.z+10].xyzw, msPosition.xyzw); - +/* +https://docs.google.com/presentation/d/19x9XDjUvkW_9gsfsMQzt3hZbRNziVsoCEHOn4AercAc/htmlpresent +This section looks like this code +Matrix WorldToEyeClipMatrix[2] // computed from SDK +Vector4 EyeClipEdge[2]={(-1,0,0,1), (1,0,0,1)} +float EyeOffsetScale[2]={0.5,-0.5} +uint eyeIndex = instanceID & 1 // use low bit as eye index. +Vector4 clipPos = worldPos * WorldToEyeClipMatrix[eyeIndex] +cullDistanceOut.x = clipDistanceOut.x = clipPos · EyeClipEdge[eyeIndex] +clipPos.x *= 0.5; // shrink to half of the screen +clipPos.x += EyeOffsetScale[eyeIndex] * clipPos.w; // scoot left or right. +clipPositionOut = clipPos +*/ if (0 < cb13[0].y) { r0.yz = dot(projSpacePosition, cb13[r0.x+1].xyzw); } else { r0.yz = float2(1,1); } - + r0.w = 2 + -cb13[0].y; r0.x = dot(cb13[0].zw, M_IdentityMatrix[r0.x+0].xy); r0.xw = r0.xw * projSpacePosition.wx; @@ -168,8 +281,9 @@ VS_OUTPUT main(VS_INPUT input) vsout.HPosition.x = r0.w * 0.5 + r0.x; vsout.HPosition.yzw = projSpacePosition.yzw; - vsout.o7.x = r0.z; - vsout.p7.x = r0.y; + vsout.ClipDistance.x = r0.z; + vsout.CullDistance.x = r0.y; +#endif // !VR // Vertex normal needs to be transformed to world-space for lighting calculations. float3 vertexNormal = input.Normal.xyz * 2.0 - 1.0; @@ -178,7 +292,7 @@ VS_OUTPUT main(VS_INPUT input) return vsout; } -#endif +#endif // VSHADER typedef VS_OUTPUT PS_INPUT; @@ -190,7 +304,7 @@ struct PS_OUTPUT float4 Albedo : SV_Target0; float2 MotionVectors : SV_Target1; float4 Normal : SV_Target2; -#endif +#endif // RENDER_DEPTH }; #ifdef PSHADER @@ -200,56 +314,70 @@ SamplerState SampShadowMaskSampler : register(s1); Texture2D TexBaseSampler : register(t0); Texture2D TexShadowMaskSampler : register(t1); -cbuffer AlphaTestRefCB : register(b13) -{ - float AlphaTestRefRS : packoffset(c0); -} -cbuffer cb0 : register(b0) -{ - float4 cb0[10]; -} +#ifdef VR struct PerEye { row_major float4x4 ScreenProj; row_major float4x4 PreviousScreenProj; }; -cbuffer cb12 : register(b12) +cbuffer cb0 : register(b0) { - float4 cb12[87]; + float4 cb0[10]; } -cbuffer PerGeometry : register(b2) +#endif // VR + +cbuffer PerFrame : register(b12) { - float4 cb2[32] : packoffset(c0); - float4 FogNearColor : packoffset(c32); - float3 WindVector : packoffset(c33); - float WindTimer : packoffset(c33.w); - float3 DirLightDirection : packoffset(c34); - float PreviousWindTimer : packoffset(c34.w); - float3 DirLightColor : packoffset(c35); - float AlphaParam1 : packoffset(c35.w); - float3 AmbientColor : packoffset(c36); - float AlphaParam2 : packoffset(c36.w); - float3 ScaleMask : packoffset(c37); - float ShadowClampValue : packoffset(c37.w); +#if !defined(VR) + row_major float4x4 ViewMatrix : packoffset(c0); + row_major float4x4 ProjMatrix : packoffset(c4); + row_major float4x4 ViewProjMatrix : packoffset(c8); + row_major float4x4 ViewProjMatrixUnjittered : packoffset(c12); + row_major float4x4 PreviousViewProjMatrixUnjittered : packoffset(c16); + row_major float4x4 InvProjMatrixUnjittered : packoffset(c20); + row_major float4x4 ProjMatrixUnjittered : packoffset(c24); + row_major float4x4 InvViewMatrix : packoffset(c28); + row_major float4x4 InvViewProjMatrix : packoffset(c32); + row_major float4x4 InvProjMatrix : packoffset(c36); + float4 CurrentPosAdjust : packoffset(c40); + float4 PreviousPosAdjust : packoffset(c41); + // notes: FirstPersonY seems 1.0 regardless of third/first person, could be LE legacy stuff + float4 GammaInvX_FirstPersonY_AlphaPassZ_CreationKitW : packoffset(c42); + float4 DynamicRes_WidthX_HeightY_PreviousWidthZ_PreviousHeightW : packoffset(c43); + float4 DynamicRes_InvWidthX_InvHeightY_WidthClampZ_HeightClampW : packoffset(c44); +#else + //VR is float4 PerFrame[87]; VR original used for eye position in PerFrame[86].x + float4 cb12[87]; +#endif // !VR } -cbuffer PerFrame : register(b3) -{ - float4 EyePosition[2]; - row_major float3x4 DirectionalAmbient; - float SunlightScale; - float Glossiness; - float SpecularStrength; - float SubsurfaceScatteringAmount; - bool EnableDirLightFix; - bool EnablePointLights; - float pad[2]; +cbuffer AlphaTestRefCB : register( +#if !defined(VR) + b11 +#else + b13 +#endif // !VR +) +{ + float AlphaTestRefRS : packoffset(c0); } +struct StructuredLight +{ + float4 color; + float4 positionWS[2]; + float radius; + bool shadow; + float mask; + bool active; +}; + +StructuredBuffer lights : register(t17); + float GetSoftLightMultiplier(float angle, float strength) { float softLightParam = saturate((strength + angle) / (1 + strength)); @@ -294,18 +422,9 @@ float3x3 CalculateTBN(float3 N, float3 p, float2 uv) return float3x3(T * invmax, B * invmax, N); } -struct StructuredLight -{ - float4 color; - float4 positionWS[2]; - float radius; - bool shadow; - float mask; - bool active; -}; - -StructuredBuffer lights : register(t17); - +#if defined(SCREEN_SPACE_SHADOWS) + #include "ScreenSpaceShadows/ShadowsPS.hlsli" +#endif PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) { @@ -328,18 +447,18 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) #if defined(RENDER_DEPTH) || defined(DO_ALPHA_TEST) float diffuseAlpha = input.VertexColor.w * baseColor.w; - if ((diffuseAlpha - AlphaTestRefRS) < 0) { discard; } -#endif +#endif // RENDER_DEPTH | DO_ALPHA_TEST #if defined(RENDER_DEPTH) // Depth psout.PS.xyz = input.Depth.xxx / input.Depth.yyy; psout.PS.w = diffuseAlpha; #else + float4 specColor = complex ? TexBaseSampler.Sample(SampBaseSampler, float2(input.TexCoord.x, 0.5 + input.TexCoord.y * 0.5)) : 1; float4 shadowColor = TexShadowMaskSampler.Load(int3(input.HPosition.xy, 0)); @@ -350,6 +469,13 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) // psout.Albedo.xyz = input.TexCoord.zzz * (diffuseColor * diffuseFraction + ambientColor); // psout.Albedo.w = 1; +#if !defined(VR) + float4 screenPosition = mul(ViewProjMatrixUnjittered, input.WorldPosition); + screenPosition.xy = screenPosition.xy / screenPosition.ww; + float4 previousScreenPosition = mul(PreviousViewProjMatrixUnjittered, input.PreviousWorldPosition); + previousScreenPosition.xy = previousScreenPosition.xy / previousScreenPosition.ww; + uint eyeIndex = 0; +#else float stereoUV = input.HPosition.x * cb0[2].xy + cb0[2].zw; stereoUV = stereoUV * cb12[86].x; @@ -369,8 +495,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) previousScreenPosition.y = dot(cb12[eyeOffset+33].xyzw, input.PreviousWorldPosition); previousScreenPosition.z = dot(cb12[eyeOffset+35].xyzw, input.PreviousWorldPosition); previousScreenPosition.xy = previousScreenPosition.xy / previousScreenPosition.zz; +#endif // !VR float2 screenMotionVector = float2(-0.5, 0.5) * (screenPosition.xy - previousScreenPosition.xy); + psout.MotionVectors = screenMotionVector; float3 ddx = ddx_coarse(input.ViewSpacePosition); @@ -380,9 +508,14 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) psout.Normal.xy = float2(0.5, 0.5) + normal.xy / normalScale; psout.Normal.zw = float2(0, 0); +#if !defined(VR) + float3 viewDirection = normalize(input.ViewDirectionVec); +#else + float3 viewDirection = normalize(-input.WorldPosition.xyz); +#endif // !VR float3 worldNormal = normalize(input.VertexNormal); - // // Swaps direction of the backfaces otherwise they seem to get lit from the wrong direction. + // Swaps direction of the backfaces otherwise they seem to get lit from the wrong direction. if (!frontFace) worldNormal.xyz = -worldNormal.xyz; if (complex) { @@ -391,7 +524,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) normalColor.xy = -normalColor.xy; // world-space -> tangent-space -> world-space. // This is because we don't have pre-computed tangents. +#if !defined(VR) + worldNormal.xyz = normalize(mul(normalColor.xyz, CalculateTBN(worldNormal.xyz, -viewDirection, input.TexCoord.xy))); +#else worldNormal.xyz = normalize(mul(normalColor.xyz, CalculateTBN(worldNormal.xyz, input.WorldPosition.xyz, input.TexCoord.xy))); +#endif // !VR } float3 dirLightColor = DirLightColor.xyz; @@ -402,6 +539,12 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) dirLightColor *= shadowColor.x; +#if defined(SCREEN_SPACE_SHADOWS) + float dirLightSShadow = PrepassScreenSpaceShadows(input.WorldPosition); + dirLightColor *= dirLightSShadow; +#endif // !SCREEN_SPACE_SHADOWS + + float3 diffuseColor = 0; float3 specularColor = 0; @@ -413,8 +556,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) lightsDiffuseColor += dirDiffuseColor; - float3 viewDirection = normalize(-input.WorldPosition.xyz); - // Generated texture to simulate light transport. // Numerous attempts were made to use a more interesting algorithm however they were mostly fruitless. float3 subsurfaceColor = baseColor.xyz; @@ -485,8 +626,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) psout.Albedo.xyz = color; psout.Albedo.w = 1; -#endif - +#endif // RENDER_DEPTH return psout; } -#endif +#endif // PSHADER \ No newline at end of file diff --git a/src/Features/Clustered.cpp b/src/Features/Clustered.cpp index d575f1119..3d9f741a0 100644 --- a/src/Features/Clustered.cpp +++ b/src/Features/Clustered.cpp @@ -57,35 +57,17 @@ void Clustered::UpdateLights() color.z = dimmer * niLight->GetLightRuntimeData().diffuse.blue; light.color = XMLoadFloat3(&color); - - - if (REL::Module::IsVR()) { - DirectX::XMFLOAT3 position{}; - - worldPos = worldPos - state->GetVRRuntimeData().posAdjust.getEye(); - - position.x = worldPos.x; - position.y = worldPos.y; - position.z = worldPos.z; - light.positionWS = XMLoadFloat3(&position); - - worldPos = niLight->world.translate; - - worldPos = worldPos - state->GetVRRuntimeData().posAdjust.getEye(1); - - position.x = worldPos.x; - position.y = worldPos.y; - position.z = worldPos.z; - light.positionWS2 = XMLoadFloat3(&position); - } else { + for (int eyeIndex = 0; eyeIndex < (!REL::Module::IsVR() ? 1 : 2); eyeIndex++) { DirectX::XMFLOAT3 position{}; - - worldPos = worldPos - state->GetVRRuntimeData().posAdjust.getEye(); - - position.x = worldPos.x; - position.y = worldPos.y; - position.z = worldPos.z; - light.positionWS = XMLoadFloat3(&position); + auto eyePos = !REL::Module::IsVR() ? + state->GetRuntimeData().posAdjust.getEye(eyeIndex) : + state->GetVRRuntimeData().posAdjust.getEye(eyeIndex); + auto adjustedWorldPos = worldPos - eyePos; + + position.x = adjustedWorldPos.x; + position.y = adjustedWorldPos.y; + position.z = adjustedWorldPos.z; + light.positionWS[eyeIndex] = XMLoadFloat3(&position); } //logger::trace("Set {}light {} at ({} {} {}) because of eye ({} {} {})", bsShadowLight ? "shadow" : "", niLight->name, worldPos.x, worldPos.y, worldPos.z, diff --git a/src/Features/Clustered.h b/src/Features/Clustered.h index f77844765..5156697ab 100644 --- a/src/Features/Clustered.h +++ b/src/Features/Clustered.h @@ -21,8 +21,7 @@ class Clustered struct alignas(16) LightSData { DirectX::XMVECTOR color; - DirectX::XMVECTOR positionWS; - DirectX::XMVECTOR positionWS2; + DirectX::XMVECTOR positionWS[2]; float radius; uint32_t shadow; float mask; diff --git a/src/Features/GrassLighting.cpp b/src/Features/GrassLighting.cpp index 929d17737..df077aea7 100644 --- a/src/Features/GrassLighting.cpp +++ b/src/Features/GrassLighting.cpp @@ -52,52 +52,59 @@ void GrassLighting::DrawSettings() } } -void GrassLighting::ModifyGrass(const RE::BSShader*, const uint32_t descriptor) +void GrassLighting::ProcessFrame(PerFrame* perFrameData, PerFrameVR* perFrameDataVR) { - const auto technique = descriptor & 0b1111; - if (technique != static_cast(GrassShaderTechniques::RenderDepth)) { - if (updatePerFrame) { - PerFrame perFrameData{}; - ZeroMemory(&perFrameData, sizeof(perFrameData)); - - auto& shaderState = RE::BSShaderManager::State::GetSingleton(); - RE::NiTransform& dalcTransform = shaderState.directionalAmbientTransform; - - Util::StoreTransform3x4NoScale(perFrameData.DirectionalAmbient, dalcTransform); - - auto accumulator = RE::BSGraphics::BSShaderAccumulator::GetCurrentAccumulator(); - auto& position = accumulator->GetRuntimeData().eyePosition; - auto state = RE::BSGraphics::RendererShadowState::GetSingleton(); + auto& shaderState = RE::BSShaderManager::State::GetSingleton(); + RE::NiTransform& dalcTransform = shaderState.directionalAmbientTransform; + auto accumulator = RE::BSGraphics::BSShaderAccumulator::GetCurrentAccumulator(); + auto& position = accumulator->GetRuntimeData().eyePosition; + auto state = RE::BSGraphics::RendererShadowState::GetSingleton(); + auto manager = RE::ImageSpaceManager::GetSingleton(); + if (REL::Module::IsVR()) { + ZeroMemory(perFrameDataVR, sizeof(perFrameDataVR)); + Util::StoreTransform3x4NoScale(perFrameDataVR->DirectionalAmbient, dalcTransform); + RE::NiPoint3 eyePosition = state->GetVRRuntimeData().posAdjust.getEye(); + perFrameDataVR->EyePosition.x = position.x - eyePosition.x; + perFrameDataVR->EyePosition.y = position.y - eyePosition.y; + perFrameDataVR->EyePosition.z = position.z - eyePosition.z; - if (REL::Module::IsVR()) { - RE::NiPoint3 eyePosition = state->GetVRRuntimeData().posAdjust.getEye(); + eyePosition = state->GetVRRuntimeData().posAdjust.getEye(1); + perFrameDataVR->EyePosition2.x = position.x - eyePosition.x; + perFrameDataVR->EyePosition2.y = position.y - eyePosition.y; + perFrameDataVR->EyePosition2.z = position.z - eyePosition.z; - perFrameData.EyePosition.x = position.x - eyePosition.x; - perFrameData.EyePosition.y = position.y - eyePosition.y; - perFrameData.EyePosition.z = position.z - eyePosition.z; + perFrameDataVR->SunlightScale = manager->data.baseData.hdr.sunlightScale; - eyePosition = state->GetVRRuntimeData().posAdjust.getEye(1); - perFrameData.EyePosition2.x = position.x - eyePosition.x; - perFrameData.EyePosition2.y = position.y - eyePosition.y; - perFrameData.EyePosition2.z = position.z - eyePosition.z; - } else { - RE::NiPoint3 eyePosition = state->GetRuntimeData().posAdjust.getEye(); + perFrameDataVR->Settings = settings; - perFrameData.EyePosition.x = position.x - eyePosition.x; - perFrameData.EyePosition.y = position.y - eyePosition.y; - perFrameData.EyePosition.z = position.z - eyePosition.z; + perFrame->Update(perFrameDataVR); - } + } else { + ZeroMemory(perFrameData, sizeof(perFrameData)); + Util::StoreTransform3x4NoScale(perFrameData->DirectionalAmbient, dalcTransform); + RE::NiPoint3 eyePosition = state->GetRuntimeData().posAdjust.getEye(); - auto manager = RE::ImageSpaceManager::GetSingleton(); - perFrameData.SunlightScale = manager->data.baseData.hdr.sunlightScale; + perFrameData->EyePosition.x = position.x - eyePosition.x; + perFrameData->EyePosition.y = position.y - eyePosition.y; + perFrameData->EyePosition.z = position.z - eyePosition.z; + perFrameData->SunlightScale = manager->data.baseData.hdr.sunlightScale; - perFrameData.Settings = settings; + perFrameData->Settings = settings; - perFrame->Update(perFrameData); + perFrame->Update(perFrameData); + } - updatePerFrame = false; + updatePerFrame = false; +} +void GrassLighting::ModifyGrass(const RE::BSShader*, const uint32_t descriptor) +{ + const auto technique = descriptor & 0b1111; + if (technique != static_cast(GrassShaderTechniques::RenderDepth)) { + PerFrame perFrameData{}; + PerFrameVR perFrameDataVR{}; + if (updatePerFrame) { + ProcessFrame(&perFrameData, &perFrameDataVR); } Clustered::GetSingleton()->Bind(true); @@ -135,7 +142,7 @@ void GrassLighting::Save(json& o_json) void GrassLighting::SetupResources() { - perFrame = new ConstantBuffer(ConstantBufferDesc()); + perFrame = !REL::Module::IsVR() ? new ConstantBuffer(ConstantBufferDesc()) : new ConstantBuffer(ConstantBufferDesc()); } void GrassLighting::Reset() diff --git a/src/Features/GrassLighting.h b/src/Features/GrassLighting.h index 7f21195b9..a26d8b608 100644 --- a/src/Features/GrassLighting.h +++ b/src/Features/GrassLighting.h @@ -24,6 +24,15 @@ struct GrassLighting : Feature }; struct alignas(16) PerFrame + { + DirectX::XMFLOAT4 EyePosition; + DirectX::XMFLOAT3X4 DirectionalAmbient; + float SunlightScale; + Settings Settings; + float pad[2]; + }; + + struct alignas(16) PerFrameVR { DirectX::XMFLOAT4 EyePosition; DirectX::XMFLOAT4 EyePosition2; @@ -46,4 +55,7 @@ struct GrassLighting : Feature virtual void Load(json& o_json); virtual void Save(json& o_json); + +private: + void ProcessFrame(PerFrame* perFrameData, PerFrameVR* perFrameDataVR); }; diff --git a/src/ShaderCache.cpp b/src/ShaderCache.cpp index 34ccecde7..8cde41d05 100644 --- a/src/ShaderCache.cpp +++ b/src/ShaderCache.cpp @@ -282,6 +282,10 @@ namespace SIE ++defines; } + if (REL::Module::IsVR()) { + defines[0] = { "VR", nullptr }; + ++defines; + } defines[0] = { nullptr, nullptr }; } From 979684bdc93bbb3425126ac0e5d8eb44b7d2359c Mon Sep 17 00:00:00 2001 From: Tim <15017472+doodlum@users.noreply.github.com> Date: Tue, 11 Jul 2023 13:53:09 +0100 Subject: [PATCH 04/14] Temporary workaround for constant buffers not working --- package/Shaders/RunGrass.hlsl | 540 +++++++++++++++++++++++++++++---- src/Features/GrassLighting.cpp | 4 +- 2 files changed, 483 insertions(+), 61 deletions(-) diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index a62930f2b..05916480a 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -1,3 +1,5 @@ +#define VR + struct VS_INPUT { float4 Position : POSITION0; @@ -8,42 +10,107 @@ struct VS_INPUT float4 InstanceData2 : TEXCOORD5; float4 InstanceData3 : TEXCOORD6; float4 InstanceData4 : TEXCOORD7; +#ifdef VR + uint InstanceID: SV_INSTANCEID; +#endif // VR + }; struct VS_OUTPUT { float4 HPosition : SV_POSITION0; - float4 DiffuseColor : COLOR0; + float4 VertexColor : COLOR0; float3 TexCoord : TEXCOORD0; - float4 AmbientColor : TEXCOORD1; - float3 ViewSpacePosition : TEXCOORD2; + float3 ViewSpacePosition : +#if !defined(VR) + TEXCOORD1; +#else + TEXCOORD2; +#endif // !VR #if defined(RENDER_DEPTH) - float2 Depth : TEXCOORD3; -#endif + float2 Depth : +#if !defined(VR) + TEXCOORD2; +#else + TEXCOORD3; +#endif // !VR +#endif // RENDER_DEPTH float4 WorldPosition : POSITION1; float4 PreviousWorldPosition : POSITION2; +#if !defined(VR) + float3 ViewDirectionVec : POSITION3; +#endif // !VR + float3 VertexNormal : POSITION4; +#ifdef VR + float ClipDistance : SV_ClipDistance0; + float CullDistance : SV_CullDistance0; +#endif // !VR }; -#ifdef VSHADER -cbuffer PerGeometry : register(b2) +// Constant Buffers (Flat and VR) +cbuffer PerGeometry : register( + #ifdef VSHADER + b2 + #else + b9 + #endif + ) { +#if !defined(VR) row_major float4x4 WorldViewProj : packoffset(c0); row_major float4x4 WorldView : packoffset(c4); row_major float4x4 World : packoffset(c8); row_major float4x4 PreviousWorld : packoffset(c12); - float4 FogNearColor : packoffset(c16); - float3 WindVector : packoffset(c17); - float WindTimer : packoffset(c17.w); - float3 DirLightDirection : packoffset(c18); - float PreviousWindTimer : packoffset(c18.w); - float3 DirLightColor : packoffset(c19); - float AlphaParam1 : packoffset(c19.w); - float3 AmbientColor : packoffset(c20); - float AlphaParam2 : packoffset(c20.w); - float3 ScaleMask : packoffset(c21); - float ShadowClampValue : packoffset(c21.w); + float4 FogNearColor : packoffset(c16); + float3 WindVector : packoffset(c17); + float WindTimer : packoffset(c17.w); + float3 DirLightDirection : packoffset(c18); + float PreviousWindTimer : packoffset(c18.w); + float3 DirLightColor : packoffset(c19); + float AlphaParam1 : packoffset(c19.w); + float3 AmbientColor : packoffset(c20); + float AlphaParam2 : packoffset(c20.w); + float3 ScaleMask : packoffset(c21); + float ShadowClampValue : packoffset(c21.w); +#else + float4 cb2[32] : packoffset(c0); + float4 FogNearColor : packoffset(c32); + float3 WindVector : packoffset(c33); + float WindTimer : packoffset(c33.w); + float3 DirLightDirection : packoffset(c34); + float PreviousWindTimer : packoffset(c34.w); + float3 DirLightColor : packoffset(c35); + float AlphaParam1 : packoffset(c35.w); + float3 AmbientColor : packoffset(c36); + float AlphaParam2 : packoffset(c36.w); + float3 ScaleMask : packoffset(c37); + float ShadowClampValue : packoffset(c37.w); +#endif // !VR } +cbuffer PerFrame : register(b10) +{ +#if !defined(VR) + float4 EyePosition; +#else + float4 EyePosition[2]; +#endif //!VR + row_major float3x4 DirectionalAmbient; + float SunlightScale; + float Glossiness; + float SpecularStrength; + float SubsurfaceScatteringAmount; + bool EnableDirLightFix; + bool EnablePointLights; + float pad[2]; +} + +#ifdef VSHADER + +#ifdef GRASS_COLLISION + #include "RunGrass\\GrassCollision.hlsli" +#endif + cbuffer cb7 : register(b7) { float4 cb7[1]; @@ -54,6 +121,13 @@ cbuffer cb8 : register(b8) float4 cb8[240]; } +#ifdef VR +cbuffer cb13 : register(b13) +{ + float4 cb13[3]; +} +#endif // VR + #define M_PI 3.1415925 // PI #define M_2PI 6.283185 // PI * 2 @@ -65,7 +139,7 @@ const static float4x4 M_IdentityMatrix = { 0, 0, 0, 1 } }; -float4 GetMSPosition(VS_INPUT input, float windTimer) +float4 GetMSPosition(VS_INPUT input, float windTimer, float3x3 world3x3) { float windAngle = 0.4 * ((input.InstanceData1.x + input.InstanceData1.y) * -0.0078125 + windTimer); float windAngleSin, windAngleCos; @@ -75,20 +149,15 @@ float4 GetMSPosition(VS_INPUT input, float windTimer) float windTmp1 = sin(M_PI * windAngleSin); float windTmp2 = sin(M_2PI * windAngleSin); float windPower = WindVector.z * (((windTmp1 + windTmp2) * 0.3 + windTmp3) * - (0.5 * (input.Color.w * input.Color.w))); + (0.5 * (input.Color.w * input.Color.w))); float3 inputPosition = input.Position.xyz * (input.InstanceData4.yyy * ScaleMask.xyz + float3(1, 1, 1)); - - float3 instancePosition; - instancePosition.z = dot( - float3(input.InstanceData4.x, input.InstanceData2.w, input.InstanceData3.w), inputPosition); - instancePosition.x = dot(input.InstanceData2.xyz, inputPosition); - instancePosition.y = dot(input.InstanceData3.xyz, inputPosition); + float3 InstanceData4 = mul(world3x3, inputPosition); float3 windVector = float3(WindVector.xy, 0); float4 msPosition; - msPosition.xyz = input.InstanceData1.xyz + (windVector * windPower + instancePosition); + msPosition.xyz = input.InstanceData1.xyz + (windVector * windPower + InstanceData4); msPosition.w = 1; return msPosition; @@ -98,41 +167,140 @@ VS_OUTPUT main(VS_INPUT input) { VS_OUTPUT vsout; - float4 msPosition = GetMSPosition(input, WindTimer); +#ifdef VR +/* +https://docs.google.com/presentation/d/19x9XDjUvkW_9gsfsMQzt3hZbRNziVsoCEHOn4AercAc/htmlpresent +This section looks like this code +Matrix WorldToEyeClipMatrix[2] // computed from SDK +Vector4 EyeClipEdge[2]={(-1,0,0,1), (1,0,0,1)} +float EyeOffsetScale[2]={0.5,-0.5} +uint eyeIndex = instanceID & 1 // use low bit as eye index. +Vector4 clipPos = worldPos * WorldToEyeClipMatrix[eyeIndex] +cullDistanceOut.x = clipDistanceOut.x = clipPos · EyeClipEdge[eyeIndex] +clipPos.x *= 0.5; // shrink to half of the screen +clipPos.x += EyeOffsetScale[eyeIndex] * clipPos.w; // scoot left or right. +clipPositionOut = clipPos +*/ + float4 r0,r1,r2,r3,r4,r5,r6; + uint4 bitmask, uiDest; + float4 fDest; + + r0.x = (int)input.InstanceID & 1; + r0.x = (uint)r0.x; + r0.x = cb13[0].y * r0.x; + r0.x = (uint)r0.x; + r0.z = (uint)r0.x << 2; + r0.y = (uint)r0.x << 2; +#endif // VR + + float3x3 world3x3 = float3x3(input.InstanceData2.xyz, input.InstanceData3.xyz, float3(input.InstanceData4.x, input.InstanceData2.w, input.InstanceData3.w)); + + float4 msPosition = GetMSPosition(input, WindTimer, world3x3); + +#ifdef GRASS_COLLISION + float3 displacement = GetDisplacedPosition(msPosition.xyz, input.Color.w); + msPosition.xyz += displacement; +#endif +#if !defined(VR) float4 projSpacePosition = mul(WorldViewProj, msPosition); vsout.HPosition = projSpacePosition; +#else + float4 projSpacePosition; + projSpacePosition.x = dot(cb2[r0.z+0].xyzw, msPosition.xyzw); + projSpacePosition.y = dot(cb2[r0.z+1].xyzw, msPosition.xyzw); + projSpacePosition.z = dot(cb2[r0.z+2].xyzw, msPosition.xyzw); + projSpacePosition.w = dot(cb2[r0.z+3].xyzw, msPosition.xyzw); +#endif // !VR #if defined(RENDER_DEPTH) vsout.Depth = projSpacePosition.zw; -#endif +#endif // RENDER_DEPTH +#ifdef VR float3 instanceNormal = float3(input.InstanceData2.z, input.InstanceData3.zw); float dirLightAngle = dot(DirLightDirection.xyz, instanceNormal); float3 diffuseMultiplier = input.InstanceData1.www * input.Color.xyz * saturate(dirLightAngle.xxx); - +#endif // VR float perInstanceFade = dot(cb8[(asuint(cb7[0].x) >> 2)].xyzw, M_IdentityMatrix[(asint(cb7[0].x) & 3)].xyzw); float distanceFade = 1 - saturate((length(projSpacePosition.xyz) - AlphaParam1) / AlphaParam2); - vsout.DiffuseColor.xyz = DirLightColor.xyz * diffuseMultiplier; - vsout.DiffuseColor.w = distanceFade * perInstanceFade; + // Note: input.Color.w is used for wind speed + vsout.VertexColor.xyz = input.Color.xyz * input.InstanceData1.www; + vsout.VertexColor.w = distanceFade * perInstanceFade; vsout.TexCoord.xy = input.TexCoord.xy; vsout.TexCoord.z = FogNearColor.w; - vsout.AmbientColor.xyz = input.InstanceData1.www * (AmbientColor.xyz * input.Color.xyz); - vsout.AmbientColor.w = ShadowClampValue; - +#if !defined(VR) vsout.ViewSpacePosition = mul(WorldView, msPosition).xyz; vsout.WorldPosition = mul(World, msPosition); +#else + vsout.ViewSpacePosition.x = dot(cb2[r0.z+8].xyzw, msPosition.xyzw); + vsout.ViewSpacePosition.y = dot(cb2[r0.z+9].xyzw, msPosition.xyzw); + vsout.ViewSpacePosition.z = dot(cb2[r0.z+10].xyzw, msPosition.xyzw); - float4 previousMsPosition = GetMSPosition(input, PreviousWindTimer); + vsout.WorldPosition.x = dot(cb2[r0.z+16].xyzw, msPosition.xyzw); + vsout.WorldPosition.y = dot(cb2[r0.z+17].xyzw, msPosition.xyzw); + vsout.WorldPosition.z = dot(cb2[r0.z+18].xyzw, msPosition.xyzw); + vsout.WorldPosition.w = dot(cb2[r0.z+19].xyzw, msPosition.xyzw); +#endif // !VR + float4 previousMsPosition = GetMSPosition(input, PreviousWindTimer, world3x3); + +#ifdef GRASS_COLLISION + previousMsPosition.xyz += displacement; +#endif // GRASS_COLLISION + +#if !defined(VR) vsout.PreviousWorldPosition = mul(PreviousWorld, previousMsPosition); + vsout.ViewDirectionVec.xyz = EyePosition.xyz - vsout.WorldPosition.xyz; +#else + vsout.PreviousWorldPosition.x = dot(cb2[r0.z+24].xyzw, previousMsPosition.xyzw); + vsout.PreviousWorldPosition.y = dot(cb2[r0.z+25].xyzw, previousMsPosition.xyzw); + vsout.PreviousWorldPosition.z = dot(cb2[r0.z+26].xyzw, previousMsPosition.xyzw); + vsout.PreviousWorldPosition.w = dot(cb2[r0.z+27].xyzw, previousMsPosition.xyzw); + +/* +https://docs.google.com/presentation/d/19x9XDjUvkW_9gsfsMQzt3hZbRNziVsoCEHOn4AercAc/htmlpresent +This section looks like this code +Matrix WorldToEyeClipMatrix[2] // computed from SDK +Vector4 EyeClipEdge[2]={(-1,0,0,1), (1,0,0,1)} +float EyeOffsetScale[2]={0.5,-0.5} +uint eyeIndex = instanceID & 1 // use low bit as eye index. +Vector4 clipPos = worldPos * WorldToEyeClipMatrix[eyeIndex] +cullDistanceOut.x = clipDistanceOut.x = clipPos · EyeClipEdge[eyeIndex] +clipPos.x *= 0.5; // shrink to half of the screen +clipPos.x += EyeOffsetScale[eyeIndex] * clipPos.w; // scoot left or right. +clipPositionOut = clipPos +*/ + if (0 < cb13[0].y) { + r0.yz = dot(projSpacePosition, cb13[r0.x+1].xyzw); + } else { + r0.yz = float2(1,1); + } + + r0.w = 2 + -cb13[0].y; + r0.x = dot(cb13[0].zw, M_IdentityMatrix[r0.x+0].xy); + r0.xw = r0.xw * projSpacePosition.wx; + r0.x = cb13[0].y * r0.x; + + vsout.HPosition.x = r0.w * 0.5 + r0.x; + vsout.HPosition.yzw = projSpacePosition.yzw; + + vsout.ClipDistance.x = r0.z; + vsout.CullDistance.x = r0.y; +#endif // !VR + + // Vertex normal needs to be transformed to world-space for lighting calculations. + float3 vertexNormal = input.Normal.xyz * 2.0 - 1.0; + vertexNormal = mul(world3x3, vertexNormal); + vsout.VertexNormal.xyz = vertexNormal; + return vsout; } -#endif +#endif // VSHADER typedef VS_OUTPUT PS_INPUT; @@ -144,7 +312,7 @@ struct PS_OUTPUT float4 Albedo : SV_Target0; float2 MotionVectors : SV_Target1; float4 Normal : SV_Target2; -#endif +#endif // RENDER_DEPTH }; #ifdef PSHADER @@ -154,51 +322,189 @@ SamplerState SampShadowMaskSampler : register(s1); Texture2D TexBaseSampler : register(t0); Texture2D TexShadowMaskSampler : register(t1); -cbuffer AlphaTestRefCB : register(b11) + + +#ifdef VR +struct PerEye +{ + row_major float4x4 ScreenProj; + row_major float4x4 PreviousScreenProj; +}; + +cbuffer cb0 : register(b0) +{ + float4 cb0[10]; +} + +#endif // VR + +cbuffer PerFrame : register(b12) +{ +#if !defined(VR) + row_major float4x4 ViewMatrix : packoffset(c0); + row_major float4x4 ProjMatrix : packoffset(c4); + row_major float4x4 ViewProjMatrix : packoffset(c8); + row_major float4x4 ViewProjMatrixUnjittered : packoffset(c12); + row_major float4x4 PreviousViewProjMatrixUnjittered : packoffset(c16); + row_major float4x4 InvProjMatrixUnjittered : packoffset(c20); + row_major float4x4 ProjMatrixUnjittered : packoffset(c24); + row_major float4x4 InvViewMatrix : packoffset(c28); + row_major float4x4 InvViewProjMatrix : packoffset(c32); + row_major float4x4 InvProjMatrix : packoffset(c36); + float4 CurrentPosAdjust : packoffset(c40); + float4 PreviousPosAdjust : packoffset(c41); + // notes: FirstPersonY seems 1.0 regardless of third/first person, could be LE legacy stuff + float4 GammaInvX_FirstPersonY_AlphaPassZ_CreationKitW : packoffset(c42); + float4 DynamicRes_WidthX_HeightY_PreviousWidthZ_PreviousHeightW : packoffset(c43); + float4 DynamicRes_InvWidthX_InvHeightY_WidthClampZ_HeightClampW : packoffset(c44); +#else + //VR is float4 PerFrame[87]; VR original used for eye position in PerFrame[86].x + float4 cb12[87]; +#endif // !VR +} + +cbuffer AlphaTestRefCB : register( +#if !defined(VR) + b11 +#else + b13 +#endif // !VR +) { float AlphaTestRefRS : packoffset(c0); } -cbuffer PerFrame : register(b12) +struct StructuredLight { - float4 UnknownPerFrame1[12] : packoffset(c0); - row_major float4x4 ScreenProj : packoffset(c12); - row_major float4x4 PreviousScreenProj : packoffset(c16); + float4 color; + float4 positionWS[2]; + float radius; + bool shadow; + float mask; + bool active; }; -PS_OUTPUT main(PS_INPUT input) +StructuredBuffer lights : register(t17); + +float GetSoftLightMultiplier(float angle, float strength) +{ + float softLightParam = saturate((strength + angle) / (1 + strength)); + float arg1 = (softLightParam * softLightParam) * (3 - 2 * softLightParam); + float clampedAngle = saturate(angle); + float arg2 = (clampedAngle * clampedAngle) * (3 - 2 * clampedAngle); + float softLigtMul = saturate(arg1 - arg2); + return softLigtMul; +} + +float3 GetLightSpecularInput(float3 L, float3 V, float3 N, float3 lightColor, float shininess) +{ + float3 H = normalize(V + L); + float HdotN = saturate(dot(H, N)); + + float lightColorMultiplier = exp2(shininess * log2(HdotN)); + return lightColor * lightColorMultiplier.xxx; +} + +float3 TransformNormal(float3 normal) +{ + return normal * 2 + -1.0.xxx; +} + +// http://www.thetenthplanet.de/archives/1180 +float3x3 CalculateTBN(float3 N, float3 p, float2 uv) +{ + // get edge vectors of the pixel triangle + float3 dp1 = ddx_coarse(p); + float3 dp2 = ddy_coarse(p); + float2 duv1 = ddx_coarse(uv); + float2 duv2 = ddy_coarse(uv); + + // solve the linear system + float3 dp2perp = cross(dp2, N); + float3 dp1perp = cross(N, dp1); + float3 T = dp2perp * duv1.x + dp1perp * duv2.x; + float3 B = dp2perp * duv1.y + dp1perp * duv2.y; + + // construct a scale-invariant frame + float invmax = rsqrt(max(dot(T, T), dot(B, B))); + return float3x3(T * invmax, B * invmax, N); +} + +#if defined(SCREEN_SPACE_SHADOWS) + #include "ScreenSpaceShadows/ShadowsPS.hlsli" +#endif + +PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) { PS_OUTPUT psout; - float4 baseColor = TexBaseSampler.Sample(SampBaseSampler, input.TexCoord.xy); + float x; + float y; + TexBaseSampler.GetDimensions(x, y); -#if defined(RENDER_DEPTH) || defined(DO_ALPHA_TEST) - float diffuseAlpha = input.DiffuseColor.w * baseColor.w; + bool complex = x != y; + float4 baseColor; + if (complex) { + baseColor = TexBaseSampler.Sample(SampBaseSampler, float2(input.TexCoord.x, input.TexCoord.y * 0.5)); + } + else + { + baseColor = TexBaseSampler.Sample(SampBaseSampler, input.TexCoord.xy); + } + +#if defined(RENDER_DEPTH) || defined(DO_ALPHA_TEST) + float diffuseAlpha = input.VertexColor.w * baseColor.w; if ((diffuseAlpha - AlphaTestRefRS) < 0) { discard; } -#endif +#endif // RENDER_DEPTH | DO_ALPHA_TEST #if defined(RENDER_DEPTH) // Depth psout.PS.xyz = input.Depth.xxx / input.Depth.yyy; psout.PS.w = diffuseAlpha; #else - float sunShadowMask = TexShadowMaskSampler.Load(int3(input.HPosition.xy, 0)).x; - // Albedo - float diffuseFraction = lerp(sunShadowMask, 1, input.AmbientColor.w); - float3 diffuseColor = input.DiffuseColor.xyz * baseColor.xyz; - float3 ambientColor = input.AmbientColor.xyz * baseColor.xyz; - psout.Albedo.xyz = input.TexCoord.zzz * (diffuseColor * diffuseFraction + ambientColor); - psout.Albedo.w = 1; + float4 specColor = complex ? TexBaseSampler.Sample(SampBaseSampler, float2(input.TexCoord.x, 0.5 + input.TexCoord.y * 0.5)) : 1; + float4 shadowColor = TexShadowMaskSampler.Load(int3(input.HPosition.xy, 0)); - float4 screenPosition = mul(ScreenProj, input.WorldPosition); + // Albedo + // float diffuseFraction = lerp(sunShadowMask, 1, input.AmbientColor.w); + // float3 diffuseColor = input.DiffuseColor.xyz * baseColor.xyz; + // float3 ambientColor = input.AmbientColor.xyz * baseColor.xyz; + // psout.Albedo.xyz = input.TexCoord.zzz * (diffuseColor * diffuseFraction + ambientColor); + // psout.Albedo.w = 1; + +#if !defined(VR) + float4 screenPosition = mul(ViewProjMatrixUnjittered, input.WorldPosition); screenPosition.xy = screenPosition.xy / screenPosition.ww; - float4 previousScreenPosition = mul(PreviousScreenProj, input.PreviousWorldPosition); + float4 previousScreenPosition = mul(PreviousViewProjMatrixUnjittered, input.PreviousWorldPosition); previousScreenPosition.xy = previousScreenPosition.xy / previousScreenPosition.ww; + uint eyeIndex = 0; +#else + float stereoUV = input.HPosition.x * cb0[2].xy + cb0[2].zw; + stereoUV = stereoUV * cb12[86].x; + + uint eyeIndex = (stereoUV >= 0.5) ? 1 : 0; + uint eyeOffset = eyeIndex; + uint bitmask; + bitmask = ((~(-1 << 1)) << 2) & 0xffffffff; eyeOffset = (((uint)eyeOffset<< 2) & bitmask) | ((uint)0 & ~bitmask); + + float3 screenPosition; + screenPosition.x = dot(cb12[eyeOffset+24].xyzw, input.WorldPosition); + screenPosition.y = dot(cb12[eyeOffset+25].xyzw, input.WorldPosition); + screenPosition.z = dot(cb12[eyeOffset+27].xyzw, input.WorldPosition); + screenPosition.xy = screenPosition.xy / screenPosition.zz; + + float3 previousScreenPosition; + previousScreenPosition.x = dot(cb12[eyeOffset+32].xyzw, input.PreviousWorldPosition); + previousScreenPosition.y = dot(cb12[eyeOffset+33].xyzw, input.PreviousWorldPosition); + previousScreenPosition.z = dot(cb12[eyeOffset+35].xyzw, input.PreviousWorldPosition); + previousScreenPosition.xy = previousScreenPosition.xy / previousScreenPosition.zz; +#endif // !VR + float2 screenMotionVector = float2(-0.5, 0.5) * (screenPosition.xy - previousScreenPosition.xy); psout.MotionVectors = screenMotionVector; @@ -209,8 +515,124 @@ PS_OUTPUT main(PS_INPUT input) float normalScale = max(1.0 / 1000.0, sqrt(normal.z * -8 + 8)); psout.Normal.xy = float2(0.5, 0.5) + normal.xy / normalScale; psout.Normal.zw = float2(0, 0); -#endif +#if !defined(VR) + float3 viewDirection = normalize(input.ViewDirectionVec); +#else + float3 viewDirection = normalize(-input.WorldPosition.xyz); +#endif // !VR + float3 worldNormal = normalize(input.VertexNormal); + + // Swaps direction of the backfaces otherwise they seem to get lit from the wrong direction. + if (!frontFace) worldNormal.xyz = -worldNormal.xyz; + + if (complex) { + float3 normalColor = float4(TransformNormal(specColor.xyz), 1); + // Inverting x as well as y seems to look more correct. + normalColor.xy = -normalColor.xy; + // world-space -> tangent-space -> world-space. + // This is because we don't have pre-computed tangents. +#if !defined(VR) + worldNormal.xyz = normalize(mul(normalColor.xyz, CalculateTBN(worldNormal.xyz, -viewDirection, input.TexCoord.xy))); +#else + worldNormal.xyz = normalize(mul(normalColor.xyz, CalculateTBN(worldNormal.xyz, input.WorldPosition.xyz, input.TexCoord.xy))); +#endif // !VR + } + + float3 dirLightColor = DirLightColor.xyz; + if (EnableDirLightFix) + { + // dirLightColor *= SunlightScale; + } + + dirLightColor *= shadowColor.x; + +#if defined(SCREEN_SPACE_SHADOWS) + float dirLightSShadow = PrepassScreenSpaceShadows(input.WorldPosition); + dirLightColor *= dirLightSShadow; +#endif // !SCREEN_SPACE_SHADOWS + + + float3 diffuseColor = 0; + float3 specularColor = 0; + + float3 lightsDiffuseColor = 0; + float3 lightsSpecularColor = 0; + + float dirLightAngle = dot(worldNormal.xyz, DirLightDirection.xyz); + float3 dirDiffuseColor = dirLightColor * saturate(dirLightAngle); + + lightsDiffuseColor += dirDiffuseColor; + + // Generated texture to simulate light transport. + // Numerous attempts were made to use a more interesting algorithm however they were mostly fruitless. + float3 subsurfaceColor = baseColor.xyz; + + // Applies lighting across the whole surface apart from what is already lit. + lightsDiffuseColor += subsurfaceColor * dirLightColor * GetSoftLightMultiplier(dirLightAngle, SubsurfaceScatteringAmount); + // Applies lighting from the opposite direction. Does not account for normals perpendicular to the light source. + lightsDiffuseColor += subsurfaceColor * dirLightColor * saturate(-dirLightAngle) * SubsurfaceScatteringAmount; + + if (complex) { + lightsSpecularColor = GetLightSpecularInput(DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz, Glossiness); + // Not physically accurate but grass will otherwise look too flat. + lightsSpecularColor += subsurfaceColor * GetLightSpecularInput(-DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz, Glossiness); + } + + if (true) { + uint light_count, dummy; + lights.GetDimensions(light_count, dummy); + for (uint light_index = 0; light_index < light_count; light_index++) + { + StructuredLight light = lights[light_index]; + if (light.active) { + float3 lightDirection = light.positionWS[eyeIndex].xyz - input.WorldPosition.xyz; + float lightDist = length(lightDirection); + float intensityFactor = saturate(lightDist / light.radius); + float intensityMultiplier = 1 - intensityFactor * intensityFactor; + if (intensityMultiplier) { + float3 lightColor = light.color.xyz; + + if (light.shadow) { + lightColor *= shadowColor[light.mask]; + } + + float3 normalizedLightDirection = normalize(lightDirection); + + float lightAngle = dot(worldNormal.xyz, normalizedLightDirection.xyz); + float3 lightDiffuseColor = lightColor * saturate(lightAngle.xxx); + + lightDiffuseColor += subsurfaceColor * lightColor * GetSoftLightMultiplier(lightAngle, SubsurfaceScatteringAmount); + lightDiffuseColor += subsurfaceColor * lightColor * saturate(-lightAngle) * SubsurfaceScatteringAmount; + + if (complex) { + lightsSpecularColor += GetLightSpecularInput(normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, Glossiness) * intensityMultiplier; + lightsSpecularColor += subsurfaceColor * GetLightSpecularInput(-normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, Glossiness) * intensityMultiplier; + } + + lightsDiffuseColor += lightDiffuseColor * intensityMultiplier; + } + } + } + } + + float3 directionalAmbientColor = mul(DirectionalAmbient, float4(worldNormal.xyz, 1)); + lightsDiffuseColor += AmbientColor; + + diffuseColor += lightsDiffuseColor; + + float3 color = diffuseColor * baseColor.xyz * input.VertexColor.xyz; + + if (complex) { + specularColor += lightsSpecularColor; + specularColor *= specColor.w * SpecularStrength; + color.xyz += specularColor; + } + + psout.Albedo.xyz = color; + psout.Albedo.w = 1; + +#endif // RENDER_DEPTH return psout; } -#endif +#endif // PSHADER \ No newline at end of file diff --git a/src/Features/GrassLighting.cpp b/src/Features/GrassLighting.cpp index df077aea7..d6bc6596c 100644 --- a/src/Features/GrassLighting.cpp +++ b/src/Features/GrassLighting.cpp @@ -113,8 +113,8 @@ void GrassLighting::ModifyGrass(const RE::BSShader*, const uint32_t descriptor) ID3D11Buffer* buffers[2]; context->VSGetConstantBuffers(2, 1, buffers); // buffers[0] buffers[1] = perFrame->CB(); - context->VSSetConstantBuffers(2, ARRAYSIZE(buffers), buffers); - context->PSSetConstantBuffers(2, ARRAYSIZE(buffers), buffers); + // context->VSSetConstantBuffers(2, ARRAYSIZE(buffers), buffers); + context->PSSetConstantBuffers(9, ARRAYSIZE(buffers), buffers); } } From e18642d5cf9f984e51be7d158c0800b716860ec7 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Wed, 12 Jul 2023 00:43:08 -0700 Subject: [PATCH 05/14] Revert "Temporary workaround for constant buffers not working" This reverts commit 979684bdc93bbb3425126ac0e5d8eb44b7d2359c. --- package/Shaders/RunGrass.hlsl | 540 ++++----------------------------- src/Features/GrassLighting.cpp | 4 +- 2 files changed, 61 insertions(+), 483 deletions(-) diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index 05916480a..a62930f2b 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -1,5 +1,3 @@ -#define VR - struct VS_INPUT { float4 Position : POSITION0; @@ -10,107 +8,42 @@ struct VS_INPUT float4 InstanceData2 : TEXCOORD5; float4 InstanceData3 : TEXCOORD6; float4 InstanceData4 : TEXCOORD7; -#ifdef VR - uint InstanceID: SV_INSTANCEID; -#endif // VR - }; struct VS_OUTPUT { float4 HPosition : SV_POSITION0; - float4 VertexColor : COLOR0; + float4 DiffuseColor : COLOR0; float3 TexCoord : TEXCOORD0; - float3 ViewSpacePosition : -#if !defined(VR) - TEXCOORD1; -#else - TEXCOORD2; -#endif // !VR + float4 AmbientColor : TEXCOORD1; + float3 ViewSpacePosition : TEXCOORD2; #if defined(RENDER_DEPTH) - float2 Depth : -#if !defined(VR) - TEXCOORD2; -#else - TEXCOORD3; -#endif // !VR -#endif // RENDER_DEPTH + float2 Depth : TEXCOORD3; +#endif float4 WorldPosition : POSITION1; float4 PreviousWorldPosition : POSITION2; -#if !defined(VR) - float3 ViewDirectionVec : POSITION3; -#endif // !VR - float3 VertexNormal : POSITION4; -#ifdef VR - float ClipDistance : SV_ClipDistance0; - float CullDistance : SV_CullDistance0; -#endif // !VR }; -// Constant Buffers (Flat and VR) -cbuffer PerGeometry : register( - #ifdef VSHADER - b2 - #else - b9 - #endif - ) +#ifdef VSHADER +cbuffer PerGeometry : register(b2) { -#if !defined(VR) row_major float4x4 WorldViewProj : packoffset(c0); row_major float4x4 WorldView : packoffset(c4); row_major float4x4 World : packoffset(c8); row_major float4x4 PreviousWorld : packoffset(c12); - float4 FogNearColor : packoffset(c16); - float3 WindVector : packoffset(c17); - float WindTimer : packoffset(c17.w); - float3 DirLightDirection : packoffset(c18); - float PreviousWindTimer : packoffset(c18.w); - float3 DirLightColor : packoffset(c19); - float AlphaParam1 : packoffset(c19.w); - float3 AmbientColor : packoffset(c20); - float AlphaParam2 : packoffset(c20.w); - float3 ScaleMask : packoffset(c21); - float ShadowClampValue : packoffset(c21.w); -#else - float4 cb2[32] : packoffset(c0); - float4 FogNearColor : packoffset(c32); - float3 WindVector : packoffset(c33); - float WindTimer : packoffset(c33.w); - float3 DirLightDirection : packoffset(c34); - float PreviousWindTimer : packoffset(c34.w); - float3 DirLightColor : packoffset(c35); - float AlphaParam1 : packoffset(c35.w); - float3 AmbientColor : packoffset(c36); - float AlphaParam2 : packoffset(c36.w); - float3 ScaleMask : packoffset(c37); - float ShadowClampValue : packoffset(c37.w); -#endif // !VR + float4 FogNearColor : packoffset(c16); + float3 WindVector : packoffset(c17); + float WindTimer : packoffset(c17.w); + float3 DirLightDirection : packoffset(c18); + float PreviousWindTimer : packoffset(c18.w); + float3 DirLightColor : packoffset(c19); + float AlphaParam1 : packoffset(c19.w); + float3 AmbientColor : packoffset(c20); + float AlphaParam2 : packoffset(c20.w); + float3 ScaleMask : packoffset(c21); + float ShadowClampValue : packoffset(c21.w); } -cbuffer PerFrame : register(b10) -{ -#if !defined(VR) - float4 EyePosition; -#else - float4 EyePosition[2]; -#endif //!VR - row_major float3x4 DirectionalAmbient; - float SunlightScale; - float Glossiness; - float SpecularStrength; - float SubsurfaceScatteringAmount; - bool EnableDirLightFix; - bool EnablePointLights; - float pad[2]; -} - -#ifdef VSHADER - -#ifdef GRASS_COLLISION - #include "RunGrass\\GrassCollision.hlsli" -#endif - cbuffer cb7 : register(b7) { float4 cb7[1]; @@ -121,13 +54,6 @@ cbuffer cb8 : register(b8) float4 cb8[240]; } -#ifdef VR -cbuffer cb13 : register(b13) -{ - float4 cb13[3]; -} -#endif // VR - #define M_PI 3.1415925 // PI #define M_2PI 6.283185 // PI * 2 @@ -139,7 +65,7 @@ const static float4x4 M_IdentityMatrix = { 0, 0, 0, 1 } }; -float4 GetMSPosition(VS_INPUT input, float windTimer, float3x3 world3x3) +float4 GetMSPosition(VS_INPUT input, float windTimer) { float windAngle = 0.4 * ((input.InstanceData1.x + input.InstanceData1.y) * -0.0078125 + windTimer); float windAngleSin, windAngleCos; @@ -149,15 +75,20 @@ float4 GetMSPosition(VS_INPUT input, float windTimer, float3x3 world3x3) float windTmp1 = sin(M_PI * windAngleSin); float windTmp2 = sin(M_2PI * windAngleSin); float windPower = WindVector.z * (((windTmp1 + windTmp2) * 0.3 + windTmp3) * - (0.5 * (input.Color.w * input.Color.w))); + (0.5 * (input.Color.w * input.Color.w))); float3 inputPosition = input.Position.xyz * (input.InstanceData4.yyy * ScaleMask.xyz + float3(1, 1, 1)); - float3 InstanceData4 = mul(world3x3, inputPosition); + + float3 instancePosition; + instancePosition.z = dot( + float3(input.InstanceData4.x, input.InstanceData2.w, input.InstanceData3.w), inputPosition); + instancePosition.x = dot(input.InstanceData2.xyz, inputPosition); + instancePosition.y = dot(input.InstanceData3.xyz, inputPosition); float3 windVector = float3(WindVector.xy, 0); float4 msPosition; - msPosition.xyz = input.InstanceData1.xyz + (windVector * windPower + InstanceData4); + msPosition.xyz = input.InstanceData1.xyz + (windVector * windPower + instancePosition); msPosition.w = 1; return msPosition; @@ -167,140 +98,41 @@ VS_OUTPUT main(VS_INPUT input) { VS_OUTPUT vsout; -#ifdef VR -/* -https://docs.google.com/presentation/d/19x9XDjUvkW_9gsfsMQzt3hZbRNziVsoCEHOn4AercAc/htmlpresent -This section looks like this code -Matrix WorldToEyeClipMatrix[2] // computed from SDK -Vector4 EyeClipEdge[2]={(-1,0,0,1), (1,0,0,1)} -float EyeOffsetScale[2]={0.5,-0.5} -uint eyeIndex = instanceID & 1 // use low bit as eye index. -Vector4 clipPos = worldPos * WorldToEyeClipMatrix[eyeIndex] -cullDistanceOut.x = clipDistanceOut.x = clipPos · EyeClipEdge[eyeIndex] -clipPos.x *= 0.5; // shrink to half of the screen -clipPos.x += EyeOffsetScale[eyeIndex] * clipPos.w; // scoot left or right. -clipPositionOut = clipPos -*/ - float4 r0,r1,r2,r3,r4,r5,r6; - uint4 bitmask, uiDest; - float4 fDest; - - r0.x = (int)input.InstanceID & 1; - r0.x = (uint)r0.x; - r0.x = cb13[0].y * r0.x; - r0.x = (uint)r0.x; - r0.z = (uint)r0.x << 2; - r0.y = (uint)r0.x << 2; -#endif // VR - - float3x3 world3x3 = float3x3(input.InstanceData2.xyz, input.InstanceData3.xyz, float3(input.InstanceData4.x, input.InstanceData2.w, input.InstanceData3.w)); - - float4 msPosition = GetMSPosition(input, WindTimer, world3x3); - -#ifdef GRASS_COLLISION - float3 displacement = GetDisplacedPosition(msPosition.xyz, input.Color.w); - msPosition.xyz += displacement; -#endif + float4 msPosition = GetMSPosition(input, WindTimer); -#if !defined(VR) float4 projSpacePosition = mul(WorldViewProj, msPosition); vsout.HPosition = projSpacePosition; -#else - float4 projSpacePosition; - projSpacePosition.x = dot(cb2[r0.z+0].xyzw, msPosition.xyzw); - projSpacePosition.y = dot(cb2[r0.z+1].xyzw, msPosition.xyzw); - projSpacePosition.z = dot(cb2[r0.z+2].xyzw, msPosition.xyzw); - projSpacePosition.w = dot(cb2[r0.z+3].xyzw, msPosition.xyzw); -#endif // !VR #if defined(RENDER_DEPTH) vsout.Depth = projSpacePosition.zw; -#endif // RENDER_DEPTH +#endif -#ifdef VR float3 instanceNormal = float3(input.InstanceData2.z, input.InstanceData3.zw); float dirLightAngle = dot(DirLightDirection.xyz, instanceNormal); float3 diffuseMultiplier = input.InstanceData1.www * input.Color.xyz * saturate(dirLightAngle.xxx); -#endif // VR + float perInstanceFade = dot(cb8[(asuint(cb7[0].x) >> 2)].xyzw, M_IdentityMatrix[(asint(cb7[0].x) & 3)].xyzw); float distanceFade = 1 - saturate((length(projSpacePosition.xyz) - AlphaParam1) / AlphaParam2); - // Note: input.Color.w is used for wind speed - vsout.VertexColor.xyz = input.Color.xyz * input.InstanceData1.www; - vsout.VertexColor.w = distanceFade * perInstanceFade; + vsout.DiffuseColor.xyz = DirLightColor.xyz * diffuseMultiplier; + vsout.DiffuseColor.w = distanceFade * perInstanceFade; vsout.TexCoord.xy = input.TexCoord.xy; vsout.TexCoord.z = FogNearColor.w; -#if !defined(VR) + vsout.AmbientColor.xyz = input.InstanceData1.www * (AmbientColor.xyz * input.Color.xyz); + vsout.AmbientColor.w = ShadowClampValue; + vsout.ViewSpacePosition = mul(WorldView, msPosition).xyz; vsout.WorldPosition = mul(World, msPosition); -#else - vsout.ViewSpacePosition.x = dot(cb2[r0.z+8].xyzw, msPosition.xyzw); - vsout.ViewSpacePosition.y = dot(cb2[r0.z+9].xyzw, msPosition.xyzw); - vsout.ViewSpacePosition.z = dot(cb2[r0.z+10].xyzw, msPosition.xyzw); - vsout.WorldPosition.x = dot(cb2[r0.z+16].xyzw, msPosition.xyzw); - vsout.WorldPosition.y = dot(cb2[r0.z+17].xyzw, msPosition.xyzw); - vsout.WorldPosition.z = dot(cb2[r0.z+18].xyzw, msPosition.xyzw); - vsout.WorldPosition.w = dot(cb2[r0.z+19].xyzw, msPosition.xyzw); -#endif // !VR + float4 previousMsPosition = GetMSPosition(input, PreviousWindTimer); - float4 previousMsPosition = GetMSPosition(input, PreviousWindTimer, world3x3); - -#ifdef GRASS_COLLISION - previousMsPosition.xyz += displacement; -#endif // GRASS_COLLISION - -#if !defined(VR) vsout.PreviousWorldPosition = mul(PreviousWorld, previousMsPosition); - vsout.ViewDirectionVec.xyz = EyePosition.xyz - vsout.WorldPosition.xyz; -#else - vsout.PreviousWorldPosition.x = dot(cb2[r0.z+24].xyzw, previousMsPosition.xyzw); - vsout.PreviousWorldPosition.y = dot(cb2[r0.z+25].xyzw, previousMsPosition.xyzw); - vsout.PreviousWorldPosition.z = dot(cb2[r0.z+26].xyzw, previousMsPosition.xyzw); - vsout.PreviousWorldPosition.w = dot(cb2[r0.z+27].xyzw, previousMsPosition.xyzw); - -/* -https://docs.google.com/presentation/d/19x9XDjUvkW_9gsfsMQzt3hZbRNziVsoCEHOn4AercAc/htmlpresent -This section looks like this code -Matrix WorldToEyeClipMatrix[2] // computed from SDK -Vector4 EyeClipEdge[2]={(-1,0,0,1), (1,0,0,1)} -float EyeOffsetScale[2]={0.5,-0.5} -uint eyeIndex = instanceID & 1 // use low bit as eye index. -Vector4 clipPos = worldPos * WorldToEyeClipMatrix[eyeIndex] -cullDistanceOut.x = clipDistanceOut.x = clipPos · EyeClipEdge[eyeIndex] -clipPos.x *= 0.5; // shrink to half of the screen -clipPos.x += EyeOffsetScale[eyeIndex] * clipPos.w; // scoot left or right. -clipPositionOut = clipPos -*/ - if (0 < cb13[0].y) { - r0.yz = dot(projSpacePosition, cb13[r0.x+1].xyzw); - } else { - r0.yz = float2(1,1); - } - - r0.w = 2 + -cb13[0].y; - r0.x = dot(cb13[0].zw, M_IdentityMatrix[r0.x+0].xy); - r0.xw = r0.xw * projSpacePosition.wx; - r0.x = cb13[0].y * r0.x; - - vsout.HPosition.x = r0.w * 0.5 + r0.x; - vsout.HPosition.yzw = projSpacePosition.yzw; - - vsout.ClipDistance.x = r0.z; - vsout.CullDistance.x = r0.y; -#endif // !VR - - // Vertex normal needs to be transformed to world-space for lighting calculations. - float3 vertexNormal = input.Normal.xyz * 2.0 - 1.0; - vertexNormal = mul(world3x3, vertexNormal); - vsout.VertexNormal.xyz = vertexNormal; - return vsout; } -#endif // VSHADER +#endif typedef VS_OUTPUT PS_INPUT; @@ -312,7 +144,7 @@ struct PS_OUTPUT float4 Albedo : SV_Target0; float2 MotionVectors : SV_Target1; float4 Normal : SV_Target2; -#endif // RENDER_DEPTH +#endif }; #ifdef PSHADER @@ -322,189 +154,51 @@ SamplerState SampShadowMaskSampler : register(s1); Texture2D TexBaseSampler : register(t0); Texture2D TexShadowMaskSampler : register(t1); - - -#ifdef VR -struct PerEye -{ - row_major float4x4 ScreenProj; - row_major float4x4 PreviousScreenProj; -}; - -cbuffer cb0 : register(b0) -{ - float4 cb0[10]; -} - -#endif // VR - -cbuffer PerFrame : register(b12) -{ -#if !defined(VR) - row_major float4x4 ViewMatrix : packoffset(c0); - row_major float4x4 ProjMatrix : packoffset(c4); - row_major float4x4 ViewProjMatrix : packoffset(c8); - row_major float4x4 ViewProjMatrixUnjittered : packoffset(c12); - row_major float4x4 PreviousViewProjMatrixUnjittered : packoffset(c16); - row_major float4x4 InvProjMatrixUnjittered : packoffset(c20); - row_major float4x4 ProjMatrixUnjittered : packoffset(c24); - row_major float4x4 InvViewMatrix : packoffset(c28); - row_major float4x4 InvViewProjMatrix : packoffset(c32); - row_major float4x4 InvProjMatrix : packoffset(c36); - float4 CurrentPosAdjust : packoffset(c40); - float4 PreviousPosAdjust : packoffset(c41); - // notes: FirstPersonY seems 1.0 regardless of third/first person, could be LE legacy stuff - float4 GammaInvX_FirstPersonY_AlphaPassZ_CreationKitW : packoffset(c42); - float4 DynamicRes_WidthX_HeightY_PreviousWidthZ_PreviousHeightW : packoffset(c43); - float4 DynamicRes_InvWidthX_InvHeightY_WidthClampZ_HeightClampW : packoffset(c44); -#else - //VR is float4 PerFrame[87]; VR original used for eye position in PerFrame[86].x - float4 cb12[87]; -#endif // !VR -} - -cbuffer AlphaTestRefCB : register( -#if !defined(VR) - b11 -#else - b13 -#endif // !VR -) +cbuffer AlphaTestRefCB : register(b11) { float AlphaTestRefRS : packoffset(c0); } -struct StructuredLight +cbuffer PerFrame : register(b12) { - float4 color; - float4 positionWS[2]; - float radius; - bool shadow; - float mask; - bool active; + float4 UnknownPerFrame1[12] : packoffset(c0); + row_major float4x4 ScreenProj : packoffset(c12); + row_major float4x4 PreviousScreenProj : packoffset(c16); }; -StructuredBuffer lights : register(t17); - -float GetSoftLightMultiplier(float angle, float strength) -{ - float softLightParam = saturate((strength + angle) / (1 + strength)); - float arg1 = (softLightParam * softLightParam) * (3 - 2 * softLightParam); - float clampedAngle = saturate(angle); - float arg2 = (clampedAngle * clampedAngle) * (3 - 2 * clampedAngle); - float softLigtMul = saturate(arg1 - arg2); - return softLigtMul; -} - -float3 GetLightSpecularInput(float3 L, float3 V, float3 N, float3 lightColor, float shininess) -{ - float3 H = normalize(V + L); - float HdotN = saturate(dot(H, N)); - - float lightColorMultiplier = exp2(shininess * log2(HdotN)); - return lightColor * lightColorMultiplier.xxx; -} - -float3 TransformNormal(float3 normal) -{ - return normal * 2 + -1.0.xxx; -} - -// http://www.thetenthplanet.de/archives/1180 -float3x3 CalculateTBN(float3 N, float3 p, float2 uv) -{ - // get edge vectors of the pixel triangle - float3 dp1 = ddx_coarse(p); - float3 dp2 = ddy_coarse(p); - float2 duv1 = ddx_coarse(uv); - float2 duv2 = ddy_coarse(uv); - - // solve the linear system - float3 dp2perp = cross(dp2, N); - float3 dp1perp = cross(N, dp1); - float3 T = dp2perp * duv1.x + dp1perp * duv2.x; - float3 B = dp2perp * duv1.y + dp1perp * duv2.y; - - // construct a scale-invariant frame - float invmax = rsqrt(max(dot(T, T), dot(B, B))); - return float3x3(T * invmax, B * invmax, N); -} - -#if defined(SCREEN_SPACE_SHADOWS) - #include "ScreenSpaceShadows/ShadowsPS.hlsli" -#endif - -PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) +PS_OUTPUT main(PS_INPUT input) { PS_OUTPUT psout; - float x; - float y; - TexBaseSampler.GetDimensions(x, y); - - bool complex = x != y; - - float4 baseColor; - if (complex) { - baseColor = TexBaseSampler.Sample(SampBaseSampler, float2(input.TexCoord.x, input.TexCoord.y * 0.5)); - } - else - { - baseColor = TexBaseSampler.Sample(SampBaseSampler, input.TexCoord.xy); - } + float4 baseColor = TexBaseSampler.Sample(SampBaseSampler, input.TexCoord.xy); #if defined(RENDER_DEPTH) || defined(DO_ALPHA_TEST) - float diffuseAlpha = input.VertexColor.w * baseColor.w; + float diffuseAlpha = input.DiffuseColor.w * baseColor.w; + if ((diffuseAlpha - AlphaTestRefRS) < 0) { discard; } -#endif // RENDER_DEPTH | DO_ALPHA_TEST +#endif #if defined(RENDER_DEPTH) // Depth psout.PS.xyz = input.Depth.xxx / input.Depth.yyy; psout.PS.w = diffuseAlpha; #else - - float4 specColor = complex ? TexBaseSampler.Sample(SampBaseSampler, float2(input.TexCoord.x, 0.5 + input.TexCoord.y * 0.5)) : 1; - float4 shadowColor = TexShadowMaskSampler.Load(int3(input.HPosition.xy, 0)); + float sunShadowMask = TexShadowMaskSampler.Load(int3(input.HPosition.xy, 0)).x; // Albedo - // float diffuseFraction = lerp(sunShadowMask, 1, input.AmbientColor.w); - // float3 diffuseColor = input.DiffuseColor.xyz * baseColor.xyz; - // float3 ambientColor = input.AmbientColor.xyz * baseColor.xyz; - // psout.Albedo.xyz = input.TexCoord.zzz * (diffuseColor * diffuseFraction + ambientColor); - // psout.Albedo.w = 1; - -#if !defined(VR) - float4 screenPosition = mul(ViewProjMatrixUnjittered, input.WorldPosition); + float diffuseFraction = lerp(sunShadowMask, 1, input.AmbientColor.w); + float3 diffuseColor = input.DiffuseColor.xyz * baseColor.xyz; + float3 ambientColor = input.AmbientColor.xyz * baseColor.xyz; + psout.Albedo.xyz = input.TexCoord.zzz * (diffuseColor * diffuseFraction + ambientColor); + psout.Albedo.w = 1; + + float4 screenPosition = mul(ScreenProj, input.WorldPosition); screenPosition.xy = screenPosition.xy / screenPosition.ww; - float4 previousScreenPosition = mul(PreviousViewProjMatrixUnjittered, input.PreviousWorldPosition); + float4 previousScreenPosition = mul(PreviousScreenProj, input.PreviousWorldPosition); previousScreenPosition.xy = previousScreenPosition.xy / previousScreenPosition.ww; - uint eyeIndex = 0; -#else - float stereoUV = input.HPosition.x * cb0[2].xy + cb0[2].zw; - stereoUV = stereoUV * cb12[86].x; - - uint eyeIndex = (stereoUV >= 0.5) ? 1 : 0; - uint eyeOffset = eyeIndex; - uint bitmask; - bitmask = ((~(-1 << 1)) << 2) & 0xffffffff; eyeOffset = (((uint)eyeOffset<< 2) & bitmask) | ((uint)0 & ~bitmask); - - float3 screenPosition; - screenPosition.x = dot(cb12[eyeOffset+24].xyzw, input.WorldPosition); - screenPosition.y = dot(cb12[eyeOffset+25].xyzw, input.WorldPosition); - screenPosition.z = dot(cb12[eyeOffset+27].xyzw, input.WorldPosition); - screenPosition.xy = screenPosition.xy / screenPosition.zz; - - float3 previousScreenPosition; - previousScreenPosition.x = dot(cb12[eyeOffset+32].xyzw, input.PreviousWorldPosition); - previousScreenPosition.y = dot(cb12[eyeOffset+33].xyzw, input.PreviousWorldPosition); - previousScreenPosition.z = dot(cb12[eyeOffset+35].xyzw, input.PreviousWorldPosition); - previousScreenPosition.xy = previousScreenPosition.xy / previousScreenPosition.zz; -#endif // !VR - float2 screenMotionVector = float2(-0.5, 0.5) * (screenPosition.xy - previousScreenPosition.xy); psout.MotionVectors = screenMotionVector; @@ -515,124 +209,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float normalScale = max(1.0 / 1000.0, sqrt(normal.z * -8 + 8)); psout.Normal.xy = float2(0.5, 0.5) + normal.xy / normalScale; psout.Normal.zw = float2(0, 0); +#endif -#if !defined(VR) - float3 viewDirection = normalize(input.ViewDirectionVec); -#else - float3 viewDirection = normalize(-input.WorldPosition.xyz); -#endif // !VR - float3 worldNormal = normalize(input.VertexNormal); - - // Swaps direction of the backfaces otherwise they seem to get lit from the wrong direction. - if (!frontFace) worldNormal.xyz = -worldNormal.xyz; - - if (complex) { - float3 normalColor = float4(TransformNormal(specColor.xyz), 1); - // Inverting x as well as y seems to look more correct. - normalColor.xy = -normalColor.xy; - // world-space -> tangent-space -> world-space. - // This is because we don't have pre-computed tangents. -#if !defined(VR) - worldNormal.xyz = normalize(mul(normalColor.xyz, CalculateTBN(worldNormal.xyz, -viewDirection, input.TexCoord.xy))); -#else - worldNormal.xyz = normalize(mul(normalColor.xyz, CalculateTBN(worldNormal.xyz, input.WorldPosition.xyz, input.TexCoord.xy))); -#endif // !VR - } - - float3 dirLightColor = DirLightColor.xyz; - if (EnableDirLightFix) - { - // dirLightColor *= SunlightScale; - } - - dirLightColor *= shadowColor.x; - -#if defined(SCREEN_SPACE_SHADOWS) - float dirLightSShadow = PrepassScreenSpaceShadows(input.WorldPosition); - dirLightColor *= dirLightSShadow; -#endif // !SCREEN_SPACE_SHADOWS - - - float3 diffuseColor = 0; - float3 specularColor = 0; - - float3 lightsDiffuseColor = 0; - float3 lightsSpecularColor = 0; - - float dirLightAngle = dot(worldNormal.xyz, DirLightDirection.xyz); - float3 dirDiffuseColor = dirLightColor * saturate(dirLightAngle); - - lightsDiffuseColor += dirDiffuseColor; - - // Generated texture to simulate light transport. - // Numerous attempts were made to use a more interesting algorithm however they were mostly fruitless. - float3 subsurfaceColor = baseColor.xyz; - - // Applies lighting across the whole surface apart from what is already lit. - lightsDiffuseColor += subsurfaceColor * dirLightColor * GetSoftLightMultiplier(dirLightAngle, SubsurfaceScatteringAmount); - // Applies lighting from the opposite direction. Does not account for normals perpendicular to the light source. - lightsDiffuseColor += subsurfaceColor * dirLightColor * saturate(-dirLightAngle) * SubsurfaceScatteringAmount; - - if (complex) { - lightsSpecularColor = GetLightSpecularInput(DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz, Glossiness); - // Not physically accurate but grass will otherwise look too flat. - lightsSpecularColor += subsurfaceColor * GetLightSpecularInput(-DirLightDirection, viewDirection, worldNormal.xyz, dirLightColor.xyz, Glossiness); - } - - if (true) { - uint light_count, dummy; - lights.GetDimensions(light_count, dummy); - for (uint light_index = 0; light_index < light_count; light_index++) - { - StructuredLight light = lights[light_index]; - if (light.active) { - float3 lightDirection = light.positionWS[eyeIndex].xyz - input.WorldPosition.xyz; - float lightDist = length(lightDirection); - float intensityFactor = saturate(lightDist / light.radius); - float intensityMultiplier = 1 - intensityFactor * intensityFactor; - if (intensityMultiplier) { - float3 lightColor = light.color.xyz; - - if (light.shadow) { - lightColor *= shadowColor[light.mask]; - } - - float3 normalizedLightDirection = normalize(lightDirection); - - float lightAngle = dot(worldNormal.xyz, normalizedLightDirection.xyz); - float3 lightDiffuseColor = lightColor * saturate(lightAngle.xxx); - - lightDiffuseColor += subsurfaceColor * lightColor * GetSoftLightMultiplier(lightAngle, SubsurfaceScatteringAmount); - lightDiffuseColor += subsurfaceColor * lightColor * saturate(-lightAngle) * SubsurfaceScatteringAmount; - - if (complex) { - lightsSpecularColor += GetLightSpecularInput(normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, Glossiness) * intensityMultiplier; - lightsSpecularColor += subsurfaceColor * GetLightSpecularInput(-normalizedLightDirection, viewDirection, worldNormal.xyz, lightColor, Glossiness) * intensityMultiplier; - } - - lightsDiffuseColor += lightDiffuseColor * intensityMultiplier; - } - } - } - } - - float3 directionalAmbientColor = mul(DirectionalAmbient, float4(worldNormal.xyz, 1)); - lightsDiffuseColor += AmbientColor; - - diffuseColor += lightsDiffuseColor; - - float3 color = diffuseColor * baseColor.xyz * input.VertexColor.xyz; - - if (complex) { - specularColor += lightsSpecularColor; - specularColor *= specColor.w * SpecularStrength; - color.xyz += specularColor; - } - - psout.Albedo.xyz = color; - psout.Albedo.w = 1; - -#endif // RENDER_DEPTH return psout; } -#endif // PSHADER \ No newline at end of file +#endif diff --git a/src/Features/GrassLighting.cpp b/src/Features/GrassLighting.cpp index d6bc6596c..df077aea7 100644 --- a/src/Features/GrassLighting.cpp +++ b/src/Features/GrassLighting.cpp @@ -113,8 +113,8 @@ void GrassLighting::ModifyGrass(const RE::BSShader*, const uint32_t descriptor) ID3D11Buffer* buffers[2]; context->VSGetConstantBuffers(2, 1, buffers); // buffers[0] buffers[1] = perFrame->CB(); - // context->VSSetConstantBuffers(2, ARRAYSIZE(buffers), buffers); - context->PSSetConstantBuffers(9, ARRAYSIZE(buffers), buffers); + context->VSSetConstantBuffers(2, ARRAYSIZE(buffers), buffers); + context->PSSetConstantBuffers(2, ARRAYSIZE(buffers), buffers); } } From 0892b5c624b68c9ef8b3c335fe3cde32804d4d93 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Wed, 12 Jul 2023 00:50:08 -0700 Subject: [PATCH 06/14] Fix name collision for PS constant buffer 12 --- features/Grass Lighting/Shaders/RunGrass.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/Grass Lighting/Shaders/RunGrass.hlsl b/features/Grass Lighting/Shaders/RunGrass.hlsl index 0602b982d..35a8196ee 100644 --- a/features/Grass Lighting/Shaders/RunGrass.hlsl +++ b/features/Grass Lighting/Shaders/RunGrass.hlsl @@ -330,7 +330,7 @@ cbuffer cb0 : register(b0) #endif // VR -cbuffer PerFrame : register(b12) +cbuffer PS_cb12 : register(b12) { #if !defined(VR) row_major float4x4 ViewMatrix : packoffset(c0); From 3ce3205d8301f5456fae614c59cbad66eef59a11 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Wed, 12 Jul 2023 00:56:06 -0700 Subject: [PATCH 07/14] Fix grass lighting Removes helper function ProcessFrame --- src/Features/GrassLighting.cpp | 83 +++++++++++++++++----------------- src/Features/GrassLighting.h | 2 - 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/src/Features/GrassLighting.cpp b/src/Features/GrassLighting.cpp index df077aea7..98f9a5ad1 100644 --- a/src/Features/GrassLighting.cpp +++ b/src/Features/GrassLighting.cpp @@ -52,59 +52,58 @@ void GrassLighting::DrawSettings() } } -void GrassLighting::ProcessFrame(PerFrame* perFrameData, PerFrameVR* perFrameDataVR) +void GrassLighting::ModifyGrass(const RE::BSShader*, const uint32_t descriptor) { - auto& shaderState = RE::BSShaderManager::State::GetSingleton(); - RE::NiTransform& dalcTransform = shaderState.directionalAmbientTransform; - auto accumulator = RE::BSGraphics::BSShaderAccumulator::GetCurrentAccumulator(); - auto& position = accumulator->GetRuntimeData().eyePosition; - auto state = RE::BSGraphics::RendererShadowState::GetSingleton(); - auto manager = RE::ImageSpaceManager::GetSingleton(); - if (REL::Module::IsVR()) { - ZeroMemory(perFrameDataVR, sizeof(perFrameDataVR)); - Util::StoreTransform3x4NoScale(perFrameDataVR->DirectionalAmbient, dalcTransform); - RE::NiPoint3 eyePosition = state->GetVRRuntimeData().posAdjust.getEye(); + const auto technique = descriptor & 0b1111; + if (technique != static_cast(GrassShaderTechniques::RenderDepth)) { + if (updatePerFrame) { + auto& shaderState = RE::BSShaderManager::State::GetSingleton(); + auto accumulator = RE::BSGraphics::BSShaderAccumulator::GetCurrentAccumulator(); + auto& position = accumulator->GetRuntimeData().eyePosition; + auto state = RE::BSGraphics::RendererShadowState::GetSingleton(); + RE::NiTransform& dalcTransform = shaderState.directionalAmbientTransform; + auto manager = RE::ImageSpaceManager::GetSingleton(); - perFrameDataVR->EyePosition.x = position.x - eyePosition.x; - perFrameDataVR->EyePosition.y = position.y - eyePosition.y; - perFrameDataVR->EyePosition.z = position.z - eyePosition.z; + if (REL::Module::IsVR()) { + PerFrameVR perFrameDataVR{}; + ZeroMemory(&perFrameDataVR, sizeof(perFrameDataVR)); + Util::StoreTransform3x4NoScale(perFrameDataVR.DirectionalAmbient, dalcTransform); - eyePosition = state->GetVRRuntimeData().posAdjust.getEye(1); - perFrameDataVR->EyePosition2.x = position.x - eyePosition.x; - perFrameDataVR->EyePosition2.y = position.y - eyePosition.y; - perFrameDataVR->EyePosition2.z = position.z - eyePosition.z; + RE::NiPoint3 eyePosition = state->GetVRRuntimeData().posAdjust.getEye(); - perFrameDataVR->SunlightScale = manager->data.baseData.hdr.sunlightScale; + perFrameDataVR.EyePosition.x = position.x - eyePosition.x; + perFrameDataVR.EyePosition.y = position.y - eyePosition.y; + perFrameDataVR.EyePosition.z = position.z - eyePosition.z; - perFrameDataVR->Settings = settings; + eyePosition = state->GetVRRuntimeData().posAdjust.getEye(1); + perFrameDataVR.EyePosition2.x = position.x - eyePosition.x; + perFrameDataVR.EyePosition2.y = position.y - eyePosition.y; + perFrameDataVR.EyePosition2.z = position.z - eyePosition.z; - perFrame->Update(perFrameDataVR); + perFrameDataVR.SunlightScale = manager->data.baseData.hdr.sunlightScale; - } else { - ZeroMemory(perFrameData, sizeof(perFrameData)); - Util::StoreTransform3x4NoScale(perFrameData->DirectionalAmbient, dalcTransform); - RE::NiPoint3 eyePosition = state->GetRuntimeData().posAdjust.getEye(); + perFrameDataVR.Settings = settings; - perFrameData->EyePosition.x = position.x - eyePosition.x; - perFrameData->EyePosition.y = position.y - eyePosition.y; - perFrameData->EyePosition.z = position.z - eyePosition.z; - perFrameData->SunlightScale = manager->data.baseData.hdr.sunlightScale; + perFrame->Update(perFrameDataVR); + } else { + PerFrame perFrameData{}; + ZeroMemory(&perFrameData, sizeof(perFrameData)); + Util::StoreTransform3x4NoScale(perFrameData.DirectionalAmbient, dalcTransform); - perFrameData->Settings = settings; + RE::NiPoint3 eyePosition = state->GetRuntimeData().posAdjust.getEye(); - perFrame->Update(perFrameData); - } + perFrameData.EyePosition.x = position.x - eyePosition.x; + perFrameData.EyePosition.y = position.y - eyePosition.y; + perFrameData.EyePosition.z = position.z - eyePosition.z; - updatePerFrame = false; -} -void GrassLighting::ModifyGrass(const RE::BSShader*, const uint32_t descriptor) -{ - const auto technique = descriptor & 0b1111; - if (technique != static_cast(GrassShaderTechniques::RenderDepth)) { - PerFrame perFrameData{}; - PerFrameVR perFrameDataVR{}; - if (updatePerFrame) { - ProcessFrame(&perFrameData, &perFrameDataVR); + perFrameData.SunlightScale = manager->data.baseData.hdr.sunlightScale; + + perFrameData.Settings = settings; + + perFrame->Update(perFrameData); + } + + updatePerFrame = false; } Clustered::GetSingleton()->Bind(true); diff --git a/src/Features/GrassLighting.h b/src/Features/GrassLighting.h index a26d8b608..550255598 100644 --- a/src/Features/GrassLighting.h +++ b/src/Features/GrassLighting.h @@ -56,6 +56,4 @@ struct GrassLighting : Feature virtual void Load(json& o_json); virtual void Save(json& o_json); -private: - void ProcessFrame(PerFrame* perFrameData, PerFrameVR* perFrameDataVR); }; From 05db83049b65928d5f6f9186ae680ff94673e3b5 Mon Sep 17 00:00:00 2001 From: Tim <15017472+doodlum@users.noreply.github.com> Date: Wed, 12 Jul 2023 22:21:42 +0100 Subject: [PATCH 08/14] Fixed LOD issue --- features/Grass Lighting/Shaders/RunGrass.hlsl | 18 ++++++++++++++---- src/Features/GrassLighting.cpp | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/features/Grass Lighting/Shaders/RunGrass.hlsl b/features/Grass Lighting/Shaders/RunGrass.hlsl index 35a8196ee..958757ac3 100644 --- a/features/Grass Lighting/Shaders/RunGrass.hlsl +++ b/features/Grass Lighting/Shaders/RunGrass.hlsl @@ -46,7 +46,13 @@ struct VS_OUTPUT }; // Constant Buffers (Flat and VR) -cbuffer PerGeometry : register(b2) +cbuffer PerGeometry : register( +#ifdef VSHADER + b2 +#else + b3 +#endif +) { #if !defined(VR) row_major float4x4 WorldViewProj : packoffset(c0); @@ -80,7 +86,13 @@ cbuffer PerGeometry : register(b2) #endif // !VR } -cbuffer PerFrame : register(b3) +cbuffer PerFrame : register( +#ifdef VSHADER + b3 +#else + b4 +#endif +) { #if !defined(VR) float4 EyePosition; @@ -572,7 +584,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) } if (EnablePointLights) { - uint counter = 0; uint light_count, dummy; lights.GetDimensions(light_count, dummy); for (uint light_index = 0; light_index < light_count; light_index++) @@ -584,7 +595,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float intensityFactor = saturate(lightDist / light.radius); float intensityMultiplier = 1 - intensityFactor * intensityFactor; if (intensityMultiplier) { - counter++; float3 lightColor = light.color.xyz; if (light.shadow) { diff --git a/src/Features/GrassLighting.cpp b/src/Features/GrassLighting.cpp index 98f9a5ad1..ef4d88a7b 100644 --- a/src/Features/GrassLighting.cpp +++ b/src/Features/GrassLighting.cpp @@ -113,7 +113,7 @@ void GrassLighting::ModifyGrass(const RE::BSShader*, const uint32_t descriptor) context->VSGetConstantBuffers(2, 1, buffers); // buffers[0] buffers[1] = perFrame->CB(); context->VSSetConstantBuffers(2, ARRAYSIZE(buffers), buffers); - context->PSSetConstantBuffers(2, ARRAYSIZE(buffers), buffers); + context->PSSetConstantBuffers(3, ARRAYSIZE(buffers), buffers); } } From 3a22bc76e0974971eb196ff021b621a6e2b2dbdc Mon Sep 17 00:00:00 2001 From: Tim <15017472+doodlum@users.noreply.github.com> Date: Sun, 16 Jul 2023 12:53:32 +0100 Subject: [PATCH 09/14] Changed bindings to support VR --- features/Grass Collision/Shaders/RunGrass/GrassCollision.hlsli | 2 +- .../Shaders/ScreenSpaceShadows/ShadowsPS.hlsli | 2 +- src/Features/GrassCollision.cpp | 2 +- src/Features/ScreenSpaceShadows.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/features/Grass Collision/Shaders/RunGrass/GrassCollision.hlsli b/features/Grass Collision/Shaders/RunGrass/GrassCollision.hlsli index beda2c00d..dd59c915e 100644 --- a/features/Grass Collision/Shaders/RunGrass/GrassCollision.hlsli +++ b/features/Grass Collision/Shaders/RunGrass/GrassCollision.hlsli @@ -1,5 +1,5 @@ -cbuffer GrassCollisionPerFrame : register(b4) +cbuffer GrassCollisionPerFrame : register(b5) { float3 boundCentre; float boundRadius; diff --git a/features/Screen-Space Shadows/Shaders/ScreenSpaceShadows/ShadowsPS.hlsli b/features/Screen-Space Shadows/Shaders/ScreenSpaceShadows/ShadowsPS.hlsli index 28e578add..07311e3d5 100644 --- a/features/Screen-Space Shadows/Shaders/ScreenSpaceShadows/ShadowsPS.hlsli +++ b/features/Screen-Space Shadows/Shaders/ScreenSpaceShadows/ShadowsPS.hlsli @@ -1,4 +1,4 @@ -cbuffer SSSData : register(b4) +cbuffer SSSData : register(b5) { bool EnableSSS; uint FrameCount; diff --git a/src/Features/GrassCollision.cpp b/src/Features/GrassCollision.cpp index ed4e36844..0a97e6893 100644 --- a/src/Features/GrassCollision.cpp +++ b/src/Features/GrassCollision.cpp @@ -229,7 +229,7 @@ void GrassCollision::ModifyGrass(const RE::BSShader*, const uint32_t) ID3D11Buffer* buffers[1]; buffers[0] = perFrame->CB(); - context->VSSetConstantBuffers(4, ARRAYSIZE(buffers), buffers); + context->VSSetConstantBuffers(5, ARRAYSIZE(buffers), buffers); } } diff --git a/src/Features/ScreenSpaceShadows.cpp b/src/Features/ScreenSpaceShadows.cpp index af01468d3..0bbc973e0 100644 --- a/src/Features/ScreenSpaceShadows.cpp +++ b/src/Features/ScreenSpaceShadows.cpp @@ -389,7 +389,7 @@ void ScreenSpaceShadows::ModifyLighting(const RE::BSShader*, const uint32_t) ID3D11Buffer* buffers[1]{}; buffers[0] = perPass->CB(); - context->PSSetConstantBuffers(4, ARRAYSIZE(buffers), buffers); + context->PSSetConstantBuffers(5, ARRAYSIZE(buffers), buffers); context->PSSetSamplers(14, 1, &computeSampler); } From 31fc1512cec4776a207bd434c1c4aede10f5b32f Mon Sep 17 00:00:00 2001 From: doodlum <15017472+doodlum@users.noreply.github.com> Date: Sun, 16 Jul 2023 12:54:51 +0100 Subject: [PATCH 10/14] Rename GrassCollision.hlsli to GrassCollision.hlsli --- .../Shaders/{RunGrass => GrassCollision}/GrassCollision.hlsli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename features/Grass Collision/Shaders/{RunGrass => GrassCollision}/GrassCollision.hlsli (99%) diff --git a/features/Grass Collision/Shaders/RunGrass/GrassCollision.hlsli b/features/Grass Collision/Shaders/GrassCollision/GrassCollision.hlsli similarity index 99% rename from features/Grass Collision/Shaders/RunGrass/GrassCollision.hlsli rename to features/Grass Collision/Shaders/GrassCollision/GrassCollision.hlsli index dd59c915e..658400601 100644 --- a/features/Grass Collision/Shaders/RunGrass/GrassCollision.hlsli +++ b/features/Grass Collision/Shaders/GrassCollision/GrassCollision.hlsli @@ -50,4 +50,4 @@ float3 GetDisplacedPosition(float3 position, float alpha) } return displacement * saturate(alpha * alpha * 5) * DisplacementMultiplier; -} \ No newline at end of file +} From ca12ac10d580c8077c2165aef86d3a3d4a02816f Mon Sep 17 00:00:00 2001 From: Tim <15017472+doodlum@users.noreply.github.com> Date: Sun, 16 Jul 2023 12:55:40 +0100 Subject: [PATCH 11/14] Fixed incorrect default grass glossiness --- package/SKSE/Plugins/CommunityShaders.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/SKSE/Plugins/CommunityShaders.json b/package/SKSE/Plugins/CommunityShaders.json index 0aac4dabe..2e526f2f3 100644 --- a/package/SKSE/Plugins/CommunityShaders.json +++ b/package/SKSE/Plugins/CommunityShaders.json @@ -29,7 +29,7 @@ "Grass Lighting": { "EnableDirLightFix": 1, "EnablePointLights": 1, - "Glossiness": 44.779998779296875, + "Glossiness": 20.0, "SpecularStrength": 0.5, "SubsurfaceScatteringAmount": 0.5 }, From 5a17be4cdc7bd091f015304ae8ae8d83456162eb Mon Sep 17 00:00:00 2001 From: Tim <15017472+doodlum@users.noreply.github.com> Date: Sun, 16 Jul 2023 12:55:56 +0100 Subject: [PATCH 12/14] Increased default grass SSS amount --- package/SKSE/Plugins/CommunityShaders.json | 2 +- src/Features/GrassLighting.cpp | 2 +- src/Features/GrassLighting.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package/SKSE/Plugins/CommunityShaders.json b/package/SKSE/Plugins/CommunityShaders.json index 2e526f2f3..29e454a32 100644 --- a/package/SKSE/Plugins/CommunityShaders.json +++ b/package/SKSE/Plugins/CommunityShaders.json @@ -31,7 +31,7 @@ "EnablePointLights": 1, "Glossiness": 20.0, "SpecularStrength": 0.5, - "SubsurfaceScatteringAmount": 0.5 + "SubsurfaceScatteringAmount": 1.0 }, "Menu": { "Toggle Key": 35 diff --git a/src/Features/GrassLighting.cpp b/src/Features/GrassLighting.cpp index ef4d88a7b..b4f87557c 100644 --- a/src/Features/GrassLighting.cpp +++ b/src/Features/GrassLighting.cpp @@ -36,7 +36,7 @@ void GrassLighting::DrawSettings() "Back lighting illuminates the back face of an object.\n" "Combined to model the transport of light through the surface."); ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f); - ImGui::SliderFloat("Subsurface Scattering Amount", &settings.SubsurfaceScatteringAmount, 0.0f, 1.0f); + ImGui::SliderFloat("Subsurface Scattering Amount", &settings.SubsurfaceScatteringAmount, 0.0f, 2.0f); ImGui::TreePop(); } diff --git a/src/Features/GrassLighting.h b/src/Features/GrassLighting.h index 550255598..5c4d7beb6 100644 --- a/src/Features/GrassLighting.h +++ b/src/Features/GrassLighting.h @@ -18,7 +18,7 @@ struct GrassLighting : Feature { float Glossiness = 20; float SpecularStrength = 0.5; - float SubsurfaceScatteringAmount = 0.5; + float SubsurfaceScatteringAmount = 1.0; std::uint32_t EnableDirLightFix = 1; std::uint32_t EnablePointLights = 1; }; From 8c7b1d1eecf65b854669237cabddad2e1abfcec7 Mon Sep 17 00:00:00 2001 From: Tim <15017472+doodlum@users.noreply.github.com> Date: Sun, 16 Jul 2023 12:56:17 +0100 Subject: [PATCH 13/14] Changed Grass Collision include to match rename --- features/Grass Lighting/Shaders/RunGrass.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/Grass Lighting/Shaders/RunGrass.hlsl b/features/Grass Lighting/Shaders/RunGrass.hlsl index 958757ac3..bc141c1e9 100644 --- a/features/Grass Lighting/Shaders/RunGrass.hlsl +++ b/features/Grass Lighting/Shaders/RunGrass.hlsl @@ -112,7 +112,7 @@ cbuffer PerFrame : register( #ifdef VSHADER #ifdef GRASS_COLLISION - #include "RunGrass\\GrassCollision.hlsli" + #include "GrassCollision\\GrassCollision.hlsli" #endif cbuffer cb7 : register(b7) From 427c5881ebc83dacb0a0149d9fd51a2b904cf5f7 Mon Sep 17 00:00:00 2001 From: Tim <15017472+doodlum@users.noreply.github.com> Date: Sun, 16 Jul 2023 12:56:38 +0100 Subject: [PATCH 14/14] Fixed screen space shadows being offset --- .../Shaders/ScreenSpaceShadows/FilterCS.hlsl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/features/Screen-Space Shadows/Shaders/ScreenSpaceShadows/FilterCS.hlsl b/features/Screen-Space Shadows/Shaders/ScreenSpaceShadows/FilterCS.hlsl index 8ae019137..1fe66ed28 100644 --- a/features/Screen-Space Shadows/Shaders/ScreenSpaceShadows/FilterCS.hlsl +++ b/features/Screen-Space Shadows/Shaders/ScreenSpaceShadows/FilterCS.hlsl @@ -121,10 +121,6 @@ void main( uint3 DTid : SV_DispatchThreadID ) float2 TexCoord = (DTid.xy + 0.5) * RcpBufferDim; - #if defined(HORIZONTAL) - TexCoord += 0.5 * RcpBufferDim; - #endif - float startDepth = GetDepth(TexCoord * 2); if (startDepth >= 1) return;