Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
094b0cd
chore: better ssgi for pbr
doodlum Sep 25, 2025
7192ae3
chore: improve precision of albedo for pbr
doodlum Sep 25, 2025
0299207
feat: reflection relighting
doodlum Sep 25, 2025
3b1bc95
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Sep 25, 2025
e07e3f3
fix: fix color space
doodlum Sep 25, 2025
c8c8478
Merge branch 'pbr-fixup' of https://github.com/doodlum/skyrim-communi…
doodlum Sep 25, 2025
cb5997c
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Sep 25, 2025
90dbdb2
fix: fix pbr color space
doodlum Sep 25, 2025
7d2cb57
Merge branch 'pbr-fixup' of https://github.com/doodlum/skyrim-communi…
doodlum Sep 25, 2025
472006f
chore: remap reflectance to match vanilla
doodlum Sep 25, 2025
6320d0c
chore: less aggressive
doodlum Sep 25, 2025
6c3115b
fix: too much ssgi
doodlum Sep 25, 2025
795ee00
fix: type mismatch
doodlum Sep 25, 2025
fefc33d
Merge branch 'pbr-fixup' of https://github.com/doodlum/skyrim-communi…
doodlum Sep 25, 2025
9f52809
fix: fix divide by zero
doodlum Sep 25, 2025
b786dc3
fix: fix nonsense
doodlum Sep 25, 2025
20bb555
Update package/Shaders/DeferredCompositeCS.hlsl
doodlum Sep 25, 2025
0d71dcc
Update features/Dynamic Cubemaps/Shaders/DynamicCubemaps/DynamicCubem…
doodlum Sep 25, 2025
411b768
Merge branches 'pbr-fixup' and 'pbr-fixup' of https://github.com/dood…
doodlum Sep 25, 2025
9a39d42
chore: consistent terms
doodlum Sep 26, 2025
e6ae8ca
fix: fix regression
doodlum Sep 26, 2025
bc24c28
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Sep 26, 2025
7ff430c
Merge branch 'pbr-fixup' of https://github.com/doodlum/skyrim-communi…
doodlum Sep 26, 2025
df4f294
chore: update skylighting
doodlum Sep 26, 2025
5069ad7
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Sep 26, 2025
f2fb85f
fix: fix too dark ambient
doodlum Sep 26, 2025
e30d44d
Merge branch 'pbr-fixup' of https://github.com/doodlum/skyrim-communi…
doodlum Sep 26, 2025
bd0cb7f
chore: better wetness fresnel
doodlum Sep 26, 2025
670ae12
chore: idk
doodlum Sep 26, 2025
7626d7c
chore: why
doodlum Sep 26, 2025
8dece3c
fix: more reliable ssgi specular
doodlum Sep 26, 2025
9ae00f9
chore: more correct
doodlum Sep 26, 2025
6b71db2
Update features/Dynamic Cubemaps/Shaders/DynamicCubemaps/DynamicCubem…
doodlum Sep 26, 2025
a150cf1
Change gamma conversion to true linear for F0
jiayev Sep 26, 2025
f1bf6b8
Change albedo parameter type in applySkylighting
jiayev Sep 26, 2025
224e949
fix truncation warnings
jiayev Sep 26, 2025
5319589
fix: fixes
doodlum Sep 26, 2025
7d6a73b
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Sep 26, 2025
9bec2f9
chore: update versions
doodlum Sep 26, 2025
10c79f9
chore: make rabbit happy
doodlum Sep 26, 2025
d4bb8cb
Update package/Shaders/DeferredCompositeCS.hlsl
doodlum Sep 26, 2025
dc1ac8f
Update package/Shaders/DeferredCompositeCS.hlsl
doodlum Sep 26, 2025
07704c3
Update package/Shaders/DeferredCompositeCS.hlsl
doodlum Sep 26, 2025
2090d73
Update package/Shaders/DeferredCompositeCS.hlsl
doodlum Sep 26, 2025
f83d3d4
Merge branch 'pbr-fixup' of https://github.com/doodlum/skyrim-communi…
doodlum Sep 26, 2025
5caedde
Update package/Shaders/DeferredCompositeCS.hlsl
doodlum Sep 26, 2025
d02814b
Update package/Shaders/Common/Color.hlsli
doodlum Sep 26, 2025
2c8124f
fix: clamp specular ao
doodlum Sep 26, 2025
65edc45
fix: fix typo
doodlum Sep 26, 2025
31f4cb8
fix: fix lod blending
doodlum Sep 26, 2025
1093f76
fix: fix albedo brightness
doodlum Sep 26, 2025
0a02e7f
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Sep 26, 2025
2d3c69e
Merge branch 'pbr-fixup' of https://github.com/doodlum/skyrim-communi…
doodlum Sep 26, 2025
fc61e74
fix: fix specular ao
doodlum Sep 26, 2025
d5370a7
chore: consistent spacing
doodlum Sep 26, 2025
d85c719
style: 🎨 apply pre-commit.ci formatting
pre-commit-ci[bot] Sep 26, 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 @@ -37,6 +37,8 @@ namespace DynamicCubemaps

float3 finalIrradiance = 0;

float directionalAmbientColorSpecular = Color::RGBToLuminance(max(0, mul(SharedData::DirectionalAmbient, float4(R, 1.0))) * Color::ReflectionNormalisationScale);

Comment thread
doodlum marked this conversation as resolved.
# if defined(IBL) && defined(LIGHTING)
const bool inWorld = (Permutation::ExtraShaderDescriptor & Permutation::ExtraFlags::InWorld);
const bool inReflection = (Permutation::ExtraShaderDescriptor & Permutation::ExtraFlags::InReflection);
Expand All @@ -51,6 +53,10 @@ namespace DynamicCubemaps
if (SharedData::InInterior) {
float3 specularIrradiance = Color::GammaToLinear(EnvTexture.SampleLevel(SampColorSampler, R, level).xyz);

float specularIrradianceLuminance = Color::RGBToLuminance(Color::GammaToLinear(EnvTexture.SampleLevel(SampColorSampler, R, 15).xyz));

specularIrradiance = (specularIrradiance / max(specularIrradianceLuminance, 0.001)) * directionalAmbientColorSpecular;

Comment thread
doodlum marked this conversation as resolved.
finalIrradiance += specularIrradiance;
return finalIrradiance;
}
Expand All @@ -60,20 +66,36 @@ namespace DynamicCubemaps
float skylightingSpecular = SphericalHarmonics::FuncProductIntegral(skylighting, specularLobe);
skylightingSpecular = Skylighting::mixSpecular(SharedData::skylightingSettings, skylightingSpecular);

directionalAmbientColorSpecular *= skylightingSpecular;

float3 specularIrradiance = 1;

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

float specularIrradianceLuminance = Color::RGBToLuminance(Color::GammaToLinear(EnvTexture.SampleLevel(SampColorSampler, R, 15).xyz));

specularIrradiance = (specularIrradiance / max(specularIrradianceLuminance, 0.001)) * directionalAmbientColorSpecular;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Comment thread
coderabbitai[bot] marked this conversation as resolved.
float3 specularIrradianceReflections = 1.0;

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

float specularIrradianceReflectionsLuminance = Color::RGBToLuminance(Color::GammaToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, 15).xyz));

specularIrradianceReflections = (specularIrradianceReflections / max(specularIrradianceReflectionsLuminance, 0.001)) * directionalAmbientColorSpecular;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

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

float specularIrradianceLuminance = Color::RGBToLuminance(Color::GammaToLinear(EnvTexture.SampleLevel(SampColorSampler, R, 15).xyz));

specularIrradiance = (specularIrradiance / max(specularIrradianceLuminance, 0.001)) * directionalAmbientColorSpecular;

finalIrradiance += specularIrradiance;
# endif
return finalIrradiance;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 2-2-0
Version = 2-2-1
2 changes: 1 addition & 1 deletion features/Skylighting/Shaders/Features/Skylighting.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-2-0
Version = 1-2-1
6 changes: 3 additions & 3 deletions features/Skylighting/Shaders/Skylighting/Skylighting.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ namespace Skylighting
}

#if defined(PSHADER)
void applySkylighting(inout float3 diffuseColor, inout float3 directionalAmbientColor, float skylightingDiffuse)
void applySkylighting(inout float3 diffuseColor, inout float3 directionalAmbientColor, float3 albedo, float skylightingDiffuse)
{
float maxScale = 1.0;
if (directionalAmbientColor.x > 0.0)
Expand All @@ -49,7 +49,7 @@ namespace Skylighting

diffuseColor = max(0.0, diffuseColor - directionalAmbientColor);

directionalAmbientColor = Color::LinearToGamma(Color::GammaToLinear(directionalAmbientColor) * skylightingDiffuse);
directionalAmbientColor = Color::LinearToGamma(Color::GammaToLinear(directionalAmbientColor) * Color::MultiBounceAO(Color::GammaToLinear(albedo / Color::PBRLightingScale), skylightingDiffuse));

diffuseColor += directionalAmbientColor;
}
Expand Down Expand Up @@ -158,4 +158,4 @@ namespace Skylighting
}
}

#endif
#endif
26 changes: 22 additions & 4 deletions package/Shaders/Common/Color.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ namespace Color
{
static float GammaCorrectionValue = 2.2;

// [Jimenez et al. 2016, "Practical Realtime Strategies for Accurate Indirect Occlusion"]
float3 MultiBounceAO(float3 baseColor, float ao)
{
float3 a = 2.0404 * baseColor - 0.3324;
float3 b = -4.7951 * baseColor + 0.6417;
float3 c = 2.7552 * baseColor + 0.6903;
return max(ao, ((ao * a + b) * ao + c) * ao);
}

// [Lagarde et al. 2014, "Moving Frostbite to Physically Based Rendering 3.0"]
float SpecularAOLagarde(float NdotV, float ao, float roughness)
{
return saturate(pow(abs(NdotV + ao), exp2(-16.0 * roughness - 1.0)) - 1.0 + ao);
}
Comment thread
doodlum marked this conversation as resolved.

float RGBToLuminance(float3 color)
{
return dot(color, float3(0.2125, 0.7154, 0.0721));
Expand Down Expand Up @@ -50,17 +65,20 @@ namespace Color
return color;
}

// Attempt to match vanilla materials tha are a darker than PBR
// Attempt to match vanilla materials that are darker than PBR
const static float PBRLightingScale = 0.666;

// Attempt to normalise reflection brightness against DALC
const static float ReflectionNormalisationScale = 0.666;

float3 GammaToLinear(float3 color)
{
return pow(abs(color), 1.8);
return pow(abs(color), 1.6);
}

float3 LinearToGamma(float3 color)
{
return pow(abs(color), 1.0 / 1.8);
return pow(abs(color), 1.0 / 1.6);
}

float3 GammaToTrueLinear(float3 color)
Expand All @@ -76,7 +94,7 @@ namespace Color
float3 Diffuse(float3 color)
{
#if defined(TRUE_PBR)
return LinearToGamma(color);
return TrueLinearToGamma(color);
#else
return color;
#endif
Expand Down
23 changes: 4 additions & 19 deletions package/Shaders/Common/PBR.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -147,21 +147,6 @@ namespace PBR
return result;
}

// [Jimenez et al. 2016, "Practical Realtime Strategies for Accurate Indirect Occlusion"]
float3 MultiBounceAO(float3 baseColor, float ao)
{
float3 a = 2.0404 * baseColor - 0.3324;
float3 b = -4.7951 * baseColor + 0.6417;
float3 c = 2.7552 * baseColor + 0.6903;
return max(ao, ((ao * a + b) * ao + c) * ao);
}

// [Lagarde et al. 2014, "Moving Frostbite to Physically Based Rendering 3.0"]
float SpecularAOLagarde(float NdotV, float ao, float roughness)
{
return saturate(pow(abs(NdotV + ao), exp2(-16.0 * roughness - 1.0)) - 1.0 + ao);
}

#if defined(GLINT)
float3 GetSpecularDirectLightMultiplierMicrofacetWithGlint(float noise, float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, float glintH,
float logDensity, float microfacetRoughness, float densityRandomization, Glints::GlintCachedVars glintCache,
Expand Down Expand Up @@ -481,12 +466,12 @@ namespace PBR
specularLobeWeight *= horizon;

float3 diffuseAO = surfaceProperties.AO;
float3 specularAO = SpecularAOLagarde(NdotV, surfaceProperties.AO, surfaceProperties.Roughness);
float3 specularAO = Color::SpecularAOLagarde(NdotV, surfaceProperties.AO, surfaceProperties.Roughness);

diffuseAO = MultiBounceAO(diffuseColor, diffuseAO.x).y;
specularAO = MultiBounceAO(surfaceProperties.F0, specularAO.x).y;
diffuseAO = Color::MultiBounceAO(diffuseColor, diffuseAO.x).y;
specularAO = Color::MultiBounceAO(surfaceProperties.F0, specularAO.x).y;

diffuseLobeWeight *= diffuseAO * Color::PBRLightingScale;
diffuseLobeWeight *= diffuseAO;
specularLobeWeight *= specularAO;
}

Expand Down
67 changes: 46 additions & 21 deletions package/Shaders/DeferredCompositeCS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,15 @@ void SampleSSGI(uint2 pixCoord, float3 normalWS, out float ao, out float3 il)
il = max(0, Color::YCoCgToRGB(float3(ssgiIlY, ssgiIlCoCg)));
}

void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, out float ao, out float3 il, in float3 normal, in float3 view)
void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, out float ao, out float3 il, in float3 normal, in float3 view, in float roughness)
{
// https://www.iryoku.com/stare-into-the-future/
ao = 1 - SsgiAoTexture[pixCoord].x;
const float SpecularPow = 8.0;
float NdotV = dot(normal, view);
float s = saturate(-0.3 + NdotV * NdotV);
ao = lerp(pow(ao, SpecularPow), 1.0, s);
ao = Color::SpecularAOLagarde(saturate(NdotV), ao, roughness);

float4 ssgiIlYSh = SsgiYTexture[pixCoord];
float ssgiIlY = SphericalHarmonics::FuncProductIntegral(ssgiIlYSh, lobe);
float2 ssgiIlCoCg = SsgiCoCgTexture[pixCoord].xy;
// specular is a bit too saturated, because CoCg are average over hemisphere
// we just cheese this bit
ssgiIlCoCg *= 0.8;

// pi to compensate for the /pi in specularLobe
// i don't think there really should be a 1/PI but without it the specular is too strong
Expand Down Expand Up @@ -152,18 +146,20 @@ void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, out float ao, out float3 il, i
diffuseColor = max(0.0, diffuseColor - directionalAmbientColor);

linDiffuseColor = Color::GammaToLinear(diffuseColor);
# if defined(INTERIOR)
linDiffuseColor *= ssgiAo;
# else
linDiffuseColor *= sqrt(ssgiAo);
# endif

float3 linAlbedo = Color::GammaToLinear(albedo / Color::PBRLightingScale);

float3 multiBounceAO = Color::MultiBounceAO(linAlbedo, ssgiAo);

linDiffuseColor *= sqrt(multiBounceAO);

diffuseColor = Color::LinearToGamma(linDiffuseColor);

diffuseColor += Color::LinearToGamma(Color::GammaToLinear(directionalAmbientColor) * ssgiAo);
diffuseColor += Color::LinearToGamma(Color::GammaToLinear(directionalAmbientColor) * multiBounceAO);

linDiffuseColor = Color::GammaToLinear(diffuseColor);

linDiffuseColor += ssgiIl * Color::GammaToLinear(albedo);
linDiffuseColor += ssgiIl * linAlbedo;
#endif

float3 color = linDiffuseColor + specularColor;
Expand All @@ -183,10 +179,18 @@ void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, out float ao, out float3 il, i

float3 finalIrradiance = 0;

float directionalAmbientColorSpecular = Color::RGBToLuminance(
Color::GammaToLinear(max(0, mul(SharedData::DirectionalAmbient, float4(R, 1.0))))
* Color::ReflectionNormalisationScale
);
# if defined(INTERIOR)
float3 specularIrradiance = Color::GammaToLinear(EnvTexture.SampleLevel(LinearSampler, R, level));

finalIrradiance += specularIrradiance;
float specularIrradianceLuminance = Color::RGBToLuminance(Color::GammaToLinear(EnvTexture.SampleLevel(LinearSampler, R, 15)));

specularIrradiance = (specularIrradiance / max(specularIrradianceLuminance, 0.001)) * directionalAmbientColorSpecular;

finalIrradiance += specularIrradiance;
# elif defined(SKYLIGHTING)
# if defined(VR)
float3 positionMS = positionWS.xyz + FrameBuffer::CameraPosAdjust[eyeIndex].xyz - FrameBuffer::CameraPosAdjust[0].xyz;
Expand All @@ -199,20 +203,36 @@ void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, out float ao, out float3 il, i
float skylightingSpecular = SphericalHarmonics::FuncProductIntegral(skylighting, specularLobe);
skylightingSpecular = Skylighting::mixSpecular(SharedData::skylightingSettings, skylightingSpecular);

directionalAmbientColorSpecular *= skylightingSpecular;

float3 specularIrradiance = 1;

if (skylightingSpecular < 1.0)
if (skylightingSpecular < 1.0){
specularIrradiance = Color::GammaToLinear(EnvTexture.SampleLevel(LinearSampler, R, level));

float specularIrradianceLuminance = Color::RGBToLuminance(Color::GammaToLinear(EnvTexture.SampleLevel(LinearSampler, R, 15)));

specularIrradiance = (specularIrradiance / max(specularIrradianceLuminance, 0.001)) * directionalAmbientColorSpecular;
}
Comment thread
doodlum marked this conversation as resolved.

float3 specularIrradianceReflections = 1.0;

if (skylightingSpecular > 0.0)
if (skylightingSpecular > 0.0){
specularIrradianceReflections = Color::GammaToLinear(EnvReflectionsTexture.SampleLevel(LinearSampler, R, level));

float specularIrradianceLuminance = Color::RGBToLuminance(Color::GammaToLinear(EnvReflectionsTexture.SampleLevel(LinearSampler, R, 15)));

specularIrradianceReflections = (specularIrradianceReflections / max(specularIrradianceLuminance, 0.001)) * directionalAmbientColorSpecular;
}
Comment thread
doodlum marked this conversation as resolved.

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

float specularIrradianceReflectionsLuminance = Color::RGBToLuminance(Color::GammaToLinear(EnvReflectionsTexture.SampleLevel(LinearSampler, R, 15)));

specularIrradianceReflections = (specularIrradianceReflections / max(specularIrradianceReflectionsLuminance, 0.001)) * directionalAmbientColorSpecular;

finalIrradiance += specularIrradianceReflections;
# endif

Expand All @@ -227,18 +247,23 @@ void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, out float ao, out float3 il, i

float ssgiAo;
float3 ssgiIlSpecular;
SampleSSGISpecular(dispatchID.xy, specularLobe, ssgiAo, ssgiIlSpecular, normalWS, V);
SampleSSGISpecular(dispatchID.xy, specularLobe, ssgiAo, ssgiIlSpecular, normalWS, V, roughness);

# if defined(VR)
float ssgiAo2;
float3 ssgiIlSpecular2;
SampleSSGISpecular(pixCoord2, specularLobe, ssgiAo2, ssgiIlSpecular2, normalWS, V);
SampleSSGISpecular(pixCoord2, specularLobe, ssgiAo2, ssgiIlSpecular2, normalWS, V, roughness);
float4 ssgiMixed = Stereo::BlendEyeColors(uv1Mono, float4(ssgiIlSpecular, ssgiAo), uv2Mono, float4(ssgiIlSpecular2, ssgiAo2));
ssgiAo = ssgiMixed.a;
ssgiIlSpecular = ssgiMixed.rgb;
# endif

finalIrradiance = (finalIrradiance * ssgiAo) + ssgiIlSpecular;
finalIrradiance = (finalIrradiance * ssgiAo);

ssgiIlSpecular = Color::RGBToYCoCg(ssgiIlSpecular);
ssgiIlSpecular = max(0, Color::YCoCgToRGB(float3(ssgiIlSpecular.x, lerp(ssgiIlSpecular.yz, Color::RGBToYCoCg(finalIrradiance).yz, 0.5))));

finalIrradiance += ssgiIlSpecular;
# endif

color += reflectance * finalIrradiance;
Expand Down
Loading