Lux URP Simple Fuzz Lighting.hlsl 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // NOTE: Based on URP Lighting.hlsl which replaced some half3 with floats to avoid lighting artifacts on mobile
  2. #ifndef LIGHTWEIGHT_FUZZLIGHTING_INCLUDED
  3. #define LIGHTWEIGHT_FUZZHLIGHTING_INCLUDED
  4. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
  5. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl"
  6. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl"
  7. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  8. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
  9. real Fuzz(real NdotV, real fuzzPower, real fuzzBias)
  10. {
  11. return exp2( (1.0h - NdotV) * fuzzPower - fuzzPower) + fuzzBias;
  12. }
  13. real WrappedDiffuse(real NdotL, real3 normalWS, real3 lightDirectionWS, real wrap)
  14. {
  15. return saturate( (dot(normalWS, lightDirectionWS) + wrap) * rcp( (1.0h + wrap) * (1.0h + wrap) ) );
  16. }
  17. // ---------
  18. struct AdditionalData {
  19. half fuzzWrap;
  20. half fuzz;
  21. };
  22. half3 DirectBDRF_LuxFuzz(BRDFData brdfData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS, half NdotL)
  23. {
  24. // Regular Code
  25. #ifndef _SPECULARHIGHLIGHTS_OFF
  26. float3 halfDir = SafeNormalize(lightDirectionWS + viewDirectionWS);
  27. float NoH = saturate(dot(normalWS, halfDir));
  28. half LoH = saturate(dot(lightDirectionWS, halfDir));
  29. // Standard specular lighting
  30. float d = NoH * NoH * brdfData.roughness2MinusOne + 1.00001f;
  31. half LoH2 = LoH * LoH;
  32. half specularTerm = brdfData.roughness2 / ((d * d) * 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. return specularTerm * brdfData.specular + brdfData.diffuse;
  38. #else
  39. return brdfData.diffuse;
  40. #endif
  41. }
  42. half3 LightingPhysicallyBased_LuxFuzz(BRDFData brdfData,
  43. #if defined(_SIMPLEFUZZ)
  44. AdditionalData addData,
  45. #endif
  46. half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS, half NdotL)
  47. {
  48. half3 radiance = lightColor * (lightAttenuation * NdotL);
  49. #if defined(_SIMPLEFUZZ)
  50. half wrappedNdotL = WrappedDiffuse(NdotL, normalWS, lightDirectionWS, addData.fuzzWrap);
  51. #endif
  52. return DirectBDRF_LuxFuzz(brdfData, normalWS, lightDirectionWS, viewDirectionWS, NdotL) * radiance
  53. #if defined(_SIMPLEFUZZ)
  54. + (addData.fuzz * brdfData.diffuse) * lightColor * (lightAttenuation * wrappedNdotL )
  55. #endif
  56. ;
  57. }
  58. half3 LightingPhysicallyBased_LuxFuzz(BRDFData brdfData,
  59. #if defined(_SIMPLEFUZZ)
  60. AdditionalData addData,
  61. #endif
  62. Light light, half3 normalWS, half3 viewDirectionWS, half NdotL)
  63. {
  64. return LightingPhysicallyBased_LuxFuzz(brdfData,
  65. #if defined(_SIMPLEFUZZ)
  66. addData,
  67. #endif
  68. light.color, light.direction, light.distanceAttenuation * light.shadowAttenuation, normalWS, viewDirectionWS, NdotL);
  69. }
  70. half4 LuxURPSimpleFuzzFragmentPBR(InputData inputData, half3 albedo, half metallic, half3 specular,
  71. half smoothness, half occlusion, half3 emission, half alpha, half4 translucency, half fuzzMask, half fuzzPower, half fuzzBias, half fuzzWrap, half fuzzStrength, half fuzzAmbient)
  72. {
  73. BRDFData brdfData;
  74. InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
  75. // ShadowMask: To ensure backward compatibility we have to avoid using shadowMask input, as it is not present in older shaders
  76. #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
  77. half4 shadowMask = inputData.shadowMask;
  78. #elif !defined (LIGHTMAP_ON)
  79. half4 shadowMask = unity_ProbesOcclusion;
  80. #else
  81. half4 shadowMask = half4(1, 1, 1, 1);
  82. #endif
  83. //Light mainLight = GetMainLight(inputData.shadowCoord);
  84. Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, shadowMask);
  85. half3 mainLightColor = mainLight.color;
  86. // SSAO
  87. #if defined(_SCREEN_SPACE_OCCLUSION)
  88. AmbientOcclusionFactor aoFactor = GetScreenSpaceAmbientOcclusion(inputData.normalizedScreenSpaceUV);
  89. mainLight.color *= aoFactor.directAmbientOcclusion;
  90. occlusion = min(occlusion, aoFactor.indirectAmbientOcclusion);
  91. #endif
  92. MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));
  93. half NdotL = saturate(dot(inputData.normalWS, mainLight.direction ));
  94. #if defined(_SIMPLEFUZZ)
  95. AdditionalData addData;
  96. addData.fuzzWrap = fuzzWrap;
  97. // We tweak the diffuse to get some ambient fuzz lighting as well.
  98. half NdotV = saturate(dot(inputData.normalWS, inputData.viewDirectionWS ));
  99. addData.fuzz = Fuzz(NdotV, fuzzPower, fuzzBias);
  100. addData.fuzz *= fuzzMask * fuzzStrength;
  101. half3 diffuse = brdfData.diffuse;
  102. brdfData.diffuse *= 1.0h + addData.fuzz * fuzzAmbient;
  103. #endif
  104. half3 color = GlobalIllumination(brdfData, inputData.bakedGI, occlusion, inputData.normalWS, inputData.viewDirectionWS);
  105. #if defined(_SIMPLEFUZZ)
  106. // Reset diffuse as we want to use WrappedNdotL lighting.
  107. brdfData.diffuse = diffuse;
  108. #endif
  109. color += LightingPhysicallyBased_LuxFuzz(brdfData,
  110. #if defined(_SIMPLEFUZZ)
  111. addData,
  112. #endif
  113. mainLight, inputData.normalWS, inputData.viewDirectionWS, NdotL);
  114. // translucency
  115. #if defined(_SCATTERING)
  116. half transPower = translucency.y;
  117. half3 transLightDir = mainLight.direction + inputData.normalWS * translucency.w;
  118. half transDot = dot( transLightDir, -inputData.viewDirectionWS );
  119. transDot = exp2(saturate(transDot) * transPower - transPower);
  120. color += brdfData.diffuse * transDot * (1.0h - NdotL) * mainLightColor * lerp(1.0h, mainLight.shadowAttenuation, translucency.z) * translucency.x * 4;
  121. #endif
  122. #ifdef _ADDITIONAL_LIGHTS
  123. uint pixelLightCount = GetAdditionalLightsCount();
  124. for (uint i = 0u; i < pixelLightCount; ++i)
  125. {
  126. // Light light = GetAdditionalPerObjectLight(index, positionWS); // here; shadowAttenuation = 1.0;
  127. // URP 10: We have to use the new GetAdditionalLight function
  128. Light light = GetAdditionalLight(i, inputData.positionWS, shadowMask);
  129. half3 lightColor = light.color;
  130. #if defined(_SCREEN_SPACE_OCCLUSION)
  131. light.color *= aoFactor.directAmbientOcclusion;
  132. #endif
  133. NdotL = saturate(dot(inputData.normalWS, light.direction ));
  134. color += LightingPhysicallyBased_LuxFuzz(brdfData,
  135. #if defined(_SIMPLEFUZZ)
  136. addData,
  137. #endif
  138. light, inputData.normalWS, inputData.viewDirectionWS, NdotL);
  139. // translucency
  140. #if defined(_SCATTERING)
  141. transPower = translucency.y;
  142. transLightDir = light.direction + inputData.normalWS * translucency.w;
  143. transDot = dot( transLightDir, -inputData.viewDirectionWS );
  144. transDot = exp2(saturate(transDot) * transPower - transPower);
  145. color += brdfData.diffuse * transDot * (1.0h - NdotL) * lightColor * lerp(1.0h, light.shadowAttenuation, translucency.z) * light.distanceAttenuation * translucency.x * 4;
  146. #endif
  147. }
  148. #endif
  149. #ifdef _ADDITIONAL_LIGHTS_VERTEX
  150. color += inputData.vertexLighting * brdfData.diffuse;
  151. #endif
  152. //color += emission;
  153. return half4(color, alpha);
  154. }
  155. #endif