Lux URP Clear Coat Lighting.hlsl 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // NOTE: Based on URP Lighting.hlsl which replaced some half3 with floats to avoid lighting artifacts on mobile
  2. // Hair lighting functions renamed to solves problems with LWRP 6.x
  3. // https://google.github.io/filament/Filament.md.html#materialsystem/clothmodel
  4. // SheenColor
  5. #ifndef UNIVERSAL_CLEARCOATLIGHTING_INCLUDED
  6. #define UNIVERSAL_CLEARCOATLIGHTING_INCLUDED
  7. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
  8. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl"
  9. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl"
  10. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  11. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
  12. // ---------
  13. struct AdditionalData {
  14. half coatThickness;
  15. half3 coatSpecular;
  16. half3 normalWS;
  17. half perceptualRoughness;
  18. half roughness;
  19. half roughness2;
  20. half normalizationTerm;
  21. half roughness2MinusOne; // roughness² - 1.0
  22. half reflectivity;
  23. half grazingTerm;
  24. half specOcclusion;
  25. };
  26. half3 DirectBDRF_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS, half NdotL)
  27. {
  28. #ifndef _SPECULARHIGHLIGHTS_OFF
  29. float3 halfDir = SafeNormalize(lightDirectionWS + viewDirectionWS);
  30. half LoH = saturate(dot(lightDirectionWS, halfDir));
  31. // Base Lobe
  32. float NoH = saturate(dot(normalWS, halfDir));
  33. float d = NoH * NoH * brdfData.roughness2MinusOne + 1.00001f;
  34. half LoH2 = LoH * LoH;
  35. LoH2 = max(0.1h, LoH2);
  36. half specularTerm = brdfData.roughness2 / ((d * d) * LoH2 /* max(0.1h, LoH2 */ * brdfData.normalizationTerm);
  37. #if defined (SHADER_API_MOBILE) || defined (SHADER_API_SWITCH)
  38. specularTerm = specularTerm - HALF_MIN;
  39. specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
  40. #endif
  41. half3 spec = specularTerm * brdfData.specular * NdotL;
  42. // Coat Lobe
  43. // From HDRP: Scale base specular
  44. #if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
  45. [branch]
  46. if (addData.coatThickness > 0.0h) {
  47. #endif
  48. half coatF = F_Schlick(addData.reflectivity /*addData.coatSpecular*/ /*CLEAR_COAT_F0*/, LoH) * addData.coatThickness;
  49. spec *= Sq(1.0h - coatF);
  50. NoH = saturate(dot(addData.normalWS, halfDir));
  51. d = NoH * NoH * addData.roughness2MinusOne + 1.00001f;
  52. // LoH2 = LoH * LoH;
  53. specularTerm = addData.roughness2 / ((d * d) * LoH2 /* max(0.1h, LoH2 */ * addData.normalizationTerm);
  54. #if defined (SHADER_API_MOBILE) || defined (SHADER_API_SWITCH)
  55. specularTerm = specularTerm - HALF_MIN;
  56. specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
  57. #endif
  58. spec += specularTerm * addData.coatSpecular * saturate(dot(addData.normalWS, lightDirectionWS));
  59. #if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
  60. }
  61. #endif
  62. half3 color = spec + brdfData.diffuse * NdotL; // from HDRP (but does not do much?) * lerp(1.0h, 1.0h - coatF, addData.coatThickness);
  63. return color;
  64. #else
  65. return brdfData.diffuse * NdotL;
  66. #endif
  67. }
  68. half3 LightingPhysicallyBased_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS)
  69. {
  70. half NdotL = saturate(dot(normalWS, lightDirectionWS));
  71. half3 radiance = lightColor * (lightAttenuation); // * NdotL);
  72. return DirectBDRF_LuxClearCoat(brdfData, addData, normalWS, lightDirectionWS, viewDirectionWS, NdotL) * radiance;
  73. }
  74. half3 LightingPhysicallyBased_LuxClearCoat(BRDFData brdfData, AdditionalData addData, Light light, half3 normalWS, half3 viewDirectionWS)
  75. {
  76. return LightingPhysicallyBased_LuxClearCoat(brdfData, addData, light.color, light.direction, light.distanceAttenuation * light.shadowAttenuation, normalWS, viewDirectionWS);
  77. }
  78. half3 EnvironmentBRDF_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 indirectDiffuse, half3 indirectSpecular, half fresnelTerm)
  79. {
  80. half3 c = indirectDiffuse * brdfData.diffuse;
  81. float surfaceReduction = 1.0 / (addData.roughness2 + 1.0);
  82. c += surfaceReduction * indirectSpecular * lerp(addData.coatSpecular, addData.grazingTerm, fresnelTerm);
  83. return c;
  84. }
  85. half3 GlobalIllumination_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 bakedGI, half occlusion, half3 normalWS, half3 baseNormalWS, half3 viewDirectionWS, half NdotV)
  86. {
  87. half3 reflectVector = reflect(-viewDirectionWS, normalWS);
  88. half fresnelTerm = Pow4(1.0 - NdotV);
  89. half3 indirectDiffuse = bakedGI * occlusion;
  90. half3 indirectSpecular = GlossyEnvironmentReflection(reflectVector, addData.perceptualRoughness, addData.specOcclusion);
  91. //return EnvironmentBRDF_LuxClearCoat(brdfData, addData, indirectDiffuse, indirectSpecular, fresnelTerm);
  92. half3 res = EnvironmentBRDF_LuxClearCoat(brdfData, addData, indirectDiffuse, indirectSpecular, fresnelTerm);
  93. #if defined(_SECONDARYLOBE)
  94. #if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
  95. [branch]
  96. if (addData.coatThickness > 0.0h) {
  97. #endif
  98. reflectVector = reflect(-viewDirectionWS, baseNormalWS);
  99. indirectSpecular = GlossyEnvironmentReflection(reflectVector, brdfData.perceptualRoughness, 1);
  100. float surfaceReduction = 1.0 / (brdfData.roughness2 + 1.0);
  101. res += NdotV * surfaceReduction * indirectSpecular * lerp(brdfData.specular, brdfData.grazingTerm, fresnelTerm);
  102. #if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
  103. }
  104. #endif
  105. #endif
  106. return res;
  107. }
  108. half3 f0ClearCoatToSurface_Lux(half3 f0)
  109. {
  110. // Approximation of iorTof0(f0ToIor(f0), 1.5)
  111. // This assumes that the clear coat layer has an IOR of 1.5
  112. #if defined(SHADER_API_MOBILE)
  113. return saturate(f0 * (f0 * 0.526868h + 0.529324h) - 0.0482256h);
  114. #else
  115. return saturate(f0 * (f0 * (0.941892h - 0.263008h * f0) + 0.346479h) - 0.0285998h);
  116. #endif
  117. }
  118. half4 LuxClearCoatFragmentPBR(InputData inputData, half3 albedo, half metallic, half3 specular,
  119. half smoothness, half occlusion, half3 emission, half alpha,
  120. half clearcoatSmoothness,
  121. half clearcoatThickness,
  122. half3 clearcoatSpecular,
  123. half3 vertexNormalWS,
  124. half3 baseColor,
  125. half3 secondaryColor
  126. )
  127. {
  128. half NdotV = saturate( dot(vertexNormalWS, inputData.viewDirectionWS) );
  129. #if defined(_SECONDARYCOLOR)
  130. albedo = lerp(secondaryColor, baseColor, NdotV);
  131. #else
  132. albedo = baseColor;
  133. #endif
  134. BRDFData brdfData;
  135. InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
  136. //#if defined(_ADJUSTSPEC)
  137. // brdfData.specular = lerp(brdfData.specular, ConvertF0ForAirInterfaceToF0ForClearCoat15(brdfData.specular), clearcoatThickness);
  138. brdfData.specular = lerp(brdfData.specular, f0ClearCoatToSurface_Lux(brdfData.specular), clearcoatThickness);
  139. //#endif
  140. // URP does also modify the roughness
  141. // Modify Roughness of base layer
  142. /* half ieta = lerp(1.0h, CLEAR_COAT_IETA, outBRDFData.clearCoat);
  143. half coatRoughnessScale = Sq(ieta);
  144. half sigma = RoughnessToVariance(PerceptualRoughnessToRoughness(outBRDFData.perceptualRoughness));
  145. outBRDFData.perceptualRoughness = RoughnessToPerceptualRoughness(VarianceToRoughness(sigma * coatRoughnessScale));
  146. */
  147. AdditionalData addData; // = (AdditionalData)0;
  148. #if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
  149. [branch]
  150. if (clearcoatThickness == 0.0h) {
  151. addData.coatThickness = 0.0h;
  152. addData.coatSpecular = brdfData.specular;
  153. addData.normalWS = inputData.normalWS;
  154. addData.perceptualRoughness = brdfData.perceptualRoughness;
  155. addData.roughness = brdfData.roughness;
  156. addData.roughness2 = brdfData.roughness2;
  157. addData.normalizationTerm = brdfData.normalizationTerm;
  158. addData.roughness2MinusOne = brdfData.roughness2MinusOne;
  159. addData.reflectivity = ReflectivitySpecular(brdfData.specular);
  160. addData.grazingTerm = brdfData.grazingTerm;
  161. addData.specOcclusion = occlusion;
  162. }
  163. else {
  164. #endif
  165. addData.coatThickness = clearcoatThickness;
  166. addData.coatSpecular = clearcoatSpecular;
  167. addData.normalWS = vertexNormalWS;
  168. addData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(clearcoatSmoothness);
  169. addData.roughness = PerceptualRoughnessToRoughness(addData.perceptualRoughness);
  170. addData.roughness2 = addData.roughness * addData.roughness;
  171. addData.normalizationTerm = addData.roughness * 4.0h + 2.0h;
  172. addData.roughness2MinusOne = addData.roughness2 - 1.0h;
  173. addData.reflectivity = ReflectivitySpecular(clearcoatSpecular);
  174. addData.grazingTerm = saturate(clearcoatSmoothness + addData.reflectivity);
  175. addData.specOcclusion = 1;
  176. #if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
  177. }
  178. #endif
  179. // ShadowMask: To ensure backward compatibility we have to avoid using shadowMask input, as it is not present in older shaders
  180. #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
  181. half4 shadowMask = inputData.shadowMask;
  182. #elif !defined (LIGHTMAP_ON)
  183. half4 shadowMask = unity_ProbesOcclusion;
  184. #else
  185. half4 shadowMask = half4(1, 1, 1, 1);
  186. #endif
  187. Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, shadowMask);
  188. //Light mainLight = GetMainLight(inputData.shadowCoord);
  189. // SSAO
  190. #if defined(_SCREEN_SPACE_OCCLUSION)
  191. AmbientOcclusionFactor aoFactor = GetScreenSpaceAmbientOcclusion(inputData.normalizedScreenSpaceUV);
  192. mainLight.color *= aoFactor.directAmbientOcclusion;
  193. occlusion = min(occlusion, aoFactor.indirectAmbientOcclusion);
  194. #endif
  195. MixRealtimeAndBakedGI(mainLight, addData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));
  196. // Approximation of refraction on BRDF
  197. half refractionScale = ((NdotV * 0.5h + 0.5h) * NdotV - 1.0h) * saturate(1.25h - 1.25h * (1.0h - clearcoatSmoothness)) + 1.0h;
  198. brdfData.diffuse = lerp(brdfData.diffuse, brdfData.diffuse * refractionScale, clearcoatThickness);
  199. // brdfData.specular = brdfData.specular * lerp(1.0, refractionScale, clearcoatThickness);
  200. half3 color = GlobalIllumination_LuxClearCoat(brdfData, addData, inputData.bakedGI, occlusion, addData.normalWS, inputData.normalWS, inputData.viewDirectionWS, NdotV);
  201. // Adjust base specular as we have a transition from coat to material and not air to material
  202. #if defined(_ADJUSTSPEC)
  203. // brdfData.specular = lerp(brdfData.specular, ConvertF0ForAirInterfaceToF0ForClearCoat15(brdfData.specular), addData.coatThickness);
  204. #endif
  205. color += LightingPhysicallyBased_LuxClearCoat(brdfData, addData, mainLight, inputData.normalWS, inputData.viewDirectionWS);
  206. #ifdef _ADDITIONAL_LIGHTS
  207. uint pixelLightCount = GetAdditionalLightsCount();
  208. for (uint i = 0u; i < pixelLightCount; ++i)
  209. {
  210. // Light light = GetAdditionalPerObjectLight(i, inputData.positionWS); // here; shadowAttenuation = 1.0;
  211. // URP 10: We have to use the new GetAdditionalLight function
  212. Light light = GetAdditionalLight(i, inputData.positionWS, shadowMask);
  213. #if defined(_SCREEN_SPACE_OCCLUSION)
  214. light.color *= aoFactor.directAmbientOcclusion;
  215. #endif
  216. color += LightingPhysicallyBased_LuxClearCoat(brdfData, addData, light, inputData.normalWS, inputData.viewDirectionWS);
  217. }
  218. #endif
  219. #ifdef _ADDITIONAL_LIGHTS_VERTEX
  220. color += inputData.vertexLighting * brdfData.diffuse;
  221. #endif
  222. color += emission;
  223. return half4(color, alpha);
  224. }
  225. #endif