Skip to content
Draft
Show file tree
Hide file tree
Changes from 122 commits
Commits
Show all changes
160 commits
Select commit Hold shift + click to select a range
0148389
new ll
jiayev Apr 18, 2025
b91ead8
ambient, emissive and particle fix
jiayev Apr 18, 2025
b5a6fea
fix wrong light color
jiayev Apr 18, 2025
7f305f5
fixes some fog issue
jiayev Apr 18, 2025
ebd04c8
LOD and project
jiayev Apr 18, 2025
f7295cc
revert ssr change
jiayev Apr 18, 2025
45d8b5f
fix sky
jiayev Apr 18, 2025
c60e7bf
other fixes
jiayev Apr 18, 2025
4d520e5
distanttree fix
jiayev Apr 18, 2025
e5da64e
real fix
jiayev Apr 19, 2025
e4c4c1d
fix effect
jiayev Apr 19, 2025
208411a
seperate fade for light color
jiayev Apr 19, 2025
3fce82b
Merge branch 'dev' into ll-renew
jiayev Apr 20, 2025
c3d39ad
fix dalc for non deferred
jiayev Apr 21, 2025
432c87f
correct dalc for deferred and grass
jiayev Apr 21, 2025
b8cb29f
fix: ensure base color is clamped to avoid negative values
jiayev Apr 21, 2025
d359396
fix: apply gamma correction to color calculation in sky
jiayev Apr 21, 2025
7eae436
fix: apply clamping to color values in gamma conversion functions
jiayev Apr 22, 2025
979d7fc
Merge branch 'dev' into ll-renew
jiayev Apr 22, 2025
3b53269
Merge branch 'dev' into ll-renew
jiayev Apr 23, 2025
5114ce7
moved to feature
jiayev Apr 23, 2025
00fffa3
Revert "distanttree fix"
jiayev Apr 23, 2025
ec4c68b
redure fog to half gamma
jiayev Apr 23, 2025
9d6815d
feat: add gamma correction option to linear lighting settings
jiayev Apr 24, 2025
f21266d
fix: conflic with isl
jiayev Apr 26, 2025
74a1c46
fix: add fade for billboard light
jiayev Apr 26, 2025
63b7ded
revert some conversion to half gamma for consistency
jiayev Apr 26, 2025
a3ced52
fix projected mismatch
jiayev Apr 27, 2025
c30aaa5
fix: correct gamma conversion for volumetric lighting
jiayev Apr 27, 2025
1599704
fix: hopefully really fix ash mismatch
jiayev Apr 28, 2025
fc01e60
Merge branch 'dev' into ll-feature
jiayev Apr 30, 2025
d811e96
revert added back invradius
jiayev Apr 30, 2025
a1a3f82
feat: add GammaToLinearLuminancePreserving function and update lighti…
jiayev Apr 30, 2025
b5fd6d1
Revert "revert added back invradius"
jiayev Apr 30, 2025
e6b3cc7
Revert "fix: add fade for billboard light"
jiayev Apr 30, 2025
9f54e09
Revert "fix: conflic with isl"
jiayev Apr 30, 2025
3ede393
revert fade changes
jiayev Apr 30, 2025
314aaf3
revert some missing changes
jiayev Apr 30, 2025
28bd4a6
feat: replace GammaToLinearLuminancePreserving with GammaToLinearLumi…
jiayev Apr 30, 2025
d4d4dfa
fix: update gamma conversion to use GammaToLinearLuminancePreservingL…
jiayev May 3, 2025
579a11e
fix: membrane color
jiayev May 8, 2025
fdfcb4b
fix format error
jiayev May 8, 2025
0e96ff7
revert dalc to half linear
jiayev May 8, 2025
ddb55e3
fix inventory gamma correction
jiayev May 9, 2025
7dbe301
fix SharedData
jiayev May 14, 2025
e3416be
disable ll while loading
jiayev May 15, 2025
7475d63
see if it fix slash effect
jiayev May 15, 2025
a8c639f
fix logic
jiayev May 16, 2025
52f6652
fix loading menu logic
jiayev May 16, 2025
3ffd38c
Merge branch 'dev' into ll-feature
jiayev May 18, 2025
0988b84
Merge branch 'dev' into ll-feature
jiayev May 18, 2025
5d96ccc
Merge branch 'dev' into ll-feature
jiayev May 19, 2025
5df25a9
Merge branch 'skin' into ll-f-merge
jiayev May 19, 2025
5b1c8a9
Merge branch 'dev' into ll-feature
jiayev May 20, 2025
c652501
add gamma settings
jiayev May 20, 2025
227d0e2
light edits
jiayev May 20, 2025
18dffad
fix compile error
jiayev May 20, 2025
7bf4524
add more sliders
jiayev May 20, 2025
0fd42f9
style: 🎨 apply clang-format changes
jiayev May 20, 2025
8b698fd
Merge branch 'll-feature' of https://github.com/jiayev/skyrim-communi…
jiayev May 20, 2025
fc936f5
style: 🎨 apply clang-format changes
jiayev May 20, 2025
43e5d4b
correct math
jiayev May 20, 2025
4a753fe
possibly fix loading menu ll
jiayev May 24, 2025
9505178
add more sliders
jiayev May 25, 2025
fe8c617
see if this work
jiayev May 25, 2025
4ad8320
fix typo
jiayev May 25, 2025
d5b61c4
add missed change
jiayev May 25, 2025
d1a9740
add sky slider, don't change fog alpha
jiayev May 25, 2025
c1497ee
fix missed caused error
jiayev May 25, 2025
d9f136f
fix effect (sort of)
jiayev May 25, 2025
7fa6387
revert the project change
jiayev May 25, 2025
7e1bd58
Merge branch 'dev' into ll-feature
jiayev Jun 18, 2025
f322c32
add irradiance color function
jiayev Jun 18, 2025
299136c
add info
jiayev Jun 18, 2025
807e409
fix error
jiayev Jun 19, 2025
a49fb96
hair ll
jiayev Jun 19, 2025
98b4e65
add vl and lf sliders
jiayev Jun 23, 2025
c62a82a
Merge branch 'dev' into ll-feature
jiayev Jun 26, 2025
b0457f4
Merge branch 'dev' into ll-feature
jiayev Jun 28, 2025
f70c8bc
add effect sliders
jiayev Jun 29, 2025
fef77d1
simplify linear lighting checks using ENABLE_LL macro
jiayev Jun 29, 2025
8f58636
Merge branch 'dev' into ll-feature
jiayev Jul 1, 2025
1216d15
refactor to remove ifs, add water slider
jiayev Jul 1, 2025
efa78d9
fix lodland color
jiayev Jul 3, 2025
aac2653
add util funcs
jiayev Jul 4, 2025
a03955a
Merge branch 'dev' into ll-feature
jiayev Jul 18, 2025
4296e85
Merge branch 'dev' into ll-feature
jiayev Jul 19, 2025
046d2b8
hair ll adapt
jiayev Jul 19, 2025
3aa9555
Merge branch 'dev' into ll-feature
jiayev Jul 20, 2025
7e6fc9f
Merge branch 'dev' into ll-feature
jiayev Jul 27, 2025
8cc0265
remove pbr compensations
jiayev Jul 28, 2025
9ede370
add vanilla lighting multipliers
jiayev Jul 29, 2025
d144657
add sliders to menu
jiayev Jul 29, 2025
055fdb2
Merge branch 'dev' into ll-feature
jiayev Jul 29, 2025
50c5f93
Merge branch 'dev' into ll-feature
jiayev Jul 30, 2025
e85e804
ll getsingleton fix
jiayev Jul 30, 2025
0e85989
Merge branch 'dev' into ll-feature
jiayev Jul 31, 2025
d287991
use light fade property for ll
jiayev Jul 31, 2025
7e8e762
fix error
jiayev Jul 31, 2025
56f5eea
change default settings
jiayev Jul 31, 2025
b2c257c
fix crashing
jiayev Jul 31, 2025
e0c2277
fix reflection pass
jiayev Jul 31, 2025
dd44727
fix flickering
jiayev Jul 31, 2025
7121e9b
set to match color
jiayev Aug 3, 2025
b0a3389
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Aug 3, 2025
7cfd09f
fix warning
jiayev Aug 3, 2025
cf2708c
ai suggestions
jiayev Aug 3, 2025
d035c62
some fixes
jiayev Aug 3, 2025
e22eef2
fix truncation of vector type
jiayev Aug 3, 2025
e8b5dad
add fade for billboard lights again
jiayev Aug 4, 2025
595bcf8
enable ll for ibl dalc, add light mult slider
jiayev Aug 4, 2025
0df2b7f
fix compile error
jiayev Aug 4, 2025
a6ae417
Merge branch 'dev' into ll-feature
jiayev Aug 8, 2025
9e3a32e
Merge branch 'dev' into ll-feature
jiayev Aug 10, 2025
05a8e87
add linear sunlight flag
jiayev Aug 10, 2025
f3c5330
add mult to grass
jiayev Aug 10, 2025
02f48d8
Merge branch 'dev' into ll-feature
jiayev Aug 10, 2025
c653e86
rework on effect ll
jiayev Aug 11, 2025
89f8529
add fog alpha
jiayev Aug 11, 2025
5bd7fb5
ll fog consistency
jiayev Aug 11, 2025
412c7ba
fix effect fog blend
jiayev Aug 11, 2025
da9dff7
add effect lighting mult
jiayev Aug 12, 2025
4048045
fix warning
jiayev Aug 12, 2025
16a0bab
handle vl better
jiayev Aug 12, 2025
479d168
fix vl
jiayev Aug 13, 2025
35af3fa
Merge branch 'dev' into ll-feature
jiayev Aug 14, 2025
35cbd8d
apply mult on soft light/back light
jiayev Aug 15, 2025
4b1e6b0
Merge branch 'dev' into ll-feature
jiayev Aug 16, 2025
91ef169
fix warning
jiayev Aug 16, 2025
fb1ad25
Merge branch 'dev' into ll-feature
jiayev Aug 23, 2025
3a3fb73
Merge branch 'dev' into ll-feature
jiayev Aug 29, 2025
a28cc84
adapt to new settings
jiayev Aug 29, 2025
a1e9d3c
Merge branch 'dev' into ll-feature
jiayev Sep 6, 2025
b1492b1
Merge branch 'dev' into ll-feature
jiayev Sep 8, 2025
5c09511
Merge branch 'dev' into ll-feature
jiayev Sep 8, 2025
d884740
Merge branch 'dev' into ll-feature
jiayev Sep 9, 2025
779d001
Merge branch 'dev' into ll-feature
jiayev Sep 9, 2025
8568c29
Merge branch 'dev' into ll-feature
jiayev Sep 9, 2025
6059727
Merge branch 'dev' into ll-feature
jiayev Sep 15, 2025
251f745
Merge branch 'dev' into ll-feature
jiayev Sep 16, 2025
25f57f9
Merge branch 'dev' into ll-feature
jiayev Sep 18, 2025
bbd30ad
try fix fade related
jiayev Sep 18, 2025
be553de
add vanilla color mult
jiayev Sep 18, 2025
c9f8a74
Merge branch 'dev' into ll-feature
jiayev Sep 19, 2025
959183a
Merge branch 'dev' into ll-feature
jiayev Sep 19, 2025
61f81f4
disable ll in main and loading menu
jiayev Sep 20, 2025
ca5846f
Merge branch 'dev' into ll-feature
jiayev Sep 24, 2025
ebac71b
Merge branch 'dev' into ll-feature
jiayev Sep 24, 2025
1c79373
Merge branch 'dev' into ll-feature
jiayev Sep 25, 2025
299a884
Merge branch 'dev' into ll-feature
jiayev Sep 26, 2025
6c7fc3a
Merge branch 'dev' into ll-feature
jiayev Sep 27, 2025
0171f74
Merge branch 'dev' into ll-feature
jiayev Sep 30, 2025
a98f47e
Merge branch 'dev' into ll-feature
jiayev Oct 5, 2025
44b70c0
Merge branch 'dev' into ll-feature
jiayev Oct 7, 2025
48f3fb0
Merge branch 'dev' into ll-feature
jiayev Oct 8, 2025
b3ff8ea
Merge remote-tracking branch 'origin/dev' into ll-feature
jiayev Oct 19, 2025
20c0ffa
Merge branch 'dev' into ll-feature
jiayev Oct 28, 2025
835e9ed
add glow sliders and separate light sliders
jiayev Oct 28, 2025
ab1beab
add missed light
jiayev Oct 28, 2025
6b013ab
fix lod
jiayev Oct 29, 2025
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
Expand Up @@ -45,7 +45,7 @@ namespace DynamicCubemaps

# if defined(SKYLIGHTING)
if (SharedData::InInterior) {
float3 specularIrradiance = Color::GammaToLinear(EnvTexture.SampleLevel(SampColorSampler, R, level).xyz);
float3 specularIrradiance = Color::IrradianceToLinear(EnvTexture.SampleLevel(SampColorSampler, R, level).xyz);

finalIrradiance += specularIrradiance;
return finalIrradiance;
Expand All @@ -59,16 +59,16 @@ namespace DynamicCubemaps
float3 specularIrradiance = 1;

if (skylightingSpecular < 1.0)
specularIrradiance = Color::GammaToLinear(EnvTexture.SampleLevel(SampColorSampler, R, level).xyz);
specularIrradiance = Color::IrradianceToLinear(EnvTexture.SampleLevel(SampColorSampler, R, level).xyz);

float3 specularIrradianceReflections = 1.0;

if (skylightingSpecular > 0.0)
specularIrradianceReflections = Color::GammaToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level).xyz);
specularIrradianceReflections = Color::IrradianceToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level).xyz);

finalIrradiance = lerp(specularIrradiance, specularIrradianceReflections, skylightingSpecular);
# else
float3 specularIrradiance = Color::GammaToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level).xyz);
float3 specularIrradiance = Color::IrradianceToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level).xyz);

finalIrradiance += specularIrradiance;
# endif
Expand Down Expand Up @@ -102,7 +102,7 @@ namespace DynamicCubemaps

# if defined(SKYLIGHTING)
if (SharedData::InInterior) {
float3 specularIrradiance = Color::GammaToLinear(EnvTexture.SampleLevel(SampColorSampler, R, level).xyz);
float3 specularIrradiance = Color::IrradianceToLinear(EnvTexture.SampleLevel(SampColorSampler, R, level).xyz);

finalIrradiance += specularIrradiance;

Expand All @@ -117,16 +117,16 @@ namespace DynamicCubemaps
float3 specularIrradiance = 1;

if (skylightingSpecular < 1.0)
specularIrradiance = Color::GammaToLinear(EnvTexture.SampleLevel(SampColorSampler, R, level).xyz);
specularIrradiance = Color::IrradianceToLinear(EnvTexture.SampleLevel(SampColorSampler, R, level).xyz);

float3 specularIrradianceReflections = 1.0;

if (skylightingSpecular > 0.0)
specularIrradianceReflections = Color::GammaToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level).xyz);
specularIrradianceReflections = Color::IrradianceToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level).xyz);

finalIrradiance = lerp(specularIrradiance, specularIrradianceReflections, skylightingSpecular);
# else
float3 specularIrradiance = Color::GammaToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level));
float3 specularIrradiance = Color::IrradianceToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bug: Missing .xyz on SampleLevel result passed to IrradianceToLinear

This call differs from the others and passes a float4 to a function expecting float3 (or unintentionally includes alpha). Fix to maintain type and semantic consistency.

- float3 specularIrradiance = Color::IrradianceToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level));
+ float3 specularIrradiance = Color::IrradianceToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level).xyz);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
float3 specularIrradiance = Color::IrradianceToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level));
float3 specularIrradiance = Color::IrradianceToLinear(
EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level).xyz
);
🤖 Prompt for AI Agents
In features/Dynamic Cubemaps/Shaders/DynamicCubemaps/DynamicCubemaps.hlsli at
line 129, the call to EnvReflectionsTexture.SampleLevel returns a float4 but is
passed directly to Color::IrradianceToLinear which expects a float3. Fix this by
appending .xyz to the SampleLevel result to pass only the RGB components,
ensuring type and semantic consistency.


finalIrradiance += specularIrradiance;
# endif
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "Common/Color.hlsli"
#include "Common/SharedData.hlsli"

TextureCube<float4> EnvCaptureTexture : register(t0);
TextureCube<float4> ReflectionsTexture : register(t1);
Expand Down Expand Up @@ -90,11 +91,11 @@ float3 GetSamplingVector(uint3 ThreadID, in RWTexture2DArray<float4> OutputTextu
}

#if defined(REFLECTIONS)
color.rgb = lerp(color.rgb, Color::GammaToLinear(ReflectionsTexture.SampleLevel(LinearSampler, uv, 0.0).rgb), saturate(mipLevel / 7.0));
color.rgb = lerp(color.rgb, Color::IrradianceToLinear(ReflectionsTexture.SampleLevel(LinearSampler, uv, 0.0).rgb), saturate(mipLevel / 7.0));
#else
color.rgb = lerp(color.rgb, color.rgb * DefaultCubemap.SampleLevel(LinearSampler, uv, 0.0).xyz, saturate(mipLevel / 7.0));
#endif

color.rgb = Color::LinearToGamma(color.rgb);
color.rgb = Color::IrradianceToGamma(color.rgb);
EnvInferredTexture[ThreadID] = max(0, color);
}
Comment on lines 93 to 101
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Accumulate in linear space; decode all samples before blending.

Currently, EnvCaptureTexture samples are accumulated in their encoded space, and only the REFLECTIONS blend sample is decoded. To preserve energy correctness under linear lighting, decode all sampled colors to linear before accumulation and encode once at the end.

Minimal change within this hunk: ensure default cubemap sample is decoded before use.

-#else
-    color.rgb = lerp(color.rgb, color.rgb * DefaultCubemap.SampleLevel(LinearSampler, uv, 0.0).xyz, saturate(mipLevel / 7.0));
-#endif
+#else
+    const float3 defaultCubemap = Color::IrradianceToLinear(DefaultCubemap.SampleLevel(LinearSampler, uv, 0.0).xyz);
+    color.rgb = lerp(color.rgb, color.rgb * defaultCubemap, saturate(mipLevel / 7.0));
+#endif

Additionally, apply these changes outside the selected range to fully linearize accumulation (illustrative snippet):

// After line 53:
float4 color = EnvCaptureTexture.SampleLevel(LinearSampler, uv, 0);
color.rgb = Color::IrradianceToLinear(color.rgb);

// In the loop when sampling tempColor:
tempColor = EnvCaptureTexture.SampleLevel(LinearSampler, uv, mipLevel);
tempColor.rgb = Color::IrradianceToLinear(tempColor.rgb);

// For the 6 face fallback:
tempColor += EnvCaptureTexture.SampleLevel(LinearSampler, float3(-1.0, 0.0, 0.0), 9);
tempColor.rgb = Color::IrradianceToLinear(tempColor.rgb);
// ...repeat for each sample, converting .rgb only

// Encode once at the end (your existing line 99 already does this):
color.rgb = Color::IrradianceToGamma(color.rgb);
🤖 Prompt for AI Agents
In features/Dynamic Cubemaps/Shaders/DynamicCubemaps/InferCubemapCS.hlsl around
lines 93 to 101, the default cubemap sample is currently used in its encoded
space, causing incorrect color blending. To fix this, decode the DefaultCubemap
sample to linear space using Color::IrradianceToLinear before blending with
lerp. Additionally, ensure all EnvCaptureTexture samples elsewhere in the file
are decoded to linear space immediately after sampling, and only encode the
final accumulated color back to gamma space once at the end.

Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,11 @@ float3 tangentToWorld(const float3 v, const float3 N, const float3 S, const floa
// Mip level to sample from.
float mipLevel = max(0.5 * log2(ws / wt) + 1.0, 0.0);

color += Color::GammaToLinear(inputTexture.SampleLevel(linear_wrap_sampler, Li, mipLevel).rgb) * cosLi;
color += Color::IrradianceToLinear(inputTexture.SampleLevel(linear_wrap_sampler, Li, mipLevel).rgb) * cosLi;
weight += cosLi;
}
}
color /= weight;

outputTexture[ThreadID] = float4(Color::LinearToGamma(color), 1.0);
outputTexture[ThreadID] = float4(Color::IrradianceToGamma(color), 1.0);
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ float smoothbumpstep(float edge0, float edge1, float x)
color /= weight;

float4 positionFinal = float4(position.xyz * 0.001, length(position) < (4096.0 * 2.5));
float4 colorFinal = float4(Color::GammaToLinear(color), 1.0);
float4 colorFinal = float4(Color::IrradianceToLinear(color), 1.0);

float lerpFactor = 0.5;

Expand Down
5 changes: 2 additions & 3 deletions features/Hair Specular/Shaders/Hair/Hair.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
#define __HAIR_DEPENDENCY_HLSL__

#include "Common/BRDF.hlsli"
#include "Common/Color.hlsli"
#include "Common/Game.hlsli"
#include "Common/Math.hlsli"

#define HAIR_LIGHTING_MULTIPLIER Math::PI // Compensating to adapt to vanilla lighting model

namespace Hair
{
Texture2D<float> TexTangentShift : register(t73);
Expand Down Expand Up @@ -194,7 +193,7 @@ namespace Hair

void GetHairDirectLightMarschner(out float3 dirDiffuse, out float3 dirSpecular, out float3 dirTransmission, float3 T, float3 L, float3 V, float3 N, float3 VN, float3 lightColor, float shininess, float selfShadow, float2 uv, float3 baseColor)
{
lightColor *= HAIR_LIGHTING_MULTIPLIER * selfShadow;
lightColor *= Color::PBRLightingCompensation * selfShadow;
dirDiffuse = 0;
dirSpecular = 0;
dirTransmission = 0;
Expand Down
3 changes: 1 addition & 2 deletions features/IBL/Shaders/IBL/DiffuseIBLCS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@ void main(uint3 dispatchID : SV_DispatchThreadID, uint groupIndex : SV_GroupInde
}
}
#endif

// Apply gamma correction
color = Color::GammaToLinear(color);
color = Color::IrradianceToLinear(color);

// Compute spherical harmonics basis for this direction
sh2 sh = SphericalHarmonics::Evaluate(rayDir);
Expand Down
Empty file added features/Linear Lighting/CORE
Empty file.
2 changes: 2 additions & 0 deletions features/Linear Lighting/Shaders/Features/LinearLighting.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Info]
Version = 1-0-0
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ void readHistory(

half3 radiance = 0;
#ifdef GI
radiance = Color::GammaToLinear(FULLRES_LOAD(srcDiffuse, pixCoord, uv * frameScale, samplerLinearClamp).rgb * GIStrength);
radiance = Color::RadianceToLinear(FULLRES_LOAD(srcDiffuse, pixCoord, uv * frameScale, samplerLinearClamp).rgb * GIStrength);
# ifdef GI_BOUNCE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Decode first, then scale: move GIStrength outside RadianceToLinear.

RadianceToLinear (like GammaToLinear) is non-linear; multiplying inside it skews results. Convert the sampled color to linear first, then apply GIStrength.

-    radiance = Color::RadianceToLinear(FULLRES_LOAD(srcDiffuse, pixCoord, uv * frameScale, samplerLinearClamp).rgb * GIStrength);
+    radiance = Color::RadianceToLinear(FULLRES_LOAD(srcDiffuse, pixCoord, uv * frameScale, samplerLinearClamp).rgb) * GIStrength;

To catch similar issues elsewhere (multiplication inside XxxToLinear()), run:


🏁 Script executed:

#!/bin/bash
# Find conversions where arguments include a multiplication
rg -n --pcre2 'Color::[A-Za-z]+ToLinear\([^)]*\*[^)]*\)'

Length of output: 384


Move multiplications outside of color‐to‐linear conversions

Applying the GI strength (or any color scaling) before converting to linear space skews the result. You should first decode the sampled/gamma value to linear, then apply the multiplier.

• In features/Screen Space GI/Shaders/ScreenSpaceGI/radianceDisocc.cs.hlsl (line 145):

-    radiance = Color::RadianceToLinear(
-        FULLRES_LOAD(srcDiffuse, pixCoord, uv * frameScale, samplerLinearClamp).rgb * GIStrength
-    );
+    radiance = Color::RadianceToLinear(
+        FULLRES_LOAD(srcDiffuse, pixCoord, uv * frameScale, samplerLinearClamp).rgb
+    ) * GIStrength;

• In package/Shaders/AmbientCompositeCS.hlsl (line 87):

-    float3 linAmbient = Color::IrradianceToLinear(albedo * directionalAmbientColor);
+    float3 linAmbient = Color::IrradianceToLinear(albedo)
+                       * directionalAmbientColor;

Please update both locations to ensure correct linear‐space lighting.

🤖 Prompt for AI Agents
In features/Screen Space GI/Shaders/ScreenSpaceGI/radianceDisocc.cs.hlsl around
lines 145-146, the multiplication by GIStrength is applied before converting the
color to linear space, which causes incorrect lighting results. To fix this,
first convert the sampled color to linear space using RadianceToLinear, then
multiply the resulting linear color by GIStrength. Apply the same fix in
package/Shaders/AmbientCompositeCS.hlsl at line 87 to ensure consistent and
correct linear-space lighting.

radiance += prev_ambient.rgb * GIBounceFade;
# endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ float4 SSSSBlurCS(
float4 colorM = ColorTexture[DTid.xy];

#if defined(HORIZONTAL)
colorM.rgb = Color::GammaToLinear(colorM.rgb);
colorM.rgb = Color::IrradianceToLinear(colorM.rgb);
#endif

if (sssAmount == 0)
Expand Down Expand Up @@ -152,7 +152,7 @@ float4 SSSSBlurCS(
float3 color = ColorTexture[coords].rgb;

#if defined(HORIZONTAL)
color.rgb = Color::GammaToLinear(color.rgb);
color.rgb = Color::IrradianceToLinear(color.rgb);
#endif

float depth = DepthTexture[coords].r;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ cbuffer PerFrameSSS : register(b1)
bool humanProfile = MaskTexture[DTid.xy].y > 0.0;

float4 color = SSSSBlurCS(DTid.xy, texCoord, float2(0.0, 1.0), sssAmount, humanProfile);
color.rgb = Color::LinearToGamma(color.rgb);
color.rgb = Color::IrradianceToGamma(color.rgb);
SSSRW[DTid.xy] = float4(color.rgb, 1.0);
}
Comment on lines +66 to 68
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Clamp before gamma encode; verify final-space expectation for SSS output.

  • HORIZONTAL path clamps to non-negative; VERTICAL doesn't. Gamma on negatives is undefined. Clamp before encode.
  • Confirm this pass is intended to emit gamma-space, given the linear-lighting goal. If gamma is deferred globally, rely on the Color::* helper to gate or keep this linear.

Proposed fix:

-        color.rgb = Color::IrradianceToGamma(color.rgb);
+        // Avoid gamma on negatives; mirrors HORIZONTAL clamping behavior
+        color.rgb = Color::IrradianceToGamma(max(0, color.rgb));

To verify usage and avoid double-encoding, search SSS outputs/consumers:


🏁 Script executed:

#!/bin/bash
rg -n -A2 -B2 $'SSSRW\\s*\\['
rg -n -A4 -B2 'SeparableSSS' features package

Length of output: 2035


Clamp before gamma conversion in vertical SSS pass

  • Horizontal pass (line 33) correctly does SSSRW[DTid.xy] = max(0, color);
  • Vertical pass (lines 43–44) applies Color::IrradianceToGamma on raw values—gamma on negatives is undefined.
  • Add the same non-negative clamp before encoding.
  • Also verify whether this shader should emit gamma-space here or defer to the global post-tonemap step.

Proposed diff in features/Subsurface Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl:

-       color.rgb = Color::IrradianceToGamma(color.rgb);
+       // Mirror horizontal clamp: avoid gamma on negative samples
+       color.rgb = Color::IrradianceToGamma(max(0, color.rgb));
🤖 Prompt for AI Agents
In features/Subsurface
Scattering/Shaders/SubsurfaceScattering/SeparableSSSCS.hlsl around lines 43 to
45, the vertical SSS pass applies gamma conversion directly on potentially
negative color values, which is undefined. Fix this by clamping the color to
non-negative values before calling Color::IrradianceToGamma, similar to the
horizontal pass at line 33. Additionally, confirm if gamma conversion should
occur here or be deferred to the global post-tonemap step and adjust
accordingly.


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ namespace WetnessEffects
float3 specularIrradiance = 1.0;
# else
float level = roughness * 7.0;
float3 specularIrradiance = Color::GammaToLinear(DynamicCubemaps::EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level).rgb);
float3 specularIrradiance = Color::IrradianceToLinear(DynamicCubemaps::EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level).rgb);
# endif
#else
float3 specularIrradiance = 1.0;
Expand Down
23 changes: 15 additions & 8 deletions package/Shaders/AmbientCompositeCS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,29 @@ void SampleSSGI(uint2 pixCoord, float3 normalWS, out float ao, out float3 il)

#if defined(IBL)
if (SharedData::iblSettings.EnableDiffuseIBL) {
directionalAmbientColor *= SharedData::iblSettings.DALCAmount;
directionalAmbientColor = SharedData::iblSettings.DALCAmount * Color::Ambient(directionalAmbientColor);
directionalAmbientColor += Color::Saturation(ImageBasedLighting::GetDiffuseIBL(-normalWS), SharedData::iblSettings.IBLSaturation) * SharedData::iblSettings.DiffuseIBLScale;
}
#endif

float3 linAlbedo = Color::GammaToLinear(albedo);
float3 linDirectionalAmbientColor = Color::GammaToLinear(directionalAmbientColor);
float3 linAlbedo = albedo;
float3 linDirectionalAmbientColor = directionalAmbientColor;
float3 linDiffuseColor = diffuseColor;
if (!SharedData::linearLightingSettings.enableLinearLighting) {
linAlbedo = Color::GammaToLinear(linAlbedo);
linDirectionalAmbientColor = Color::GammaToLinear(linDirectionalAmbientColor);
linDiffuseColor = Color::GammaToLinear(linDiffuseColor);
} else {
linDirectionalAmbientColor = Color::Ambient(linDirectionalAmbientColor);
}
#if defined(IBL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Decode domains consistently; avoid mixing gamma and semantic spaces.

Albedo in the GBuffer is typically stored post Color::Diffuse(...). Decoding it with plain GammaToLinear when LL is disabled, and leaving it as-is when enabled, can be wrong. Prefer decoding with Color::ColorToLinear (or a dedicated Diffuse->Linear) either way. Also, build lin* consistently in one spot.

Suggested replacement:

- float3 linAlbedo = albedo;
- float3 linDirectionalAmbientColor = directionalAmbientColor;
- float3 linDiffuseColor = diffuseColor;
- if (!SharedData::linearLightingSettings.enableLinearLighting) {
-   linAlbedo = Color::GammaToLinear(linAlbedo);
-   linDirectionalAmbientColor = Color::GammaToLinear(linDirectionalAmbientColor);
-   linDiffuseColor = Color::GammaToLinear(linDiffuseColor);
- } else {
-   linDirectionalAmbientColor = Color::Ambient(linDirectionalAmbientColor);
- }
+ float3 linAlbedo = Color::ColorToLinear(albedo);
+ float3 linDirectionalAmbientColor = SharedData::linearLightingSettings.enableLinearLighting
+   ? Color::Ambient(directionalAmbientColor)
+   : Color::GammaToLinear(directionalAmbientColor);
+ float3 linDiffuseColor = SharedData::linearLightingSettings.enableLinearLighting
+   ? diffuseColor
+   : Color::GammaToLinear(diffuseColor);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
float3 linAlbedo = albedo;
float3 linDirectionalAmbientColor = directionalAmbientColor;
float3 linDiffuseColor = diffuseColor;
if (!SharedData::linearLightingSettings.enableLinearLighting) {
linAlbedo = Color::GammaToLinear(linAlbedo);
linDirectionalAmbientColor = Color::GammaToLinear(linDirectionalAmbientColor);
linDiffuseColor = Color::GammaToLinear(linDiffuseColor);
} else {
linDirectionalAmbientColor = Color::Ambient(linDirectionalAmbientColor);
}
#if defined(IBL)
float3 linAlbedo = Color::ColorToLinear(albedo);
float3 linDirectionalAmbientColor = SharedData::linearLightingSettings.enableLinearLighting
? Color::Ambient(directionalAmbientColor)
: Color::GammaToLinear(directionalAmbientColor);
float3 linDiffuseColor = SharedData::linearLightingSettings.enableLinearLighting
? diffuseColor
: Color::GammaToLinear(diffuseColor);
#if defined(IBL)
🤖 Prompt for AI Agents
In package/Shaders/AmbientCompositeCS.hlsl around lines 70 to 80, the code
inconsistently decodes albedo and related colors by mixing gamma and semantic
spaces, which can cause incorrect lighting results. Replace the use of
Color::GammaToLinear with Color::ColorToLinear (or a dedicated Diffuse-to-Linear
conversion) for all lin* variables regardless of the linear lighting setting,
and consolidate the decoding logic in one place to ensure consistent domain
decoding.

if (SharedData::iblSettings.EnableDiffuseIBL) {
linDirectionalAmbientColor = directionalAmbientColor;
}
#endif
float3 linDiffuseColor = Color::GammaToLinear(diffuseColor);
float3 originalDiffuseColor = linDiffuseColor;

float3 linAmbient = Color::GammaToLinear(albedo * directionalAmbientColor);
float3 linAmbient = Color::IrradianceToLinear(albedo * directionalAmbientColor);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

linAmbient formula mixes domains; compute from decoded terms.

Color::IrradianceToLinear(albedo * directionalAmbientColor) applies an irradiance decode to a reflectance*irradiance product. Instead multiply decoded quantities.

Apply:

- float3 linAmbient = Color::IrradianceToLinear(albedo * directionalAmbientColor);
+ float3 linAmbient = linAlbedo * linDirectionalAmbientColor;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
float3 linAmbient = Color::IrradianceToLinear(albedo * directionalAmbientColor);
float3 linAmbient = linAlbedo * linDirectionalAmbientColor;
🤖 Prompt for AI Agents
In package/Shaders/AmbientCompositeCS.hlsl at line 87, the calculation of
linAmbient incorrectly applies irradiance decoding to a product of albedo and
directionalAmbientColor. To fix this, decode albedo and directionalAmbientColor
separately before multiplying them, ensuring both terms are in the correct
linear domain prior to multiplication.


float visibility = 1.0;
#if defined(SKYLIGHTING)
Expand Down Expand Up @@ -140,13 +147,13 @@ void SampleSSGI(uint2 pixCoord, float3 normalWS, out float ao, out float3 il)
#endif

linAmbient *= visibility;
diffuseColor = Color::LinearToGamma(linDiffuseColor);
directionalAmbientColor = Color::LinearToGamma(linDirectionalAmbientColor * visibility);
diffuseColor = Color::IrradianceToGamma(linDiffuseColor);
directionalAmbientColor = Color::IrradianceToGamma(linDirectionalAmbientColor * visibility);

diffuseColor = diffuseColor + directionalAmbientColor * albedo;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Compute and accumulate ambient in linear; encode once at the end.

Currently you convert both diffuse and ambient back to gamma and then multiply by (gamma) albedo, leaving linAmbient unused. This mixes spaces and defeats linear-lighting intent.

Apply:

- linAmbient *= visibility;
- diffuseColor = Color::IrradianceToGamma(linDiffuseColor);
- directionalAmbientColor = Color::IrradianceToGamma(linDirectionalAmbientColor * visibility);
- diffuseColor = diffuseColor + directionalAmbientColor * albedo;
+ linAmbient *= visibility;
+ linDiffuseColor += linAmbient;
+ diffuseColor = Color::IrradianceToGamma(linDiffuseColor);
🤖 Prompt for AI Agents
In package/Shaders/AmbientCompositeCS.hlsl around lines 149 to 154, the code
converts diffuse and ambient colors to gamma space before multiplying by albedo,
which is incorrect because albedo is in gamma space and linAmbient is unused. To
fix this, keep all ambient and diffuse lighting calculations in linear space,
accumulate them linearly, multiply by the linear albedo, and only convert the
final color to gamma space once at the end.

#if defined(SSGI)
DiffuseAmbientRW[dispatchID.xy] = Color::GammaToLinear(diffuseColor - originalDiffuseColor);
DiffuseAmbientRW[dispatchID.xy] = Color::IrradianceToLinear(diffuseColor - originalDiffuseColor);
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

SSGI writeback mixes spaces; write linear delta.

originalDiffuseColor is linear, but diffuseColor is gamma after re-encoding above. Converting a mixed-space difference with IrradianceToLinear is incorrect.

Apply:

- DiffuseAmbientRW[dispatchID.xy] = Color::IrradianceToLinear(diffuseColor - originalDiffuseColor);
+ DiffuseAmbientRW[dispatchID.xy] = linDiffuseColor - originalDiffuseColor;
🤖 Prompt for AI Agents
In package/Shaders/AmbientCompositeCS.hlsl at lines 156-157, the code
incorrectly applies IrradianceToLinear to the difference between a gamma-space
diffuseColor and a linear originalDiffuseColor, causing a mixed-space
calculation. To fix this, convert diffuseColor back to linear space before
subtracting originalDiffuseColor, then write the linear delta without reapplying
IrradianceToLinear.


MainRW[dispatchID.xy] = float4(diffuseColor, 1);
Expand Down
Loading