Lux_Lighting_ClearCoat.hlsl 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. #if !defined(SHADERGRAPH_PREVIEW) || defined(LIGHTWEIGHT_LIGHTING_INCLUDED)
  2. // As we do not have access to the vertex lights we will make the shader always sample add lights per pixel
  3. #if defined(_ADDITIONAL_LIGHTS_VERTEX)
  4. #undef _ADDITIONAL_LIGHTS_VERTEX
  5. #define _ADDITIONAL_LIGHTS
  6. #endif
  7. #if defined(LIGHTWEIGHT_LIGHTING_INCLUDED) || defined(UNIVERSAL_LIGHTING_INCLUDED)
  8. struct AdditionalData {
  9. half coatThickness;
  10. half3 coatSpecular;
  11. half3 normalWS;
  12. half perceptualRoughness;
  13. half roughness;
  14. half roughness2;
  15. half normalizationTerm;
  16. half roughness2MinusOne; // roughness² - 1.0
  17. half reflectivity;
  18. half grazingTerm;
  19. half specOcclusion;
  20. bool enableSecondaryLobe;
  21. };
  22. half3 DirectBDRF_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS, half NdotL)
  23. {
  24. #ifndef _SPECULARHIGHLIGHTS_OFF
  25. float3 halfDir = SafeNormalize(lightDirectionWS + viewDirectionWS);
  26. half LoH = saturate(dot(lightDirectionWS, halfDir));
  27. // Base Lobe
  28. float NoH = saturate(dot(normalWS, halfDir));
  29. float d = NoH * NoH * brdfData.roughness2MinusOne + 1.00001f;
  30. half LoH2 = LoH * LoH;
  31. LoH2 = max(0.1h, LoH2); // as we can reuse it
  32. half specularTerm = brdfData.roughness2 / ((d * d) * LoH2 /* max(0.1h, LoH2) */ * brdfData.normalizationTerm);
  33. #if defined (SHADER_API_MOBILE) || defined (SHADER_API_SWITCH)
  34. specularTerm = specularTerm - HALF_MIN;
  35. specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
  36. #endif
  37. half3 spec = specularTerm * brdfData.specular * NdotL;
  38. // Coat Lobe
  39. // From HDRP: Scale base specular
  40. //#if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
  41. // [branch]
  42. // if (addData.coatThickness > 0.0h) {
  43. //#endif
  44. half coatF = F_Schlick(addData.reflectivity /*addData.coatSpecular*/ /*CLEAR_COAT_F0*/, LoH) * addData.coatThickness;
  45. spec *= Sq(1.0h - coatF);
  46. //spec *= (1.0h - coatF); // as used by filament, na, not really
  47. NoH = saturate(dot(addData.normalWS, halfDir));
  48. d = NoH * NoH * addData.roughness2MinusOne + 1.00001f;
  49. //LoH2 = LoH * LoH; no need to recalculate LoH2!
  50. specularTerm = addData.roughness2 / ((d * d) * LoH2 /* max(0.1h, LoH2) */ * addData.normalizationTerm);
  51. #if defined (SHADER_API_MOBILE) || defined (SHADER_API_SWITCH)
  52. specularTerm = specularTerm - HALF_MIN;
  53. specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
  54. #endif
  55. spec += specularTerm * addData.coatSpecular * saturate(dot(addData.normalWS, lightDirectionWS));
  56. //#if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
  57. // }
  58. //#endif
  59. half3 color = spec + brdfData.diffuse * NdotL; // * lerp(1.0h, 1.0h - coatF, addData.coatThickness);
  60. return color;
  61. #else
  62. return brdfData.diffuse * NdotL;
  63. #endif
  64. }
  65. half3 LightingPhysicallyBased_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS)
  66. {
  67. half NdotL = saturate(dot(normalWS, lightDirectionWS));
  68. half3 radiance = lightColor * (lightAttenuation); // * NdotL);
  69. return DirectBDRF_LuxClearCoat(brdfData, addData, normalWS, lightDirectionWS, viewDirectionWS, NdotL) * radiance;
  70. }
  71. half3 LightingPhysicallyBased_LuxClearCoat(BRDFData brdfData, AdditionalData addData, Light light, half3 normalWS, half3 viewDirectionWS)
  72. {
  73. return LightingPhysicallyBased_LuxClearCoat(brdfData, addData, light.color, light.direction, light.distanceAttenuation * light.shadowAttenuation, normalWS, viewDirectionWS);
  74. }
  75. half3 EnvironmentBRDF_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 indirectDiffuse, half3 indirectSpecular, half fresnelTerm)
  76. {
  77. half3 c = indirectDiffuse * brdfData.diffuse;
  78. float surfaceReduction = 1.0 / (addData.roughness2 + 1.0);
  79. c += surfaceReduction * indirectSpecular * lerp(addData.coatSpecular, addData.grazingTerm, fresnelTerm);
  80. return c;
  81. }
  82. half3 GlobalIllumination_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 bakedGI, half occlusion, half3 normalWS, half3 baseNormalWS, half3 viewDirectionWS, half NdotV)
  83. {
  84. half3 reflectVector = reflect(-viewDirectionWS, normalWS);
  85. half fresnelTerm = Pow4(1.0 - NdotV);
  86. half3 indirectDiffuse = bakedGI * occlusion;
  87. half3 indirectSpecular = GlossyEnvironmentReflection(reflectVector, addData.perceptualRoughness, addData.specOcclusion);
  88. half3 res = EnvironmentBRDF_LuxClearCoat(brdfData, addData, indirectDiffuse, indirectSpecular, fresnelTerm);
  89. //#if defined(_SECONDARYLOBE)
  90. if (addData.enableSecondaryLobe) {
  91. #if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
  92. [branch]
  93. if (addData.coatThickness > 0.0h) {
  94. #endif
  95. reflectVector = reflect(-viewDirectionWS, baseNormalWS);
  96. indirectSpecular = GlossyEnvironmentReflection(reflectVector, brdfData.perceptualRoughness, 1);
  97. float surfaceReduction = 1.0 / (brdfData.roughness2 + 1.0);
  98. res += NdotV * surfaceReduction * indirectSpecular * lerp(brdfData.specular, brdfData.grazingTerm, fresnelTerm);
  99. #if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
  100. }
  101. #endif
  102. //#endif
  103. }
  104. return res;
  105. }
  106. half3 f0ClearCoatToSurface_Lux(half3 f0)
  107. {
  108. // Approximation of iorTof0(f0ToIor(f0), 1.5)
  109. // This assumes that the clear coat layer has an IOR of 1.5
  110. #if defined(SHADER_API_MOBILE)
  111. return saturate(f0 * (f0 * 0.526868h + 0.529324h) - 0.0482256h);
  112. #else
  113. return saturate(f0 * (f0 * (0.941892h - 0.263008h * f0) + 0.346479h) - 0.0285998h);
  114. #endif
  115. }
  116. #endif
  117. #endif
  118. void Lighting_half(
  119. // Base inputs
  120. float3 positionWS,
  121. half3 viewDirectionWS,
  122. // Normal inputs
  123. half3 normalWS,
  124. half3 tangentWS,
  125. half3 bitangentWS,
  126. bool enableNormalMapping,
  127. half3 normalTS,
  128. // Surface description
  129. half3 albedo, // albedo is baseColor
  130. half metallic,
  131. half3 specular,
  132. half smoothness,
  133. half occlusion,
  134. half alpha,
  135. // Lighting specific inputs
  136. half clearcoatSmoothness,
  137. half clearcoatThickness,
  138. half3 clearcoatSpecular,
  139. half3 secondaryColor,
  140. bool enableSecondaryColor,
  141. bool enableSecondaryLobe,
  142. // Lightmapping
  143. float2 lightMapUV,
  144. // Final lit color
  145. out half3 MetaAlbedo,
  146. out half3 FinalLighting,
  147. out half3 MetaSpecular
  148. )
  149. {
  150. //#ifdef SHADERGRAPH_PREVIEW
  151. #if defined(SHADERGRAPH_PREVIEW) || ( !defined(LIGHTWEIGHT_LIGHTING_INCLUDED) && !defined(UNIVERSAL_LIGHTING_INCLUDED) )
  152. FinalLighting = albedo;
  153. MetaAlbedo = half3(0,0,0);
  154. MetaSpecular = half3(0,0,0);
  155. #else
  156. // Real Lighting ----------
  157. // Cache the geometry normal used by the coat
  158. half3 vertexNormalWS = NormalizeNormalPerPixel(normalWS);
  159. if (enableNormalMapping) {
  160. normalWS = TransformTangentToWorld(normalTS, half3x3(tangentWS.xyz, bitangentWS.xyz, normalWS.xyz));
  161. }
  162. normalWS = NormalizeNormalPerPixel(normalWS);
  163. viewDirectionWS = SafeNormalize(viewDirectionWS);
  164. // GI Lighting
  165. half3 bakedGI;
  166. #ifdef LIGHTMAP_ON
  167. lightMapUV = lightMapUV * unity_LightmapST.xy + unity_LightmapST.zw;
  168. bakedGI = SAMPLE_GI(lightMapUV, half3(0,0,0), normalWS);
  169. #else
  170. bakedGI = SampleSH(normalWS);
  171. #endif
  172. // Clear Coat Lighting
  173. half NdotV = saturate( dot(vertexNormalWS, viewDirectionWS) );
  174. #if !defined(LIGHTWEIGHT_META_PASS_INCLUDED) && !defined(UNIVERSAL_META_PASS_INCLUDED)
  175. if(enableSecondaryColor) {
  176. albedo = lerp(secondaryColor, albedo, NdotV);
  177. }
  178. #endif
  179. BRDFData brdfData;
  180. InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
  181. // Adjust specular as we have a transition from coat to material and not air to material
  182. brdfData.specular = lerp(brdfData.specular, f0ClearCoatToSurface_Lux(brdfData.specular), clearcoatThickness);
  183. AdditionalData addData;
  184. addData.coatThickness = clearcoatThickness;
  185. addData.coatSpecular = clearcoatSpecular;
  186. addData.normalWS = vertexNormalWS;
  187. addData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(clearcoatSmoothness);
  188. addData.roughness = PerceptualRoughnessToRoughness(addData.perceptualRoughness);
  189. addData.roughness2 = addData.roughness * addData.roughness;
  190. addData.normalizationTerm = addData.roughness * 4.0h + 2.0h;
  191. addData.roughness2MinusOne = addData.roughness2 - 1.0h;
  192. addData.reflectivity = ReflectivitySpecular(clearcoatSpecular);
  193. addData.grazingTerm = saturate(clearcoatSmoothness + addData.reflectivity);
  194. addData.specOcclusion = 1;
  195. addData.enableSecondaryLobe = enableSecondaryLobe;
  196. float4 clipPos = TransformWorldToHClip(positionWS);
  197. // Get Shadow Sampling Coords / Unfortunately per pixel...
  198. #if SHADOWS_SCREEN
  199. float4 shadowCoord = ComputeScreenPos(clipPos);
  200. #else
  201. float4 shadowCoord = TransformWorldToShadowCoord(positionWS);
  202. #endif
  203. // Shadow mask
  204. #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
  205. half4 shadowMask = SAMPLE_SHADOWMASK(lightMapUV);
  206. #elif !defined (LIGHTMAP_ON)
  207. half4 shadowMask = unity_ProbesOcclusion;
  208. #else
  209. half4 shadowMask = half4(1, 1, 1, 1);
  210. #endif
  211. //Light mainLight = GetMainLight(shadowCoord);
  212. Light mainLight = GetMainLight(shadowCoord, positionWS, shadowMask);
  213. // SSAO
  214. #if defined(_SCREEN_SPACE_OCCLUSION)
  215. float4 ndc = clipPos * 0.5f;
  216. float2 normalized = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
  217. normalized /= clipPos.w;
  218. normalized *= _ScreenParams.xy;
  219. // We could also use IN.Screenpos(default) --> ( IN.Screenpos.xy * _ScreenParams.xy)
  220. // HDRP 10.1
  221. normalized = GetNormalizedScreenSpaceUV(normalized);
  222. AmbientOcclusionFactor aoFactor = GetScreenSpaceAmbientOcclusion(normalized);
  223. mainLight.color *= aoFactor.directAmbientOcclusion;
  224. occlusion = min(occlusion, aoFactor.indirectAmbientOcclusion);
  225. #endif
  226. MixRealtimeAndBakedGI(mainLight, normalWS, bakedGI, half4(0, 0, 0, 0));
  227. // Approximation of refraction on BRDF
  228. half refractionScale = ((NdotV * 0.5 + 0.5) * NdotV - 1.0) * saturate(1.25 - 1.25 * (1.0 - clearcoatSmoothness)) + 1;
  229. brdfData.diffuse = lerp(brdfData.diffuse, brdfData.diffuse * refractionScale, clearcoatThickness);
  230. // GI
  231. FinalLighting = GlobalIllumination_LuxClearCoat(brdfData, addData, bakedGI, occlusion, addData.normalWS, normalWS, viewDirectionWS, NdotV);
  232. // Main Light
  233. FinalLighting += LightingPhysicallyBased_LuxClearCoat(brdfData, addData, mainLight, normalWS, viewDirectionWS);
  234. // Handle additional lights
  235. #ifdef _ADDITIONAL_LIGHTS
  236. uint pixelLightCount = GetAdditionalLightsCount();
  237. for (uint i = 0u; i < pixelLightCount; ++i) {
  238. // Light light = GetAdditionalPerObjectLight(index, positionWS); // here; shadowAttenuation = 1.0;
  239. // URP 10: We have to use the new GetAdditionalLight function
  240. Light light = GetAdditionalLight(i, positionWS, shadowMask);
  241. #if defined(_SCREEN_SPACE_OCCLUSION)
  242. light.color *= aoFactor.directAmbientOcclusion;
  243. #endif
  244. FinalLighting += LightingPhysicallyBased_LuxClearCoat(brdfData, addData, light, normalWS, viewDirectionWS);
  245. }
  246. #endif
  247. // Set Albedo for meta pass
  248. #if defined(LIGHTWEIGHT_META_PASS_INCLUDED) || defined(UNIVERSAL_META_PASS_INCLUDED)
  249. FinalLighting = half3(0,0,0);
  250. MetaAlbedo = albedo;
  251. MetaSpecular = specular;
  252. #else
  253. MetaAlbedo = half3(0,0,0);
  254. MetaSpecular = half3(0,0,0);
  255. #endif
  256. // End Real Lighting ----------
  257. #endif
  258. }
  259. // Unity 2019.1. needs a float version
  260. void Lighting_float(
  261. // Base inputs
  262. float3 positionWS,
  263. half3 viewDirectionWS,
  264. // Normal inputs
  265. half3 normalWS,
  266. half3 tangentWS,
  267. half3 bitangentWS,
  268. bool enableNormalMapping,
  269. half3 normalTS,
  270. // Surface description
  271. half3 albedo,
  272. half metallic,
  273. half3 specular,
  274. half smoothness,
  275. half occlusion,
  276. half alpha,
  277. // Lighting specific inputs
  278. half clearcoatSmoothness,
  279. half clearcoatThickness,
  280. half3 clearcoatSpecular,
  281. half3 secondaryColor,
  282. bool enableSecondaryColor,
  283. bool enableSecondaryLobe,
  284. // Lightmapping
  285. float2 lightMapUV,
  286. // Final lit color
  287. out half3 MetaAlbedo,
  288. out half3 FinalLighting,
  289. out half3 MetaSpecular
  290. )
  291. {
  292. Lighting_half(
  293. positionWS, viewDirectionWS, normalWS, tangentWS, bitangentWS, enableNormalMapping, normalTS,
  294. albedo, metallic, specular, smoothness, occlusion, alpha,
  295. clearcoatSmoothness, clearcoatThickness, clearcoatSpecular, secondaryColor, enableSecondaryColor, enableSecondaryLobe,
  296. lightMapUV, MetaAlbedo, FinalLighting, MetaSpecular);
  297. }