浏览代码

Merge pull request #705 from Unity-Technologies/Convert-shaderLibrary-to-half-float-support

Change ShaderLibrary to use REAL instead of float/half
/main
GitHub 7 年前
当前提交
c58c9930
共有 36 个文件被更改,包括 2158 次插入2114 次删除
  1. 136
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/AreaLighting.hlsl
  2. 46
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/BC6H.hlsl
  3. 190
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/BSDF.hlsl
  4. 196
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Color.hlsl
  5. 129
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl
  6. 154
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/CommonLighting.hlsl
  7. 50
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/CommonMaterial.hlsl
  8. 6
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/CommonShadow.hlsl
  9. 24
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Debug.hlsl
  10. 80
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/EntityLighting.hlsl
  11. 319
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/ImageBasedLighting.hlsl
  12. 72
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Macros.hlsl
  13. 60
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/NormalSurfaceGradient.hlsl
  14. 238
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Packing.hlsl
  15. 56
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/PerPixelDisplacement.hlsl
  16. 24
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/QuaternionMath.hlsl
  17. 20
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Random.hlsl
  18. 38
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Refraction.hlsl
  19. 434
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Sampling/Fibonacci.hlsl
  20. 754
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Sampling/Hammersley.hlsl
  21. 6
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Sampling/SampleUVMappingInternal.hlsl
  22. 22
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Sampling/SampleUVMappingNormalInternal.hlsl
  23. 220
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Sampling/Sampling.hlsl
  24. 24
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/Shadow.hlsl
  25. 320
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
  26. 10
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowMoments.hlsl
  27. 494
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSampling.hlsl
  28. 40
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowTexFetch.hlsl
  29. 44
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Tessellation.hlsl
  30. 26
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/VolumeRendering.hlsl
  31. 10
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Wind.hlsl
  32. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.hlsl
  33. 8
      SampleScenes/HDTest/AnimTest/ThreeDScans/Gutenberg/Materials.meta
  34. 8
      Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/030_Shader_RenderOrder.meta
  35. 4
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/SHMath.hlsl
  36. 8
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/SHMath.hlsl.meta

136
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/AreaLighting.hlsl


#define APPROXIMATE_SPHERE_LIGHT_NUMERICALLY
// Not normalized by the factor of 1/TWO_PI.
float3 ComputeEdgeFactor(float3 V1, float3 V2)
real3 ComputeEdgeFactor(real3 V1, real3 V2)
float V1oV2 = dot(V1, V2);
float3 V1xV2 = cross(V1, V2);
real V1oV2 = dot(V1, V2);
real3 V1xV2 = cross(V1, V2);
#if 0
return V1xV2 * (rsqrt(1.0 - V1oV2 * V1oV2) * acos(V1oV2));
#else

float x = abs(V1oV2);
float y = 1.5707921083647782 + x * (-0.9995697178013095 + x * (0.778026455830408 + x * (-0.6173111361273548 + x * (0.4202724111150622 + x * (-0.19452783598217288 + x * 0.04232040013661036)))));
real x = abs(V1oV2);
real y = 1.5707921083647782 + x * (-0.9995697178013095 + x * (0.778026455830408 + x * (-0.6173111361273548 + x * (0.4202724111150622 + x * (-0.19452783598217288 + x * 0.04232040013661036)))));
if (V1oV2 < 0)
{

// Not normalized by the factor of 1/TWO_PI.
// Ref: Improving radiosity solutions through the use of analytically determined form-factors.
float IntegrateEdge(float3 V1, float3 V2)
real IntegrateEdge(real3 V1, real3 V2)
// 'sinSqSigma' is the sine^2 of the half of the opening angle of the sphere as seen from the shaded point.
// 'sinSqSigma' is the sine^2 of the real of the opening angle of the sphere as seen from the shaded point.
float DiffuseSphereLightIrradiance(float sinSqSigma, float cosOmega)
real DiffuseSphereLightIrradiance(real sinSqSigma, real cosOmega)
float x = sinSqSigma;
float y = cosOmega;
real x = sinSqSigma;
real y = cosOmega;
// Use a numerical fit found in Mathematica. Mean absolute error: 0.00476944.
// You can use the following Mathematica code to reproduce our results:

#else
#if 0 // Ref: Area Light Sources for Real-Time Graphics, page 4 (1996).
float sinSqOmega = saturate(1 - cosOmega * cosOmega);
float cosSqSigma = saturate(1 - sinSqSigma);
float sinSqGamma = saturate(cosSqSigma / sinSqOmega);
float cosSqGamma = saturate(1 - sinSqGamma);
real sinSqOmega = saturate(1 - cosOmega * cosOmega);
real cosSqSigma = saturate(1 - sinSqSigma);
real sinSqGamma = saturate(cosSqSigma / sinSqOmega);
real cosSqGamma = saturate(1 - sinSqGamma);
float sinSigma = sqrt(sinSqSigma);
float sinGamma = sqrt(sinSqGamma);
float cosGamma = sqrt(cosSqGamma);
real sinSigma = sqrt(sinSqSigma);
real sinGamma = sqrt(sinSqGamma);
real cosGamma = sqrt(cosSqGamma);
float sigma = asin(sinSigma);
float omega = acos(cosOmega);
float gamma = asin(sinGamma);
real sigma = asin(sinSigma);
real omega = acos(cosOmega);
real gamma = asin(sinGamma);
if (omega >= HALF_PI + sigma)
{

float e = sinSqSigma * cosOmega;
real e = sinSqSigma * cosOmega;
[branch]
if (omega < HALF_PI - sigma)

}
else
{
float g = (-2 * sqrt(sinSqOmega * cosSqSigma) + sinGamma) * cosGamma + (HALF_PI - gamma);
float h = cosOmega * (cosGamma * sqrt(saturate(sinSqSigma - cosSqGamma)) + sinSqSigma * asin(saturate(cosGamma / sinSigma)));
real g = (-2 * sqrt(sinSqOmega * cosSqSigma) + sinGamma) * cosGamma + (HALF_PI - gamma);
real h = cosOmega * (cosGamma * sqrt(saturate(sinSqSigma - cosSqGamma)) + sinSqSigma * asin(saturate(cosGamma / sinSigma)));
if (omega < HALF_PI)
{

}
}
#else // Ref: Moving Frostbite to Physically Based Rendering, page 47 (2015, optimized).
float cosSqOmega = cosOmega * cosOmega; // y^2
real cosSqOmega = cosOmega * cosOmega; // y^2
[branch]
if (cosSqOmega > sinSqSigma) // (y^2)>x

else
{
float cotSqSigma = rcp(sinSqSigma) - 1; // 1/x-1
float tanSqSigma = rcp(cotSqSigma); // x/(1-x)
float sinSqOmega = 1 - cosSqOmega; // 1-y^2
real cotSqSigma = rcp(sinSqSigma) - 1; // 1/x-1
real tanSqSigma = rcp(cotSqSigma); // x/(1-x)
real sinSqOmega = 1 - cosSqOmega; // 1-y^2
float w = sinSqOmega * tanSqSigma; // (1-y^2)*(x/(1-x))
float x = -cosOmega * rsqrt(w); // -y*Sqrt[(1/x-1)/(1-y^2)]
float y = sqrt(sinSqOmega * tanSqSigma - cosSqOmega); // Sqrt[(1-y^2)*(x/(1-x))-y^2]
float z = y * cotSqSigma; // Sqrt[(1-y^2)*(x/(1-x))-y^2]*(1/x-1)
real w = sinSqOmega * tanSqSigma; // (1-y^2)*(x/(1-x))
real x = -cosOmega * rsqrt(w); // -y*Sqrt[(1/x-1)/(1-y^2)]
real y = sqrt(sinSqOmega * tanSqSigma - cosSqOmega); // Sqrt[(1-y^2)*(x/(1-x))-y^2]
real z = y * cotSqSigma; // Sqrt[(1-y^2)*(x/(1-x))-y^2]*(1/x-1)
float a = cosOmega * acos(x) - z; // y*ArcCos[-y*Sqrt[(1/x-1)/(1-y^2)]]-Sqrt[(1-y^2)*(x/(1-x))-y^2]*(1/x-1)
float b = atan(y); // ArcTan[Sqrt[(1-y^2)*(x/(1-x))-y^2]]
real a = cosOmega * acos(x) - z; // y*ArcCos[-y*Sqrt[(1/x-1)/(1-y^2)]]-Sqrt[(1-y^2)*(x/(1-x))-y^2]*(1/x-1)
real b = atan(y); // ArcTan[Sqrt[(1-y^2)*(x/(1-x))-y^2]]
return saturate(INV_PI * (a * sinSqSigma + b));
}

// Expects non-normalized vertex positions.
float PolygonIrradiance(float4x3 L)
real PolygonIrradiance(real4x3 L)
{
#ifdef APPROXIMATE_POLY_LIGHT_AS_SPHERE_LIGHT
[unroll]

}
float3 F = float3(0, 0, 0);
real3 F = real3(0, 0, 0);
float3 V1 = L[edge];
float3 V2 = L[(edge + 1) % 4];
real3 V1 = L[edge];
real3 V2 = L[(edge + 1) % 4];
float f2 = saturate(dot(F, F));
float sinSqSigma = min(sqrt(f2), 0.999);
float cosOmega = clamp(F.z * rsqrt(f2), -1, 1);
real f2 = saturate(dot(F, F));
real sinSqSigma = min(sqrt(f2), 0.999);
real cosOmega = clamp(F.z * rsqrt(f2), -1, 1);
return DiffuseSphereLightIrradiance(sinSqSigma, cosOmega);
#else

// The fifth vertex for cases when clipping cuts off one corner.
// Due to a compiler bug, copying L into a vector array with 5 rows
// messes something up, so we need to stick with the matrix + the L4 vertex.
float3 L4 = L[3];
real3 L4 = L[3];
// This switch is surprisingly fast. Tried replacing it with a lookup array of vertices.
// Even though that replaced the switch with just some indexing and no branches, it became

}
// 3. Integrate
float sum = 0;
real sum = 0;
sum += IntegrateEdge(L[0], L[1]);
sum += IntegrateEdge(L[1], L[2]);
sum += IntegrateEdge(L[2], L[3]);

#endif
}
float LineFpo(float tLDDL, float lrcpD, float rcpD)
real LineFpo(real tLDDL, real lrcpD, real rcpD)
float LineFwt(float tLDDL, float l)
real LineFwt(real tLDDL, real l)
{
// Compute: l * ((l / d) / (d * d + l * l)).
return l * tLDDL;

// 'tangent' is the line's tangent direction.
// 'normal' is the direction orthogonal to the tangent. It is the shortest vector between
// the shaded point and the line, pointing away from the shaded point.
float LineIrradiance(float l1, float l2, float3 normal, float3 tangent)
real LineIrradiance(real l1, real l2, real3 normal, real3 tangent)
float d = length(normal);
float l1rcpD = l1 * rcp(d);
float l2rcpD = l2 * rcp(d);
float tLDDL1 = l1rcpD / (d * d + l1 * l1);
float tLDDL2 = l2rcpD / (d * d + l2 * l2);
float intWt = LineFwt(tLDDL2, l2) - LineFwt(tLDDL1, l1);
float intP0 = LineFpo(tLDDL2, l2rcpD, rcp(d)) - LineFpo(tLDDL1, l1rcpD, rcp(d));
real d = length(normal);
real l1rcpD = l1 * rcp(d);
real l2rcpD = l2 * rcp(d);
real tLDDL1 = l1rcpD / (d * d + l1 * l1);
real tLDDL2 = l2rcpD / (d * d + l2 * l2);
real intWt = LineFwt(tLDDL2, l2) - LineFwt(tLDDL1, l1);
real intP0 = LineFpo(tLDDL2, l2rcpD, rcp(d)) - LineFpo(tLDDL1, l1rcpD, rcp(d));
float ComputeLineWidthFactor(float3x3 invM, float3 ortho)
real ComputeLineWidthFactor(real3x3 invM, real3 ortho)
float det = invM._11 * invM._22 - invM._22 * invM._31 * invM._13;
float3x3 cof = {invM._22, 0.0, -invM._22 * invM._31,
0.0, invM._11 - invM._13 * invM._31, 0.0,
-invM._13 * invM._22, 0.0, invM._11 * invM._22};
real det = invM._11 * invM._22 - invM._22 * invM._31 * invM._13;
real3x3 cof = {invM._22, 0.0, -invM._22 * invM._31,
0.0, invM._11 - invM._13 * invM._31, 0.0,
-invM._13 * invM._22, 0.0, invM._11 * invM._22};
// 1.0 / length(mul(V, (1.0 / s * M))) = abs(s) / length(mul(V, M)).
return abs(det) / length(mul(ortho, cof));

float LTCEvaluate(float3 P1, float3 P2, float3 B, float3x3 invM)
real LTCEvaluate(real3 P1, real3 P2, real3 B, real3x3 invM)
{
// Inverse-transform the endpoints.
P1 = mul(P1, invM);

if (P1.z <= 0.0 && P2.z <= 0.0) return 0.0;
float width = ComputeLineWidthFactor(invM, B);
real width = ComputeLineWidthFactor(invM, B);
if (P1.z > P2.z)
{

// Recompute the length and the tangent in the new coordinate system.
float len = length(P2 - P1);
float3 T = normalize(P2 - P1);
real len = length(P2 - P1);
real3 T = normalize(P2 - P1);
float t = -P1.z / T.z;
P1 = float3(P1.xy + t * T.xy, 0.0);
real t = -P1.z / T.z;
P1 = real3(P1.xy + t * T.xy, 0.0);
// Set the length of the visible part of the light.
len -= t;

// between the shaded point and the line, pointing away from the shaded point.
// Can be interpreted as a point on the line, since the shaded point is at the origin.
float proj = dot(P1, T);
float3 P0 = P1 - proj * T;
real proj = dot(P1, T);
real3 P0 = P1 - proj * T;
float l1 = proj;
float l2 = l1 + len;
real l1 = proj;
real l2 = l1 + len;
float irradiance = LineIrradiance(l1, l2, P0, T);
real irradiance = LineIrradiance(l1, l2, P0, T);
// Guard against numerical precision issues.
return max(INV_PI * width * irradiance, 0.0);

46
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/BC6H.hlsl


// Measure compression error
float CalcMSLE(float3 a, float3 b)
{
float3 err = log2(( b + 1.0f) / (a + 1.0f ));
float3 err = log2(( b + 1.0) / (a + 1.0 ));
err = err * err;
return err.x + err.y + err.z;
}

{
return (f32tof16(x) * 128.0f) / (0x7bff + 1.0f);
return (f32tof16(x) * 128.0) / (0x7bff + 1.0);
return (f32tof16(x) * 512.0f) / (0x7bff + 1.0f);
return (f32tof16(x) * 512.0) / (0x7bff + 1.0);
return (f32tof16(x) * 1024.0f) / (0x7bff + 1.0f);
return (f32tof16(x) * 1024.0) / (0x7bff + 1.0);
return (x * 65536.0f + 0x8000) / 128.0f;
return (x * 65536.0 + 0x8000) / 128.0;
return (x * 65536.0f + 0x8000) / 512.0f;
return (x * 65536.0 + 0x8000) / 512.0;
return (x * 65536.0f + 0x8000) / 1024.0f;
return (x * 65536.0 + 0x8000) / 1024.0;
uint ComputeIndex3( float texelPos, float endPoint0Pos, float endPoint1Pos )
uint ComputeIndex3(float texelPos, float endPoint0Pos, float endPoint1Pos )
return (uint) clamp( r * 6.98182f + 0.00909f + 0.5f, 0.0f, 7.0f );
return (uint) clamp( r * 6.98182f + 0.00909f + 0.5f, 0.0, 7.0 );
uint ComputeIndex4( float texelPos, float endPoint0Pos, float endPoint1Pos )
uint ComputeIndex4(float texelPos, float endPoint0Pos, float endPoint1Pos )
return (uint) clamp( r * 14.93333f + 0.03333f + 0.5f, 0.0f, 15.0f );
return (uint) clamp( r * 14.93333f + 0.03333f + 0.5f, 0.0, 15.0 );
void SignExtend( inout float3 v1, uint mask, uint signFlag )
void SignExtend(inout float3 v1, uint mask, uint signFlag )
{
int3 v = (int3) v1;
v.x = ( v.x & mask ) | ( v.x < 0 ? signFlag : 0 );

// 2nd step for unquantize
float3 FinishUnquantize( float3 endpoint0Unq, float3 endpoint1Unq, float weight )
{
float3 comp = ( endpoint0Unq * ( 64.0f - weight ) + endpoint1Unq * weight + 32.0f ) * ( 31.0f / 4096.0f );
float3 comp = ( endpoint0Unq * ( 64.0 - weight ) + endpoint1Unq * weight + 32.0 ) * ( 31.0 / 4096.0 );
return f16tof32( uint3( comp ) );
}

refinedBlockMax = max( refinedBlockMax, texels[ i ] == blockMax ? refinedBlockMax : texels[ i ] );
}
float3 logBlockMax = log2( blockMax + 1.0f );
float3 logBlockMin = log2( blockMin + 1.0f );
float3 logRefinedBlockMax = log2( refinedBlockMax + 1.0f );
float3 logRefinedBlockMin = log2( refinedBlockMin + 1.0f );
float3 logBlockMaxExt = ( logBlockMax - logBlockMin ) * ( 1.0f / 32.0f );
float3 logBlockMax = log2( blockMax + 1.0 );
float3 logBlockMin = log2( blockMin + 1.0 );
float3 logRefinedBlockMax = log2( refinedBlockMax + 1.0 );
float3 logRefinedBlockMin = log2( refinedBlockMin + 1.0 );
float3 logBlockMaxExt = ( logBlockMax - logBlockMin ) * ( 1.0 / 32.0 );
blockMin = exp2( logBlockMin ) - 1.0f;
blockMax = exp2( logBlockMax ) - 1.0f;
blockMin = exp2( logBlockMin ) - 1.0;
blockMax = exp2( logBlockMax ) - 1.0;
float3 blockDir = blockMax - blockMin;
blockDir = blockDir / ( blockDir.x + blockDir.y + blockDir.z );

// compute compression error (MSLE)
float3 endpoint0Unq = Unquantize10( endpoint0 );
float3 endpoint1Unq = Unquantize10( endpoint1 );
float msle = 0.0f;
float msle = 0.0;
float weight = floor( ( indices[ i ] * 64.0f ) / 15.0f + 0.5f );
float weight = floor( ( indices[ i ] * 64.0 ) / 15.0 + 0.5);
float3 texelUnc = FinishUnquantize( endpoint0Unq, endpoint1Unq, weight );
msle += CalcMSLE( texels[ i ], texelUnc );

190
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/BSDF.hlsl


// Fresnel term
//-----------------------------------------------------------------------------
float F_Schlick(float f0, float f90, float u)
real F_Schlick(real f0, real f90, real u)
float x = 1.0 - u;
float x2 = x * x;
float x5 = x * x2 * x2;
real x = 1.0 - u;
real x2 = x * x;
real x5 = x * x2 * x2;
float F_Schlick(float f0, float u)
real F_Schlick(real f0, real u)
float3 F_Schlick(float3 f0, float f90, float u)
real3 F_Schlick(real3 f0, real f90, real u)
float x = 1.0 - u;
float x2 = x * x;
float x5 = x * x2 * x2;
real x = 1.0 - u;
real x2 = x * x;
real x5 = x * x2 * x2;
float3 F_Schlick(float3 f0, float u)
real3 F_Schlick(real3 f0, real u)
float F_Transm_Schlick(float f0, float f90, float u)
real F_Transm_Schlick(real f0, real f90, real u)
float x = 1.0 - u;
float x2 = x * x;
float x5 = x * x2 * x2;
real x = 1.0 - u;
real x2 = x * x;
real x5 = x * x2 * x2;
float F_Transm_Schlick(float f0, float u)
real F_Transm_Schlick(real f0, real u)
float3 F_Transm_Schlick(float3 f0, float f90, float u)
real3 F_Transm_Schlick(real3 f0, real f90, real u)
float x = 1.0 - u;
float x2 = x * x;
float x5 = x * x2 * x2;
real x = 1.0 - u;
real x2 = x * x;
real x5 = x * x2 * x2;
float3 F_Transm_Schlick(float3 f0, float u)
real3 F_Transm_Schlick(real3 f0, real u)
{
return F_Transm_Schlick(f0, 1.0, u); // sub mul mul mad mad*3
}

//-----------------------------------------------------------------------------
float D_GGXNoPI(float NdotH, float roughness)
real D_GGXNoPI(real NdotH, real roughness)
float a2 = Sq(roughness);
float s = (NdotH * a2 - NdotH) * NdotH + 1.0;
real a2 = Sq(roughness);
real s = (NdotH * a2 - NdotH) * NdotH + 1.0;
float D_GGX(float NdotH, float roughness)
real D_GGX(real NdotH, real roughness)
float G_MaskingSmithGGX(float NdotV, float roughness)
real G_MaskingSmithGGX(real NdotV, real roughness)
{
// G1(V, H) = HeavisideStep(VdotH) / (1 + Λ(V)).
// Λ(V) = -0.5 + 0.5 * sqrt(1 + 1 / a²).

}
// Ref: Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs, p. 12.
float D_GGX_Visible(float NdotH, float NdotV, float VdotH, float roughness)
real D_GGX_Visible(real NdotH, real NdotV, real VdotH, real roughness)
float GetSmithJointGGXPartLambdaV(float NdotV, float roughness)
real GetSmithJointGGXPartLambdaV(real NdotV, real roughness)
float a2 = Sq(roughness);
real a2 = Sq(roughness);
float V_SmithJointGGX(float NdotL, float NdotV, float roughness, float partLambdaV)
real V_SmithJointGGX(real NdotL, real NdotV, real roughness, real partLambdaV)
float a2 = Sq(roughness);
real a2 = Sq(roughness);
// Original formulation:
// lambda_v = (-1 + sqrt(a2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5

// Reorder code to be more optimal:
float lambdaV = NdotL * partLambdaV;
float lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);
real lambdaV = NdotL * partLambdaV;
real lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);
float V_SmithJointGGX(float NdotL, float NdotV, float roughness)
real V_SmithJointGGX(real NdotL, real NdotV, real roughness)
float partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
real partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
float DV_SmithJointGGX(float NdotH, float NdotL, float NdotV, float roughness, float partLambdaV)
real DV_SmithJointGGX(real NdotH, real NdotL, real NdotV, real roughness, real partLambdaV)
float a2 = Sq(roughness);
float s = (NdotH * a2 - NdotH) * NdotH + 1.0;
real a2 = Sq(roughness);
real s = (NdotH * a2 - NdotH) * NdotH + 1.0;
float lambdaV = NdotL * partLambdaV;
float lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);
real lambdaV = NdotL * partLambdaV;
real lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);
float2 D = float2(a2, s * s); // Fraction without the multiplier (1/Pi)
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the multiplier (1/2)
real2 D = real2(a2, s * s); // Fraction without the multiplier (1/Pi)
real2 G = real2(1, lambdaV + lambdaL); // Fraction without the multiplier (1/2)
float DV_SmithJointGGX(float NdotH, float NdotL, float NdotV, float roughness)
real DV_SmithJointGGX(real NdotH, real NdotL, real NdotV, real roughness)
float partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
real partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
return DV_SmithJointGGX(NdotH, NdotL, NdotV, roughness, partLambdaV);
}

// Otherwise, the worst case relative error is around 10%.
// https://www.desmos.com/calculator/wtp8lnjutx
float GetSmithJointGGXPartLambdaVApprox(float NdotV, float roughness)
real GetSmithJointGGXPartLambdaVApprox(real NdotV, real roughness)
float a = roughness;
real a = roughness;
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness, float partLambdaV)
real V_SmithJointGGXApprox(real NdotL, real NdotV, real roughness, real partLambdaV)
float a = roughness;
real a = roughness;
float lambdaV = NdotL * partLambdaV;
float lambdaL = NdotV * (NdotL * (1 - a) + a);
real lambdaV = NdotL * partLambdaV;
real lambdaL = NdotV * (NdotL * (1 - a) + a);
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness)
real V_SmithJointGGXApprox(real NdotL, real NdotV, real roughness)
float partLambdaV = GetSmithJointGGXPartLambdaVApprox(NdotV, roughness);
real partLambdaV = GetSmithJointGGXPartLambdaVApprox(NdotV, roughness);
float D_GGXAnisoNoPI(float TdotH, float BdotH, float NdotH, float roughnessT, float roughnessB)
real D_GGXAnisoNoPI(real TdotH, real BdotH, real NdotH, real roughnessT, real roughnessB)
float a2 = roughnessT * roughnessB;
float3 v = float3(roughnessB * TdotH, roughnessT * BdotH, a2 * NdotH);
float s = dot(v, v);
real a2 = roughnessT * roughnessB;
real3 v = real3(roughnessB * TdotH, roughnessT * BdotH, a2 * NdotH);
real s = dot(v, v);
float D_GGXAniso(float TdotH, float BdotH, float NdotH, float roughnessT, float roughnessB)
real D_GGXAniso(real TdotH, real BdotH, real NdotH, real roughnessT, real roughnessB)
float GetSmithJointGGXAnisoPartLambdaV(float TdotV, float BdotV, float NdotV, float roughnessT, float roughnessB)
real GetSmithJointGGXAnisoPartLambdaV(real TdotV, real BdotV, real NdotV, real roughnessT, real roughnessB)
return length(float3(roughnessT * TdotV, roughnessB * BdotV, NdotV));
return length(real3(roughnessT * TdotV, roughnessB * BdotV, NdotV));
float V_SmithJointGGXAniso(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB, float partLambdaV)
real V_SmithJointGGXAniso(real TdotV, real BdotV, real NdotV, real TdotL, real BdotL, real NdotL, real roughnessT, real roughnessB, real partLambdaV)
float lambdaV = NdotL * partLambdaV;
float lambdaL = NdotV * length(float3(roughnessT * TdotL, roughnessB * BdotL, NdotL));
real lambdaV = NdotL * partLambdaV;
real lambdaL = NdotV * length(real3(roughnessT * TdotL, roughnessB * BdotL, NdotL));
float V_SmithJointGGXAniso(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB)
real V_SmithJointGGXAniso(real TdotV, real BdotV, real NdotV, real TdotL, real BdotL, real NdotL, real roughnessT, real roughnessB)
float partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB);
real partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB);
float DV_SmithJointGGXAniso(float TdotH, float BdotH, float NdotH, float NdotV,
float TdotL, float BdotL, float NdotL,
float roughnessT, float roughnessB, float partLambdaV)
real DV_SmithJointGGXAniso(real TdotH, real BdotH, real NdotH, real NdotV,
real TdotL, real BdotL, real NdotL,
real roughnessT, real roughnessB, real partLambdaV)
float a2 = roughnessT * roughnessB;
float3 v = float3(roughnessB * TdotH, roughnessT * BdotH, a2 * NdotH);
float s = dot(v, v);
real a2 = roughnessT * roughnessB;
real3 v = real3(roughnessB * TdotH, roughnessT * BdotH, a2 * NdotH);
real s = dot(v, v);
float lambdaV = NdotL * partLambdaV;
float lambdaL = NdotV * length(float3(roughnessT * TdotL, roughnessB * BdotL, NdotL));
real lambdaV = NdotL * partLambdaV;
real lambdaL = NdotV * length(real3(roughnessT * TdotL, roughnessB * BdotL, NdotL));
float2 D = float2(a2 * a2 * a2, s * s); // Fraction without the multiplier (1/Pi)
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the multiplier (1/2)
real2 D = real2(a2 * a2 * a2, s * s); // Fraction without the multiplier (1/Pi)
real2 G = real2(1, lambdaV + lambdaL); // Fraction without the multiplier (1/2)
float DV_SmithJointGGXAniso(float TdotH, float BdotH, float NdotH,
float TdotV, float BdotV, float NdotV,
float TdotL, float BdotL, float NdotL,
float roughnessT, float roughnessB)
real DV_SmithJointGGXAniso(real TdotH, real BdotH, real NdotH,
real TdotV, real BdotV, real NdotV,
real TdotL, real BdotL, real NdotL,
real roughnessT, real roughnessB)
float partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB);
real partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB);
return DV_SmithJointGGXAniso(TdotH, BdotH, NdotH, NdotV, TdotL, BdotL, NdotL,
roughnessT, roughnessB, partLambdaV);
}

//-----------------------------------------------------------------------------
float LambertNoPI()
real LambertNoPI()
float Lambert()
real Lambert()
float DisneyDiffuseNoPI(float NdotV, float NdotL, float LdotV, float perceptualRoughness)
real DisneyDiffuseNoPI(real NdotV, real NdotL, real LdotV, real perceptualRoughness)
// float fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness;
float fd90 = 0.5 + (perceptualRoughness + perceptualRoughness * LdotV);
// real fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness;
real fd90 = 0.5 + (perceptualRoughness + perceptualRoughness * LdotV);
float lightScatter = F_Schlick(1.0, fd90, NdotL);
float viewScatter = F_Schlick(1.0, fd90, NdotV);
real lightScatter = F_Schlick(1.0, fd90, NdotL);
real viewScatter = F_Schlick(1.0, fd90, NdotV);
// Normalize the BRDF for polar view angles of up to (Pi/4).
// We use the worst case of (roughness = albedo = 1), and, for each view angle,

return rcp(1.03571) * (lightScatter * viewScatter);
}
float DisneyDiffuse(float NdotV, float NdotL, float LdotV, float perceptualRoughness)
real DisneyDiffuse(real NdotV, real NdotL, real LdotV, real perceptualRoughness)
float3 DiffuseGGXNoPI(float3 albedo, float NdotV, float NdotL, float NdotH, float LdotV, float roughness)
real3 DiffuseGGXNoPI(real3 albedo, real NdotV, real NdotL, real NdotH, real LdotV, real roughness)
float facing = 0.5 + 0.5 * LdotV; // (LdotH)^2
float rough = facing * (0.9 - 0.4 * facing) * (0.5 / NdotH + 1);
float transmitL = F_Transm_Schlick(0, NdotL);
float transmitV = F_Transm_Schlick(0, NdotV);
float smooth = transmitL * transmitV * 1.05; // Normalize F_t over the hemisphere
float single = lerp(smooth, rough, roughness); // Rescaled by PI
float multiple = roughness * (0.1159 * PI); // Rescaled by PI
real facing = 0.5 + 0.5 * LdotV; // (LdotH)^2
real rough = facing * (0.9 - 0.4 * facing) * (0.5 / NdotH + 1);
real transmitL = F_Transm_Schlick(0, NdotL);
real transmitV = F_Transm_Schlick(0, NdotV);
real smooth = transmitL * transmitV * 1.05; // Normalize F_t over the hemisphere
real single = lerp(smooth, rough, roughness); // Rescaled by PI
real multiple = roughness * (0.1159 * PI); // Rescaled by PI
float3 DiffuseGGX(float3 albedo, float NdotV, float NdotL, float NdotH, float LdotV, float roughness)
real3 DiffuseGGX(real3 albedo, real NdotV, real NdotL, real NdotH, real LdotV, real roughness)
{
// Note that we could save 2 cycles by inlining the multiplication by INV_PI.
return INV_PI * DiffuseGGXNoPI(albedo, NdotV, NdotL, NdotH, LdotV, roughness);

196
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Color.hlsl


//-----------------------------------------------------------------------------
// Gamma20
float Gamma20ToLinear(float c)
real Gamma20ToLinear(real c)
float3 Gamma20ToLinear(float3 c)
real3 Gamma20ToLinear(real3 c)
float4 Gamma20ToLinear(float4 c)
real4 Gamma20ToLinear(real4 c)
return float4(Gamma20ToLinear(c.rgb), c.a);
return real4(Gamma20ToLinear(c.rgb), c.a);
float LinearToGamma20(float c)
real LinearToGamma20(real c)
float3 LinearToGamma20(float3 c)
real3 LinearToGamma20(real3 c)
float4 LinearToGamma20(float4 c)
real4 LinearToGamma20(real4 c)
return float4(LinearToGamma20(c.rgb), c.a);
return real4(LinearToGamma20(c.rgb), c.a);
float Gamma22ToLinear(float c)
real Gamma22ToLinear(real c)
float3 Gamma22ToLinear(float3 c)
real3 Gamma22ToLinear(real3 c)
return pow(c.rgb, float3(2.2, 2.2, 2.2));
return pow(c.rgb, real3(2.2, 2.2, 2.2));
float4 Gamma22ToLinear(float4 c)
real4 Gamma22ToLinear(real4 c)
return float4(Gamma22ToLinear(c.rgb), c.a);
return real4(Gamma22ToLinear(c.rgb), c.a);
float LinearToGamma22(float c)
real LinearToGamma22(real c)
float3 LinearToGamma22(float3 c)
real3 LinearToGamma22(real3 c)
return pow(c.rgb, float3(0.454545454545455, 0.454545454545455, 0.454545454545455));
return pow(c.rgb, real3(0.454545454545455, 0.454545454545455, 0.454545454545455));
float4 LinearToGamma22(float4 c)
real4 LinearToGamma22(real4 c)
return float4(LinearToGamma22(c.rgb), c.a);
return real4(LinearToGamma22(c.rgb), c.a);
float3 SRGBToLinear(float3 c)
real3 SRGBToLinear(real3 c)
float3 linearRGBLo = c / 12.92;
float3 linearRGBHi = pow((c + 0.055) / 1.055, float3(2.4, 2.4, 2.4));
float3 linearRGB = (c <= 0.04045) ? linearRGBLo : linearRGBHi;
real3 linearRGBLo = c / 12.92;
real3 linearRGBHi = pow((c + 0.055) / 1.055, real3(2.4, 2.4, 2.4));
real3 linearRGB = (c <= 0.04045) ? linearRGBLo : linearRGBHi;
float4 SRGBToLinear(float4 c)
real4 SRGBToLinear(real4 c)
return float4(SRGBToLinear(c.rgb), c.a);
return real4(SRGBToLinear(c.rgb), c.a);
float3 LinearToSRGB(float3 c)
real3 LinearToSRGB(real3 c)
float3 sRGBLo = c * 12.92;
float3 sRGBHi = (pow(c, float3(1.0/2.4, 1.0/2.4, 1.0/2.4)) * 1.055) - 0.055;
float3 sRGB = (c <= 0.0031308) ? sRGBLo : sRGBHi;
real3 sRGBLo = c * 12.92;
real3 sRGBHi = (pow(c, real3(1.0/2.4, 1.0/2.4, 1.0/2.4)) * 1.055) - 0.055;
real3 sRGB = (c <= 0.0031308) ? sRGBLo : sRGBHi;
float4 LinearToSRGB(float4 c)
real4 LinearToSRGB(real4 c)
return float4(LinearToSRGB(c.rgb), c.a);
return real4(LinearToSRGB(c.rgb), c.a);
float3 FastSRGBToLinear(float3 c)
real3 FastSRGBToLinear(real3 c)
float4 FastSRGBToLinear(float4 c)
real4 FastSRGBToLinear(real4 c)
return float4(FastSRGBToLinear(c.rgb), c.a);
return real4(FastSRGBToLinear(c.rgb), c.a);
float3 FastLinearToSRGB(float3 c)
real3 FastLinearToSRGB(real3 c)
float4 FastLinearToSRGB(float4 c)
real4 FastLinearToSRGB(real4 c)
return float4(FastLinearToSRGB(c.rgb), c.a);
return real4(FastLinearToSRGB(c.rgb), c.a);
}
//-----------------------------------------------------------------------------

// Convert rgb to luminance
// with rgb in linear space with sRGB primaries and D65 white point
float Luminance(float3 linearRgb)
real Luminance(real3 linearRgb)
return dot(linearRgb, float3(0.2126729f, 0.7151522f, 0.0721750f));
return dot(linearRgb, real3(0.2126729f, 0.7151522f, 0.0721750f));
float Luminance(float4 linearRgba)
real Luminance(real4 linearRgba)
{
return Luminance(linearRgba.rgb);
}

// Ref: http://www.nvidia.com/object/real-time-ycocg-dxt-compression.html
#define YCOCG_CHROMA_BIAS (128.0 / 255.0)
float3 RGBToYCoCg(float3 rgb)
real3 RGBToYCoCg(real3 rgb)
float3 YCoCg;
YCoCg.x = dot(rgb, float3(0.25, 0.5, 0.25));
YCoCg.y = dot(rgb, float3(0.5, 0.0, -0.5)) + YCOCG_CHROMA_BIAS;
YCoCg.z = dot(rgb, float3(-0.25, 0.5, -0.25)) + YCOCG_CHROMA_BIAS;
real3 YCoCg;
YCoCg.x = dot(rgb, real3(0.25, 0.5, 0.25));
YCoCg.y = dot(rgb, real3(0.5, 0.0, -0.5)) + YCOCG_CHROMA_BIAS;
YCoCg.z = dot(rgb, real3(-0.25, 0.5, -0.25)) + YCOCG_CHROMA_BIAS;
float3 YCoCgToRGB(float3 YCoCg)
real3 YCoCgToRGB(real3 YCoCg)
float Y = YCoCg.x;
float Co = YCoCg.y - YCOCG_CHROMA_BIAS;
float Cg = YCoCg.z - YCOCG_CHROMA_BIAS;
real Y = YCoCg.x;
real Co = YCoCg.y - YCOCG_CHROMA_BIAS;
real Cg = YCoCg.z - YCOCG_CHROMA_BIAS;
float3 rgb;
real3 rgb;
rgb.r = Y + Co - Cg;
rgb.g = Y + Cg;
rgb.b = Y - Co - Cg;

// Following function can be use to reconstruct chroma component for a checkboard YCoCg pattern
// Reference: The Compact YCoCg Frame Buffer
float YCoCgCheckBoardEdgeFilter(float centerLum, float2 a0, float2 a1, float2 a2, float2 a3)
real YCoCgCheckBoardEdgeFilter(real centerLum, real2 a0, real2 a1, real2 a2, real2 a3)
float4 lum = float4(a0.x, a1.x, a2.x, a3.x);
// Optimize: float4 w = 1.0 - step(30.0 / 255.0, abs(lum - centerLum));
float4 w = 1.0 - saturate((abs(lum.xxxx - centerLum) - 30.0 / 255.0) * HALF_MAX);
float W = w.x + w.y + w.z + w.w;
real4 lum = real4(a0.x, a1.x, a2.x, a3.x);
// Optimize: real4 w = 1.0 - step(30.0 / 255.0, abs(lum - centerLum));
real4 w = 1.0 - saturate((abs(lum.xxxx - centerLum) - 30.0 / 255.0) * HALF_MAX);
real W = w.x + w.y + w.z + w.w;
// handle the special case where all the weights are zero.
return (W == 0.0) ? a0.y : (w.x * a0.y + w.y* a1.y + w.z* a2.y + w.w * a3.y) / W;
}

// Hue [0.0, 1.0]
// Sat [0.0, 1.0]
// Lum [0.0, HALF_MAX]
float3 RgbToHsv(float3 c)
real3 RgbToHsv(real3 c)
const float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
float4 p = lerp(float4(c.bg, K.wz), float4(c.gb, K.xy), step(c.b, c.g));
float4 q = lerp(float4(p.xyw, c.r), float4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
const float e = 1.0e-4;
return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
const real4 K = real4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
real4 p = lerp(real4(c.bg, K.wz), real4(c.gb, K.xy), step(c.b, c.g));
real4 q = lerp(real4(p.xyw, c.r), real4(c.r, p.yzx), step(p.x, c.r));
real d = q.x - min(q.w, q.y);
const real e = 1.0e-4;
return real3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
float3 HsvToRgb(float3 c)
real3 HsvToRgb(real3 c)
const float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
const real4 K = real4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
real3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * lerp(K.xxx, saturate(p - K.xxx), c.y);
}

struct ParamsPQ
{
float N, M;
float C1, C2, C3;
real N, M;
real C1, C2, C3;
};
static const ParamsPQ PQ =

2392.0 / 4096.0 * 32.0, // C3
};
float3 LinearToPQ(float3 x, float maxPQValue)
real3 LinearToPQ(real3 x, real maxPQValue)
float3 nd = (PQ.C1 + PQ.C2 * x) / (1.0 + PQ.C3 * x);
real3 nd = (PQ.C1 + PQ.C2 * x) / (1.0 + PQ.C3 * x);
float3 LinearToPQ(float3 x)
real3 LinearToPQ(real3 x)
float3 PQToLinear(float3 x, float maxPQValue)
real3 PQToLinear(real3 x, real maxPQValue)
float3 nd = max(x - PQ.C1, 0.0) / (PQ.C2 - (PQ.C3 * x));
real3 nd = max(x - PQ.C1, 0.0) / (PQ.C2 - (PQ.C3 * x));
float3 PQToLinear(float3 x)
real3 PQToLinear(real3 x)
{
return PQToLinear(x, DEFAULT_MAX_PQ);
}

struct ParamsLogC
{
float cut;
float a, b, c, d, e, f;
real cut;
real a, b, c, d, e, f;
};
static const ParamsLogC LogC =

0.092819 // f
};
float LinearToLogC_Precise(half x)
real LinearToLogC_Precise(real x)
float o;
real o;
if (x > LogC.cut)
o = LogC.c * log10(LogC.a * x + LogC.b) + LogC.d;
else

float3 LinearToLogC(float3 x)
real3 LinearToLogC(real3 x)
return float3(
return real3(
LinearToLogC_Precise(x.x),
LinearToLogC_Precise(x.y),
LinearToLogC_Precise(x.z)

#endif
}
float LogCToLinear_Precise(float x)
real LogCToLinear_Precise(real x)
float o;
real o;
if (x > LogC.e * LogC.cut + LogC.f)
o = (pow(10.0, (x - LogC.d) / LogC.c) - LogC.b) / LogC.a;
else

float3 LogCToLinear(float3 x)
real3 LogCToLinear(real3 x)
return float3(
return real3(
LogCToLinear_Precise(x.x),
LogCToLinear_Precise(x.y),
LogCToLinear_Precise(x.z)

// Fast reversible tonemapper
// http://gpuopen.com/optimized-reversible-tonemapper-for-resolve/
float3 FastTonemap(float3 c)
real3 FastTonemap(real3 c)
float4 FastTonemap(float4 c)
real4 FastTonemap(real4 c)
return float4(FastTonemap(c.rgb), c.a);
return real4(FastTonemap(c.rgb), c.a);
float3 FastTonemap(float3 c, float w)
real3 FastTonemap(real3 c, real w)
float4 FastTonemap(float4 c, float w)
real4 FastTonemap(real4 c, real w)
return float4(FastTonemap(c.rgb, w), c.a);
return real4(FastTonemap(c.rgb, w), c.a);
float3 FastTonemapInvert(float3 c)
real3 FastTonemapInvert(real3 c)
float4 FastTonemapInvert(float4 c)
real4 FastTonemapInvert(real4 c)
return float4(FastTonemapInvert(c.rgb), c.a);
return real4(FastTonemapInvert(c.rgb), c.a);
float3 ApplyLut3D(TEXTURE3D_ARGS(tex, samplerTex), float3 uvw, float2 scaleOffset)
real3 ApplyLut3D(TEXTURE3D_ARGS(tex, samplerTex), real3 uvw, real2 scaleOffset)
float shift = floor(uvw.z);
real shift = floor(uvw.z);
uvw.xy = uvw.xy * scaleOffset.y * scaleOffset.xx + scaleOffset.xx * 0.5;
uvw.x += shift * scaleOffset.x;
return SAMPLE_TEXTURE3D(tex, samplerTex, uvw).rgb;

// scaleOffset = (1 / lut_width, 1 / lut_height, lut_height - 1)
float3 ApplyLut2D(TEXTURE2D_ARGS(tex, samplerTex), float3 uvw, float3 scaleOffset)
real3 ApplyLut2D(TEXTURE2D_ARGS(tex, samplerTex), real3 uvw, real3 scaleOffset)
float shift = floor(uvw.z);
real shift = floor(uvw.z);
SAMPLE_TEXTURE2D(tex, samplerTex, uvw.xy + float2(scaleOffset.y, 0.0)).rgb,
SAMPLE_TEXTURE2D(tex, samplerTex, uvw.xy + real2(scaleOffset.y, 0.0)).rgb,
uvw.z - shift
);
return uvw;

// params = (lut_height, 0.5 / lut_width, 0.5 / lut_height, lut_height / lut_height - 1)
float3 GetLutStripValue(float2 uv, float4 params)
real3 GetLutStripValue(real2 uv, real4 params)
float3 color;
real3 color;
color.r = frac(uv.x * params.x);
color.b = uv.x - color.r / params.x;
color.g = uv.y;

129
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Common.hlsl


// Convention:
// Unity is Y up - left handed
// Unity is Y up and left handed in world space
// Caution: When going from world space to view space, unity is right handed in view space and the determinant of the matrix is negative
// For cubemap capture (reflection probe) view space is still left handed (cubemap convention) and the determinant is positive.
// The lighting code assume that 1 Unity unit (1uu) == 1 meters. This is very important regarding physically based light unit and inverse square attenuation
// space at the end of the variable name
// WS: world space

// uniform have _ as prefix + uppercase _LowercaseThenCamelCase
// Do not use "in", only "out" or "inout" as califier, no "inline" keyword either, useless.
// When declaring "out" argument of function, they are always last
// headers from ShaderLibrary do not include "common.hlsl", this should be included in the .shader using it (or Material.hlsl)
// These structures need to be align on float4 to respect various packing rules from sahder language.
// This mean that these structure need to be padded.
// These structures need to be align on float4 to respect various packing rules from shader language. This mean that these structure need to be padded.
// Rules: When doing an array for constant buffer variables, we always use float4 to avoid any packing issue, particularly between compute shader and pixel shaders
// i.e don't use SetGlobalFloatArray or SetComputeFloatParams
// The array can be alias in hlsl. Exemple:
// uniform float4 packedArray[3];
// static float unpackedArray[12] = (float[12])packedArray;
// The function of the shader library are stateless, no uniform decalare in it.
// Any function that require an explicit precision, use float or half qualifier, when the function can support both, it use real (see below)
// If a function require to have both a half and a float version, then both need to be explicitly define
#ifndef real
#ifdef SHADER_API_MOBILE
#define real half
#define real2 half2
#define real3 half3
#define real4 half4
#define real2x2 half2x2
#define real2x3 half2x3
#define real3x2 half3x2
#define real3x3 half3x3
#define real3x4 half3x4
#define real4x3 half4x3
#define real4x4 half4x4
// Do not use "in", only "out" or "inout" as califier, not "inline" keyword either, useless.
#define REAL_MIN HALF_MIN
#define REAL_MAX HALF_MAX
#define TEMPLATE_1_REAL TEMPLATE_1_HALF
#define TEMPLATE_2_REAL TEMPLATE_2_HALF
#define TEMPLATE_3_REAL TEMPLATE_3_HALF
// The lighting code assume that 1 Unity unit (1uu) == 1 meters. This is very important regarding physically based light unit and inverse square attenuation
#else
// When declaring "out" argument of function, they are always last
#define real float
#define real2 float2
#define real3 float3
#define real4 float4
// headers from ShaderLibrary do not include "common.hlsl", this should be included in the .shader using it (or Material.hlsl)
#define real2x2 float2x2
#define real2x3 float2x3
#define real3x2 float3x2
#define real3x3 float3x3
#define real3x4 float3x4
#define real4x3 float4x3
#define real4x4 float4x4
#define REAL_MIN FLT_MIN
#define REAL_MAX FLT_MAX
#define TEMPLATE_1_REAL TEMPLATE_1_FLT
#define TEMPLATE_2_REAL TEMPLATE_2_FLT
#define TEMPLATE_3_REAL TEMPLATE_3_FLT
// Rules: When doing an array for constant buffer variables, we always use float4 to avoid any packing issue, particularly between compute shader and pixel shaders
// i.e don't use SetGlobalFloatArray or SetComputeFloatParams
// The array can be alias in hlsl. Exemple:
// uniform float4 packedArray[3];
// static float unpackedArray[12] = (float[12]packedArray;
#endif // SHADER_API_MOBILE
#endif // #ifndef real
// Include language header
#if defined(SHADER_API_D3D11)

#ifndef INTRINSIC_WAVEREADFIRSTLANE
// Warning: for correctness, the argument must have the same value across the wave!
TEMPLATE_1_FLT(WaveReadFirstLane, scalarValue, return scalarValue)
TEMPLATE_1_REAL(WaveReadFirstLane, scalarValue, return scalarValue)
TEMPLATE_1_INT(WaveReadFirstLane, scalarValue, return scalarValue)
#endif

#endif // INTRINSIC_MAD24
#ifndef INTRINSIC_MINMAX3
TEMPLATE_3_FLT(Min3, a, b, c, return min(min(a, b), c))
TEMPLATE_3_REAL(Min3, a, b, c, return min(min(a, b), c))
TEMPLATE_3_FLT(Max3, a, b, c, return max(max(a, b), c))
TEMPLATE_3_REAL(Max3, a, b, c, return max(max(a, b), c))
TEMPLATE_3_INT(Max3, a, b, c, return max(max(a, b), c))
#endif // INTRINSIC_MINMAX3

// Common math functions
// ----------------------------------------------------------------------------
float DegToRad(float deg)
real DegToRad(real deg)
float RadToDeg(float rad)
real RadToDeg(real rad)
TEMPLATE_1_FLT(Sq, x, return x * x)
TEMPLATE_1_REAL(Sq, x, return x * x)
float FastACosPos(float inX)
real FastACosPos(real inX)
float x = abs(inX);
float res = (0.0468878 * x + -0.203471) * x + 1.570796; // p(x)
real x = abs(inX);
real res = (0.0468878 * x + -0.203471) * x + 1.570796; // p(x)
res *= sqrt(1.0 - x);
return res;

// Input [-1, 1] and output [0, PI]
// 12 VALU
float FastACos(float inX)
real FastACos(real inX)
float res = FastACosPos(inX);
real res = FastACosPos(inX);
return (inX >= 0) ? res : PI - res; // Undo range reduction
}

// input [-1, 1] and output [-PI/2, PI/2]
float FastASin(float x)
real FastASin(real x)
{
return HALF_PI - FastACos(x);
}

// 4 VGPR, 14 FR (10 FR, 1 QR), 2 scalar
// input [0, infinity] and output [0, PI/2]
float FastATanPos(float x)
real FastATanPos(real x)
float t0 = (x < 1.0) ? x : 1.0 / x;
float t1 = t0 * t0;
float poly = 0.0872929;
real t0 = (x < 1.0) ? x : 1.0 / x;
real t1 = t0 * t0;
real poly = 0.0872929;
poly = -0.301895 + poly * t1;
poly = 1.0 + poly * t1;
poly = poly * t0;

// 4 VGPR, 16 FR (12 FR, 1 QR), 2 scalar
// input [-infinity, infinity] and output [-PI/2, PI/2]
float FastATan(float x)
real FastATan(real x)
float t0 = FastATanPos(abs(x));
real t0 = FastATanPos(abs(x));
return (x < 0.0) ? -t0 : t0;
}

TEMPLATE_2_FLT(PositivePow, base, power, return pow(max(abs(base), FLT_EPS), power))
TEMPLATE_2_REAL(PositivePow, base, power, return pow(max(abs(base), FLT_EPS), power))
// Computes (FastSign(s) * x) using 2x VALU.
// See the comment about FastSign() below.

// Orthonormalizes the tangent frame using the Gram-Schmidt process.
// We assume that both the tangent and the normal are normalized.
// Returns the new tangent (the normal is unaffected).
float3 Orthonormalize(float3 tangent, float3 normal)
real3 Orthonormalize(real3 tangent, real3 normal)
float Smoothstep01(float x)
real Smoothstep01(real x)
{
return x * x * (3.0 - (2.0 * x));
}

float phi = (coord.x * 2.f * PI - PI*0.5f);
float cosTheta = cos(theta);
float sinTheta = sqrt(1.0f - min(1.0f, cosTheta*cosTheta));
float sinTheta = sqrt(1.0 - min(1.0, cosTheta*cosTheta));
float cosPhi = cos(phi);
float sinPhi = sin(phi);

// ----------------------------------------------------------------------------
// Normalize that account for vectors with zero length
float3 SafeNormalize(float3 inVec)
real3 SafeNormalize(real3 inVec)
float dp3 = max(FLT_MIN, dot(inVec, inVec));
return inVec * rsqrt(dp3);
}
// Normalize that account for vectors with zero length
half3 SafeNormalize(half3 inVec)
{
half dp3 = max(HALF_MIN, dot(inVec, inVec));
real dp3 = max(REAL_MIN, dot(inVec, inVec));
return inVec * rsqrt(dp3);
}

154
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/CommonLighting.hlsl


#define UNITY_COMMON_LIGHTING_INCLUDED
// These clamping function to max of floating point 16 bit are use to prevent INF in code in case of extreme value
float ClampToFloat16Max(float value)
{
return min(value, HALF_MAX);
}
float2 ClampToFloat16Max(float2 value)
{
return min(value, HALF_MAX);
}
float3 ClampToFloat16Max(float3 value)
{
return min(value, HALF_MAX);
}
float4 ClampToFloat16Max(float4 value)
{
return min(value, HALF_MAX);
}
TEMPLATE_1_REAL(ClampToFloat16Max, value, return min(value, HALF_MAX))
// Ligthing convention
// Light direction is oriented backward (-Z). i.e in shader code, light direction is -lightData.forward

// of dimensions [-1, 1]^3 to a vector centered within the unit sphere.
// The function expects 'v' to be within the cube (possibly unexpected results otherwise).
// Ref: http://mathproofs.blogspot.com/2005/07/mapping-cube-to-sphere.html
float3 MapCubeToSphere(float3 v)
real3 MapCubeToSphere(real3 v)
float3 v2 = v * v;
float2 vr3 = v2.xy * rcp(3.0);
return v * sqrt((float3)1.0 - 0.5 * v2.yzx - 0.5 * v2.zxy + vr3.yxx * v2.zzy);
real3 v2 = v * v;
real2 vr3 = v2.xy * rcp(3.0);
return v * sqrt((real3)1.0 - 0.5 * v2.yzx - 0.5 * v2.zxy + vr3.yxx * v2.zzy);
float ComputeCubeToSphereMapSqMagnitude(float3 v)
real ComputeCubeToSphereMapSqMagnitude(real3 v)
float3 v2 = v * v;
real3 v2 = v * v;
// Note: dot(v, v) is often computed before this function is called,
// so the compiler should optimize and use the precomputed result here.
return dot(v, v) - v2.x * v2.y - v2.y * v2.z - v2.z * v2.x + v2.x * v2.y * v2.z;

// Ref: http://bpeers.com/blog/?itemid=1017
float ComputeCubemapTexelSolidAngle(float3 L, float texelArea)
real ComputeCubemapTexelSolidAngle(real3 L, real texelArea)
float d = Max3(abs(L.x), abs(L.y), abs(L.z));
real d = Max3(abs(L.x), abs(L.y), abs(L.z));
float invDist = d;
real invDist = d;
// dw = dA * cosTheta / (dist * dist), cosTheta = 1.0 / dist,
// where 'dA' is the area of the cube map texel.

//-----------------------------------------------------------------------------
// Ref: Moving Frostbite to PBR
float SmoothDistanceAttenuation(float squaredDistance, float invSqrAttenuationRadius)
real SmoothDistanceAttenuation(real squaredDistance, real invSqrAttenuationRadius)
float factor = squaredDistance * invSqrAttenuationRadius;
float smoothFactor = saturate(1.0 - factor * factor);
real factor = squaredDistance * invSqrAttenuationRadius;
real smoothFactor = saturate(1.0 - factor * factor);
float GetDistanceAttenuation(float sqrDist, float invSqrAttenuationRadius)
real GetDistanceAttenuation(real sqrDist, real invSqrAttenuationRadius)
float attenuation = 1.0 / (max(PUNCTUAL_LIGHT_THRESHOLD * PUNCTUAL_LIGHT_THRESHOLD, sqrDist));
real attenuation = 1.0 / (max(PUNCTUAL_LIGHT_THRESHOLD * PUNCTUAL_LIGHT_THRESHOLD, sqrDist));
float GetDistanceAttenuation(float3 unL, float invSqrAttenuationRadius)
real GetDistanceAttenuation(real3 unL, real invSqrAttenuationRadius)
float sqrDist = dot(unL, unL);
real sqrDist = dot(unL, unL);
float GetAngleAttenuation(float3 L, float3 lightDir, float lightAngleScale, float lightAngleOffset)
real GetAngleAttenuation(real3 L, real3 lightDir, real lightAngleScale, real lightAngleOffset)
float cd = dot(lightDir, L);
float attenuation = saturate(cd * lightAngleScale + lightAngleOffset);
real cd = dot(lightDir, L);
real attenuation = saturate(cd * lightAngleScale + lightAngleOffset);
// smooth the transition
attenuation *= attenuation;

// The transformation is performed along the major axis of the ellipsoid (corresponding to 'r1').
// Both the ellipsoid (e.i. 'axis') and 'unL' should be in the same coordinate system.
// 'unL' should be computed from the center of the ellipsoid.
float GetEllipsoidalDistanceAttenuation(float3 unL, float invSqRadius,
float3 axis, float invAspectRatio)
real GetEllipsoidalDistanceAttenuation(real3 unL, real invSqRadius,
real3 axis, real invAspectRatio)
float projL = dot(unL, axis);
real projL = dot(unL, axis);
float diff = projL - projL * invAspectRatio;
real diff = projL - projL * invAspectRatio;
float sqDist = dot(unL, unL);
real sqDist = dot(unL, unL);
return SmoothDistanceAttenuation(sqDist, invSqRadius);
}

float GetEllipsoidalDistanceAttenuation(float3 unL, float3 invHalfDim)
real GetEllipsoidalDistanceAttenuation(real3 unL, real3 invHalfDim)
float sqDist = dot(unL, unL);
real sqDist = dot(unL, unL);
return SmoothDistanceAttenuation(sqDist, 1.0);
}

// 'unL' should be computed from the center of the box.
float GetBoxDistanceAttenuation(float3 unL, float3 invHalfDim)
real GetBoxDistanceAttenuation(real3 unL, real3 invHalfDim)
{
// Transform the light vector so that we can work with
// with the box as if it was a [-1, 1]^2 cube.

if (Max3(abs(unL.x), abs(unL.y), abs(unL.z)) > 1.0) return 0.0;
float sqDist = ComputeCubeToSphereMapSqMagnitude(unL);
real sqDist = ComputeCubeToSphereMapSqMagnitude(unL);
return SmoothDistanceAttenuation(sqDist, 1.0);
}

float2 GetIESTextureCoordinate(float3x3 lightToWord, float3 L)
real2 GetIESTextureCoordinate(real3x3 lightToWord, real3 L)
float3 dir = mul(lightToWord, -L); // Using matrix on left side do a transpose
real3 dir = mul(lightToWord, -L); // Using matrix on left side do a transpose
float2 sphericalCoord; // .x is theta, .y is phi
real2 sphericalCoord; // .x is theta, .y is phi
float theta = atan2(dir.y, dir.x);
real theta = atan2(dir.y, dir.x);
sphericalCoord.x = theta * INV_TWO_PI;
return sphericalCoord;

//-----------------------------------------------------------------------------
// Ref: Horizon Occlusion for Normal Mapped Reflections: http://marmosetco.tumblr.com/post/81245981087
float GetHorizonOcclusion(float3 V, float3 normalWS, float3 vertexNormal, float horizonFade)
real GetHorizonOcclusion(real3 V, real3 normalWS, real3 vertexNormal, real horizonFade)
float3 R = reflect(-V, normalWS);
float specularOcclusion = saturate(1.0 + horizonFade * dot(R, vertexNormal));
real3 R = reflect(-V, normalWS);
real specularOcclusion = saturate(1.0 + horizonFade * dot(R, vertexNormal));
// smooth it
return specularOcclusion * specularOcclusion;
}

float GetSpecularOcclusionFromAmbientOcclusion(float NdotV, float ambientOcclusion, float roughness)
real GetSpecularOcclusionFromAmbientOcclusion(real NdotV, real ambientOcclusion, real roughness)
{
return saturate(PositivePow(NdotV + ambientOcclusion, exp2(-16.0 * roughness - 1.0)) - 1.0 + ambientOcclusion);
}

float3 GTAOMultiBounce(float visibility, float3 albedo)
real3 GTAOMultiBounce(real visibility, real3 albedo)
float3 a = 2.0404 * albedo - 0.3324;
float3 b = -4.7951 * albedo + 0.6417;
float3 c = 2.7552 * albedo + 0.6903;
real3 a = 2.0404 * albedo - 0.3324;
real3 b = -4.7951 * albedo + 0.6417;
real3 c = 2.7552 * albedo + 0.6903;
float x = visibility;
real x = visibility;
float SphericalCapIntersectionSolidArea(float cosC1, float cosC2, float cosB)
real SphericalCapIntersectionSolidArea(real cosC1, real cosC2, real cosB)
float r1 = FastACos(cosC1);
float r2 = FastACos(cosC2);
float rd = FastACos(cosB);
float area = 0.0;
real r1 = FastACos(cosC1);
real r2 = FastACos(cosC2);
real rd = FastACos(cosB);
real area = 0.0;
if (rd <= max(r1, r2) - min(r1, r2))
{

}
else
{
float diff = abs(r1 - r2);
float den = r1 + r2 - diff;
float x = 1.0 - saturate((rd - diff) / den);
real diff = abs(r1 - r2);
real den = r1 + r2 - diff;
real x = 1.0 - saturate((rd - diff) / den);
area = smoothstep(0.0, 1.0, x);
area *= TWO_PI - TWO_PI * max(cosC1, cosC2);
}

// Ref: Steve McAuley - Energy-Conserving Wrapped Diffuse
float ComputeWrappedDiffuseLighting(float NdotL, float w)
real ComputeWrappedDiffuseLighting(real NdotL, real w)
{
return saturate((NdotL + w) / ((1 + w) * (1 + w)));
}

// Inputs: normalized normal and view vectors.
// Outputs: front-facing normal, and the new non-negative value of the cosine of the view angle.
// Important: call Orthonormalize() on the tangent and recompute the bitangent afterwards.
float3 GetViewReflectedNormal(float3 N, float3 V, out float NdotV)
real3 GetViewReflectedNormal(real3 N, real3 V, out real NdotV)
{
// Fragments of front-facing geometry can have back-facing normals due to interpolation,
// normal mapping and decals. This can cause visible artifacts from both direct (negative or

// Generates an orthonormal right-handed basis from a unit vector.
// Ref: http://marc-b-reynolds.github.io/quaternions/2016/07/06/Orthonormal.html
float3x3 GetLocalFrame(float3 localZ)
real3x3 GetLocalFrame(real3 localZ)
float x = localZ.x;
float y = localZ.y;
float z = localZ.z;
float sz = FastSign(z);
float a = 1 / (sz + z);
float ya = y * a;
float b = x * ya;
float c = x * sz;
real x = localZ.x;
real y = localZ.y;
real z = localZ.z;
real sz = FastSign(z);
real a = 1 / (sz + z);
real ya = y * a;
real b = x * ya;
real c = x * sz;
float3 localX = float3(c * x * a - 1, sz * b, c);
float3 localY = float3(b, y * ya - sz, y);
real3 localX = real3(c * x * a - 1, sz * b, c);
real3 localY = real3(b, y * ya - sz, y);
return float3x3(localX, localY, localZ);
return real3x3(localX, localY, localZ);
float3x3 GetLocalFrame(float3 localZ, float3 localX)
real3x3 GetLocalFrame(real3 localZ, real3 localX)
float3 localY = cross(localZ, localX);
real3 localY = cross(localZ, localX);
return float3x3(localX, localY, localZ);
return real3x3(localX, localY, localZ);
float IORToFresnel0(float ior)
real IORToFresnel0(real ior)
{
return Sq((ior - 1.0) / (ior + 1.0));
}

50
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/CommonMaterial.hlsl


// Helper functions for roughness
//-----------------------------------------------------------------------------
float PerceptualRoughnessToRoughness(float perceptualRoughness)
real PerceptualRoughnessToRoughness(real perceptualRoughness)
float RoughnessToPerceptualRoughness(float roughness)
real RoughnessToPerceptualRoughness(real roughness)
float PerceptualSmoothnessToRoughness(float perceptualSmoothness)
real PerceptualSmoothnessToRoughness(real perceptualSmoothness)
float PerceptualSmoothnessToPerceptualRoughness(float perceptualSmoothness)
real PerceptualSmoothnessToPerceptualRoughness(real perceptualSmoothness)
{
return (1.0 - perceptualSmoothness);
}

// Note: making the constant too small results in aliasing.
float ClampRoughnessForAnalyticalLights(float roughness)
real ClampRoughnessForAnalyticalLights(real roughness)
{
return max(roughness, 1.0/1024.0);
}

// If IBL needs the linear roughness value for some reason, it can be computed as follows:
// float roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
void ConvertAnisotropyToRoughness(float perceptualRoughness, float anisotropy, out float roughnessT, out float roughnessB)
// real roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
void ConvertAnisotropyToRoughness(real perceptualRoughness, real anisotropy, out real roughnessT, out real roughnessB)
float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
real roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
// Use the parametrization of Sony Imageworks.
// Ref: Revisiting Physically Based Shading at Imageworks, p. 15.

// ref https://www.gamedev.net/topic/678043-how-to-blend-world-space-normals/#entry5287707
// assume compositing in world space
// Note: Using vtxNormal = float3(0, 0, 1) give the BlendNormalRNM formulation.
// Note: Using vtxNormal = real3(0, 0, 1) give the BlendNormalRNM formulation.
float3 BlendNormalWorldspaceRNM(float3 n1, float3 n2, float3 vtxNormal)
real3 BlendNormalWorldspaceRNM(real3 n1, real3 n2, real3 vtxNormal)
float4 q = float4(cross(vtxNormal, n2), dot(vtxNormal, n2) + 1.0) / sqrt(2.0 * (dot(vtxNormal, n2) + 1));
real4 q = real4(cross(vtxNormal, n2), dot(vtxNormal, n2) + 1.0) / sqrt(2.0 * (dot(vtxNormal, n2) + 1));
// Rotate the normal
return n1 * (q.w * q.w - dot(q.xyz, q.xyz)) + 2 * q.xyz * dot(q.xyz, n1) + 2 * q.w * cross(q.xyz, n1);

// Reoriented Normal Mapping
// Blending when n1 and n2 are already 'unpacked' and normalised
// assume compositing in tangent space
float3 BlendNormalRNM(float3 n1, float3 n2)
real3 BlendNormalRNM(real3 n1, real3 n2)
float3 t = n1.xyz + float3(0.0, 0.0, 1.0);
float3 u = n2.xyz * float3(-1.0, -1.0, 1.0);
float3 r = (t / t.z) * dot(t, u) - u;
real3 t = n1.xyz + real3(0.0, 0.0, 1.0);
real3 u = n2.xyz * real3(-1.0, -1.0, 1.0);
real3 r = (t / t.z) * dot(t, u) - u;
float3 BlendNormal(float3 n1, float3 n2)
real3 BlendNormal(real3 n1, real3 n2)
return normalize(float3(n1.xy * n2.z + n2.xy * n1.z, n1.z * n2.z));
return normalize(real3(n1.xy * n2.z + n2.xy * n1.z, n1.z * n2.z));
float3 ComputeTriplanarWeights(float3 normal)
real3 ComputeTriplanarWeights(real3 normal)
float3 blendWeights = abs(normal);
real3 blendWeights = abs(normal);
blendWeights = max(blendWeights, float3(0.0, 0.0, 0.0));
blendWeights = max(blendWeights, real3(0.0, 0.0, 0.0));
blendWeights /= dot(blendWeights, 1.0);
return blendWeights;

uvZY = float2(position.z, position.y);
}
float LerpWhiteTo(float b, float t)
real LerpWhiteTo(real b, real t)
float oneMinusT = 1.0 - t;
real oneMinusT = 1.0 - t;
float3 LerpWhiteTo(float3 b, float t)
real3 LerpWhiteTo(real3 b, real t)
float oneMinusT = 1.0 - t;
return float3(oneMinusT, oneMinusT, oneMinusT) + b * t;
real oneMinusT = 1.0 - t;
return real3(oneMinusT, oneMinusT, oneMinusT) + b * t;
}

6
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/CommonShadow.hlsl


// Ref: https://mynameismjp.wordpress.com/2015/02/18/shadow-sample-update/
// Calculates the offset to use for sampling the shadow map, based on the surface normal
float3 GetShadowPosOffset(float NdotL, float3 normalWS, float2 invShadowMapSize)
real3 GetShadowPosOffset(real NdotL, real3 normalWS, real2 invShadowMapSize)
float texelSize = 2.0 * invShadowMapSize.x;
float offsetScaleNormalize = saturate(1.0 - NdotL);
real texelSize = 2.0 * invShadowMapSize.x;
real offsetScaleNormalize = saturate(1.0 - NdotL);
// return texelSize * OffsetScale * offsetScaleNormalize * normalWS;
return texelSize * offsetScaleNormalize * normalWS;
}

24
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Debug.hlsl


// Given an enum (represented by an int here), return a color.
// Use for DebugView of enum
float3 GetIndexColor(int index)
real3 GetIndexColor(int index)
float3 outColor = float3(1.0, 0.0, 0.0);
real3 outColor = real3(1.0, 0.0, 0.0);
outColor = float3(1.0, 0.5, 0.5);
outColor = real3(1.0, 0.5, 0.5);
outColor = float3(0.5, 1.0, 0.5);
outColor = real3(0.5, 1.0, 0.5);
outColor = float3(0.5, 0.5, 1.0);
outColor = real3(0.5, 0.5, 1.0);
outColor = float3(1.0, 1.0, 0.5);
outColor = real3(1.0, 1.0, 0.5);
outColor = float3(1.0, 0.5, 1.0);
outColor = real3(1.0, 0.5, 1.0);
outColor = float3(0.5, 1.0, 1.0);
outColor = real3(0.5, 1.0, 1.0);
outColor = float3(0.25, 0.75, 1.0);
outColor = real3(0.25, 0.75, 1.0);
outColor = float3(1.0, 0.75, 0.25);
outColor = real3(1.0, 0.75, 0.25);
outColor = float3(0.75, 1.0, 0.25);
outColor = real3(0.75, 1.0, 0.25);
outColor = float3(0.75, 0.25, 1.0);
outColor = real3(0.75, 0.25, 1.0);
return outColor;
}

80
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/EntityLighting.hlsl


// TODO: Check if PI is correctly handled!
// Ref: "Efficient Evaluation of Irradiance Environment Maps" from ShaderX 2
float3 SHEvalLinearL0L1(float3 N, float4 shAr, float4 shAg, float4 shAb)
real3 SHEvalLinearL0L1(real3 N, real4 shAr, real4 shAg, real4 shAb)
float4 vA = float4(N, 1.0);
real4 vA = real4(N, 1.0);
float3 x1;
real3 x1;
// Linear (L1) + constant (L0) polynomial terms
x1.r = dot(shAr, vA);
x1.g = dot(shAg, vA);

}
float3 SHEvalLinearL2(float3 N, float4 shBr, float4 shBg, float4 shBb, float4 shC)
real3 SHEvalLinearL2(real3 N, real4 shBr, real4 shBg, real4 shBb, real4 shC)
float3 x2;
real3 x2;
float4 vB = N.xyzz * N.yzzx;
real4 vB = N.xyzz * N.yzzx;
float vC = N.x * N.x - N.y * N.y;
float3 x3 = shC.rgb * vC;
real vC = N.x * N.x - N.y * N.y;
real3 x3 = shC.rgb * vC;
float3 SampleSH9(float4 SHCoefficients[7], float3 N)
real3 SampleSH9(real4 SHCoefficients[7], real3 N)
float4 shAr = SHCoefficients[0];
float4 shAg = SHCoefficients[1];
float4 shAb = SHCoefficients[2];
float4 shBr = SHCoefficients[3];
float4 shBg = SHCoefficients[4];
float4 shBb = SHCoefficients[5];
float4 shCr = SHCoefficients[6];
real4 shAr = SHCoefficients[0];
real4 shAg = SHCoefficients[1];
real4 shAb = SHCoefficients[2];
real4 shBr = SHCoefficients[3];
real4 shBg = SHCoefficients[4];
real4 shBb = SHCoefficients[5];
real4 shCr = SHCoefficients[6];
float3 res = SHEvalLinearL0L1(N, shAr, shAg, shAb);
real3 res = SHEvalLinearL0L1(N, shAr, shAg, shAb);
// Quadratic polynomials
res += SHEvalLinearL2(N, shBr, shBg, shBb, shCr);

float3 SampleProbeVolumeSH4(TEXTURE3D_ARGS(SHVolumeTexture, SHVolumeSampler), float3 positionWS, float3 normalWS, float4x4 WorldToTexture,
float transformToLocal, float texelSizeX, float3 probeVolumeMin, float3 probeVolumeSizeInv)
{
float3 position = (transformToLocal == 1.0f) ? mul(WorldToTexture, float4(positionWS, 1.0)).xyz : positionWS;
float3 position = (transformToLocal == 1.0) ? mul(WorldToTexture, float4(positionWS, 1.0)).xyz : positionWS;
float3 texCoord = (position - probeVolumeMin) * probeVolumeSizeInv.xyz;
// Each component is store in the same texture 3D. Each use one quater on the x axis
// Here we get R component then increase by step size (0.25) to get other component. This assume 4 component

float4 SampleProbeOcclusion(TEXTURE3D_ARGS(SHVolumeTexture, SHVolumeSampler), float3 positionWS, float4x4 WorldToTexture,
float transformToLocal, float texelSizeX, float3 probeVolumeMin, float3 probeVolumeSizeInv)
{
float3 position = (transformToLocal == 1.0f) ? mul(WorldToTexture, float4(positionWS, 1.0)).xyz : positionWS;
float3 position = (transformToLocal == 1.0) ? mul(WorldToTexture, float4(positionWS, 1.0)).xyz : positionWS;
float3 texCoord = (position - probeVolumeMin) * probeVolumeSizeInv.xyz;
// Sample fourth texture in the atlas

// (But these kind of platform should use regular render loop and not news shaders).
// RGBM lightmaps are currently always gamma encoded, so we use a constant of range^2.2 = 5^2.2
#define LIGHTMAP_RGBM_RANGE 34.493242f
#define LIGHTMAP_RGBM_RANGE 34.493242
// DLRD lightmaps are currently always gamma encoded, so we use a constant of 2.0^2.2 = 4.59
#define LIGHTMAP_DLDR_RANGE 4.59f
// DLDR lightmaps are currently always gamma encoded, so we use a constant of 2.0^2.2 = 4.59
#define LIGHTMAP_DLDR_RANGE 4.59
// TODO: This is the max value allowed for emissive (bad name - but keep for now to retrieve it) (It is 8^2.2 (gamma) and 8 is the limit of punctual light slider...), comme from UnityCg.cginc. Fix it!
// Ask Jesper if this can be change for HDRenderPipeline

// Same goes for emissive packed as an input for Enlighten with another hard coded multiplier.
// TODO: This function is used with the LightTransport pass to encode lightmap or emissive
float4 PackEmissiveRGBM(float3 rgb)
real4 PackEmissiveRGBM(real3 rgb)
float kOneOverRGBMMaxRange = 1.0 / EMISSIVE_RGBM_SCALE;
const float kMinMultiplier = 2.0 * 1e-2;
real kOneOverRGBMMaxRange = 1.0 / EMISSIVE_RGBM_SCALE;
const real kMinMultiplier = 2.0 * 1e-2;
float4 rgbm = float4(rgb * kOneOverRGBMMaxRange, 1.0);
real4 rgbm = real4(rgb * kOneOverRGBMMaxRange, 1.0);
rgbm.a = max(max(rgbm.r, rgbm.g), max(rgbm.b, kMinMultiplier));
rgbm.a = ceil(rgbm.a * 255.0) / 255.0;

return rgbm;
}
float3 UnpackLightmapRGBM(float4 rgbmInput)
real3 UnpackLightmapRGBM(real4 rgbmInput)
return rgbmInput.rgb * pow(rgbmInput.a, 2.2f) * LIGHTMAP_RGBM_RANGE;
return rgbmInput.rgb * pow(rgbmInput.a, 2.2) * LIGHTMAP_RGBM_RANGE;
float3 UnpackLightmapDoubleLDR(float4 encodedColor)
real3 UnpackLightmapDoubleLDR(real4 encodedColor)
float3 DecodeLightmap(float4 encodedIlluminance)
real3 DecodeLightmap(real4 encodedIlluminance)
{
#if defined(UNITY_LIGHTMAP_RGBM_ENCODING)
return UnpackLightmapRGBM(encodedIlluminance);

}
float3 DecodeHDREnvironment(float4 encodedIrradiance, float4 decodeInstructions)
real3 DecodeHDREnvironment(real4 encodedIrradiance, real4 decodeInstructions)
float alpha = max(decodeInstructions.w * (encodedIrradiance.a - 1.0) + 1.0, 0.0);
real alpha = max(decodeInstructions.w * (encodedIrradiance.a - 1.0) + 1.0, 0.0);
float3 SampleSingleLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), float2 uv, float4 transform, bool encodedLightmap)
real3 SampleSingleLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), float2 uv, float4 transform, bool encodedLightmap)
float3 illuminance = float3(0.0, 0.0, 0.0);
real3 illuminance = real3(0.0, 0.0, 0.0);
float4 encodedIlluminance = SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgba;
real4 encodedIlluminance = SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgba;
illuminance = DecodeLightmap(encodedIlluminance);
}
else

return illuminance;
}
float3 SampleDirectionalLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), TEXTURE2D_ARGS(lightmapDirTex, lightmapDirSampler), float2 uv, float4 transform, float3 normalWS, bool encodedLightmap)
real3 SampleDirectionalLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), TEXTURE2D_ARGS(lightmapDirTex, lightmapDirSampler), float2 uv, float4 transform, float3 normalWS, bool encodedLightmap)
{
// In directional mode Enlighten bakes dominant light direction
// in a way, that using it for half Lambert and then dividing by a "rebalancing coefficient"

// transform is scale and bias
uv = uv * transform.xy + transform.zw;
float4 direction = SAMPLE_TEXTURE2D(lightmapDirTex, lightmapDirSampler, uv);
real4 direction = SAMPLE_TEXTURE2D(lightmapDirTex, lightmapDirSampler, uv);
float3 illuminance = float3(0.0, 0.0, 0.0);
real3 illuminance = real3(0.0, 0.0, 0.0);
half4 encodedIlluminance = SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgba;
real4 encodedIlluminance = SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgba;
illuminance = DecodeLightmap(encodedIlluminance);
}
else

float halfLambert = dot(normalWS, direction.xyz - 0.5) + 0.5;
real halfLambert = dot(normalWS, direction.xyz - 0.5) + 0.5;
return illuminance * halfLambert / max(1e-4, direction.w);
}

319
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/ImageBasedLighting.hlsl


#include "CommonLighting.hlsl"
#include "CommonMaterial.hlsl"
#include "BSDF.hlsl"
#include "Random.hlsl"
#include "Sampling/Sampling.hlsl"
#ifndef UNITY_SPECCUBE_LOD_STEPS

// approximating the cone of the specular lobe, and then computing the MIP map level
// which (approximately) covers the footprint of the lobe with a single texel.
// Improves the perceptual roughness distribution.
float PerceptualRoughnessToMipmapLevel(float perceptualRoughness, uint mipMapCount)
real PerceptualRoughnessToMipmapLevel(real perceptualRoughness, uint mipMapCount)
{
perceptualRoughness = perceptualRoughness * (1.7 - 0.7 * perceptualRoughness);

float PerceptualRoughnessToMipmapLevel(float perceptualRoughness)
real PerceptualRoughnessToMipmapLevel(real perceptualRoughness)
{
return PerceptualRoughnessToMipmapLevel(perceptualRoughness, UNITY_SPECCUBE_LOD_STEPS);
}

// which (approximately) covers the footprint of the lobe with a single texel.
// Improves the perceptual roughness distribution and adds reflection (contact) hardening.
// TODO: optimize!
float PerceptualRoughnessToMipmapLevel(float perceptualRoughness, float NdotR)
real PerceptualRoughnessToMipmapLevel(real perceptualRoughness, real NdotR)
float m = PerceptualRoughnessToRoughness(perceptualRoughness);
real m = PerceptualRoughnessToRoughness(perceptualRoughness);
float n = (2.0 / max(FLT_EPS, m * m)) - 2.0;
real n = (2.0 / max(FLT_EPS, m * m)) - 2.0;
// Remap from n_dot_h formulation to n_dot_r. See section "Pre-convolved Cube Maps vs Path Tracers" --> https://s3.amazonaws.com/docs.knaldtech.com/knald/1.0.0/lys_power_drops.html
n /= (4.0 * max(NdotR, FLT_EPS));

}
// The inverse of the *approximated* version of perceptualRoughnessToMipmapLevel().
float MipmapLevelToPerceptualRoughness(float mipmapLevel)
real MipmapLevelToPerceptualRoughness(real mipmapLevel)
float perceptualRoughness = saturate(mipmapLevel / UNITY_SPECCUBE_LOD_STEPS);
real perceptualRoughness = saturate(mipmapLevel / UNITY_SPECCUBE_LOD_STEPS);
return saturate(1.7 / 1.4 - sqrt(2.89 / 1.96 - (2.8 / 1.96) * perceptualRoughness));
}

// Ref: Donald Revie - Implementing Fur Using Deferred Shading (GPU Pro 2)
// The grain direction (e.g. hair or brush direction) is assumed to be orthogonal to the normal.
// The returned normal is NOT normalized.
float3 ComputeGrainNormal(float3 grainDir, float3 V)
real3 ComputeGrainNormal(real3 grainDir, real3 V)
float3 B = cross(grainDir, V);
real3 B = cross(grainDir, V);
return cross(B, grainDir);
}

float3 GetAnisotropicModifiedNormal(float3 grainDir, float3 N, float3 V, float anisotropy)
real3 GetAnisotropicModifiedNormal(real3 grainDir, real3 N, real3 V, real anisotropy)
float3 grainNormal = ComputeGrainNormal(grainDir, V);
real3 grainNormal = ComputeGrainNormal(grainDir, V);
float3 GetSpecularDominantDir(float3 N, float3 R, float roughness, float NdotV)
real3 GetSpecularDominantDir(real3 N, real3 R, real roughness, real NdotV)
float a = 1.0 - roughness;
float s = sqrt(a);
real a = 1.0 - roughness;
real s = sqrt(a);
float lerpFactor = (s + roughness) * a;
real lerpFactor = (s + roughness) * a;
float lerpFactor = (s + roughness) * saturate(a * a + lerp(0.0, a, NdotV * NdotV));
real lerpFactor = (s + roughness) * saturate(a * a + lerp(0.0, a, NdotV * NdotV));
#endif
// The result is not normalized as we fetch in a cubemap

// To simulate the streching of highlight at grazing angle for IBL we shrink the roughness
// which allow to fake an anisotropic specular lobe.
// Ref: http://www.frostbite.com/2015/08/stochastic-screen-space-reflections/ - slide 84
float AnisotropicStrechAtGrazingAngle(float roughness, float perceptualRoughness, float NdotV)
real AnisotropicStrechAtGrazingAngle(real roughness, real perceptualRoughness, real NdotV)
{
return roughness * lerp(saturate(NdotV * 2.0), 1.0, perceptualRoughness);
}

// ----------------------------------------------------------------------------
void SampleGGXDir(float2 u,
float3 V,
float3x3 localToWorld,
float roughness,
out float3 L,
out float NdotL,
out float NdotH,
out float VdotH,
void SampleGGXDir(real2 u,
real3 V,
real3x3 localToWorld,
real roughness,
out real3 L,
out real NdotL,
out real NdotH,
out real VdotH,
float cosTheta = sqrt((1.0 - u.x) / (1.0 + (roughness * roughness - 1.0) * u.x));
float phi = TWO_PI * u.y;
real cosTheta = sqrt((1.0 - u.x) / (1.0 + (roughness * roughness - 1.0) * u.x));
real phi = TWO_PI * u.y;
float3 localH = SphericalToCartesian(phi, cosTheta);
real3 localH = SphericalToCartesian(phi, cosTheta);
float3 localV;
real3 localV;
localV = float3(0.0, 0.0, 1.0);
localV = real3(0.0, 0.0, 1.0);
VdotH = NdotH;
}
else

}
// Compute { localL = reflect(-localV, localH) }
float3 localL = -localV + 2.0 * VdotH * localH;
real3 localL = -localV + 2.0 * VdotH * localH;
NdotL = localL.z;
L = mul(localL, localToWorld);

void SampleVisibleAnisoGGXDir(float2 u, float3 V, float3x3 localToWorld,
float roughnessT, float roughnessB,
out float3 L,
out float NdotL,
out float NdotH,
out float VdotH,
bool VeqN = false)
void SampleVisibleAnisoGGXDir(real2 u, real3 V, real3x3 localToWorld,
real roughnessT, real roughnessB,
out real3 L,
out real NdotL,
out real NdotH,
out real VdotH,
bool VeqN = false)
float3 localV = mul(V, transpose(localToWorld));
real3 localV = mul(V, transpose(localToWorld));
float3x3 viewToLocal;
real3x3 viewToLocal;
if (VeqN)
{
viewToLocal = k_identity3x3;

viewToLocal[2] = normalize(float3(roughnessT * localV.x, roughnessB * localV.y, localV.z));
viewToLocal[0] = (viewToLocal[2].z < 0.9999) ? normalize(cross(viewToLocal[2], float3(0, 0, 1))) : float3(1, 0, 0);
viewToLocal[2] = normalize(real3(roughnessT * localV.x, roughnessB * localV.y, localV.z));
viewToLocal[0] = (viewToLocal[2].z < 0.9999) ? normalize(cross(viewToLocal[2], real3(0, 0, 1))) : real3(1, 0, 0);
float r = sqrt(u.x);
float b = viewToLocal[2].z + 1;
float a = rcp(b);
float c = (u.y < a) ? u.y * b : 1 + (u.y * b - 1) / viewToLocal[2].z;
float phi = PI * c;
float p1 = r * cos(phi);
float p2 = r * sin(phi) * ((u.y < a) ? 1 : viewToLocal[2].z);
real r = sqrt(u.x);
real b = viewToLocal[2].z + 1;
real a = rcp(b);
real c = (u.y < a) ? u.y * b : 1 + (u.y * b - 1) / viewToLocal[2].z;
real phi = PI * c;
real p1 = r * cos(phi);
real p2 = r * sin(phi) * ((u.y < a) ? 1 : viewToLocal[2].z);
float3 viewH = normalize(float3(roughnessT * p1, roughnessB * p2, sqrt(1 - p1 * p1 - p2 * p2)));
real3 viewH = normalize(real3(roughnessT * p1, roughnessB * p2, sqrt(1 - p1 * p1 - p2 * p2)));
float3 localH = mul(viewH, viewToLocal);
real3 localH = mul(viewH, viewToLocal);
float3 localL = -localV + 2 * VdotH * localH;
real3 localL = -localV + 2 * VdotH * localH;
NdotL = localL.z;
L = mul(localL, localToWorld);

void SampleAnisoGGXDir(float2 u,
float3 V,
float3 N,
float3 tangentX,
float3 tangentY,
float roughnessT,
float roughnessB,
out float3 H,
out float3 L)
void SampleAnisoGGXDir(real2 u,
real3 V,
real3 N,
real3 tangentX,
real3 tangentY,
real roughnessT,
real roughnessB,
out real3 H,
out real3 L)
{
// AnisoGGX NDF sampling
H = sqrt(u.x / (1.0 - u.x)) * (roughnessT * cos(TWO_PI * u.y) * tangentX + roughnessB * sin(TWO_PI * u.y) * tangentY) + N;

}
// weightOverPdf return the weight (without the diffuseAlbedo term) over pdf. diffuseAlbedo term must be apply by the caller.
void ImportanceSampleLambert(float2 u,
float3x3 localToWorld,
out float3 L,
out float NdotL,
out float weightOverPdf)
void ImportanceSampleLambert(real2 u,
real3x3 localToWorld,
out real3 L,
out real NdotL,
out real weightOverPdf)
float3 localL = SampleHemisphereCosine(u.x, u.y);
real3 localL = SampleHemisphereCosine(u.x, u.y);
NdotL = localL.z;

}
// weightOverPdf return the weight (without the Fresnel term) over pdf. Fresnel term must be apply by the caller.
void ImportanceSampleGGX(float2 u,
float3 V,
float3x3 localToWorld,
float roughness,
float NdotV,
out float3 L,
out float VdotH,
out float NdotL,
out float weightOverPdf)
void ImportanceSampleGGX(real2 u,
real3 V,
real3x3 localToWorld,
real roughness,
real NdotV,
out real3 L,
out real VdotH,
out real NdotL,
out real weightOverPdf)
float NdotH;
real NdotH;
SampleGGXDir(u, V, localToWorld, roughness, L, NdotL, NdotH, VdotH);
// Importance sampling weight for each sample

// Remind (L.H) == (V.H)
// F is apply outside the function
float Vis = V_SmithJointGGX(NdotL, NdotV, roughness);
real Vis = V_SmithJointGGX(NdotL, NdotV, roughness);
void ImportanceSampleAnisoGGX(float2 u,
float3 V,
float3x3 localToWorld,
float roughnessT,
float roughnessB,
float NdotV,
out float3 L,
out float VdotH,
out float NdotL,
out float weightOverPdf)
void ImportanceSampleAnisoGGX(real2 u,
real3 V,
real3x3 localToWorld,
real roughnessT,
real roughnessB,
real NdotV,
out real3 L,
out real VdotH,
out real NdotL,
out real weightOverPdf)
float3 tangentX = localToWorld[0];
float3 tangentY = localToWorld[1];
float3 N = localToWorld[2];
real3 tangentX = localToWorld[0];
real3 tangentY = localToWorld[1];
real3 N = localToWorld[2];
float3 H;
real3 H;
float NdotH = saturate(dot(N, H));
real NdotH = saturate(dot(N, H));
// Note: since L and V are symmetric around H, LdotH == VdotH
VdotH = saturate(dot(V, H));
NdotL = saturate(dot(N, L));

// F is apply outside the function
// For anisotropy we must not saturate these values
float TdotV = dot(tangentX, V);
float BdotV = dot(tangentY, V);
float TdotL = dot(tangentX, L);
float BdotL = dot(tangentY, L);
real TdotV = dot(tangentX, V);
real BdotV = dot(tangentY, V);
real TdotL = dot(tangentX, L);
real BdotL = dot(tangentY, L);
float Vis = V_SmithJointGGXAniso(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB);
real Vis = V_SmithJointGGXAniso(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB);
weightOverPdf = 4.0 * Vis * NdotL * VdotH / NdotH;
}

// Ref: Listing 18 in "Moving Frostbite to PBR" + https://knarkowicz.wordpress.com/2014/12/27/analytical-dfg-term-for-ibl/
float4 IntegrateGGXAndDisneyFGD(float3 V, float3 N, float roughness, uint sampleCount = 8192)
real4 IntegrateGGXAndDisneyFGD(real3 V, real3 N, real roughness, uint sampleCount = 8192)
float NdotV = saturate(dot(N, V));
float4 acc = float4(0.0, 0.0, 0.0, 0.0);
real NdotV = saturate(dot(N, V));
real4 acc = real4(0.0, 0.0, 0.0, 0.0);
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
real2 randNum = InitRandom(V.xy * 0.5 + 0.5);
float3x3 localToWorld = GetLocalFrame(N);
real3x3 localToWorld = GetLocalFrame(N);
float2 u = frac(randNum + Hammersley2d(i, sampleCount));
real2 u = frac(randNum + Hammersley2d(i, sampleCount));
float VdotH;
float NdotL;
float weightOverPdf;
real VdotH;
real NdotL;
real weightOverPdf;
float3 L; // Unused
real3 L; // Unused
ImportanceSampleGGX(u, V, localToWorld, roughness, NdotV,
L, VdotH, NdotL, weightOverPdf);

if (NdotL > 0.0)
{
float LdotV = dot(L, V);
float disneyDiffuse = DisneyDiffuseNoPI(NdotV, NdotL, LdotV, RoughnessToPerceptualRoughness(roughness));
real LdotV = dot(L, V);
real disneyDiffuse = DisneyDiffuseNoPI(NdotV, NdotL, LdotV, RoughnessToPerceptualRoughness(roughness));
acc.z += disneyDiffuse * weightOverPdf;
}

}
// Ref: Listing 19 in "Moving Frostbite to PBR"
float4 IntegrateLD(TEXTURECUBE_ARGS(tex, sampl),
real4 IntegrateLD(TEXTURECUBE_ARGS(tex, sampl),
float3 V,
float3 N,
float roughness,
float index, // Current MIP level minus one
float invOmegaP,
real3 V,
real3 N,
real roughness,
real index, // Current MIP level minus one
real invOmegaP,
float3x3 localToWorld = GetLocalFrame(N);
real3x3 localToWorld = GetLocalFrame(N);
float NdotV = 1; // N == V
float partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
real NdotV = 1; // N == V
real partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
float3 lightInt = float3(0.0, 0.0, 0.0);
float cbsdfInt = 0.0;
real3 lightInt = real3(0.0, 0.0, 0.0);
real cbsdfInt = 0.0;
float3 L;
float NdotL, NdotH, LdotH;
real3 L;
real NdotL, NdotH, LdotH;
if (usePrecomputedSamples)
{

// or Structured buffer, or perhaps even declare all the constants in an
// HLSL header to allow the compiler to inline everything.
float3 localL = LOAD_TEXTURE2D(ggxIblSamples, uint2(i, index)).xyz;
real3 localL = LOAD_TEXTURE2D(ggxIblSamples, uint2(i, index)).xyz;
L = mul(localL, localToWorld);
NdotL = localL.z;

{
float2 u = Fibonacci2d(i, sampleCount);
real2 u = Fibonacci2d(i, sampleCount);
// Note: if (N == V), all of the microsurface normals are visible.
SampleGGXDir(u, V, localToWorld, roughness, L, NdotL, NdotH, LdotH, true);

float mipLevel;
real mipLevel;
if (!prefilter) // BRDF importance sampling
{

// - OmegaS: Solid angle associated with the sample
// - OmegaP: Solid angle associated with the texel of the cubemap
float omegaS;
real omegaS;
if (usePrecomputedSamples)
{

{
// float PDF = D * NdotH * Jacobian, where Jacobian = 1 / (4 * LdotH).
// real PDF = D * NdotH * Jacobian, where Jacobian = 1 / (4 * LdotH).
float pdf = 0.25 * D_GGX(NdotH, roughness);
real pdf = 0.25 * D_GGX(NdotH, roughness);
// float omegaP = FOUR_PI / (6.0 * cubemapWidth * cubemapWidth);
const float mipBias = roughness;
// real omegaP = FOUR_PI / (6.0 * cubemapWidth * cubemapWidth);
const real mipBias = roughness;
float3 val = SAMPLE_TEXTURECUBE_LOD(tex, sampl, L, mipLevel).rgb;
real3 val = SAMPLE_TEXTURECUBE_LOD(tex, sampl, L, mipLevel).rgb;
// The goal of this function is to use Monte-Carlo integration to find
// X = Integral{Radiance(L) * CBSDF(L, N, V) dL} / Integral{CBSDF(L, N, V) dL}.

#ifndef USE_KARIS_APPROXIMATION
// The choice of the Fresnel factor does not appear to affect the result.
float F = 1; // F_Schlick(F0, LdotH);
float V = V_SmithJointGGX(NdotL, NdotV, roughness, partLambdaV);
float G = V * NdotL * NdotV; // 4 cancels out
real F = 1; // F_Schlick(F0, LdotH);
real V = V_SmithJointGGX(NdotL, NdotV, roughness, partLambdaV);
real G = V * NdotL * NdotV; // 4 cancels out
lightInt += F * G * val;
cbsdfInt += F * G;

#endif
}
return float4(lightInt / cbsdfInt, 1.0);
return real4(lightInt / cbsdfInt, 1.0);
uint BinarySearchRow(uint j, float needle, TEXTURE2D(haystack), uint n)
uint BinarySearchRow(uint j, real needle, TEXTURE2D(haystack), uint n)
float v = LOAD_TEXTURE2D(haystack, uint2(i, j)).r;
real v = LOAD_TEXTURE2D(haystack, uint2(i, j)).r;
if (needle < v)
{

return i;
}
float4 IntegrateLD_MIS(TEXTURECUBE_ARGS(envMap, sampler_envMap),
real4 IntegrateLD_MIS(TEXTURECUBE_ARGS(envMap, sampler_envMap),
float3 V,
float3 N,
float roughness,
float invOmegaP,
real3 V,
real3 N,
real roughness,
real invOmegaP,
float3x3 localToWorld = GetLocalFrame(N);
real3x3 localToWorld = GetLocalFrame(N);
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
real2 randNum = InitRandom(V.xy * 0.5 + 0.5);
float3 lightInt = float3(0.0, 0.0, 0.0);
float cbsdfInt = 0.0;
real3 lightInt = real3(0.0, 0.0, 0.0);
real cbsdfInt = 0.0;
/*
// Dedicate 50% of samples to light sampling at 1.0 roughness.

*/
// The value of the integral of intensity values of the environment map (as a 2D step function).
float envMapInt2dStep = LOAD_TEXTURE2D(marginalRowDensities, uint2(height, 0)).r;
real envMapInt2dStep = LOAD_TEXTURE2D(marginalRowDensities, uint2(height, 0)).r;
float envMapIntSphere = envMapInt2dStep * INV_FOUR_PI;
real envMapIntSphere = envMapInt2dStep * INV_FOUR_PI;
float2 s = frac(randNum + Hammersley2d(i, sampleCount));
real2 s = frac(randNum + Hammersley2d(i, sampleCount));
// Sample a row from the marginal distribution.
uint y = BinarySearchRow(0, s.x, marginalRowDensities, height - 1);

// Compute the coordinates of the sample.
// Note: we take the sample in between two texels, and also apply the half-texel offset.
// We could compute fractional coordinates at the cost of 4 extra texel samples.
float u = saturate((float)x / width + 1.0 / width);
float v = saturate((float)y / height + 1.0 / height);
float3 L = ConvertEquiarealToCubemap(u, v);
real u = saturate((real)x / width + 1.0 / width);
real v = saturate((real)y / height + 1.0 / height);
real3 L = ConvertEquiarealToCubemap(u, v);
float NdotL = saturate(dot(N, L));
real NdotL = saturate(dot(N, L));
float3 val = SAMPLE_TEXTURECUBE_LOD(envMap, sampler_envMap, L, 0).rgb;
float pdf = (val.r + val.g + val.b) / envMapIntSphere;
real3 val = SAMPLE_TEXTURECUBE_LOD(envMap, sampler_envMap, L, 0).rgb;
real pdf = (val.r + val.g + val.b) / envMapIntSphere;
float NdotH = sqrt(NdotL * 0.5 + 0.5);
real NdotH = sqrt(NdotL * 0.5 + 0.5);
// *********************************************************************************
// Our goal is to use Monte-Carlo integration with importance sampling to evaluate

// Weight = D * NdotL / (4 * PDF).
// *********************************************************************************
float weight = D_GGX(NdotH, roughness) * NdotL / (4.0 * pdf);
real weight = D_GGX(NdotH, roughness) * NdotL / (4.0 * pdf);
lightInt += weight * val;
cbsdfInt += weight;

// Prevent NaNs arising from the division of 0 by 0.
cbsdfInt = max(cbsdfInt, FLT_EPS);
return float4(lightInt / cbsdfInt, 1.0);
return real4(lightInt / cbsdfInt, 1.0);
}
#endif // UNITY_IMAGE_BASED_LIGHTING_INCLUDED

72
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Macros.hlsl


#define HALF_PI 1.57079632679489661923
#define INV_HALF_PI 0.63661977236758134308
#define LOG2_E 1.44269504088896340736
#define INFINITY asfloat(0x7F800000)
#define MILLIMETERS_PER_METER 1000
#define METERS_PER_MILLIMETER rcp(MILLIMETERS_PER_METER)

#define FLT_EPS 5.960464478e-8 // 2^-24, machine epsilon: 1 + EPS = 1 (half of the ULP for 1)
#define FLT_MIN 1.175494351e-38 // Minimum representable positive floating-point number
#define FLT_MAX 3.402823466e+38 // Maximum representable floating-point number
#define HALF_MIN 6.103515625e-5 // 2^-14, the same value for 10, 11 and 16-bit: https://www.khronos.org/opengl/wiki/Small_Float_Formats
#define HALF_MAX 65504.0
#define UINT_MAX 0xFFFFFFFFu
#define FLT_INF asfloat(0x7F800000)
#define FLT_EPS 5.960464478e-8 // 2^-24, machine epsilon: 1 + EPS = 1 (half of the ULP for 1.0f)
#define FLT_MIN 1.175494351e-38 // Minimum representable positive floating-point number
#define FLT_MAX 3.402823466e+38 // Maximum representable floating-point number
#define HALF_MIN 6.103515625e-5 // 2^-14, the same value for 10, 11 and 16-bit: https://www.khronos.org/opengl/wiki/Small_Float_Formats
#define HALF_MAX 65504.0
#define UINT_MAX 0xFFFFFFFFu
float FunctionName(float Parameter1) { FunctionBody; } \
float2 FunctionName(float2 Parameter1) { FunctionBody; } \
float3 FunctionName(float3 Parameter1) { FunctionBody; } \
float4 FunctionName(float4 Parameter1) { FunctionBody; }
float FunctionName(float Parameter1) { FunctionBody; } \
float2 FunctionName(float2 Parameter1) { FunctionBody; } \
float3 FunctionName(float3 Parameter1) { FunctionBody; } \
float4 FunctionName(float4 Parameter1) { FunctionBody; }
#define TEMPLATE_1_HALF(FunctionName, Parameter1, FunctionBody) \
half FunctionName(half Parameter1) { FunctionBody; } \
half2 FunctionName(half2 Parameter1) { FunctionBody; } \
half3 FunctionName(half3 Parameter1) { FunctionBody; } \
half4 FunctionName(half4 Parameter1) { FunctionBody; }
#ifdef SHADER_API_GLES
#define TEMPLATE_1_INT(FunctionName, Parameter1, FunctionBody) \

#endif
#define TEMPLATE_2_FLT(FunctionName, Parameter1, Parameter2, FunctionBody) \
float FunctionName(float Parameter1, float Parameter2) { FunctionBody; } \
float2 FunctionName(float2 Parameter1, float2 Parameter2) { FunctionBody; } \
float3 FunctionName(float3 Parameter1, float3 Parameter2) { FunctionBody; } \
float4 FunctionName(float4 Parameter1, float4 Parameter2) { FunctionBody; }
float FunctionName(float Parameter1, float Parameter2) { FunctionBody; } \
float2 FunctionName(float2 Parameter1, float2 Parameter2) { FunctionBody; } \
float3 FunctionName(float3 Parameter1, float3 Parameter2) { FunctionBody; } \
float4 FunctionName(float4 Parameter1, float4 Parameter2) { FunctionBody; }
#define TEMPLATE_2_HALF(FunctionName, Parameter1, Parameter2, FunctionBody) \
half FunctionName(half Parameter1, half Parameter2) { FunctionBody; } \
half2 FunctionName(half2 Parameter1, half2 Parameter2) { FunctionBody; } \
half3 FunctionName(half3 Parameter1, half3 Parameter2) { FunctionBody; } \
half4 FunctionName(half4 Parameter1, half4 Parameter2) { FunctionBody; }
#ifdef SHADER_API_GLES

#endif
#define TEMPLATE_3_FLT(FunctionName, Parameter1, Parameter2, Parameter3, FunctionBody) \
float FunctionName(float Parameter1, float Parameter2, float Parameter3) { FunctionBody; } \
float2 FunctionName(float2 Parameter1, float2 Parameter2, float2 Parameter3) { FunctionBody; } \
float3 FunctionName(float3 Parameter1, float3 Parameter2, float3 Parameter3) { FunctionBody; } \
float4 FunctionName(float4 Parameter1, float4 Parameter2, float4 Parameter3) { FunctionBody; }
float FunctionName(float Parameter1, float Parameter2, float Parameter3) { FunctionBody; } \
float2 FunctionName(float2 Parameter1, float2 Parameter2, float2 Parameter3) { FunctionBody; } \
float3 FunctionName(float3 Parameter1, float3 Parameter2, float3 Parameter3) { FunctionBody; } \
float4 FunctionName(float4 Parameter1, float4 Parameter2, float4 Parameter3) { FunctionBody; }
#define TEMPLATE_3_HALF(FunctionName, Parameter1, Parameter2, Parameter3, FunctionBody) \
half FunctionName(half Parameter1, half Parameter2, half Parameter3) { FunctionBody; } \
half2 FunctionName(half2 Parameter1, half2 Parameter2, half2 Parameter3) { FunctionBody; } \
half3 FunctionName(half3 Parameter1, half3 Parameter2, half3 Parameter3) { FunctionBody; } \
half4 FunctionName(half4 Parameter1, half4 Parameter2, half4 Parameter3) { FunctionBody; }
#ifdef SHADER_API_GLES
#define TEMPLATE_3_INT(FunctionName, Parameter1, Parameter2, Parameter3, FunctionBody) \

#ifdef SHADER_API_GLES
#define TEMPLATE_SWAP(FunctionName) \
void FunctionName(inout float a, inout float b) { float t = a; a = b; b = t; } \
void FunctionName(inout float2 a, inout float2 b) { float2 t = a; a = b; b = t; } \
void FunctionName(inout float3 a, inout float3 b) { float3 t = a; a = b; b = t; } \
void FunctionName(inout float4 a, inout float4 b) { float4 t = a; a = b; b = t; } \
void FunctionName(inout real a, inout real b) { real t = a; a = b; b = t; } \
void FunctionName(inout real2 a, inout real2 b) { real2 t = a; a = b; b = t; } \
void FunctionName(inout real3 a, inout real3 b) { real3 t = a; a = b; b = t; } \
void FunctionName(inout real4 a, inout real4 b) { real4 t = a; a = b; b = t; } \
void FunctionName(inout int a, inout int b) { int t = a; a = b; b = t; } \
void FunctionName(inout int2 a, inout int2 b) { int2 t = a; a = b; b = t; } \
void FunctionName(inout int3 a, inout int3 b) { int3 t = a; a = b; b = t; } \

void FunctionName(inout bool4 a, inout bool4 b) { bool4 t = a; a = b; b = t; }
#else
#define TEMPLATE_SWAP(FunctionName) \
void FunctionName(inout float a, inout float b) { float t = a; a = b; b = t; } \
void FunctionName(inout float2 a, inout float2 b) { float2 t = a; a = b; b = t; } \
void FunctionName(inout float3 a, inout float3 b) { float3 t = a; a = b; b = t; } \
void FunctionName(inout float4 a, inout float4 b) { float4 t = a; a = b; b = t; } \
void FunctionName(inout real a, inout real b) { real t = a; a = b; b = t; } \
void FunctionName(inout real2 a, inout real2 b) { real2 t = a; a = b; b = t; } \
void FunctionName(inout real3 a, inout real3 b) { real3 t = a; a = b; b = t; } \
void FunctionName(inout real4 a, inout real4 b) { real4 t = a; a = b; b = t; } \
void FunctionName(inout int a, inout int b) { int t = a; a = b; b = t; } \
void FunctionName(inout int2 a, inout int2 b) { int2 t = a; a = b; b = t; } \
void FunctionName(inout int3 a, inout int3 b) { int3 t = a; a = b; b = t; } \

60
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/NormalSurfaceGradient.hlsl


// this produces an orthonormal basis of the tangent and bitangent WITHOUT vertex level tangent/bitangent for any UV including procedurally generated
// method released with the demo for publication of "bump mapping unparametrized surfaces on the GPU"
// http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html
void SurfaceGradientGenBasisTB(float3 nrmVertexNormal, float3 sigmaX, float3 sigmaY, float flipSign, float2 texST, out float3 vT, out float3 vB)
void SurfaceGradientGenBasisTB(real3 nrmVertexNormal, real3 sigmaX, real3 sigmaY, real flipSign, real2 texST, out real3 vT, out real3 vB)
float2 dSTdx = ddx_fine(texST), dSTdy = ddy_fine(texST);
real2 dSTdx = ddx_fine(texST), dSTdy = ddy_fine(texST);
float det = dot(dSTdx, float2(dSTdy.y, -dSTdy.x));
float sign_det = det < 0 ? -1 : 1;
real det = dot(dSTdx, real2(dSTdy.y, -dSTdy.x));
real sign_det = det < 0 ? -1 : 1;
float2 invC0 = sign_det * float2(dSTdy.y, -dSTdx.y);
real2 invC0 = sign_det * real2(dSTdy.y, -dSTdx.y);
vT = sigmaX * invC0.x + sigmaY * invC0.y;
if (abs(det) > 0.0)
vT = normalize(vT);

// surface gradient from an on the fly TBN (deriv obtained using tspaceNormalToDerivative()) or from conventional vertex level TBN (mikktspace compliant and deriv obtained using tspaceNormalToDerivative())
float3 SurfaceGradientFromTBN(float2 deriv, float3 vT, float3 vB)
real3 SurfaceGradientFromTBN(real2 deriv, real3 vT, real3 vB)
{
return deriv.x * vT + deriv.y * vB;
}

// this allows us to mix the contribution together with a series of other contributions including tangent space normals
// v does not need to be unit length as long as it establishes the direction.
float3 SurfaceGradientFromPerturbedNormal(float3 nrmVertexNormal, float3 v)
real3 SurfaceGradientFromPerturbedNormal(real3 nrmVertexNormal, real3 v)
float3 n = nrmVertexNormal;
float s = 1.0 / max(FLT_EPS, abs(dot(n, v)));
real3 n = nrmVertexNormal;
real s = 1.0 / max(FLT_EPS, abs(dot(n, v)));
return s * (dot(n, v) * n - v);
}

float3 SurfaceGradientFromVolumeGradient(float3 nrmVertexNormal, float3 grad)
real3 SurfaceGradientFromVolumeGradient(real3 nrmVertexNormal, real3 grad)
{
return grad - dot(nrmVertexNormal, grad) * nrmVertexNormal;
}

// derivs obtained using tspaceNormalToDerivative() and weights using computeTriplanarWeights().
float3 SurfaceGradientFromTriplanarProjection(float3 nrmVertexNormal, float3 triplanarWeights, float2 deriv_xplane, float2 deriv_yplane, float2 deriv_zplane)
real3 SurfaceGradientFromTriplanarProjection(real3 nrmVertexNormal, real3 triplanarWeights, real2 deriv_xplane, real2 deriv_yplane, real2 deriv_zplane)
const float w0 = triplanarWeights.x, w1 = triplanarWeights.y, w2 = triplanarWeights.z;
const real w0 = triplanarWeights.x, w1 = triplanarWeights.y, w2 = triplanarWeights.z;
float3 volumeGrad = float3(w2 * deriv_zplane.x + w1 * deriv_yplane.y, w2 * deriv_zplane.y + w0 * deriv_xplane.y, w0 * deriv_xplane.x + w1 * deriv_yplane.x);
real3 volumeGrad = real3(w2 * deriv_zplane.x + w1 * deriv_yplane.y, w2 * deriv_zplane.y + w0 * deriv_xplane.y, w0 * deriv_xplane.x + w1 * deriv_yplane.x);
float3 SurfaceGradientResolveNormal(float3 nrmVertexNormal, float3 surfGrad)
real3 SurfaceGradientResolveNormal(real3 nrmVertexNormal, real3 surfGrad)
{
return normalize(nrmVertexNormal - surfGrad);
}

// So a max angle of 89.55 degrees ;) id argue thats close enough to the vertical limit at 90 degrees
// vT is channels.xy of a tangent space normal in[-1; 1]
// out: convert vT to a derivative
float2 UnpackDerivativeNormalAG(float4 packedNormal, float scale = 1.0)
real2 UnpackDerivativeNormalAG(real4 packedNormal, real scale = 1.0)
const float fS = 1.0 / (128.0 * 128.0);
float2 vT = packedNormal.wy * 2.0 - 1.0;
float2 vTsq = vT * vT;
float nz_sq = 1 - vTsq.x - vTsq.y;
float maxcompxy_sq = fS * max(vTsq.x, vTsq.y);
float z_inv = rsqrt(max(nz_sq, maxcompxy_sq));
float2 deriv = -z_inv * float2(vT.x, vT.y);
const real fS = 1.0 / (128.0 * 128.0);
real2 vT = packedNormal.wy * 2.0 - 1.0;
real2 vTsq = vT * vT;
real nz_sq = 1 - vTsq.x - vTsq.y;
real maxcompxy_sq = fS * max(vTsq.x, vTsq.y);
real z_inv = rsqrt(max(nz_sq, maxcompxy_sq));
real2 deriv = -z_inv * real2(vT.x, vT.y);
float2 UnpackDerivativeNormalRGorAG(float4 packedNormal, float scale = 1.0)
real2 UnpackDerivativeNormalRGorAG(real4 packedNormal, real scale = 1.0)
{
// This do the trick
packedNormal.w *= packedNormal.x;

float2 UnpackDerivativeNormalRGB(float4 packedNormal, float scale = 1.0)
real2 UnpackDerivativeNormalRGB(real4 packedNormal, real scale = 1.0)
const float fS = 1.0 / (128.0 * 128.0);
float3 vT = packedNormal.xyz * 2.0 - 1.0;
float3 vTsq = vT * vT;
float maxcompxy_sq = fS * max(vTsq.x, vTsq.y);
float z_inv = rsqrt(max(vTsq.z, maxcompxy_sq));
float2 deriv = -z_inv * float2(vT.x, vT.y);
const real fS = 1.0 / (128.0 * 128.0);
real3 vT = packedNormal.xyz * 2.0 - 1.0;
real3 vTsq = vT * vT;
real maxcompxy_sq = fS * max(vTsq.x, vTsq.y);
real z_inv = rsqrt(max(vTsq.z, maxcompxy_sq));
real2 deriv = -z_inv * real2(vT.x, vT.y);
return deriv * scale;
}

238
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Packing.hlsl


// Normal packing
//-----------------------------------------------------------------------------
float3 PackNormalMaxComponent(float3 n)
real3 PackNormalMaxComponent(real3 n)
float3 UnpackNormalMaxComponent(float3 n)
real3 UnpackNormalMaxComponent(real3 n)
{
return normalize(n * 2.0 - 1.0);
}

// return float between [-1, 1]
float2 PackNormalOctEncode(float3 n)
// return real between [-1, 1]
real2 PackNormalOctEncode(real3 n)
//float l1norm = dot(abs(n), 1.0);
//float2 res0 = n.xy * (1.0 / l1norm);
//real l1norm = dot(abs(n), 1.0);
//real2 res0 = n.xy * (1.0 / l1norm);
//float2 val = 1.0 - abs(res0.yx);
//return (n.zz < float2(0.0, 0.0) ? (res0 >= 0.0 ? val : -val) : res0);
//real2 val = 1.0 - abs(res0.yx);
//return (n.zz < real2(0.0, 0.0) ? (res0 >= 0.0 ? val : -val) : res0);
float t = saturate(-n.z);
real t = saturate(-n.z);
float3 UnpackNormalOctEncode(float2 f)
real3 UnpackNormalOctEncode(real2 f)
float3 n = float3(f.x, f.y, 1.0 - abs(f.x) - abs(f.y));
real3 n = real3(f.x, f.y, 1.0 - abs(f.x) - abs(f.y));
//float2 val = 1.0 - abs(n.yx);
//n.xy = (n.zz < float2(0.0, 0.0) ? (n.xy >= 0.0 ? val : -val) : n.xy);
//real2 val = 1.0 - abs(n.yx);
//n.xy = (n.zz < real2(0.0, 0.0) ? (n.xy >= 0.0 ? val : -val) : n.xy);
float t = max(-n.z, 0.0);
real t = max(-n.z, 0.0);
float2 PackNormalHemiOctEncode(float3 n)
real2 PackNormalHemiOctEncode(real3 n)
float l1norm = dot(abs(n), 1.0);
float2 res = n.xy * (1.0 / l1norm);
real l1norm = dot(abs(n), 1.0);
real2 res = n.xy * (1.0 / l1norm);
return float2(res.x + res.y, res.x - res.y);
return real2(res.x + res.y, res.x - res.y);
float3 UnpackNormalHemiOctEncode(float2 f)
real3 UnpackNormalHemiOctEncode(real2 f)
float2 val = float2(f.x + f.y, f.x - f.y) * 0.5;
float3 n = float3(val, 1.0 - dot(abs(val), 1.0));
real2 val = real2(f.x + f.y, f.x - f.y) * 0.5;
real3 n = real3(val, 1.0 - dot(abs(val), 1.0));
return normalize(n);
}

// v0 = float3(1.0, 0.0, -1.0 / sqrt(2.0));
// v1 = float3(-1.0, 0.0, -1.0 / sqrt(2.0));
// v2 = float3(0.0, 1.0, 1.0 / sqrt(2.0));
// v3 = float3(0.0, -1.0, 1.0 / sqrt(2.0));
// v0 = real3(1.0, 0.0, -1.0 / sqrt(2.0));
// v1 = real3(-1.0, 0.0, -1.0 / sqrt(2.0));
// v2 = real3(0.0, 1.0, 1.0 / sqrt(2.0));
// v3 = real3(0.0, -1.0, 1.0 / sqrt(2.0));
static const float3 tetraBasisNormal[4] =
static const real3 tetraBasisNormal[4] =
float3(0., 0.816497, -0.57735),
float3(-0.816497, 0., 0.57735),
float3(0.816497, 0., 0.57735),
float3(0., -0.816497, -0.57735)
real3(0., 0.816497, -0.57735),
real3(-0.816497, 0., 0.57735),
real3(0.816497, 0., 0.57735),
real3(0., -0.816497, -0.57735)
static const float3x3 tetraBasisArray[4] =
static const real3x3 tetraBasisArray[4] =
float3x3(-1., 0., 0.,0., 0.57735, 0.816497,0., 0.816497, -0.57735),
float3x3(0., -1., 0.,0.57735, 0., 0.816497,-0.816497, 0., 0.57735),
float3x3(0., 1., 0.,-0.57735, 0., 0.816497,0.816497, 0., 0.57735),
float3x3(1., 0., 0.,0., -0.57735, 0.816497,0., -0.816497, -0.57735)
real3x3(-1., 0., 0.,0., 0.57735, 0.816497,0., 0.816497, -0.57735),
real3x3(0., -1., 0.,0.57735, 0., 0.816497,-0.816497, 0., 0.57735),
real3x3(0., 1., 0.,-0.57735, 0., 0.816497,0.816497, 0., 0.57735),
real3x3(1., 0., 0.,0., -0.57735, 0.816497,0., -0.816497, -0.57735)
float2 PackNormalTetraEncode(float3 n, out uint faceIndex)
real2 PackNormalTetraEncode(real3 n, out uint faceIndex)
float dot0 = dot(n, tetraBasisNormal[0]);
float dot1 = dot(n, tetraBasisNormal[1]);
float dot2 = dot(n, tetraBasisNormal[2]);
float dot3 = dot(n, tetraBasisNormal[3]);
real dot0 = dot(n, tetraBasisNormal[0]);
real dot1 = dot(n, tetraBasisNormal[1]);
real dot2 = dot(n, tetraBasisNormal[2]);
real dot3 = dot(n, tetraBasisNormal[3]);
float maxi0 = max(dot0, dot1);
float maxi1 = max(dot2, dot3);
float maxi = max(maxi0, maxi1);
real maxi0 = max(dot0, dot1);
real maxi1 = max(dot2, dot3);
real maxi = max(maxi0, maxi1);
// Get the index from the greatest dot
if (maxi == dot0)

}
// Assume f [-1..1]
float3 UnpackNormalTetraEncode(float2 f, uint faceIndex)
real3 UnpackNormalTetraEncode(real2 f, uint faceIndex)
float3 n = float3(f.xy, sqrt(1.0 - dot(f.xy, f.xy)));
real3 n = real3(f.xy, sqrt(1.0 - dot(f.xy, f.xy)));
half3 UnpackNormalRGB(half4 packedNormal, half scale = 1.0)
real3 UnpackNormalRGB(real4 packedNormal, real scale = 1.0)
half3 normal;
real3 normal;
half3 UnpackNormalAG(half4 packedNormal, half scale = 1.0)
real3 UnpackNormalAG(real4 packedNormal, real scale = 1.0)
half3 normal;
real3 normal;
normal.xy = packedNormal.wy * 2.0 - 1.0;
normal.xy *= scale;
normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));

// Unpack normal as DXT5nm (1, y, 0, x) or BC5 (x, y, 0, 1)
half3 UnpackNormalmapRGorAG(half4 packedNormal, half scale = 1.0)
real3 UnpackNormalmapRGorAG(real4 packedNormal, real scale = 1.0)
{
// This do the trick
packedNormal.w *= packedNormal.x;

#if !defined(SHADER_API_GLES)
// Ref: http://realtimecollisiondetection.net/blog/?p=15
float4 PackToLogLuv(float3 vRGB)
real4 PackToLogLuv(real3 vRGB)
const float3x3 M = float3x3(
const real3x3 M = real3x3(
float4 vResult;
float3 Xp_Y_XYZp = mul(vRGB, M);
Xp_Y_XYZp = max(Xp_Y_XYZp, float3(1e-6, 1e-6, 1e-6));
real4 vResult;
real3 Xp_Y_XYZp = mul(vRGB, M);
Xp_Y_XYZp = max(Xp_Y_XYZp, real3(1e-6, 1e-6, 1e-6));
float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;
real Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;
float3 UnpackFromLogLuv(float4 vLogLuv)
real3 UnpackFromLogLuv(real4 vLogLuv)
const float3x3 InverseM = float3x3(
const real3x3 InverseM = real3x3(
float Le = vLogLuv.z * 255.0 + vLogLuv.w;
float3 Xp_Y_XYZp;
real Le = vLogLuv.z * 255.0 + vLogLuv.w;
real3 Xp_Y_XYZp;
float3 vRGB = mul(Xp_Y_XYZp, InverseM);
return max(vRGB, float3(0.0, 0.0, 0.0));
real3 vRGB = mul(Xp_Y_XYZp, InverseM);
return max(vRGB, real3(0.0, 0.0, 0.0));
}
// The standard 32-bit HDR color format

/*
// This is GCN intrinsic
uint FindBiggestComponent(float4 q)
uint FindBiggestComponent(real4 q)
{
uint xyzIndex = CubeMapFaceID(q.x, q.y, q.z) * 0.5f;
uint wIndex = 3;

}
// Pack a quaternion into a 10:10:10:2
float4 PackQuat(float4 quat)
real4 PackQuat(real4 quat)
{
uint index = FindBiggestComponent(quat);

float4 packedQuat;
real4 packedQuat;
packedQuat.xyz = quat.xyz * FastSign(quat.w) * sqrt(0.5) + 0.5;
packedQuat.w = index / 3.0;

// Unpack a quaternion from a 10:10:10:2
float4 UnpackQuat(float4 packedQuat)
real4 UnpackQuat(real4 packedQuat)
float4 quat;
real4 quat;
quat.xyz = packedQuat.xyz * sqrt(2.0) - (1.0 / sqrt(2.0));
quat.w = sqrt(1.0 - saturate(dot(quat.xyz, quat.xyz)));

// Integer packing
//-----------------------------------------------------------------------------
// Packs an integer stored using at most 'numBits' into a [0..1] float.
float PackInt(uint i, uint numBits)
// Packs an integer stored using at most 'numBits' into a [0..1] real.
real PackInt(uint i, uint numBits)
// Unpacks a [0..1] float into an integer of size 'numBits'.
uint UnpackInt(float f, uint numBits)
// Unpacks a [0..1] real into an integer of size 'numBits'.
uint UnpackInt(real f, uint numBits)
// Packs a [0..255] integer into a [0..1] float.
float PackByte(uint i)
// Packs a [0..255] integer into a [0..1] real.
real PackByte(uint i)
// Unpacks a [0..1] float into a [0..255] integer.
uint UnpackByte(float f)
// Unpacks a [0..1] real into a [0..255] integer.
uint UnpackByte(real f)
// Packs a [0..65535] integer into a [0..1] float.
float PackShort(uint i)
// Packs a [0..65535] integer into a [0..1] real.
real PackShort(uint i)
// Unpacks a [0..1] float into a [0..65535] integer.
uint UnpackShort(float f)
// Unpacks a [0..1] real into a [0..65535] integer.
uint UnpackShort(real f)
// Packs 8 lowermost bits of a [0..65535] integer into a [0..1] float.
float PackShortLo(uint i)
// Packs 8 lowermost bits of a [0..65535] integer into a [0..1] real.
real PackShortLo(uint i)
// Packs 8 uppermost bits of a [0..65535] integer into a [0..1] float.
float PackShortHi(uint i)
// Packs 8 uppermost bits of a [0..65535] integer into a [0..1] real.
real PackShortHi(uint i)
float Pack2Byte(float2 inputs)
real Pack2Byte(real2 inputs)
float2 temp = inputs * float2(255.0, 255.0);
real2 temp = inputs * real2(255.0, 255.0);
float combined = temp.x + temp.y;
real combined = temp.x + temp.y;
float2 Unpack2Byte(float inputs)
real2 Unpack2Byte(real inputs)
float temp = round(inputs * 65535.0);
float ipart;
float fpart = modf(temp / 256.0, ipart);
float2 result = float2(ipart, round(256.0 * fpart));
return result * (1.0 / float2(255.0, 255.0));
real temp = round(inputs * 65535.0);
real ipart;
real fpart = modf(temp / 256.0, ipart);
real2 result = real2(ipart, round(256.0 * fpart));
return result * (1.0 / real2(255.0, 255.0));
// Encode a float in [0..1] and an int in [0..maxi - 1] as a float [0..1] to be store in log2(precision) bit
// Encode a real in [0..1] and an int in [0..maxi - 1] as a real [0..1] to be store in log2(precision) bit
// maxi must be a power of two and define the number of bit dedicated 0..1 to the int part (log2(maxi))
// Example: precision is 256.0, maxi is 2, i is [0..1] encode on 1 bit. f is [0..1] encode on 7 bit.
// Example: precision is 256.0, maxi is 4, i is [0..3] encode on 2 bit. f is [0..1] encode on 6 bit.

//...
float PackFloatInt(float f, int i, float maxi, float precision)
real PackFloatInt(real f, int i, real maxi, real precision)
float precisionMinusOne = precision - 1.0;
float t1 = ((precision / maxi) - 1.0) / precisionMinusOne;
float t2 = (precision / maxi) / precisionMinusOne;
real precisionMinusOne = precision - 1.0;
real t1 = ((precision / maxi) - 1.0) / precisionMinusOne;
real t2 = (precision / maxi) / precisionMinusOne;
return t1 * f + t2 * float(i);
return t1 * f + t2 * real(i);
void UnpackFloatInt(float val, float maxi, float precision, out float f, out int i)
void UnpackFloatInt(real val, real maxi, real precision, out real f, out int i)
float precisionMinusOne = precision - 1.0;
float t1 = ((precision / maxi) - 1.0) / precisionMinusOne;
float t2 = (precision / maxi) / precisionMinusOne;
real precisionMinusOne = precision - 1.0;
real t1 = ((precision / maxi) - 1.0) / precisionMinusOne;
real t2 = (precision / maxi) / precisionMinusOne;
//f = (val - t2 * float(i)) / t1 => convert in mads form
f = saturate((-t2 * float(i) + val) / t1); // Saturate in case of precision issue
//f = (val - t2 * real(i)) / t1 => convert in mads form
f = saturate((-t2 * real(i) + val) / t1); // Saturate in case of precision issue
float PackFloatInt8bit(float f, int i, float maxi)
real PackFloatInt8bit(real f, int i, real maxi)
void UnpackFloatInt8bit(float val, float maxi, out float f, out int i)
void UnpackFloatInt8bit(real val, real maxi, out real f, out int i)
float PackFloatInt10bit(float f, int i, float maxi)
real PackFloatInt10bit(real f, int i, real maxi)
void UnpackFloatInt10bit(float val, float maxi, out float f, out int i)
void UnpackFloatInt10bit(real val, real maxi, out real f, out int i)
float PackFloatInt16bit(float f, int i, float maxi)
real PackFloatInt16bit(real f, int i, real maxi)
void UnpackFloatInt16bit(float val, float maxi, out float f, out int i)
void UnpackFloatInt16bit(real val, real maxi, out real f, out int i)
{
UnpackFloatInt(val, maxi, 65536.0, f, i);
}

//-----------------------------------------------------------------------------
// src must be between 0.0 and 1.0
uint PackFloatToUInt(float src, uint offset, uint numBits)
uint PackFloatToUInt(real src, uint offset, uint numBits)
float UnpackUIntToFloat(uint src, uint offset, uint numBits)
real UnpackUIntToFloat(uint src, uint offset, uint numBits)
return float(BitFieldExtract(src, offset, numBits)) * rcp(maxInt);
return real(BitFieldExtract(src, offset, numBits)) * rcp(maxInt);
uint PackToR10G10B10A2(float4 rgba)
uint PackToR10G10B10A2(real4 rgba)
{
return (PackFloatToUInt(rgba.x, 0, 10) |
PackFloatToUInt(rgba.y, 10, 10) |

float4 UnpackFromR10G10B10A2(uint rgba)
real4 UnpackFromR10G10B10A2(uint rgba)
float4 ouput;
real4 ouput;
ouput.x = UnpackUIntToFloat(rgba, 0, 10);
ouput.y = UnpackUIntToFloat(rgba, 10, 10);
ouput.z = UnpackUIntToFloat(rgba, 20, 10);

// Both the input and the output are in the [0, 1] range.
float2 PackFloatToR8G8(float f)
real2 PackFloatToR8G8(real f)
return float2(PackShortLo(i), PackShortHi(i));
return real2(PackShortLo(i), PackShortHi(i));
float UnpackFloatFromR8G8(float2 f)
real UnpackFloatFromR8G8(real2 f)
{
uint lo = UnpackByte(f.x);
uint hi = UnpackByte(f.y);

56
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/PerPixelDisplacement.hlsl


// it return the offset to apply to the UVSet provide in PerPixelHeightDisplacementParam
// viewDirTS is view vector in texture space matching the UVSet
// ref: https://www.gamedev.net/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262
float2 ParallaxOcclusionMapping(float lod, float lodThreshold, int numSteps, float3 viewDirTS, PerPixelHeightDisplacementParam ppdParam, out float outHeight)
real2 ParallaxOcclusionMapping(real lod, real lodThreshold, int numSteps, real3 viewDirTS, PerPixelHeightDisplacementParam ppdParam, out real outHeight)
float stepSize = 1.0 / (float)numSteps;
real stepSize = 1.0 / (real)numSteps;
// float parallaxLimit = -length(viewDirTS.xy) / viewDirTS.z;
// float2 parallaxDir = normalize(Out.viewDirTS.xy);
// float2 parallaxMaxOffsetTS = parallaxDir * parallaxLimit;
// real parallaxLimit = -length(viewDirTS.xy) / viewDirTS.z;
// real2 parallaxDir = normalize(Out.viewDirTS.xy);
// real2 parallaxMaxOffsetTS = parallaxDir * parallaxLimit;
float2 parallaxMaxOffsetTS = (viewDirTS.xy / -viewDirTS.z);
float2 texOffsetPerStep = stepSize * parallaxMaxOffsetTS;
real2 parallaxMaxOffsetTS = (viewDirTS.xy / -viewDirTS.z);
real2 texOffsetPerStep = stepSize * parallaxMaxOffsetTS;
float2 texOffsetCurrent = float2(0.0, 0.0);
float prevHeight = ComputePerPixelHeightDisplacement(texOffsetCurrent, lod, ppdParam);
real2 texOffsetCurrent = real2(0.0, 0.0);
real prevHeight = ComputePerPixelHeightDisplacement(texOffsetCurrent, lod, ppdParam);
float currHeight = ComputePerPixelHeightDisplacement(texOffsetCurrent, lod, ppdParam);
float rayHeight = 1.0 - stepSize; // Start at top less one sample
real currHeight = ComputePerPixelHeightDisplacement(texOffsetCurrent, lod, ppdParam);
real rayHeight = 1.0 - stepSize; // Start at top less one sample
// Linear search
for (int stepIndex = 0; stepIndex < numSteps; ++stepIndex)

#define POM_SECANT_METHOD 1
#if POM_SECANT_METHOD
float pt0 = rayHeight + stepSize;
float pt1 = rayHeight;
float delta0 = pt0 - prevHeight;
float delta1 = pt1 - currHeight;
real pt0 = rayHeight + stepSize;
real pt1 = rayHeight;
real delta0 = pt0 - prevHeight;
real delta1 = pt1 - currHeight;
float delta;
float2 offset;
real delta;
real2 offset;
// Secant method to affine the search
// Ref: Faster Relief Mapping Using the Secant Method - Eric Risser

float intersectionHeight = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);
real intersectionHeight = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);
// Retrieve offset require to find this intersectionHeight
offset = (1 - intersectionHeight) * texOffsetPerStep * numSteps;

#else // regular POM intersection
//float pt0 = rayHeight + stepSize;
//float pt1 = rayHeight;
//float delta0 = pt0 - prevHeight;
//float delta1 = pt1 - currHeight;
//float intersectionHeight = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);
//float2 offset = (1 - intersectionHeight) * texOffsetPerStep * numSteps;
//real pt0 = rayHeight + stepSize;
//real pt1 = rayHeight;
//real delta0 = pt0 - prevHeight;
//real delta1 = pt1 - currHeight;
//real intersectionHeight = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);
//real2 offset = (1 - intersectionHeight) * texOffsetPerStep * numSteps;
float delta0 = currHeight - rayHeight;
float delta1 = (rayHeight + stepSize) - prevHeight;
float ratio = delta0 / (delta0 + delta1);
float2 offset = texOffsetCurrent - ratio * texOffsetPerStep;
real delta0 = currHeight - rayHeight;
real delta1 = (rayHeight + stepSize) - prevHeight;
real ratio = delta0 / (delta0 + delta1);
real2 offset = texOffsetCurrent - ratio * texOffsetPerStep;
currHeight = ComputePerPixelHeightDisplacement(offset, lod, ppdParam);

24
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/QuaternionMath.hlsl


// Ref: https://cedec.cesa.or.jp/2015/session/ENG/14698.html The Rendering Materials of Far Cry 4
float4 TangentSpaceToQuat(float3 tagent, float3 bitangent, float3 normal)
real4 TangentSpaceToQuat(real3 tagent, real3 bitangent, real3 normal)
float4 quat;
real4 quat;
quat.x = normal.y - bitangent.z;
quat.y = tangent.z - normal.x;
quat.z = bitangent.x - tangent.y;

}
void QuatToTangentSpace(float4 quaterion, out float3 tangent, out float3 bitangent, out float3 normal)
void QuatToTangentSpace(real4 quaterion, out real3 tangent, out real3 bitangent, out real3 normal)
tangent = float3(1.0, 0.0, 0.0)
+ float3(-2.0, 2.0, 2.0) * quat.y * quat.yxw
+ float3(-2.0, -2.0, 2.0) * quat.z * quaternion.zwx;
tangent = real3(1.0, 0.0, 0.0)
+ real3(-2.0, 2.0, 2.0) * quat.y * quat.yxw
+ real3(-2.0, -2.0, 2.0) * quat.z * quaternion.zwx;
bitangent = float3(0.0, 1.0, 0.0)
+ float3(2.0, -2.0, 2.0) * quat.z * quat.wzy
+ float3(2.0, -2.0, -2.0) * quat.x * quaternion.yxw;
bitangent = real3(0.0, 1.0, 0.0)
+ real3(2.0, -2.0, 2.0) * quat.z * quat.wzy
+ real3(2.0, -2.0, -2.0) * quat.x * quaternion.yxw;
normal = float3(0.0, 0.0, 1.0)
+ float3(2.0, 2.0, -2.0) * quat.x * quat.zwx
+ float3(-2.0, 2.0, -2.0) * quat.y * quaternion.wzy;
normal = real3(0.0, 0.0, 1.0)
+ real3(2.0, 2.0, -2.0) * quat.x * quat.zwx
+ real3(-2.0, 2.0, -2.0) * quat.y * quaternion.wzy;
}
#endif // UNITY_QUATERNIONMATH_INCLUDED

20
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Random.hlsl


return ConstructFloat(JenkinsHash(v));
}
float Hash(uint s)
{
s = s ^ 2747636419u;
s = s * 2654435769u;
s = s ^ (s >> 16);
s = s * 2654435769u;
s = s ^ (s >> 16);
s = s * 2654435769u;
return float(s) * rcp(4294967296.0); // 2^-32
}
float2 InitRandom(float2 input)
{
float2 r;
r.x = Hash(uint(input.x * UINT_MAX));
r.y = Hash(uint(input.y * UINT_MAX));
return r;
}
#endif // SHADER_API_GLES
#endif // UNITY_NOISE_INCLUDED

38
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Refraction.hlsl


struct RefractionModelResult
{
float distance; // length of the transmission during refraction through the shape
float3 positionWS; // out ray position
float3 rayWS; // out ray direction
real dist; // length of the transmission during refraction through the shape
float3 positionWS; // out ray position
real3 rayWS; // out ray direction
RefractionModelResult RefractionModelSphere(float3 V, float3 positionWS, float3 normalWS, float ior, float thickness)
RefractionModelResult RefractionModelSphere(real3 V, float3 positionWS, real3 normalWS, real ior, real thickness)
{
// Sphere shape model:
// We approximate locally the shape of the object as sphere, that is tangent to the shape.

// First refraction (tangent sphere in)
// Refracted ray
float3 R1 = refract(-V, normalWS, 1.0 / ior);
real3 R1 = refract(-V, normalWS, 1.0 / ior);
float3 C = positionWS - normalWS * thickness * 0.5;
real3 C = positionWS - normalWS * thickness * 0.5;
float NoR1 = dot(normalWS, R1);
real NoR1 = dot(normalWS, R1);
float distance = -NoR1 * thickness;
real dist = -NoR1 * thickness;
float3 P1 = positionWS + R1 * distance;
real3 P1 = positionWS + R1 * dist;
float3 N1 = normalize(C - P1);
real3 N1 = normalize(C - P1);
float3 R2 = refract(R1, N1, ior);
float N1oR2 = dot(N1, R2);
float VoR1 = dot(V, R1);
real3 R2 = refract(R1, N1, ior);
real N1oR2 = dot(N1, R2);
real VoR1 = dot(V, R1);
result.distance = distance;
result.dist = dist;
result.positionWS = P1;
result.rayWS = R2;

RefractionModelResult RefractionModelPlane(float3 V, float3 positionWS, float3 normalWS, float ior, float thickness)
RefractionModelResult RefractionModelPlane(real3 V, float3 positionWS, real3 normalWS, real ior, real thickness)
{
// Plane shape model:
// We approximate locally the shape of the object as a plane with normal {normalWS} at {positionWS}

float3 R = refract(-V, normalWS, 1.0 / ior);
real3 R = refract(-V, normalWS, 1.0 / ior);
float distance = thickness / dot(R, -normalWS);
real dist = thickness / dot(R, -normalWS);
result.distance = distance;
result.positionWS = positionWS + R * distance;
result.dist = dist;
result.positionWS = positionWS + R * dist;
result.rayWS = -V;
return result;

434
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Sampling/Fibonacci.hlsl


// Computes a point using the Fibonacci sequence of length N.
// Input: Fib[N - 1], Fib[N - 2], and the index 'i' of the point.
// Ref: Efficient Quadrature Rules for Illumination Integrals
float2 Fibonacci2dSeq(float fibN1, float fibN2, uint i)
real2 Fibonacci2dSeq(real fibN1, real fibN2, uint i)
return float2(i / fibN1 + (0.5f / fibN1), frac(i * (fibN2 / fibN1)));
return real2(i / fibN1 + (0.5/ fibN1), frac(i * (fibN2 / fibN1)));
float2 Golden2dSeq(uint i, float n)
real2 Golden2dSeq(uint i, real n)
return float2(i / n + (0.5f / n), frac(i * rcp(GOLDEN_RATIO)));
return real2(i / n + (0.5/ n), frac(i * rcp(GOLDEN_RATIO)));
}
static const uint k_FibonacciSeq[] = {

static const float2 k_Fibonacci2dSeq21[] = {
float2(0.02380952, 0.00000000),
float2(0.07142857, 0.61904764),
float2(0.11904762, 0.23809528),
float2(0.16666667, 0.85714293),
float2(0.21428572, 0.47619057),
float2(0.26190478, 0.09523821),
float2(0.30952382, 0.71428585),
float2(0.35714287, 0.33333349),
float2(0.40476191, 0.95238113),
float2(0.45238096, 0.57142878),
float2(0.50000000, 0.19047642),
float2(0.54761904, 0.80952406),
float2(0.59523809, 0.42857170),
float2(0.64285713, 0.04761887),
float2(0.69047618, 0.66666698),
float2(0.73809522, 0.28571510),
float2(0.78571427, 0.90476227),
float2(0.83333331, 0.52380943),
float2(0.88095236, 0.14285755),
float2(0.92857140, 0.76190567),
float2(0.97619045, 0.38095284)
static const real2 k_Fibonacci2dSeq21[] = {
real2(0.02380952, 0.00000000),
real2(0.07142857, 0.61904764),
real2(0.11904762, 0.23809528),
real2(0.16666667, 0.85714293),
real2(0.21428572, 0.47619057),
real2(0.26190478, 0.09523821),
real2(0.30952382, 0.71428585),
real2(0.35714287, 0.33333349),
real2(0.40476191, 0.95238113),
real2(0.45238096, 0.57142878),
real2(0.50000000, 0.19047642),
real2(0.54761904, 0.80952406),
real2(0.59523809, 0.42857170),
real2(0.64285713, 0.04761887),
real2(0.69047618, 0.66666698),
real2(0.73809522, 0.28571510),
real2(0.78571427, 0.90476227),
real2(0.83333331, 0.52380943),
real2(0.88095236, 0.14285755),
real2(0.92857140, 0.76190567),
real2(0.97619045, 0.38095284)
static const float2 k_Fibonacci2dSeq34[] = {
float2(0.01470588, 0.00000000),
float2(0.04411765, 0.61764705),
float2(0.07352941, 0.23529410),
float2(0.10294118, 0.85294116),
float2(0.13235295, 0.47058821),
float2(0.16176471, 0.08823538),
float2(0.19117647, 0.70588231),
float2(0.22058824, 0.32352924),
float2(0.25000000, 0.94117641),
float2(0.27941176, 0.55882359),
float2(0.30882353, 0.17647076),
float2(0.33823529, 0.79411745),
float2(0.36764705, 0.41176462),
float2(0.39705881, 0.02941132),
float2(0.42647058, 0.64705849),
float2(0.45588234, 0.26470566),
float2(0.48529410, 0.88235283),
float2(0.51470590, 0.50000000),
float2(0.54411763, 0.11764717),
float2(0.57352942, 0.73529434),
float2(0.60294116, 0.35294151),
float2(0.63235295, 0.97058773),
float2(0.66176468, 0.58823490),
float2(0.69117647, 0.20588207),
float2(0.72058821, 0.82352924),
float2(0.75000000, 0.44117641),
float2(0.77941179, 0.05882263),
float2(0.80882353, 0.67646980),
float2(0.83823532, 0.29411697),
float2(0.86764705, 0.91176414),
float2(0.89705884, 0.52941132),
float2(0.92647058, 0.14705849),
float2(0.95588237, 0.76470566),
float2(0.98529410, 0.38235283)
static const real2 k_Fibonacci2dSeq34[] = {
real2(0.01470588, 0.00000000),
real2(0.04411765, 0.61764705),
real2(0.07352941, 0.23529410),
real2(0.10294118, 0.85294116),
real2(0.13235295, 0.47058821),
real2(0.16176471, 0.08823538),
real2(0.19117647, 0.70588231),
real2(0.22058824, 0.32352924),
real2(0.25000000, 0.94117641),
real2(0.27941176, 0.55882359),
real2(0.30882353, 0.17647076),
real2(0.33823529, 0.79411745),
real2(0.36764705, 0.41176462),
real2(0.39705881, 0.02941132),
real2(0.42647058, 0.64705849),
real2(0.45588234, 0.26470566),
real2(0.48529410, 0.88235283),
real2(0.51470590, 0.50000000),
real2(0.54411763, 0.11764717),
real2(0.57352942, 0.73529434),
real2(0.60294116, 0.35294151),
real2(0.63235295, 0.97058773),
real2(0.66176468, 0.58823490),
real2(0.69117647, 0.20588207),
real2(0.72058821, 0.82352924),
real2(0.75000000, 0.44117641),
real2(0.77941179, 0.05882263),
real2(0.80882353, 0.67646980),
real2(0.83823532, 0.29411697),
real2(0.86764705, 0.91176414),
real2(0.89705884, 0.52941132),
real2(0.92647058, 0.14705849),
real2(0.95588237, 0.76470566),
real2(0.98529410, 0.38235283)
static const float2 k_Fibonacci2dSeq55[] = {
float2(0.00909091, 0.00000000),
float2(0.02727273, 0.61818182),
float2(0.04545455, 0.23636365),
float2(0.06363636, 0.85454547),
float2(0.08181818, 0.47272730),
float2(0.10000000, 0.09090900),
float2(0.11818182, 0.70909095),
float2(0.13636364, 0.32727289),
float2(0.15454546, 0.94545460),
float2(0.17272727, 0.56363630),
float2(0.19090909, 0.18181801),
float2(0.20909090, 0.80000019),
float2(0.22727273, 0.41818190),
float2(0.24545455, 0.03636360),
float2(0.26363635, 0.65454578),
float2(0.28181818, 0.27272701),
float2(0.30000001, 0.89090919),
float2(0.31818181, 0.50909138),
float2(0.33636364, 0.12727261),
float2(0.35454544, 0.74545479),
float2(0.37272727, 0.36363602),
float2(0.39090911, 0.98181820),
float2(0.40909091, 0.60000038),
float2(0.42727274, 0.21818161),
float2(0.44545454, 0.83636379),
float2(0.46363637, 0.45454597),
float2(0.48181817, 0.07272720),
float2(0.50000000, 0.69090843),
float2(0.51818180, 0.30909157),
float2(0.53636366, 0.92727280),
float2(0.55454546, 0.54545403),
float2(0.57272726, 0.16363716),
float2(0.59090906, 0.78181839),
float2(0.60909092, 0.39999962),
float2(0.62727273, 0.01818275),
float2(0.64545453, 0.63636398),
float2(0.66363639, 0.25454521),
float2(0.68181819, 0.87272835),
float2(0.69999999, 0.49090958),
float2(0.71818179, 0.10909081),
float2(0.73636365, 0.72727203),
float2(0.75454545, 0.34545517),
float2(0.77272725, 0.96363640),
float2(0.79090911, 0.58181763),
float2(0.80909091, 0.20000076),
float2(0.82727271, 0.81818199),
float2(0.84545457, 0.43636322),
float2(0.86363637, 0.05454636),
float2(0.88181818, 0.67272758),
float2(0.89999998, 0.29090881),
float2(0.91818184, 0.90909195),
float2(0.93636364, 0.52727318),
float2(0.95454544, 0.14545441),
float2(0.97272730, 0.76363754),
float2(0.99090910, 0.38181686)
static const real2 k_Fibonacci2dSeq55[] = {
real2(0.00909091, 0.00000000),
real2(0.02727273, 0.61818182),
real2(0.04545455, 0.23636365),
real2(0.06363636, 0.85454547),
real2(0.08181818, 0.47272730),
real2(0.10000000, 0.09090900),
real2(0.11818182, 0.70909095),
real2(0.13636364, 0.32727289),
real2(0.15454546, 0.94545460),
real2(0.17272727, 0.56363630),
real2(0.19090909, 0.18181801),
real2(0.20909090, 0.80000019),
real2(0.22727273, 0.41818190),
real2(0.24545455, 0.03636360),
real2(0.26363635, 0.65454578),
real2(0.28181818, 0.27272701),
real2(0.30000001, 0.89090919),
real2(0.31818181, 0.50909138),
real2(0.33636364, 0.12727261),
real2(0.35454544, 0.74545479),
real2(0.37272727, 0.36363602),
real2(0.39090911, 0.98181820),
real2(0.40909091, 0.60000038),
real2(0.42727274, 0.21818161),
real2(0.44545454, 0.83636379),
real2(0.46363637, 0.45454597),
real2(0.48181817, 0.07272720),
real2(0.50000000, 0.69090843),
real2(0.51818180, 0.30909157),
real2(0.53636366, 0.92727280),
real2(0.55454546, 0.54545403),
real2(0.57272726, 0.16363716),
real2(0.59090906, 0.78181839),
real2(0.60909092, 0.39999962),
real2(0.62727273, 0.01818275),
real2(0.64545453, 0.63636398),
real2(0.66363639, 0.25454521),
real2(0.68181819, 0.87272835),
real2(0.69999999, 0.49090958),
real2(0.71818179, 0.10909081),
real2(0.73636365, 0.72727203),
real2(0.75454545, 0.34545517),
real2(0.77272725, 0.96363640),
real2(0.79090911, 0.58181763),
real2(0.80909091, 0.20000076),
real2(0.82727271, 0.81818199),
real2(0.84545457, 0.43636322),
real2(0.86363637, 0.05454636),
real2(0.88181818, 0.67272758),
real2(0.89999998, 0.29090881),
real2(0.91818184, 0.90909195),
real2(0.93636364, 0.52727318),
real2(0.95454544, 0.14545441),
real2(0.97272730, 0.76363754),
real2(0.99090910, 0.38181686)
static const float2 k_Fibonacci2dSeq89[] = {
float2(0.00561798, 0.00000000),
float2(0.01685393, 0.61797750),
float2(0.02808989, 0.23595500),
float2(0.03932584, 0.85393250),
float2(0.05056180, 0.47191000),
float2(0.06179775, 0.08988762),
float2(0.07303371, 0.70786500),
float2(0.08426967, 0.32584238),
float2(0.09550562, 0.94382000),
float2(0.10674157, 0.56179762),
float2(0.11797753, 0.17977524),
float2(0.12921348, 0.79775238),
float2(0.14044943, 0.41573000),
float2(0.15168539, 0.03370762),
float2(0.16292135, 0.65168476),
float2(0.17415731, 0.26966286),
float2(0.18539326, 0.88764000),
float2(0.19662921, 0.50561714),
float2(0.20786516, 0.12359524),
float2(0.21910113, 0.74157238),
float2(0.23033708, 0.35955048),
float2(0.24157304, 0.97752762),
float2(0.25280899, 0.59550476),
float2(0.26404494, 0.21348286),
float2(0.27528089, 0.83146000),
float2(0.28651685, 0.44943714),
float2(0.29775280, 0.06741524),
float2(0.30898875, 0.68539238),
float2(0.32022473, 0.30336952),
float2(0.33146068, 0.92134666),
float2(0.34269664, 0.53932571),
float2(0.35393259, 0.15730286),
float2(0.36516854, 0.77528000),
float2(0.37640449, 0.39325714),
float2(0.38764045, 0.01123428),
float2(0.39887640, 0.62921333),
float2(0.41011235, 0.24719048),
float2(0.42134830, 0.86516762),
float2(0.43258426, 0.48314476),
float2(0.44382024, 0.10112190),
float2(0.45505619, 0.71910095),
float2(0.46629214, 0.33707809),
float2(0.47752810, 0.95505524),
float2(0.48876405, 0.57303238),
float2(0.50000000, 0.19100952),
float2(0.51123595, 0.80898666),
float2(0.52247190, 0.42696571),
float2(0.53370786, 0.04494286),
float2(0.54494381, 0.66292000),
float2(0.55617976, 0.28089714),
float2(0.56741571, 0.89887428),
float2(0.57865167, 0.51685333),
float2(0.58988762, 0.13483047),
float2(0.60112357, 0.75280762),
float2(0.61235952, 0.37078476),
float2(0.62359548, 0.98876190),
float2(0.63483149, 0.60673904),
float2(0.64606744, 0.22471619),
float2(0.65730339, 0.84269333),
float2(0.66853935, 0.46067429),
float2(0.67977530, 0.07865143),
float2(0.69101125, 0.69662857),
float2(0.70224720, 0.31460571),
float2(0.71348315, 0.93258286),
float2(0.72471911, 0.55056000),
float2(0.73595506, 0.16853714),
float2(0.74719101, 0.78651428),
float2(0.75842696, 0.40449142),
float2(0.76966292, 0.02246857),
float2(0.78089887, 0.64044571),
float2(0.79213482, 0.25842667),
float2(0.80337077, 0.87640381),
float2(0.81460673, 0.49438095),
float2(0.82584268, 0.11235809),
float2(0.83707863, 0.73033524),
float2(0.84831458, 0.34831238),
float2(0.85955054, 0.96628952),
float2(0.87078649, 0.58426666),
float2(0.88202250, 0.20224380),
float2(0.89325845, 0.82022095),
float2(0.90449440, 0.43820190),
float2(0.91573036, 0.05617905),
float2(0.92696631, 0.67415619),
float2(0.93820226, 0.29213333),
float2(0.94943821, 0.91011047),
float2(0.96067417, 0.52808762),
float2(0.97191012, 0.14606476),
float2(0.98314607, 0.76404190),
float2(0.99438202, 0.38201904)
static const real2 k_Fibonacci2dSeq89[] = {
real2(0.00561798, 0.00000000),
real2(0.01685393, 0.61797750),
real2(0.02808989, 0.23595500),
real2(0.03932584, 0.85393250),
real2(0.05056180, 0.47191000),
real2(0.06179775, 0.08988762),
real2(0.07303371, 0.70786500),
real2(0.08426967, 0.32584238),
real2(0.09550562, 0.94382000),
real2(0.10674157, 0.56179762),
real2(0.11797753, 0.17977524),
real2(0.12921348, 0.79775238),
real2(0.14044943, 0.41573000),
real2(0.15168539, 0.03370762),
real2(0.16292135, 0.65168476),
real2(0.17415731, 0.26966286),
real2(0.18539326, 0.88764000),
real2(0.19662921, 0.50561714),
real2(0.20786516, 0.12359524),
real2(0.21910113, 0.74157238),
real2(0.23033708, 0.35955048),
real2(0.24157304, 0.97752762),
real2(0.25280899, 0.59550476),
real2(0.26404494, 0.21348286),
real2(0.27528089, 0.83146000),
real2(0.28651685, 0.44943714),
real2(0.29775280, 0.06741524),
real2(0.30898875, 0.68539238),
real2(0.32022473, 0.30336952),
real2(0.33146068, 0.92134666),
real2(0.34269664, 0.53932571),
real2(0.35393259, 0.15730286),
real2(0.36516854, 0.77528000),
real2(0.37640449, 0.39325714),
real2(0.38764045, 0.01123428),
real2(0.39887640, 0.62921333),
real2(0.41011235, 0.24719048),
real2(0.42134830, 0.86516762),
real2(0.43258426, 0.48314476),
real2(0.44382024, 0.10112190),
real2(0.45505619, 0.71910095),
real2(0.46629214, 0.33707809),
real2(0.47752810, 0.95505524),
real2(0.48876405, 0.57303238),
real2(0.50000000, 0.19100952),
real2(0.51123595, 0.80898666),
real2(0.52247190, 0.42696571),
real2(0.53370786, 0.04494286),
real2(0.54494381, 0.66292000),
real2(0.55617976, 0.28089714),
real2(0.56741571, 0.89887428),
real2(0.57865167, 0.51685333),
real2(0.58988762, 0.13483047),
real2(0.60112357, 0.75280762),
real2(0.61235952, 0.37078476),
real2(0.62359548, 0.98876190),
real2(0.63483149, 0.60673904),
real2(0.64606744, 0.22471619),
real2(0.65730339, 0.84269333),
real2(0.66853935, 0.46067429),
real2(0.67977530, 0.07865143),
real2(0.69101125, 0.69662857),
real2(0.70224720, 0.31460571),
real2(0.71348315, 0.93258286),
real2(0.72471911, 0.55056000),
real2(0.73595506, 0.16853714),
real2(0.74719101, 0.78651428),
real2(0.75842696, 0.40449142),
real2(0.76966292, 0.02246857),
real2(0.78089887, 0.64044571),
real2(0.79213482, 0.25842667),
real2(0.80337077, 0.87640381),
real2(0.81460673, 0.49438095),
real2(0.82584268, 0.11235809),
real2(0.83707863, 0.73033524),
real2(0.84831458, 0.34831238),
real2(0.85955054, 0.96628952),
real2(0.87078649, 0.58426666),
real2(0.88202250, 0.20224380),
real2(0.89325845, 0.82022095),
real2(0.90449440, 0.43820190),
real2(0.91573036, 0.05617905),
real2(0.92696631, 0.67415619),
real2(0.93820226, 0.29213333),
real2(0.94943821, 0.91011047),
real2(0.96067417, 0.52808762),
real2(0.97191012, 0.14606476),
real2(0.98314607, 0.76404190),
real2(0.99438202, 0.38201904)
float2 Fibonacci2d(uint i, uint sampleCount)
real2 Fibonacci2d(uint i, uint sampleCount)
{
switch (sampleCount)
{

}
// Returns the radius as the X coordinate, and the angle as the Y coordinate.
float2 SampleDiskFibonacci(uint i, uint sampleCount)
real2 SampleDiskFibonacci(uint i, uint sampleCount)
float2 f = Fibonacci2d(i, sampleCount);
return float2(f.x, TWO_PI * f.y);
real2 f = Fibonacci2d(i, sampleCount);
return real2(f.x, TWO_PI * f.y);
float2 SampleHemisphereFibonacci(uint i, uint sampleCount)
real2 SampleHemisphereFibonacci(uint i, uint sampleCount)
float2 f = Fibonacci2d(i, sampleCount);
return float2(1 - f.x, TWO_PI * f.y);
real2 f = Fibonacci2d(i, sampleCount);
return real2(1 - f.x, TWO_PI * f.y);
float2 SampleSphereFibonacci(uint i, uint sampleCount)
real2 SampleSphereFibonacci(uint i, uint sampleCount)
float2 f = Fibonacci2d(i, sampleCount);
return float2(1 - 2 * f.x, TWO_PI * f.y);
real2 f = Fibonacci2d(i, sampleCount);
return real2(1 - 2 * f.x, TWO_PI * f.y);
}
#endif // UNITY_FIBONACCI_INCLUDED

754
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Sampling/Hammersley.hlsl


#endif
}
float VanDerCorputBase2(uint i)
real VanDerCorputBase2(uint i)
return ReverseBits32(i) * rcp(4294967296.0); // 0x100000000
return ReverseBits32(i) * rcp(4294967296.0); // 2^-32
float2 Hammersley2dSeq(uint i, uint sequenceLength)
real2 Hammersley2dSeq(uint i, uint sequenceLength)
return float2(float(i) / float(sequenceLength), VanDerCorputBase2(i));
return real2(real(i) / real(sequenceLength), VanDerCorputBase2(i));
static const float2 k_Hammersley2dSeq16[] = {
float2(0.00000000, 0.00000000),
float2(0.06250000, 0.50000000),
float2(0.12500000, 0.25000000),
float2(0.18750000, 0.75000000),
float2(0.25000000, 0.12500000),
float2(0.31250000, 0.62500000),
float2(0.37500000, 0.37500000),
float2(0.43750000, 0.87500000),
float2(0.50000000, 0.06250000),
float2(0.56250000, 0.56250000),
float2(0.62500000, 0.31250000),
float2(0.68750000, 0.81250000),
float2(0.75000000, 0.18750000),
float2(0.81250000, 0.68750000),
float2(0.87500000, 0.43750000),
float2(0.93750000, 0.93750000)
static const real2 k_Hammersley2dSeq16[] = {
real2(0.00000000, 0.00000000),
real2(0.06250000, 0.50000000),
real2(0.12500000, 0.25000000),
real2(0.18750000, 0.75000000),
real2(0.25000000, 0.12500000),
real2(0.31250000, 0.62500000),
real2(0.37500000, 0.37500000),
real2(0.43750000, 0.87500000),
real2(0.50000000, 0.06250000),
real2(0.56250000, 0.56250000),
real2(0.62500000, 0.31250000),
real2(0.68750000, 0.81250000),
real2(0.75000000, 0.18750000),
real2(0.81250000, 0.68750000),
real2(0.87500000, 0.43750000),
real2(0.93750000, 0.93750000)
static const float2 k_Hammersley2dSeq32[] = {
float2(0.00000000, 0.00000000),
float2(0.03125000, 0.50000000),
float2(0.06250000, 0.25000000),
float2(0.09375000, 0.75000000),
float2(0.12500000, 0.12500000),
float2(0.15625000, 0.62500000),
float2(0.18750000, 0.37500000),
float2(0.21875000, 0.87500000),
float2(0.25000000, 0.06250000),
float2(0.28125000, 0.56250000),
float2(0.31250000, 0.31250000),
float2(0.34375000, 0.81250000),
float2(0.37500000, 0.18750000),
float2(0.40625000, 0.68750000),
float2(0.43750000, 0.43750000),
float2(0.46875000, 0.93750000),
float2(0.50000000, 0.03125000),
float2(0.53125000, 0.53125000),
float2(0.56250000, 0.28125000),
float2(0.59375000, 0.78125000),
float2(0.62500000, 0.15625000),
float2(0.65625000, 0.65625000),
float2(0.68750000, 0.40625000),
float2(0.71875000, 0.90625000),
float2(0.75000000, 0.09375000),
float2(0.78125000, 0.59375000),
float2(0.81250000, 0.34375000),
float2(0.84375000, 0.84375000),
float2(0.87500000, 0.21875000),
float2(0.90625000, 0.71875000),
float2(0.93750000, 0.46875000),
float2(0.96875000, 0.96875000)
static const real2 k_Hammersley2dSeq32[] = {
real2(0.00000000, 0.00000000),
real2(0.03125000, 0.50000000),
real2(0.06250000, 0.25000000),
real2(0.09375000, 0.75000000),
real2(0.12500000, 0.12500000),
real2(0.15625000, 0.62500000),
real2(0.18750000, 0.37500000),
real2(0.21875000, 0.87500000),
real2(0.25000000, 0.06250000),
real2(0.28125000, 0.56250000),
real2(0.31250000, 0.31250000),
real2(0.34375000, 0.81250000),
real2(0.37500000, 0.18750000),
real2(0.40625000, 0.68750000),
real2(0.43750000, 0.43750000),
real2(0.46875000, 0.93750000),
real2(0.50000000, 0.03125000),
real2(0.53125000, 0.53125000),
real2(0.56250000, 0.28125000),
real2(0.59375000, 0.78125000),
real2(0.62500000, 0.15625000),
real2(0.65625000, 0.65625000),
real2(0.68750000, 0.40625000),
real2(0.71875000, 0.90625000),
real2(0.75000000, 0.09375000),
real2(0.78125000, 0.59375000),
real2(0.81250000, 0.34375000),
real2(0.84375000, 0.84375000),
real2(0.87500000, 0.21875000),
real2(0.90625000, 0.71875000),
real2(0.93750000, 0.46875000),
real2(0.96875000, 0.96875000)
static const float2 k_Hammersley2dSeq64[] = {
float2(0.00000000, 0.00000000),
float2(0.01562500, 0.50000000),
float2(0.03125000, 0.25000000),
float2(0.04687500, 0.75000000),
float2(0.06250000, 0.12500000),
float2(0.07812500, 0.62500000),
float2(0.09375000, 0.37500000),
float2(0.10937500, 0.87500000),
float2(0.12500000, 0.06250000),
float2(0.14062500, 0.56250000),
float2(0.15625000, 0.31250000),
float2(0.17187500, 0.81250000),
float2(0.18750000, 0.18750000),
float2(0.20312500, 0.68750000),
float2(0.21875000, 0.43750000),
float2(0.23437500, 0.93750000),
float2(0.25000000, 0.03125000),
float2(0.26562500, 0.53125000),
float2(0.28125000, 0.28125000),
float2(0.29687500, 0.78125000),
float2(0.31250000, 0.15625000),
float2(0.32812500, 0.65625000),
float2(0.34375000, 0.40625000),
float2(0.35937500, 0.90625000),
float2(0.37500000, 0.09375000),
float2(0.39062500, 0.59375000),
float2(0.40625000, 0.34375000),
float2(0.42187500, 0.84375000),
float2(0.43750000, 0.21875000),
float2(0.45312500, 0.71875000),
float2(0.46875000, 0.46875000),
float2(0.48437500, 0.96875000),
float2(0.50000000, 0.01562500),
float2(0.51562500, 0.51562500),
float2(0.53125000, 0.26562500),
float2(0.54687500, 0.76562500),
float2(0.56250000, 0.14062500),
float2(0.57812500, 0.64062500),
float2(0.59375000, 0.39062500),
float2(0.60937500, 0.89062500),
float2(0.62500000, 0.07812500),
float2(0.64062500, 0.57812500),
float2(0.65625000, 0.32812500),
float2(0.67187500, 0.82812500),
float2(0.68750000, 0.20312500),
float2(0.70312500, 0.70312500),
float2(0.71875000, 0.45312500),
float2(0.73437500, 0.95312500),
float2(0.75000000, 0.04687500),
float2(0.76562500, 0.54687500),
float2(0.78125000, 0.29687500),
float2(0.79687500, 0.79687500),
float2(0.81250000, 0.17187500),
float2(0.82812500, 0.67187500),
float2(0.84375000, 0.42187500),
float2(0.85937500, 0.92187500),
float2(0.87500000, 0.10937500),
float2(0.89062500, 0.60937500),
float2(0.90625000, 0.35937500),
float2(0.92187500, 0.85937500),
float2(0.93750000, 0.23437500),
float2(0.95312500, 0.73437500),
float2(0.96875000, 0.48437500),
float2(0.98437500, 0.98437500)
static const real2 k_Hammersley2dSeq64[] = {
real2(0.00000000, 0.00000000),
real2(0.01562500, 0.50000000),
real2(0.03125000, 0.25000000),
real2(0.04687500, 0.75000000),
real2(0.06250000, 0.12500000),
real2(0.07812500, 0.62500000),
real2(0.09375000, 0.37500000),
real2(0.10937500, 0.87500000),
real2(0.12500000, 0.06250000),
real2(0.14062500, 0.56250000),
real2(0.15625000, 0.31250000),
real2(0.17187500, 0.81250000),
real2(0.18750000, 0.18750000),
real2(0.20312500, 0.68750000),
real2(0.21875000, 0.43750000),
real2(0.23437500, 0.93750000),
real2(0.25000000, 0.03125000),
real2(0.26562500, 0.53125000),
real2(0.28125000, 0.28125000),
real2(0.29687500, 0.78125000),
real2(0.31250000, 0.15625000),
real2(0.32812500, 0.65625000),
real2(0.34375000, 0.40625000),
real2(0.35937500, 0.90625000),
real2(0.37500000, 0.09375000),
real2(0.39062500, 0.59375000),
real2(0.40625000, 0.34375000),
real2(0.42187500, 0.84375000),
real2(0.43750000, 0.21875000),
real2(0.45312500, 0.71875000),
real2(0.46875000, 0.46875000),
real2(0.48437500, 0.96875000),
real2(0.50000000, 0.01562500),
real2(0.51562500, 0.51562500),
real2(0.53125000, 0.26562500),
real2(0.54687500, 0.76562500),
real2(0.56250000, 0.14062500),
real2(0.57812500, 0.64062500),
real2(0.59375000, 0.39062500),
real2(0.60937500, 0.89062500),
real2(0.62500000, 0.07812500),
real2(0.64062500, 0.57812500),
real2(0.65625000, 0.32812500),
real2(0.67187500, 0.82812500),
real2(0.68750000, 0.20312500),
real2(0.70312500, 0.70312500),
real2(0.71875000, 0.45312500),
real2(0.73437500, 0.95312500),
real2(0.75000000, 0.04687500),
real2(0.76562500, 0.54687500),
real2(0.78125000, 0.29687500),
real2(0.79687500, 0.79687500),
real2(0.81250000, 0.17187500),
real2(0.82812500, 0.67187500),
real2(0.84375000, 0.42187500),
real2(0.85937500, 0.92187500),
real2(0.87500000, 0.10937500),
real2(0.89062500, 0.60937500),
real2(0.90625000, 0.35937500),
real2(0.92187500, 0.85937500),
real2(0.93750000, 0.23437500),
real2(0.95312500, 0.73437500),
real2(0.96875000, 0.48437500),
real2(0.98437500, 0.98437500)
static const float2 k_Hammersley2dSeq256[] = {
float2(0.00000000, 0.00000000),
float2(0.00390625, 0.50000000),
float2(0.00781250, 0.25000000),
float2(0.01171875, 0.75000000),
float2(0.01562500, 0.12500000),
float2(0.01953125, 0.62500000),
float2(0.02343750, 0.37500000),
float2(0.02734375, 0.87500000),
float2(0.03125000, 0.06250000),
float2(0.03515625, 0.56250000),
float2(0.03906250, 0.31250000),
float2(0.04296875, 0.81250000),
float2(0.04687500, 0.18750000),
float2(0.05078125, 0.68750000),
float2(0.05468750, 0.43750000),
float2(0.05859375, 0.93750000),
float2(0.06250000, 0.03125000),
float2(0.06640625, 0.53125000),
float2(0.07031250, 0.28125000),
float2(0.07421875, 0.78125000),
float2(0.07812500, 0.15625000),
float2(0.08203125, 0.65625000),
float2(0.08593750, 0.40625000),
float2(0.08984375, 0.90625000),
float2(0.09375000, 0.09375000),
float2(0.09765625, 0.59375000),
float2(0.10156250, 0.34375000),
float2(0.10546875, 0.84375000),
float2(0.10937500, 0.21875000),
float2(0.11328125, 0.71875000),
float2(0.11718750, 0.46875000),
float2(0.12109375, 0.96875000),
float2(0.12500000, 0.01562500),
float2(0.12890625, 0.51562500),
float2(0.13281250, 0.26562500),
float2(0.13671875, 0.76562500),
float2(0.14062500, 0.14062500),
float2(0.14453125, 0.64062500),
float2(0.14843750, 0.39062500),
float2(0.15234375, 0.89062500),
float2(0.15625000, 0.07812500),
float2(0.16015625, 0.57812500),
float2(0.16406250, 0.32812500),
float2(0.16796875, 0.82812500),
float2(0.17187500, 0.20312500),
float2(0.17578125, 0.70312500),
float2(0.17968750, 0.45312500),
float2(0.18359375, 0.95312500),
float2(0.18750000, 0.04687500),
float2(0.19140625, 0.54687500),
float2(0.19531250, 0.29687500),
float2(0.19921875, 0.79687500),
float2(0.20312500, 0.17187500),
float2(0.20703125, 0.67187500),
float2(0.21093750, 0.42187500),
float2(0.21484375, 0.92187500),
float2(0.21875000, 0.10937500),
float2(0.22265625, 0.60937500),
float2(0.22656250, 0.35937500),
float2(0.23046875, 0.85937500),
float2(0.23437500, 0.23437500),
float2(0.23828125, 0.73437500),
float2(0.24218750, 0.48437500),
float2(0.24609375, 0.98437500),
float2(0.25000000, 0.00781250),
float2(0.25390625, 0.50781250),
float2(0.25781250, 0.25781250),
float2(0.26171875, 0.75781250),
float2(0.26562500, 0.13281250),
float2(0.26953125, 0.63281250),
float2(0.27343750, 0.38281250),
float2(0.27734375, 0.88281250),
float2(0.28125000, 0.07031250),
float2(0.28515625, 0.57031250),
float2(0.28906250, 0.32031250),
float2(0.29296875, 0.82031250),
float2(0.29687500, 0.19531250),
float2(0.30078125, 0.69531250),
float2(0.30468750, 0.44531250),
float2(0.30859375, 0.94531250),
float2(0.31250000, 0.03906250),
float2(0.31640625, 0.53906250),
float2(0.32031250, 0.28906250),
float2(0.32421875, 0.78906250),
float2(0.32812500, 0.16406250),
float2(0.33203125, 0.66406250),
float2(0.33593750, 0.41406250),
float2(0.33984375, 0.91406250),
float2(0.34375000, 0.10156250),
float2(0.34765625, 0.60156250),
float2(0.35156250, 0.35156250),
float2(0.35546875, 0.85156250),
float2(0.35937500, 0.22656250),
float2(0.36328125, 0.72656250),
float2(0.36718750, 0.47656250),
float2(0.37109375, 0.97656250),
float2(0.37500000, 0.02343750),
float2(0.37890625, 0.52343750),
float2(0.38281250, 0.27343750),
float2(0.38671875, 0.77343750),
float2(0.39062500, 0.14843750),
float2(0.39453125, 0.64843750),
float2(0.39843750, 0.39843750),
float2(0.40234375, 0.89843750),
float2(0.40625000, 0.08593750),
float2(0.41015625, 0.58593750),
float2(0.41406250, 0.33593750),
float2(0.41796875, 0.83593750),
float2(0.42187500, 0.21093750),
float2(0.42578125, 0.71093750),
float2(0.42968750, 0.46093750),
float2(0.43359375, 0.96093750),
float2(0.43750000, 0.05468750),
float2(0.44140625, 0.55468750),
float2(0.44531250, 0.30468750),
float2(0.44921875, 0.80468750),
float2(0.45312500, 0.17968750),
float2(0.45703125, 0.67968750),
float2(0.46093750, 0.42968750),
float2(0.46484375, 0.92968750),
float2(0.46875000, 0.11718750),
float2(0.47265625, 0.61718750),
float2(0.47656250, 0.36718750),
float2(0.48046875, 0.86718750),
float2(0.48437500, 0.24218750),
float2(0.48828125, 0.74218750),
float2(0.49218750, 0.49218750),
float2(0.49609375, 0.99218750),
float2(0.50000000, 0.00390625),
float2(0.50390625, 0.50390625),
float2(0.50781250, 0.25390625),
float2(0.51171875, 0.75390625),
float2(0.51562500, 0.12890625),
float2(0.51953125, 0.62890625),
float2(0.52343750, 0.37890625),
float2(0.52734375, 0.87890625),
float2(0.53125000, 0.06640625),
float2(0.53515625, 0.56640625),
float2(0.53906250, 0.31640625),
float2(0.54296875, 0.81640625),
float2(0.54687500, 0.19140625),
float2(0.55078125, 0.69140625),
float2(0.55468750, 0.44140625),
float2(0.55859375, 0.94140625),
float2(0.56250000, 0.03515625),
float2(0.56640625, 0.53515625),
float2(0.57031250, 0.28515625),
float2(0.57421875, 0.78515625),
float2(0.57812500, 0.16015625),
float2(0.58203125, 0.66015625),
float2(0.58593750, 0.41015625),
float2(0.58984375, 0.91015625),
float2(0.59375000, 0.09765625),
float2(0.59765625, 0.59765625),
float2(0.60156250, 0.34765625),
float2(0.60546875, 0.84765625),
float2(0.60937500, 0.22265625),
float2(0.61328125, 0.72265625),
float2(0.61718750, 0.47265625),
float2(0.62109375, 0.97265625),
float2(0.62500000, 0.01953125),
float2(0.62890625, 0.51953125),
float2(0.63281250, 0.26953125),
float2(0.63671875, 0.76953125),
float2(0.64062500, 0.14453125),
float2(0.64453125, 0.64453125),
float2(0.64843750, 0.39453125),
float2(0.65234375, 0.89453125),
float2(0.65625000, 0.08203125),
float2(0.66015625, 0.58203125),
float2(0.66406250, 0.33203125),
float2(0.66796875, 0.83203125),
float2(0.67187500, 0.20703125),
float2(0.67578125, 0.70703125),
float2(0.67968750, 0.45703125),
float2(0.68359375, 0.95703125),
float2(0.68750000, 0.05078125),
float2(0.69140625, 0.55078125),
float2(0.69531250, 0.30078125),
float2(0.69921875, 0.80078125),
float2(0.70312500, 0.17578125),
float2(0.70703125, 0.67578125),
float2(0.71093750, 0.42578125),
float2(0.71484375, 0.92578125),
float2(0.71875000, 0.11328125),
float2(0.72265625, 0.61328125),
float2(0.72656250, 0.36328125),
float2(0.73046875, 0.86328125),
float2(0.73437500, 0.23828125),
float2(0.73828125, 0.73828125),
float2(0.74218750, 0.48828125),
float2(0.74609375, 0.98828125),
float2(0.75000000, 0.01171875),
float2(0.75390625, 0.51171875),
float2(0.75781250, 0.26171875),
float2(0.76171875, 0.76171875),
float2(0.76562500, 0.13671875),
float2(0.76953125, 0.63671875),
float2(0.77343750, 0.38671875),
float2(0.77734375, 0.88671875),
float2(0.78125000, 0.07421875),
float2(0.78515625, 0.57421875),
float2(0.78906250, 0.32421875),
float2(0.79296875, 0.82421875),
float2(0.79687500, 0.19921875),
float2(0.80078125, 0.69921875),
float2(0.80468750, 0.44921875),
float2(0.80859375, 0.94921875),
float2(0.81250000, 0.04296875),
float2(0.81640625, 0.54296875),
float2(0.82031250, 0.29296875),
float2(0.82421875, 0.79296875),
float2(0.82812500, 0.16796875),
float2(0.83203125, 0.66796875),
float2(0.83593750, 0.41796875),
float2(0.83984375, 0.91796875),
float2(0.84375000, 0.10546875),
float2(0.84765625, 0.60546875),
float2(0.85156250, 0.35546875),
float2(0.85546875, 0.85546875),
float2(0.85937500, 0.23046875),
float2(0.86328125, 0.73046875),
float2(0.86718750, 0.48046875),
float2(0.87109375, 0.98046875),
float2(0.87500000, 0.02734375),
float2(0.87890625, 0.52734375),
float2(0.88281250, 0.27734375),
float2(0.88671875, 0.77734375),
float2(0.89062500, 0.15234375),
float2(0.89453125, 0.65234375),
float2(0.89843750, 0.40234375),
float2(0.90234375, 0.90234375),
float2(0.90625000, 0.08984375),
float2(0.91015625, 0.58984375),
float2(0.91406250, 0.33984375),
float2(0.91796875, 0.83984375),
float2(0.92187500, 0.21484375),
float2(0.92578125, 0.71484375),
float2(0.92968750, 0.46484375),
float2(0.93359375, 0.96484375),
float2(0.93750000, 0.05859375),
float2(0.94140625, 0.55859375),
float2(0.94531250, 0.30859375),
float2(0.94921875, 0.80859375),
float2(0.95312500, 0.18359375),
float2(0.95703125, 0.68359375),
float2(0.96093750, 0.43359375),
float2(0.96484375, 0.93359375),
float2(0.96875000, 0.12109375),
float2(0.97265625, 0.62109375),
float2(0.97656250, 0.37109375),
float2(0.98046875, 0.87109375),
float2(0.98437500, 0.24609375),
float2(0.98828125, 0.74609375),
float2(0.99218750, 0.49609375),
float2(0.99609375, 0.99609375)
static const real2 k_Hammersley2dSeq256[] = {
real2(0.00000000, 0.00000000),
real2(0.00390625, 0.50000000),
real2(0.00781250, 0.25000000),
real2(0.01171875, 0.75000000),
real2(0.01562500, 0.12500000),
real2(0.01953125, 0.62500000),
real2(0.02343750, 0.37500000),
real2(0.02734375, 0.87500000),
real2(0.03125000, 0.06250000),
real2(0.03515625, 0.56250000),
real2(0.03906250, 0.31250000),
real2(0.04296875, 0.81250000),
real2(0.04687500, 0.18750000),
real2(0.05078125, 0.68750000),
real2(0.05468750, 0.43750000),
real2(0.05859375, 0.93750000),
real2(0.06250000, 0.03125000),
real2(0.06640625, 0.53125000),
real2(0.07031250, 0.28125000),
real2(0.07421875, 0.78125000),
real2(0.07812500, 0.15625000),
real2(0.08203125, 0.65625000),
real2(0.08593750, 0.40625000),
real2(0.08984375, 0.90625000),
real2(0.09375000, 0.09375000),
real2(0.09765625, 0.59375000),
real2(0.10156250, 0.34375000),
real2(0.10546875, 0.84375000),
real2(0.10937500, 0.21875000),
real2(0.11328125, 0.71875000),
real2(0.11718750, 0.46875000),
real2(0.12109375, 0.96875000),
real2(0.12500000, 0.01562500),
real2(0.12890625, 0.51562500),
real2(0.13281250, 0.26562500),
real2(0.13671875, 0.76562500),
real2(0.14062500, 0.14062500),
real2(0.14453125, 0.64062500),
real2(0.14843750, 0.39062500),
real2(0.15234375, 0.89062500),
real2(0.15625000, 0.07812500),
real2(0.16015625, 0.57812500),
real2(0.16406250, 0.32812500),
real2(0.16796875, 0.82812500),
real2(0.17187500, 0.20312500),
real2(0.17578125, 0.70312500),
real2(0.17968750, 0.45312500),
real2(0.18359375, 0.95312500),
real2(0.18750000, 0.04687500),
real2(0.19140625, 0.54687500),
real2(0.19531250, 0.29687500),
real2(0.19921875, 0.79687500),
real2(0.20312500, 0.17187500),
real2(0.20703125, 0.67187500),
real2(0.21093750, 0.42187500),
real2(0.21484375, 0.92187500),
real2(0.21875000, 0.10937500),
real2(0.22265625, 0.60937500),
real2(0.22656250, 0.35937500),
real2(0.23046875, 0.85937500),
real2(0.23437500, 0.23437500),
real2(0.23828125, 0.73437500),
real2(0.24218750, 0.48437500),
real2(0.24609375, 0.98437500),
real2(0.25000000, 0.00781250),
real2(0.25390625, 0.50781250),
real2(0.25781250, 0.25781250),
real2(0.26171875, 0.75781250),
real2(0.26562500, 0.13281250),
real2(0.26953125, 0.63281250),
real2(0.27343750, 0.38281250),
real2(0.27734375, 0.88281250),
real2(0.28125000, 0.07031250),
real2(0.28515625, 0.57031250),
real2(0.28906250, 0.32031250),
real2(0.29296875, 0.82031250),
real2(0.29687500, 0.19531250),
real2(0.30078125, 0.69531250),
real2(0.30468750, 0.44531250),
real2(0.30859375, 0.94531250),
real2(0.31250000, 0.03906250),
real2(0.31640625, 0.53906250),
real2(0.32031250, 0.28906250),
real2(0.32421875, 0.78906250),
real2(0.32812500, 0.16406250),
real2(0.33203125, 0.66406250),
real2(0.33593750, 0.41406250),
real2(0.33984375, 0.91406250),
real2(0.34375000, 0.10156250),
real2(0.34765625, 0.60156250),
real2(0.35156250, 0.35156250),
real2(0.35546875, 0.85156250),
real2(0.35937500, 0.22656250),
real2(0.36328125, 0.72656250),
real2(0.36718750, 0.47656250),
real2(0.37109375, 0.97656250),
real2(0.37500000, 0.02343750),
real2(0.37890625, 0.52343750),
real2(0.38281250, 0.27343750),
real2(0.38671875, 0.77343750),
real2(0.39062500, 0.14843750),
real2(0.39453125, 0.64843750),
real2(0.39843750, 0.39843750),
real2(0.40234375, 0.89843750),
real2(0.40625000, 0.08593750),
real2(0.41015625, 0.58593750),
real2(0.41406250, 0.33593750),
real2(0.41796875, 0.83593750),
real2(0.42187500, 0.21093750),
real2(0.42578125, 0.71093750),
real2(0.42968750, 0.46093750),
real2(0.43359375, 0.96093750),
real2(0.43750000, 0.05468750),
real2(0.44140625, 0.55468750),
real2(0.44531250, 0.30468750),
real2(0.44921875, 0.80468750),
real2(0.45312500, 0.17968750),
real2(0.45703125, 0.67968750),
real2(0.46093750, 0.42968750),
real2(0.46484375, 0.92968750),
real2(0.46875000, 0.11718750),
real2(0.47265625, 0.61718750),
real2(0.47656250, 0.36718750),
real2(0.48046875, 0.86718750),
real2(0.48437500, 0.24218750),
real2(0.48828125, 0.74218750),
real2(0.49218750, 0.49218750),
real2(0.49609375, 0.99218750),
real2(0.50000000, 0.00390625),
real2(0.50390625, 0.50390625),
real2(0.50781250, 0.25390625),
real2(0.51171875, 0.75390625),
real2(0.51562500, 0.12890625),
real2(0.51953125, 0.62890625),
real2(0.52343750, 0.37890625),
real2(0.52734375, 0.87890625),
real2(0.53125000, 0.06640625),
real2(0.53515625, 0.56640625),
real2(0.53906250, 0.31640625),
real2(0.54296875, 0.81640625),
real2(0.54687500, 0.19140625),
real2(0.55078125, 0.69140625),
real2(0.55468750, 0.44140625),
real2(0.55859375, 0.94140625),
real2(0.56250000, 0.03515625),
real2(0.56640625, 0.53515625),
real2(0.57031250, 0.28515625),
real2(0.57421875, 0.78515625),
real2(0.57812500, 0.16015625),
real2(0.58203125, 0.66015625),
real2(0.58593750, 0.41015625),
real2(0.58984375, 0.91015625),
real2(0.59375000, 0.09765625),
real2(0.59765625, 0.59765625),
real2(0.60156250, 0.34765625),
real2(0.60546875, 0.84765625),
real2(0.60937500, 0.22265625),
real2(0.61328125, 0.72265625),
real2(0.61718750, 0.47265625),
real2(0.62109375, 0.97265625),
real2(0.62500000, 0.01953125),
real2(0.62890625, 0.51953125),
real2(0.63281250, 0.26953125),
real2(0.63671875, 0.76953125),
real2(0.64062500, 0.14453125),
real2(0.64453125, 0.64453125),
real2(0.64843750, 0.39453125),
real2(0.65234375, 0.89453125),
real2(0.65625000, 0.08203125),
real2(0.66015625, 0.58203125),
real2(0.66406250, 0.33203125),
real2(0.66796875, 0.83203125),
real2(0.67187500, 0.20703125),
real2(0.67578125, 0.70703125),
real2(0.67968750, 0.45703125),
real2(0.68359375, 0.95703125),
real2(0.68750000, 0.05078125),
real2(0.69140625, 0.55078125),
real2(0.69531250, 0.30078125),
real2(0.69921875, 0.80078125),
real2(0.70312500, 0.17578125),
real2(0.70703125, 0.67578125),
real2(0.71093750, 0.42578125),
real2(0.71484375, 0.92578125),
real2(0.71875000, 0.11328125),
real2(0.72265625, 0.61328125),
real2(0.72656250, 0.36328125),
real2(0.73046875, 0.86328125),
real2(0.73437500, 0.23828125),
real2(0.73828125, 0.73828125),
real2(0.74218750, 0.48828125),
real2(0.74609375, 0.98828125),
real2(0.75000000, 0.01171875),
real2(0.75390625, 0.51171875),
real2(0.75781250, 0.26171875),
real2(0.76171875, 0.76171875),
real2(0.76562500, 0.13671875),
real2(0.76953125, 0.63671875),
real2(0.77343750, 0.38671875),
real2(0.77734375, 0.88671875),
real2(0.78125000, 0.07421875),
real2(0.78515625, 0.57421875),
real2(0.78906250, 0.32421875),
real2(0.79296875, 0.82421875),
real2(0.79687500, 0.19921875),
real2(0.80078125, 0.69921875),
real2(0.80468750, 0.44921875),
real2(0.80859375, 0.94921875),
real2(0.81250000, 0.04296875),
real2(0.81640625, 0.54296875),
real2(0.82031250, 0.29296875),
real2(0.82421875, 0.79296875),
real2(0.82812500, 0.16796875),
real2(0.83203125, 0.66796875),
real2(0.83593750, 0.41796875),
real2(0.83984375, 0.91796875),
real2(0.84375000, 0.10546875),
real2(0.84765625, 0.60546875),
real2(0.85156250, 0.35546875),
real2(0.85546875, 0.85546875),
real2(0.85937500, 0.23046875),
real2(0.86328125, 0.73046875),
real2(0.86718750, 0.48046875),
real2(0.87109375, 0.98046875),
real2(0.87500000, 0.02734375),
real2(0.87890625, 0.52734375),
real2(0.88281250, 0.27734375),
real2(0.88671875, 0.77734375),
real2(0.89062500, 0.15234375),
real2(0.89453125, 0.65234375),
real2(0.89843750, 0.40234375),
real2(0.90234375, 0.90234375),
real2(0.90625000, 0.08984375),
real2(0.91015625, 0.58984375),
real2(0.91406250, 0.33984375),
real2(0.91796875, 0.83984375),
real2(0.92187500, 0.21484375),
real2(0.92578125, 0.71484375),
real2(0.92968750, 0.46484375),
real2(0.93359375, 0.96484375),
real2(0.93750000, 0.05859375),
real2(0.94140625, 0.55859375),
real2(0.94531250, 0.30859375),
real2(0.94921875, 0.80859375),
real2(0.95312500, 0.18359375),
real2(0.95703125, 0.68359375),
real2(0.96093750, 0.43359375),
real2(0.96484375, 0.93359375),
real2(0.96875000, 0.12109375),
real2(0.97265625, 0.62109375),
real2(0.97656250, 0.37109375),
real2(0.98046875, 0.87109375),
real2(0.98437500, 0.24609375),
real2(0.98828125, 0.74609375),
real2(0.99218750, 0.49609375),
real2(0.99609375, 0.99609375)
float2 Hammersley2d(uint i, uint sampleCount)
real2 Hammersley2d(uint i, uint sampleCount)
{
switch (sampleCount)
{

6
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Sampling/SampleUVMappingInternal.hlsl


// Also we use multiple inclusion to handle the various variation for lod and bias
// param can be unused, lod or bias
float4 ADD_FUNC_SUFFIX(SampleUVMapping)(TEXTURE2D_ARGS(textureName, samplerName), UVMapping uvMapping, float param)
real4 ADD_FUNC_SUFFIX(SampleUVMapping)(TEXTURE2D_ARGS(textureName, samplerName), UVMapping uvMapping, real param)
float3 triplanarWeights = uvMapping.triplanarWeights;
float4 val = float4(0.0, 0.0, 0.0, 0.0);
real3 triplanarWeights = uvMapping.triplanarWeights;
real4 val = real4(0.0, 0.0, 0.0, 0.0);
if (triplanarWeights.x > 0.0)
val += triplanarWeights.x * SAMPLE_TEXTURE_FUNC(textureName, samplerName, uvMapping.uvZY, param);

22
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Sampling/SampleUVMappingNormalInternal.hlsl


float3 ADD_FUNC_SUFFIX(ADD_NORMAL_FUNC_SUFFIX(SampleUVMappingNormal))(TEXTURE2D_ARGS(textureName, samplerName), UVMapping uvMapping, float scale, float param)
real3 ADD_FUNC_SUFFIX(ADD_NORMAL_FUNC_SUFFIX(SampleUVMappingNormal))(TEXTURE2D_ARGS(textureName, samplerName), UVMapping uvMapping, real scale, real param)
float3 triplanarWeights = uvMapping.triplanarWeights;
real3 triplanarWeights = uvMapping.triplanarWeights;
float2 derivXplane;
float2 derivYPlane;
float2 derivZPlane;
derivXplane = derivYPlane = derivZPlane = float2(0.0, 0.0);
real2 derivXplane;
real2 derivYPlane;
real2 derivZPlane;
derivXplane = derivYPlane = derivZPlane = real2(0.0, 0.0);
if (triplanarWeights.x > 0.0)
derivXplane = triplanarWeights.x * UNPACK_DERIVATIVE_FUNC(SAMPLE_TEXTURE_FUNC(textureName, samplerName, uvMapping.uvZY, param), scale);

// Assume derivXplane, derivYPlane and derivZPlane sampled using (z,y), (z,x) and (x,y) respectively.
// TODO: Check with morten convention! Do it follow ours ?
float3 volumeGrad = float3(derivZPlane.x + derivYPlane.y, derivZPlane.y + derivXplane.y, derivXplane.x + derivYPlane.x);
real3 volumeGrad = real3(derivZPlane.x + derivYPlane.y, derivZPlane.y + derivXplane.y, derivXplane.x + derivYPlane.x);
float3 val = float3(0.0, 0.0, 0.0);
real3 val = real3(0.0, 0.0, 0.0);
if (triplanarWeights.x > 0.0)
val += triplanarWeights.x * UNPACK_NORMAL_FUNC(SAMPLE_TEXTURE_FUNC(textureName, samplerName, uvMapping.uvZY, param), scale);

else if (uvMapping.mappingType == UV_MAPPING_PLANAR)
{
// Note: Planar is on uv coordinate (and not uvXZ)
float2 derivYPlane = UNPACK_DERIVATIVE_FUNC(SAMPLE_TEXTURE_FUNC(textureName, samplerName, uvMapping.uv, param), scale);
real2 derivYPlane = UNPACK_DERIVATIVE_FUNC(SAMPLE_TEXTURE_FUNC(textureName, samplerName, uvMapping.uv, param), scale);
float3 volumeGrad = float3(derivYPlane.y, 0.0, derivYPlane.x);
real3 volumeGrad = real3(derivYPlane.y, 0.0, derivYPlane.x);
return SurfaceGradientFromVolumeGradient(uvMapping.normalWS, volumeGrad);
}
#endif

float2 deriv = UNPACK_DERIVATIVE_FUNC(SAMPLE_TEXTURE_FUNC(textureName, samplerName, uvMapping.uv, param), scale);
real2 deriv = UNPACK_DERIVATIVE_FUNC(SAMPLE_TEXTURE_FUNC(textureName, samplerName, uvMapping.uv, param), scale);
return SurfaceGradientFromTBN(deriv, uvMapping.tangentWS, uvMapping.bitangentWS);
#else
return UNPACK_NORMAL_FUNC(SAMPLE_TEXTURE_FUNC(textureName, samplerName, uvMapping.uv, param), scale);

220
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Sampling/Sampling.hlsl


#include "Fibonacci.hlsl"
#include "Hammersley.hlsl"
float Hash(uint s)
{
s = s ^ 2747636419u;
s = s * 2654435769u;
s = s ^ (s >> 16);
s = s * 2654435769u;
s = s ^ (s >> 16);
s = s * 2654435769u;
return float(s) / 4294967295.0;
}
float2 InitRandom(float2 input)
{
float2 r;
r.x = Hash(uint(input.x * 4294967295.0));
r.y = Hash(uint(input.y * 4294967295.0));
return r;
}
float3 SphericalToCartesian(float phi, float cosTheta)
real3 SphericalToCartesian(real phi, real cosTheta)
float sinPhi, cosPhi;
real sinPhi, cosPhi;
float sinTheta = sqrt(saturate(1.0 - cosTheta * cosTheta));
real sinTheta = sqrt(saturate(1.0 - cosTheta * cosTheta));
return float3(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta);
return real3(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta);
float3 TransformGLtoDX(float3 v)
real3 TransformGLtoDX(real3 v)
float3 ConvertEquiarealToCubemap(float u, float v)
real3 ConvertEquiarealToCubemap(real u, real v)
float phi = TWO_PI - TWO_PI * u;
float cosTheta = 1.0 - 2.0 * v;
real phi = TWO_PI - TWO_PI * u;
real cosTheta = 1.0 - 2.0 * v;
float2 CubemapTexelToNVC(uint2 unPositionTXS, uint cubemapSize)
real2 CubemapTexelToNVC(uint2 unPositionTXS, uint cubemapSize)
return 2.0 * float2(unPositionTXS) / float(max(cubemapSize - 1, 1)) - 1.0;
return 2.0 * real2(unPositionTXS) / real(max(cubemapSize - 1, 1)) - 1.0;
static const float3 CUBEMAP_FACE_BASIS_MAPPING[6][3] =
static const real3 CUBEMAP_FACE_BASIS_MAPPING[6][3] =
float3(0.0, 0.0, -1.0),
float3(0.0, -1.0, 0.0),
float3(1.0, 0.0, 0.0)
real3(0.0, 0.0, -1.0),
real3(0.0, -1.0, 0.0),
real3(1.0, 0.0, 0.0)
float3(0.0, 0.0, 1.0),
float3(0.0, -1.0, 0.0),
float3(-1.0, 0.0, 0.0)
real3(0.0, 0.0, 1.0),
real3(0.0, -1.0, 0.0),
real3(-1.0, 0.0, 0.0)
float3(1.0, 0.0, 0.0),
float3(0.0, 0.0, 1.0),
float3(0.0, 1.0, 0.0)
real3(1.0, 0.0, 0.0),
real3(0.0, 0.0, 1.0),
real3(0.0, 1.0, 0.0)
float3(1.0, 0.0, 0.0),
float3(0.0, 0.0, -1.0),
float3(0.0, -1.0, 0.0)
real3(1.0, 0.0, 0.0),
real3(0.0, 0.0, -1.0),
real3(0.0, -1.0, 0.0)
float3(1.0, 0.0, 0.0),
float3(0.0, -1.0, 0.0),
float3(0.0, 0.0, 1.0)
real3(1.0, 0.0, 0.0),
real3(0.0, -1.0, 0.0),
real3(0.0, 0.0, 1.0)
float3(-1.0, 0.0, 0.0),
float3(0.0, -1.0, 0.0),
float3(0.0, 0.0, -1.0)
real3(-1.0, 0.0, 0.0),
real3(0.0, -1.0, 0.0),
real3(0.0, 0.0, -1.0)
float3 CubemapTexelToDirection(float2 positionNVC, uint faceId)
real3 CubemapTexelToDirection(real2 positionNVC, uint faceId)
float3 dir = CUBEMAP_FACE_BASIS_MAPPING[faceId][0] * positionNVC.x
real3 dir = CUBEMAP_FACE_BASIS_MAPPING[faceId][0] * positionNVC.x
+ CUBEMAP_FACE_BASIS_MAPPING[faceId][1] * positionNVC.y
+ CUBEMAP_FACE_BASIS_MAPPING[faceId][2];

// Performs uniform sampling of the unit disk.
// Ref: PBRT v3, p. 777.
float2 SampleDiskUniform(float u1, float u2)
real2 SampleDiskUniform(real u1, real u2)
float r = sqrt(u1);
float phi = TWO_PI * u2;
real r = sqrt(u1);
real phi = TWO_PI * u2;
float sinPhi, cosPhi;
real sinPhi, cosPhi;
return r * float2(cosPhi, sinPhi);
return r * real2(cosPhi, sinPhi);
float3 SampleHemisphereCosine(float u1, float u2)
real3 SampleHemisphereCosine(real u1, real u2)
float3 localL;
real3 localL;
// Since we don't really care about the area distortion,
// we substitute uniform disk sampling for the concentric one.

return localL;
}
float3 SampleHemisphereUniform(float u1, float u2)
real3 SampleHemisphereUniform(real u1, real u2)
float phi = TWO_PI * u2;
float cosTheta = 1.0 - u1;
real phi = TWO_PI * u2;
real cosTheta = 1.0 - u1;
float3 SampleSphereUniform(float u1, float u2)
real3 SampleSphereUniform(real u1, real u2)
float phi = TWO_PI * u2;
float cosTheta = 1.0 - 2.0 * u1;
real phi = TWO_PI * u2;
real cosTheta = 1.0 - 2.0 * u1;
void SampleSphere( float2 u,
float4x4 localToWorld,
float radius,
out float lightPdf,
out float3 P,
out float3 Ns)
void SampleSphere(real2 u,
real4x4 localToWorld,
real radius,
out real lightPdf,
out real3 P,
out real3 Ns)
float u1 = u.x;
float u2 = u.y;
real u1 = u.x;
real u2 = u.y;
Ns = SampleSphereUniform(u1, u2);

lightPdf = 1.0 / (FOUR_PI * radius * radius);
}
void SampleHemisphere( float2 u,
float4x4 localToWorld,
float radius,
out float lightPdf,
out float3 P,
out float3 Ns)
void SampleHemisphere(real2 u,
real4x4 localToWorld,
real radius,
out real lightPdf,
out real3 P,
out real3 Ns)
float u1 = u.x;
float u2 = u.y;
real u1 = u.x;
real u2 = u.y;
// Random point at hemisphere surface
Ns = -SampleHemisphereUniform(u1, u2); // We want the y down hemisphere

P = mul(float4(P, 1.0), localToWorld).xyz;
Ns = mul(Ns, (float3x3)(localToWorld));
P = mul(real4(P, 1.0), localToWorld).xyz;
Ns = mul(Ns, (real3x3)(localToWorld));
// pdf is inverse of area
lightPdf = 1.0 / (TWO_PI * radius * radius);

void SampleCylinder(float2 u,
float4x4 localToWorld,
float radius,
float width,
out float lightPdf,
out float3 P,
out float3 Ns)
void SampleCylinder(real2 u,
real4x4 localToWorld,
real radius,
real width,
out real lightPdf,
out real3 P,
out real3 Ns)
float u1 = u.x;
float u2 = u.y;
real u1 = u.x;
real u2 = u.y;
float t = (u1 - 0.5) * width;
float theta = 2.0 * PI * u2;
float cosTheta = cos(theta);
float sinTheta = sin(theta);
real t = (u1 - 0.5) * width;
real theta = 2.0 * PI * u2;
real cosTheta = cos(theta);
real sinTheta = sin(theta);
P = float3(t, radius * cosTheta, radius * sinTheta);
Ns = normalize(float3(0.0, cosTheta, sinTheta));
P = real3(t, radius * cosTheta, radius * sinTheta);
Ns = normalize(real3(0.0, cosTheta, sinTheta));
P = mul(float4(P, 1.0), localToWorld).xyz;
Ns = mul(Ns, (float3x3)(localToWorld));
P = mul(real4(P, 1.0), localToWorld).xyz;
Ns = mul(Ns, (real3x3)(localToWorld));
void SampleRectangle( float2 u,
float4x4 localToWorld,
float width,
float height,
out float lightPdf,
out float3 P,
out float3 Ns)
void SampleRectangle(real2 u,
real4x4 localToWorld,
real width,
real height,
out real lightPdf,
out real3 P,
out real3 Ns)
P = float3((u.x - 0.5) * width, (u.y - 0.5) * height, 0);
Ns = float3(0, 0, -1); // Light point backward (-Z)
P = real3((u.x - 0.5) * width, (u.y - 0.5) * height, 0);
Ns = real3(0, 0, -1); // Light point backward (-Z)
P = mul(float4(P, 1.0), localToWorld).xyz;
Ns = mul(Ns, (float3x3)(localToWorld));
P = mul(real4(P, 1.0), localToWorld).xyz;
Ns = mul(Ns, (real3x3)(localToWorld));
void SampleDisk(float2 u,
float4x4 localToWorld,
float radius,
out float lightPdf,
out float3 P,
out float3 Ns)
void SampleDisk(real2 u,
real4x4 localToWorld,
real radius,
out real lightPdf,
out real3 P,
out real3 Ns)
P = float3(radius * SampleDiskUniform(u.x, u.y), 0);
Ns = float3(0.0, 0.0, -1.0); // Light point backward (-Z)
P = real3(radius * SampleDiskUniform(u.x, u.y), 0);
Ns = real3(0.0, 0.0, -1.0); // Light point backward (-Z)
P = mul(float4(P, 1.0), localToWorld).xyz;
Ns = mul(Ns, (float3x3)(localToWorld));
P = mul(real4(P, 1.0), localToWorld).xyz;
Ns = mul(Ns, (real3x3)(localToWorld));
// pdf is inverse of area
lightPdf = 1.0 / (PI * radius * radius);

24
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/Shadow.hlsl


SHADOW_DEFINE_SAMPLING_FUNCS( SHADOWCONTEXT_MAX_TEX2DARRAY, SHADOWCONTEXT_MAX_TEXCUBEARRAY, SHADOWCONTEXT_MAX_COMPSAMPLER, SHADOWCONTEXT_MAX_SAMPLER )
// helper function to extract shadowmap data from the ShadowData struct
void UnpackShadowmapId( uint shadowmapId, out uint texIdx, out uint sampIdx, out float slice )
void UnpackShadowmapId( uint shadowmapId, out uint texIdx, out uint sampIdx, out real slice )
slice = (float)(shadowmapId & 0xffff);
slice = (real)(shadowmapId & 0xffff);
}
void UnpackShadowmapId( uint shadowmapId, out uint texIdx, out uint sampIdx )
{

void UnpackShadowmapId( uint shadowmapId, out float slice )
void UnpackShadowmapId( uint shadowmapId, out real slice )
slice = (float)(shadowmapId & 0xffff);
slice = (real)(shadowmapId & 0xffff);
}
void UnpackShadowType( uint packedShadowType, out uint shadowType, out uint shadowAlgorithm )

}
// shadow sampling prototypes
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 positionSS );
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real4 L );
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real4 L, real2 positionSS );
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L );
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 positionSS );
real GetDirectionalShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real3 L );
real GetDirectionalShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real3 L, real2 positionSS );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real4 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 positionSS )
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real4 L, real2 positionSS )
{
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L );
}

float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L )
real GetDirectionalShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real3 L )
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 positionSS )
real GetDirectionalShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real3 L, real2 positionSS )
{
return GetDirectionalShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L );
}

320
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl


// Helper function to offset depth based on the surface normal and light direction.
// If the light hits the surface perpendicularly there will be no offset.
float3 EvalShadow_NormalBias( float3 normalWS, float NoL, float2 texelSize, float normalBias )
real3 EvalShadow_NormalBias( real3 normalWS, real NoL, real2 texelSize, real normalBias )
float3 EvalShadow_GetTexcoords( ShadowData sd, float3 positionWS, out float3 posNDC, bool clampToRect )
real3 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, out real3 posNDC, bool clampToRect )
float4 posCS = mul(float4(positionWS, 1.0), sd.worldToShadow);
real4 posCS = mul(real4(positionWS, 1.0), sd.worldToShadow);
float3 posTC = posNDC * 0.5 + 0.5;
real3 posTC = posNDC * 0.5 + 0.5;
posTC.xy = clampToRect ? clamp( posTC.xy, sd.texelSizeRcp.zw*0.5, 1.0.xx - sd.texelSizeRcp.zw*0.5 ) : posTC.xy;
posTC.xy = posTC.xy * sd.scaleOffset.xy + sd.scaleOffset.zw;
#if UNITY_REVERSED_Z

}
float3 EvalShadow_GetTexcoords( ShadowData sd, float3 positionWS )
real3 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS )
float3 ndc;
real3 ndc;
uint2 EvalShadow_GetTexcoords( ShadowData sd, float3 positionWS, out float2 closestSampleNDC )
uint2 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, out real2 closestSampleNDC )
float4 posCS = mul( float4( positionWS, 1.0 ), sd.worldToShadow );
float2 posNDC = posCS.xy / posCS.w;
real4 posCS = mul( real4( positionWS, 1.0 ), sd.worldToShadow );
real2 posNDC = posCS.xy / posCS.w;
float2 posTC = posNDC * 0.5 + 0.5;
real2 posTC = posNDC * 0.5 + 0.5;
int EvalShadow_GetCubeFaceID( float3 dir )
int EvalShadow_GetCubeFaceID( real3 dir )
float3 adir = abs(dir);
real3 adir = abs(dir);
// +Z -Z
int faceIndex = dir.z > 0.0 ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;

//
// Point shadows
//
float EvalShadow_PointDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float4 L )
real EvalShadow_PointDepth( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real4 L )
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
float3 lpos = positionWS + L.xyz * L.w;
real3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
real3 lpos = positionWS + L.xyz * L.w;
positionWS = biased_posWS;
int faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1;
// load the right shadow data for the current face

positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
// get shadowmap texcoords
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
float slice;
real slice;
float EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float4 L ) \
real EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real4 L ) \
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
float3 lpos = positionWS + L.xyz * L.w; \
real3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
real3 lpos = positionWS + L.xyz * L.w; \
positionWS = biased_posWS; \
int faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1; \
/* load the right shadow data for the current face */ \

positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
float slice; \
real slice; \
UnpackShadowmapId( sd.id, slice ); \
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \
}

//
// Spot shadows
//
float EvalShadow_SpotDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L )
real EvalShadow_SpotDepth( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real3 L )
{
// load the right shadow data for the current face
ShadowData sd = shadowContext.shadowDatas[index];

// get shadowmap texcoords
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
float slice;
real slice;
float EvalShadow_SpotDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
real EvalShadow_SpotDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \
{ \
/* load the right shadow data for the current face */ \
ShadowData sd = shadowContext.shadowDatas[index]; \

/* get shadowmap texcoords */ \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
float slice; \
real slice; \
UnpackShadowmapId( sd.id, slice ); \
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \
}

//
// Punctual shadows for Point and Spot
//
float EvalShadow_PunctualDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float4 L )
real EvalShadow_PunctualDepth( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real4 L )
{
// load the right shadow data for the current face
int faceIndex = 0;

[branch]
if( shadowType == GPUSHADOWTYPE_POINT )
{
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
float3 lpos = positionWS + L.xyz * L.w;
real3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
real3 lpos = positionWS + L.xyz * L.w;
positionWS = biased_posWS;
faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1;
}

sd = shadowContext.shadowDatas[index + faceIndex];
uint payloadOffset = GetPayloadOffset( sd );
// get shadowmap texcoords
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
float slice;
real slice;
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice );
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );

float EvalShadow_PunctualDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float4 L ) \
real EvalShadow_PunctualDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real4 L ) \
{ \
/* load the right shadow data for the current face */ \
int faceIndex = 0; \

[branch] \
if( shadowType == GPUSHADOWTYPE_POINT ) \
{ \
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
float3 lpos = positionWS + L.xyz * L.w; \
real3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
real3 lpos = positionWS + L.xyz * L.w; \
positionWS = biased_posWS; \
faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1; \
} \

sd = shadowContext.shadowDatas[index + faceIndex]; \
uint payloadOffset = GetPayloadOffset( sd ); \
/* get shadowmap texcoords */ \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
float slice; \
real slice; \
UnpackShadowmapId( sd.id, slice ); \
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \
}

#define kMaxShadowCascades 4
#define SHADOW_REPEAT_CASCADE( _x ) _x, _x, _x, _x
int EvalShadow_GetSplitSphereIndexForDirshadows( float3 positionWS, float4 dirShadowSplitSpheres[4], out float relDistance )
int EvalShadow_GetSplitSphereIndexForDirshadows( real3 positionWS, real4 dirShadowSplitSpheres[4], out real relDistance )
float3 fromCenter0 = positionWS.xyz - dirShadowSplitSpheres[0].xyz;
float3 fromCenter1 = positionWS.xyz - dirShadowSplitSpheres[1].xyz;
float3 fromCenter2 = positionWS.xyz - dirShadowSplitSpheres[2].xyz;
float3 fromCenter3 = positionWS.xyz - dirShadowSplitSpheres[3].xyz;
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
real3 fromCenter0 = positionWS.xyz - dirShadowSplitSpheres[0].xyz;
real3 fromCenter1 = positionWS.xyz - dirShadowSplitSpheres[1].xyz;
real3 fromCenter2 = positionWS.xyz - dirShadowSplitSpheres[2].xyz;
real3 fromCenter3 = positionWS.xyz - dirShadowSplitSpheres[3].xyz;
real4 distances2 = real4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
float4 dirShadowSplitSphereSqRadii;
real4 dirShadowSplitSphereSqRadii;
float4 weights = float4( distances2 < dirShadowSplitSphereSqRadii );
real4 weights = real4( distances2 < dirShadowSplitSphereSqRadii );
int idx = int( 4.0 - dot( weights, float4( 4.0, 3.0, 2.0, 1.0 ) ) );
int idx = int( 4.0 - dot( weights, real4( 4.0, 3.0, 2.0, 1.0 ) ) );
int EvalShadow_GetSplitSphereIndexForDirshadows( float3 positionWS, float4 dirShadowSplitSpheres[4] )
int EvalShadow_GetSplitSphereIndexForDirshadows( real3 positionWS, real4 dirShadowSplitSpheres[4] )
float relDist;
real relDist;
uint EvalShadow_LoadSplitSpheres( ShadowContext shadowContext, int index, out float4 splitSpheres[4] )
uint EvalShadow_LoadSplitSpheres( ShadowContext shadowContext, int index, out real4 splitSpheres[4] )
{
uint offset = GetPayloadOffset( shadowContext.shadowDatas[index] );

return offset + 4;
}
float EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L )
real EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real3 L )
float4 dirShadowSplitSpheres[4];
real4 dirShadowSplitSpheres[4];
float relDistance;
real relDistance;
float4 scales = asfloat( shadowContext.payloads[payloadOffset] );
real4 scales = asfloat( shadowContext.payloads[payloadOffset] );
float4 borders = asfloat( shadowContext.payloads[payloadOffset] );
real4 borders = asfloat( shadowContext.payloads[payloadOffset] );
float border = borders[shadowSplitIndex];
float alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border );
real border = borders[shadowSplitIndex];
real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border );
float3 orig_pos = positionWS;
real3 orig_pos = positionWS;
float3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz;
float3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[min( shadowSplitIndex+1, kMaxShadowCascades-1 )].xyz );
float3 wposDir = normalize( -splitSphere + positionWS );
float cascDot = dot( cascadeDir, wposDir );
real3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz;
real3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[min( shadowSplitIndex+1, kMaxShadowCascades-1 )].xyz );
real3 wposDir = normalize( -splitSphere + positionWS );
real cascDot = dot( cascadeDir, wposDir );
float3 posNDC;
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true );
real3 posNDC;
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true );
float slice;
real slice;
float shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
float shadow1 = 1.0;
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
real shadow1 = 1.0;
shadowSplitIndex++;
if( shadowSplitIndex < kMaxShadowCascades )

}
#define EvalShadow_CascadedDepth_( _samplerType ) \
float EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, uint shadowAlgorithms[kMaxShadowCascades], Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
real EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, uint shadowAlgorithms[kMaxShadowCascades], Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \
float4 dirShadowSplitSpheres[kMaxShadowCascades]; \
real4 dirShadowSplitSpheres[kMaxShadowCascades]; \
float relDistance; \
real relDistance; \
float4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \
real4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \
float4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \
real4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \
float border = borders[shadowSplitIndex]; \
float alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \
real border = borders[shadowSplitIndex]; \
real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \
float3 orig_pos = positionWS; \
real3 orig_pos = positionWS; \
float3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz; \
float3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[min( shadowSplitIndex+1, kMaxShadowCascades-1 )].xyz ); \
float3 wposDir = normalize( -splitSphere + positionWS ); \
float cascDot = dot( cascadeDir, wposDir ); \
real3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz; \
real3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[min( shadowSplitIndex+1, kMaxShadowCascades-1 )].xyz ); \
real3 wposDir = normalize( -splitSphere + positionWS ); \
real cascDot = dot( cascadeDir, wposDir ); \
float3 posNDC; \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true ); \
real3 posNDC; \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true ); \
float slice; \
real slice; \
float shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
float shadow1 = 1.0; \
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
real shadow1 = 1.0; \
\
shadowSplitIndex++; \
if( shadowSplitIndex < kMaxShadowCascades ) \

return shadow; \
} \
\
float EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
real EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \
{ \
uint shadowAlgorithms[kMaxShadowCascades] = { SHADOW_REPEAT_CASCADE( shadowAlgorithm ) }; \
return EvalShadow_CascadedDepth_Blend( shadowContext, shadowAlgorithms, tex, samp, positionWS, normalWS, index, L ); \

#undef EvalShadow_CascadedDepth_
float EvalShadow_hash12( float2 pos )
real EvalShadow_hash12( real2 pos )
float3 p3 = frac( pos.xyx * float3( 443.8975, 397.2973, 491.1871 ) );
real3 p3 = frac( pos.xyx * real3( 443.8975, 397.2973, 491.1871 ) );
float EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L )
real EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real3 L )
float4 dirShadowSplitSpheres[kMaxShadowCascades];
real4 dirShadowSplitSpheres[kMaxShadowCascades];
float relDistance;
real relDistance;
float4 scales = asfloat( shadowContext.payloads[payloadOffset] );
real4 scales = asfloat( shadowContext.payloads[payloadOffset] );
float4 borders = asfloat( shadowContext.payloads[payloadOffset] );
real4 borders = asfloat( shadowContext.payloads[payloadOffset] );
float border = borders[shadowSplitIndex];
float alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border );
real border = borders[shadowSplitIndex];
real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border );
float3 orig_pos = positionWS;
real3 orig_pos = positionWS;
float3 posNDC;
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true );
real3 posNDC;
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true );
float3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz;
float3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[min( 3, shadowSplitIndex + 1 )].xyz );
float3 wposDir = normalize( -splitSphere + positionWS );
float cascDot = dot( cascadeDir, wposDir );
real3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz;
real3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[min( 3, shadowSplitIndex + 1 )].xyz );
real3 wposDir = normalize( -splitSphere + positionWS );
real cascDot = dot( cascadeDir, wposDir );
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) );
if( shadowSplitIndex < nextSplit && step( EvalShadow_hash12( posTC.xy ), alpha ) )

}
// sample the texture
uint texIdx, sampIdx;
float slice;
real slice;
float shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
float EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, uint shadowAlgorithms[kMaxShadowCascades], Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
real EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, uint shadowAlgorithms[kMaxShadowCascades], Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \
float4 dirShadowSplitSpheres[kMaxShadowCascades]; \
real4 dirShadowSplitSpheres[kMaxShadowCascades]; \
float relDistance; \
real relDistance; \
float4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \
real4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \
float4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \
real4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \
float border = borders[shadowSplitIndex]; \
float alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \
real border = borders[shadowSplitIndex]; \
real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \
float3 orig_pos = positionWS; \
real3 orig_pos = positionWS; \
float3 posNDC; \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true ); \
real3 posNDC; \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true ); \
float3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz; \
float3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[nextSplit].xyz ); \
float3 wposDir = normalize( -splitSphere + positionWS ); \
float cascDot = dot( cascadeDir, wposDir ); \
real3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz; \
real3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[nextSplit].xyz ); \
real3 wposDir = normalize( -splitSphere + positionWS ); \
real cascDot = dot( cascadeDir, wposDir ); \
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) ); \
\
if( shadowSplitIndex != nextSplit && step( EvalShadow_hash12( posTC.xy ), alpha ) ) \

posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
} \
/* sample the texture */ \
float slice; \
real slice; \
float shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
float EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
real EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \
{ \
uint shadowAlgorithms[kMaxShadowCascades] = { SHADOW_REPEAT_CASCADE( shadowAlgorithm ) }; \
return EvalShadow_CascadedDepth_Dither( shadowContext, shadowAlgorithms, tex, samp, positionWS, normalWS, index, L ); \

//------------------------------------------------------------------------------------------------------------------------------------
float3 EvalShadow_GetClosestSample_Point( ShadowContext shadowContext, float3 positionWS, int index, float3 L )
real3 EvalShadow_GetClosestSample_Point( ShadowContext shadowContext, real3 positionWS, int index, real3 L )
{
// get the algorithm
ShadowData sd = shadowContext.shadowDatas[index];

float4 closestNDC = { 0,0,0,1 };
real4 closestNDC = { 0,0,0,1 };
float slice;
real slice;
float4 closestWS = mul( closestNDC, sd.shadowToWorld );
real4 closestWS = mul( closestNDC, sd.shadowToWorld );
float3 EvalShadow_GetClosestSample_Point( ShadowContext shadowContext, Texture2DArray tex, float3 positionWS, int index, float3 L )
real3 EvalShadow_GetClosestSample_Point( ShadowContext shadowContext, Texture2DArray tex, real3 positionWS, int index, real3 L )
{
// get the algorithm
ShadowData sd = shadowContext.shadowDatas[index];

float4 closestNDC = { 0,0,0,1 };
real4 closestNDC = { 0,0,0,1 };
float slice;
real slice;
float4 closestWS = mul( closestNDC, sd.shadowToWorld );
real4 closestWS = mul( closestNDC, sd.shadowToWorld );
float3 EvalShadow_GetClosestSample_Spot( ShadowContext shadowContext, float3 positionWS, int index )
real3 EvalShadow_GetClosestSample_Spot( ShadowContext shadowContext, real3 positionWS, int index )
float4 closestNDC = { 0,0,0,1 };
real4 closestNDC = { 0,0,0,1 };
float slice;
real slice;
float4 closestWS = mul( closestNDC, sd.shadowToWorld );
real4 closestWS = mul( closestNDC, sd.shadowToWorld );
float3 EvalShadow_GetClosestSample_Spot( ShadowContext shadowContext, Texture2DArray tex, float3 positionWS, int index )
real3 EvalShadow_GetClosestSample_Spot( ShadowContext shadowContext, Texture2DArray tex, real3 positionWS, int index )
float4 closestNDC = { 0,0,0,1 };
real4 closestNDC = { 0,0,0,1 };
float slice;
real slice;
float4 closestWS = mul( closestNDC, sd.shadowToWorld );
real4 closestWS = mul( closestNDC, sd.shadowToWorld );
float3 EvalShadow_GetClosestSample_Punctual( ShadowContext shadowContext, float3 positionWS, int index, float3 L )
real3 EvalShadow_GetClosestSample_Punctual( ShadowContext shadowContext, real3 positionWS, int index, real3 L )
{
// get the algorithm
ShadowData sd = shadowContext.shadowDatas[index];

int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (EvalShadow_GetCubeFaceID( L ) + 1) : 0;
sd = shadowContext.shadowDatas[index + faceIndex];
float4 closestNDC = { 0,0,0,1 };
real4 closestNDC = { 0,0,0,1 };
float slice;
real slice;
float4 closestWS = mul( closestNDC, sd.shadowToWorld );
real4 closestWS = mul( closestNDC, sd.shadowToWorld );
float3 EvalShadow_GetClosestSample_Punctual( ShadowContext shadowContext, Texture2DArray tex, float3 positionWS, int index, float3 L )
real3 EvalShadow_GetClosestSample_Punctual( ShadowContext shadowContext, Texture2DArray tex, real3 positionWS, int index, real3 L )
{
// get the algorithm
ShadowData sd = shadowContext.shadowDatas[index];

int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (EvalShadow_GetCubeFaceID( L ) + 1) : 0;
sd = shadowContext.shadowDatas[index + faceIndex];
float4 closestNDC = { 0,0,0,1 };
real4 closestNDC = { 0,0,0,1 };
float slice;
real slice;
float4 closestWS = mul( closestNDC, sd.shadowToWorld );
real4 closestWS = mul( closestNDC, sd.shadowToWorld );
float3 EvalShadow_GetClosestSample_Cascade( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float4 L )
real3 EvalShadow_GetClosestSample_Cascade( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real4 L )
float4 dirShadowSplitSpheres[4];
real4 dirShadowSplitSpheres[4];
float relDistance;
real relDistance;
float4 scales = asfloat( shadowContext.payloads[payloadOffset] );
real4 scales = asfloat( shadowContext.payloads[payloadOffset] );
float4 borders = asfloat( shadowContext.payloads[payloadOffset] );
real4 borders = asfloat( shadowContext.payloads[payloadOffset] );
float4 closestNDC = { 0,0,0,1 };
real4 closestNDC = { 0,0,0,1 };
float slice;
real slice;
float4 closestWS = mul( closestNDC, sd.shadowToWorld );
real4 closestWS = mul( closestNDC, sd.shadowToWorld );
float3 EvalShadow_GetClosestSample_Cascade( ShadowContext shadowContext, Texture2DArray tex, float3 positionWS, float3 normalWS, int index, float4 L )
real3 EvalShadow_GetClosestSample_Cascade( ShadowContext shadowContext, Texture2DArray tex, real3 positionWS, real3 normalWS, int index, real4 L )
float4 dirShadowSplitSpheres[4];
real4 dirShadowSplitSpheres[4];
float relDistance;
real relDistance;
float4 scales = asfloat( shadowContext.payloads[payloadOffset] );
real4 scales = asfloat( shadowContext.payloads[payloadOffset] );
float4 borders = asfloat( shadowContext.payloads[payloadOffset] );
real4 borders = asfloat( shadowContext.payloads[payloadOffset] );
float4 closestNDC = { 0,0,0,1 };
real4 closestNDC = { 0,0,0,1 };
float slice;
real slice;
float4 closestWS = mul( closestNDC, sd.shadowToWorld );
real4 closestWS = mul( closestNDC, sd.shadowToWorld );
return closestWS.xyz / closestWS.w;
}

10
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowMoments.hlsl


float mD = depth - moments.x;
float p = variance / (variance + mD * mD);
p = saturate( (p - lightLeakBias) / (1.0f - lightLeakBias) );
p = saturate( (p - lightLeakBias) / (1.0 - lightLeakBias) );
return max( p, depth <= moments.x );
}

}
// helpers for MSM
// Prepare the moments so there's little quantization error when storing the moments at half
// Prepare the moments so there's little quantization error when storing the moments at float
// precision. This step becomes unnecessary if the moments are stored in 32bit floats.
float4 ShadowMoments_Encode16MSM( float depth )
{

32.23703778 , -59.4683975703, -1.9077466311, -33.7652110555,
-68.571074599 , 82.0359750338, 9.3496555107, 47.9456096605,
39.3703274134, -35.364903257 , -6.6543490743, -23.9728048165 };
float4 optimized = mul( moments, mat );
optimized[0] += 0.035955884801;

float quotient = (switchVal[0] * z[2] - b[0] * (switchVal[0] + z[2]) + b[1]) / ((z[2] - switchVal[1]) * (z[0] - z[1]));
float attenuation = saturate( switchVal[2] + switchVal[3] * quotient );
return saturate( ((1.0 - attenuation) - lightLeakBias) / (1.0f - lightLeakBias) );
return saturate( ((1.0 - attenuation) - lightLeakBias) / (1.0 - lightLeakBias) );
}
float ShadowMoments_SolveDelta4MSM( float3 z, float4 b, float lightLeakBias)

float w1Factor = (z[0] > zFree) ? 1.0 : 0.0;
float attenuation = saturate( (b[1] - b[0] + (b[2] - b[0] - (zFree + 1.0) * (b[1] - b[0])) * (zFree - w1Factor - z[0]) / (z[0] * (z[0] - zFree))) / (zFree - w1Factor) + 1.0 - b[0] );
return saturate( ((1.0 - attenuation) - lightLeakBias) / (1.0f - lightLeakBias) );
return saturate( ((1.0 - attenuation) - lightLeakBias) / (1.0 - lightLeakBias) );
}

494
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSampling.hlsl


// | \
// ---- <-- length of this side is "triangleHeight"
// _ _ _ _ <-- texels
float SampleShadow_GetTriangleTexelArea(float triangleHeight)
real SampleShadow_GetTriangleTexelArea(real triangleHeight)
{
return triangleHeight - 0.5;
}

// / \
// _ _ _ _ <-- texels
// X Y Z W <-- result indices (in computedArea.xyzw and computedAreaUncut.xyzw)
void SampleShadow_GetTexelAreas_Tent_3x3(float offset, out float4 computedArea, out float4 computedAreaUncut)
void SampleShadow_GetTexelAreas_Tent_3x3(real offset, out real4 computedArea, out real4 computedAreaUncut)
float offset01SquaredHalved = (offset + 0.5) * (offset + 0.5) * 0.5;
real offset01SquaredHalved = (offset + 0.5) * (offset + 0.5) * 0.5;
computedAreaUncut.x = computedArea.x = offset01SquaredHalved - offset;
computedAreaUncut.w = computedArea.w = offset01SquaredHalved;

computedAreaUncut.y = SampleShadow_GetTriangleTexelArea(1.5 - offset);
// This area is superior to the one we are looking for if (offset < 0) thus we need to
// subtract the area of the triangle defined by (0,1.5-offset), (0,1.5+offset), (-offset,1.5).
float clampedOffsetLeft = min(offset,0);
float areaOfSmallLeftTriangle = clampedOffsetLeft * clampedOffsetLeft;
real clampedOffsetLeft = min(offset,0);
real areaOfSmallLeftTriangle = clampedOffsetLeft * clampedOffsetLeft;
float clampedOffsetRight = max(offset,0);
float areaOfSmallRightTriangle = clampedOffsetRight * clampedOffsetRight;
real clampedOffsetRight = max(offset,0);
real areaOfSmallRightTriangle = clampedOffsetRight * clampedOffsetRight;
void SampleShadow_GetTexelWeights_Tent_3x3(float offset, out float4 computedWeight)
void SampleShadow_GetTexelWeights_Tent_3x3(real offset, out real4 computedWeight)
float4 dummy;
real4 dummy;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedWeight, dummy);
computedWeight *= 0.44444;//0.44 == 1/(the triangle area)
}

// / \
// _ _ _ _ _ _ <-- texels
// 0 1 2 3 4 5 <-- computed area indices (in texelsWeights[])
void SampleShadow_GetTexelWeights_Tent_5x5(float offset, out float3 texelsWeightsA, out float3 texelsWeightsB)
void SampleShadow_GetTexelWeights_Tent_5x5(real offset, out real3 texelsWeightsA, out real3 texelsWeightsB)
float4 computedArea_From3texelTriangle;
float4 computedAreaUncut_From3texelTriangle;
real4 computedArea_From3texelTriangle;
real4 computedAreaUncut_From3texelTriangle;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedArea_From3texelTriangle, computedAreaUncut_From3texelTriangle);
// Triangle slope is 45 degree thus we can almost reuse the result of the 3 texel wide computation.

// / \
// _ _ _ _ _ _ _ _ <-- texels
// 0 1 2 3 4 5 6 7 <-- computed area indices (in texelsWeights[])
void SampleShadow_GetTexelWeights_Tent_7x7(float offset, out float4 texelsWeightsA, out float4 texelsWeightsB)
void SampleShadow_GetTexelWeights_Tent_7x7(real offset, out real4 texelsWeightsA, out real4 texelsWeightsB)
float4 computedArea_From3texelTriangle;
float4 computedAreaUncut_From3texelTriangle;
real4 computedArea_From3texelTriangle;
real4 computedAreaUncut_From3texelTriangle;
SampleShadow_GetTexelAreas_Tent_3x3(offset, computedArea_From3texelTriangle, computedAreaUncut_From3texelTriangle);
// Triangle slope is 45 degree thus we can almost reuse the result of the 3 texel wide computation.

}
// 3x3 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_3x3(float4 shadowMapTexture_TexelSize, float2 coord, out float fetchesWeights[4], out float2 fetchesUV[4])
void SampleShadow_ComputeSamples_Tent_3x3(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[4], out real2 fetchesUV[4])
float2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
float2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
float2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
float4 texelsWeightsU, texelsWeightsV;
real4 texelsWeightsU, texelsWeightsV;
float2 fetchesWeightsU = texelsWeightsU.xz + texelsWeightsU.yw;
float2 fetchesWeightsV = texelsWeightsV.xz + texelsWeightsV.yw;
real2 fetchesWeightsU = texelsWeightsU.xz + texelsWeightsU.yw;
real2 fetchesWeightsV = texelsWeightsV.xz + texelsWeightsV.yw;
float2 fetchesOffsetsU = texelsWeightsU.yw / fetchesWeightsU.xy + float2(-1.5,0.5);
float2 fetchesOffsetsV = texelsWeightsV.yw / fetchesWeightsV.xy + float2(-1.5,0.5);
real2 fetchesOffsetsU = texelsWeightsU.yw / fetchesWeightsU.xy + real2(-1.5,0.5);
real2 fetchesOffsetsV = texelsWeightsV.yw / fetchesWeightsV.xy + real2(-1.5,0.5);
float2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + float2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + float2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + float2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[3] = bilinearFetchOrigin + float2(fetchesOffsetsU.y, fetchesOffsetsV.y);
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;

// 5x5 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_5x5(float4 shadowMapTexture_TexelSize, float2 coord, out float fetchesWeights[9], out float2 fetchesUV[9])
void SampleShadow_ComputeSamples_Tent_5x5(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[9], out real2 fetchesUV[9])
float2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
float2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
float2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
float3 texelsWeightsU_A, texelsWeightsU_B;
float3 texelsWeightsV_A, texelsWeightsV_B;
real3 texelsWeightsU_A, texelsWeightsU_B;
real3 texelsWeightsV_A, texelsWeightsV_B;
float3 fetchesWeightsU = float3(texelsWeightsU_A.xz, texelsWeightsU_B.y) + float3(texelsWeightsU_A.y, texelsWeightsU_B.xz);
float3 fetchesWeightsV = float3(texelsWeightsV_A.xz, texelsWeightsV_B.y) + float3(texelsWeightsV_A.y, texelsWeightsV_B.xz);
real3 fetchesWeightsU = real3(texelsWeightsU_A.xz, texelsWeightsU_B.y) + real3(texelsWeightsU_A.y, texelsWeightsU_B.xz);
real3 fetchesWeightsV = real3(texelsWeightsV_A.xz, texelsWeightsV_B.y) + real3(texelsWeightsV_A.y, texelsWeightsV_B.xz);
float3 fetchesOffsetsU = float3(texelsWeightsU_A.y, texelsWeightsU_B.xz) / fetchesWeightsU.xyz + float3(-2.5,-0.5,1.5);
float3 fetchesOffsetsV = float3(texelsWeightsV_A.y, texelsWeightsV_B.xz) / fetchesWeightsV.xyz + float3(-2.5,-0.5,1.5);
real3 fetchesOffsetsU = real3(texelsWeightsU_A.y, texelsWeightsU_B.xz) / fetchesWeightsU.xyz + real3(-2.5,-0.5,1.5);
real3 fetchesOffsetsV = real3(texelsWeightsV_A.y, texelsWeightsV_B.xz) / fetchesWeightsV.xyz + real3(-2.5,-0.5,1.5);
float2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + float2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + float2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + float2(fetchesOffsetsU.z, fetchesOffsetsV.x);
fetchesUV[3] = bilinearFetchOrigin + float2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[4] = bilinearFetchOrigin + float2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesUV[5] = bilinearFetchOrigin + float2(fetchesOffsetsU.z, fetchesOffsetsV.y);
fetchesUV[6] = bilinearFetchOrigin + float2(fetchesOffsetsU.x, fetchesOffsetsV.z);
fetchesUV[7] = bilinearFetchOrigin + float2(fetchesOffsetsU.y, fetchesOffsetsV.z);
fetchesUV[8] = bilinearFetchOrigin + float2(fetchesOffsetsU.z, fetchesOffsetsV.z);
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y);
fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z);
fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z);
fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;

}
// 7x7 Tent filter (45 degree sloped triangles in U and V)
void SampleShadow_ComputeSamples_Tent_7x7(float4 shadowMapTexture_TexelSize, float2 coord, out float fetchesWeights[16], out float2 fetchesUV[16])
void SampleShadow_ComputeSamples_Tent_7x7(real4 shadowMapTexture_TexelSize, real2 coord, out real fetchesWeights[16], out real2 fetchesUV[16])
float2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
float2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
float2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
real2 tentCenterInTexelSpace = coord.xy * shadowMapTexture_TexelSize.zw;
real2 centerOfFetchesInTexelSpace = floor(tentCenterInTexelSpace + 0.5);
real2 offsetFromTentCenterToCenterOfFetches = tentCenterInTexelSpace - centerOfFetchesInTexelSpace;
float4 texelsWeightsU_A, texelsWeightsU_B;
float4 texelsWeightsV_A, texelsWeightsV_B;
real4 texelsWeightsU_A, texelsWeightsU_B;
real4 texelsWeightsV_A, texelsWeightsV_B;
float4 fetchesWeightsU = float4(texelsWeightsU_A.xz, texelsWeightsU_B.xz) + float4(texelsWeightsU_A.yw, texelsWeightsU_B.yw);
float4 fetchesWeightsV = float4(texelsWeightsV_A.xz, texelsWeightsV_B.xz) + float4(texelsWeightsV_A.yw, texelsWeightsV_B.yw);
real4 fetchesWeightsU = real4(texelsWeightsU_A.xz, texelsWeightsU_B.xz) + real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw);
real4 fetchesWeightsV = real4(texelsWeightsV_A.xz, texelsWeightsV_B.xz) + real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw);
float4 fetchesOffsetsU = float4(texelsWeightsU_A.yw, texelsWeightsU_B.yw) / fetchesWeightsU.xyzw + float4(-3.5,-1.5,0.5,2.5);
float4 fetchesOffsetsV = float4(texelsWeightsV_A.yw, texelsWeightsV_B.yw) / fetchesWeightsV.xyzw + float4(-3.5,-1.5,0.5,2.5);
real4 fetchesOffsetsU = real4(texelsWeightsU_A.yw, texelsWeightsU_B.yw) / fetchesWeightsU.xyzw + real4(-3.5,-1.5,0.5,2.5);
real4 fetchesOffsetsV = real4(texelsWeightsV_A.yw, texelsWeightsV_B.yw) / fetchesWeightsV.xyzw + real4(-3.5,-1.5,0.5,2.5);
float2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + float2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + float2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + float2(fetchesOffsetsU.z, fetchesOffsetsV.x);
fetchesUV[3] = bilinearFetchOrigin + float2(fetchesOffsetsU.w, fetchesOffsetsV.x);
fetchesUV[4] = bilinearFetchOrigin + float2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[5] = bilinearFetchOrigin + float2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesUV[6] = bilinearFetchOrigin + float2(fetchesOffsetsU.z, fetchesOffsetsV.y);
fetchesUV[7] = bilinearFetchOrigin + float2(fetchesOffsetsU.w, fetchesOffsetsV.y);
fetchesUV[8] = bilinearFetchOrigin + float2(fetchesOffsetsU.x, fetchesOffsetsV.z);
fetchesUV[9] = bilinearFetchOrigin + float2(fetchesOffsetsU.y, fetchesOffsetsV.z);
fetchesUV[10] = bilinearFetchOrigin + float2(fetchesOffsetsU.z, fetchesOffsetsV.z);
fetchesUV[11] = bilinearFetchOrigin + float2(fetchesOffsetsU.w, fetchesOffsetsV.z);
fetchesUV[12] = bilinearFetchOrigin + float2(fetchesOffsetsU.x, fetchesOffsetsV.w);
fetchesUV[13] = bilinearFetchOrigin + float2(fetchesOffsetsU.y, fetchesOffsetsV.w);
fetchesUV[14] = bilinearFetchOrigin + float2(fetchesOffsetsU.z, fetchesOffsetsV.w);
fetchesUV[15] = bilinearFetchOrigin + float2(fetchesOffsetsU.w, fetchesOffsetsV.w);
real2 bilinearFetchOrigin = centerOfFetchesInTexelSpace * shadowMapTexture_TexelSize.xy;
fetchesUV[0] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.x);
fetchesUV[1] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.x);
fetchesUV[2] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.x);
fetchesUV[3] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.x);
fetchesUV[4] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.y);
fetchesUV[5] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.y);
fetchesUV[6] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.y);
fetchesUV[7] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.y);
fetchesUV[8] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.z);
fetchesUV[9] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.z);
fetchesUV[10] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.z);
fetchesUV[11] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.z);
fetchesUV[12] = bilinearFetchOrigin + real2(fetchesOffsetsU.x, fetchesOffsetsV.w);
fetchesUV[13] = bilinearFetchOrigin + real2(fetchesOffsetsU.y, fetchesOffsetsV.w);
fetchesUV[14] = bilinearFetchOrigin + real2(fetchesOffsetsU.z, fetchesOffsetsV.w);
fetchesUV[15] = bilinearFetchOrigin + real2(fetchesOffsetsU.w, fetchesOffsetsV.w);
fetchesWeights[0] = fetchesWeightsU.x * fetchesWeightsV.x;
fetchesWeights[1] = fetchesWeightsU.y * fetchesWeightsV.x;

//
// 1 tap PCF sampling
//
float SampleShadow_PCF_1tap( ShadowContext shadowContext, inout uint payloadOffset, float3 tcs, float bias, uint slice, uint texIdx, uint sampIdx )
real SampleShadow_PCF_1tap( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, real bias, uint slice, uint texIdx, uint sampIdx )
float depthBias = asfloat( shadowContext.payloads[payloadOffset].x );
real depthBias = asfloat( shadowContext.payloads[payloadOffset].x );
payloadOffset++;
// add the depth bias

}
float SampleShadow_PCF_1tap( ShadowContext shadowContext, inout uint payloadOffset, float3 tcs, float bias, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_PCF_1tap( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, real bias, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
float depthBias = asfloat( shadowContext.payloads[payloadOffset].x );
real depthBias = asfloat( shadowContext.payloads[payloadOffset].x );
payloadOffset++;
// add the depth bias

//
// 3x3 tent PCF sampling (4 taps)
//
float SampleShadow_PCF_Tent_3x3( ShadowContext shadowContext, inout uint payloadOffset, float4 texelSizeRcp, float3 coord, uint slice, uint texIdx, uint sampIdx )
real SampleShadow_PCF_Tent_3x3( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, uint texIdx, uint sampIdx )
float2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
float depthBias = params.x;
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;
float4 shadowMapTexture_TexelSize = float4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
real4 shadowMapTexture_TexelSize = real4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
float shadow = 0.0;
float fetchesWeights[4];
float2 fetchesUV[4];
real shadow = 0.0;
real fetchesWeights[4];
real2 fetchesUV[4];
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( fetchesUV[i].xy, coord.z ), slice ).x;
float SampleShadow_PCF_Tent_3x3(ShadowContext shadowContext, inout uint payloadOffset, float4 texelSizeRcp, float3 coord, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_PCF_Tent_3x3(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
float2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
float depthBias = params.x;
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;
float4 shadowMapTexture_TexelSize = float4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
real4 shadowMapTexture_TexelSize = real4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
float shadow = 0.0;
float fetchesWeights[4];
float2 fetchesUV[4];
real shadow = 0.0;
real fetchesWeights[4];
real2 fetchesUV[4];
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[i].xy, coord.z ), slice ).x;
}
return shadow;
}

//
float SampleShadow_PCF_Tent_5x5( ShadowContext shadowContext, inout uint payloadOffset, float4 texelSizeRcp, float3 coord, uint slice, uint texIdx, uint sampIdx )
real SampleShadow_PCF_Tent_5x5( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, uint texIdx, uint sampIdx )
float2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
float depthBias = params.x;
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;
float4 shadowMapTexture_TexelSize = float4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
real4 shadowMapTexture_TexelSize = real4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
float shadow = 0.0;
float fetchesWeights[9];
float2 fetchesUV[9];
real shadow = 0.0;
real fetchesWeights[9];
real2 fetchesUV[9];
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( fetchesUV[i].xy, coord.z ), slice ).x;
float SampleShadow_PCF_Tent_5x5(ShadowContext shadowContext, inout uint payloadOffset, float4 texelSizeRcp, float3 coord, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_PCF_Tent_5x5(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
float2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
float depthBias = params.x;
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;
float4 shadowMapTexture_TexelSize = float4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
real4 shadowMapTexture_TexelSize = real4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
float shadow = 0.0;
float fetchesWeights[9];
float2 fetchesUV[9];
real shadow = 0.0;
real fetchesWeights[9];
real2 fetchesUV[9];
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[i].xy, coord.z ), slice ).x;
}
return shadow;

// 7x7 tent PCF sampling (16 taps)
//
float SampleShadow_PCF_Tent_7x7( ShadowContext shadowContext, inout uint payloadOffset, float4 texelSizeRcp, float3 coord, uint slice, uint texIdx, uint sampIdx )
real SampleShadow_PCF_Tent_7x7( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, uint texIdx, uint sampIdx )
float2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
float depthBias = params.x;
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;
float4 shadowMapTexture_TexelSize = float4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
real4 shadowMapTexture_TexelSize = real4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
float shadow = 0.0;
float fetchesWeights[16];
float2 fetchesUV[16];
real shadow = 0.0;
real fetchesWeights[16];
real2 fetchesUV[16];
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( fetchesUV[i].xy, coord.z ), slice ).x;
float SampleShadow_PCF_Tent_7x7(ShadowContext shadowContext, inout uint payloadOffset, float4 texelSizeRcp, float3 coord, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_PCF_Tent_7x7(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
float2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
float depthBias = params.x;
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;
float4 shadowMapTexture_TexelSize = float4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
real4 shadowMapTexture_TexelSize = real4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
float shadow = 0.0;
float fetchesWeights[16];
float2 fetchesUV[16];
real shadow = 0.0;
real fetchesWeights[16];
real2 fetchesUV[16];
SampleShadow_ComputeSamples_Tent_7x7(shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV);

for( i = 0; i < 1; i++ )
{
shadow += fetchesWeights[ 0] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 0].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 1] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 1].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 2] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 2].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 3] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 3].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 0] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 0].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 1] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 1].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 2] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 2].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 3] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 3].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 4] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 4].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 5] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 5].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 6] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 6].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 7] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 7].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 4] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 4].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 5] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 5].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 6] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 6].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 7] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 7].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 8] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 8].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 9] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[ 9].xy, coord.z ), slice ).x;
shadow += fetchesWeights[10] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[10].xy, coord.z ), slice ).x;
shadow += fetchesWeights[11] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[11].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 8] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 8].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 9] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 9].xy, coord.z ), slice ).x;
shadow += fetchesWeights[10] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[10].xy, coord.z ), slice ).x;
shadow += fetchesWeights[11] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[11].xy, coord.z ), slice ).x;
shadow += fetchesWeights[12] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[12].xy, coord.z ), slice ).x;
shadow += fetchesWeights[13] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[13].xy, coord.z ), slice ).x;
shadow += fetchesWeights[14] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[14].xy, coord.z ), slice ).x;
shadow += fetchesWeights[15] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[15].xy, coord.z ), slice ).x;
shadow += fetchesWeights[12] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[12].xy, coord.z ), slice ).x;
shadow += fetchesWeights[13] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[13].xy, coord.z ), slice ).x;
shadow += fetchesWeights[14] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[14].xy, coord.z ), slice ).x;
shadow += fetchesWeights[15] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[15].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[i].xy, coord.z ), slice ).x;
}
#endif
return shadow;

// 9 tap adaptive PCF sampling
//
float SampleShadow_PCF_9tap_Adaptive( ShadowContext shadowContext, inout uint payloadOffset, float4 texelSizeRcp, float3 tcs, float bias, uint slice, uint texIdx, uint sampIdx )
real SampleShadow_PCF_9tap_Adaptive( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 tcs, real bias, uint slice, uint texIdx, uint sampIdx )
float2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
float depthBias = params.x;
float filterSize = params.y;
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;
real filterSize = params.y;
payloadOffset++;
texelSizeRcp *= filterSize;

// Terms0 are weights for the individual samples, the other terms are offsets in texel space
float4 vShadow3x3PCFTerms0 = float4( 20.0f / 267.0f, 33.0f / 267.0f, 55.0f / 267.0f, 0.0f );
float4 vShadow3x3PCFTerms1 = float4( texelSizeRcp.x, texelSizeRcp.y, -texelSizeRcp.x, -texelSizeRcp.y );
float4 vShadow3x3PCFTerms2 = float4( texelSizeRcp.x, texelSizeRcp.y, 0.0f, 0.0f );
float4 vShadow3x3PCFTerms3 = float4(-texelSizeRcp.x, -texelSizeRcp.y, 0.0f, 0.0f );
real4 vShadow3x3PCFTerms0 = real4( 20.0 / 267.0, 33.0 / 267.0, 55.0 / 267.0, 0.0 );
real4 vShadow3x3PCFTerms1 = real4( texelSizeRcp.x, texelSizeRcp.y, -texelSizeRcp.x, -texelSizeRcp.y );
real4 vShadow3x3PCFTerms2 = real4( texelSizeRcp.x, texelSizeRcp.y, 0.0, 0.0 );
real4 vShadow3x3PCFTerms3 = real4(-texelSizeRcp.x, -texelSizeRcp.y, 0.0, 0.0 );
float4 v20Taps;
v20Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms1.xy, tcs.z ), slice ).x; // 1 1
v20Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms1.zy, tcs.z ), slice ).x; // -1 1
v20Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms1.xw, tcs.z ), slice ).x; // 1 -1
v20Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms1.zw, tcs.z ), slice ).x; // -1 -1
float flSum = dot( v20Taps.xyzw, float4( 0.25, 0.25, 0.25, 0.25 ) );
real4 v20Taps;
v20Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.xy, tcs.z ), slice ).x; // 1 1
v20Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.zy, tcs.z ), slice ).x; // -1 1
v20Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.xw, tcs.z ), slice ).x; // 1 -1
v20Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.zw, tcs.z ), slice ).x; // -1 -1
real flSum = dot( v20Taps.xyzw, real4( 0.25, 0.25, 0.25, 0.25 ) );
// fully in light or shadow? -> bail
if( ( flSum == 0.0 ) || ( flSum == 1.0 ) )
return flSum;

float4 v33Taps;
v33Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms2.xz, tcs.z ), slice ).x; // 1 0
v33Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms3.xz, tcs.z ), slice ).x; // -1 0
v33Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms3.zy, tcs.z ), slice ).x; // 0 -1
v33Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, float3( tcs.xy + vShadow3x3PCFTerms2.zy, tcs.z ), slice ).x; // 0 1
real4 v33Taps;
v33Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms2.xz, tcs.z ), slice ).x; // 1 0
v33Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms3.xz, tcs.z ), slice ).x; // -1 0
v33Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms3.zy, tcs.z ), slice ).x; // 0 -1
v33Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms2.zy, tcs.z ), slice ).x; // 0 1
flSum += dot( v33Taps.xyzw, vShadow3x3PCFTerms0.yyyy );
flSum += SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, tcs, slice ).x * vShadow3x3PCFTerms0.z;

float SampleShadow_PCF_9tap_Adaptive(ShadowContext shadowContext, inout uint payloadOffset, float4 texelSizeRcp, float3 tcs, float bias, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_PCF_9tap_Adaptive(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 tcs, real bias, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
float2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
float depthBias = params.x;
float filterSize = params.y;
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;
real filterSize = params.y;
payloadOffset++;
texelSizeRcp *= filterSize;

// Terms0 are weights for the individual samples, the other terms are offsets in texel space
float4 vShadow3x3PCFTerms0 = float4(20.0f / 267.0f, 33.0f / 267.0f, 55.0f / 267.0f, 0.0f);
float4 vShadow3x3PCFTerms1 = float4( texelSizeRcp.x, texelSizeRcp.y, -texelSizeRcp.x, -texelSizeRcp.y);
float4 vShadow3x3PCFTerms2 = float4( texelSizeRcp.x, texelSizeRcp.y, 0.0f, 0.0f);
float4 vShadow3x3PCFTerms3 = float4(-texelSizeRcp.x, -texelSizeRcp.y, 0.0f, 0.0f);
real4 vShadow3x3PCFTerms0 = real4(20.0 / 267.0, 33.0 / 267.0, 55.0 / 267.0, 0.0);
real4 vShadow3x3PCFTerms1 = real4( texelSizeRcp.x, texelSizeRcp.y, -texelSizeRcp.x, -texelSizeRcp.y);
real4 vShadow3x3PCFTerms2 = real4( texelSizeRcp.x, texelSizeRcp.y, 0.0, 0.0);
real4 vShadow3x3PCFTerms3 = real4(-texelSizeRcp.x, -texelSizeRcp.y, 0.0, 0.0);
float4 v20Taps;
v20Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms1.xy, tcs.z ), slice ).x; // 1 1
v20Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms1.zy, tcs.z ), slice ).x; // -1 1
v20Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms1.xw, tcs.z ), slice ).x; // 1 -1
v20Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms1.zw, tcs.z ), slice ).x; // -1 -1
float flSum = dot( v20Taps.xyzw, float4( 0.25, 0.25, 0.25, 0.25 ) );
real4 v20Taps;
v20Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.xy, tcs.z ), slice ).x; // 1 1
v20Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.zy, tcs.z ), slice ).x; // -1 1
v20Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.xw, tcs.z ), slice ).x; // 1 -1
v20Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.zw, tcs.z ), slice ).x; // -1 -1
real flSum = dot( v20Taps.xyzw, real4( 0.25, 0.25, 0.25, 0.25 ) );
// fully in light or shadow? -> bail
if( ( flSum == 0.0 ) || ( flSum == 1.0 ) )
return flSum;

float4 v33Taps;
v33Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms2.xz, tcs.z ), slice ).x; // 1 0
v33Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms3.xz, tcs.z ), slice ).x; // -1 0
v33Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms3.zy, tcs.z ), slice ).x; // 0 -1
v33Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, float3( tcs.xy + vShadow3x3PCFTerms2.zy, tcs.z ), slice ).x; // 0 1
real4 v33Taps;
v33Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms2.xz, tcs.z ), slice ).x; // 1 0
v33Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms3.xz, tcs.z ), slice ).x; // -1 0
v33Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms3.zy, tcs.z ), slice ).x; // 0 -1
v33Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms2.zy, tcs.z ), slice ).x; // 0 1
flSum += dot( v33Taps.xyzw, vShadow3x3PCFTerms0.yyyy );
flSum += SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, tcs, slice ).x * vShadow3x3PCFTerms0.z;

//
// 1 tap VSM sampling
//
float SampleShadow_VSM_1tap( ShadowContext shadowContext, inout uint payloadOffset, float3 tcs, uint slice, uint texIdx, uint sampIdx )
real SampleShadow_VSM_1tap( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, uint slice, uint texIdx, uint sampIdx )
float depth = 1.0 - tcs.z;
real depth = 1.0 - tcs.z;
float depth = tcs.z;
real depth = tcs.z;
float2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
float lightLeakBias = params.x;
float varianceBias = params.y;
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real lightLeakBias = params.x;
real varianceBias = params.y;
float2 moments = SampleShadow_T2DA( shadowContext, texIdx, sampIdx, tcs.xy, slice ).xy;
real2 moments = SampleShadow_T2DA( shadowContext, texIdx, sampIdx, tcs.xy, slice ).xy;
float SampleShadow_VSM_1tap(ShadowContext shadowContext, inout uint payloadOffset, float3 tcs, uint slice, Texture2DArray tex, SamplerState samp )
real SampleShadow_VSM_1tap(ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, uint slice, Texture2DArray tex, SamplerState samp )
float depth = 1.0 - tcs.z;
real depth = 1.0 - tcs.z;
float depth = tcs.z;
real depth = tcs.z;
float2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
float lightLeakBias = params.x;
float varianceBias = params.y;
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real lightLeakBias = params.x;
real varianceBias = params.y;
float2 moments = SAMPLE_TEXTURE2D_ARRAY_LOD( tex, samp, tcs.xy, slice, 0.0 ).xy;
real2 moments = SAMPLE_TEXTURE2D_ARRAY_LOD( tex, samp, tcs.xy, slice, 0.0 ).xy;
return ShadowMoments_ChebyshevsInequality( moments, depth, varianceBias, lightLeakBias );
}

//
float SampleShadow_EVSM_1tap( ShadowContext shadowContext, inout uint payloadOffset, float3 tcs, uint slice, uint texIdx, uint sampIdx, bool fourMoments )
real SampleShadow_EVSM_1tap( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, uint slice, uint texIdx, uint sampIdx, bool fourMoments )
float depth = 1.0 - tcs.z;
real depth = 1.0 - tcs.z;
float depth = tcs.z;
real depth = tcs.z;
float4 params = asfloat( shadowContext.payloads[payloadOffset] );
float lightLeakBias = params.x;
float varianceBias = params.y;
float2 evsmExponents = params.zw;
real4 params = asfloat( shadowContext.payloads[payloadOffset] );
real lightLeakBias = params.x;
real varianceBias = params.y;
real2 evsmExponents = params.zw;
float2 warpedDepth = ShadowMoments_WarpDepth( depth, evsmExponents );
real2 warpedDepth = ShadowMoments_WarpDepth( depth, evsmExponents );
float4 moments = SampleShadow_T2DA( shadowContext, texIdx, sampIdx, tcs.xy, slice );
real4 moments = SampleShadow_T2DA( shadowContext, texIdx, sampIdx, tcs.xy, slice );
float2 depthScale = evsmExponents * warpedDepth;
float2 minVariance = depthScale * depthScale * varianceBias;
real2 depthScale = evsmExponents * warpedDepth;
real2 minVariance = depthScale * depthScale * varianceBias;
float posContrib = ShadowMoments_ChebyshevsInequality( moments.xz, warpedDepth.x, minVariance.x, lightLeakBias );
float negContrib = ShadowMoments_ChebyshevsInequality( moments.yw, warpedDepth.y, minVariance.y, lightLeakBias );
real posContrib = ShadowMoments_ChebyshevsInequality( moments.xz, warpedDepth.x, minVariance.x, lightLeakBias );
real negContrib = ShadowMoments_ChebyshevsInequality( moments.yw, warpedDepth.y, minVariance.y, lightLeakBias );
return min( posContrib, negContrib );
}
else

}
float SampleShadow_EVSM_1tap( ShadowContext shadowContext, inout uint payloadOffset, float3 tcs, uint slice, Texture2DArray tex, SamplerState samp, bool fourMoments )
real SampleShadow_EVSM_1tap( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, uint slice, Texture2DArray tex, SamplerState samp, bool fourMoments )
float depth = 1.0 - tcs.z;
real depth = 1.0 - tcs.z;
float depth = tcs.z;
real depth = tcs.z;
float4 params = asfloat( shadowContext.payloads[payloadOffset] );
float lightLeakBias = params.x;
float varianceBias = params.y;
float2 evsmExponents = params.zw;
real4 params = asfloat( shadowContext.payloads[payloadOffset] );
real lightLeakBias = params.x;
real varianceBias = params.y;
real2 evsmExponents = params.zw;
float2 warpedDepth = ShadowMoments_WarpDepth( depth, evsmExponents );
real2 warpedDepth = ShadowMoments_WarpDepth( depth, evsmExponents );
float4 moments = SAMPLE_TEXTURE2D_ARRAY_LOD( tex, samp, tcs.xy, slice, 0.0 );
real4 moments = SAMPLE_TEXTURE2D_ARRAY_LOD( tex, samp, tcs.xy, slice, 0.0 );
float2 depthScale = evsmExponents * warpedDepth;
float2 minVariance = depthScale * depthScale * varianceBias;
real2 depthScale = evsmExponents * warpedDepth;
real2 minVariance = depthScale * depthScale * varianceBias;
float posContrib = ShadowMoments_ChebyshevsInequality( moments.xz, warpedDepth.x, minVariance.x, lightLeakBias );
float negContrib = ShadowMoments_ChebyshevsInequality( moments.yw, warpedDepth.y, minVariance.y, lightLeakBias );
real posContrib = ShadowMoments_ChebyshevsInequality( moments.xz, warpedDepth.x, minVariance.x, lightLeakBias );
real negContrib = ShadowMoments_ChebyshevsInequality( moments.yw, warpedDepth.y, minVariance.y, lightLeakBias );
return min( posContrib, negContrib );
}
else

//
// 1 tap MSM sampling
//
float SampleShadow_MSM_1tap( ShadowContext shadowContext, inout uint payloadOffset, float3 tcs, uint slice, uint texIdx, uint sampIdx, bool useHamburger )
real SampleShadow_MSM_1tap( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, uint slice, uint texIdx, uint sampIdx, bool useHamburger )
float4 params = asfloat( shadowContext.payloads[payloadOffset] );
float lightLeakBias = params.x;
float momentBias = params.y;
float depthBias = params.z;
float bpp16 = params.w;
real4 params = asfloat( shadowContext.payloads[payloadOffset] );
real lightLeakBias = params.x;
real momentBias = params.y;
real depthBias = params.z;
real bpp16 = params.w;
float depth = (1.0 - tcs.z) - depthBias;
real depth = (1.0 - tcs.z) - depthBias;
float depth = tcs.z + depthBias;
real depth = tcs.z + depthBias;
float4 moments = SampleShadow_T2DA( shadowContext, texIdx, sampIdx, tcs.xy, slice );
real4 moments = SampleShadow_T2DA( shadowContext, texIdx, sampIdx, tcs.xy, slice );
float3 z;
float4 b;
real3 z;
real4 b;
ShadowMoments_SolveMSM( moments, depth, momentBias, z, b );
if( useHamburger )

}
float SampleShadow_MSM_1tap( ShadowContext shadowContext, inout uint payloadOffset, float3 tcs, uint slice, Texture2DArray tex, SamplerState samp, bool useHamburger )
real SampleShadow_MSM_1tap( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, uint slice, Texture2DArray tex, SamplerState samp, bool useHamburger )
float4 params = asfloat( shadowContext.payloads[payloadOffset] );
float lightLeakBias = params.x;
float momentBias = params.y;
float depthBias = params.z;
float bpp16 = params.w;
real4 params = asfloat( shadowContext.payloads[payloadOffset] );
real lightLeakBias = params.x;
real momentBias = params.y;
real depthBias = params.z;
real bpp16 = params.w;
float depth = (1.0 - tcs.z) - depthBias;
real depth = (1.0 - tcs.z) - depthBias;
float depth = tcs.z + depthBias;
real depth = tcs.z + depthBias;
float4 moments = SAMPLE_TEXTURE2D_ARRAY_LOD( tex, samp, tcs.xy, slice, 0.0 );
real4 moments = SAMPLE_TEXTURE2D_ARRAY_LOD( tex, samp, tcs.xy, slice, 0.0 );
float3 z;
float4 b;
real3 z;
real4 b;
ShadowMoments_SolveMSM( moments, depth, momentBias, z, b );
if( useHamburger )

//-----------------------------------------------------------------------------------------------------
// helper function to dispatch a specific shadow algorithm
float SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, float3 posTC, float depthBias, uint slice, uint algorithm, uint texIdx, uint sampIdx )
real SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, real3 posTC, real depthBias, uint slice, uint algorithm, uint texIdx, uint sampIdx )
{
[branch]
switch( algorithm )

}
}
float SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, float3 posTC, float depthBias, uint slice, uint algorithm, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, real3 posTC, real depthBias, uint slice, uint algorithm, Texture2DArray tex, SamplerComparisonState compSamp )
{
[branch]
switch( algorithm )

}
}
float SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, float3 posTC, float depthBias, uint slice, uint algorithm, Texture2DArray tex, SamplerState samp )
real SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, real3 posTC, real depthBias, uint slice, uint algorithm, Texture2DArray tex, SamplerState samp )
{
[branch]
switch( algorithm )

40
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowTexFetch.hlsl


#if SHADOW_SUPPORTS_DYNAMIC_INDEXING != 0
// Shader model >= 5.1
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots , _SamplerCompSlots ) float4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float slice ) { return SAMPLE_TEXTURE2D_ARRAY_SHADOW( ctxt.tex2DArray[texIdx], ctxt.compSamplers[sampIdx], tcs, slice ); }
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots , _SamplerSlots ) float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float2 tcs, float slice, float lod = 0.0 ) { return SAMPLE_TEXTURE2D_ARRAY_LOD( ctxt.tex2DArray[texIdx], ctxt.samplers[sampIdx], tcs, slice, lod ); }
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_LOAD( _Tex2DArraySlots ) float4 LoadShadow_T2DA( ShadowContext ctxt, uint texIdx, uint2 tcs, uint slice, uint lod = 0 ) { return LOAD_TEXTURE2D_ARRAY_LOD( ctxt.tex2DArray[texIdx], tcs, slice, lod ).x; }
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_COMP( _TexCubeArraySlots, _SamplerCompSlots ) float4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float4 tcs, float cubeIdx ) { return SAMPLE_TEXTURECUBE_ARRAY_SHADOW( ctxt.texCubeArray[texIdx], ctxt.compSamplers[sampIdx], tcs, cubeIdx );}
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_SAMP( _TexCubeArraySlots, _SamplerSlots ) float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float cubeIdx, float lod = 0.0 ) { return SAMPLE_TEXTURECUBE_ARRAY_LOD( ctxt.texCubeArray[texIdx], ctxt.samplers[sampIdx], tcs, cubeIdx, lod ); }
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots , _SamplerCompSlots ) real4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, real3 tcs, real slice ) { return SAMPLE_TEXTURE2D_ARRAY_SHADOW( ctxt.tex2DArray[texIdx], ctxt.compSamplers[sampIdx], tcs, slice ); }
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots , _SamplerSlots ) real4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, real2 tcs, real slice, real lod = 0.0 ) { return SAMPLE_TEXTURE2D_ARRAY_LOD( ctxt.tex2DArray[texIdx], ctxt.samplers[sampIdx], tcs, slice, lod ); }
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_LOAD( _Tex2DArraySlots ) real4 LoadShadow_T2DA( ShadowContext ctxt, uint texIdx, uint2 tcs, uint slice, uint lod = 0 ) { return LOAD_TEXTURE2D_ARRAY_LOD( ctxt.tex2DArray[texIdx], tcs, slice, lod ).x; }
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_COMP( _TexCubeArraySlots, _SamplerCompSlots ) real4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, real4 tcs, real cubeIdx ) { return SAMPLE_TEXTURECUBE_ARRAY_SHADOW( ctxt.texCubeArray[texIdx], ctxt.compSamplers[sampIdx], tcs, cubeIdx );}
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_SAMP( _TexCubeArraySlots, _SamplerSlots ) real4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, real3 tcs, real cubeIdx, real lod = 0.0 ) { return SAMPLE_TEXTURECUBE_ARRAY_LOD( ctxt.texCubeArray[texIdx], ctxt.samplers[sampIdx], tcs, cubeIdx, lod ); }
#else // helper macros if dynamic indexing does not work

float4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float slice ) \
real4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, real3 tcs, real slice ) \
float4 res = 1.0.xxxx; \
real4 res = 1.0.xxxx; \
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \
{ \
[unroll] for( uint j = 0; j < _SamplerCompSlots; j++ ) \

}
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots, _SamplerSlots ) \
float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float2 tcs, float slice, float lod = 0.0 ) \
real4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, real2 tcs, real slice, real lod = 0.0 ) \
float4 res = 1.0.xxxx; \
real4 res = 1.0.xxxx; \
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \
{ \
[unroll] for( uint j = 0; j < _SamplerSlots; j++ ) \

}
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_LOAD( _Tex2DArraySlots ) \
float LoadShadow_T2DA( ShadowContext ctxt, uint texIdx, uint2 tcs, uint slice, uint lod = 0 ) \
real LoadShadow_T2DA( ShadowContext ctxt, uint texIdx, uint2 tcs, uint slice, uint lod = 0 ) \
float res = 1.0; \
real res = 1.0; \
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \
{ \
[branch] if( i == texIdx ) \

# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_COMP( _TexCubeArraySlots, _SamplerCompSlots ) \
float4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float4 tcs, float cubeIdx ) \
real4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, real4 tcs, real cubeIdx ) \
float4 res = 1.0.xxxx; \
real4 res = 1.0.xxxx; \
[unroll] for( uint i = 0; i < _TexCubeArraySlots; i++ ) \
{ \
[unroll] for( uint j = 0; j < _SamplerCompSlots; j++ ) \

}
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_SAMP( _TexCubeArraySlots, _SamplerSlots ) \
float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float cubeIdx, float lod = 0.0 ) \
real4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, real3 tcs, real cubeIdx, real lod = 0.0 ) \
float4 res = 1.0.xxxx; \
real4 res = 1.0.xxxx; \
[unroll] for( uint i = 0; i < _TexCubeArraySlots; i++ ) \
{ \
[unroll] for( uint j = 0; j < _SamplerSlots; j++ ) \

#endif // SHADOW_SUPPORTS_DYNAMIC_INDEXING != 0
// helper macro to suppress code generation if _cnt is 0
#define SHADOW_DECLARE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots , _SamplerCompSlots ) float4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float slice );
#define SHADOW_DECLARE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots , _SamplerSlots ) float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float2 tcs, float slice, float lod = 0.0 );
#define SHADOW_DECLARE_SAMPLING_FUNC_T2DA_LOAD( _Tex2DArraySlots ) float4 LoadShadow_T2DA( ShadowContext ctxt, uint texIdx, uint2 tcs, uint slice, uint lod = 0 );
#define SHADOW_DECLARE_SAMPLING_FUNC_TCA_COMP( _TexCubeArraySlots, _SamplerCompSlots ) float4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float4 tcs, float cubeIdx );
#define SHADOW_DECLARE_SAMPLING_FUNC_TCA_SAMP( _TexCubeArraySlots, _SamplerSlots ) float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float cubeIdx, float lod = 0.0 );
#define SHADOW_DECLARE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots , _SamplerCompSlots ) real4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, real3 tcs, real slice );
#define SHADOW_DECLARE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots , _SamplerSlots ) real4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, real2 tcs, real slice, real lod = 0.0 );
#define SHADOW_DECLARE_SAMPLING_FUNC_T2DA_LOAD( _Tex2DArraySlots ) real4 LoadShadow_T2DA( ShadowContext ctxt, uint texIdx, uint2 tcs, uint slice, uint lod = 0 );
#define SHADOW_DECLARE_SAMPLING_FUNC_TCA_COMP( _TexCubeArraySlots, _SamplerCompSlots ) real4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, real4 tcs, real cubeIdx );
#define SHADOW_DECLARE_SAMPLING_FUNC_TCA_SAMP( _TexCubeArraySlots, _SamplerSlots ) real4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, real3 tcs, real cubeIdx, real lod = 0.0 );
#define SHADOW_CAT( _left, _right ) _left ## _right

44
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Tessellation.hlsl


// p0, p1, p2 triangle world position
// p0, p1, p2 triangle world vertex normal
float3 PhongTessellation(float3 positionWS, float3 p0, float3 p1, float3 p2, float3 n0, float3 n1, float3 n2, float3 baryCoords, float shape)
real3 PhongTessellation(real3 positionWS, real3 p0, real3 p1, real3 p2, real3 n0, real3 n1, real3 n2, real3 baryCoords, real shape)
float3 c0 = ProjectPointOnPlane(positionWS, p0, n0);
float3 c1 = ProjectPointOnPlane(positionWS, p1, n1);
float3 c2 = ProjectPointOnPlane(positionWS, p2, n2);
real3 c0 = ProjectPointOnPlane(positionWS, p0, n0);
real3 c1 = ProjectPointOnPlane(positionWS, p1, n1);
real3 c2 = ProjectPointOnPlane(positionWS, p2, n2);
float3 phongPositionWS = baryCoords.x * c0 + baryCoords.y * c1 + baryCoords.z * c2;
real3 phongPositionWS = baryCoords.x * c0 + baryCoords.y * c1 + baryCoords.z * c2;
return lerp(positionWS, phongPositionWS, shape);
}

// Compute both screen and distance based adaptation - return factor between 0 and 1
float3 GetScreenSpaceTessFactor(float3 p0, float3 p1, float3 p2, float4x4 viewProjectionMatrix, float4 screenSize, float triangleSize)
real3 GetScreenSpaceTessFactor(real3 p0, real3 p1, real3 p2, real4x4 viewProjectionMatrix, real4 screenSize, real triangleSize)
float2 edgeScreenPosition0 = ComputeNormalizedDeviceCoordinates(p0, viewProjectionMatrix) * screenSize.xy;
float2 edgeScreenPosition1 = ComputeNormalizedDeviceCoordinates(p1, viewProjectionMatrix) * screenSize.xy;
float2 edgeScreenPosition2 = ComputeNormalizedDeviceCoordinates(p2, viewProjectionMatrix) * screenSize.xy;
real2 edgeScreenPosition0 = ComputeNormalizedDeviceCoordinates(p0, viewProjectionMatrix) * screenSize.xy;
real2 edgeScreenPosition1 = ComputeNormalizedDeviceCoordinates(p1, viewProjectionMatrix) * screenSize.xy;
real2 edgeScreenPosition2 = ComputeNormalizedDeviceCoordinates(p2, viewProjectionMatrix) * screenSize.xy;
float EdgeScale = 1.0 / triangleSize; // Edge size in reality, but name is simpler
float3 tessFactor;
real EdgeScale = 1.0 / triangleSize; // Edge size in reality, but name is simpler
real3 tessFactor;
tessFactor.x = saturate(distance(edgeScreenPosition1, edgeScreenPosition2) * EdgeScale);
tessFactor.y = saturate(distance(edgeScreenPosition0, edgeScreenPosition2) * EdgeScale);
tessFactor.z = saturate(distance(edgeScreenPosition0, edgeScreenPosition1) * EdgeScale);

float3 GetDistanceBasedTessFactor(float3 p0, float3 p1, float3 p2, float3 cameraPosWS, float tessMinDist, float tessMaxDist)
real3 GetDistanceBasedTessFactor(real3 p0, real3 p1, real3 p2, real3 cameraPosWS, real tessMinDist, real tessMaxDist)
float3 edgePosition0 = 0.5 * (p1 + p2);
float3 edgePosition1 = 0.5 * (p0 + p2);
float3 edgePosition2 = 0.5 * (p0 + p1);
real3 edgePosition0 = 0.5 * (p1 + p2);
real3 edgePosition1 = 0.5 * (p0 + p2);
real3 edgePosition2 = 0.5 * (p0 + p1);
float dist0 = distance(edgePosition0, cameraPosWS);
float dist1 = distance(edgePosition1, cameraPosWS);
float dist2 = distance(edgePosition2, cameraPosWS);
real dist0 = distance(edgePosition0, cameraPosWS);
real dist1 = distance(edgePosition1, cameraPosWS);
real dist2 = distance(edgePosition2, cameraPosWS);
float fadeDist = tessMaxDist - tessMinDist;
float3 tessFactor;
real fadeDist = tessMaxDist - tessMinDist;
real3 tessFactor;
tessFactor.x = saturate(1.0 - (dist0 - tessMinDist) / fadeDist);
tessFactor.y = saturate(1.0 - (dist1 - tessMinDist) / fadeDist);
tessFactor.z = saturate(1.0 - (dist2 - tessMinDist) / fadeDist);

float4 CalcTriTessFactorsFromEdgeTessFactors(float3 triVertexFactors)
real4 CalcTriTessFactorsFromEdgeTessFactors(real3 triVertexFactors)
float4 tess;
real4 tess;
tess.x = triVertexFactors.x;
tess.y = triVertexFactors.y;
tess.z = triVertexFactors.z;

26
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/VolumeRendering.hlsl


#ifndef UNITY_VOLUME_RENDERING_INCLUDED
#define UNITY_VOLUME_RENDERING_INCLUDED
float OpticalDepthHomogeneous(float extinction, float intervalLength)
real OpticalDepthHomogeneous(real extinction, real intervalLength)
float Transmittance(float opticalDepth)
real Transmittance(real opticalDepth)
float TransmittanceIntegralOverHomogeneousInterval(float extinction, float start, float end)
real TransmittanceIntegralOverHomogeneousInterval(real extinction, real start, real end)
float3 OpticalDepthHomogeneous(float3 extinction, float intervalLength)
real3 OpticalDepthHomogeneous(real3 extinction, real intervalLength)
float3 Transmittance(float3 opticalDepth)
real3 Transmittance(real3 opticalDepth)
float3 TransmittanceIntegralOverHomogeneousInterval(float3 extinction, float start, float end)
real3 TransmittanceIntegralOverHomogeneousInterval(real3 extinction, real start, real end)
float IsotropicPhaseFunction()
real IsotropicPhaseFunction()
float HenyeyGreensteinPhasePartConstant(float asymmetry)
real HenyeyGreensteinPhasePartConstant(real asymmetry)
float g = asymmetry;
real g = asymmetry;
float HenyeyGreensteinPhasePartVarying(float asymmetry, float LdotD)
real HenyeyGreensteinPhasePartVarying(real asymmetry, real LdotD)
float g = asymmetry;
real g = asymmetry;
float HenyeyGreensteinPhaseFunction(float asymmetry, float LdotD)
real HenyeyGreensteinPhaseFunction(real asymmetry, real LdotD)
{
return HenyeyGreensteinPhasePartConstant(asymmetry) *
HenyeyGreensteinPhasePartVarying(asymmetry, LdotD);

float3 TransmittanceColorAtDistanceToAbsorption(float3 transmittanceColor, float atDistance)
real3 TransmittanceColorAtDistanceToAbsorption(real3 transmittanceColor, real atDistance)
{
return -log(transmittanceColor + FLT_EPS) / max(atDistance, FLT_EPS);
}

10
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Wind.hlsl


// Globals
// TODO: no global variable or resource declarations in the Shader Library. Functions and macros only!
TEXTURE2D(WIND_SETTINGS_TexNoise);
SAMPLER(sampler_WIND_SETTINGS_TexNoise);
TEXTURE2D(WIND_SETTINGS_TexGust);

float3 trunk = float3(0,0,0);
if(WIND_SETTINGS_WorldDirectionAndSpeed.w > 0.0f || WIND_SETTINGS_Turbulence > 0.0f)
if(WIND_SETTINGS_WorldDirectionAndSpeed.w > 0.0 || WIND_SETTINGS_Turbulence > 0.0)
float gust = 0.0f;
float gust = 0.0;
if(WIND_SETTINGS_GustSpeed > 0.0f)
if(WIND_SETTINGS_GustSpeed > 0.0)
{
gust = texGust((PivotPosition - gustWorldOffset)*WIND_SETTINGS_GustWorldScale,3);
gust = pow(gust, 2) * WIND_SETTINGS_GustScale;

{
WindData wind = GetAnalyticalWind(positionWS, rootWP, drag, shiverDrag, initialBend, time);
if (wind.Strength > 0.0f)
if (wind.Strength > 0.0)
{
float att = AttenuateTrunk(distance(positionWS, rootWP), stiffness);
float3 rotAxis = cross(float3(0, 1, 0), wind.Direction);

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/Lit/Lit.hlsl


RefractionModelResult refraction = REFRACTION_MODEL(V, posInput, bsdfData);
preLightData.transmissionRefractV = refraction.rayWS;
preLightData.transmissionPositionWS = refraction.positionWS;
preLightData.transmissionTransmittance = exp(-bsdfData.absorptionCoefficient * refraction.distance);
preLightData.transmissionTransmittance = exp(-bsdfData.absorptionCoefficient * refraction.dist);
// Empirical remap to try to match a bit the refractio probe blurring for the fallback
preLightData.transmissionSSMipLevel = sqrt(bsdfData.perceptualRoughness) * uint(_GaussianPyramidColorMipSize.z);
#else

8
SampleScenes/HDTest/AnimTest/ThreeDScans/Gutenberg/Materials.meta


fileFormatVersion: 2
guid: 3a4343f81dd267d4cbbd6726951946b3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Tests/GraphicsTests/RenderPipeline/LightweightPipeline/Scenes/030_Shader_RenderOrder.meta


fileFormatVersion: 2
guid: f78229abd339e4d49b6e0e29fd79df0c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

4
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/SHMath.hlsl


#ifndef UNITY_SHMATH_INCLUDED
#define UNITY_SHMATH_INCLUDED
#endif // UNITY_SHMATH_INCLUDED

8
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/SHMath.hlsl.meta


fileFormatVersion: 2
guid: 6c7ed7ec061ae2243bb560c39b451a15
timeCreated: 1472140530
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存