GlobalIllumination.hlsl 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. #ifndef UNIVERSAL_GLOBAL_ILLUMINATION_INCLUDED
  2. #define UNIVERSAL_GLOBAL_ILLUMINATION_INCLUDED
  3. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl"
  4. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl"
  5. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RealtimeLights.hlsl"
  6. // If lightmap is not defined than we evaluate GI (ambient + probes) from SH
  7. // We might do it fully or partially in vertex to save shader ALU
  8. #if !defined(LIGHTMAP_ON)
  9. // TODO: Controls things like these by exposing SHADER_QUALITY levels (low, medium, high)
  10. #if defined(SHADER_API_GLES) || !defined(_NORMALMAP)
  11. // Evaluates SH fully in vertex
  12. #define EVALUATE_SH_VERTEX
  13. #elif !SHADER_HINT_NICE_QUALITY
  14. // Evaluates L2 SH in vertex and L0L1 in pixel
  15. #define EVALUATE_SH_MIXED
  16. #endif
  17. // Otherwise evaluate SH fully per-pixel
  18. #endif
  19. // Renamed -> LIGHTMAP_SHADOW_MIXING
  20. #if !defined(_MIXED_LIGHTING_SUBTRACTIVE) && defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK)
  21. #define _MIXED_LIGHTING_SUBTRACTIVE
  22. #endif
  23. // Samples SH L0, L1 and L2 terms
  24. half3 SampleSH(half3 normalWS)
  25. {
  26. // LPPV is not supported in Ligthweight Pipeline
  27. real4 SHCoefficients[7];
  28. SHCoefficients[0] = unity_SHAr;
  29. SHCoefficients[1] = unity_SHAg;
  30. SHCoefficients[2] = unity_SHAb;
  31. SHCoefficients[3] = unity_SHBr;
  32. SHCoefficients[4] = unity_SHBg;
  33. SHCoefficients[5] = unity_SHBb;
  34. SHCoefficients[6] = unity_SHC;
  35. return max(half3(0, 0, 0), SampleSH9(SHCoefficients, normalWS));
  36. }
  37. // SH Vertex Evaluation. Depending on target SH sampling might be
  38. // done completely per vertex or mixed with L2 term per vertex and L0, L1
  39. // per pixel. See SampleSHPixel
  40. half3 SampleSHVertex(half3 normalWS)
  41. {
  42. #if defined(EVALUATE_SH_VERTEX)
  43. return SampleSH(normalWS);
  44. #elif defined(EVALUATE_SH_MIXED)
  45. // no max since this is only L2 contribution
  46. return SHEvalLinearL2(normalWS, unity_SHBr, unity_SHBg, unity_SHBb, unity_SHC);
  47. #endif
  48. // Fully per-pixel. Nothing to compute.
  49. return half3(0.0, 0.0, 0.0);
  50. }
  51. // SH Pixel Evaluation. Depending on target SH sampling might be done
  52. // mixed or fully in pixel. See SampleSHVertex
  53. half3 SampleSHPixel(half3 L2Term, half3 normalWS)
  54. {
  55. #if defined(EVALUATE_SH_VERTEX)
  56. return L2Term;
  57. #elif defined(EVALUATE_SH_MIXED)
  58. half3 res = SHEvalLinearL0L1(normalWS, unity_SHAr, unity_SHAg, unity_SHAb);
  59. #ifdef UNITY_COLORSPACE_GAMMA
  60. res = LinearToSRGB(res);
  61. #endif
  62. return max(half3(0, 0, 0), res);
  63. #endif
  64. // Default: Evaluate SH fully per-pixel
  65. return SampleSH(normalWS);
  66. }
  67. #if defined(UNITY_DOTS_INSTANCING_ENABLED)
  68. #define LIGHTMAP_NAME unity_Lightmaps
  69. #define LIGHTMAP_INDIRECTION_NAME unity_LightmapsInd
  70. #define LIGHTMAP_SAMPLER_NAME samplerunity_Lightmaps
  71. #define LIGHTMAP_SAMPLE_EXTRA_ARGS staticLightmapUV, unity_LightmapIndex.x
  72. #else
  73. #define LIGHTMAP_NAME unity_Lightmap
  74. #define LIGHTMAP_INDIRECTION_NAME unity_LightmapInd
  75. #define LIGHTMAP_SAMPLER_NAME samplerunity_Lightmap
  76. #define LIGHTMAP_SAMPLE_EXTRA_ARGS staticLightmapUV
  77. #endif
  78. // Sample baked and/or realtime lightmap. Non-Direction and Directional if available.
  79. half3 SampleLightmap(float2 staticLightmapUV, float2 dynamicLightmapUV, half3 normalWS)
  80. {
  81. #ifdef UNITY_LIGHTMAP_FULL_HDR
  82. bool encodedLightmap = false;
  83. #else
  84. bool encodedLightmap = true;
  85. #endif
  86. half4 decodeInstructions = half4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0.0h, 0.0h);
  87. // The shader library sample lightmap functions transform the lightmap uv coords to apply bias and scale.
  88. // However, universal pipeline already transformed those coords in vertex. We pass half4(1, 1, 0, 0) and
  89. // the compiler will optimize the transform away.
  90. half4 transformCoords = half4(1, 1, 0, 0);
  91. float3 diffuseLighting = 0;
  92. #if defined(LIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED)
  93. diffuseLighting = SampleDirectionalLightmap(TEXTURE2D_LIGHTMAP_ARGS(LIGHTMAP_NAME, LIGHTMAP_SAMPLER_NAME),
  94. TEXTURE2D_LIGHTMAP_ARGS(LIGHTMAP_INDIRECTION_NAME, LIGHTMAP_SAMPLER_NAME),
  95. LIGHTMAP_SAMPLE_EXTRA_ARGS, transformCoords, normalWS, encodedLightmap, decodeInstructions);
  96. #elif defined(LIGHTMAP_ON)
  97. diffuseLighting = SampleSingleLightmap(TEXTURE2D_LIGHTMAP_ARGS(LIGHTMAP_NAME, LIGHTMAP_SAMPLER_NAME), LIGHTMAP_SAMPLE_EXTRA_ARGS, transformCoords, encodedLightmap, decodeInstructions);
  98. #endif
  99. #if defined(DYNAMICLIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED)
  100. diffuseLighting += SampleDirectionalLightmap(TEXTURE2D_ARGS(unity_DynamicLightmap, samplerunity_DynamicLightmap),
  101. TEXTURE2D_ARGS(unity_DynamicDirectionality, samplerunity_DynamicLightmap),
  102. dynamicLightmapUV, transformCoords, normalWS, false, decodeInstructions);
  103. #elif defined(DYNAMICLIGHTMAP_ON)
  104. diffuseLighting += SampleSingleLightmap(TEXTURE2D_ARGS(unity_DynamicLightmap, samplerunity_DynamicLightmap),
  105. dynamicLightmapUV, transformCoords, false, decodeInstructions);
  106. #endif
  107. return diffuseLighting;
  108. }
  109. // Legacy version of SampleLightmap where Realtime GI is not supported.
  110. half3 SampleLightmap(float2 staticLightmapUV, half3 normalWS)
  111. {
  112. float2 dummyDynamicLightmapUV = float2(0,0);
  113. half3 result = SampleLightmap(staticLightmapUV, dummyDynamicLightmapUV, normalWS);
  114. return result;
  115. }
  116. // We either sample GI from baked lightmap or from probes.
  117. // If lightmap: sampleData.xy = lightmapUV
  118. // If probe: sampleData.xyz = L2 SH terms
  119. #if defined(LIGHTMAP_ON) && defined(DYNAMICLIGHTMAP_ON)
  120. #define SAMPLE_GI(staticLmName, dynamicLmName, shName, normalWSName) SampleLightmap(staticLmName, dynamicLmName, normalWSName)
  121. #elif defined(DYNAMICLIGHTMAP_ON)
  122. #define SAMPLE_GI(staticLmName, dynamicLmName, shName, normalWSName) SampleLightmap(0, dynamicLmName, normalWSName)
  123. #elif defined(LIGHTMAP_ON)
  124. #define SAMPLE_GI(staticLmName, shName, normalWSName) SampleLightmap(staticLmName, 0, normalWSName)
  125. #else
  126. #define SAMPLE_GI(staticLmName, shName, normalWSName) SampleSHPixel(shName, normalWSName)
  127. #endif
  128. half3 BoxProjectedCubemapDirection(half3 reflectionWS, float3 positionWS, float4 cubemapPositionWS, float4 boxMin, float4 boxMax)
  129. {
  130. // Is this probe using box projection?
  131. if (cubemapPositionWS.w > 0.0f)
  132. {
  133. float3 boxMinMax = (reflectionWS > 0.0f) ? boxMax.xyz : boxMin.xyz;
  134. half3 rbMinMax = half3(boxMinMax - positionWS) / reflectionWS;
  135. half fa = half(min(min(rbMinMax.x, rbMinMax.y), rbMinMax.z));
  136. half3 worldPos = half3(positionWS - cubemapPositionWS.xyz);
  137. half3 result = worldPos + reflectionWS * fa;
  138. return result;
  139. }
  140. else
  141. {
  142. return reflectionWS;
  143. }
  144. }
  145. float CalculateProbeWeight(float3 positionWS, float4 probeBoxMin, float4 probeBoxMax)
  146. {
  147. float blendDistance = probeBoxMax.w;
  148. float3 weightDir = min(positionWS - probeBoxMin.xyz, probeBoxMax.xyz - positionWS) / blendDistance;
  149. return saturate(min(weightDir.x, min(weightDir.y, weightDir.z)));
  150. }
  151. half CalculateProbeVolumeSqrMagnitude(float4 probeBoxMin, float4 probeBoxMax)
  152. {
  153. half3 maxToMin = half3(probeBoxMax.xyz - probeBoxMin.xyz);
  154. return dot(maxToMin, maxToMin);
  155. }
  156. half3 CalculateIrradianceFromReflectionProbes(half3 reflectVector, float3 positionWS, half perceptualRoughness)
  157. {
  158. half probe0Volume = CalculateProbeVolumeSqrMagnitude(unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
  159. half probe1Volume = CalculateProbeVolumeSqrMagnitude(unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
  160. half volumeDiff = probe0Volume - probe1Volume;
  161. float importanceSign = unity_SpecCube1_BoxMin.w;
  162. // A probe is dominant if its importance is higher
  163. // Or have equal importance but smaller volume
  164. bool probe0Dominant = importanceSign > 0.0f || (importanceSign == 0.0f && volumeDiff < -0.0001h);
  165. bool probe1Dominant = importanceSign < 0.0f || (importanceSign == 0.0f && volumeDiff > 0.0001h);
  166. float desiredWeightProbe0 = CalculateProbeWeight(positionWS, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
  167. float desiredWeightProbe1 = CalculateProbeWeight(positionWS, unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
  168. // Subject the probes weight if the other probe is dominant
  169. float weightProbe0 = probe1Dominant ? min(desiredWeightProbe0, 1.0f - desiredWeightProbe1) : desiredWeightProbe0;
  170. float weightProbe1 = probe0Dominant ? min(desiredWeightProbe1, 1.0f - desiredWeightProbe0) : desiredWeightProbe1;
  171. float totalWeight = weightProbe0 + weightProbe1;
  172. // If either probe 0 or probe 1 is dominant the sum of weights is guaranteed to be 1.
  173. // If neither is dominant this is not guaranteed - only normalize weights if totalweight exceeds 1.
  174. weightProbe0 /= max(totalWeight, 1.0f);
  175. weightProbe1 /= max(totalWeight, 1.0f);
  176. half3 irradiance = half3(0.0h, 0.0h, 0.0h);
  177. half3 originalReflectVector = reflectVector;
  178. half mip = PerceptualRoughnessToMipmapLevel(perceptualRoughness);
  179. // Sample the first reflection probe
  180. if (weightProbe0 > 0.01f)
  181. {
  182. #ifdef _REFLECTION_PROBE_BOX_PROJECTION
  183. reflectVector = BoxProjectedCubemapDirection(originalReflectVector, positionWS, unity_SpecCube0_ProbePosition, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
  184. #endif // _REFLECTION_PROBE_BOX_PROJECTION
  185. half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, mip));
  186. #if defined(UNITY_USE_NATIVE_HDR)
  187. irradiance += weightProbe0 * encodedIrradiance.rbg;
  188. #else
  189. irradiance += weightProbe0 * DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
  190. #endif // UNITY_USE_NATIVE_HDR
  191. }
  192. // Sample the second reflection probe
  193. if (weightProbe1 > 0.01f)
  194. {
  195. #ifdef _REFLECTION_PROBE_BOX_PROJECTION
  196. reflectVector = BoxProjectedCubemapDirection(originalReflectVector, positionWS, unity_SpecCube1_ProbePosition, unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
  197. #endif // _REFLECTION_PROBE_BOX_PROJECTION
  198. half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(unity_SpecCube1, samplerunity_SpecCube1, reflectVector, mip));
  199. #if defined(UNITY_USE_NATIVE_HDR) || defined(UNITY_DOTS_INSTANCING_ENABLED)
  200. irradiance += weightProbe1 * encodedIrradiance.rbg;
  201. #else
  202. irradiance += weightProbe1 * DecodeHDREnvironment(encodedIrradiance, unity_SpecCube1_HDR);
  203. #endif // UNITY_USE_NATIVE_HDR || UNITY_DOTS_INSTANCING_ENABLED
  204. }
  205. // Use any remaining weight to blend to environment reflection cube map
  206. if (totalWeight < 0.99f)
  207. {
  208. half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(_GlossyEnvironmentCubeMap, sampler_GlossyEnvironmentCubeMap, originalReflectVector, mip));
  209. #if defined(UNITY_USE_NATIVE_HDR) || defined(UNITY_DOTS_INSTANCING_ENABLED)
  210. irradiance += (1.0f - totalWeight) * encodedIrradiance.rbg;
  211. #else
  212. irradiance += (1.0f - totalWeight) * DecodeHDREnvironment(encodedIrradiance, _GlossyEnvironmentCubeMap_HDR);
  213. #endif // UNITY_USE_NATIVE_HDR || UNITY_DOTS_INSTANCING_ENABLED
  214. }
  215. return irradiance;
  216. }
  217. half3 GlossyEnvironmentReflection(half3 reflectVector, float3 positionWS, half perceptualRoughness, half occlusion)
  218. {
  219. #if !defined(_ENVIRONMENTREFLECTIONS_OFF)
  220. half3 irradiance;
  221. #ifdef _REFLECTION_PROBE_BLENDING
  222. irradiance = CalculateIrradianceFromReflectionProbes(reflectVector, positionWS, perceptualRoughness);
  223. #else
  224. #ifdef _REFLECTION_PROBE_BOX_PROJECTION
  225. reflectVector = BoxProjectedCubemapDirection(reflectVector, positionWS, unity_SpecCube0_ProbePosition, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
  226. #endif // _REFLECTION_PROBE_BOX_PROJECTION
  227. half mip = PerceptualRoughnessToMipmapLevel(perceptualRoughness);
  228. half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, mip));
  229. #if defined(UNITY_USE_NATIVE_HDR)
  230. irradiance = encodedIrradiance.rgb;
  231. #else
  232. irradiance = DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
  233. #endif // UNITY_USE_NATIVE_HDR
  234. #endif // _REFLECTION_PROBE_BLENDING
  235. return irradiance * occlusion;
  236. #else
  237. return _GlossyEnvironmentColor.rgb * occlusion;
  238. #endif // _ENVIRONMENTREFLECTIONS_OFF
  239. }
  240. half3 GlossyEnvironmentReflection(half3 reflectVector, half perceptualRoughness, half occlusion)
  241. {
  242. #if !defined(_ENVIRONMENTREFLECTIONS_OFF)
  243. half3 irradiance;
  244. half mip = PerceptualRoughnessToMipmapLevel(perceptualRoughness);
  245. half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, mip));
  246. #if defined(UNITY_USE_NATIVE_HDR)
  247. irradiance = encodedIrradiance.rgb;
  248. #else
  249. irradiance = DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
  250. #endif // UNITY_USE_NATIVE_HDR
  251. return irradiance * occlusion;
  252. #else
  253. return _GlossyEnvironmentColor.rgb * occlusion;
  254. #endif // _ENVIRONMENTREFLECTIONS_OFF
  255. }
  256. half3 SubtractDirectMainLightFromLightmap(Light mainLight, half3 normalWS, half3 bakedGI)
  257. {
  258. // Let's try to make realtime shadows work on a surface, which already contains
  259. // baked lighting and shadowing from the main sun light.
  260. // Summary:
  261. // 1) Calculate possible value in the shadow by subtracting estimated light contribution from the places occluded by realtime shadow:
  262. // a) preserves other baked lights and light bounces
  263. // b) eliminates shadows on the geometry facing away from the light
  264. // 2) Clamp against user defined ShadowColor.
  265. // 3) Pick original lightmap value, if it is the darkest one.
  266. // 1) Gives good estimate of illumination as if light would've been shadowed during the bake.
  267. // We only subtract the main direction light. This is accounted in the contribution term below.
  268. half shadowStrength = GetMainLightShadowStrength();
  269. half contributionTerm = saturate(dot(mainLight.direction, normalWS));
  270. half3 lambert = mainLight.color * contributionTerm;
  271. half3 estimatedLightContributionMaskedByInverseOfShadow = lambert * (1.0 - mainLight.shadowAttenuation);
  272. half3 subtractedLightmap = bakedGI - estimatedLightContributionMaskedByInverseOfShadow;
  273. // 2) Allows user to define overall ambient of the scene and control situation when realtime shadow becomes too dark.
  274. half3 realtimeShadow = max(subtractedLightmap, _SubtractiveShadowColor.xyz);
  275. realtimeShadow = lerp(bakedGI, realtimeShadow, shadowStrength);
  276. // 3) Pick darkest color
  277. return min(bakedGI, realtimeShadow);
  278. }
  279. half3 GlobalIllumination(BRDFData brdfData, BRDFData brdfDataClearCoat, float clearCoatMask,
  280. half3 bakedGI, half occlusion, float3 positionWS,
  281. half3 normalWS, half3 viewDirectionWS)
  282. {
  283. half3 reflectVector = reflect(-viewDirectionWS, normalWS);
  284. half NoV = saturate(dot(normalWS, viewDirectionWS));
  285. half fresnelTerm = Pow4(1.0 - NoV);
  286. half3 indirectDiffuse = bakedGI;
  287. half3 indirectSpecular = GlossyEnvironmentReflection(reflectVector, positionWS, brdfData.perceptualRoughness, 1.0h);
  288. half3 color = EnvironmentBRDF(brdfData, indirectDiffuse, indirectSpecular, fresnelTerm);
  289. if (IsOnlyAOLightingFeatureEnabled())
  290. {
  291. color = half3(1,1,1); // "Base white" for AO debug lighting mode
  292. }
  293. #if defined(_CLEARCOAT) || defined(_CLEARCOATMAP)
  294. half3 coatIndirectSpecular = GlossyEnvironmentReflection(reflectVector, positionWS, brdfDataClearCoat.perceptualRoughness, 1.0h);
  295. // TODO: "grazing term" causes problems on full roughness
  296. half3 coatColor = EnvironmentBRDFClearCoat(brdfDataClearCoat, clearCoatMask, coatIndirectSpecular, fresnelTerm);
  297. // Blend with base layer using khronos glTF recommended way using NoV
  298. // Smooth surface & "ambiguous" lighting
  299. // NOTE: fresnelTerm (above) is pow4 instead of pow5, but should be ok as blend weight.
  300. half coatFresnel = kDielectricSpec.x + kDielectricSpec.a * fresnelTerm;
  301. return (color * (1.0 - coatFresnel * clearCoatMask) + coatColor) * occlusion;
  302. #else
  303. return color * occlusion;
  304. #endif
  305. }
  306. // Backwards compatiblity
  307. half3 GlobalIllumination(BRDFData brdfData, half3 bakedGI, half occlusion, float3 positionWS, half3 normalWS, half3 viewDirectionWS)
  308. {
  309. const BRDFData noClearCoat = (BRDFData)0;
  310. return GlobalIllumination(brdfData, noClearCoat, 0.0, bakedGI, occlusion, positionWS, normalWS, viewDirectionWS);
  311. }
  312. half3 GlobalIllumination(BRDFData brdfData, BRDFData brdfDataClearCoat, float clearCoatMask,
  313. half3 bakedGI, half occlusion,
  314. half3 normalWS, half3 viewDirectionWS)
  315. {
  316. half3 reflectVector = reflect(-viewDirectionWS, normalWS);
  317. half NoV = saturate(dot(normalWS, viewDirectionWS));
  318. half fresnelTerm = Pow4(1.0 - NoV);
  319. half3 indirectDiffuse = bakedGI;
  320. half3 indirectSpecular = GlossyEnvironmentReflection(reflectVector, brdfData.perceptualRoughness, half(1.0));
  321. half3 color = EnvironmentBRDF(brdfData, indirectDiffuse, indirectSpecular, fresnelTerm);
  322. #if defined(_CLEARCOAT) || defined(_CLEARCOATMAP)
  323. half3 coatIndirectSpecular = GlossyEnvironmentReflection(reflectVector, brdfDataClearCoat.perceptualRoughness, half(1.0));
  324. // TODO: "grazing term" causes problems on full roughness
  325. half3 coatColor = EnvironmentBRDFClearCoat(brdfDataClearCoat, clearCoatMask, coatIndirectSpecular, fresnelTerm);
  326. // Blend with base layer using khronos glTF recommended way using NoV
  327. // Smooth surface & "ambiguous" lighting
  328. // NOTE: fresnelTerm (above) is pow4 instead of pow5, but should be ok as blend weight.
  329. half coatFresnel = kDielectricSpec.x + kDielectricSpec.a * fresnelTerm;
  330. return (color * (1.0 - coatFresnel * clearCoatMask) + coatColor) * occlusion;
  331. #else
  332. return color * occlusion;
  333. #endif
  334. }
  335. half3 GlobalIllumination(BRDFData brdfData, half3 bakedGI, half occlusion, half3 normalWS, half3 viewDirectionWS)
  336. {
  337. const BRDFData noClearCoat = (BRDFData)0;
  338. return GlobalIllumination(brdfData, noClearCoat, 0.0, bakedGI, occlusion, normalWS, viewDirectionWS);
  339. }
  340. void MixRealtimeAndBakedGI(inout Light light, half3 normalWS, inout half3 bakedGI)
  341. {
  342. #if defined(LIGHTMAP_ON) && defined(_MIXED_LIGHTING_SUBTRACTIVE)
  343. bakedGI = SubtractDirectMainLightFromLightmap(light, normalWS, bakedGI);
  344. #endif
  345. }
  346. // Backwards compatibility
  347. void MixRealtimeAndBakedGI(inout Light light, half3 normalWS, inout half3 bakedGI, half4 shadowMask)
  348. {
  349. MixRealtimeAndBakedGI(light, normalWS, bakedGI);
  350. }
  351. void MixRealtimeAndBakedGI(inout Light light, half3 normalWS, inout half3 bakedGI, AmbientOcclusionFactor aoFactor)
  352. {
  353. if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_AMBIENT_OCCLUSION))
  354. {
  355. bakedGI *= aoFactor.indirectAmbientOcclusion;
  356. }
  357. MixRealtimeAndBakedGI(light, normalWS, bakedGI);
  358. }
  359. #endif