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 }; }