Cleanup some old unused shader code

This commit is contained in:
Wojtek Figat
2020-12-20 10:22:54 +01:00
parent afeaaee376
commit 8a870a07ae
25 changed files with 199 additions and 685 deletions

View File

@@ -90,15 +90,15 @@ Texture3D AtmosphereInscatterTexture : register(t2);
float2 GetTransmittanceUV(float radius, float Mu)
{
float U, V;
float u, v;
#if TRANSMITTANCE_NON_LINEAR
V = sqrt((radius - RadiusGround) / (RadiusAtmosphere - RadiusGround));
U = atan((Mu + 0.15) / (1.0 + 0.15) * tan(1.5)) / 1.5;
v = sqrt((radius - RadiusGround) / (RadiusAtmosphere - RadiusGround));
u = atan((Mu + 0.15) / (1.0 + 0.15) * tan(1.5)) / 1.5;
#else
V = (radius - RadiusGround) / (RadiusAtmosphere - RadiusGround);
U = (Mu + 0.15) / (1.0 + 0.15);
v = (radius - RadiusGround) / (RadiusAtmosphere - RadiusGround);
u = (Mu + 0.15) / (1.0 + 0.15);
#endif
return float2(U, V);
return float2(u, v);
}
void GetTransmittanceRMuS(float2 uv, out float radius, out float MuS)
@@ -116,9 +116,9 @@ void GetTransmittanceRMuS(float2 uv, out float radius, out float MuS)
float2 GetIrradianceUV(float radius, float MuS)
{
float V = (radius - RadiusGround) / (RadiusAtmosphere - RadiusGround);
float U = (MuS + 0.2) / (1.0 + 0.2);
return float2(U, V);
float v = (radius - RadiusGround) / (RadiusAtmosphere - RadiusGround);
float u = (MuS + 0.2) / (1.0 + 0.2);
return float2(u, v);
}
void GetIrradianceRMuS(float2 uv, out float radius, out float MuS)
@@ -137,9 +137,6 @@ float4 Texture4DSample(Texture3D tex, float radius, float Mu, float MuS, float N
float4 TexOffset = RMu < 0.0 && Delta > 0.0 ? float4(1.0, 0.0, 0.0, 0.5 - 0.5 / float(InscatterMuNum)) : float4(-1.0, H * H, H, 0.5 + 0.5 / float(InscatterMuNum));
float MuR = 0.5 / float(AtmosphericFogInscatterAltitudeSampleNum) + Rho / H * (1.0 - 1.0 / float(AtmosphericFogInscatterAltitudeSampleNum));
float MuMu = TexOffset.w + (RMu * TexOffset.x + sqrt(Delta + TexOffset.y)) / (Rho + TexOffset.z) * (0.5 - 1.0 / float(InscatterMuNum));
// paper formula
//float MuMuS = 0.5 / float(InscatterMuSNum) + max((1.0 - exp(-3.0 * MuS - 0.6)) / (1.0 - exp(-3.6)), 0.0) * (1.0 - 1.0 / float(InscatterMuSNum));
// better formula
float MuMuS = 0.5 / float(InscatterMuSNum) + (atan(max(MuS, -0.1975) * tan(1.26 * 1.1)) / 1.1 + (1.0 - 0.26)) * 0.5 * (1.0 - 1.0 / float(InscatterMuSNum));
#else
float MuR = 0.5 / float(AtmosphericFogInscatterAltitudeSampleNum) + Rho / H * (1.0 - 1.0 / float(AtmosphericFogInscatterAltitudeSampleNum));
@@ -154,35 +151,32 @@ float4 Texture4DSample(Texture3D tex, float radius, float Mu, float MuS, float N
+ tex.SampleLevel(SamplerLinearClamp, float3((MuNu + MuMuS + 1.0) / float(InscatterNuNum), MuMu, MuR), 0) * LerpValue;
}
float Mod(float X, float Y)
float Mod(float x, float y)
{
return X - Y * floor(X/Y);
return x - y * floor(x / y);
}
void GetMuMuSNu(float2 uv, float radius, float4 DhdH, out float Mu, out float MuS, out float Nu)
{
float X = uv.x * float(InscatterMuSNum * InscatterNuNum) - 0.5;
float Y = uv.y * float(InscatterMuNum) - 0.5;
float x = uv.x * float(InscatterMuSNum * InscatterNuNum) - 0.5;
float y = uv.y * float(InscatterMuNum) - 0.5;
#if INSCATTER_NON_LINEAR
if (Y < float(InscatterMuNum) * 0.5f)
if (y < float(InscatterMuNum) * 0.5f)
{
float D = 1.0 - Y / (float(InscatterMuNum) * 0.5f - 1.0);
D = min(max(DhdH.z, D * DhdH.w), DhdH.w * 0.999);
Mu = (RadiusGround * RadiusGround - radius * radius - D * D) / (2.0 * radius * D);
float d = 1.0 - y / (float(InscatterMuNum) * 0.5f - 1.0);
d = min(max(DhdH.z, d * DhdH.w), DhdH.w * 0.999);
Mu = (RadiusGround * RadiusGround - radius * radius - d * d) / (2.0 * radius * d);
Mu = min(Mu, -sqrt(1.0 - (RadiusGround / radius) * (RadiusGround / radius)) - 0.001);
}
else
{
float D = (Y - float(InscatterMuNum) * 0.5f) / (float(InscatterMuNum) * 0.5f - 1.0);
D = min(max(DhdH.x, D * DhdH.y), DhdH.y * 0.999);
Mu = (RadiusAtmosphere * RadiusAtmosphere - radius * radius - D * D) / (2.0 * radius * D);
float d = (y - float(InscatterMuNum) * 0.5f) / (float(InscatterMuNum) * 0.5f - 1.0);
d = min(max(DhdH.x, d * DhdH.y), DhdH.y * 0.999);
Mu = (RadiusAtmosphere * RadiusAtmosphere - radius * radius - d * d) / (2.0 * radius * d);
}
MuS = Mod(X, float(InscatterMuSNum)) / (float(InscatterMuSNum) - 1.0);
// paper formula
//MuS = -(0.6 + log(1.0 - MuS * (1.0 - exp(-3.6)))) / 3.0;
// better formula
MuS = Mod(x, float(InscatterMuSNum)) / (float(InscatterMuSNum) - 1.0);
MuS = tan((2.0 * MuS - 1.0 + 0.26) * 1.1) / tan(1.26 * 1.1);
Nu = -1.0 + floor(X / float(InscatterMuSNum)) / (float(InscatterNuNum) - 1.0) * 2.0;
Nu = -1.0 + floor(x / float(InscatterMuSNum)) / (float(InscatterNuNum) - 1.0) * 2.0;
#else
Mu = -1.0 + 2.0 * Y / (float(InscatterMuNum) - 1.0);
MuS = Mod(X, float(InscatterMuSNum)) / (float(InscatterMuSNum) - 1.0);
@@ -191,10 +185,7 @@ void GetMuMuSNu(float2 uv, float radius, float4 DhdH, out float Mu, out float Mu
#endif
}
/**
* Nearest intersection of ray r,mu with ground or top atmosphere boundary
* mu=cos(ray zenith angle at ray origin)
*/
// Nearest intersection of ray r,mu with ground or top atmosphere boundary, mu=cos(ray zenith angle at ray origin)
float Limit(float radius, float Mu)
{
float Dout = -radius * Mu + sqrt(radius * radius * (Mu * Mu - 1.0) + RadiusLimit * RadiusLimit);
@@ -210,32 +201,20 @@ float Limit(float radius, float Mu)
return Dout;
}
/**
* Transmittance(=transparency) of atmosphere for infinite ray (r,mu)
* (mu=cos(view zenith angle)), intersections with ground ignored
*/
// Transmittance(=transparency) of atmosphere for infinite ray (r,mu) (mu=cos(view zenith angle)), intersections with ground ignored
float3 Transmittance(float radius, float Mu)
{
float2 uv = GetTransmittanceUV(radius, Mu);
return AtmosphereTransmittanceTexture.SampleLevel(SamplerLinearClamp, uv, 0).rgb;
}
/**
* Transmittance(=transparency) of atmosphere for infinite ray (r,mu)
* (mu=cos(view zenith angle)), or zero if ray intersects ground
*/
// Transmittance(=transparency) of atmosphere for infinite ray (r,mu) (mu=cos(view zenith angle)), or zero if ray intersects ground
float3 TransmittanceWithShadow(float radius, float Mu)
{
// Need to correct calculation based on shadow feature, currently don't consider
//return Mu < -sqrt(1.0 - (RadiusGround / radius) * (RadiusGround / radius)) ? float3(0.f, 0.f, 0.f) : Transmittance(Radius, Mu);
return Transmittance(radius, Mu);
}
/**
* Transmittance(=transparency) of atmosphere between x and x0
* Assume segment x,x0 not intersecting ground
* D = Distance between x and x0, mu=cos(zenith angle of [x,x0) ray at x)
*/
//Transmittance(=transparency) of atmosphere between x and x0. Assume segment x,x0 not intersecting ground. D = Distance between x and x0, mu=cos(zenith angle of [x,x0) ray at x)
float3 TransmittanceWithDistance(float radius, float Mu, float D)
{
float3 result;
@@ -252,42 +231,36 @@ float3 TransmittanceWithDistance(float radius, float Mu, float D)
return result;
}
/**
* Transmittance(=transparency) of atmosphere between x and x0
* Assume segment x,x0 not intersecting ground
* radius=||x||, Mu=cos(zenith angle of [x,x0) ray at x), v=unit direction vector of [x,x0) ray
*/
// Transmittance(=transparency) of atmosphere between x and x0. Assume segment x,x0 not intersecting ground radius=||x||, Mu=cos(zenith angle of [x,x0) ray at x), v=unit direction vector of [x,x0) ray
float3 TransmittanceWithDistance(float radius, float Mu, float3 V, float3 X0)
{
float3 result;
float R1 = length(X0);
float d1 = length(X0);
float Mu1 = dot(X0, V) / radius;
if (Mu > 0.0)
{
result = min(Transmittance(radius, Mu) / Transmittance(R1, Mu1), 1.0);
}
result = min(Transmittance(radius, Mu) / Transmittance(d1, Mu1), 1.0);
else
{
result = min(Transmittance(R1, -Mu1) / Transmittance(radius, -Mu), 1.0);
}
result = min(Transmittance(d1, -Mu1) / Transmittance(radius, -Mu), 1.0);
return result;
}
/**
* Optical depth for ray (r,mu) of length d, using analytic formula
* (mu=cos(view zenith angle)), intersections with ground ignored
* H=height scale of exponential density function
*/
// Optical depth for ray (r,mu) of length d, using analytic formula (mu=cos(view zenith angle)), intersections with ground ignored H=height scale of exponential density function
float OpticalDepthWithDistance(float H, float radius, float Mu, float D)
{
float particleDensity = 6.2831; // REK 04, Table 2
float A = sqrt((0.5/H)*radius);
float2 A01 = A * float2(Mu, Mu + D / radius);
float a = sqrt(0.5 / H * radius);
float2 A01 = a * float2(Mu, Mu + D / radius);
float2 A01Sign = sign(A01);
float2 A01Squared = A01*A01;
float X = A01Sign.y > A01Sign.x ? exp(A01Squared.x) : 0.0;
float2 Y = A01Sign / (2.3193 * abs(A01) + sqrt(1.52 * A01Squared + 4.0)) * float2(1.0, exp(-D / H*(D / (2.0 * radius) + Mu)));
return sqrt((particleDensity * H)*radius) * exp((RadiusGround - radius) / H) * (X + dot(Y, float2(1.0, -1.0)));
float x = A01Sign.y > A01Sign.x ? exp(A01Squared.x) : 0.0;
float2 y = A01Sign / (2.3193 * abs(A01) + sqrt(1.52 * A01Squared + 4.0)) * float2(1.0, exp(-D / H*(D / (2.0 * radius) + Mu)));
return sqrt((particleDensity * H)*radius) * exp((RadiusGround - radius) / H) * (x + dot(y, float2(1.0, -1.0)));
}
// Transmittance(=transparency) of atmosphere for ray (r,mu) of length d (mu=cos(view zenith angle)), intersections with ground ignored uses analytic formula instead of transmittance texture, REK 04, Atmospheric Transparency
float3 AnalyticTransmittance(float R, float Mu, float D)
{
return exp(- BetaRayleighScattering * OpticalDepthWithDistance(HeightScaleRayleigh, R, Mu, D) - BetaMieExtinction * OpticalDepthWithDistance(HeightScaleMie, R, Mu, D));
}
float3 Irradiance(Texture2D tex, float r, float muS)
@@ -296,32 +269,23 @@ float3 Irradiance(Texture2D tex, float r, float muS)
return tex.SampleLevel(SamplerLinearClamp, uv, 0).rgb;
}
/** Rayleigh phase function */
// Rayleigh phase function
float PhaseFunctionR(float Mu)
{
return (3.0 / (16.0 * PI)) * (1.0 + Mu * Mu);
}
/** Mie phase function */
// Mie phase function
float PhaseFunctionM(float Mu)
{
return 1.5 * 1.0 / (4.0 * PI) * (1.0 - MieG * MieG) * pow(1.0 + (MieG * MieG) - 2.0 * MieG * Mu, -3.0/2.0) * (1.0 + Mu * Mu) / (2.0 + MieG * MieG);
}
/** Approximated single Mie scattering (cf. approximate Cm in paragraph "Angular precision") */
// Approximated single Mie scattering (cf. approximate Cm in paragraph "Angular precision")
float3 GetMie(float4 RayMie)
{
// RayMie.rgb=C*, RayMie.w=Cm,r
return RayMie.rgb * RayMie.w / max(RayMie.r, 1e-4) * (BetaRayleighScattering.rrr / BetaRayleighScattering.rgb);
}
/** Transmittance(=transparency) of atmosphere for ray (r,mu) of length d
* (mu=cos(view zenith angle)), intersections with ground ignored
* uses analytic formula instead of transmittance texture, REK 04, Atmospheric Transparency
*/
float3 AnalyticTransmittance(float R, float Mu, float D)
{
return exp(- BetaRayleighScattering * OpticalDepthWithDistance(HeightScaleRayleigh, R, Mu, D) - BetaMieExtinction * OpticalDepthWithDistance(HeightScaleMie, R, Mu, D));
}
#endif

View File

@@ -298,57 +298,6 @@ float3 inscatter(inout float3 x, inout float t, float3 v, float3 s, out float r,
return result;
}
/*
//ground radiance at end of ray x+tv, when sun in direction s
//attenuated bewteen ground and viewer (=R[L0]+R[L*])
float3 groundColor(float3 x, float t, float3 v, float3 s, float r, float mu, float3 attenuation)
{
float3 result;
if (t > 0.0)
{
// if ray hits ground surface
// ground reflectance at end of ray, x0
float3 x0 = x + t * v;
float r0 = length(x0);
float3 n = x0 / r0;
float4 SceneColor = 0;
SceneColor.xyz = saturate(SceneColor.xyz + 0.05);
float4 Reflectance = SceneColor * float4(0.2, 0.2, 0.2, 1.0);
if (r0 > RadiusGround + 0.01)
{
reflectance = float4(0.4, 0.4, 0.4, 0.0);
}
// direct sun light (radiance) reaching x0
float muS = dot(n, s);
float3 sunLight = transmittanceWithShadow(r0, muS);
// precomputed sky light (irradiance) (=E[L*]) at x0
float3 groundSkyLight = Irradiance(AtmosphereIrradianceTexture, r0, muS);
// light reflected at x0 (=(R[L0]+R[L*])/T(x,x0))
float3 groundColor = reflectance.rgb * (max(muS, 0.0) * sunLight + groundSkyLight) * ISun / M_PI;
// water specular color due to sunLight
if (reflectance.w > 0.0)
{
float3 h = normalize(s - v);
float fresnel = 0.02 + 0.98 * pow(1.0 - dot(-v, h), 5.0);
float waterBrdf = fresnel * pow(max(dot(h, n), 0.0), 150.0);
groundColor += reflectance.w * max(waterBrdf, 0.0) * sunLight * ISun;
}
result = attenuation * groundColor; //=R[L0]+R[L*]
} else { // ray looking at the sky
result = 0.0;
}
return result;
}
*/
static const float EPSILON_ATMOSPHERE = 0.002f;
static const float EPSILON_INSCATTER = 0.004f;
@@ -534,7 +483,7 @@ float4 GetAtmosphericFog(AtmosphericFogData atmosphericFog, float viewFar, float
#if 1
// TODO: scale viewPosition from cm to km !!!!!!!
// TODO: scale viewPosition from cm to km
float scale = 0.0001f * atmosphericFog.AtmosphericFogDistanceScale;
viewPosition.y = (viewPosition.y - atmosphericFog.AtmosphericFogGroundOffset) * atmosphericFog.AtmosphericFogAltitudeScale;

View File

@@ -66,16 +66,16 @@ void GS_Atmosphere(triangle Quad_VS2PS input[3], inout TriangleStream<Atmosphere
float OpticalDepth(float H, float radius, float Mu)
{
float result = 0.0;
float Dx = Limit(radius, Mu) / float(TransmittanceIntegralSamples);
float Ti = Limit(radius, Mu) / float(TransmittanceIntegralSamples);
float Xi = 0.0;
float Yi = exp(-(radius - RadiusGround) / H);
LOOP
for (int i = 1; i <= TransmittanceIntegralSamples; i++)
{
float Xj = float(i) * Dx;
float Xj = float(i) * Ti;
float Yj = exp(-(sqrt(radius * radius + Xj * Xj + 2.0 * Xj * radius * Mu) - RadiusGround) / H);
result += (Yi + Yj) / 2.0 * Dx;
result += (Yi + Yj) / 2.0 * Ti;
Xi = Xj;
Yi = Yj;
}
@@ -221,8 +221,8 @@ void Inscatter(float Radius, float Mu, float MuS, float Nu, out float3 RayMie)
Radius = clamp(Radius, RadiusGround, RadiusAtmosphere);
Mu = clamp(Mu, -1.0, 1.0);
MuS = clamp(MuS, -1.0, 1.0);
float Variation = sqrt(1.0 - Mu * Mu) * sqrt(1.0 - MuS * MuS);
Nu = clamp(Nu, MuS * Mu - Variation, MuS * Mu + Variation);
float variation = sqrt(1.0 - Mu * Mu) * sqrt(1.0 - MuS * MuS);
Nu = clamp(Nu, MuS * Mu - variation, MuS * Mu + variation);
float cThetaMin = -sqrt(1.0 - (RadiusGround / Radius) * (RadiusGround / Radius));
@@ -358,7 +358,5 @@ float4 PS_Inscatter1_B(AtmosphereGSOutput input) : SV_Target
float Mu, MuS, Nu;
GetMuMuSNu(input.TexCoord, AtmosphereR, DhdH, Mu, MuS, Nu);
Inscatter(AtmosphereR, Mu, MuS, Nu, Ray, Mie);
// Store separately Rayleigh and Mie contributions, WITHOUT the phase function factor (cf "Angular precision")
return float4(Mie, 1);
}

View File

@@ -5,61 +5,11 @@
#include "./Flax/Math.hlsl"
// Bidirectional reflectance distribution functions
// Physically based shading model:
// Microfacet specular = D*G*F / (4*NoL*NoV) = D*Vis*F
// Vis = G / (4*NoL*NoV)
float3 Diffuse_Lambert(float3 diffuseColor)
{
return diffuseColor * (1 / PI);
}
// [Burley 2012, "Physically-Based Shading at Disney"]
float3 Diffuse_Burley(float3 diffuseColor, float roughness, float NoV, float NoL, float VoH)
{
float FD90 = 0.5 + 2 * VoH * VoH * roughness;
float FdV = 1 + (FD90 - 1) * Pow5(1 - NoV);
float FdL = 1 + (FD90 - 1) * Pow5(1 - NoL);
return diffuseColor * ((1 / PI) * FdV * FdL);
}
// [Gotanda 2012, "Beyond a Simple Physically Based Blinn-Phong Model in Real-Time"]
float3 Diffuse_OrenNayar(float3 diffuseColor, float roughness, float NoV, float NoL, float VoH)
{
float a = roughness * roughness;
float s = a;
float s2 = s * s;
float VoL = 2 * VoH * VoH - 1;
float Cosri = VoL - NoV * NoL;
float C1 = 1 - 0.5 * s2 / (s2 + 0.33);
float C2 = 0.45 * s2 / (s2 + 0.09) * Cosri * (Cosri >= 0 ? rcp( max(NoL, NoV)) : 1);
return diffuseColor / PI * (C1 + C2) * (1 + roughness * 0.5);
}
float PhongShadingPow(float x, float y)
{
return ClampedPow(x, y);
}
// [Blinn 1977, "Models of light reflection for computer synthesized pictures"]
float D_Blinn(float roughness, float NoH)
{
float a = roughness * roughness;
float a2 = a * a;
float n = 2 / a2 - 2;
return (n + 2) / (2 * PI) * PhongShadingPow(NoH, n);
}
// [Beckmann 1963, "The scattering of electromagnetic waves from rough surfaces"]
float D_Beckmann(float roughness, float NoH)
{
float a = roughness * roughness;
float a2 = a * a;
float NoH2 = NoH * NoH;
return exp((NoH2 - 1) / (a2 * NoH2)) / (PI * a2 * NoH2 * NoH2);
}
// GGX / Trowbridge-Reitz
// [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"]
float D_GGX(float roughness, float NoH)
@@ -70,36 +20,6 @@ float D_GGX(float roughness, float NoH)
return a2 / (PI * d * d);
}
// Anisotropic GGX
// [Burley 2012, "Physically-Based Shading at Disney"]
float D_GGXaniso(float roughnessX, float roughnessY, float NoH, float3 H, float3 X, float3 Y)
{
float ax = roughnessX * roughnessX;
float ay = roughnessY * roughnessY;
float XoH = dot(X, H);
float YoH = dot(Y, H);
float d = XoH * XoH / (ax * ax) + YoH * YoH / (ay * ay) + NoH * NoH;
return 1 / (PI * ax * ay * d * d);
}
float Vis_Implicit()
{
return 0.25;
}
// [Neumann et al. 1999, "Compact metallic reflectance models"]
float Vis_Neumann(float NoV, float NoL)
{
return 1 / (4 * max(NoL, NoV));
}
// [Kelemen 2001, "A microfacet based coupled specular-matte brdf model with importance sampling"]
float Vis_Kelemen(float VoH)
{
// constant to prevent NaN
return rcp(4 * VoH * VoH + 1e-5);
}
// Tuned to match behavior of Vis_Smith
// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
float Vis_Schlick(float roughness, float NoV, float NoL)
@@ -116,8 +36,8 @@ float Vis_Smith(float roughness, float NoV, float NoL)
{
float a = Square(roughness);
float a2 = a * a;
float vis_SmithV = NoV + sqrt( NoV * (NoV - NoV * a2) + a2);
float vis_SmithL = NoL + sqrt( NoL * (NoL - NoL * a2) + a2);
float vis_SmithV = NoV + sqrt(NoV * (NoV - NoV * a2) + a2);
float vis_SmithL = NoL + sqrt(NoL * (NoL - NoL * a2) + a2);
return rcp(vis_SmithV * vis_SmithL);
}
@@ -126,14 +46,9 @@ float Vis_Smith(float roughness, float NoV, float NoL)
float Vis_SmithJointApprox(float roughness, float NoV, float NoL)
{
float a = Square(roughness);
float vis_SmithV = NoL * (NoV * (1 - a) + a);
float vis_SmithL = NoV * (NoL * (1 - a) + a);
return 0.5 * rcp(vis_SmithV + vis_SmithL);
}
float3 F_None(float3 specularColor)
{
return specularColor;
float visSmithV = NoL * (NoV * (1 - a) + a);
float visSmithL = NoV * (NoL * (1 - a) + a);
return 0.5 * rcp(visSmithV + visSmithL);
}
// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
@@ -143,86 +58,43 @@ float3 F_Schlick(float3 specularColor, float VoH)
return saturate(50.0 * specularColor.g) * fc + (1 - fc) * specularColor;
}
float3 F_Fresnel(float3 specularColor, float VoH)
{
float3 specularColorSqrt = sqrt(clamp(float3(0, 0, 0), float3(0.99, 0.99, 0.99), specularColor));
float3 n = (1 + specularColorSqrt ) / (1 - specularColorSqrt);
float3 g = sqrt(n * n + VoH * VoH - 1);
return 0.5 * Square((g - VoH) / (g + VoH)) * (1 + Square(((g + VoH) * VoH - 1) / ((g - VoH) * VoH + 1)));
}
float D_InvBlinn(float roughness, float NoH)
{
float m = roughness * roughness;
float m2 = m * m;
float A = 4;
float cos2h = NoH * NoH;
return rcp( PI * (1 + A * m2)) * (1 + A * exp(-cos2h / m2));
}
float D_InvBeckmann(float roughness, float NoH)
{
float m = roughness * roughness;
float m2 = m * m;
float A = 4;
float cos2h = NoH * NoH;
float sin2h = 1 - cos2h;
float sin4h = sin2h * sin2h;
return rcp(PI * (1 + A * m2) * sin4h) * (sin4h + A * exp(-cos2h / (m2 * sin2h)));
}
float D_InvGGX(float roughness, float NoH)
{
float a = roughness * roughness;
float a2 = a * a;
float A = 4;
float d = (NoH - a2 * NoH) * NoH + a2;
return rcp(PI * (1 + A * a2)) * (1 + 4 * a2 * a2 / (d * d));
}
float Vis_Cloth(float NoV, float NoL)
{
return rcp(4 * (NoL + NoV - NoL * NoV));
}
#define REFLECTION_CAPTURE_NUM_MIPS 7
#define REFLECTION_CAPTURE_ROUGHEST_MIP 1
#define REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE 1.2
half ProbeMipFromRoughness(half roughness)
{
half levelFrom1x1 = REFLECTION_CAPTURE_ROUGHEST_MIP - REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE * log2(roughness);
return REFLECTION_CAPTURE_NUM_MIPS - 1 - levelFrom1x1;
half mip1px = REFLECTION_CAPTURE_ROUGHEST_MIP - REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE * log2(roughness);
return REFLECTION_CAPTURE_NUM_MIPS - 1 - mip1px;
}
half SSRMipFromRoughness(half roughness)
{
half levelFrom1x1 = 4 - REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE * log2(roughness);
return max(1, 10 - levelFrom1x1);
half mip1px = 4 - REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE * log2(roughness);
return max(1, 10 - mip1px);
}
float ComputeReflectionCaptureRoughnessFromMip(float mip)
{
float levelFrom1x1 = REFLECTION_CAPTURE_NUM_MIPS - 1 - mip;
return exp2((REFLECTION_CAPTURE_ROUGHEST_MIP - levelFrom1x1) / REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE);
float mip1px = REFLECTION_CAPTURE_NUM_MIPS - 1 - mip;
return exp2((REFLECTION_CAPTURE_ROUGHEST_MIP - mip1px) / REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE);
}
// [Lazarov 2013, "Getting More Physical in Call of Duty: Black Ops II"]
float3 EnvBRDFApprox(float3 specularColor, float roughness, float NoV)
{
// Approximate version, base for pre integrated version
const half4 c0 = {-1, -0.0275, -0.572, 0.022};
const half4 c1 = {1, 0.0425, 1.04, -0.04};
const half4 c0 = { -1, -0.0275, -0.572, 0.022 };
const half4 c1 = { 1, 0.0425, 1.04, -0.04 };
half4 r = roughness * c0 + c1;
half a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
half2 ab = half2(-1.04, 1.04) * a004 + r.zw;
return specularColor * ab.x + saturate(50.0 * specularColor.g) * ab.y;
}
// Pre integrated environment GF
// Importance sampled preintegrated G * F
float3 EnvBRDF(Texture2D preIntegratedGF, float3 specularColor, float roughness, float NoV)
{
// Importance sampled preintegrated G * F
float2 ab = preIntegratedGF.SampleLevel(SamplerLinearClamp, float2(NoV, roughness), 0).rg;
return specularColor * ab.x + saturate(50.0 * specularColor.g) * ab.y;
}
@@ -231,29 +103,7 @@ float3 EnvBRDF(Texture2D preIntegratedGF, float3 specularColor, float roughness,
float RoughnessToSpecularPower(float roughness)
{
// TODO: use path tracer as a reference and calculate valid params for this conversion
return pow(2, 13 * (1 - roughness));
#if 0
float coeff = pow(4, roughness);
coeff = max(coeff, 2.0f / (MAX_SPECULAR_POWER + 2.0f));
return 2.0f / coeff - 2.0f;
//const float Log2Of1OnLn2_Plus1 = 1.52876637294; // log2(1 / ln(2)) + 1
//return exp2(10 * roughness + Log2Of1OnLn2_Plus1);
//return pow(2, 2 * (1 - roughness));
return pow(2, 13 * (1 - roughness));
//return exp2(10 * roughness + 1);
#endif
}
/*
float SpecularPowerToRoughness(float specularPower)
{
return pow(-0.25f, specularPower * 0.5f + 1.0f);
}
*/
#endif

View File

@@ -18,67 +18,4 @@ bool RayHitRect(float3 r, float3 rectCenter, float3 rectX, float3 rectY, float3
return inExtentX && inExtentY;
}
// Computes where a ray hits a sphere (which is centered at the origin).
// \param[in] rayOrigin The start position of the ray.
// \param[in] rayDirection The normalized direction of the ray.
// \param[in] radius The radius of the sphere.
// \param[out] enter The ray parameter where the ray enters the sphere.
// 0 if the ray is already in the sphere.
// \param[out] exit The ray parameter where the ray exits the sphere.
// \return 0 or a positive value if the ray hits the sphere. A negative value
// if the ray does not touch the sphere.
float HitSphere(float3 rayOrigin, float3 rayDirection, float radius, out float enter, out float exit)
{
// Solve the equation: ||rayOrigin + distance * rayDirection|| = r
//
// This is a straight-forward quadratic equation:
// ||O + d * D|| = r
// => (O + d * D)2 = r2 where V2 means V.V
// => d2 * D2 + 2 * d * (O.D) + O2 - r2 = 0
// D2 is 1 because the rayDirection is normalized.
// => d = -O.D + sqrt((O.D)2 - O2 + r2)
float OD = dot(rayOrigin, rayDirection);
float OO = dot(rayOrigin, rayOrigin);
float radicand = OD * OD - OO + radius * radius;
enter = max(0, -OD - sqrt(radicand));
exit = -OD + sqrt(radicand);
// If radicand is negative then we do not have a result - no hit.
return radicand;
}
// Clips a ray to an AABB. Does not handle rays parallel to any of the planes.
//
// @param rayOrigin - The origin of the ray in world space.
// @param rayEnd - The end of the ray in world space.
// @param boxMin - The minimum extrema of the box.
// @param boxMax - The maximum extrema of the box.
// @return - Returns the closest intersection along the ray in x, and furthest in y.
// If the ray did not intersect the box, then the furthest intersection <= the closest intersection.
// The intersections will always be in the range [0,1], which corresponds to [rayOrigin, rayEnd] in worldspace.
// To find the world space position of either intersection, simply plug it back into the ray equation:
// WorldPos = RayOrigin + (rayEnd - RayOrigin) * Intersection;
float2 LineBoxIntersect(float3 rayOrigin, float3 rayEnd, float3 boxMin, float3 boxMax)
{
float3 invRayDir = 1.0f / (rayEnd - rayOrigin);
//find the ray intersection with each of the 3 planes defined by the minimum extrema.
float3 planeIntersections1 = (boxMin - rayOrigin) * invRayDir;
//find the ray intersection with each of the 3 planes defined by the maximum extrema.
float3 planeIntersections2 = (boxMax - rayOrigin) * invRayDir;
//get the closest of these intersections along the ray
float3 closestPlaneIntersections = min(planeIntersections1, planeIntersections2);
//get the furthest of these intersections along the ray
float3 furthestPlaneIntersections = max(planeIntersections1, planeIntersections2);
float2 boxIntersections;
//find the furthest near intersection
boxIntersections.x = max(closestPlaneIntersections.x, max(closestPlaneIntersections.y, closestPlaneIntersections.z));
//find the closest far intersection
boxIntersections.y = min(furthestPlaneIntersections.x, min(furthestPlaneIntersections.y, furthestPlaneIntersections.z));
//clamp the intersections to be between rayOrigin and RayEnd on the ray
return saturate(boxIntersections);
}
#endif

View File

@@ -45,31 +45,20 @@ Texture2D LutTexture : register(t0);
// [Krystek 1985, "An algorithm to calculate correlated colour temperature"]
float2 PlanckianLocusChromaticity(float temp)
{
float u = ( 0.860117757f + 1.54118254e-4f * temp + 1.28641212e-7f * temp*temp ) / ( 1.0f + 8.42420235e-4f * temp + 7.08145163e-7f * temp*temp );
float v = ( 0.317398726f + 4.22806245e-5f * temp + 4.20481691e-8f * temp*temp ) / ( 1.0f - 2.89741816e-5f * temp + 1.61456053e-7f * temp*temp );
float x = 3*u / ( 2*u - 8*v + 4 );
float y = 2*v / ( 2*u - 8*v + 4 );
return float2(x,y);
float u = (0.860117757f + 1.54118254e-4f * temp + 1.28641212e-7f * temp * temp) / (1.0f + 8.42420235e-4f * temp + 7.08145163e-7f * temp * temp);
float v = (0.317398726f + 4.22806245e-5f * temp + 4.20481691e-8f * temp * temp) / (1.0f - 2.89741816e-5f * temp + 1.61456053e-7f * temp * temp);
float x = 3 * u / (2 * u - 8 * v + 4);
float y = 2 * v / (2 * u - 8 * v + 4);
return float2(x, y);
}
// Accurate for 4000K < temp < 25000K
// in: correlated color temperature
// out: CIE 1931 chromaticity
float2 D_IlluminantChromaticity(float temp)
// Calculates chromaticity from temperature
float2 IlluminantChromaticity(float temp)
{
// Correct for revision of Plank's law
// This makes 6500 == D65
temp *= 1.4388 / 1.438;
float x = temp <= 7000 ?
0.244063 + ( 0.09911e3 + ( 2.9678e6 - 4.6070e9 / temp ) / temp ) / temp :
0.237040 + ( 0.24748e3 + ( 1.9018e6 - 2.0064e9 / temp ) / temp ) / temp;
float y = -3 * x*x + 2.87 * x - 0.275;
return float2(x,y);
float x = temp <= 7000 ? 0.244063 + (0.09911e3 + (2.9678e6 - 4.6070e9 / temp) / temp) / temp : 0.237040 + (0.24748e3 + (1.9018e6 - 2.0064e9 / temp) / temp) / temp;
float y = -3 * x * x + 2.87 * x - 0.275;
return float2(x, y);
}
// Find closest color temperature to chromaticity
@@ -77,38 +66,31 @@ float2 D_IlluminantChromaticity(float temp)
float CorrelatedColortemperature(float x, float y)
{
float n = (x - 0.3320) / (0.1858 - y);
return -449 * n*n*n + 3525 * n*n - 6823.3 * n + 5520.33;
return -449 * n * n * n + 3525 * n * n - 6823.3 * n + 5520.33;
}
// [McCamy 1992, "Correlated color temperature as an explicit function of chromaticity coordinates"]
float2 PlanckianIsothermal(float temp, float tint)
{
float u = ( 0.860117757f + 1.54118254e-4f * temp + 1.28641212e-7f * temp*temp ) / ( 1.0f + 8.42420235e-4f * temp + 7.08145163e-7f * temp*temp );
float v = ( 0.317398726f + 4.22806245e-5f * temp + 4.20481691e-8f * temp*temp ) / ( 1.0f - 2.89741816e-5f * temp + 1.61456053e-7f * temp*temp );
float ud = ( -1.13758118e9f - 1.91615621e6f * temp - 1.53177f * temp*temp ) / Square( 1.41213984e6f + 1189.62f * temp + temp*temp );
float vd = ( 1.97471536e9f - 705674.0f * temp - 308.607f * temp*temp ) / Square( 6.19363586e6f - 179.456f * temp + temp*temp );
float2 uvd = normalize( float2( u, v ) );
// Correlated color temperature is meaningful within +/- 0.05
float u = (0.860117757f + 1.54118254e-4f * temp + 1.28641212e-7f * temp * temp) / (1.0f + 8.42420235e-4f * temp + 7.08145163e-7f * temp * temp);
float v = (0.317398726f + 4.22806245e-5f * temp + 4.20481691e-8f * temp * temp) / (1.0f - 2.89741816e-5f * temp + 1.61456053e-7f * temp * temp);
float ud = (-1.13758118e9f - 1.91615621e6f * temp - 1.53177f * temp * temp) / Square(1.41213984e6f + 1189.62f * temp + temp * temp);
float vd = (1.97471536e9f - 705674.0f * temp - 308.607f * temp * temp) / Square(6.19363586e6f - 179.456f * temp + temp * temp);
float2 uvd = normalize(float2(u, v));
u += -uvd.y * tint * 0.05;
v += uvd.x * tint * 0.05;
float x = 3*u / ( 2*u - 8*v + 4 );
float y = 2*v / ( 2*u - 8*v + 4 );
float x = 3 * u / (2 * u - 8 * v + 4);
float y = 2 * v / (2 * u - 8 * v + 4);
return float2(x,y);
}
float3 WhiteBalance(float3 linearColor)
{
float2 srcWhiteDaylight = D_IlluminantChromaticity(WhiteTemp);
float2 srcWhiteDaylight = IlluminantChromaticity(WhiteTemp);
float2 srcWhitePlankian = PlanckianLocusChromaticity(WhiteTemp);
float2 srcWhite = WhiteTemp < 4000 ? srcWhitePlankian : srcWhiteDaylight;
float2 d65White = float2(0.31270, 0.32900);
// Offset along isotherm
float2 isothermal = PlanckianIsothermal(WhiteTemp, WhiteTint) - srcWhitePlankian;
srcWhite += isothermal;
@@ -280,7 +262,6 @@ float4 CombineLUTs(float2 uv, uint layerIndex)
// Move from encoded LUT color space to linear color
//float3 linearColor = encodedColor.rgb; // Default
//float3 linearColor = LogCToLinear(encodedColor.rgb); // LogC
float3 linearColor = LogToLinear(encodedColor.rgb) - LogToLinear(0); // Log
// Apply white balance

View File

@@ -196,25 +196,6 @@ struct Quad_GS2PS
uint LayerIndex : SV_RenderTargetArrayIndex;
};
float VisualizeTextureGrid(float2 texCoord, float2 textureSize, float gridSize)
{
if (gridSize > 0)
{
float2 t = frac(texCoord * textureSize);
return (t.x < gridSize || t.x > 1 - gridSize) || (t.y < gridSize || t.y > 1 - gridSize);
}
else
{
int2 t = int2(texCoord * textureSize);
return (t.x % 2 == 0 && t.y % 2 == 0) || (t.x % 2 == 1 && t.y % 2 == 1);
}
}
float BiasedNDotL(float NoL)
{
return saturate(NoL * 1.08f - 0.08f);
}
float Luminance(float3 color)
{
return dot(color, float3(0.299f, 0.587f, 0.114f));

View File

@@ -9,73 +9,50 @@
// http://gpuopen.com/optimized-reversible-tonemapper-for-resolve/
float3 FastTonemap(float3 c)
{
return c * rcp(max(max(c.r, c.g), c.b) + 1.0);
return c * rcp(max(max(c.r, c.g), c.b) + 1.0);
}
float4 FastTonemap(float4 c)
{
return float4(FastTonemap(c.rgb), c.a);
return float4(FastTonemap(c.rgb), c.a);
}
float3 FastTonemap(float3 c, float w)
{
return c * (w * rcp(max(max(c.r, c.g), c.b) + 1.0));
return c * (w * rcp(max(max(c.r, c.g), c.b) + 1.0));
}
float4 FastTonemap(float4 c, float w)
{
return float4(FastTonemap(c.rgb, w), c.a);
return float4(FastTonemap(c.rgb, w), c.a);
}
float3 FastTonemapInvert(float3 c)
{
return c * rcp(1.0 - max(max(c.r, c.g), c.b));
return c * rcp(1.0 - max(max(c.r, c.g), c.b));
}
float4 FastTonemapInvert(float4 c)
{
return float4(FastTonemapInvert(c.rgb), c.a);
return float4(FastTonemapInvert(c.rgb), c.a);
}
half3 LinearTo709Branchless(half3 linearColor)
{
linearColor = max(6.10352e-5, linearColor);
return min(linearColor * 4.5, pow(max(linearColor, 0.018), 0.45) * 1.099 - 0.099);
}
half3 LinearToSrgbBranchless(half3 linearColor)
{
linearColor = max(6.10352e-5, linearColor);
return min(linearColor * 12.92, pow(max(linearColor, 0.00313067), 1.0/2.4) * 1.055 - 0.055);
}
half LinearToSrgbBranchingChannel(half linearColor)
half LinearToSrgbChannel(half linearColor)
{
if (linearColor < 0.00313067)
return linearColor * 12.92;
return pow(linearColor, (1.0/2.4)) * 1.055 - 0.055;
return pow(linearColor, (1.0 / 2.4)) * 1.055 - 0.055;
}
half3 LinearToSrgbBranching(half3 linearColor)
half3 LinearToSrgb(half3 linearColor)
{
return half3(
LinearToSrgbBranchingChannel(linearColor.r),
LinearToSrgbBranchingChannel(linearColor.g),
LinearToSrgbBranchingChannel(linearColor.b));
LinearToSrgbChannel(linearColor.r),
LinearToSrgbChannel(linearColor.g),
LinearToSrgbChannel(linearColor.b));
}
half3 LinearToSrgb(half3 linearColor)
{
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM4
// Branching is faster than branchless on PC
return LinearToSrgbBranching(linearColor);
#else
// Use branchless on mobile
return LinearToSrgbBranchless(linearColor);
#endif
}
half3 sRGBToLinear(half3 color)
half3 sRGBToLinear(half3 color)
{
color = max(6.10352e-5, color);
return color > 0.04045 ? pow(color * (1.0 / 1.055) + 0.0521327, 2.4) : color * (1.0 / 12.92);
@@ -103,7 +80,7 @@ float3 LinearToLog(float3 linearColor)
const float exposureGrey = 444;
// Using stripped down, 'pure log', formula. Parameterized by grey points and dynamic range covered.
float3 logColor = log2(linearColor) / linearRange - log2(linearGrey) / linearRange + exposureGrey / 1023.0; // scalar: 3log2 3mad
float3 logColor = log2(linearColor) / linearRange - log2(linearGrey) / linearRange + exposureGrey / 1023.0; // scalar: 3log2 3mad
//float3 logColor = (log2(linearColor) - log2(linearGrey)) / linearRange + exposureGrey / 1023.0;
//float3 logColor = log2(linearColor / linearGrey) / linearRange + exposureGrey / 1023.0;
//float3 logColor = (0.432699 * log10(0.5 * linearColor + 0.037584) + 0.616596) + 0.03; // SLog
@@ -113,74 +90,4 @@ float3 LinearToLog(float3 linearColor)
return logColor;
}
// Alexa LogC converters (El 1000)
// See http://www.vocas.nl/webfm_send/964
// Max range is ~58.85666
struct ParamsLogC
{
float cut;
float a, b, c, d, e, f;
};
static const ParamsLogC LogC =
{
0.011361, // cut
5.555556, // a
0.047996, // b
0.244161, // c
0.386036, // d
5.301883, // e
0.092819 // f
};
float3 LinearToLogC(float3 linearColor)
{
return LogC.c * log10(LogC.a * linearColor + LogC.b) + LogC.d;
}
float3 LogCToLinear(float3 logcColor)
{
return (pow(10.0, (logcColor - LogC.d) / LogC.c) - LogC.b) / LogC.a;
}
// Dolby PQ transforms
float3 ST2084ToLinear(float3 pq)
{
const float m1 = 0.1593017578125; // = 2610. / 4096. * .25;
const float m2 = 78.84375; // = 2523. / 4096. * 128;
const float c1 = 0.8359375; // = 2392. / 4096. * 32 - 2413./4096.*32 + 1;
const float c2 = 18.8515625; // = 2413. / 4096. * 32;
const float c3 = 18.6875; // = 2392. / 4096. * 32;
const float C = 10000.;
float3 Np = pow(pq, 1.0 / m2);
float3 L = Np - c1;
L = max(0.0, L);
L = L / (c2 - c3 * Np);
L = pow(L, 1.0 / m1);
float3 P = L * C;
return P;
}
float3 LinearToST2084(float3 lin)
{
const float m1 = 0.1593017578125; // = 2610. / 4096. * .25;
const float m2 = 78.84375; // = 2523. / 4096. * 128;
const float c1 = 0.8359375; // = 2392. / 4096. * 32 - 2413./4096.*32 + 1;
const float c2 = 18.8515625; // = 2413. / 4096. * 32;
const float c3 = 18.6875; // = 2392. / 4096. * 32;
const float C = 10000.0;
float3 L = lin / C;
float3 Lm = pow(L, m1);
float3 N1 = (c1 + c2 * Lm);
float3 N2 = (1.0 + c3 * Lm);
float3 N = N1 * rcp(N2);
float3 P = pow(N, m2);
return P;
}
#endif

View File

@@ -60,18 +60,6 @@ void CS_GenerateHistogram(uint3 groupId : SV_GroupID, uint3 dispatchThreadId : S
if (dispatchThreadId.x < InputSize.x && dispatchThreadId.y < InputSize.y)
{
uint weight = 1u;
// Vignette weighting to add more focus on the center of the screen
#if 0
{
float2 uv = float2(dispatchThreadId.xy) / float2(InputSize.x, InputSize.y);
float2 d = abs(uv - (0.5).xx);
float factor = saturate(1.0 - dot(d, d));
factor *= factor;
weight = (uint)(64.0 * factor);
}
#endif
float3 color = Input[dispatchThreadId.xy].xyz;
float luminance = Luminance(color);
float logLuminance = ComputeHistogramPositionFromLuminance(luminance);

View File

@@ -3,19 +3,13 @@
#ifndef __IES_PROFILE__
#define __IES_PROFILE__
// Apply 1D IES light profile texture
// Calculate IES light profile from 1D texture
float ComputeLightProfileMultiplier(Texture2D tex, float3 worldPosition, float3 lightPosition, float3 lightDirection)
{
float3 negLightDirection = normalize(worldPosition - lightPosition);
// -1..1
float dotProd = dot(negLightDirection, lightDirection);
// -PI..PI (this distortion could be put into the texture but not without quality loss or more memory)
float angle = asin(dotProd);
// 0..1
float normAngle = angle / PI + 0.5f;
return tex.SampleLevel(SamplerLinearClamp, float2(normAngle, 0), 0).r;
float3 l = normalize(worldPosition - lightPosition);
float d = dot(lightPosition, lightDirection);
float angle = asin(d) / PI + 0.5f;
return tex.SampleLevel(SamplerLinearClamp, float2(angle, 0), 0).r;
}
#endif

View File

@@ -47,8 +47,8 @@ struct LightingData
// WorldLightVector is the vector from the position being shaded to the light, divided by the radius of the light.
float RadialAttenuation(float3 worldLightVector, half falloffExponent)
{
float normalizeDistanceSquared = dot(worldLightVector, worldLightVector);
return pow(1.0f - saturate(normalizeDistanceSquared), falloffExponent);
float t = dot(worldLightVector, worldLightVector);
return pow(1.0f - saturate(t), falloffExponent);
}
// Calculates attenuation for a spot light. Where L normalize vector to light.

View File

@@ -5,8 +5,8 @@
uint NextPow2(uint value)
{
uint mask = (1 << firstbithigh(value)) - 1;
return (value + mask) & ~mask;
uint mask = (1 << firstbithigh(value)) - 1;
return (value + mask) & ~mask;
}
float3 SafeNormalize(float3 v)
@@ -17,7 +17,6 @@ float3 SafeNormalize(float3 v)
float3 ExtractLargestComponent(float3 v)
{
float3 a = abs(v);
if (a.x > a.y)
{
if (a.x > a.z)
@@ -32,161 +31,160 @@ float3 ExtractLargestComponent(float3 v)
return float3(0, v.y > 0 ? 1 : -1, 0);
}
}
return float3(0, 0, v.z > 0 ? 1 : -1);
}
float Square(float x)
{
return x*x;
return x * x;
}
float2 Square(float2 x)
{
return x*x;
return x * x;
}
float3 Square(float3 x)
{
return x*x;
return x * x;
}
float4 Square(float4 x)
{
return x*x;
return x * x;
}
float Pow2(float x)
{
return x*x;
return x * x;
}
float2 Pow2(float2 x)
{
return x*x;
return x * x;
}
float3 Pow2(float3 x)
{
return x*x;
return x * x;
}
float4 Pow2(float4 x)
{
return x*x;
return x * x;
}
float Pow3(float x)
{
return x*x*x;
return x * x * x;
}
float2 Pow3(float2 x)
{
return x*x*x;
return x * x * x;
}
float3 Pow3(float3 x)
{
return x*x*x;
return x * x * x;
}
float4 Pow3(float4 x)
{
return x*x*x;
return x * x * x;
}
float Pow4(float x)
{
float xx = x*x;
float xx = x * x;
return xx * xx;
}
float2 Pow4(float2 x)
{
float2 xx = x*x;
float2 xx = x * x;
return xx * xx;
}
float3 Pow4(float3 x)
{
float3 xx = x*x;
float3 xx = x * x;
return xx * xx;
}
float4 Pow4(float4 x)
{
float4 xx = x*x;
float4 xx = x * x;
return xx * xx;
}
float Pow5(float x)
{
float xx = x*x;
float xx = x * x;
return xx * xx * x;
}
float2 Pow5(float2 x)
{
float2 xx = x*x;
float2 xx = x * x;
return xx * xx * x;
}
float3 Pow5(float3 x)
{
float3 xx = x*x;
float3 xx = x * x;
return xx * xx * x;
}
float4 Pow5(float4 x)
{
float4 xx = x*x;
float4 xx = x * x;
return xx * xx * x;
}
float Pow6(float x)
{
float xx = x*x;
float xx = x * x;
return xx * xx * xx;
}
float2 Pow6(float2 x)
{
float2 xx = x*x;
float2 xx = x * x;
return xx * xx * xx;
}
float3 Pow6(float3 x)
{
float3 xx = x*x;
float3 xx = x * x;
return xx * xx * xx;
}
float4 Pow6(float4 x)
{
float4 xx = x*x;
float4 xx = x * x;
return xx * xx * xx;
}
float ClampedPow(float x,float y)
float ClampedPow(float x, float y)
{
return pow(max(abs(x), 0.000001f),y);
return pow(max(abs(x), 0.000001f), y);
}
float2 ClampedPow(float2 x,float2 y)
float2 ClampedPow(float2 x, float2 y)
{
return pow(max(abs(x), float2(0.000001f, 0.000001f)), y);
}
float3 ClampedPow(float3 x,float3 y)
float3 ClampedPow(float3 x, float3 y)
{
return pow(max(abs(x), float3(0.000001f, 0.000001f, 0.000001f)), y);
}
}
float4 ClampedPow(float4 x,float4 y)
float4 ClampedPow(float4 x, float4 y)
{
return pow(max(abs(x), float4(0.000001f, 0.000001f, 0.000001f, 0.000001f)), y);
}
}
float4 FindQuatBetween(float3 from, float3 to)
{
@@ -208,8 +206,8 @@ float4 FindQuatBetween(float3 from, float3 to)
{
w = 0.f;
result = abs(from.x) > abs(from.y)
? float4(-from.z, 0.f, from.x, w)
: float4(0.f, -from.z, from.y, w);
? float4(-from.z, 0.f, from.x, w)
: float4(0.f, -from.z, from.y, w);
}
return normalize(result);
@@ -218,23 +216,13 @@ float4 FindQuatBetween(float3 from, float3 to)
// Rotates Position about the given axis by the given angle, in radians, and returns the offset to position
float3 RotateAboutAxis(float4 normalizedRotationAxisAndAngle, float3 positionOnAxis, float3 position)
{
// Project position onto the rotation axis and find the closest point on the axis to Position
float3 closestPointOnAxis = positionOnAxis + normalizedRotationAxisAndAngle.xyz * dot(normalizedRotationAxisAndAngle.xyz, position - positionOnAxis);
// Construct orthogonal axes in the plane of the rotation
float3 axisU = position - closestPointOnAxis;
float3 axisV = cross(normalizedRotationAxisAndAngle.xyz, axisU);
float cosAngle, sinAngle;
sincos(normalizedRotationAxisAndAngle.w, sinAngle, cosAngle);
// Rotate using the orthogonal axes
float3 rotation = axisU * cosAngle + axisV * sinAngle;
// Reconstruct the rotated world space position
float3 rotatedPosition = closestPointOnAxis + rotation;
// Convert from position to a position offset
return rotatedPosition - position;
float3 pointOnAxis = positionOnAxis + normalizedRotationAxisAndAngle.xyz * dot(normalizedRotationAxisAndAngle.xyz, position - positionOnAxis);
float3 axisU = position - pointOnAxis;
float3 axisV = cross(normalizedRotationAxisAndAngle.xyz, axisU);
float cosAngle, sinAngle;
sincos(normalizedRotationAxisAndAngle.w, sinAngle, cosAngle);
float3 rotation = axisU * cosAngle + axisV * sinAngle;
return pointOnAxis + rotation - position;
}
#endif

View File

@@ -133,10 +133,10 @@ float4 ImportanceSampleGGX(float2 e, float roughness)
// Multiple importance sampling power heuristic of two functions with a power of two.
// [Veach 1997, "Robust Monte Carlo Methods for Light Transport Simulation"]
float MISWeight(uint number, float pdf, uint otherNumber, float otherpdf)
float MISWeight(uint number, float PDF, uint otherNumber, float otherPDF)
{
float weight = number * pdf;
float otherWeight = otherNumber * otherpdf;
float weight = number * PDF;
float otherWeight = otherNumber * otherPDF;
return weight * weight / (weight * weight + otherWeight * otherWeight);
}

View File

@@ -107,7 +107,6 @@ half3 ColorLookupTable(half3 linearColor)
{
// Move from linear color to encoded LUT color space
//float3 encodedColor = linearColor; // Default
//float3 encodedColor = saturate(LinearToLogC(linearColor)); // LogC
float3 encodedColor = LinearToLog(linearColor + LogToLinear(0)); // Log
float3 uvw = encodedColor * ((LUTSize - 1) / LUTSize) + (0.5f / LUTSize);

View File

@@ -25,44 +25,42 @@ float4 SampleCubemap(float3 uv)
return Cube.SampleLevel(SamplerLinearClamp, uv, SourceMipIndex);
}
float3 GetCubemapVector(float2 scaledUVs)
float3 GetCubemapVector(float2 uv)
{
float3 cubeCoordinates;
float3 coords;
if (CubeFace == 0)
{
cubeCoordinates = float3(1, -scaledUVs.y, -scaledUVs.x);
coords = float3(1, -uv.y, -uv.x);
}
else if (CubeFace == 1)
{
cubeCoordinates = float3(-1, -scaledUVs.y, scaledUVs.x);
coords = float3(-1, -uv.y, uv.x);
}
else if (CubeFace == 2)
{
cubeCoordinates = float3(scaledUVs.x, 1, scaledUVs.y);
coords = float3(uv.x, 1, uv.y);
}
else if (CubeFace == 3)
{
cubeCoordinates = float3(scaledUVs.x, -1, -scaledUVs.y);
coords = float3(uv.x, -1, -uv.y);
}
else if (CubeFace == 4)
{
cubeCoordinates = float3(scaledUVs.x, -scaledUVs.y, 1);
coords = float3(uv.x, -uv.y, 1);
}
else
{
cubeCoordinates = float3(-scaledUVs.x, -scaledUVs.y, -1);
coords = float3(-uv.x, -uv.y, -1);
}
return cubeCoordinates;
return coords;
}
// Pixel Shader for filtring probe mip levels
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_FilterFace(Quad_VS2PS input) : SV_Target
{
float2 scaledUVs = input.TexCoord * 2 - 1;
float3 cubeCoordinates = GetCubemapVector(scaledUVs);
float2 uv = input.TexCoord * 2 - 1;
float3 cubeCoordinates = GetCubemapVector(uv);
#define NUM_FILTER_SAMPLES 512
@@ -102,10 +100,9 @@ float4 PS_CopyFace(Quad_VS2PS input) : SV_Target
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_CalcDiffuseIrradiance(Quad_VS2PS input) : SV_Target
{
float2 scaledUVs = input.TexCoord * 2 - 1;
float3 cubeCoordinates = normalize(GetCubemapVector(scaledUVs));
float squaredUVs = 1 + dot(scaledUVs, scaledUVs);
float2 uv = input.TexCoord * 2 - 1;
float3 cubeCoordinates = normalize(GetCubemapVector(uv));
float squaredUVs = 1 + dot(uv, uv);
// Dividing by NumSamples here to keep the sum in the range of fp16, once we get down to the 1x1 mip
float weight = 4 / (sqrt(squaredUVs) * squaredUVs);
@@ -124,23 +121,23 @@ float4 PS_AccDiffuseIrradiance(Quad_VS2PS input) : SV_Target
{
float4 result = 0;
{
float2 scaledUVs = saturate(input.TexCoord + Sample01.xy) * 2 - 1;
float3 cubeCoordinates = GetCubemapVector(scaledUVs);
float2 uv = saturate(input.TexCoord + Sample01.xy) * 2 - 1;
float3 cubeCoordinates = GetCubemapVector(uv);
result += SampleCubemap(cubeCoordinates);
}
{
float2 scaledUVs = saturate(input.TexCoord + Sample01.zw) * 2 - 1;
float3 cubeCoordinates = GetCubemapVector(scaledUVs);
float2 uv = saturate(input.TexCoord + Sample01.zw) * 2 - 1;
float3 cubeCoordinates = GetCubemapVector(uv);
result += SampleCubemap(cubeCoordinates);
}
{
float2 scaledUVs = saturate(input.TexCoord + Sample23.xy) * 2 - 1;
float3 cubeCoordinates = GetCubemapVector(scaledUVs);
float2 uv = saturate(input.TexCoord + Sample23.xy) * 2 - 1;
float3 cubeCoordinates = GetCubemapVector(uv);
result += SampleCubemap(cubeCoordinates);
}
{
float2 scaledUVs = saturate(input.TexCoord + Sample23.zw) * 2 - 1;
float3 cubeCoordinates = GetCubemapVector(scaledUVs);
float2 uv = saturate(input.TexCoord + Sample23.zw) * 2 - 1;
float3 cubeCoordinates = GetCubemapVector(uv);
result += SampleCubemap(cubeCoordinates);
}
return result / 4.0f;

View File

@@ -24,14 +24,17 @@ float PerlinRamp(in float t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
float2 PerlinRamp(in float2 t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
float3 PerlinRamp(in float3 t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
float4 PerlinRamp(in float4 t)
{
return t * t * t * (t * (t * 6 - 15) + 10);

View File

@@ -11,21 +11,20 @@ struct ThreeBandSHVector
half V2;
};
ThreeBandSHVector SHBasisFunction3(half3 inputVector)
ThreeBandSHVector SHBasisFunction3(half3 v)
{
ThreeBandSHVector result;
result.V0.x = 0.282095f;
result.V0.y = -0.488603f * inputVector.y;
result.V0.z = 0.488603f * inputVector.z;
result.V0.w = -0.488603f * inputVector.x;
result.V0.y = -0.488603f * v.y;
result.V0.z = 0.488603f * v.z;
result.V0.w = -0.488603f * v.x;
half3 vectorSquared = inputVector * inputVector;
result.V1.x = 1.092548f * inputVector.x * inputVector.y;
result.V1.y = -1.092548f * inputVector.y * inputVector.z;
result.V1.z = 0.315392f * (3.0f * inputVector.z - 1.0f);
result.V1.w = -1.092548f * inputVector.x * inputVector.z;
result.V2 = 0.546274f * (inputVector.x - inputVector.y);
result.V1.x = 1.092548f * v.x * v.y;
result.V1.y = -1.092548f * v.y * v.z;
result.V1.z = 0.315392f * (3.0f * v.z - 1.0f);
result.V1.w = -1.092548f * v.x * v.z;
result.V2 = 0.546274f * (v.x - v.y);
return result;
}

View File

@@ -57,7 +57,6 @@ int GetCubeFaceIndex(float3 direction)
float3 GetShadowPositionOffset(float offsetScale, float NoL, float3 normal)
{
// Note: offsetScale should be multiplied by 2*ShadowMapTextureTexelSize on CPU
float normalOffsetScale = saturate(1.0f - NoL);
return normal * (offsetScale * normalOffsetScale);
}
@@ -65,8 +64,6 @@ float3 GetShadowPositionOffset(float offsetScale, float NoL, float3 normal)
float CalculateSubsurfaceOcclusion(float opacity, float sceneDepth, float shadowMapDepth)
{
float thickness = max(sceneDepth - shadowMapDepth, 0);
//float density = -0.05f * log(1 - min(opacity, 0.999f));
//float occlusion = saturate(exp(-thickness * density));
float occlusion = 1 - thickness * lerp(1.0f, 100.0f, opacity);
return shadowMapDepth > 0.99f ? 1 : occlusion;
}

View File

@@ -103,30 +103,12 @@ float3 ComputeVolumeUV(float3 worldPosition, float4x4 worldToClip)
return float3(ndcPosition.xy * float2(0.5f, -0.5f) + 0.5f, ComputeNormalizedZSliceFromDepth(ndcPosition.w));
}
float IsotropicPhase()
{
return 1 / (4 * PI);
}
float HenyeyGreensteinPhase(float g, float cosTheta)
{
return (1 - g * g) / (4 * PI * pow(1 + g * g + 2 * g * cosTheta, 1.5f));
}
float SchlickPhase(float k, float cosTheta)
{
float t = (1 + k * cosTheta);
return (1 - k * k) / (4 * PI * t * t);
}
float RaleighPhase(float cosTheta)
{
return 3.0f * (1.0f + cosTheta * cosTheta) / (16.0f * PI);
}
// Positive g = forward scattering
// Zero g = isotropic
// Negative g = backward scattering
// +g = forward scattering, 0=g = isotropic, -g = backward scattering
float PhaseFunction(float g, float cosTheta)
{
return HenyeyGreensteinPhase(g, cosTheta);