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,2 +1,2 @@
[Info]
Version = 1-0-0
Version = 1-1-0
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace InverseSquareLighting
float isEnabled = 1.0f - float((light.lightFlags & LightLimitFix::LightFlags::Disabled) != 0);
float isInvSq = float((light.lightFlags & LightLimitFix::LightFlags::InverseSquare) != 0);

float invSq = SCALED_UNITS_SQ * rcp(distance * distance + SCALED_UNITS_SQ);
float invSq = SCALED_UNITS_SQ * rcp(distance * distance + SCALED_UNITS_SQ * light.size * light.size / 2.0f);
float t = saturate((light.radius - distance) * light.fadeZone);
float fastSmoothstep = t * t * (3.0f - 2.0f * t);
invSq *= fastSmoothstep;
Expand Down
8 changes: 6 additions & 2 deletions features/Light Limit Fix/Shaders/LightLimitFix/Common.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,18 @@ struct LightGrid
struct Light
{
float3 color;
float fade;
float radius;
float invRadius;
float fadeZone;
float size;
float4 positionWS[2];
float4 positionVS[2];
uint4 roomFlags;
uint lightFlags;
uint shadowLightIndex;
float invRadius;
float fadeZone;
uint pad0;
uint pad1;
};

#endif //__LLF_COMMON_DEPENDENCY_HLSL__
2 changes: 1 addition & 1 deletion package/Shaders/Common/PBR.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ namespace PBR
// [Lagarde et al. 2014, "Moving Frostbite to Physically Based Rendering 3.0"]
float SpecularAOLagarde(float NdotV, float ao, float roughness)
{
return saturate(pow(NdotV + ao, exp2(-16.0 * roughness - 1.0)) - 1.0 + ao);
return saturate(pow(abs(NdotV + ao), exp2(-16.0 * roughness - 1.0)) - 1.0 + ao);
}

#if defined(GLINT)
Expand Down
24 changes: 14 additions & 10 deletions src/Features/InverseSquareLighting.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "InverseSquareLighting.h"
#include "Features/InverseSquareLighting/Common.h"
#include "LightLimitFix.h"
#include <numbers>

void InverseSquareLighting::DrawSettings()
{
Expand Down Expand Up @@ -38,6 +39,8 @@ void InverseSquareLighting::SetExtLightData(RE::NiLight* niLight, const RE::TESO
runtimeData->flags.set(LightLimitFix::LightFlags::InverseSquare);
runtimeData->cutoffOverride = std::clamp(ligh->data.fallofExponent, 0.01f, 1.f);
runtimeData->lighFormId = ligh->formID;
const float size = ligh->data.fov >= 50.0f ? std::numbers::sqrt2_v<float> : ligh->data.fov;
runtimeData->size = std::clamp(size, 0.01f, 50.0f);
}

void InverseSquareLighting::ProcessLight(LightLimitFix::LightData& light, RE::BSLight* bsLight, RE::NiLight* niLight) const
Expand All @@ -56,26 +59,27 @@ void InverseSquareLighting::ProcessLight(LightLimitFix::LightData& light, RE::BS

if (bsLight->pointLight && isInvSq) {
const float intensity = runtimeData->fade * 4;
light.radius = CalculateRadius(intensity, bsLight->IsShadowLight(), runtimeData->cutoffOverride);
light.radius = CalculateRadius(intensity, bsLight->IsShadowLight(), runtimeData->cutoffOverride, runtimeData->size);
runtimeData->radius = light.radius;
light.invRadius = 1.f / light.radius;
light.fadeZone = 1.f / (light.radius * std::clamp(FadeZoneBase * light.invRadius, 0.f, 1.f));
runtimeData->radius.x = light.radius;
runtimeData->radius.y = light.radius;
runtimeData->radius.z = light.radius;
light.size = runtimeData->size;
light.color /= std::max(0.001f, std::max(light.color.x, std::max(light.color.y, light.color.z)));
light.color *= intensity;
light.fade = intensity;
} else {
light.radius = runtimeData->radius.x;
light.radius = runtimeData->radius;
light.invRadius = 1.f / light.radius;
light.color *= runtimeData->fade;
light.fade = runtimeData->fade;
}
}

float InverseSquareLighting::CalculateRadius(const float intensity, const bool shadowCaster, const float cutoffOverride)
float InverseSquareLighting::CalculateRadius(const float intensity, const bool shadowCaster, const float cutoffOverride, const float size)
{
float cutoff = shadowCaster ? DefaultShadowCasterCutoff : DefaultCutoff;
cutoff = cutoffOverride == 1.f ? cutoff : cutoffOverride;
const float radius = std::sqrt(ScaledUnitsSq * ((intensity - cutoff) / cutoff));
const float radius = std::sqrt(ScaledUnitsSq * ((2 * intensity - cutoff * size * size) / (2 * cutoff)));
return isnan(radius) ? 1.f : radius;
}

Expand All @@ -85,9 +89,9 @@ inline float InverseSquareLighting::SmoothStep(const float edge0, const float ed
return t * t * (3.0f - 2.0f * t);
}

float InverseSquareLighting::GetAttenuation(const float distance, const float radius)
float InverseSquareLighting::GetAttenuation(const float distance, const float radius, const float size)
{
const float attenuation = ScaledUnitsSq / (distance * distance + ScaledUnitsSq);
const float attenuation = ScaledUnitsSq / (distance * distance + ScaledUnitsSq * size * size / 2);
const float fadeZone = std::clamp(FadeZoneBase / radius, 0.0f, 1.0f);
const float fade = SmoothStep(0, radius * fadeZone, radius - distance);
return attenuation * fade;
Expand All @@ -105,7 +109,7 @@ float InverseSquareLighting::BSLight_GetLuminance::thunk(RE::BSLight* bsLight, R
return func(bsLight, targetPosition, refLight);

const float dist = niLight->world.translate.GetDistance(*targetPosition);
const float attenuation = GetAttenuation(dist, runtimeData->radius.x);
const float attenuation = GetAttenuation(dist, runtimeData->radius, runtimeData->size);
const float luminance = (runtimeData->diffuse.red + runtimeData->diffuse.green + runtimeData->diffuse.blue) * runtimeData->fade * attenuation * (1.0f / 3.0f);
bsLight->luminance = luminance;

Expand Down
4 changes: 2 additions & 2 deletions src/Features/InverseSquareLighting.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ struct InverseSquareLighting : Feature

virtual void PostPostLoad() override;

static float CalculateRadius(float intensity, bool shadowCaster, float cutoffOverride);
static float CalculateRadius(float intensity, bool shadowCaster, float cutoffOverride, float size);

void ProcessLight(LightLimitFix::LightData& light, RE::BSLight* bsLight, RE::NiLight* niLight) const;

static float GetAttenuation(float distance, float radius);
static float GetAttenuation(float distance, float radius, float size);

struct CreatePointLight
{
Expand Down
4 changes: 3 additions & 1 deletion src/Features/InverseSquareLighting/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ struct ISLCommon
float cutoffOverride;
RE::FormID lighFormId;
RE::NiColor diffuse;
RE::NiPoint3 radius;
float radius;
float pad1C;
float size;
float fade;
std::uint32_t unk138;

Expand Down
13 changes: 7 additions & 6 deletions src/Features/InverseSquareLighting/LightEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,14 @@ void LightEditor::DrawSettings()

if (isInvSq)
ImGui::BeginDisabled();
ImGui::SliderFloat("Radius", &current.data.radius.x, 2.f, 8096.f, "%.0f");
ImGui::SliderFloat("Radius", &current.data.radius, 2.f, 8096.f, "%.0f");
if (isInvSq)
ImGui::EndDisabled();

if (isInvSq)
ImGui::SliderFloat("Cutoff Override", &current.data.cutoffOverride, 0.01f, 1.f, "%.3f", ImGuiSliderFlags_AlwaysClamp);
if (isInvSq) {
ImGui::SliderFloat("Size", &current.data.size, 0.01f, 10.0f, "%.3f");
ImGui::SliderFloat("Cutoff", &current.data.cutoffOverride, 0.01f, 1.f, "%.3f", ImGuiSliderFlags_AlwaysClamp);
}

ImGui::Spacing();
ImGui::Spacing();
Expand Down Expand Up @@ -258,10 +260,9 @@ void LightEditor::UpdateSelectedLight(RE::TESObjectREFR* refr, RE::TESObjectLIGH

if (current.data.flags.any(LightLimitFix::LightFlags::InverseSquare)) {
current.data.radius = runtimeData->radius;
runtimeData->cutoffOverride = std::clamp(current.data.cutoffOverride, 0.01f, 1.f);
runtimeData->cutoffOverride = std::clamp(current.data.cutoffOverride, 0.01f, 1.0f);
runtimeData->size = std::clamp(current.data.size, 0.1f, 50.0f);
} else {
current.data.radius.y = current.data.radius.x;
current.data.radius.z = current.data.radius.x;
runtimeData->radius = current.data.radius;
runtimeData->cutoffOverride = current.data.cutoffOverride;
}
Expand Down
1 change: 1 addition & 0 deletions src/Features/LightLimitFix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ void LightLimitFix::BSLightingShader_SetupGeometry_GeometrySetupConstantPointLig
} else {
light.radius = runtimeData.radius.x;
light.color *= runtimeData.fade;
light.fade = runtimeData.fade;
}

light.color *= bsLight->lodDimmer;
Expand Down
8 changes: 6 additions & 2 deletions src/Features/LightLimitFix.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,18 @@ struct LightLimitFix : Feature
struct alignas(16) LightData
{
float3 color;
float fade;
float radius;
float invRadius;
float fadeZone;
float size;
PositionOpt positionWS[2];
PositionOpt positionVS[2];
uint128_t roomFlags = uint32_t(0);
stl::enumeration<LightFlags> lightFlags;
uint32_t shadowMaskIndex = 0;
float invRadius;
float fadeZone;
uint pad0;
uint pad1;
};

struct ClusterAABB
Expand Down