No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

EntityLighting.hlsl 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #ifndef UNITY_ENTITY_LIGHTING_INCLUDED
  2. #define UNITY_ENTITY_LIGHTING_INCLUDED
  3. #if SHADER_API_MOBILE || SHADER_API_GLES3 || SHADER_API_SWITCH || defined(UNITY_UNIFIED_SHADER_PRECISION_MODEL)
  4. #pragma warning (disable : 3205) // conversion of larger type to smaller
  5. #endif
  6. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
  7. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
  8. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/SphericalHarmonics.hlsl"
  9. #define LIGHTMAP_RGBM_MAX_GAMMA real(5.0) // NB: Must match value in RGBMRanges.h
  10. #define LIGHTMAP_RGBM_MAX_LINEAR real(34.493242) // LIGHTMAP_RGBM_MAX_GAMMA ^ 2.2
  11. #ifdef UNITY_LIGHTMAP_RGBM_ENCODING
  12. #ifdef UNITY_COLORSPACE_GAMMA
  13. #define LIGHTMAP_HDR_MULTIPLIER LIGHTMAP_RGBM_MAX_GAMMA
  14. #define LIGHTMAP_HDR_EXPONENT real(1.0) // Not used in gamma color space
  15. #else
  16. #define LIGHTMAP_HDR_MULTIPLIER LIGHTMAP_RGBM_MAX_LINEAR
  17. #define LIGHTMAP_HDR_EXPONENT real(2.2)
  18. #endif
  19. #elif defined(UNITY_LIGHTMAP_DLDR_ENCODING)
  20. #ifdef UNITY_COLORSPACE_GAMMA
  21. #define LIGHTMAP_HDR_MULTIPLIER real(2.0)
  22. #else
  23. #define LIGHTMAP_HDR_MULTIPLIER real(4.59) // 2.0 ^ 2.2
  24. #endif
  25. #define LIGHTMAP_HDR_EXPONENT real(0.0)
  26. #else // (UNITY_LIGHTMAP_FULL_HDR)
  27. #define LIGHTMAP_HDR_MULTIPLIER real(1.0)
  28. #define LIGHTMAP_HDR_EXPONENT real(1.0)
  29. #endif
  30. // This sample a 3D volume storing SH
  31. // Volume is store as 3D texture with 4 R, G, B, Occ set of 4 coefficient store atlas in same 3D texture. Occ is use for occlusion.
  32. // 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
  33. // 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)
  34. // It should also handle the camera relative path (if the render pipeline use it)
  35. // bakeDiffuseLighting and backBakeDiffuseLighting must be initialize outside the function
  36. void SampleProbeVolumeSH4(TEXTURE3D_PARAM(SHVolumeTexture, SHVolumeSampler), float3 positionWS, float3 normalWS, float3 backNormalWS, float4x4 WorldToTexture,
  37. float transformToLocal, float texelSizeX, float3 probeVolumeMin, float3 probeVolumeSizeInv,
  38. inout float3 bakeDiffuseLighting, inout float3 backBakeDiffuseLighting)
  39. {
  40. float3 position = (transformToLocal == 1.0) ? mul(WorldToTexture, float4(positionWS, 1.0)).xyz : positionWS;
  41. float3 texCoord = (position - probeVolumeMin) * probeVolumeSizeInv.xyz;
  42. // Each component is store in the same texture 3D. Each use one quater on the x axis
  43. // Here we get R component then increase by step size (0.25) to get other component. This assume 4 component
  44. // but last one is not used.
  45. // Clamp to edge of the "internal" texture, as R is from half texel to size of R texture minus half texel.
  46. // This avoid leaking
  47. texCoord.x = clamp(texCoord.x * 0.25, 0.5 * texelSizeX, 0.25 - 0.5 * texelSizeX);
  48. float4 shAr = SAMPLE_TEXTURE3D_LOD(SHVolumeTexture, SHVolumeSampler, texCoord, 0);
  49. texCoord.x += 0.25;
  50. float4 shAg = SAMPLE_TEXTURE3D_LOD(SHVolumeTexture, SHVolumeSampler, texCoord, 0);
  51. texCoord.x += 0.25;
  52. float4 shAb = SAMPLE_TEXTURE3D_LOD(SHVolumeTexture, SHVolumeSampler, texCoord, 0);
  53. bakeDiffuseLighting += SHEvalLinearL0L1(normalWS, shAr, shAg, shAb);
  54. backBakeDiffuseLighting += SHEvalLinearL0L1(backNormalWS, shAr, shAg, shAb);
  55. }
  56. // Just a shortcut that call function above
  57. float3 SampleProbeVolumeSH4(TEXTURE3D_PARAM(SHVolumeTexture, SHVolumeSampler), float3 positionWS, float3 normalWS, float4x4 WorldToTexture,
  58. float transformToLocal, float texelSizeX, float3 probeVolumeMin, float3 probeVolumeSizeInv)
  59. {
  60. float3 backNormalWSUnused = 0.0;
  61. float3 bakeDiffuseLighting = 0.0;
  62. float3 backBakeDiffuseLightingUnused = 0.0;
  63. SampleProbeVolumeSH4(TEXTURE3D_ARGS(SHVolumeTexture, SHVolumeSampler), positionWS, normalWS, backNormalWSUnused, WorldToTexture,
  64. transformToLocal, texelSizeX, probeVolumeMin, probeVolumeSizeInv,
  65. bakeDiffuseLighting, backBakeDiffuseLightingUnused);
  66. return bakeDiffuseLighting;
  67. }
  68. // The SphericalHarmonicsL2 coefficients are packed into 7 coefficients per color channel instead of 9.
  69. // The packing from 9 to 7 is done from engine code and will use the alpha component of the pixel to store an additional SH coefficient.
  70. // The 3D atlas texture will contain 7 SH coefficient parts.
  71. // bakeDiffuseLighting and backBakeDiffuseLighting must be initialize outside the function
  72. void SampleProbeVolumeSH9(TEXTURE3D_PARAM(SHVolumeTexture, SHVolumeSampler), float3 positionWS, float3 normalWS, float3 backNormalWS, float4x4 WorldToTexture,
  73. float transformToLocal, float texelSizeX, float3 probeVolumeMin, float3 probeVolumeSizeInv,
  74. inout float3 bakeDiffuseLighting, inout float3 backBakeDiffuseLighting)
  75. {
  76. float3 position = (transformToLocal == 1.0f) ? mul(WorldToTexture, float4(positionWS, 1.0)).xyz : positionWS;
  77. float3 texCoord = (position - probeVolumeMin) * probeVolumeSizeInv;
  78. const uint shCoeffCount = 7;
  79. const float invShCoeffCount = 1.0f / float(shCoeffCount);
  80. // We need to compute proper X coordinate to sample into the atlas.
  81. texCoord.x = texCoord.x / shCoeffCount;
  82. // Clamp the x coordinate otherwise we'll have leaking between RGB coefficients.
  83. float texCoordX = clamp(texCoord.x, 0.5f * texelSizeX, invShCoeffCount - 0.5f * texelSizeX);
  84. float4 SHCoefficients[7];
  85. for (uint i = 0; i < shCoeffCount; i++)
  86. {
  87. texCoord.x = texCoordX + i * invShCoeffCount;
  88. SHCoefficients[i] = SAMPLE_TEXTURE3D_LOD(SHVolumeTexture, SHVolumeSampler, texCoord, 0);
  89. }
  90. bakeDiffuseLighting += SampleSH9(SHCoefficients, normalize(normalWS));
  91. backBakeDiffuseLighting += SampleSH9(SHCoefficients, normalize(backNormalWS));
  92. }
  93. // Just a shortcut that call function above
  94. float3 SampleProbeVolumeSH9(TEXTURE3D_PARAM(SHVolumeTexture, SHVolumeSampler), float3 positionWS, float3 normalWS, float4x4 WorldToTexture,
  95. float transformToLocal, float texelSizeX, float3 probeVolumeMin, float3 probeVolumeSizeInv)
  96. {
  97. float3 backNormalWSUnused = 0.0;
  98. float3 bakeDiffuseLighting = 0.0;
  99. float3 backBakeDiffuseLightingUnused = 0.0;
  100. SampleProbeVolumeSH9(TEXTURE3D_ARGS(SHVolumeTexture, SHVolumeSampler), positionWS, normalWS, backNormalWSUnused, WorldToTexture,
  101. transformToLocal, texelSizeX, probeVolumeMin, probeVolumeSizeInv,
  102. bakeDiffuseLighting, backBakeDiffuseLightingUnused);
  103. return bakeDiffuseLighting;
  104. }
  105. float4 SampleProbeOcclusion(TEXTURE3D_PARAM(SHVolumeTexture, SHVolumeSampler), float3 positionWS, float4x4 WorldToTexture,
  106. float transformToLocal, float texelSizeX, float3 probeVolumeMin, float3 probeVolumeSizeInv)
  107. {
  108. float3 position = (transformToLocal == 1.0) ? mul(WorldToTexture, float4(positionWS, 1.0)).xyz : positionWS;
  109. float3 texCoord = (position - probeVolumeMin) * probeVolumeSizeInv.xyz;
  110. // Sample fourth texture in the atlas
  111. // We need to compute proper U coordinate to sample.
  112. // Clamp the coordinate otherwize we'll have leaking between ShB coefficients and Probe Occlusion(Occ) info
  113. texCoord.x = max(texCoord.x * 0.25 + 0.75, 0.75 + 0.5 * texelSizeX);
  114. return SAMPLE_TEXTURE3D(SHVolumeTexture, SHVolumeSampler, texCoord);
  115. }
  116. // Following functions are to sample enlighten lightmaps (or lightmaps encoded the same way as our
  117. // enlighten implementation). They assume use of RGB9E5 for dynamic illuminance map and RGBM for baked ones.
  118. // It is required for other platform that aren't supporting this format to implement variant of these functions
  119. // (But these kind of platform should use regular render loop and not news shaders).
  120. // TODO: This is the max value allowed for emissive (bad name - but keep for now to retrieve it) (It is 8^2.2 (gamma) and 8 is the limit of punctual light slider...), comme from UnityCg.cginc. Fix it!
  121. // Ask Jesper if this can be change for HDRenderPipeline
  122. #define EMISSIVE_RGBM_SCALE 97.0
  123. // RGBM stuff is temporary. For now baked lightmap are in RGBM and the RGBM range for lightmaps is specific so we can't use the generic method.
  124. // In the end baked lightmaps are going to be BC6H so the code will be the same as dynamic lightmaps.
  125. // Same goes for emissive packed as an input for Enlighten with another hard coded multiplier.
  126. // TODO: This function is used with the LightTransport pass to encode lightmap or emissive
  127. real4 PackEmissiveRGBM(real3 rgb)
  128. {
  129. real kOneOverRGBMMaxRange = 1.0 / EMISSIVE_RGBM_SCALE;
  130. const real kMinMultiplier = 2.0 * 1e-2;
  131. real4 rgbm = real4(rgb * kOneOverRGBMMaxRange, 1.0);
  132. rgbm.a = max(max(rgbm.r, rgbm.g), max(rgbm.b, kMinMultiplier));
  133. rgbm.a = ceil(rgbm.a * 255.0) / 255.0;
  134. // Division-by-zero warning from d3d9, so make compiler happy.
  135. rgbm.a = max(rgbm.a, kMinMultiplier);
  136. rgbm.rgb /= rgbm.a;
  137. return rgbm;
  138. }
  139. real3 UnpackLightmapRGBM(real4 rgbmInput, real4 decodeInstructions)
  140. {
  141. #ifdef UNITY_COLORSPACE_GAMMA
  142. return rgbmInput.rgb * (rgbmInput.a * decodeInstructions.x);
  143. #else
  144. return rgbmInput.rgb * (PositivePow(rgbmInput.a, decodeInstructions.y) * decodeInstructions.x);
  145. #endif
  146. }
  147. real3 UnpackLightmapDoubleLDR(real4 encodedColor, real4 decodeInstructions)
  148. {
  149. return encodedColor.rgb * decodeInstructions.x;
  150. }
  151. #ifndef BUILTIN_TARGET_API
  152. real3 DecodeLightmap(real4 encodedIlluminance, real4 decodeInstructions)
  153. {
  154. #if defined(UNITY_LIGHTMAP_RGBM_ENCODING)
  155. return UnpackLightmapRGBM(encodedIlluminance, decodeInstructions);
  156. #elif defined(UNITY_LIGHTMAP_DLDR_ENCODING)
  157. return UnpackLightmapDoubleLDR(encodedIlluminance, decodeInstructions);
  158. #else // (UNITY_LIGHTMAP_FULL_HDR)
  159. return encodedIlluminance.rgb;
  160. #endif
  161. }
  162. #endif
  163. real3 DecodeHDREnvironment(real4 encodedIrradiance, real4 decodeInstructions)
  164. {
  165. // Take into account texture alpha if decodeInstructions.w is true(the alpha value affects the RGB channels)
  166. real alpha = max(decodeInstructions.w * (encodedIrradiance.a - 1.0) + 1.0, 0.0);
  167. // If Linear mode is not supported we can skip exponent part
  168. return (decodeInstructions.x * PositivePow(alpha, decodeInstructions.y)) * encodedIrradiance.rgb;
  169. }
  170. #if defined(UNITY_DOTS_INSTANCING_ENABLED) && !defined(USE_LEGACY_LIGHTMAPS)
  171. // ^ GPU-driven rendering is enabled, and we haven't opted-out from lightmap
  172. // texture arrays. This minimizes batch breakages, but texture arrays aren't
  173. // supported in a performant way on all GPUs.
  174. #define TEXTURE2D_LIGHTMAP_PARAM TEXTURE2D_ARRAY_PARAM
  175. #define TEXTURE2D_LIGHTMAP_ARGS TEXTURE2D_ARRAY_ARGS
  176. #define SAMPLE_TEXTURE2D_LIGHTMAP SAMPLE_TEXTURE2D_ARRAY
  177. #define LIGHTMAP_EXTRA_ARGS float2 uv, float slice
  178. #define LIGHTMAP_EXTRA_ARGS_USE uv, slice
  179. #else
  180. // ^ Lightmaps are not bound as texture arrays, but as individual textures. The
  181. // batch is broken every time lightmaps are changed, but this is well-supported
  182. // on all GPUs.
  183. #define TEXTURE2D_LIGHTMAP_PARAM TEXTURE2D_PARAM
  184. #define TEXTURE2D_LIGHTMAP_ARGS TEXTURE2D_ARGS
  185. #define SAMPLE_TEXTURE2D_LIGHTMAP SAMPLE_TEXTURE2D
  186. #define LIGHTMAP_EXTRA_ARGS float2 uv
  187. #define LIGHTMAP_EXTRA_ARGS_USE uv
  188. #endif
  189. // For the built-in target, lightmaps are defined with half precision.
  190. // Unfortunately, TEXTURE2D_Half_PARAM is not defined.
  191. #ifdef BUILTIN_TARGET_API
  192. #undef TEXTURE2D_LIGHTMAP_PARAM
  193. #undef TEXTURE2D_LIGHTMAP_ARGS
  194. #undef SAMPLE_TEXTURE2D_LIGHTMAP
  195. #ifdef SHADER_API_GLES
  196. #define TEXTURE2D_LIGHTMAP_PARAM(textureName, samplerName) TEXTURE2D_HALF(textureName)
  197. #else
  198. #define TEXTURE2D_LIGHTMAP_PARAM(textureName, samplerName) TEXTURE2D_HALF(textureName), SAMPLER(samplerName)
  199. #endif
  200. #define TEXTURE2D_LIGHTMAP_ARGS TEXTURE2D_ARGS
  201. #define SAMPLE_TEXTURE2D_LIGHTMAP SAMPLE_TEXTURE2D
  202. #endif
  203. // isStaticLightmap mean it is not an Enlighten map
  204. real3 SampleSingleLightmap(TEXTURE2D_LIGHTMAP_PARAM(lightmapTex, lightmapSampler), LIGHTMAP_EXTRA_ARGS, float4 transform, bool isStaticLightmap)
  205. {
  206. real4 decodeInstructions = real4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0.0, 0.0);
  207. // transform is scale and bias
  208. uv = uv * transform.xy + transform.zw;
  209. real4 encodedIlluminance = SAMPLE_TEXTURE2D_LIGHTMAP(lightmapTex, lightmapSampler, LIGHTMAP_EXTRA_ARGS_USE).rgba;
  210. // Remark: static lightmap is RGBM for now, dynamic lightmap is RGB9E5
  211. real3 illuminance = isStaticLightmap ? DecodeLightmap(encodedIlluminance, decodeInstructions) : encodedIlluminance.rgb;
  212. return illuminance;
  213. }
  214. // deprecated
  215. real3 SampleSingleLightmap(TEXTURE2D_LIGHTMAP_PARAM(lightmapTex, lightmapSampler), LIGHTMAP_EXTRA_ARGS, float4 transform, bool isStaticLightmap, real4 ignore)
  216. {
  217. return SampleSingleLightmap(TEXTURE2D_LIGHTMAP_ARGS(lightmapTex, lightmapSampler), LIGHTMAP_EXTRA_ARGS_USE, transform, isStaticLightmap);
  218. }
  219. void SampleDirectionalLightmap(TEXTURE2D_LIGHTMAP_PARAM(lightmapTex, lightmapSampler), TEXTURE2D_LIGHTMAP_PARAM(lightmapDirTex, lightmapDirSampler), LIGHTMAP_EXTRA_ARGS, float4 transform,
  220. float3 normalWS, float3 backNormalWS, bool isStaticLightmap, inout real3 bakeDiffuseLighting, inout real3 backBakeDiffuseLighting)
  221. {
  222. // In directional mode Enlighten bakes dominant light direction
  223. // in a way, that using it for half Lambert and then dividing by a "rebalancing coefficient"
  224. // gives a result close to plain diffuse response lightmaps, but normalmapped.
  225. // Note that dir is not unit length on purpose. Its length is "directionality", like
  226. // for the directional specular lightmaps.
  227. real3 illuminance = SampleSingleLightmap(TEXTURE2D_LIGHTMAP_ARGS(lightmapTex, lightmapSampler), LIGHTMAP_EXTRA_ARGS_USE, transform, isStaticLightmap);
  228. // transform is scale and bias
  229. uv = uv * transform.xy + transform.zw;
  230. real4 direction = SAMPLE_TEXTURE2D_LIGHTMAP(lightmapDirTex, lightmapDirSampler, LIGHTMAP_EXTRA_ARGS_USE);
  231. real halfLambert = dot(normalWS, direction.xyz - 0.5) + 0.5;
  232. bakeDiffuseLighting += illuminance * halfLambert / max(1e-4, direction.w);
  233. real backHalfLambert = dot(backNormalWS, direction.xyz - 0.5) + 0.5;
  234. backBakeDiffuseLighting += illuminance * backHalfLambert / max(1e-4, direction.w);
  235. }
  236. // deprecated
  237. void SampleDirectionalLightmap(TEXTURE2D_LIGHTMAP_PARAM(lightmapTex, lightmapSampler), TEXTURE2D_LIGHTMAP_PARAM(lightmapDirTex, lightmapDirSampler), LIGHTMAP_EXTRA_ARGS, float4 transform,
  238. float3 normalWS, float3 backNormalWS, bool isStaticLightmap, real4 ignore, inout real3 bakeDiffuseLighting, inout real3 backBakeDiffuseLighting)
  239. {
  240. SampleDirectionalLightmap(TEXTURE2D_LIGHTMAP_ARGS(lightmapTex, lightmapSampler), TEXTURE2D_LIGHTMAP_ARGS(lightmapDirTex, lightmapDirSampler), LIGHTMAP_EXTRA_ARGS_USE,
  241. transform, normalWS, backNormalWS, isStaticLightmap, bakeDiffuseLighting, backBakeDiffuseLighting);
  242. }
  243. // Just a shortcut that call function above
  244. real3 SampleDirectionalLightmap(TEXTURE2D_LIGHTMAP_PARAM(lightmapTex, lightmapSampler), TEXTURE2D_LIGHTMAP_PARAM(lightmapDirTex, lightmapDirSampler), LIGHTMAP_EXTRA_ARGS, float4 transform, float3 normalWS, bool isStaticLightmap)
  245. {
  246. float3 backNormalWSUnused = 0.0;
  247. real3 bakeDiffuseLighting = 0.0;
  248. real3 backBakeDiffuseLightingUnused = 0.0;
  249. SampleDirectionalLightmap(TEXTURE2D_LIGHTMAP_ARGS(lightmapTex, lightmapSampler), TEXTURE2D_LIGHTMAP_ARGS(lightmapDirTex, lightmapDirSampler), LIGHTMAP_EXTRA_ARGS_USE, transform,
  250. normalWS, backNormalWSUnused, isStaticLightmap, bakeDiffuseLighting, backBakeDiffuseLightingUnused);
  251. return bakeDiffuseLighting;
  252. }
  253. // deprecated
  254. real3 SampleDirectionalLightmap(TEXTURE2D_LIGHTMAP_PARAM(lightmapTex, lightmapSampler), TEXTURE2D_LIGHTMAP_PARAM(lightmapDirTex, lightmapDirSampler), LIGHTMAP_EXTRA_ARGS, float4 transform, float3 normalWS,
  255. bool isStaticLightmap, real4 ignore)
  256. {
  257. return SampleDirectionalLightmap(TEXTURE2D_LIGHTMAP_ARGS(lightmapTex, lightmapSampler), TEXTURE2D_LIGHTMAP_ARGS(lightmapDirTex, lightmapDirSampler), LIGHTMAP_EXTRA_ARGS_USE, transform, normalWS, isStaticLightmap);
  258. }
  259. #if SHADER_API_MOBILE || SHADER_API_GLES3 || SHADER_API_SWITCH
  260. #pragma warning (enable : 3205) // conversion of larger type to smaller
  261. #endif
  262. #endif // UNITY_ENTITY_LIGHTING_INCLUDED