Skip to content

Commit

Permalink
chore: tweak features to improve pbr consistency (#961)
Browse files Browse the repository at this point in the history
* chore: consistency changes

* style: 🎨 apply clang-format changes

* chore: change min specular skylighting default

* fix: F0 color

* chore: nullptr 8th render target

* fix: complex material color

* chore: reduce ao power

* chore: apply gloss in gamma space for vanilla

* style: 🎨 apply clang-format changes

* fix: corrected too shiny vanilla specular

* style: 🎨 apply clang-format changes

* chore: more consistency

* chore: more consistent ssgi/ssao

* style: 🎨 apply clang-format changes

* fix: grass specular gamma space

* fix: bloom not using hue preservation

* chore: slightly biased gamma to linear conversions

* fix: terrain lod blending

* style: 🎨 apply clang-format changes

* chore: remove f0 of 0.04

* chore: do pbr specular in srgb

* style: 🎨 apply clang-format changes

* chore: less strong difference

* chore: apply skylighting directly to reflections cubemap

* chore: cheese better specular

* style: 🎨 apply clang-format changes

* chore: revert ao change

* chore: scale specular on everything

* chore: change default ssgi settings for performance

* chore: rename ssgi presets

* fix: do not darken mirrorlike reflections

* chore: less bloomy beast races

* chore: different ssgi settings

* chore: revert ini change

* chore: add sheen to ssil

* chore: dont double scale skylighting

* chore: remove accidental change

* chore: do nothing fancy with ssgi specular

* chore: more natural tonemap

---------

Co-authored-by: doodlum <[email protected]>
  • Loading branch information
doodlum and doodlum authored Feb 12, 2025
1 parent 0ef68b6 commit 4606ba9
Show file tree
Hide file tree
Showing 16 changed files with 185 additions and 161 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,58 @@ namespace DynamicCubemaps

#if !defined(WATER)

float3 GetDynamicCubemapSpecularIrradiance(float2 uv, float3 N, float3 VN, float3 V, float roughness, float distance)
# if defined(SKYLIGHTING)
float3 GetDynamicCubemapSpecularIrradiance(float2 uv, float3 N, float3 VN, float3 V, float roughness, sh2 skylighting)
# else
float3 GetDynamicCubemapSpecularIrradiance(float2 uv, float3 N, float3 VN, float3 V, float roughness)
# endif
{
float3 R = reflect(-V, N);
float NoV = saturate(dot(N, V));

float level = roughness * 7.0;

// Horizon specular occlusion
// https://marmosetco.tumblr.com/post/81245981087
float horizon = min(1.0 + dot(R, VN), 1.0);
horizon *= horizon * horizon;

float3 specularIrradiance = EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level).xyz;
specularIrradiance = Color::GammaToLinear(specularIrradiance);
specularIrradiance *= horizon;
# if defined(DEFERRED)
return horizon;
# else

float3 finalIrradiance = 0;

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

return finalIrradiance;
}

sh2 specularLobe = SphericalHarmonics::FauxSpecularLobe(N, -V, roughness);

float skylightingSpecular = SphericalHarmonics::FuncProductIntegral(skylighting, specularLobe);
skylightingSpecular = Skylighting::mixSpecular(SharedData::skylightingSettings, skylightingSpecular);

float3 specularIrradiance = 1;

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

float3 specularIrradianceReflections = 1.0;

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

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

finalIrradiance += specularIrradiance;
# endif
return finalIrradiance;
# endif
}

# if defined(SKYLIGHTING)
Expand Down Expand Up @@ -64,7 +101,7 @@ namespace DynamicCubemaps

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

finalIrradiance += specularIrradiance;

Expand All @@ -86,9 +123,9 @@ namespace DynamicCubemaps
if (skylightingSpecular > 0.0)
specularIrradianceReflections = Color::GammaToLinear(EnvReflectionsTexture.SampleLevel(SampColorSampler, R, level));

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

finalIrradiance += specularIrradiance;
# endif
Expand Down
11 changes: 5 additions & 6 deletions package/Shaders/AmbientCompositeCS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,10 @@ Texture2DArray<float3> stbn_vec3_2Dx1D_128x128x64 : register(t4);

#endif

Texture2D<float3> Masks2Texture : register(t5);

#if defined(SSGI)
Texture2D<float> SsgiAoTexture : register(t6);
Texture2D<float4> SsgiYTexture : register(t7);
Texture2D<float2> SsgiCoCgTexture : register(t8);
Texture2D<float> SsgiAoTexture : register(t5);
Texture2D<float4> SsgiYTexture : register(t6);
Texture2D<float2> SsgiCoCgTexture : register(t7);
#endif

RWTexture2D<float4> MainRW : register(u0);
Expand Down Expand Up @@ -53,7 +51,6 @@ void SampleSSGI(uint2 pixCoord, float3 normalWS, out float ao, out float3 il)

float3 diffuseColor = MainRW[dispatchID.xy];
float3 albedo = AlbedoTexture[dispatchID.xy];
float3 masks2 = Masks2Texture[dispatchID.xy];

float3 normalWS = normalize(mul(FrameBuffer::CameraViewInverse[eyeIndex], float4(normalVS, 0)).xyz);

Expand Down Expand Up @@ -109,6 +106,8 @@ void SampleSSGI(uint2 pixCoord, float3 normalWS, out float ao, out float3 il)
visibility *= ssgiAo;
# if defined(INTERIOR)
linDiffuseColor *= ssgiAo;
# else
linDiffuseColor *= lerp(ssgiAo, 1.0, 0.5);
# endif

float clampedLinAlbedo = min(linAlbedo, 0.5);
Expand Down
12 changes: 6 additions & 6 deletions package/Shaders/Common/Color.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,23 @@ namespace Color
tmp - color.y);
}

// attempt to match vanilla diffuse that's a bit darker than normal srgb textures
const static float AlbedoDiffusePower = 1 / 1.7;
// Attempt to match vanilla materials tha are a darker than PBR
const static float PBRLightingScale = 0.666;

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

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

float3 Diffuse(float3 color)
{
#if defined(TRUE_PBR)
return pow(abs(color), AlbedoDiffusePower);
return pow(abs(color), 1.0 / 2.2);
#else
return color;
#endif
Expand All @@ -66,7 +66,7 @@ namespace Color
float3 Light(float3 color)
{
#if defined(TRUE_PBR)
return color * Math::PI;
return color * Math::PI; // Compensate for traditional Lambertian diffuse
#else
return color;
#endif
Expand Down
7 changes: 5 additions & 2 deletions package/Shaders/Common/DisplayMapping.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ namespace DisplayMapping
return XYZToRGB(col);
}

float3 HuePreservingHejlBurgessDawson(float3 col)
float3 HuePreservingHejlBurgessDawson(float3 col, float3 bloomCol)
{
float3 ictcp = RGBToICtCp(col);

Expand All @@ -137,12 +137,15 @@ namespace DisplayMapping
col = ICtCpToRGB(ictcp * float3(1, saturationAmount.xx));

// Hue preserving mapping
float maxCol = Color::RGBToLuminance(col);
float maxCol = max(col.x, max(col.y, col.z));
float mappedMax = GetTonemapFactorHejlBurgessDawson(maxCol);
float3 compressedHuePreserving = col * mappedMax / maxCol;

compressedHuePreserving += saturate(Param.x - mappedMax) * bloomCol;

// Non-hue preserving mapping
float3 perChannelCompressed = GetTonemapFactorHejlBurgessDawson(col);
perChannelCompressed += saturate(Param.x - perChannelCompressed) * bloomCol;

col = lerp(perChannelCompressed, compressedHuePreserving, 0.6);

Expand Down
32 changes: 16 additions & 16 deletions package/Shaders/Common/PBR.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,15 @@ namespace PBR
surfaceProperties.Roughness = 1;
surfaceProperties.Metallic = 0;
surfaceProperties.AO = 1;
surfaceProperties.F0 = 0.04;
surfaceProperties.F0 = 0;

surfaceProperties.SubsurfaceColor = 0;
surfaceProperties.Thickness = 0;

surfaceProperties.CoatColor = 0;
surfaceProperties.CoatStrength = 0;
surfaceProperties.CoatRoughness = 0;
surfaceProperties.CoatF0 = 0.04;
surfaceProperties.CoatF0 = 0;

surfaceProperties.FuzzColor = 0;
surfaceProperties.FuzzWeight = 0;
Expand All @@ -116,21 +116,21 @@ namespace PBR

struct LightProperties
{
float3 LinearLightColor;
float3 LinearCoatLightColor;
float3 LightColor;
float3 CoatLightColor;
};

LightProperties InitLightProperties(float3 lightColor, float3 nonParallaxShadow, float3 parallaxShadow)
{
LightProperties result;
result.LinearLightColor = lightColor * nonParallaxShadow * parallaxShadow;
result.LightColor = lightColor * nonParallaxShadow * parallaxShadow;
[branch] if ((PBRFlags & Flags::InterlayerParallax) != 0)
{
result.LinearCoatLightColor = lightColor * nonParallaxShadow;
result.CoatLightColor = lightColor * nonParallaxShadow;
}
else
{
result.LinearCoatLightColor = result.LinearLightColor;
result.CoatLightColor = result.LightColor;
}
return result;
}
Expand Down Expand Up @@ -431,20 +431,20 @@ namespace PBR
#if !defined(LANDSCAPE) && !defined(LODLANDSCAPE)
[branch] if ((PBRFlags & Flags::HairMarschner) != 0)
{
transmission += lightProperties.LinearLightColor * GetHairColorMarschner(N, V, L, NdotL, NdotV, VdotL, 0, 1, 0, surfaceProperties);
transmission += lightProperties.LightColor * GetHairColorMarschner(N, V, L, NdotL, NdotV, VdotL, 0, 1, 0, surfaceProperties);
}
else
#endif
{
diffuse += lightProperties.LinearLightColor * satNdotL * GetDiffuseDirectLightMultiplierLambert();
diffuse += lightProperties.LightColor * satNdotL * GetDiffuseDirectLightMultiplierLambert();

float3 F;
#if defined(GLINT)
specular += GetSpecularDirectLightMultiplierMicrofacetWithGlint(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, mul(tbnTr, H),
surfaceProperties.GlintLogMicrofacetDensity, surfaceProperties.GlintMicrofacetRoughness, surfaceProperties.GlintDensityRandomization, surfaceProperties.GlintCache, F) *
lightProperties.LinearLightColor * satNdotL;
lightProperties.LightColor * satNdotL;
#else
specular += GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, F) * lightProperties.LinearLightColor * satNdotL;
specular += GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, F) * lightProperties.LightColor * satNdotL;
#endif

float2 specularBRDF = GetEnvBRDFApproxLazarov(surfaceProperties.Roughness, satNdotV);
Expand All @@ -453,7 +453,7 @@ namespace PBR
#if !defined(LANDSCAPE) && !defined(LODLANDSCAPE)
[branch] if ((PBRFlags & Flags::Fuzz) != 0)
{
float3 fuzzSpecular = GetSpecularDirectLightMultiplierMicroflakes(surfaceProperties.Roughness, surfaceProperties.FuzzColor, satNdotL, satNdotV, satNdotH, satVdotH) * lightProperties.LinearLightColor * satNdotL;
float3 fuzzSpecular = GetSpecularDirectLightMultiplierMicroflakes(surfaceProperties.Roughness, surfaceProperties.FuzzColor, satNdotL, satNdotV, satNdotH, satVdotH) * lightProperties.LightColor * satNdotL;
fuzzSpecular *= 1 + surfaceProperties.FuzzColor * (1 / (specularBRDF.x + specularBRDF.y) - 1);

specular = lerp(specular, fuzzSpecular, surfaceProperties.FuzzWeight);
Expand All @@ -465,7 +465,7 @@ namespace PBR
float forwardScatter = exp2(saturate(-VdotL) * subsurfacePower - subsurfacePower);
float backScatter = saturate(satNdotL * surfaceProperties.Thickness + (1.0 - surfaceProperties.Thickness)) * 0.5;
float subsurface = lerp(backScatter, 1, forwardScatter) * (1.0 - surfaceProperties.Thickness);
transmission += surfaceProperties.SubsurfaceColor * subsurface * lightProperties.LinearLightColor * GetDiffuseDirectLightMultiplierLambert();
transmission += surfaceProperties.SubsurfaceColor * subsurface * lightProperties.LightColor * GetDiffuseDirectLightMultiplierLambert();
}
else if ((PBRFlags & Flags::TwoLayer) != 0)
{
Expand All @@ -484,13 +484,13 @@ namespace PBR
}

float3 coatF;
float3 coatSpecular = GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.CoatRoughness, surfaceProperties.CoatF0, coatNdotL, coatNdotV, coatNdotH, coatVdotH, coatF) * lightProperties.LinearCoatLightColor * coatNdotL;
float3 coatSpecular = GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.CoatRoughness, surfaceProperties.CoatF0, coatNdotL, coatNdotV, coatNdotH, coatVdotH, coatF) * lightProperties.CoatLightColor * coatNdotL;

float3 layerAttenuation = 1 - coatF * surfaceProperties.CoatStrength;
diffuse *= layerAttenuation;
specular *= layerAttenuation;

coatDiffuse += lightProperties.LinearCoatLightColor * coatNdotL * GetDiffuseDirectLightMultiplierLambert();
coatDiffuse += lightProperties.CoatLightColor * coatNdotL * GetDiffuseDirectLightMultiplierLambert();
specular += coatSpecular * surfaceProperties.CoatStrength;
}
#endif
Expand Down Expand Up @@ -587,7 +587,7 @@ namespace PBR
diffuseAO = MultiBounceAO(diffuseColor, diffuseAO.x).y;
specularAO = MultiBounceAO(surfaceProperties.F0, specularAO.x).y;

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

Expand Down
33 changes: 17 additions & 16 deletions package/Shaders/DeferredCompositeCS.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,37 @@ Texture2D<float3> SpecularTexture : register(t0);
Texture2D<unorm float3> AlbedoTexture : register(t1);
Texture2D<unorm float3> NormalRoughnessTexture : register(t2);
Texture2D<unorm float3> MasksTexture : register(t3);
Texture2D<unorm float3> Masks2Texture : register(t4);

RWTexture2D<float4> MainRW : register(u0);
RWTexture2D<float4> NormalTAAMaskSpecularMaskRW : register(u1);
RWTexture2D<float2> MotionVectorsRW : register(u2);
Texture2D<float> DepthTexture : register(t5);
Texture2D<float> DepthTexture : register(t4);

#if defined(DYNAMIC_CUBEMAPS)
Texture2D<float3> ReflectanceTexture : register(t6);
TextureCube<float3> EnvTexture : register(t7);
TextureCube<float3> EnvReflectionsTexture : register(t8);
Texture2D<float3> ReflectanceTexture : register(t5);
TextureCube<float3> EnvTexture : register(t6);
TextureCube<float3> EnvReflectionsTexture : register(t7);

SamplerState LinearSampler : register(s0);
#endif

#if defined(SKYLIGHTING)
# include "Skylighting/Skylighting.hlsli"

Texture3D<sh2> SkylightingProbeArray : register(t9);
Texture2DArray<float3> stbn_vec3_2Dx1D_128x128x64 : register(t10);
Texture3D<sh2> SkylightingProbeArray : register(t8);
Texture2DArray<float3> stbn_vec3_2Dx1D_128x128x64 : register(t9);

#endif

#if defined(SSGI)
Texture2D<float4> SsgiAoTexture : register(t11);
Texture2D<float4> SsgiYTexture : register(t12);
Texture2D<float4> SsgiCoCgTexture : register(t13);
Texture2D<float4> SsgiSpecularTexture : register(t14);
Texture2D<float4> SsgiAoTexture : register(t10);
Texture2D<float4> SsgiYTexture : register(t11);
Texture2D<float4> SsgiCoCgTexture : register(t12);
Texture2D<float4> SsgiSpecularTexture : register(t13);

void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, out float ao, out float3 il)
{
ao = 1 - SsgiAoTexture[pixCoord];
ao = pow(ao, 0.25);

float4 ssgiIlYSh = SsgiYTexture[pixCoord];
float ssgiIlY = SphericalHarmonics::FuncProductIntegral(ssgiIlYSh, lobe);
Expand Down Expand Up @@ -77,7 +75,6 @@ void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, out float ao, out float3 il)
float3 diffuseColor = MainRW[dispatchID.xy];
float3 specularColor = SpecularTexture[dispatchID.xy];
float3 albedo = AlbedoTexture[dispatchID.xy];
float3 masks2 = Masks2Texture[dispatchID.xy];

float depth = DepthTexture[dispatchID.xy];
float4 positionWS = float4(2 * float2(uv.x, -uv.y + 1) - 1, depth, 1);
Expand All @@ -89,7 +86,7 @@ void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, out float ao, out float3 il)

float glossiness = normalGlossiness.z;

float3 color = diffuseColor + specularColor;
float3 color = Color::GammaToLinear(diffuseColor) + specularColor;

#if defined(DYNAMIC_CUBEMAPS)

Expand Down Expand Up @@ -167,14 +164,18 @@ void SampleSSGISpecular(uint2 pixCoord, sh2 lobe, out float ao, out float3 il)
ssgiIlSpecular = ssgiMixed.rgb;
# endif

finalIrradiance = finalIrradiance * ssgiAo + ssgiIlSpecular;
finalIrradiance = (finalIrradiance * ssgiAo * smoothstep(0.0, 1.0 - (1.0 / 7.0), glossiness)) + ssgiIlSpecular;
# else
finalIrradiance *= smoothstep(0.0, 1.0 - (1.0 / 7.0), glossiness);
# endif

color += reflectance * Color::LinearToGamma(finalIrradiance);
color += reflectance * finalIrradiance;
}

#endif

color = Color::LinearToGamma(color);

#if defined(DEBUG)

# if defined(VR)
Expand Down
Loading

0 comments on commit 4606ba9

Please sign in to comment.