Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#include "Common/FrameBuffer.hlsli"

#include "LightLimitFix/Common.hlsli"

cbuffer PerFrame : register(b0)
{
row_major float4x4 InvProjMatrix[2];
float LightsNear;
float LightsFar;
uint2 pad0;
Expand All @@ -16,7 +17,7 @@ float3 GetPositionVS(float2 texcoord, float depth, int eyeIndex = 0)
clipSpaceLocation.y *= -1;
clipSpaceLocation.z = depth;
clipSpaceLocation.w = 1.0f;
float4 homogenousLocation = mul(clipSpaceLocation, InvProjMatrix[eyeIndex]);
float4 homogenousLocation = mul(FrameBuffer::CameraProjInverse[eyeIndex], clipSpaceLocation);
return homogenousLocation.xyz / homogenousLocation.w;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "Common/FrameBuffer.hlsli"
#include "LightLimitFix/Common.hlsli"

cbuffer PerFrame : register(b0)
Expand All @@ -19,12 +20,12 @@ RWStructuredBuffer<LightGrid> lightGrid : register(u2);

groupshared Light sharedLights[GROUP_SIZE];

bool LightIntersectsCluster(float3 position, float radius, ClusterAABB cluster)
bool LightIntersectsCluster(float3 position, float radiusSquared, ClusterAABB cluster)
{
float3 closest = max(cluster.minPoint.xyz, min(position, cluster.maxPoint.xyz));

float3 dist = closest - position;
return dot(dist, dist) <= radius;
return dot(dist, dist) <= radiusSquared;
}

[numthreads(NUMTHREAD_X, NUMTHREAD_Y, NUMTHREAD_Z)] void main(
Expand Down Expand Up @@ -56,13 +57,18 @@ bool LightIntersectsCluster(float3 position, float radius, ClusterAABB cluster)
for (uint i = 0; i < LightCount; i++) {
Light light = lights[i];

float radius = light.radius * light.radius;
float radiusSquared = light.radius * light.radius;

#if defined(VR)
[branch] if (LightIntersectsCluster(light.positionVS[0].xyz, radius, cluster) || LightIntersectsCluster(light.positionVS[1].xyz, radius, cluster))
float3 positionVSLeft = FrameBuffer::WorldToView(light.positionWS[0].xyz, true, 0);
float3 positionVSRight = FrameBuffer::WorldToView(light.positionWS[1].xyz, true, 0);

[branch] if (LightIntersectsCluster(positionVSLeft, radiusSquared, cluster) || LightIntersectsCluster(positionVSRight, radiusSquared, cluster))
{
#else
[branch] if (LightIntersectsCluster(light.positionVS[0].xyz, radius, cluster))
float3 positionVS = FrameBuffer::WorldToView(light.positionWS[0].xyz, true, 0);

[branch] if (LightIntersectsCluster(positionVS, radiusSquared, cluster))
{
#endif
visibleLightIndices[visibleLightCount] = i;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ struct Light
float fadeZone;
float sizeBias;
float4 positionWS[2];
float4 positionVS[2];
uint4 roomFlags;
uint lightFlags;
uint shadowLightIndex;
Expand Down
62 changes: 8 additions & 54 deletions features/Light Limit Fix/Shaders/LightLimitFix/LightLimitFix.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -21,68 +21,22 @@ namespace LightLimitFix
{
const uint3 clusterSize = SharedData::lightLimitFixSettings.ClusterSize.xyz;

z = max(z, SharedData::CameraData.y);
if (!FrameBuffer::FrameParams.y) // Fix first person lights
uv = 0.5;

if (z > SharedData::CameraData.x)
return false;
z = max(z, SharedData::CameraData.y);

float clampedZ = clamp(z, SharedData::CameraData.y, SharedData::CameraData.x);
uint clusterZ = uint(max((log2(z) - log2(SharedData::CameraData.y)) * clusterSize.z / log2(SharedData::CameraData.x / SharedData::CameraData.y), 0.0));
uint clusterZ = log(z / SharedData::CameraData.y) * clusterSize.z / log(SharedData::CameraData.x / SharedData::CameraData.y);
uint3 cluster = uint3(uint2(uv * clusterSize.xy), clusterZ);

// Bounds validation to prevent out-of-range cluster indices
if (any(cluster >= clusterSize))
return false;

clusterIndex = cluster.x + (clusterSize.x * cluster.y) + (clusterSize.x * clusterSize.y * cluster.z);
return true;
}

bool IsSaturated(float value)
{
return value == saturate(value);
}

bool IsSaturated(float2 value)
{
return IsSaturated(value.x) && IsSaturated(value.y);
}

float ContactShadows(float3 viewPosition, float noise2D, float3 lightDirectionVS, uint contactShadowSteps, uint a_eyeIndex = 0)
{
if (contactShadowSteps == 0)
return 1.0;

float2 depthDeltaMult = float2(0.20, 0.05);

// Extend contact shadow distance
lightDirectionVS *= 2.0;

// Offset starting position with interleaved gradient noise
viewPosition += lightDirectionVS * noise2D;

// Accumulate samples
float contactShadow = 0.0;
for (uint i = 0; i < contactShadowSteps; i++) {
// Step the ray
viewPosition += lightDirectionVS;

float2 rayUV = FrameBuffer::ViewToUV(viewPosition, true, a_eyeIndex);

// Ensure the UV coordinates are inside the screen
if (!IsSaturated(rayUV))
break;

// Compute the difference between the ray's and the camera's depth
float rayDepth = SharedData::GetScreenDepth(rayUV, a_eyeIndex);

// Difference between the current ray distance and the marched light
float depthDelta = viewPosition.z - rayDepth;
if (rayDepth > 16.5) // First person
contactShadow = max(contactShadow, saturate(depthDelta * depthDeltaMult.x) - saturate(depthDelta * depthDeltaMult.y));
if (contactShadow == 1.0)
break;
}

return 1.0 - saturate(contactShadow);
}

// Copyright 2019 Google LLC.
// SPDX-License-Identifier: Apache-2.0

Expand Down
3 changes: 1 addition & 2 deletions package/Shaders/Common/SharedData.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,9 @@ namespace SharedData

struct LightLimitFixSettings
{
uint EnableContactShadows;
uint EnableLightsVisualisation;
uint LightsVisualisationMode;
float pad0;
float2 pad0;
uint4 ClusterSize;
};

Expand Down
25 changes: 4 additions & 21 deletions package/Shaders/Lighting.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -2545,8 +2545,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
lightOffset = LightLimitFix::lightGrid[clusterIndex].offset;
}

uint contactShadowSteps = round(4.0 * (1.0 - saturate(viewPosition.z / 1024.0)));

[loop] for (uint lightIndex = 0; lightIndex < totalLightCount; lightIndex++)
{
LightLimitFix::Light light;
Expand Down Expand Up @@ -2588,20 +2586,6 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
float3 normalizedLightDirection = normalize(lightDirection);
float lightAngle = dot(worldNormal.xyz, normalizedLightDirection.xyz);

float contactShadow = 1.0;

# if defined(DEFERRED)
[branch] if (
SharedData::lightLimitFixSettings.EnableContactShadows &&
!(light.lightFlags & LightLimitFix::LightFlags::Simple) &&
shadowComponent != 0.0 &&
lightAngle > 0.0)
{
float3 normalizedLightDirectionVS = normalize(light.positionVS[eyeIndex].xyz - viewPosition.xyz);
contactShadow = LightLimitFix::ContactShadows(viewPosition, screenNoise, normalizedLightDirectionVS, contactShadowSteps, eyeIndex);
}
# endif

float3 refractedLightDirection = normalizedLightDirection;
# if defined(TRUE_PBR) && !defined(LANDSCAPE) && !defined(LODLANDSCAPE)
[branch] if ((PBRFlags & PBR::Flags::InterlayerParallax) != 0)
Expand All @@ -2618,8 +2602,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
SharedData::extendedMaterialSettings.EnableShadows &&
!(light.lightFlags & LightLimitFix::LightFlags::Simple) &&
lightAngle > 0.0 &&
shadowComponent != 0.0 &&
contactShadow != 0.0)
shadowComponent != 0.0)
{
float3 lightDirectionTS = normalize(mul(refractedLightDirection, tbn).xyz);
# if defined(PARALLAX)
Expand All @@ -2644,7 +2627,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)

# if defined(TRUE_PBR)
{
PBR::LightProperties lightProperties = PBR::InitLightProperties(lightColor, lightShadow * contactShadow, parallaxShadow);
PBR::LightProperties lightProperties = PBR::InitLightProperties(lightColor, lightShadow, parallaxShadow);
float3 pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor;
PBR::GetDirectLightInput(pointDiffuseColor, coatPointDiffuseColor, pointTransmissionColor, pointSpecularColor, worldNormal.xyz, coatWorldNormal, refractedViewDirection, viewDirection, refractedLightDirection, normalizedLightDirection, lightProperties, pbrSurfaceProperties, tbnTr, uvOriginal);
lightsDiffuseColor += pointDiffuseColor;
Expand All @@ -2659,7 +2642,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
# else
lightColor *= lightShadow;

float3 lightDiffuseColor = lightColor * contactShadow * parallaxShadow * saturate(lightAngle.xxx);
float3 lightDiffuseColor = lightColor * parallaxShadow * saturate(lightAngle.xxx);
Comment thread
doodlum marked this conversation as resolved.
float lightBacklighting = 1.0 + saturate(dot(normalizedLightDirection.xyz, viewDirection));

# if defined(SOFT_LIGHTING)
Expand All @@ -2679,7 +2662,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
float hairShadow = Hair::HairSelfShadow(input.WorldPosition.xyz, normalizedLightDirection, screenNoise, eyeIndex);
float3 lightSpecularColor = 0;
float3 lightTransmissionColor = 0;
Hair::GetHairDirectLight(lightDiffuseColor, lightSpecularColor, lightTransmissionColor, hairT, normalizedLightDirection, viewDirection, worldNormal.xyz, vertexNormal.xyz, lightColor * contactShadow, SharedData::hairSpecularSettings.HairGlossiness, hairShadow, uv, baseColor.xyz);
Hair::GetHairDirectLight(lightDiffuseColor, lightSpecularColor, lightTransmissionColor, hairT, normalizedLightDirection, viewDirection, worldNormal.xyz, vertexNormal.xyz, lightColor, SharedData::hairSpecularSettings.HairGlossiness, hairShadow, uv, baseColor.xyz);
lightsSpecularColor += lightSpecularColor;
transmissionColor += lightTransmissionColor;
} else {
Expand Down
19 changes: 18 additions & 1 deletion src/Deferred.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,28 @@ void Deferred::PrepassPasses()
if (!shaderCache->IsEnabled())
return;

auto context = globals::game::renderer->GetRuntimeData().context;
auto context = globals::d3d::context;
context->OMSetRenderTargets(0, nullptr, nullptr); // Unbind all bound render targets

globals::game::stateUpdateFlags->set(RE::BSGraphics::ShaderFlags::DIRTY_RENDERTARGET); // Run OMSetRenderTargets again

{
ID3D11Buffer* buffers[1] = { *globals::game::perFrame.get() };

ID3D11Buffer* vrBuffer = nullptr;

if (REL::Module::IsVR()) {
static REL::Relocation<ID3D11Buffer**> VRValues{ REL::Offset(0x3180688) };
vrBuffer = *VRValues.get();
}
if (vrBuffer) {
context->CSSetConstantBuffers(12, 1, buffers);
context->CSSetConstantBuffers(13, 1, &vrBuffer);
} else {
context->CSSetConstantBuffers(12, 1, buffers);
}
}

globals::truePBR->PrePass();
for (auto* feature : Feature::GetFeatureList()) {
if (feature->loaded) {
Expand Down
Loading