Cleanup some old unused shader code

This commit is contained in:
2020-12-20 10:22:54 +01:00
parent afeaaee376
commit 8a870a07ae
25 changed files with 199 additions and 685 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+45 -81
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
+1 -52
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;
+5 -7
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);
}
+15 -165
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
-63
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
+20 -39
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
-19
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));
+14 -107
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
-12
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);
+5 -11
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
+2 -2
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.
+42 -54
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
+3 -3
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);
}
-1
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);
+22 -25
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;
+3
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);
+9 -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;
}
-3
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;
}
+1 -19
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);