Skip to content

Commit

Permalink
feat: add VR support for distanttree (#250)
Browse files Browse the repository at this point in the history
  • Loading branch information
alandtse authored Apr 7, 2024
1 parent 3c2d04c commit bab9f89
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 31 deletions.
115 changes: 84 additions & 31 deletions features/Tree LOD Lighting/Shaders/DistantTree.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,21 @@
#include "Common/LightingData.hlsl"
#include "Common/MotionBlur.hlsl"

cbuffer PerFrame : register(b3)
#ifdef VR
cbuffer VRValues : register(b13)
{
float AlphaTestRefRS : packoffset(c0);
float StereoEnabled : packoffset(c0.y);
float2 EyeOffsetScale : packoffset(c0.z);
float4 EyeClipEdge[2] : packoffset(c1);
}

const static float4x4 M_IdentityMatrix = {
{ 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 }
};
#endif // VR

cbuffer TreePerFrame : register(b3)
{
row_major float3x4 DirectionalAmbient;
float4 DirLightColor;
Expand All @@ -24,6 +38,9 @@ struct VS_INPUT
float4 InstanceData2 : TEXCOORD5;
float4 InstanceData3 : TEXCOORD6; // Unused
float4 InstanceData4 : TEXCOORD7; // Unused
#if defined(VR)
uint InstanceID : SV_INSTANCEID;
#endif // VR
};

struct VS_OUTPUT
Expand All @@ -38,7 +55,16 @@ struct VS_OUTPUT
#endif
float3 SphereNormal : TEXCOORD4;

row_major float3x4 World : POSITION3;
#if !defined(VR)
row_major float3x4 World[1] : POSITION3;
#else
row_major float3x4 World[2] : POSITION3;
#endif // VR
#if defined(VR)
float ClipDistance : SV_ClipDistance0; // o11
float CullDistance : SV_CullDistance0; // p11
uint EyeIndex : EYEIDX0;
#endif // VR
};

#ifdef VSHADER
Expand All @@ -49,14 +75,25 @@ cbuffer PerTechnique : register(b0)

cbuffer PerGeometry : register(b2)
{
row_major float4x4 WorldViewProj : packoffset(c0);
row_major float4x4 World : packoffset(c4);
row_major float4x4 PreviousWorld : packoffset(c8);
# if !defined(VR)
row_major float4x4 WorldViewProj[1] : packoffset(c0);
row_major float4x4 World[1] : packoffset(c4);
row_major float4x4 PreviousWorld[1] : packoffset(c8);
# else
row_major float4x4 WorldViewProj[2] : packoffset(c0);
row_major float4x4 World[2] : packoffset(c8);
row_major float4x4 PreviousWorld[2] : packoffset(c16);
# endif
};

VS_OUTPUT main(VS_INPUT input)
{
VS_OUTPUT vsout;
# if !defined(VR)
uint eyeIndex = 0;
# else // VR
uint eyeIndex = StereoEnabled * (input.InstanceID.x & 1);
# endif // VR

float3 scaledModelPosition = input.InstanceData1.www * input.Position.xyz;
float3 adjustedModelPosition = 0.0.xxx;
Expand All @@ -65,14 +102,14 @@ VS_OUTPUT main(VS_INPUT input)
adjustedModelPosition.z = scaledModelPosition.z;

float4 finalModelPosition = float4(input.InstanceData1.xyz + adjustedModelPosition.xyz, 1.0);
float4 viewPosition = mul(WorldViewProj, finalModelPosition);
float4 viewPosition = mul(WorldViewProj[eyeIndex], finalModelPosition);

# ifdef RENDER_DEPTH
vsout.Depth.xy = viewPosition.zw;
vsout.Depth.zw = input.InstanceData2.zw;
# else
vsout.WorldPosition = mul(World, finalModelPosition);
vsout.PreviousWorldPosition = mul(PreviousWorld, finalModelPosition);
vsout.WorldPosition = mul(World[eyeIndex], finalModelPosition);
vsout.PreviousWorldPosition = mul(PreviousWorld[eyeIndex], finalModelPosition);
# endif

vsout.Position = viewPosition;
Expand All @@ -83,10 +120,35 @@ VS_OUTPUT main(VS_INPUT input)
adjustedModelPosition.y = dot(input.InstanceData2.yx, scaledModelPosition.xy);
adjustedModelPosition.z = scaledModelPosition.z;

vsout.SphereNormal.xyz = mul(World, normalize(adjustedModelPosition));
vsout.SphereNormal.xyz = mul(World[eyeIndex], normalize(float4(adjustedModelPosition, 0)));

vsout.World[0] = World[0];
# ifdef VR
vsout.World[1] = World[1];
vsout.EyeIndex = eyeIndex;
# endif // VR

# ifdef VR
float4 r0;
float4 projSpacePosition = vsout.Position;
r0.xyzw = 0;
if (0 < StereoEnabled) {
r0.yz = dot(projSpacePosition, EyeClipEdge[eyeIndex]); // projSpacePosition is clipPos
} else {
r0.yz = float2(1, 1);
}

r0.w = 2 + -StereoEnabled;
r0.x = dot(EyeOffsetScale, M_IdentityMatrix[eyeIndex].xy);
r0.xw = r0.xw * projSpacePosition.wx;
r0.x = StereoEnabled * r0.x;

vsout.World = World;
vsout.Position.x = r0.w * 0.5 + r0.x;
vsout.Position.yzw = projSpacePosition.yzw;

vsout.ClipDistance.x = r0.z;
vsout.CullDistance.x = r0.y;
# endif // VR
return vsout;
}
#endif
Expand All @@ -108,35 +170,20 @@ SamplerState SampDiffuse : register(s0);
SamplerState SampShadowMaskSampler : register(s14);
Texture2D<float4> TexDiffuse : register(t0);

# if !defined(VR)
cbuffer AlphaTestRefCB : register(b11)
{
float AlphaTestRefRS : packoffset(c0);
}
# endif

cbuffer PerTechnique : register(b0)
{
float4 DiffuseColor : packoffset(c0);
float4 AmbientColor : packoffset(c1);
};

const static float DepthOffsets[16] = {
0.003921568,
0.533333361,
0.133333340,
0.666666687,
0.800000000,
0.266666681,
0.933333337,
0.400000000,
0.200000000,
0.733333349,
0.066666670,
0.600000000,
0.996078432,
0.466666669,
0.866666675,
0.333333343
};
const static float DepthOffsets[16] = { 0.003921568, 0.533333361, 0.133333340, 0.666666687, 0.800000000, 0.266666681, 0.933333337, 0.400000000, 0.200000000, 0.733333349, 0.066666670, 0.600000000, 0.996078432, 0.466666669, 0.866666675, 0.333333343 };

float GetSoftLightMultiplier(float angle, float strength)
{
Expand Down Expand Up @@ -186,6 +233,12 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace
{
PS_OUTPUT psout;

# if !defined(VR)
uint eyeIndex = 0;
# else
uint eyeIndex = input.EyeIndex;
# endif

# if defined(RENDER_DEPTH)
uint2 temp = uint2(input.Position.xy);
uint index = ((temp.x << 2) & 12) | (temp.y & 3);
Expand Down Expand Up @@ -215,7 +268,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace
}
# endif

float2 screenMotionVector = GetSSMotionVector(input.WorldPosition, input.PreviousWorldPosition);
float2 screenMotionVector = GetSSMotionVector(input.WorldPosition, input.PreviousWorldPosition, eyeIndex);

psout.MotionVector = screenMotionVector;

Expand Down Expand Up @@ -249,7 +302,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace
}

# if defined(CLOUD_SHADOWS)
float3 normalizedDirLightDirectionWS = -normalize(mul(input.World, float4(DirLightDirection.xyz, 0))).xyz;
float3 normalizedDirLightDirectionWS = -normalize(mul(input.World[eyeIndex], float4(DirLightDirection.xyz, 0))).xyz;

float3 cloudShadowMult = 1.0;
if (perPassCloudShadow[0].EnableCloudShadows && !lightingData[0].Reflections) {
Expand All @@ -261,7 +314,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace
float3 nsDirLightColor = dirLightColor;

# if defined(SCREEN_SPACE_SHADOWS)
float dirLightSShadow = PrepassScreenSpaceShadows(input.WorldPosition);
float dirLightSShadow = PrepassScreenSpaceShadows(input.WorldPosition.xyz, eyeIndex);
# endif

float3 diffuseColor = 0;
Expand Down
1 change: 1 addition & 0 deletions src/Features/DistantTreeLighting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ void DistantTreeLighting::ModifyDistantTree(const RE::BSShader*, const uint32_t
context->VSGetConstantBuffers(2, 1, buffers); // buffers[0]
buffers[1] = perPass->CB();
context->VSSetConstantBuffers(2, ARRAYSIZE(buffers), buffers);
context->PSGetConstantBuffers(2, 1, buffers); // buffers[0]
context->PSSetConstantBuffers(2, ARRAYSIZE(buffers), buffers);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/Features/DistantTreeLighting.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ struct DistantTreeLighting : Feature
virtual void Save(json& o_json);

virtual void RestoreDefaultSettings();
bool SupportsVR() override { return true; };
};
1 change: 1 addition & 0 deletions src/ShaderCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ namespace SIE
type == RE::BSShader::Type::Water ||
type == RE::BSShader::Type::Effect;
return type == RE::BSShader::Type::Lighting ||
type == RE::BSShader::Type::DistantTree ||
type == RE::BSShader::Type::Water ||
type == RE::BSShader::Type::Grass;
}
Expand Down

0 comments on commit bab9f89

Please sign in to comment.