Skip to content

Commit

Permalink
feat(VR): enable volumetric lighting
Browse files Browse the repository at this point in the history
  • Loading branch information
alandtse committed Oct 2, 2024
1 parent 9fd7253 commit dbab58d
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Info]
Version = 1-0-0
22 changes: 16 additions & 6 deletions package/Shaders/ISApplyVolumetricLighting.hlsl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "Common/DummyVSTexCoord.hlsl"
#include "Common/FrameBuffer.hlsli"
#include "Common/VR.hlsli"

typedef VS_OUTPUT PS_INPUT;

Expand Down Expand Up @@ -34,8 +35,16 @@ PS_OUTPUT main(PS_INPUT input)
{
PS_OUTPUT psout;

uint eyeIndex = GetEyeIndexFromTexCoord(input.TexCoord);
float2 screenPosition = GetDynamicResolutionAdjustedScreenPosition(input.TexCoord);
float depth = DepthTex.Sample(DepthSampler, screenPosition).x;

# ifdef VR
if (depth < 0.0001) { // not a valid location
psout.VL = 0.0;
return psout;
}
# endif
float repartition = clamp(RepartitionTex.SampleLevel(RepartitionSampler, depth, 0).x, 0, 0.9999);
float vl = g_IntensityX_TemporalY.x * VLTex.SampleLevel(VLSampler, float3(input.TexCoord, repartition), 0).x;

Expand All @@ -45,17 +54,18 @@ PS_OUTPUT main(PS_INPUT input)

if (0.001 < g_IntensityX_TemporalY.y) {
float2 motionVector = MotionVectorsTex.Sample(MotionVectorsSampler, screenPosition).xy;
float2 previousTexCoord = input.TexCoord + motionVector;
float2 previousScreenPosition = GetPreviousDynamicResolutionAdjustedScreenPosition(previousTexCoord);
float2 previousTexCoord = ConvertFromStereoUV(input.TexCoord, eyeIndex) + motionVector;
float2 previousScreenPosition = GetPreviousDynamicResolutionAdjustedScreenPosition(ConvertToStereoUV(previousTexCoord, eyeIndex));
float previousVl = PreviousFrameTex.Sample(PreviousFrameSampler, previousScreenPosition).x;
float previousDepth = PreviousDepthTex.Sample(PreviousDepthSampler, previousScreenPosition).x;

float temporalContribution = g_IntensityX_TemporalY.y * (1 - smoothstep(0, 1, min(1, 100 * abs(depth - previousDepth))));

float isValid = 0;
if (previousTexCoord.x >= 0 && previousTexCoord.x < 1 && previousTexCoord.y >= 0 && previousTexCoord.y < 1) {
isValid = 1;
}
float isValid = (previousTexCoord.x >= 0 && previousTexCoord.x < 1 && previousTexCoord.y >= 0 && previousTexCoord.y < 1
# ifdef VR
&& abs(previousDepth) > 0.0001
# endif
);
psout.VL = lerp(adjustedVl, previousVl, temporalContribution * isValid);
} else {
psout.VL = adjustedVl;
Expand Down
47 changes: 35 additions & 12 deletions package/Shaders/ISVolumetricLightingGenerateCS.hlsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include "Common/Constants.hlsli"
#include "Common/Random.hlsli"
#include "Common/VR.hlsli"

#if defined(CSHADER)
SamplerState ShadowmapSampler : register(s0);
Expand All @@ -16,21 +18,39 @@ RWTexture3D<float4> DensityCopyRW : register(u1);

cbuffer PerTechnique : register(b0)
{
float4x4 CameraViewProj : packoffset(c0);
float4x4 CameraViewProjInverse : packoffset(c4);
float4x3 ShadowMapProj[3] : packoffset(c8);
# ifndef VR
float4x4 CameraViewProj[1] : packoffset(c0);
float4x4 CameraViewProjInverse[1] : packoffset(c4);
float4x3 ShadowMapProj[1][3] : packoffset(c8);
float3 EndSplitDistances : packoffset(c17.x);
float ShadowMapCount : packoffset(c17.w);
float EnableShadowCasting : packoffset(c18);
float3 DirLightDirection : packoffset(c19);
float3 TextureDimensions : packoffset(c20);
float3 WindInput : packoffset(c21);
float3 WindInput[1] : packoffset(c21);
float InverseDensityScale : packoffset(c21.w);
float3 PosAdjust : packoffset(c22);
float3 PosAdjust[1] : packoffset(c22);
float IterationIndex : packoffset(c22.w);
float PhaseContribution : packoffset(c23.x);
float PhaseScattering : packoffset(c23.y);
float DensityContribution : packoffset(c23.z);
# else
float4x4 CameraViewProj[2] : packoffset(c0);
float4x4 CameraViewProjInverse[2] : packoffset(c8);
float4x3 ShadowMapProj[2][3] : packoffset(c16);
float3 EndSplitDistances : packoffset(c34.x);
float ShadowMapCount : packoffset(c34.w);
float EnableShadowCasting : packoffset(c35.x);
float3 DirLightDirection : packoffset(c36);
float3 TextureDimensions : packoffset(c37);
float3 WindInput[2] : packoffset(c38);
float InverseDensityScale : packoffset(c39.w);
float3 PosAdjust[2] : packoffset(c40);
float IterationIndex : packoffset(c41.w);
float PhaseContribution : packoffset(c42.x);
float PhaseScattering : packoffset(c42.y);
float DensityContribution : packoffset(c42.z);
# endif
}

[numthreads(32, 32, 1)] void main(uint3 dispatchID
Expand All @@ -44,29 +64,32 @@ cbuffer PerTechnique : register(b0)
{ 1.000000, 1.000000, 0 },
{ 1.000000, 1.000000, 1.000000 } };

float3 depthUv = dispatchID.xyz / TextureDimensions.xyz + 0.001 * StepCoefficients[IterationIndex].xyz;
float3 normalizedCoordinates = dispatchID.xyz / TextureDimensions.xyz;
float2 uv = normalizedCoordinates.xy;
uint eyeIndex = GetEyeIndexFromTexCoord(uv);
float3 depthUv = ConvertFromStereoUV(normalizedCoordinates, eyeIndex) + 0.001 * StepCoefficients[IterationIndex].xyz;
float depth = InverseRepartitionTex.SampleLevel(InverseRepartitionSampler, depthUv.z, 0).x;
float4 positionCS = float4(2 * depthUv.x - 1, 1 - 2 * depthUv.y, depth, 1);

float4 positionWS = mul(transpose(CameraViewProjInverse), positionCS);
float4 positionWS = mul(transpose(CameraViewProjInverse[eyeIndex]), positionCS);
positionWS /= positionWS.w;

float4 positionCSShifted = mul(transpose(CameraViewProj), positionWS);
float4 positionCSShifted = mul(transpose(CameraViewProj[eyeIndex]), positionWS);
positionCSShifted /= positionCSShifted.w;

float shadowMapDepth = positionCSShifted.z;

float shadowContribution = 1;
if (EndSplitDistances.z >= shadowMapDepth) {
float4x3 lightProjectionMatrix = ShadowMapProj[0];
float4x3 lightProjectionMatrix = ShadowMapProj[eyeIndex][0];
float shadowMapThreshold = 0.01;
float cascadeIndex = 0;
if (2.5 < ShadowMapCount && EndSplitDistances.y < shadowMapDepth) {
lightProjectionMatrix = ShadowMapProj[2];
lightProjectionMatrix = ShadowMapProj[eyeIndex][2];
shadowMapThreshold = 0;
cascadeIndex = 2;
} else if (EndSplitDistances.x < shadowMapDepth) {
lightProjectionMatrix = ShadowMapProj[1];
lightProjectionMatrix = ShadowMapProj[eyeIndex][1];
shadowMapThreshold = 0;
cascadeIndex = 1;
}
Expand Down Expand Up @@ -95,7 +118,7 @@ cbuffer PerTechnique : register(b0)
}
}

float3 noiseUv = 0.0125 * (InverseDensityScale * (positionWS.xyz + WindInput));
float3 noiseUv = 0.0125 * (InverseDensityScale * (positionWS.xyz + WindInput[0]));
float noise = NoiseTex.SampleLevel(NoiseSampler, noiseUv, 0).x;
float densityFactor = noise * (1 - 0.75 * smoothstep(0, 1, saturate(2 * positionWS.z / 300)));
float densityContribution = lerp(1, densityFactor, DensityContribution);
Expand Down
4 changes: 3 additions & 1 deletion src/Feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "Features/SubsurfaceScattering.h"
#include "Features/TerrainBlending.h"
#include "Features/TerrainShadows.h"
#include "Features/VolumetricLighting.h"
#include "Features/WaterLighting.h"
#include "Features/WetnessEffects.h"

Expand Down Expand Up @@ -124,7 +125,8 @@ const std::vector<Feature*>& Feature::GetFeatureList()
TerrainShadows::GetSingleton(),
ScreenSpaceGI::GetSingleton(),
Skylighting::GetSingleton(),
TerrainBlending::GetSingleton()
TerrainBlending::GetSingleton(),
VolumetricLighting::GetSingleton()
};

static std::vector<Feature*> featuresVR(features);
Expand Down
69 changes: 69 additions & 0 deletions src/Features/VolumetricLighting.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "VolumetricLighting.h"
#include "State.h"
#include "Util.h"

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(
VolumetricLighting::Settings,
EnabledVL);

void VolumetricLighting::DrawSettings()
{
if (ImGui::TreeNodeEx("Settings", ImGuiTreeNodeFlags_DefaultOpen)) {
if (!State::GetSingleton()->isVR) {
RenderImGuiSettingsTree(VLSettings, "Skyrim Settings");
} else {
if (ImGui::Checkbox("Enable Volumetric Lighting in VR", reinterpret_cast<bool*>(&settings.EnabledVL))) {
if (auto _tt = Util::HoverTooltipWrapper()) {
ImGui::Text("Enable Volumetric Lighting in VR");
}
SetBooleanSettings(hiddenVRSettings, GetName(), settings.EnabledVL);
}
if (settings.EnabledVL) {
RenderImGuiSettingsTree(VLSettings, "Skyrim Settings");
RenderImGuiSettingsTree(hiddenVRSettings, "hiddenVR");
}
}
ImGui::Spacing();
ImGui::TreePop();
}
}

void VolumetricLighting::LoadSettings(json& o_json)
{
settings = o_json;
LoadGameSettings(VLSettings);
}

void VolumetricLighting::SaveSettings(json& o_json)
{
o_json = settings;
SaveGameSettings(VLSettings);
}

void VolumetricLighting::RestoreDefaultSettings()
{
settings = {};
ResetGameSettingsToDefaults(VLSettings);
if (State::GetSingleton()->isVR) {
ResetGameSettingsToDefaults(hiddenVRSettings);
}
}

void VolumetricLighting::DataLoaded()
{
// if (REL::Module::IsVR() && settings.EnabledVL) {
// EnableBooleanSettings(hiddenVRSettings, GetName());
// enabledAtBoot = true;
// }
}

void VolumetricLighting::PostPostLoad()
{
if (REL::Module::IsVR() && settings.EnabledVL) {
EnableBooleanSettings(hiddenVRSettings, GetName());
}
}

void VolumetricLighting::Reset()
{
}
87 changes: 87 additions & 0 deletions src/Features/VolumetricLighting.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#pragma once

#include "Buffer.h"
#include "Feature.h"

struct VolumetricLighting : Feature
{
public:
static VolumetricLighting* GetSingleton()
{
static VolumetricLighting singleton;
return &singleton;
}

struct Settings
{
uint EnabledVL = true;
};

Settings settings;

bool enabledAtBoot = false;

virtual inline std::string GetName() override { return "Volumetric Lighting"; }
virtual inline std::string GetShortName() override { return "VolumetricLighting"; }

virtual void Reset() override;

virtual void SaveSettings(json&) override;
virtual void LoadSettings(json&) override;
virtual void RestoreDefaultSettings() override;
virtual void DrawSettings() override;
virtual void DataLoaded() override;
virtual void PostPostLoad() override;

std::map<std::string, gameSetting> VLSettings{
{ "bEnableVolumetricLighting:Display", { "Enable Volumetric Lighting (INI)", "Enables or disables volumetric lighting effects.", 0, true, false, true } },
{ "bVolumetricLightingDisableInterior:Display", { "Disable Interior Volumetric Lighting", "Disables volumetric lighting effects for interior spaces.", REL::Relocate<uintptr_t>(0, 0, 0x1ed4038), true, false, true } },
{ "bVolumetricLightingUpdateWeather:Display", { "Update Volumetric Lighting with Weather", "Updates volumetric lighting based on weather conditions.", 0, true, false, true } },
{ "bVolumetricLightingEnableTemporalAccumulation:Display", { "Enable Volumetric Lighting Temporal Accumulation", "Enables temporal accumulation for volumetric lighting effects.", 0, true, false, true } },
{ "iVolumetricLightingQuality:Display", { "Lighting Quality", "Adjusts the quality of volumetric lighting. [-1,-2] (off, low, mid, high).", REL::Relocate<uintptr_t>(0, 0, 0x1ed4030), 1, -1, 2 } },
{ "fVolumetricLightingCustomColorContribution:Display", { "Custom Color Contribution", "Controls the contribution of custom colors to volumetric lighting.", 0, 0.0f, 0.0f, 1.0f } },
{ "fVolumetricLightingDensityContribution:Display", { "Density Contribution", "Adjusts the density contribution of volumetric lighting.", 0, 0.3f, 0.0f, 1.0f } },
{ "fVolumetricLightingDensityScale:Display", { "Density Scale", "Scales the density of volumetric lighting effects.", 0, 300.0f, 0.0f, 1000.0f } },
{ "fVolumetricLightingIntensity:Display", { "Intensity", "Sets the intensity of volumetric lighting effects.", 0, 2.0f, 0.0f, 10.0f } },
{ "fVolumetricLightingPhaseContribution:Display", { "Phase Contribution", "Controls the contribution of phase to the volumetric lighting effects.", 0, 0.83f, 0.0f, 1.0f } },
{ "fVolumetricLightingPhaseScattering:Display", { "Phase Scattering", "Sets the phase scattering for volumetric lighting.", 0, 0.85f, 0.0f, 1.0f } },
{ "fVolumetricLightingRangeFactor:Display", { "Range Factor", "Adjusts the range factor for volumetric lighting effects.", 0, 40.0f, 0.0f, 100.0f } },
{ "fVolumetricLightingTemporalAccumulationFactor:Display", { "Temporal Accumulation Factor", "Controls the strength of temporal accumulation in volumetric lighting.", 0, 0.75f, 0.0f, 5.0f } },
{ "fVolumetricLightingWindFallingSpeed:Display", { "Wind Falling Speed", "Sets the speed at which wind affects falling particles in volumetric lighting.", 0, 0.3f, 0.0f, 1.0f } },
{ "fVolumetricLightingWindSpeedScale:Display", { "Wind Speed Scale", "Scales the wind speed effect on volumetric lighting.", 0, 15.0f, 0.0f, 50.0f } },
// { "iVolumetricLightingNoiseTextureDepth:Display", { "Noise Texture Depth", "Sets the depth of the noise texture used for volumetric lighting.", 0, 32, 1, 128 } },
// { "iVolumetricLightingNoiseTextureHeight:Display", { "Noise Texture Height", "Sets the height of the noise texture used for volumetric lighting.", 0, 32, 1, 128 } },
// { "iVolumetricLightingNoiseTextureWidth:Display", { "Noise Texture Width", "Sets the width of the noise texture used for volumetric lighting.", 0, 32, 1, 128 } },
// { "iVolumetricLightingTextureDepthHigh:Display", { "High Depth Texture", "Sets the depth for the high-quality volumetric lighting texture.", 0, 90, 1, 128 } },
// { "iVolumetricLightingTextureDepthMedium:Display", { "Medium Depth Texture", "Sets the depth for the medium-quality volumetric lighting texture.", 0, 70, 1, 128 } },
// { "iVolumetricLightingTextureDepthLow:Display", { "Low Depth Texture", "Sets the depth for the low-quality volumetric lighting texture.", 0, 50, 1, 128 } },
// { "iVolumetricLightingTextureFormatHigh:Display", { "High Texture Format", "Sets the format for the high-quality volumetric lighting texture.", 0, 1, 0, 2 } },
// { "iVolumetricLightingTextureFormatMedium:Display", { "Medium Texture Format", "Sets the format for the medium-quality volumetric lighting texture.", 0, 1, 0, 2 } },
// { "iVolumetricLightingTextureFormatLow:Display", { "Low Texture Format", "Sets the format for the low-quality volumetric lighting texture.", 0, 0, 0, 2 } },
// { "iVolumetricLightingTextureHeightHigh:Display", { "High Texture Height", "Sets the height for the high-quality volumetric lighting texture.", 0, 192, 1, 512 } },
// { "iVolumetricLightingTextureHeightMedium:Display", { "Medium Texture Height", "Sets the height for the medium-quality volumetric lighting texture.", 0, 128, 1, 512 } },
// { "iVolumetricLightingTextureHeightLow:Display", { "Low Texture Height", "Sets the height for the low-quality volumetric lighting texture.", 0, 96, 1, 512 } },
// { "iVolumetricLightingTextureWidthHigh:Display", { "High Texture Width", "Sets the width for the high-quality volumetric lighting texture.", 0, 320, 1, 512 } },
// { "iVolumetricLightingTextureWidthMedium:Display", { "Medium Texture Width", "Sets the width for the medium-quality volumetric lighting texture.", 0, 224, 1, 512 } },
// { "iVolumetricLightingTextureWidthLow:Display", { "Low Texture Width", "Sets the width for the low-quality volumetric lighting texture.", 0, 160, 1, 512 } },
};

std::map<std::string, gameSetting> hiddenVRSettings{
{ "bEnableVolumetricLighting:Display", { "Enable Volumetric Lighting Shaders (INI) ",
"Enables volumetric lighting effects by creating shaders. "
"Needed at startup. ",
0x1ed63d8, true, false, true } },
{ "bVolumetricLightingEnable:Display", { "Enable Volumetric Lighting (INI))", "Enables volumetric lighting. ", 0x3485360, true, false, true } },
{ "bVolumetricLightingUpdateWeather:Display", { "Enable Volumetric Lighting (Weather) (INI) ",
"Enables volumetric lighting for weather. "
"Only used during startup and used to set bVLWeatherUpdate.",
0x3485361, true, false, true } },
{ "bVLWeatherUpdate", { "Enable Volumetric Lighting (Weather)", "Enables volumetric lighting for weather.", 0x3485363, true, false, true } },
{ "bVolumetricLightingEnabled_143232EF0", { "Enable Volumetric Lighting (Papyrus) ",
"Enables volumetric lighting. "
"This is the Papyrus command. ",
REL::Relocate<uintptr_t>(0x3232ef0, 0, 0x3485362), true, false, true } },
};

virtual bool SupportsVR() override { return true; };
};

0 comments on commit dbab58d

Please sign in to comment.