浏览代码

Change ShaderLibrary to use REAL instead of float/half

/feature-ReflectionProbeFit
sebastienlagarde 7 年前
当前提交
d83489f4
共有 43 个文件被更改,包括 2438 次插入2420 次删除
  1. 24
      ScriptableRenderPipeline/Core/ShaderLibrary/API/D3D11.hlsl
  2. 28
      ScriptableRenderPipeline/Core/ShaderLibrary/API/GLCore.hlsl
  3. 32
      ScriptableRenderPipeline/Core/ShaderLibrary/API/GLES2.hlsl
  4. 28
      ScriptableRenderPipeline/Core/ShaderLibrary/API/GLES3.hlsl
  5. 24
      ScriptableRenderPipeline/Core/ShaderLibrary/API/Metal.hlsl
  6. 24
      ScriptableRenderPipeline/Core/ShaderLibrary/API/PSSL.hlsl
  7. 24
      ScriptableRenderPipeline/Core/ShaderLibrary/API/Vulkan.hlsl
  8. 24
      ScriptableRenderPipeline/Core/ShaderLibrary/API/XBoxOne.hlsl
  9. 132
      ScriptableRenderPipeline/Core/ShaderLibrary/AreaLighting.hlsl
  10. 96
      ScriptableRenderPipeline/Core/ShaderLibrary/BC6H.hlsl
  11. 190
      ScriptableRenderPipeline/Core/ShaderLibrary/BSDF.hlsl
  12. 196
      ScriptableRenderPipeline/Core/ShaderLibrary/Color.hlsl
  13. 198
      ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl
  14. 144
      ScriptableRenderPipeline/Core/ShaderLibrary/CommonLighting.hlsl
  15. 58
      ScriptableRenderPipeline/Core/ShaderLibrary/CommonMaterial.hlsl
  16. 6
      ScriptableRenderPipeline/Core/ShaderLibrary/CommonShadow.hlsl
  17. 24
      ScriptableRenderPipeline/Core/ShaderLibrary/Debug.hlsl
  18. 94
      ScriptableRenderPipeline/Core/ShaderLibrary/EntityLighting.hlsl
  19. 76
      ScriptableRenderPipeline/Core/ShaderLibrary/GeometricTools.hlsl
  20. 320
      ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl
  21. 42
      ScriptableRenderPipeline/Core/ShaderLibrary/Macros.hlsl
  22. 60
      ScriptableRenderPipeline/Core/ShaderLibrary/NormalSurfaceGradient.hlsl
  23. 262
      ScriptableRenderPipeline/Core/ShaderLibrary/Packing.hlsl
  24. 56
      ScriptableRenderPipeline/Core/ShaderLibrary/PerPixelDisplacement.hlsl
  25. 24
      ScriptableRenderPipeline/Core/ShaderLibrary/QuaternionMath.hlsl
  26. 18
      ScriptableRenderPipeline/Core/ShaderLibrary/Random.hlsl
  27. 32
      ScriptableRenderPipeline/Core/ShaderLibrary/Refraction.hlsl
  28. 434
      ScriptableRenderPipeline/Core/ShaderLibrary/Sampling/Fibonacci.hlsl
  29. 752
      ScriptableRenderPipeline/Core/ShaderLibrary/Sampling/Hammersley.hlsl
  30. 16
      ScriptableRenderPipeline/Core/ShaderLibrary/Sampling/SampleUVMapping.hlsl
  31. 6
      ScriptableRenderPipeline/Core/ShaderLibrary/Sampling/SampleUVMappingInternal.hlsl
  32. 22
      ScriptableRenderPipeline/Core/ShaderLibrary/Sampling/SampleUVMappingNormalInternal.hlsl
  33. 208
      ScriptableRenderPipeline/Core/ShaderLibrary/Sampling/Sampling.hlsl
  34. 58
      ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/Resources/ShadowBlurMoments.compute
  35. 24
      ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/Shadow.hlsl
  36. 320
      ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
  37. 82
      ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowMoments.hlsl
  38. 494
      ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowSampling.hlsl
  39. 40
      ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowTexFetch.hlsl
  40. 44
      ScriptableRenderPipeline/Core/ShaderLibrary/Tessellation.hlsl
  41. 26
      ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl
  42. 88
      ScriptableRenderPipeline/Core/ShaderLibrary/Wind.hlsl
  43. 8
      SampleScenes/HDTest/AnimTest/ThreeDScans/Gutenberg/Materials.meta

24
ScriptableRenderPipeline/Core/ShaderLibrary/API/D3D11.hlsl


#define UNITY_UV_STARTS_AT_TOP 1
#define UNITY_REVERSED_Z 1
#define UNITY_NEAR_CLIP_VALUE (1.0)
#define UNITY_NEAR_CLIP_VALUE (REAL(1.0))
#define UNITY_RAW_FAR_CLIP_VALUE (0.0)
#define UNITY_RAW_FAR_CLIP_VALUE (REAL(0.0))
#define FRONT_FACE_SEMANTIC SV_IsFrontFace
#define FRONT_FACE_TYPE bool
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL) ? (FRONT) : (BACK))

#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod)
#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias)
#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, REAL3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, REAL3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, REAL3(coord2, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, REAL4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, REAL4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, REAL4(coord3, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, REAL3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, REAL4((coord4).xyz, index), (coord4).w)
#define SAMPLE_DEPTH_TEXTURE(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).r
#define SAMPLE_DEPTH_TEXTURE_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod).r

#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod))
#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2)
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index))
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, REAL3(coord2, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, REAL4(coord3, index))
#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2)
#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2)

28
ScriptableRenderPipeline/Core/ShaderLibrary/API/GLCore.hlsl


#define UNITY_UV_STARTS_AT_TOP 0
#define UNITY_REVERSED_Z 0
#define UNITY_GATHER_SUPPORTED 0
#define UNITY_NEAR_CLIP_VALUE (-1.0)
#define UNITY_NEAR_CLIP_VALUE (REAL(-1.0))
#define UNITY_RAW_FAR_CLIP_VALUE (1.0)
#define UNITY_RAW_FAR_CLIP_VALUE (REAL(1.0))
#define FRONT_FACE_TYPE float
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL > 0.0) ? (FRONT) : (BACK))
#define FRONT_FACE_TYPE REAL
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL > REAL(0.0)) ? (FRONT) : (BACK))
#define CBUFFER_START(name)
#define CBUFFER_END

#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod)
#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias)
#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, ddx, ddy) textureName.SampleGrad(samplerName, coord2, ddx, ddy)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, REAL3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, REAL3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, REAL3(coord2, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, REAL4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, REAL4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, REAL4(coord3, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, REAL3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, REAL4((coord4).xyz, index), (coord4).w)
#define SAMPLE_DEPTH_TEXTURE(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).r
#define SAMPLE_DEPTH_TEXTURE_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod).r

#if (SHADER_TARGET >= 45)
#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2)
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index))
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, REAL3(coord2, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, REAL4(coord3, index))
#else
#define GATHER_TEXTURE2D(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).rrrr
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index).rrrr

32
ScriptableRenderPipeline/Core/ShaderLibrary/API/GLES2.hlsl


#define UNITY_UV_STARTS_AT_TOP 0
#define UNITY_REVERSED_Z 0
#define UNITY_GATHER_SUPPORTED 0
#define UNITY_NEAR_CLIP_VALUE (-1.0)
#define UNITY_NEAR_CLIP_VALUE (REAL(-1.0))
#define UNITY_RAW_FAR_CLIP_VALUE (1.0)
#define UNITY_RAW_FAR_CLIP_VALUE (REAL(1.0))
#define FRONT_FACE_TYPE float
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL > 0.0) ? (FRONT) : (BACK))
#define FRONT_FACE_TYPE REAL
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL > REAL(0.0)) ? (FRONT) : (BACK))
#define CBUFFER_START(name)
#define CBUFFER_END

#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) tex2D(textureName, coord2)
#if (SHADER_TARGET >= 30)
#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) tex2Dlod(textureName, float4(coord2, 0, lod))
#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) tex2Dlod(textureName, REAL4(coord2, 0, lod))
#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) tex2Dbias(textureName, float4(coord2, 0, bias))
#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) tex2Dbias(textureName, REAL4(coord2, 0, bias))
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) SAMPLE_TEXTURECUBE(textureName, samplerName, float3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, float3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, float3(coord2, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) SAMPLE_TEXTURECUBE(textureName, samplerName, REAL3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, REAL3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, REAL3(coord2, index), bias)
#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) texCUBEbias(textureName, float4(coord3, bias))
#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) texCUBEbias(textureName, REAL4(coord3, bias))
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) SAMPLE_TEXTURECUBE(textureName, samplerName, coord3)
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias)

#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, float4(coord3.xy, index, coord3.w))
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, REAL4(coord3.xy, index, coord3.w))
#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) SHADOWCUBE_SAMPLE(textureName, samplerName, coord4)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4)

#define LOAD_TEXTURE2D(textureName, unCoord2) half4(0, 0, 0, 0) // Not supported
#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) half4(0, 0, 0, 0) // Not supported
#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) half4(0, 0, 0, 0) // Not supported
#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) half4(0, 0, 0, 0) // Not supported
#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) half4(0, 0, 0, 0) // Not supported
#define LOAD_TEXTURE2D(textureName, unCoord2) REAL4(0, 0, 0, 0) // Not supported
#define LOAD_TEXTURE2D_LOD(textureName, unCoord2, lod) REAL4(0, 0, 0, 0) // Not supported
#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) REAL4(0, 0, 0, 0) // Not supported
#define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index) REAL4(0, 0, 0, 0) // Not supported
#define LOAD_TEXTURE2D_ARRAY_LOD(textureName, unCoord2, index, lod) REAL4(0, 0, 0, 0) // Not supported
// Gather not supported. Fallback to regular texture sampling.
#define GATHER_TEXTURE2D(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).rrrr

28
ScriptableRenderPipeline/Core/ShaderLibrary/API/GLES3.hlsl


#define UNITY_UV_STARTS_AT_TOP 0
#define UNITY_REVERSED_Z 0
#define UNITY_GATHER_SUPPORTED 0
#define UNITY_NEAR_CLIP_VALUE (-1.0)
#define UNITY_NEAR_CLIP_VALUE (REAL(-1.0))
#define UNITY_RAW_FAR_CLIP_VALUE (1.0)
#define UNITY_RAW_FAR_CLIP_VALUE (REAL(1.0))
#define FRONT_FACE_TYPE float
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL > 0.0) ? (FRONT) : (BACK))
#define FRONT_FACE_TYPE REAL
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL > REAL(0.0)) ? (FRONT) : (BACK))
#define ERROR_ON_UNSUPPORTED_FUNCTION(funcName) #error ##funcName is not supported on GLES 3.0

#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod)
#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias)
#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, ddx, ddy) textureName.SampleGrad(samplerName, coord2, ddx, ddy)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, REAL3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, REAL3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, REAL3(coord2, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, REAL4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, REAL4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, REAL4(coord3, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, REAL3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, REAL4((coord4).xyz, index), (coord4).w)
#define SAMPLE_DEPTH_TEXTURE(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).r
#define SAMPLE_DEPTH_TEXTURE_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod).r

#if (SHADER_TARGET >= 45)
#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2)
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index))
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, REAL3(coord2, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, REAL4(coord3, index))
#else
#define GATHER_TEXTURE2D(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).rrrr
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index).rrrr

24
ScriptableRenderPipeline/Core/ShaderLibrary/API/Metal.hlsl


#define UNITY_UV_STARTS_AT_TOP 1
#define UNITY_REVERSED_Z 1
#define UNITY_NEAR_CLIP_VALUE (1.0)
#define UNITY_NEAR_CLIP_VALUE (REAL(1.0))
#define UNITY_RAW_FAR_CLIP_VALUE (0.0)
#define UNITY_RAW_FAR_CLIP_VALUE (REAL(0.0))
#define FRONT_FACE_SEMANTIC SV_IsFrontFace
#define FRONT_FACE_TYPE bool
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL) ? (FRONT) : (BACK))

#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod)
#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias)
#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, REAL3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, REAL3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, REAL3(coord2, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, REAL4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, REAL4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, REAL4(coord3, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, REAL3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, REAL4((coord4).xyz, index), (coord4).w)
#define SAMPLE_DEPTH_TEXTURE(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).r
#define SAMPLE_DEPTH_TEXTURE_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod).r

#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod))
#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2)
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index))
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, REAL3(coord2, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, REAL4(coord3, index))
#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2)
#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2)

24
ScriptableRenderPipeline/Core/ShaderLibrary/API/PSSL.hlsl


#define UNITY_UV_STARTS_AT_TOP 1
#define UNITY_REVERSED_Z 1
#define UNITY_NEAR_CLIP_VALUE (1.0)
#define UNITY_NEAR_CLIP_VALUE (REAL(1.0))
#define UNITY_RAW_FAR_CLIP_VALUE (0.0)
#define UNITY_RAW_FAR_CLIP_VALUE (REAL(0.0))
#define FRONT_FACE_SEMANTIC SV_IsFrontFace
#define FRONT_FACE_TYPE bool
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL) ? (FRONT) : (BACK))

#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod)
#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias)
#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, REAL3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, REAL3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, REAL3(coord2, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, REAL4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, REAL4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, REAL4(coord3, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, REAL3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, REAL4((coord4).xyz, index), (coord4).w)
#define SAMPLE_DEPTH_TEXTURE(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).r
#define SAMPLE_DEPTH_TEXTURE_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod).r

#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod))
#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2)
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index))
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, REAL3(coord2, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, REAL4(coord3, index))
#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2)
#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2)

24
ScriptableRenderPipeline/Core/ShaderLibrary/API/Vulkan.hlsl


#define UNITY_UV_STARTS_AT_TOP 1
#define UNITY_REVERSED_Z 1
#define UNITY_NEAR_CLIP_VALUE (1.0)
#define UNITY_NEAR_CLIP_VALUE (REAL(1.0))
#define UNITY_RAW_FAR_CLIP_VALUE (0.0)
#define UNITY_RAW_FAR_CLIP_VALUE (REAL(0.0))
#define FRONT_FACE_SEMANTIC SV_IsFrontFace
#define FRONT_FACE_TYPE bool
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL) ? (FRONT) : (BACK))

#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod)
#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias)
#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, REAL3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, REAL3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, REAL3(coord2, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, REAL4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, REAL4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, REAL4(coord3, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, REAL3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, REAL4((coord4).xyz, index), (coord4).w)
#define SAMPLE_DEPTH_TEXTURE(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).r
#define SAMPLE_DEPTH_TEXTURE_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod).r

#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod))
#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2)
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index))
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, REAL3(coord2, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, REAL4(coord3, index))
#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2)
#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2)

24
ScriptableRenderPipeline/Core/ShaderLibrary/API/XBoxOne.hlsl


#define UNITY_UV_STARTS_AT_TOP 1
#define UNITY_REVERSED_Z 1
#define UNITY_NEAR_CLIP_VALUE (1.0)
#define UNITY_NEAR_CLIP_VALUE (REAL(1.0))
#define UNITY_RAW_FAR_CLIP_VALUE (0.0)
#define UNITY_RAW_FAR_CLIP_VALUE (REAL(0.0))
#define FRONT_FACE_SEMANTIC SV_IsFrontFace
#define FRONT_FACE_TYPE bool
#define IS_FRONT_VFACE(VAL, FRONT, BACK) ((VAL) ? (FRONT) : (BACK))

#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod)
#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias)
#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, dpdx, dpdy) textureName.SampleGrad(samplerName, coord2, dpdx, dpdy)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, float3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Sample(samplerName, REAL3(coord2, index))
#define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, REAL3(coord2, index), lod)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, REAL3(coord2, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, float4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias)
#define SAMPLE_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Sample(samplerName, REAL4(coord3, index))
#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, REAL4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, REAL4(coord3, index), bias)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, REAL3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, float4((coord4).xyz, index), (coord4).w)
#define SAMPLE_TEXTURECUBE_ARRAY_SHADOW(textureName, samplerName, coord4, index) textureName.SampleCmpLevelZero(samplerName, REAL4((coord4).xyz, index), (coord4).w)
#define SAMPLE_DEPTH_TEXTURE(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).r
#define SAMPLE_DEPTH_TEXTURE_LOD(textureName, samplerName, coord2, lod) SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod).r

#define LOAD_TEXTURE3D_LOD(textureName, unCoord3, lod) textureName.Load(int4(unCoord3, lod))
#define GATHER_TEXTURE2D(textureName, samplerName, coord2) textureName.Gather(samplerName, coord2)
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, float3(coord2, index))
#define GATHER_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index) textureName.Gather(samplerName, REAL3(coord2, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, float4(coord3, index))
#define GATHER_TEXTURECUBE_ARRAY(textureName, samplerName, coord3, index) textureName.Gather(samplerName, REAL4(coord3, index))
#define GATHER_RED_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherRed(samplerName, coord2)
#define GATHER_GREEN_TEXTURE2D(textureName, samplerName, coord2) textureName.GatherGreen(samplerName, coord2)

132
ScriptableRenderPipeline/Core/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,
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};

// For line lights.
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);

96
ScriptableRenderPipeline/Core/ShaderLibrary/BC6H.hlsl


// Doc: https://msdn.microsoft.com/en-us/library/windows/desktop/hh308952(v=vs.85).aspx
// Measure compression error
float CalcMSLE(float3 a, float3 b)
REAL CalcMSLE(REAL3 a, REAL3 b)
float3 err = log2(( b + 1.0f) / (a + 1.0f ));
REAL3 err = log2(( b + 1.0) / (a + 1.0 ));
float3 Quantize7(float3 x)
REAL3 Quantize7(REAL3 x)
return (f32tof16(x) * 128.0f) / (0x7bff + 1.0f);
return (f32tof16(x) * 128.0) / (0x7bff + 1.0);
float3 Quantize9(float3 x)
REAL3 Quantize9(REAL3 x)
return (f32tof16(x) * 512.0f) / (0x7bff + 1.0f);
return (f32tof16(x) * 512.0) / (0x7bff + 1.0);
float3 Quantize10(float3 x)
REAL3 Quantize10(REAL3 x)
return (f32tof16(x) * 1024.0f) / (0x7bff + 1.0f);
return (f32tof16(x) * 1024.0) / (0x7bff + 1.0);
float3 Unquantize7(float3 x)
REAL3 Unquantize7(REAL3 x)
return (x * 65536.0f + 0x8000) / 128.0f;
return (x * 65536.0 + 0x8000) / 128.0;
float3 Unquantize9(float3 x)
REAL3 Unquantize9(REAL3 x)
return (x * 65536.0f + 0x8000) / 512.0f;
return (x * 65536.0 + 0x8000) / 512.0;
float3 Unquantize10(float3 x)
REAL3 Unquantize10(REAL3 x)
return (x * 65536.0f + 0x8000) / 1024.0f;
return (x * 65536.0 + 0x8000) / 1024.0;
uint ComputeIndex3( float texelPos, float endPoint0Pos, float endPoint1Pos )
uint ComputeIndex3( REAL texelPos, REAL endPoint0Pos, REAL endPoint1Pos )
float r = ( texelPos - endPoint0Pos ) / ( endPoint1Pos - endPoint0Pos );
return (uint) clamp( r * 6.98182f + 0.00909f + 0.5f, 0.0f, 7.0f );
REAL r = ( texelPos - endPoint0Pos ) / ( endPoint1Pos - endPoint0Pos );
return (uint) clamp( r * 6.98182f + 0.00909f + 0.5f, 0.0, 7.0 );
uint ComputeIndex4( float texelPos, float endPoint0Pos, float endPoint1Pos )
uint ComputeIndex4( REAL texelPos, REAL endPoint0Pos, REAL endPoint1Pos )
float r = ( texelPos - endPoint0Pos ) / ( endPoint1Pos - endPoint0Pos );
return (uint) clamp( r * 14.93333f + 0.03333f + 0.5f, 0.0f, 15.0f );
REAL r = ( texelPos - endPoint0Pos ) / ( endPoint1Pos - endPoint0Pos );
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 REAL3 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 )
REAL3 FinishUnquantize( REAL3 endpoint0Unq, REAL3 endpoint1Unq, REAL weight )
float3 comp = ( endpoint0Unq * ( 64.0f - weight ) + endpoint1Unq * weight + 32.0f ) * ( 31.0f / 4096.0f );
REAL3 comp = ( endpoint0Unq * ( 64.0 - weight ) + endpoint1Unq * weight + 32.0 ) * ( 31.0 / 4096.0 );
void EncodeMode11( inout uint4 block, inout float blockMSLE, float3 texels[ 16 ] )
void EncodeMode11( inout uint4 block, inout REAL blockMSLE, REAL3 texels[ 16 ] )
float3 blockMin = texels[ 0 ];
float3 blockMax = texels[ 0 ];
REAL3 blockMin = texels[ 0 ];
REAL3 blockMax = texels[ 0 ];
uint i;
for (i = 1; i < 16; ++i )
{

// refine endpoints in log2 RGB space
float3 refinedBlockMin = blockMax;
float3 refinedBlockMax = blockMin;
REAL3 refinedBlockMin = blockMax;
REAL3 refinedBlockMax = blockMin;
for (i = 0; i < 16; ++i )
{
refinedBlockMin = min( refinedBlockMin, texels[ i ] == blockMin ? refinedBlockMin : 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 );
REAL3 logBlockMax = log2( blockMax + 1.0 );
REAL3 logBlockMin = log2( blockMin + 1.0 );
REAL3 logRefinedBlockMax = log2( refinedBlockMax + 1.0 );
REAL3 logRefinedBlockMin = log2( refinedBlockMin + 1.0 );
REAL3 logBlockMaxExt = ( logBlockMax - logBlockMin ) * ( 1.0 / 32.0 );
blockMin = exp2( logBlockMin ) - 1.0f;
blockMax = exp2( logBlockMax ) - 1.0f;
float3 blockDir = blockMax - blockMin;
blockMin = exp2( logBlockMin ) - 1.0;
blockMax = exp2( logBlockMax ) - 1.0;
REAL3 blockDir = blockMax - blockMin;
float3 endpoint0 = Quantize10( blockMin );
float3 endpoint1 = Quantize10( blockMax );
float endPoint0Pos = f32tof16( dot( blockMin, blockDir ) );
float endPoint1Pos = f32tof16( dot( blockMax, blockDir ) );
REAL3 endpoint0 = Quantize10( blockMin );
REAL3 endpoint1 = Quantize10( blockMax );
REAL endPoint0Pos = f32tof16( dot( blockMin, blockDir ) );
REAL endPoint1Pos = f32tof16( dot( blockMax, blockDir ) );
float fixupTexelPos = f32tof16( dot( texels[ 0 ], blockDir ) );
REAL fixupTexelPos = f32tof16( dot( texels[ 0 ], blockDir ) );
uint fixupIndex = ComputeIndex4( fixupTexelPos, endPoint0Pos, endPoint1Pos );
if ( fixupIndex > 7 )
{

uint indices[ 16 ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (i = 0; i < 16; ++i )
{
float texelPos = f32tof16( dot( texels[ i ], blockDir ) );
REAL texelPos = f32tof16( dot( texels[ i ], blockDir ) );
float3 endpoint0Unq = Unquantize10( endpoint0 );
float3 endpoint1Unq = Unquantize10( endpoint1 );
float msle = 0.0f;
REAL3 endpoint0Unq = Unquantize10( endpoint0 );
REAL3 endpoint1Unq = Unquantize10( endpoint1 );
REAL msle = 0.0;
float weight = floor( ( indices[ i ] * 64.0f ) / 15.0f + 0.5f );
float3 texelUnc = FinishUnquantize( endpoint0Unq, endpoint1Unq, weight );
REAL weight = floor( ( indices[ i ] * 64.0 ) / 15.0 + 0.5);
REAL3 texelUnc = FinishUnquantize( endpoint0Unq, endpoint1Unq, weight );
msle += CalcMSLE( texels[ i ], texelUnc );
}

190
ScriptableRenderPipeline/Core/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/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;

198
ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl


// VertDefault
// FragDefault / FragForward / FragDeferred
// constant floating number written as 1.0 (not 1, not 1.0f, not 1.0h)
// constant floating number written as 1.0 (not 1, not 1.0, not 1.0h)
// uniform have _ as prefix + uppercase _LowercaseThenCamelCase

// Structure definition that are share between C# and hlsl.
// These structures need to be align on float4 to respect various packing rules from sahder language.
// These structures need to be align on REAL4 to respect various packing rules from sahder language.
// This mean that these structure need to be padded.
// Do not use "in", only "out" or "inout" as califier, not "inline" keyword either, useless.

// headers from ShaderLibrary do not include "common.hlsl", this should be included in the .shader using it (or Material.hlsl)
// 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
// Rules: When doing an array for constant buffer variables, we always use REAL4 to avoid any packing issue, particularly between compute shader and pixel shaders
// uniform float4 packedArray[3];
// static float unpackedArray[12] = (float[12]packedArray;
// uniform REAL4 packedArray[3];
// static REAL unpackedArray[12] = (REAL[12]packedArray;
#ifndef REAL
#define REAL float
#define REAL2 float2
#define REAL3 float3
#define REAL4 float4
#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
#endif
// Include language header
#if defined(SHADER_API_D3D11)

#ifndef INTRINSIC_CUBEMAP_FACE_ID
// TODO: implement this. Is the reference implementation of cubemapID provide by AMD the reverse of our ?
/*
float CubemapFaceID(float3 dir)
REAL CubemapFaceID(REAL3 dir)
float faceID;
REAL faceID;
if (abs(dir.z) >= abs(dir.x) && abs(dir.z) >= abs(dir.y))
{
faceID = (dir.z < 0.0) ? 5.0 : 4.0;

}
*/
void GetCubeFaceID(float3 dir, out int faceIndex)
void GetCubeFaceID(REAL3 dir, out int faceIndex)
float3 adir = abs(dir);
REAL3 adir = abs(dir);
// +Z -Z
faceIndex = dir.z > 0.0 ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;

// Common math functions
// ----------------------------------------------------------------------------
float DegToRad(float deg)
REAL DegToRad(REAL deg)
float RadToDeg(float rad)
REAL RadToDeg(REAL rad)
{
return rad * (180.0 / PI);
}

// Input [0, 1] and output [0, PI/2]
// 9 VALU
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;
}

// Computes (FastSign(s) * x) using 2x VALU.
// See the comment about FastSign() below.
float FastMulBySignOf(float s, float x, bool ignoreNegZero = true)
REAL FastMulBySignOf(REAL s, REAL x, bool ignoreNegZero = true)
{
#if !defined(SHADER_API_GLES)
if (ignoreNegZero)

// Therefore, we treat -0 as +0 by default: FastSign(+0) = FastSign(-0) = 1.
// If (ignoreNegZero = false), FastSign(-0, false) = -1.
// Note that the sign() function in HLSL implements signum, which returns 0 for 0.
float FastSign(float s, bool ignoreNegZero = true)
REAL FastSign(REAL s, bool ignoreNegZero = true)
{
return FastMulBySignOf(s, 1.0, ignoreNegZero);
}

// 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 ComputeTextureLOD(float2 uv)
REAL ComputeTextureLOD(REAL2 uv)
float2 ddx_ = ddx(uv);
float2 ddy_ = ddy(uv);
float d = max(dot(ddx_, ddx_), dot(ddy_, ddy_));
REAL2 ddx_ = ddx(uv);
REAL2 ddy_ = ddy(uv);
REAL d = max(dot(ddx_, ddx_), dot(ddy_, ddy_));
return max(0.5 * log2(d), 0.0);
}

float ComputeTextureLOD(float2 uv, float4 texelSize)
REAL ComputeTextureLOD(REAL2 uv, REAL4 texelSize)
{
uv *= texelSize.zw;

// Texture format sampling
// ----------------------------------------------------------------------------
float2 DirectionToLatLongCoordinate(float3 unDir)
REAL2 DirectionToLatLongCoordinate(REAL3 unDir)
float3 dir = normalize(unDir);
REAL3 dir = normalize(unDir);
return float2(1.0 - 0.5 * INV_PI * atan2(dir.x, -dir.z), asin(dir.y) * INV_PI + 0.5);
return REAL2(1.0 - 0.5 * INV_PI * atan2(dir.x, -dir.z), asin(dir.y) * INV_PI + 0.5);
float3 LatlongToDirectionCoordinate(float2 coord)
REAL3 LatlongToDirectionCoordinate(REAL2 coord)
float theta = coord.y * PI;
float phi = (coord.x * 2.f * PI - PI*0.5f);
REAL theta = coord.y * PI;
REAL phi = (coord.x * 2.f * PI - PI*0.5f);
float cosTheta = cos(theta);
float sinTheta = sqrt(1.0f - min(1.0f, cosTheta*cosTheta));
float cosPhi = cos(phi);
float sinPhi = sin(phi);
REAL cosTheta = cos(theta);
REAL sinTheta = sqrt(1.0 - min(1.0, cosTheta*cosTheta));
REAL cosPhi = cos(phi);
REAL sinPhi = sin(phi);
float3 direction = float3(sinTheta*cosPhi, cosTheta, sinTheta*sinPhi);
REAL3 direction = REAL3(sinTheta*cosPhi, cosTheta, sinTheta*sinPhi);
direction.xy *= -1.0;
return direction;
}

// Z buffer to linear 0..1 depth (0 at near plane, 1 at far plane).
// Does not correctly handle oblique view frustums.
float Linear01DepthFromNear(float depth, float4 zBufferParam)
REAL Linear01DepthFromNear(REAL depth, REAL4 zBufferParam)
{
return 1.0 / (zBufferParam.x + zBufferParam.y / depth);
}

float Linear01Depth(float depth, float4 zBufferParam)
REAL Linear01Depth(REAL depth, REAL4 zBufferParam)
{
return 1.0 / (zBufferParam.x * depth + zBufferParam.y);
}

float LinearEyeDepth(float depth, float4 zBufferParam)
REAL LinearEyeDepth(REAL depth, REAL4 zBufferParam)
{
return 1.0 / (zBufferParam.z * depth + zBufferParam.w);
}

// Ref: An Efficient Depth Linearization Method for Oblique View Frustums, Eq. 6.
float LinearEyeDepth(float2 positionNDC, float deviceDepth, float4 invProjParam)
REAL LinearEyeDepth(REAL2 positionNDC, REAL deviceDepth, REAL4 invProjParam)
float4 positionCS = float4(positionNDC * 2.0 - 1.0, deviceDepth, 1.0);
float viewSpaceZ = rcp(dot(positionCS, invProjParam));
REAL4 positionCS = REAL4(positionNDC * 2.0 - 1.0, deviceDepth, 1.0);
REAL viewSpaceZ = rcp(dot(positionCS, invProjParam));
// The view space uses a right-handed coordinate system.
return -viewSpaceZ;
}

// Typically, this is the cheapest variant, provided you've already computed 'positionWS'.
float LinearEyeDepth(float3 positionWS, float4x4 viewProjMatrix)
REAL LinearEyeDepth(REAL3 positionWS, REAL4x4 viewProjMatrix)
return mul(viewProjMatrix, float4(positionWS, 1.0)).w;
return mul(viewProjMatrix, REAL4(positionWS, 1.0)).w;
}
// ----------------------------------------------------------------------------

static const float3x3 k_identity3x3 = {1, 0, 0,
static const REAL3x3 k_identity3x3 = {1, 0, 0,
static const float4x4 k_identity4x4 = {1, 0, 0, 0,
static const REAL4x4 k_identity4x4 = {1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1};

// (position = positionVS) => (clipSpaceTransform = UNITY_MATRIX_P)
// (position = positionWS) => (clipSpaceTransform = UNITY_MATRIX_VP)
float2 ComputeNormalizedDeviceCoordinates(float3 position, float4x4 clipSpaceTransform = k_identity4x4)
REAL2 ComputeNormalizedDeviceCoordinates(REAL3 position, REAL4x4 clipSpaceTransform = k_identity4x4)
float4 positionCS = mul(clipSpaceTransform, float4(position, 1.0));
float2 positionNDC = positionCS.xy * (rcp(positionCS.w) * 0.5) + 0.5;
REAL4 positionCS = mul(clipSpaceTransform, REAL4(position, 1.0));
REAL2 positionNDC = positionCS.xy * (rcp(positionCS.w) * 0.5) + 0.5;
#if UNITY_UV_STARTS_AT_TOP
positionNDC.y = 1.0 - positionNDC.y;
#endif

float4 ComputeClipSpacePosition(float2 positionNDC, float deviceDepth)
REAL4 ComputeClipSpacePosition(REAL2 positionNDC, REAL deviceDepth)
return float4(positionNDC * 2.0 - 1.0, deviceDepth, 1.0);
return REAL4(positionNDC * 2.0 - 1.0, deviceDepth, 1.0);
float3 ComputeViewSpacePosition(float2 positionNDC, float deviceDepth, float4x4 invProjMatrix)
REAL3 ComputeViewSpacePosition(REAL2 positionNDC, REAL deviceDepth, REAL4x4 invProjMatrix)
float4 positionCS = ComputeClipSpacePosition(positionNDC, deviceDepth);
float4 positionVS = mul(invProjMatrix, positionCS);
REAL4 positionCS = ComputeClipSpacePosition(positionNDC, deviceDepth);
REAL4 positionVS = mul(invProjMatrix, positionCS);
float3 ComputeWorldSpacePosition(float2 positionNDC, float deviceDepth, float4x4 invViewProjMatrix)
REAL3 ComputeWorldSpacePosition(REAL2 positionNDC, REAL deviceDepth, REAL4x4 invViewProjMatrix)
float4 positionCS = ComputeClipSpacePosition(positionNDC, deviceDepth);
float4 hpositionWS = mul(invViewProjMatrix, positionCS);
REAL4 positionCS = ComputeClipSpacePosition(positionNDC, deviceDepth);
REAL4 hpositionWS = mul(invViewProjMatrix, positionCS);
return hpositionWS.xyz / hpositionWS.w;
}

struct PositionInputs
{
float3 positionWS; // World space position (could be camera-relative)
float2 positionNDC; // Normalized screen UVs : [0, 1) (with the half-pixel offset)
REAL3 positionWS; // World space position (could be camera-relative)
REAL2 positionNDC; // Normalized screen UVs : [0, 1) (with the REAL-pixel offset)
float deviceDepth; // Depth from the depth buffer : [0, 1] (typically reversed)
float linearDepth; // View space Z coordinate : [Near, Far]
REAL deviceDepth; // Depth from the depth buffer : [0, 1] (typically reversed)
REAL linearDepth; // View space Z coordinate : [Near, Far]
};
// This function is use to provide an easy way to sample into a screen texture, either from a pixel or a compute shaders.

PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, uint2 tileCoord) // Specify explicit tile coordinates so that we can easily make it lane invariant for compute evaluation.
PositionInputs GetPositionInput(REAL2 positionSS, REAL2 invScreenSize, uint2 tileCoord) // Specify explicit tile coordinates so that we can easily make it lane invariant for compute evaluation.
{
PositionInputs posInput;
ZERO_INITIALIZE(PositionInputs, posInput);

// In case of compute shader an extra half offset is added to the screenPos to shift the integer position to pixel center.
posInput.positionNDC.xy += float2(0.5, 0.5);
// In case of compute shader an extra REAL offset is added to the screenPos to shift the integer position to pixel center.
posInput.positionNDC.xy += REAL2(0.5, 0.5);
#endif
posInput.positionNDC *= invScreenSize;

return posInput;
}
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize)
PositionInputs GetPositionInput(REAL2 positionSS, REAL2 invScreenSize)
{
return GetPositionInput(positionSS, invScreenSize, uint2(0, 0));
}

void UpdatePositionInput(float deviceDepth, float linearDepth, float3 positionWS, inout PositionInputs posInput)
void UpdatePositionInput(REAL deviceDepth, REAL linearDepth, REAL3 positionWS, inout PositionInputs posInput)
{
posInput.deviceDepth = deviceDepth;
posInput.linearDepth = linearDepth;

// From deferred or compute shader
// depth must be the depth from the raw depth buffer. This allow to handle all kind of depth automatically with the inverse view projection matrix.
// For information. In Unity Depth is always in range 0..1 (even on OpenGL) but can be reversed.
void UpdatePositionInput(float deviceDepth, float4x4 invViewProjMatrix, float4x4 viewProjMatrix, inout PositionInputs posInput)
void UpdatePositionInput(REAL deviceDepth, REAL4x4 invViewProjMatrix, REAL4x4 viewProjMatrix, inout PositionInputs posInput)
posInput.linearDepth = mul(viewProjMatrix, float4(posInput.positionWS, 1.0)).w;
posInput.linearDepth = mul(viewProjMatrix, REAL4(posInput.positionWS, 1.0)).w;
void ApplyDepthOffsetPositionInput(float3 V, float depthOffsetVS, float4x4 viewProjMatrix, inout PositionInputs posInput)
void ApplyDepthOffsetPositionInput(REAL3 V, REAL depthOffsetVS, REAL4x4 viewProjMatrix, inout PositionInputs posInput)
float4 positionCS = mul(viewProjMatrix, float4(posInput.positionWS, 1.0));
REAL4 positionCS = mul(viewProjMatrix, REAL4(posInput.positionWS, 1.0));
posInput.linearDepth = positionCS.w;
posInput.deviceDepth = positionCS.z / positionCS.w;
}

// ----------------------------------------------------------------------------
// 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));
float2 GetFullScreenTriangleTexCoord(uint vertexID)
REAL2 GetFullScreenTriangleTexCoord(uint vertexID)
return float2((vertexID << 1) & 2, 1.0 - (vertexID & 2));
return REAL2((vertexID << 1) & 2, 1.0 - (vertexID & 2));
return float2((vertexID << 1) & 2, vertexID & 2);
return REAL2((vertexID << 1) & 2, vertexID & 2);
float4 GetFullScreenTriangleVertexPosition(uint vertexID, float z = UNITY_NEAR_CLIP_VALUE)
REAL4 GetFullScreenTriangleVertexPosition(uint vertexID, REAL z = UNITY_NEAR_CLIP_VALUE)
float2 uv = float2((vertexID << 1) & 2, vertexID & 2);
return float4(uv * 2.0 - 1.0, z, 1.0);
REAL2 uv = REAL2((vertexID << 1) & 2, vertexID & 2);
return REAL4(uv * 2.0 - 1.0, z, 1.0);
}
#if !defined(SHADER_API_GLES)

// LOD1 must use this function with ditherFactor 0..1
void LODDitheringTransition(uint2 positionSS, float ditherFactor)
void LODDitheringTransition(uint2 positionSS, REAL ditherFactor)
float p = GenerateHashedRandomFloat(positionSS);
REAL p = GenerateHashedRandomFloat(positionSS);
// We want to have a symmetry between 0..0.5 ditherFactor and 0.5..1 so no pixels are transparent during the transition
// this is handled by this test which reverse the pattern

144
ScriptableRenderPipeline/Core/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)
REAL ClampToFloat16Max(REAL value)
float2 ClampToFloat16Max(float2 value)
REAL2 ClampToFloat16Max(REAL2 value)
float3 ClampToFloat16Max(float3 value)
REAL3 ClampToFloat16Max(REAL3 value)
float4 ClampToFloat16Max(float4 value)
REAL4 ClampToFloat16Max(REAL4 value)
{
return min(value, HALF_MAX);
}

// 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

// For one, it does not solve the incorrect lookup direction problem, since the normal itself
// is not modified. There is a more insidious issue, however. 'NdotV' is a constituent element
// of the mathematical system describing the relationships between different vectors - and
// not just normal and view vectors, but also light vectors, half vectors, tangent vectors, etc.
// not just normal and view vectors, but also light vectors, REAL vectors, tangent vectors, etc.
// Changing only one angle (or its cosine) leaves the system in an inconsistent state, where
// certain relationships can take on different values depending on whether 'NdotV' is used
// in the calculation or not. Therefore, it is important to change the normal (or another

// 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));
}

58
ScriptableRenderPipeline/Core/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;

void GetTriplanarCoordinate(float3 position, out float2 uvXZ, out float2 uvXY, out float2 uvZY)
void GetTriplanarCoordinate(REAL3 position, out REAL2 uvXZ, out REAL2 uvXY, out REAL2 uvZY)
uvXZ = float2(position.z, position.x);
uvXY = float2(position.x, position.y);
uvZY = float2(position.z, position.y);
uvXZ = REAL2(position.z, position.x);
uvXY = REAL2(position.x, position.y);
uvZY = REAL2(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/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/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;
}

94
ScriptableRenderPipeline/Core/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);

// TODO: the packing here is inefficient as we will fetch values far away from each other and they may not fit into the cache - Suggest we pack RGB continuously
// TODO: The calcul of texcoord could be perform with a single matrix multicplication calcualted on C++ side that will fold probeVolumeMin and probeVolumeSizeInv into it and handle the identity case, no reasons to do it in C++ (ask Ionut about it)
// It should also handle the camera relative path (if the render pipeline use it)
float3 SampleProbeVolumeSH4(TEXTURE3D_ARGS(SHVolumeTexture, SHVolumeSampler), float3 positionWS, float3 normalWS, float4x4 WorldToTexture,
float transformToLocal, float texelSizeX, float3 probeVolumeMin, float3 probeVolumeSizeInv)
REAL3 SampleProbeVolumeSH4(TEXTURE3D_ARGS(SHVolumeTexture, SHVolumeSampler), REAL3 positionWS, REAL3 normalWS, REAL4x4 WorldToTexture,
REAL transformToLocal, REAL texelSizeX, REAL3 probeVolumeMin, REAL3 probeVolumeSizeInv)
float3 position = (transformToLocal == 1.0f) ? mul(WorldToTexture, float4(positionWS, 1.0)).xyz : positionWS;
float3 texCoord = (position - probeVolumeMin) * probeVolumeSizeInv.xyz;
REAL3 position = (transformToLocal == 1.0) ? mul(WorldToTexture, REAL4(positionWS, 1.0)).xyz : positionWS;
REAL3 texCoord = (position - probeVolumeMin) * probeVolumeSizeInv.xyz;
// Clamp to edge of the "internal" texture, as R is from half texel to size of R texture minus half texel.
// Clamp to edge of the "internal" texture, as R is from REAL texel to size of R texture minus REAL texel.
float4 shAr = SAMPLE_TEXTURE3D(SHVolumeTexture, SHVolumeSampler, texCoord);
REAL4 shAr = SAMPLE_TEXTURE3D(SHVolumeTexture, SHVolumeSampler, texCoord);
float4 shAg = SAMPLE_TEXTURE3D(SHVolumeTexture, SHVolumeSampler, texCoord);
REAL4 shAg = SAMPLE_TEXTURE3D(SHVolumeTexture, SHVolumeSampler, texCoord);
float4 shAb = SAMPLE_TEXTURE3D(SHVolumeTexture, SHVolumeSampler, texCoord);
REAL4 shAb = SAMPLE_TEXTURE3D(SHVolumeTexture, SHVolumeSampler, texCoord);
float4 SampleProbeOcclusion(TEXTURE3D_ARGS(SHVolumeTexture, SHVolumeSampler), float3 positionWS, float4x4 WorldToTexture,
float transformToLocal, float texelSizeX, float3 probeVolumeMin, float3 probeVolumeSizeInv)
REAL4 SampleProbeOcclusion(TEXTURE3D_ARGS(SHVolumeTexture, SHVolumeSampler), REAL3 positionWS, REAL4x4 WorldToTexture,
REAL transformToLocal, REAL texelSizeX, REAL3 probeVolumeMin, REAL3 probeVolumeSizeInv)
float3 position = (transformToLocal == 1.0f) ? mul(WorldToTexture, float4(positionWS, 1.0)).xyz : positionWS;
float3 texCoord = (position - probeVolumeMin) * probeVolumeSizeInv.xyz;
REAL3 position = (transformToLocal == 1.0) ? mul(WorldToTexture, REAL4(positionWS, 1.0)).xyz : positionWS;
REAL3 texCoord = (position - probeVolumeMin) * probeVolumeSizeInv.xyz;
// Sample fourth texture in the atlas
// We need to compute proper U coordinate to sample.

// 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)
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), REAL2 uv, REAL4 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), REAL2 uv, REAL4 transform, REAL3 normalWS, bool encodedLightmap)
// in a way, that using it for half Lambert and then dividing by a "rebalancing coefficient"
// in a way, that using it for REAL Lambert and then dividing by a "rebalancing coefficient"
// gives a result close to plain diffuse response lightmaps, but normalmapped.
// Note that dir is not unit length on purpose. Its length is "directionality", like

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);
}

76
ScriptableRenderPipeline/Core/ShaderLibrary/GeometricTools.hlsl


// return furthest near intersection in x and closest far intersection in y
// if (intersections.y > intersections.x) the ray hit the box, else it miss it
// Assume dir is normalize
float2 BoxRayIntersect(float3 start, float3 dir, float3 boxMin, float3 boxMax)
REAL2 BoxRayIntersect(REAL3 start, REAL3 dir, REAL3 boxMin, REAL3 boxMax)
float3 invDir = 1.0 / dir;
REAL3 invDir = 1.0 / dir;
float3 firstPlaneIntersect = (boxMin - start) * invDir;
float3 secondPlaneIntersect = (boxMax - start) * invDir;
REAL3 firstPlaneIntersect = (boxMin - start) * invDir;
REAL3 secondPlaneIntersect = (boxMax - start) * invDir;
float3 closestPlane = min(firstPlaneIntersect, secondPlaneIntersect);
float3 furthestPlane = max(firstPlaneIntersect, secondPlaneIntersect);
REAL3 closestPlane = min(firstPlaneIntersect, secondPlaneIntersect);
REAL3 furthestPlane = max(firstPlaneIntersect, secondPlaneIntersect);
float2 intersections;
REAL2 intersections;
// Find the furthest near intersection
intersections.x = max(closestPlane.x, max(closestPlane.y, closestPlane.z));
// Find the closest far intersection

// This simplified version assume that we care about the result only when we are inside the box
// Assume dir is normalize
float BoxRayIntersectSimple(float3 start, float3 dir, float3 boxMin, float3 boxMax)
REAL BoxRayIntersectSimple(REAL3 start, REAL3 dir, REAL3 boxMin, REAL3 boxMax)
float3 invDir = 1.0 / dir;
REAL3 invDir = 1.0 / dir;
float3 rbmin = (boxMin - start) * invDir;
float3 rbmax = (boxMax - start) * invDir;
REAL3 rbmin = (boxMin - start) * invDir;
REAL3 rbmax = (boxMax - start) * invDir;
float3 rbminmax = (dir > 0.0) ? rbmax : rbmin;
REAL3 rbminmax = (dir > 0.0) ? rbmax : rbmin;
float2 SphereRayIntersect(float3 start, float3 dir, float radius, out bool intersect)
REAL2 SphereRayIntersect(REAL3 start, REAL3 dir, REAL radius, out bool intersect)
float a = dot(dir, dir);
float b = dot(dir, start) * 2.0;
float c = dot(start, start) - radius * radius;
float discriminant = b * b - 4.0 * a * c;
REAL a = dot(dir, dir);
REAL b = dot(dir, start) * 2.0;
REAL c = dot(start, start) - radius * radius;
REAL discriminant = b * b - 4.0 * a * c;
float2 intersections = float2(0.0, 0.0);
REAL2 intersections = REAL2(0.0, 0.0);
intersect = false;
if (discriminant < 0.0 || a == 0.0)
{

else
{
float sqrtDiscriminant = sqrt(discriminant);
REAL sqrtDiscriminant = sqrt(discriminant);
intersections.x = (-b - sqrtDiscriminant) / (2.0 * a);
intersections.y = (-b + sqrtDiscriminant) / (2.0 * a);
intersect = true;

// This simplified version assume that we care about the result only when we are inside the sphere
// Assume Sphere is at the origin (i.e start = position - spherePosition) and dir is normalized
// Ref: http://http.developer.nvidia.com/GPUGems/gpugems_ch19.html
float SphereRayIntersectSimple(float3 start, float3 dir, float radius)
REAL SphereRayIntersectSimple(REAL3 start, REAL3 dir, REAL radius)
float b = dot(dir, start) * 2.0;
float c = dot(start, start) - radius * radius;
float discriminant = b * b - 4.0 * c;
REAL b = dot(dir, start) * 2.0;
REAL c = dot(start, start) - radius * radius;
REAL discriminant = b * b - 4.0 * c;
float3 RayPlaneIntersect(in float3 rayOrigin, in float3 rayDirection, in float3 planeOrigin, in float3 planeNormal)
REAL3 RayPlaneIntersect(in REAL3 rayOrigin, in REAL3 rayDirection, in REAL3 planeOrigin, in REAL3 planeNormal)
float dist = dot(planeNormal, planeOrigin - rayOrigin) / dot(planeNormal, rayDirection);
REAL dist = dot(planeNormal, planeOrigin - rayOrigin) / dot(planeNormal, rayDirection);
return rayOrigin + rayDirection * dist;
}

// Box is AABB
float DistancePointBox(float3 position, float3 boxMin, float3 boxMax)
REAL DistancePointBox(REAL3 position, REAL3 boxMin, REAL3 boxMax)
return length(max(max(position - boxMax, boxMin - position), float3(0.0, 0.0, 0.0)));
return length(max(max(position - boxMax, boxMin - position), REAL3(0.0, 0.0, 0.0)));
float3 ProjectPointOnPlane(float3 position, float3 planePosition, float3 planeNormal)
REAL3 ProjectPointOnPlane(REAL3 position, REAL3 planePosition, REAL3 planeNormal)
{
return position - (dot(position - planePosition, planeNormal) * planeNormal);
}

// Positive -> in front (above), negative -> behind (below).
float DistanceFromPlane(float3 p, float4 plane)
REAL DistanceFromPlane(REAL3 p, REAL4 plane)
return dot(float4(p, 1.0), plane);
return dot(REAL4(p, 1.0), plane);
bool CullTriangleFrustum(float3 p0, float3 p1, float3 p2, float epsilon, float4 frustumPlanes[6], int numPlanes)
bool CullTriangleFrustum(REAL3 p0, REAL3 p1, REAL3 p2, REAL epsilon, REAL4 frustumPlanes[6], int numPlanes)
{
bool outside = false;

// Returns 'true' if the edge of the triangle is outside of the frustum.
// The edges are defined s.t. they are on the opposite side of the point with the given index.
// 'epsilon' is the (negative) distance to (outside of) the frustum below which we cull the triangle.
bool3 CullTriangleEdgesFrustum(float3 p0, float3 p1, float3 p2, float epsilon, float4 frustumPlanes[6], int numPlanes)
bool3 CullTriangleEdgesFrustum(REAL3 p0, REAL3 p1, REAL3 p2, REAL epsilon, REAL4 frustumPlanes[6], int numPlanes)
{
bool3 edgesOutside = false;

// Returns 'true' if a triangle defined by 3 vertices is back-facing.
// 'epsilon' is the (negative) value of dot(N, V) below which we cull the triangle.
// 'winding' can be used to change the order: pass 1 for (p0 -> p1 -> p2), or -1 for (p0 -> p2 -> p1).
bool CullTriangleBackFace(float3 p0, float3 p1, float3 p2, float epsilon, float3 viewPos, float winding)
bool CullTriangleBackFace(REAL3 p0, REAL3 p1, REAL3 p2, REAL epsilon, REAL3 viewPos, REAL winding)
float3 edge1 = p1 - p0;
float3 edge2 = p2 - p0;
REAL3 edge1 = p1 - p0;
REAL3 edge2 = p2 - p0;
float3 N = cross(edge1, edge2);
float3 V = viewPos - p0;
float NdotV = dot(N, V) * winding;
REAL3 N = cross(edge1, edge2);
REAL3 V = viewPos - p0;
REAL NdotV = dot(N, V) * winding;
// Optimize:
// NdotV / (length(N) * length(V)) < Epsilon

320
ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl


// 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,
void SampleVisibleAnisoGGXDir(REAL2 u, REAL3 V, REAL3x3 localToWorld,
REAL roughnessT, REAL roughnessB,
out REAL3 L,
out REAL NdotL,
out REAL NdotH,
out REAL VdotH,
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)
// Convert sample from half angle to incident angle
// Convert sample from REAL angle to incident angle
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.
// Note: we take the sample in between two texels, and also apply the REAL-texel offset.
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

42
ScriptableRenderPipeline/Core/ShaderLibrary/Macros.hlsl


#define CENTIMETERS_PER_METER 100
#define METERS_PER_CENTIMETER rcp(CENTIMETERS_PER_METER)
#define FLT_EPS 5.960464478e-8 // 2^-24, machine epsilon: 1 + EPS = 1 (half of the ULP for 1)
#define FLT_EPS 5.960464478e-8 // 2^-24, machine epsilon: 1 + EPS = 1 (REAL 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 TEMPLATE_1_FLT(FunctionName, Parameter1, FunctionBody) \
float FunctionName(float Parameter1) { FunctionBody; } \
float2 FunctionName(float2 Parameter1) { FunctionBody; } \
float3 FunctionName(float3 Parameter1) { FunctionBody; } \
float4 FunctionName(float4 Parameter1) { FunctionBody; }
REAL FunctionName(REAL Parameter1) { FunctionBody; } \
REAL2 FunctionName(REAL2 Parameter1) { FunctionBody; } \
REAL3 FunctionName(REAL3 Parameter1) { FunctionBody; } \
REAL4 FunctionName(REAL4 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; }
REAL FunctionName(REAL Parameter1, REAL Parameter2) { FunctionBody; } \
REAL2 FunctionName(REAL2 Parameter1, REAL2 Parameter2) { FunctionBody; } \
REAL3 FunctionName(REAL3 Parameter1, REAL3 Parameter2) { FunctionBody; } \
REAL4 FunctionName(REAL4 Parameter1, REAL4 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; }
REAL FunctionName(REAL Parameter1, REAL Parameter2, REAL Parameter3) { FunctionBody; } \
REAL2 FunctionName(REAL2 Parameter1, REAL2 Parameter2, REAL2 Parameter3) { FunctionBody; } \
REAL3 FunctionName(REAL3 Parameter1, REAL3 Parameter2, REAL3 Parameter3) { FunctionBody; } \
REAL4 FunctionName(REAL4 Parameter1, REAL4 Parameter2, REAL4 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/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;
}

262
ScriptableRenderPipeline/Core/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)
{
//float l1norm = dot(abs(n), 1.0);
//float2 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);
// Optimized version of above code:
n *= rcp(dot(abs(n), 1.0));
float t = saturate(-n.z);
return n.xy + (n.xy >= 0.0 ? t : -t);
// return REAL between [-1, 1]
REAL2 PackNormalOctEncode(REAL3 n)
{
//REAL l1norm = dot(abs(n), 1.0);
//REAL2 res0 = n.xy * (1.0 / l1norm);
//REAL2 val = 1.0 - abs(res0.yx);
//return (n.zz < REAL2(0.0, 0.0) ? (res0 >= 0.0 ? val : -val) : res0);
// Optimized version of above code:
n *= rcp(dot(abs(n), 1.0));
REAL t = saturate(-n.z);
return n.xy + (n.xy >= 0.0 ? t : -t);
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));
uint PackToR11G11B10f(float3 rgb)
uint PackToR11G11B10f(REAL3 rgb)
{
uint r = (f32tof16(rgb.x) << 17) & 0xFFE00000;
uint g = (f32tof16(rgb.y) << 6) & 0x001FFC00;

float3 UnpackFromR11G11B10f(uint rgb)
REAL3 UnpackFromR11G11B10f(uint rgb)
float r = f16tof32((rgb >> 17) & 0x7FF0);
float g = f16tof32((rgb >> 6) & 0x7FF0);
float b = f16tof32((rgb << 5) & 0x7FE0);
return float3(r, g, b);
REAL r = f16tof32((rgb >> 17) & 0x7FF0);
REAL g = f16tof32((rgb >> 6) & 0x7FF0);
REAL b = f16tof32((rgb << 5) & 0x7FE0);
return REAL3(r, g, b);
}
#endif // SHADER_API_GLES

/*
// 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/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/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

18
ScriptableRenderPipeline/Core/ShaderLibrary/Random.hlsl


return JenkinsHash(v.x ^ JenkinsHash(v.y) ^ JenkinsHash(v.z) ^ JenkinsHash(v.w));
}
// Construct a float with half-open range [0, 1) using low 23 bits.
// Construct a REAL with REAL-open range [0, 1) using low 23 bits.
float ConstructFloat(int m) {
REAL ConstructFloat(int m) {
const int ieeeMantissa = 0x007FFFFF; // Binary FP32 mantissa bitmask
const int ieeeOne = 0x3F800000; // 1.0 in FP32 IEEE

float f = asfloat(m); // Range [1, 2)
REAL f = asfloat(m); // Range [1, 2)
float ConstructFloat(uint m)
REAL ConstructFloat(uint m)
// Pseudo-random value in half-open range [0, 1). The distribution is reasonably uniform.
// Pseudo-random value in REAL-open range [0, 1). The distribution is reasonably uniform.
float GenerateHashedRandomFloat(uint x)
REAL GenerateHashedRandomFloat(uint x)
float GenerateHashedRandomFloat(uint2 v)
REAL GenerateHashedRandomFloat(uint2 v)
float GenerateHashedRandomFloat(uint3 v)
REAL GenerateHashedRandomFloat(uint3 v)
float GenerateHashedRandomFloat(uint4 v)
REAL GenerateHashedRandomFloat(uint4 v)
{
return ConstructFloat(JenkinsHash(v));
}

32
ScriptableRenderPipeline/Core/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 distance; // length of the transmission during refraction through the shape
REAL3 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, REAL3 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 distance = -NoR1 * thickness;
float3 P1 = positionWS + R1 * distance;
REAL3 P1 = positionWS + R1 * distance;
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);
RefractionModelResult result;
result.distance = distance;

return result;
}
RefractionModelResult RefractionModelPlane(float3 V, float3 positionWS, float3 normalWS, float ior, float thickness)
RefractionModelResult RefractionModelPlane(REAL3 V, REAL3 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 distance = thickness / dot(R, -normalWS);
RefractionModelResult result;
result.distance = distance;

434
ScriptableRenderPipeline/Core/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

752
ScriptableRenderPipeline/Core/ShaderLibrary/Sampling/Hammersley.hlsl


#endif
}
float VanDerCorputBase2(uint i)
REAL VanDerCorputBase2(uint i)
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)
{

16
ScriptableRenderPipeline/Core/ShaderLibrary/Sampling/SampleUVMapping.hlsl


struct UVMapping
{
int mappingType;
float2 uv; // Current uv or planar uv
REAL2 uv; // Current uv or planar uv
float2 uvZY;
float2 uvXZ;
float2 uvXY;
REAL2 uvZY;
REAL2 uvXZ;
REAL2 uvXY;
float3 normalWS; // vertex normal
float3 triplanarWeights;
REAL3 normalWS; // vertex normal
REAL3 triplanarWeights;
float3 tangentWS;
float3 bitangentWS;
REAL3 tangentWS;
REAL3 bitangentWS;
// TODO: store also object normal map for object triplanar
#endif
};

6
ScriptableRenderPipeline/Core/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/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);

208
ScriptableRenderPipeline/Core/ShaderLibrary/Sampling/Sampling.hlsl


#include "Fibonacci.hlsl"
#include "Hammersley.hlsl"
float Hash(uint s)
REAL Hash(uint s)
{
s = s ^ 2747636419u;
s = s * 2654435769u;

s = s * 2654435769u;
return float(s) / 4294967295.0;
return REAL(s) / 4294967295.0;
float2 InitRandom(float2 input)
REAL2 InitRandom(REAL2 input)
float2 r;
REAL2 r;
r.x = Hash(uint(input.x * 4294967295.0));
r.y = Hash(uint(input.y * 4294967295.0));

//-----------------------------------------------------------------------------
// Transforms the unit vector from the spherical to the Cartesian (right-handed, Z up) coordinate.
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);

58
ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/Resources/ShadowBlurMoments.compute


#include "../ShadowMoments.hlsl"
#if MAX_MSAA > 1
Texture2DMS<float> depthTex;
Texture2DMS<REAL> depthTex;
Texture2D<float> depthTex;
Texture2D<REAL> depthTex;
uniform float4 blurWeightsStorage[3]; // Unity expects float arrays to be tightly packed
static float blurWeights[12] = (float[12])blurWeightsStorage;
uniform REAL4 blurWeightsStorage[3]; // Unity expects REAL arrays to be tightly packed
static REAL blurWeights[12] = (REAL[12])blurWeightsStorage;
static const int kBits_16 = 1; // 16 bits per channel
static const int kChannels_2 = 2; // 2 channels per pixel

# define SHADOW_MOMENTS 2
float2 DepthToMoments( float depth )
REAL2 DepthToMoments( REAL depth )
return float2( depth, depth * depth );
return REAL2( depth, depth * depth );
uniform float evsmExponent;
uniform REAL evsmExponent;
float2 DepthToMoments( float depth )
REAL2 DepthToMoments( REAL depth )
float2 moments = ShadowMoments_WarpDepth( depth, evsmExponent.xx );
return float2( moments.x, moments.x * moments.x );
REAL2 moments = ShadowMoments_WarpDepth( depth, evsmExponent.xx );
return REAL2( moments.x, moments.x * moments.x );
uniform float2 evsmExponents;
uniform REAL2 evsmExponents;
float4 DepthToMoments( float depth )
REAL4 DepthToMoments( REAL depth )
float2 moments = ShadowMoments_WarpDepth( depth, evsmExponents );
return float4( moments.xy, moments.xy * moments.xy );
REAL2 moments = ShadowMoments_WarpDepth( depth, evsmExponents );
return REAL4( moments.xy, moments.xy * moments.xy );
float4 DepthToMoments( float depth )
REAL4 DepthToMoments( REAL depth )
float dsq = depth * depth;
return float4( depth, dsq, depth * dsq, dsq * dsq );
REAL dsq = depth * depth;
return REAL4( depth, dsq, depth * dsq, dsq * dsq );
}
}
#else

#define BLUR_BORDER (BLUR_SIZE / 2)
#define LDS_STRIDE (THREADS + BLUR_BORDER + BLUR_BORDER)
#define moment_t MERGE_NAME( float, SHADOW_MOMENTS )
#define moment_t MERGE_NAME( REAL, SHADOW_MOMENTS )
groupshared float moments1[THREADS * LDS_STRIDE]; // contains the blurred first moment
groupshared float moments2[THREADS * LDS_STRIDE]; // contains the blurred second moment
groupshared float moments3[THREADS * LDS_STRIDE]; // contains the blurred third moment
groupshared float moments4[THREADS * LDS_STRIDE]; // contains the blurred fourth moment
groupshared REAL moments1[THREADS * LDS_STRIDE]; // contains the blurred first moment
groupshared REAL moments2[THREADS * LDS_STRIDE]; // contains the blurred second moment
groupshared REAL moments3[THREADS * LDS_STRIDE]; // contains the blurred third moment
groupshared REAL moments4[THREADS * LDS_STRIDE]; // contains the blurred fourth moment
groupshared float sampleWeights[MAX_MSAA];
groupshared float sumWeights;
groupshared REAL sampleWeights[MAX_MSAA];
groupshared REAL sumWeights;
int getLDSIdx( int2 pos, int stride )
{

uint width, height, sampleCnt;
depthTex.GetDimensions( width, height, sampleCnt );
sampleCnt = clamp( sampleCnt, 2, MAX_MSAA );
float sampleCntRcp = 1.0 / sampleCnt;
REAL sampleCntRcp = 1.0 / sampleCnt;
float2 spos = depthTex.GetSamplePosition( groupThreadId.x );
REAL2 spos = depthTex.GetSamplePosition( groupThreadId.x );
float sum = 0.0;
REAL sum = 0.0;
for( uint i = 0; i < sampleCnt; i++ )
sum += sampleWeights[i];
sumWeights = 1.0 / sum;

[loop]
for( uint is = 0; is < sampleCnt; is++ )
{
float depth = depthTex.Load( min( srcIdx, validSrc ), is ).x;
REAL depth = depthTex.Load( min( srcIdx, validSrc ), is ).x;
depth = reverse_z ? (1.0 - depth) : depth;
# if SHADOW_MOMENT_ALGORITHM == MSM
// We're pancaking triangles to znear in the depth pass so depth and subsequently all moments can end up being zero.

writeToShared( avgMoments, int2( ldsIdx.x, groupThreadId.y ), LDS_STRIDE );
#else
float depth = depthTex.Load( int3( min( srcIdx, validSrc ), 0 ) ).x;
REAL depth = depthTex.Load( int3( min( srcIdx, validSrc ), 0 ) ).x;
depth = reverse_z ? (1.0 - depth) : depth;
# if SHADOW_MOMENT_ALGORITHM == MSM
// We're pancaking triangles to znear in the depth pass so depth and subsequently all moments can end up being zero.

24
ScriptableRenderPipeline/Core/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/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;
}

82
ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowMoments.hlsl


// Chebychev's inequality (one-tailed version)
// P( x >= t ) <= pmax(t) := sigma^2 / (sigma^2 + (t - u)^2)
// for us t is depth, u is E(x) i.d. the blurred depth
float ShadowMoments_ChebyshevsInequality( float2 moments, float depth, float minVariance, float lightLeakBias )
REAL ShadowMoments_ChebyshevsInequality( REAL2 moments, REAL depth, REAL minVariance, REAL lightLeakBias )
float variance = max( moments.y - (moments.x * moments.x), minVariance );
REAL variance = max( moments.y - (moments.x * moments.x), minVariance );
float mD = depth - moments.x;
float p = variance / (variance + mD * mD);
REAL mD = depth - moments.x;
REAL p = variance / (variance + mD * mD);
p = saturate( (p - lightLeakBias) / (1.0f - lightLeakBias) );
p = saturate( (p - lightLeakBias) / (1.0 - lightLeakBias) );
float2 ShadowMoments_WarpDepth( float depth, float2 exponents )
REAL2 ShadowMoments_WarpDepth( REAL depth, REAL2 exponents )
float pos = exp( exponents.x * depth );
float neg = -exp(-exponents.y * depth );
return float2( pos, neg );
REAL pos = exp( exponents.x * depth );
REAL neg = -exp(-exponents.y * depth );
return REAL2( pos, neg );
// 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 REAL
float4 ShadowMoments_Encode16MSM( float depth )
REAL4 ShadowMoments_Encode16MSM( REAL depth )
float dsq = depth * depth;
float4 moments = { depth, dsq, depth * dsq, dsq * dsq };
float4x4 mat = { - 2.07224649 , 13.7948857237, 0.105877704 , 9.7924062118,
REAL dsq = depth * depth;
REAL4 moments = { depth, dsq, depth * dsq, dsq * dsq };
REAL4x4 mat = { - 2.07224649 , 13.7948857237, 0.105877704 , 9.7924062118,
float4 optimized = mul( moments, mat );
REAL4 optimized = mul( moments, mat );
float4 ShadowMoments_Decode16MSM( float4 moments )
REAL4 ShadowMoments_Decode16MSM( REAL4 moments )
float4x4 mat = { 0.2227744146, 0.1549679261, 0.1451988946, 0.163127443,
REAL4x4 mat = { 0.2227744146, 0.1549679261, 0.1451988946, 0.163127443,
0.0771972861, 0.1394629426, 0.2120202157, 0.2591432266,
0.7926986636, 0.7963415838, 0.7258694464, 0.6539092497,
0.0319417555, -0.1722823173, -0.2758014811, -0.3376131734 };

// Note: Don't call this with all moments being equal or 0.0, otherwise this code degenerates into lots of +/-inf calculations
// which don't behave quite the same on all hardware.
void ShadowMoments_SolveMSM( float4 moments, float depth, float momentBias, out float3 z, out float4 b )
void ShadowMoments_SolveMSM( REAL4 moments, REAL depth, REAL momentBias, out REAL3 z, out REAL4 b )
{
// Bias input data to avoid artifacts
z[0] = depth;

float L32D22 = mad( -b[0], b[1], b[2] );
float D22 = mad( -b[0], b[0], b[1] );
float sqDepthVar = mad( -b[1], b[1], b[3] );
float D33D22 = dot( float2( sqDepthVar, -L32D22 ), float2( D22, L32D22 ) );
float InvD22 = 1.0 / D22;
float L32 = L32D22 * InvD22;
REAL L32D22 = mad( -b[0], b[1], b[2] );
REAL D22 = mad( -b[0], b[0], b[1] );
REAL sqDepthVar = mad( -b[1], b[1], b[3] );
REAL D33D22 = dot( REAL2( sqDepthVar, -L32D22 ), REAL2( D22, L32D22 ) );
REAL InvD22 = 1.0 / D22;
REAL L32 = L32D22 * InvD22;
float3 c = float3( 1.0, z[0], z[0] * z[0] );
REAL3 c = REAL3( 1.0, z[0], z[0] * z[0] );
// Forward substitution to solve L * c1 = bz;
c[1] -= b.x;
c[2] -= b.y + L32 * c[1];

c[1] -= L32 * c[2];
c[0] -= dot( c.yz, b.xy );
// Solve the quadratic equation c[0] + c[1] * z + c[2] * z^2 to obtain solutions z[1] and z[2]
float p = c[1] / c[2];
float q = c[0] / c[2];
float D = ((p*p) * 0.25) - q;
float r = sqrt( D );
REAL p = c[1] / c[2];
REAL q = c[0] / c[2];
REAL D = ((p*p) * 0.25) - q;
REAL r = sqrt( D );
float ShadowMoments_SolveDelta3MSM( float3 z, float2 b, float lightLeakBias )
REAL ShadowMoments_SolveDelta3MSM( REAL3 z, REAL2 b, REAL lightLeakBias )
float4 switchVal = (z[2] < z[0]) ? float4( z[1], z[0], 1.0, 1.0 )
: ((z[1] < z[0]) ? float4( z[0], z[1], 0.0, 1.0 ) : 0.0.xxxx);
REAL4 switchVal = (z[2] < z[0]) ? REAL4( z[1], z[0], 1.0, 1.0 )
: ((z[1] < z[0]) ? REAL4( z[0], z[1], 0.0, 1.0 ) : 0.0.xxxx);
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 );
REAL quotient = (switchVal[0] * z[2] - b[0] * (switchVal[0] + z[2]) + b[1]) / ((z[2] - switchVal[1]) * (z[0] - z[1]));
REAL 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)
REAL ShadowMoments_SolveDelta4MSM( REAL3 z, REAL4 b, REAL lightLeakBias)
float zFree = ((b[2] - b[1]) * z[0] + b[2] - b[3]) / ((b[1] - b[0]) * z[0] + b[1] - b[2]);
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] );
REAL zFree = ((b[2] - b[1]) * z[0] + b[2] - b[3]) / ((b[1] - b[0]) * z[0] + b[1] - b[2]);
REAL w1Factor = (z[0] > zFree) ? 1.0 : 0.0;
REAL 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/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/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/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/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);
}

88
ScriptableRenderPipeline/Core/ShaderLibrary/Wind.hlsl


TEXTURE2D(WIND_SETTINGS_TexGust);
SAMPLER(sampler_WIND_SETTINGS_TexGust);
float4 WIND_SETTINGS_WorldDirectionAndSpeed;
float WIND_SETTINGS_FlexNoiseScale;
float WIND_SETTINGS_ShiverNoiseScale;
float WIND_SETTINGS_Turbulence;
float WIND_SETTINGS_GustSpeed;
float WIND_SETTINGS_GustScale;
float WIND_SETTINGS_GustWorldScale;
REAL4 WIND_SETTINGS_WorldDirectionAndSpeed;
REAL WIND_SETTINGS_FlexNoiseScale;
REAL WIND_SETTINGS_ShiverNoiseScale;
REAL WIND_SETTINGS_Turbulence;
REAL WIND_SETTINGS_GustSpeed;
REAL WIND_SETTINGS_GustScale;
REAL WIND_SETTINGS_GustWorldScale;
float AttenuateTrunk(float x, float s)
REAL AttenuateTrunk(REAL x, REAL s)
float r = (x / s);
REAL r = (x / s);
float3 Rotate(float3 pivot, float3 position, float3 rotationAxis, float angle)
REAL3 Rotate(REAL3 pivot, REAL3 position, REAL3 rotationAxis, REAL angle)
float3 cpa = pivot + rotationAxis * dot(rotationAxis, position - pivot);
REAL3 cpa = pivot + rotationAxis * dot(rotationAxis, position - pivot);
float3 Direction;
float Strength;
float3 ShiverStrength;
float3 ShiverDirection;
REAL3 Direction;
REAL Strength;
REAL3 ShiverStrength;
REAL3 ShiverDirection;
float3 texNoise(float3 worldPos, float LOD)
REAL3 texNoise(REAL3 worldPos, REAL LOD)
float texGust(float3 worldPos, float LOD)
REAL texGust(REAL3 worldPos, REAL LOD)
WindData GetAnalyticalWind(float3 WorldPosition, float3 PivotPosition, float drag, float shiverDrag, float initialBend, float4 time)
WindData GetAnalyticalWind(REAL3 WorldPosition, REAL3 PivotPosition, REAL drag, REAL shiverDrag, REAL initialBend, REAL4 time)
float3 normalizedDir = normalize(WIND_SETTINGS_WorldDirectionAndSpeed.xyz);
REAL3 normalizedDir = normalize(WIND_SETTINGS_WorldDirectionAndSpeed.xyz);
float3 worldOffset = normalizedDir * WIND_SETTINGS_WorldDirectionAndSpeed.w * time.y;
float3 gustWorldOffset = normalizedDir * WIND_SETTINGS_GustSpeed * time.y;
REAL3 worldOffset = normalizedDir * WIND_SETTINGS_WorldDirectionAndSpeed.w * time.y;
REAL3 gustWorldOffset = normalizedDir * WIND_SETTINGS_GustSpeed * time.y;
float3 trunk = float3(0,0,0);
REAL3 trunk = REAL3(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;
REAL gust = 0.0;
if(WIND_SETTINGS_GustSpeed > 0.0f)
if(WIND_SETTINGS_GustSpeed > 0.0)
float3 trunkNoise =
REAL3 trunkNoise =
(
(normalizedDir * WIND_SETTINGS_WorldDirectionAndSpeed.w)
+ (gust * normalizedDir * WIND_SETTINGS_GustSpeed)

// Shiver Noise
float3 shiverNoise = texNoise((WorldPosition - worldOffset)*WIND_SETTINGS_ShiverNoiseScale,0) * shiverDrag * WIND_SETTINGS_Turbulence;
REAL3 shiverNoise = texNoise((WorldPosition - worldOffset)*WIND_SETTINGS_ShiverNoiseScale,0) * shiverDrag * WIND_SETTINGS_Turbulence;
float3 dir = trunkNoise;
float flex = length(trunkNoise) + initialBend;
float shiver = length(shiverNoise);
REAL3 dir = trunkNoise;
REAL flex = length(trunkNoise) + initialBend;
REAL shiver = length(shiverNoise);
result.Direction = dir;
result.ShiverDirection = shiverNoise;

void ApplyWindDisplacement( inout float3 positionWS,
float3 normalWS,
float3 rootWP,
float stiffness,
float drag,
float shiverDrag,
float shiverDirectionality,
float initialBend,
float shiverMask,
float4 time)
void ApplyWindDisplacement( inout REAL3 positionWS,
REAL3 normalWS,
REAL3 rootWP,
REAL stiffness,
REAL drag,
REAL shiverDrag,
REAL shiverDirectionality,
REAL initialBend,
REAL shiverMask,
REAL4 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);
REAL att = AttenuateTrunk(distance(positionWS, rootWP), stiffness);
REAL3 rotAxis = cross(REAL3(0, 1, 0), wind.Direction);
float3 shiverDirection = normalize(lerp(normalWS, normalize(wind.Direction + wind.ShiverDirection), shiverDirectionality));
REAL3 shiverDirection = normalize(lerp(normalWS, normalize(wind.Direction + wind.ShiverDirection), shiverDirectionality));
positionWS += wind.ShiverStrength * shiverDirection * shiverMask;
}

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


fileFormatVersion: 2
guid: 3a4343f81dd267d4cbbd6726951946b3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存