Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: glint for PBR #413

Merged
merged 19 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
523 changes: 523 additions & 0 deletions package/Shaders/Common/Glints/Glints2023.hlsli

Large diffs are not rendered by default.

130 changes: 130 additions & 0 deletions package/Shaders/Common/Glints/noisegen.cs.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
RWTexture2D<float4> tex_noise : register(u0);

static const float GAUSSIAN_AVG = 0.0;
static const float GAUSSIAN_STD = 1.0;

uint CoordToFlatId(uint2 coord, uint width)
{
return coord.y * width + coord.x;
}

float PackFloats(float a, float b)
{
uint a16 = f32tof16(a);
uint b16 = f32tof16(b);
uint abPacked = (a16 << 16) | b16;
return asfloat(abPacked);
}

uint WangHash(uint seed)
{
seed = (seed ^ 61) ^ (seed >> 16);
seed *= 9;
seed = seed ^ (seed >> 4);
seed *= 0x27d4eb2d;
seed = seed ^ (seed >> 15);
return seed;
}

void RandXorshift(inout uint rngState)
{
// Xorshift algorithm from George Marsaglia's paper
rngState ^= (rngState << 13);
rngState ^= (rngState >> 17);
rngState ^= (rngState << 5);
}

float RandXorshiftFloat(inout uint rngState)
{
RandXorshift(rngState);
float res = float(rngState) * (1.0 / 4294967296.0);
return res;
}

float Erf(float x)
{
// Save the sign of x
int sign = 1;
if (x < 0)
sign = -1;
x = abs(x);

// A&S formula 7.1.26
float t = 1.0 / (1.0 + 0.3275911 * x);
float y = 1.0 - (((((1.061405429 * t + -1.453152027) * t) + 1.421413741) * t + -0.284496736) * t + 0.254829592) * t * exp(-x * x);

return sign * y;
}

float ErfInv(float x)
{
float w, p;
w = -log((1.0f - x) * (1.0f + x));
if (w < 5.000000f) {
w = w - 2.500000;
p = 2.81022636e-08;
p = 3.43273939e-07 + p * w;
p = -3.5233877e-06 + p * w;
p = -4.39150654e-06 + p * w;
p = 0.00021858087 + p * w;
p = -0.00125372503 + p * w;
p = -0.00417768164 + p * w;
p = 0.246640727 + p * w;
p = 1.50140941 + p * w;
} else {
w = sqrt(w) - 3.000000;
p = -0.000200214257;
p = 0.000100950558 + p * w;
p = 0.00134934322 + p * w;
p = -0.00367342844 + p * w;
p = 0.00573950773 + p * w;
p = -0.0076224613 + p * w;
p = 0.00943887047 + p * w;
p = 1.00167406 + p * w;
p = 2.83297682 + p * w;
}
return p * x;
}

float CDF(float x, float mu, float sigma)
{
float U = 0.5 * (1 + Erf((x - mu) / (sigma * sqrt(2.0))));
return U;
}

float InvCDF(float U, float mu, float sigma)
{
float x = sigma * sqrt(2.0) * ErfInv(2.0 * U - 1.0) + mu;
return x;
}

[numthreads(32, 32, 1)] void main(const uint2 tid
: SV_DispatchThreadID) {
uint2 size;
tex_noise.GetDimensions(size.x, size.y);
int offset = size.x * size.y * 0x69420;

// Generate random numbers for this cell and the next ones in X and Y
int2 pixelCoord00 = tid.xy;
uint rngState00 = WangHash(CoordToFlatId(pixelCoord00 * 123, size.x) + offset);
float u00 = RandXorshiftFloat(rngState00);
float g00 = InvCDF(RandXorshiftFloat(rngState00), GAUSSIAN_AVG, GAUSSIAN_STD);

int2 pixelCoord01 = (pixelCoord00 + int2(0, 1)) % size;
uint rngState01 = WangHash(CoordToFlatId(pixelCoord01 * 123, size.x) + offset);
float u01 = RandXorshiftFloat(rngState01);
float g01 = InvCDF(RandXorshiftFloat(rngState01), GAUSSIAN_AVG, GAUSSIAN_STD);

int2 pixelCoord10 = (pixelCoord00 + int2(1, 0)) % size;
uint rngState10 = WangHash(CoordToFlatId(pixelCoord10 * 123, size.x) + offset);
float u10 = RandXorshiftFloat(rngState10);
float g10 = InvCDF(RandXorshiftFloat(rngState10), GAUSSIAN_AVG, GAUSSIAN_STD);

int2 pixelCoord11 = (pixelCoord00 + int2(1, 1)) % size;
uint rngState11 = WangHash(CoordToFlatId(pixelCoord11 * 123, size.x) + offset);
float u11 = RandXorshiftFloat(rngState11);
float g11 = InvCDF(RandXorshiftFloat(rngState11), GAUSSIAN_AVG, GAUSSIAN_STD);

// Pack 8 values into 4
tex_noise[tid.xy] = float4(PackFloats(u00, g00), PackFloats(u01, g01), PackFloats(u10, g10), PackFloats(u11, g11));
}
81 changes: 79 additions & 2 deletions package/Shaders/Common/PBR.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
#define TruePBR_InterlayerParallax (1 << 7)
#define TruePBR_CoatNormal (1 << 8)
#define TruePBR_Fuzz (1 << 9)
#define TruePBR_HairMarschner (1 << 9)
#define TruePBR_HairMarschner (1 << 10)
#define TruePBR_Glint (1 << 11)

#define TruePBR_LandTile0PBR (1 << 0)
#define TruePBR_LandTile1PBR (1 << 1)
#define TruePBR_LandTile2PBR (1 << 2)
Expand All @@ -21,9 +23,19 @@
#define TruePBR_LandTile3HasDisplacement (1 << 9)
#define TruePBR_LandTile4HasDisplacement (1 << 10)
#define TruePBR_LandTile5HasDisplacement (1 << 11)
#define TruePBR_LandTile0HasGlint (1 << 12)
#define TruePBR_LandTile1HasGlint (1 << 13)
#define TruePBR_LandTile2HasGlint (1 << 14)
#define TruePBR_LandTile3HasGlint (1 << 15)
#define TruePBR_LandTile4HasGlint (1 << 16)
#define TruePBR_LandTile5HasGlint (1 << 17)

namespace PBR
{
#if defined(GLINT)
# include "Common/Glints/Glints2023.hlsli"
#endif

struct SurfaceProperties
{
float3 BaseColor;
Expand All @@ -39,8 +51,40 @@ namespace PBR
float3 CoatF0;
float3 FuzzColor;
float FuzzWeight;
float GlintScreenSpaceScale;
float GlintLogMicrofacetDensity;
float GlintMicrofacetRoughness;
float GlintDensityRandomization;
};

SurfaceProperties InitSurfaceProperties()
{
SurfaceProperties surfaceProperties;

surfaceProperties.Roughness = 1;
surfaceProperties.Metallic = 0;
surfaceProperties.AO = 1;
surfaceProperties.F0 = 0.04;

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

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

surfaceProperties.FuzzColor = 0;
surfaceProperties.FuzzWeight = 0;

surfaceProperties.GlintScreenSpaceScale = 1.5;
surfaceProperties.GlintLogMicrofacetDensity = 40.0;
surfaceProperties.GlintMicrofacetRoughness = 0.015;
surfaceProperties.GlintDensityRandomization = 2.0;

return surfaceProperties;
}

float3 AdjustDirectionalLightColor(float3 lightColor)
{
return pbrSettings.DirectionalLightColorMultiplier * sRGB2Lin(lightColor);
Expand Down Expand Up @@ -110,6 +154,22 @@ namespace PBR
return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);
}

#if defined(GLINT)
float3 GetSpecularDirectLightMultiplierMicrofacetWithGlint(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, GlintInput glintInput, out float3 F)
{
float D = GetNormalDistributionFunctionGGX(roughness, NdotH);
[branch] if (glintInput.LogMicrofacetDensity > 1.1)
{
float D_max = GetNormalDistributionFunctionGGX(roughness, 1);
D = SampleGlints2023NDF(glintInput, D, D_max);
}
float G = GetVisibilityFunctionSmithJointApprox(roughness, NdotV, NdotL);
F = GetFresnelFactorSchlick(specularColor, VdotH);

return D * G * F;
}
#endif

float3 GetSpecularDirectLightMultiplierMicrofacet(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, out float3 F)
{
float D = GetNormalDistributionFunctionGGX(roughness, NdotH);
Expand Down Expand Up @@ -312,7 +372,8 @@ namespace PBR
return color;
}

void GetDirectLightInput(out float3 diffuse, out float3 coatDiffuse, out float3 transmission, out float3 specular, float3 N, float3 coatN, float3 V, float3 coatV, float3 L, float3 coatL, float3 lightColor, float3 coatLightColor, SurfaceProperties surfaceProperties)
void GetDirectLightInput(out float3 diffuse, out float3 coatDiffuse, out float3 transmission, out float3 specular, float3 N, float3 coatN, float3 V, float3 coatV, float3 L, float3 coatL, float3 lightColor, float3 coatLightColor, SurfaceProperties surfaceProperties,
float3x3 tbnTr, float2 uv)
{
diffuse = 0;
coatDiffuse = 0;
Expand Down Expand Up @@ -343,8 +404,24 @@ namespace PBR
{
diffuse += lightColor * satNdotL;

#if defined(GLINT)
GlintInput glintInput;
glintInput.H = mul(tbnTr, H);
glintInput.uv = uv;
glintInput.duvdx = ddx(uv);
glintInput.duvdy = ddy(uv);
glintInput.ScreenSpaceScale = max(1, surfaceProperties.GlintScreenSpaceScale);
glintInput.LogMicrofacetDensity = clamp(40.f - surfaceProperties.GlintLogMicrofacetDensity, 1, 40);
glintInput.MicrofacetRoughness = clamp(surfaceProperties.GlintMicrofacetRoughness, 0.005, 0.3);
glintInput.DensityRandomization = clamp(surfaceProperties.GlintDensityRandomization, 0, 5);
#endif

float3 F;
#if defined(GLINT)
specular += PI * GetSpecularDirectLightMultiplierMicrofacetWithGlint(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, glintInput, F) * lightColor * satNdotL;
#else
specular += PI * GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, F) * lightColor * satNdotL;
#endif

float2 specularBRDF = 0;
[branch] if (pbrSettings.UseMultipleScattering)
Expand Down
Loading
Loading