Skip to content
292 changes: 135 additions & 157 deletions features/Dynamic Cubemaps/Shaders/DynamicCubemaps/DynamicCubemaps.hlsli

Large diffs are not rendered by default.

97 changes: 64 additions & 33 deletions features/IBL/Shaders/IBL/IBL.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -10,56 +10,88 @@
namespace ImageBasedLighting
{
#if defined(IBL_DEFERRED)
Texture2D<sh2> DiffuseIBLTexture : register(t14);
Texture2D<sh2> DiffuseSkyIBLTexture : register(t15);
Texture2D<sh2> EnvIBLTexture : register(t14);
Texture2D<sh2> SkyIBLTexture : register(t15);
#else
Texture2D<sh2> DiffuseIBLTexture : register(t76);
Texture2D<sh2> DiffuseSkyIBLTexture : register(t77);
Texture2D<sh2> EnvIBLTexture : register(t76);
Texture2D<sh2> SkyIBLTexture : register(t77);
TextureCube<float4> StaticDiffuseIBLTexture : register(t78);
TextureCube<float4> StaticSpecularIBLTexture : register(t79);
#endif
float3 GetDiffuseIBL(float3 rayDir)

/// Get Env IBL color from environment cubemap SH (without sky)
float3 GetEnvIBL(float3 rayDir)
{
sh2 shR = DiffuseIBLTexture.Load(int3(0, 0, 0));
sh2 shG = DiffuseIBLTexture.Load(int3(1, 0, 0));
sh2 shB = DiffuseIBLTexture.Load(int3(2, 0, 0));
sh2 shR = EnvIBLTexture.Load(int3(0, 0, 0));
sh2 shG = EnvIBLTexture.Load(int3(1, 0, 0));
sh2 shB = EnvIBLTexture.Load(int3(2, 0, 0));
float colorR = SphericalHarmonics::SHHallucinateZH3Irradiance(shR, rayDir);
float colorG = SphericalHarmonics::SHHallucinateZH3Irradiance(shG, rayDir);
float colorB = SphericalHarmonics::SHHallucinateZH3Irradiance(shB, rayDir);
return float3(colorR, colorG, colorB) / Math::PI;
}

float3 GetSkyDiffuseIBL(float3 rayDir)
/// Get Sky-only IBL color from game's native reflections cubemap SH
float3 GetSkyIBL(float3 rayDir)
{
sh2 shR = DiffuseSkyIBLTexture.Load(int3(0, 0, 0));
sh2 shG = DiffuseSkyIBLTexture.Load(int3(1, 0, 0));
sh2 shB = DiffuseSkyIBLTexture.Load(int3(2, 0, 0));
sh2 shR = SkyIBLTexture.Load(int3(0, 0, 0));
sh2 shG = SkyIBLTexture.Load(int3(1, 0, 0));
sh2 shB = SkyIBLTexture.Load(int3(2, 0, 0));
float colorR = SphericalHarmonics::SHHallucinateZH3Irradiance(shR, rayDir);
float colorG = SphericalHarmonics::SHHallucinateZH3Irradiance(shG, rayDir);
float colorB = SphericalHarmonics::SHHallucinateZH3Irradiance(shB, rayDir);
return float3(colorR, colorG, colorB) / Math::PI;
return max(0, float3(colorR, colorG, colorB) / Math::PI);
}

#if defined(SKYLIGHTING) && !defined(INTERIOR)
float3 GetIBLColor(float3 rayDir, float skylighting)
#else
float3 GetIBLColor(float3 rayDir)
#endif
/// Compute ratio between DALC and IBL for brightness/color matching.
/// Mode 0 (Luminance Ratio): scalar ratio from luminance, broadcast to float3 (loses DALC tint).
/// Mode 1 (Color Ratio): per-channel ratio, preserves DALC color tint.
/// DALCAmount interpolates between 1.0 (no matching) and the computed ratio.
float3 GetIBLRatio()
{
float3 color = 0;
if (SharedData::InInterior) {
color = GetDiffuseIBL(rayDir);
} else
#if defined(SKYLIGHTING)
{
color = lerp(GetDiffuseIBL(rayDir), GetSkyDiffuseIBL(rayDir), skylighting);
}
#else
{
color = GetSkyDiffuseIBL(rayDir);
// 0th order DALC (DC term)
float3 dalc0 = Color::Ambient(SharedData::GetAmbient(0.f));

// 0th order IBL SH (DC term from env cubemap)
sh2 iblSHR = EnvIBLTexture.Load(int3(0, 0, 0));
sh2 iblSHG = EnvIBLTexture.Load(int3(1, 0, 0));
sh2 iblSHB = EnvIBLTexture.Load(int3(2, 0, 0));

float colorR = SphericalHarmonics::SHHallucinateZH3Irradiance(iblSHR, float3(0, 0, 0));
float colorG = SphericalHarmonics::SHHallucinateZH3Irradiance(iblSHG, float3(0, 0, 0));
float colorB = SphericalHarmonics::SHHallucinateZH3Irradiance(iblSHB, float3(0, 0, 0));
float3 ibl0 = max(0, float3(colorR, colorG, colorB) / Math::PI);

if (SharedData::iblSettings.DALCMode == 1) {
// Mode 1: per-channel ratio preserving DALC color tint
float3 ratio = dalc0 / max(ibl0, 0.001);
return lerp(1.0, ratio, SharedData::iblSettings.DALCAmount);
} else {
// Mode 0: scalar luminance ratio (default)
float dalcLum = Color::RGBToLuminance(dalc0);
float iblLum = Color::RGBToLuminance(ibl0);
float ratio = (iblLum > 0.001) ? (dalcLum / iblLum) : 1.0;
return lerp(1.0, ratio, SharedData::iblSettings.DALCAmount);
}
#endif
return color;
}

/// Get Env IBL color with settings applied (saturation, scale, ratio)
float3 GetEnvIBLColor(float3 rayDir)
{
float3 ratio = GetIBLRatio();
return Color::Saturation(GetEnvIBL(rayDir), SharedData::iblSettings.EnvIBLSaturation) * SharedData::iblSettings.EnvIBLScale * ratio;
}

/// Get Sky IBL color with settings applied (saturation, scale; no ratio)
float3 GetSkyIBLColor(float3 rayDir)
{
return Color::Saturation(GetSkyIBL(rayDir), SharedData::iblSettings.SkyIBLSaturation) * SharedData::iblSettings.SkyIBLScale;
}

/// Get combined IBL color: Env IBL + Sky IBL (for contexts without skylighting)
float3 GetIBLColor(float3 rayDir)
{
return GetEnvIBLColor(rayDir) + GetSkyIBLColor(rayDir);
}

#if defined(LIGHTING)
Expand All @@ -71,8 +103,7 @@ namespace ImageBasedLighting

float3 GetFogIBLColor(float3 fogColor)
{
float3 directionalAmbientColor = max(0, mul(SharedData::DirectionalAmbient, float4(float3(0, 0, 0), 1.0))).xyz;
float3 iblColor = directionalAmbientColor * SharedData::iblSettings.DALCAmount + Color::Saturation(GetSkyDiffuseIBL(float3(0, 0, 0)), SharedData::iblSettings.IBLSaturation) * SharedData::iblSettings.DiffuseIBLScale;
float3 iblColor = GetEnvIBLColor(float3(0, 0, 0)) + GetSkyIBLColor(float3(0, 0, 0));
if (SharedData::iblSettings.PreserveFogLuminance) {
const float fogLuminance = Color::RGBToLuminance(fogColor);
const float iblLuminance = Color::RGBToLuminance(iblColor);
Expand Down
19 changes: 10 additions & 9 deletions package/Shaders/Common/ShadowSampling.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,18 @@ namespace ShadowSampling
void ExtractLighting(float3 inputColor, out float3 dirColor, out float3 ambientColor)
#endif
{
float3 ambientColorAmb = max(0, mul(SharedData::DirectionalAmbient, float4(0, 0, 1, 1)));
float3 ambientColorAmb = max(0, SharedData::GetAmbient(float3(0, 0, 1)));

#if defined(IBL)
if (SharedData::iblSettings.EnableDiffuseIBL && (!SharedData::InInterior || SharedData::iblSettings.EnableInterior)) {
ambientColorAmb *= SharedData::iblSettings.DALCAmount;
# if defined(SKYLIGHTING) && !defined(INTERIOR)
float3 iblColor = Color::Saturation(ImageBasedLighting::GetIBLColor(float3(0, 0, -1), skylightingDiffuse), SharedData::iblSettings.IBLSaturation) * SharedData::iblSettings.DiffuseIBLScale;
# else
float3 iblColor = Color::Saturation(ImageBasedLighting::GetIBLColor(float3(0, 0, -1)), SharedData::iblSettings.IBLSaturation) * SharedData::iblSettings.DiffuseIBLScale;
# endif
ambientColorAmb += Color::IrradianceToGamma(iblColor);
if (SharedData::iblSettings.EnableIBL) {
if (SharedData::iblSettings.DALCMode == 2) {
// Mode 2: keep vanilla DALC scaled by DALCAmount, add sky IBL overlay
ambientColorAmb = ambientColorAmb * SharedData::iblSettings.DALCAmount + Color::IrradianceToGamma(ImageBasedLighting::GetSkyIBLColor(float3(0, 0, -1)));
} else {
float3 envIBLColor = Color::IrradianceToGamma(ImageBasedLighting::GetEnvIBLColor(float3(0, 0, -1)));
float3 skyIBLColor = Color::IrradianceToGamma(ImageBasedLighting::GetSkyIBLColor(float3(0, 0, -1)));
ambientColorAmb = envIBLColor + skyIBLColor;
}
}
#endif

Expand Down
21 changes: 17 additions & 4 deletions package/Shaders/Common/SharedData.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define __SHARED_DATA_DEPENDENCY_HLSL__

#include "Common/FrameBuffer.hlsli"
#include "Common/Spherical Harmonics/SphericalHarmonics.hlsli"
#include "Common/VR.hlsli"

namespace SharedData
Expand All @@ -23,6 +24,10 @@ namespace SharedData
bool InMapMenu; // If the world/local map is open (note that the renderer is still deferred here)
bool HideSky; // HideSky flag in WorldSpace, e.g. Blackreach
float MipBias; // Offset to mip level for TAA sharpness#
float pad0;
float4 AmbientSHR;
float4 AmbientSHG;
float4 AmbientSHB;
Comment thread
jiayev marked this conversation as resolved.
};

struct GrassLightingSettings
Expand Down Expand Up @@ -182,14 +187,17 @@ namespace SharedData

struct IBLSettings
{
uint EnableDiffuseIBL;
uint EnableIBL;
uint PreserveFogLuminance;
uint UseStaticIBL;
uint EnableInterior;
float DiffuseIBLScale;
float DALCAmount;
float IBLSaturation;
float EnvIBLScale;
float SkyIBLScale;
float EnvIBLSaturation;
float SkyIBLSaturation;
float FogAmount;
uint DALCMode; // 0: Luminance Ratio, 1: Color Ratio, 2: DALC + Sky
float2 pad0;
};

struct ExtendedTranslucencySettings
Expand Down Expand Up @@ -325,6 +333,11 @@ namespace SharedData
return waterData;
}

float3 GetAmbient(float3 normal)
{
return SphericalHarmonics::Unproject(AmbientSHR, AmbientSHG, AmbientSHB, normal);
}

#endif // PSHADER
}
#endif // __SHARED_DATA_DEPENDENCY_HLSL__
131 changes: 60 additions & 71 deletions package/Shaders/DeferredCompositeCS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, inout float ao, out float3 il,
float3 ssgiIl;
SampleSSGI(dispatchID.xy, normalWS, ssgiAo, ssgiIl);

float3 directionalAmbientColor = Color::Ambient(max(0, mul(SharedData::DirectionalAmbient, float4(normalWS, 1.0))));
float3 directionalAmbientColor = Color::Ambient(max(0, SharedData::GetAmbient(normalWS)));
directionalAmbientColor *= albedo;

directionalAmbientColor = Color::RGBToYCoCg(directionalAmbientColor);
Expand Down Expand Up @@ -173,26 +173,9 @@ void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, inout float ao, out float3 il,

float3 finalIrradiance = 0;

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

# if defined(INTERIOR)
float3 specularIrradiance = EnvTexture.SampleLevel(LinearSampler, R, level);

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

# if defined(IBL)
float3 iblColor = 0;
if (SharedData::iblSettings.EnableDiffuseIBL && SharedData::iblSettings.EnableInterior) {
directionalAmbientColorSpecular *= SharedData::iblSettings.DALCAmount;
iblColor += Color::Saturation(ImageBasedLighting::GetIBLColor(-R), SharedData::iblSettings.IBLSaturation) * SharedData::iblSettings.DiffuseIBLScale;
float iblColorLuminance = Color::RGBToLuminance(Color::IrradianceToGamma(iblColor));
directionalAmbientColorSpecular += iblColorLuminance;
}
# endif
specularIrradiance = (specularIrradiance / max(specularIrradianceLuminance, 0.001)) * directionalAmbientColorSpecular;

finalIrradiance = Color::IrradianceToLinear(specularIrradiance);
# elif defined(SKYLIGHTING)
# if defined(SKYLIGHTING)
# if defined(VR)
float3 positionMS = positionWS.xyz + FrameBuffer::CameraPosAdjust[eyeIndex].xyz - FrameBuffer::CameraPosAdjust[0].xyz;
# else
Expand All @@ -204,64 +187,70 @@ void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, inout float ao, out float3 il,
float skylightingSpecular = SphericalHarmonics::FuncProductIntegral(skylighting, specularLobe);
skylightingSpecular = saturate(skylightingSpecular);
skylightingSpecular = Skylighting::mixSpecular(SharedData::skylightingSettings, skylightingSpecular);
# endif

# if defined(IBL)
float3 iblColor = 0;
if (SharedData::iblSettings.EnableDiffuseIBL) {
directionalAmbientColorSpecular *= SharedData::iblSettings.DALCAmount;
iblColor += Color::Saturation(ImageBasedLighting::GetIBLColor(-R, skylightingSpecular), SharedData::iblSettings.IBLSaturation) * SharedData::iblSettings.DiffuseIBLScale;
float iblColorLuminance = Color::RGBToLuminance(Color::IrradianceToGamma(iblColor));
directionalAmbientColorSpecular += iblColorLuminance;
}
# if defined(IBL)
if (SharedData::iblSettings.EnableIBL) {
float3 envSample = EnvTexture.SampleLevel(LinearSampler, R, level);
float3 fullSample = EnvReflectionsTexture.SampleLevel(LinearSampler, R, level);
float3 envSpecular, skySpecular;

if (SharedData::iblSettings.DALCMode == 2) {
// Mode 2: DALC-normalized env scaled by DALCAmount + sky overlay
float envLum = Color::RGBToLuminance(EnvTexture.SampleLevel(LinearSampler, R, 15));
envSpecular = Color::IrradianceToLinear((envSample / max(envLum, 0.001)) * directionalAmbientColorSpecular) * SharedData::iblSettings.DALCAmount;
skySpecular = Color::IrradianceToLinear(max(0, fullSample - envSample)) * SharedData::iblSettings.SkyIBLScale;
# if defined(SKYLIGHTING)
skySpecular *= skylightingSpecular;
# elif defined(INTERIOR)
skySpecular = 0;
# endif
} else {
// Mode 0/1: IBL ratio-based
float3 ratio = ImageBasedLighting::GetIBLRatio();
envSpecular = Color::IrradianceToLinear(envSample * ratio) * SharedData::iblSettings.EnvIBLScale;
skySpecular = Color::IrradianceToLinear(max(0, fullSample - envSample)) * SharedData::iblSettings.SkyIBLScale;
# if defined(SKYLIGHTING)
skySpecular *= skylightingSpecular;
# elif defined(INTERIOR)
skySpecular = 0;
# endif
}

directionalAmbientColorSpecular = Color::IrradianceToLinear(directionalAmbientColorSpecular);
directionalAmbientColorSpecular *= skylightingSpecular;
directionalAmbientColorSpecular = Color::IrradianceToGamma(directionalAmbientColorSpecular);

float3 specularIrradianceReflections = 0.0;

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

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

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

specularIrradianceReflections = Color::IrradianceToLinear(specularIrradianceReflections);
}

float3 specularIrradiance = 0.0;

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

finalIrradiance = envSpecular + skySpecular;
} else
# endif
{
// Fallback without IBL: normalize-by-luminance with DALC
# if defined(INTERIOR)
float3 specularIrradiance = EnvTexture.SampleLevel(LinearSampler, R, level);
float specularIrradianceLuminance = Color::RGBToLuminance(EnvTexture.SampleLevel(LinearSampler, R, 15));

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

specularIrradiance = Color::IrradianceToLinear(specularIrradiance);
}

finalIrradiance = lerp(specularIrradiance, specularIrradianceReflections, skylightingSpecular);
finalIrradiance = Color::IrradianceToLinear(specularIrradiance);
# elif defined(SKYLIGHTING)
float3 specularIrradianceReflections = 0.0;
if (skylightingSpecular > 0.0) {
specularIrradianceReflections = EnvReflectionsTexture.SampleLevel(LinearSampler, R, level);
float lum = Color::RGBToLuminance(EnvReflectionsTexture.SampleLevel(LinearSampler, R, 15));
specularIrradianceReflections = (specularIrradianceReflections / max(lum, 0.001)) * directionalAmbientColorSpecular;
specularIrradianceReflections = Color::IrradianceToLinear(specularIrradianceReflections);
}
float3 specularIrradiance = 0.0;
if (skylightingSpecular < 1.0) {
specularIrradiance = EnvTexture.SampleLevel(LinearSampler, R, level);
float lum = Color::RGBToLuminance(EnvTexture.SampleLevel(LinearSampler, R, 15));
float dalcScaled = Color::IrradianceToGamma(Color::IrradianceToLinear(directionalAmbientColorSpecular) * skylightingSpecular);
specularIrradiance = (specularIrradiance / max(lum, 0.001)) * dalcScaled;
specularIrradiance = Color::IrradianceToLinear(specularIrradiance);
}
finalIrradiance = lerp(specularIrradiance, specularIrradianceReflections, skylightingSpecular);
# else
Comment thread
jiayev marked this conversation as resolved.
# if defined(IBL)
float3 iblColor = 0;
if (SharedData::iblSettings.EnableDiffuseIBL) {
directionalAmbientColorSpecular *= SharedData::iblSettings.DALCAmount;
iblColor += Color::Saturation(ImageBasedLighting::GetIBLColor(-R), SharedData::iblSettings.IBLSaturation) * SharedData::iblSettings.DiffuseIBLScale;
float iblColorLuminance = Color::RGBToLuminance(Color::IrradianceToGamma(iblColor));
directionalAmbientColorSpecular += iblColorLuminance;
}
# endif
float3 specularIrradianceReflections = EnvReflectionsTexture.SampleLevel(LinearSampler, R, level);

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

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

finalIrradiance = Color::IrradianceToLinear(specularIrradianceReflections);
float3 specularIrradiance = EnvReflectionsTexture.SampleLevel(LinearSampler, R, level);
float specularIrradianceLuminance = Color::RGBToLuminance(EnvReflectionsTexture.SampleLevel(LinearSampler, R, 15));
specularIrradiance = (specularIrradiance / max(specularIrradianceLuminance, 0.001)) * directionalAmbientColorSpecular;
finalIrradiance = Color::IrradianceToLinear(specularIrradiance);
# endif
}

# if defined(SSGI)
float3 ssgiIlSpecular;
Expand Down
Loading
Loading