Lux URP Cloth Lighting.hlsl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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 LIGHTWEIGHT_CLOTHLIGHTING_INCLUDED
  6. #define LIGHTWEIGHT_CLOTHLIGHTING_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. // --------- rename!!!!!!!!!
  13. // Ref: https://knarkowicz.wordpress.com/2018/01/04/cloth-shading/
  14. real D_CharlieNoPI_Lux(real NdotH, real roughness)
  15. {
  16. float invR = rcp(roughness);
  17. float cos2h = NdotH * NdotH;
  18. float sin2h = 1.0 - cos2h;
  19. // Note: We have sin^2 so multiply by 0.5 to cancel it
  20. return (2.0 + invR) * PositivePow(sin2h, invR * 0.5) / 2.0;
  21. }
  22. real D_Charlie_Lux(real NdotH, real roughness)
  23. {
  24. return INV_PI * D_CharlieNoPI_Lux(NdotH, roughness);
  25. }
  26. // We use V_Ashikhmin instead of V_Charlie in practice for game due to the cost of V_Charlie
  27. real V_Ashikhmin_Lux(real NdotL, real NdotV)
  28. {
  29. // Use soft visibility term introduce in: Crafting a Next-Gen Material Pipeline for The Order : 1886
  30. return 1.0 / (4.0 * (NdotL + NdotV - NdotL * NdotV));
  31. }
  32. // A diffuse term use with fabric done by tech artist - empirical
  33. real FabricLambertNoPI_Lux(real roughness)
  34. {
  35. return lerp(1.0, 0.5, roughness);
  36. }
  37. real FabricLambert_Lux(real roughness)
  38. {
  39. return INV_PI * FabricLambertNoPI_Lux(roughness);
  40. }
  41. // ---------
  42. struct AdditionalData {
  43. half3 tangentWS;
  44. half3 bitangentWS;
  45. float partLambdaV;
  46. half roughnessT;
  47. half roughnessB;
  48. half3 anisoReflectionNormal;
  49. half3 sheenColor;
  50. };
  51. half3 DirectBDRF_LuxCloth(BRDFData brdfData, AdditionalData addData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS, half NdotL)
  52. {
  53. #ifndef _SPECULARHIGHLIGHTS_OFF
  54. float3 halfDir = SafeNormalize(lightDirectionWS + viewDirectionWS);
  55. float NoH = saturate(dot(normalWS, halfDir));
  56. half LoH = saturate(dot(lightDirectionWS, halfDir));
  57. half NdotV = saturate(dot(normalWS, viewDirectionWS ));
  58. #if defined(_COTTONWOOL)
  59. // NOTE: We use the noPI version here!!!!!!
  60. float D = D_CharlieNoPI_Lux(NoH, brdfData.roughness);
  61. // Unity: V_Charlie is expensive, use approx with V_Ashikhmin instead
  62. // Unity: float Vis = V_Charlie(NdotL, NdotV, bsdfData.roughness);
  63. float Vis = V_Ashikhmin_Lux(NdotL, NdotV);
  64. // Unity: Fabrics are dieletric but we simulate forward scattering effect with colored specular (fuzz tint term)
  65. // Unity: We don't use Fresnel term for CharlieD
  66. // SheenColor seemed way too dark (compared to HDRP) – so i multiply it with PI which looked ok and somehow matched HDRP
  67. // Therefore we use the noPI charlie version. As PI is a constant factor the artists can tweak the look by adjusting the sheen color.
  68. float3 F = addData.sheenColor; // * PI;
  69. half3 specularLighting = F * Vis * D;
  70. // Unity: Note: diffuseLighting originally is multiply by color in PostEvaluateBSDF
  71. // So we do it here :)
  72. // Using saturate to get rid of artifacts around the borders.
  73. return saturate(specularLighting) + brdfData.diffuse * FabricLambert_Lux(brdfData.roughness);
  74. #else
  75. float TdotH = dot(addData.tangentWS, halfDir);
  76. float TdotL = dot(addData.tangentWS, lightDirectionWS);
  77. float BdotH = dot(addData.bitangentWS, halfDir);
  78. float BdotL = dot(addData.bitangentWS, lightDirectionWS);
  79. float3 F = F_Schlick(brdfData.specular, LoH);
  80. //float TdotV = dot(addData.tangentWS, viewDirectionWS);
  81. //float BdotV = dot(addData.bitangentWS, viewDirectionWS);
  82. float DV = DV_SmithJointGGXAniso(
  83. TdotH, BdotH, NoH, NdotV, TdotL, BdotL, NdotL,
  84. addData.roughnessT, addData.roughnessB, addData.partLambdaV
  85. );
  86. // Check NdotL gets factores in outside as well.. correct?
  87. half3 specularLighting = F * DV;
  88. return specularLighting + brdfData.diffuse;
  89. #endif
  90. //half3 color = specularTerm * brdfData.specular + brdfData.diffuse;
  91. //return color;
  92. #else
  93. return brdfData.diffuse;
  94. #endif
  95. }
  96. half3 LightingPhysicallyBased_LuxCloth(BRDFData brdfData, AdditionalData addData, half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS, half NdotL)
  97. {
  98. //half NdotL = saturate(dot(normalWS, lightDirectionWS));
  99. half3 radiance = lightColor * (lightAttenuation * NdotL);
  100. return DirectBDRF_LuxCloth(brdfData, addData, normalWS, lightDirectionWS, viewDirectionWS, NdotL) * radiance;
  101. }
  102. half3 LightingPhysicallyBased_LuxCloth(BRDFData brdfData, AdditionalData addData, Light light, half3 normalWS, half3 viewDirectionWS, half NdotL)
  103. {
  104. return LightingPhysicallyBased_LuxCloth(brdfData, addData, light.color, light.direction, light.distanceAttenuation * light.shadowAttenuation, normalWS, viewDirectionWS, NdotL);
  105. }
  106. half4 LuxURPClothFragmentPBR(InputData inputData, half3 albedo, half metallic, half3 specular,
  107. half smoothness, half occlusion, half3 emission, half alpha, half3 tangentWS, half anisotropy, half3 sheenColor, half4 translucency)
  108. {
  109. #if defined(_COTTONWOOL)
  110. smoothness = lerp(0.0h, 0.6h, smoothness);
  111. #endif
  112. BRDFData brdfData;
  113. InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
  114. // Do not apply energy conservtion
  115. brdfData.diffuse = albedo;
  116. brdfData.specular = specular;
  117. AdditionalData addData;
  118. // Adjust tangentWS in case normal mapping is active
  119. #if defined(_NORMALMAP)
  120. tangentWS = Orthonormalize(tangentWS, inputData.normalWS);
  121. #endif
  122. addData.tangentWS = tangentWS;
  123. addData.bitangentWS = cross(inputData.normalWS, tangentWS);
  124. // We do not apply ClampRoughnessForAnalyticalLights here
  125. addData.roughnessT = brdfData.roughness * (1 + anisotropy);
  126. addData.roughnessB = brdfData.roughness * (1 - anisotropy);
  127. #if !defined(_COTTONWOOL)
  128. float TdotV = dot(addData.tangentWS, inputData.viewDirectionWS);
  129. float BdotV = dot(addData.bitangentWS, inputData.viewDirectionWS);
  130. float NdotV = dot(inputData.normalWS, inputData.viewDirectionWS);
  131. addData.partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, addData.roughnessT, addData.roughnessB);
  132. // Set reflection normal and roughness – derived from GetGGXAnisotropicModifiedNormalAndRoughness
  133. half3 grainDirWS = (anisotropy >= 0.0) ? addData.bitangentWS : addData.tangentWS;
  134. half stretch = abs(anisotropy) * saturate(1.5h * sqrt(brdfData.perceptualRoughness));
  135. addData.anisoReflectionNormal = GetAnisotropicModifiedNormal(grainDirWS, inputData.normalWS, inputData.viewDirectionWS, stretch);
  136. half iblPerceptualRoughness = brdfData.perceptualRoughness * saturate(1.2 - abs(anisotropy));
  137. // Overwrite perceptual roughness for ambient specular reflections
  138. brdfData.perceptualRoughness = iblPerceptualRoughness;
  139. #else
  140. // partLambdaV should be 0.0f in case of cotton wool
  141. addData.partLambdaV = 0.0h;
  142. addData.anisoReflectionNormal = inputData.normalWS;
  143. float NdotV = dot(inputData.normalWS, inputData.viewDirectionWS);
  144. // Only used for reflections - so we skip it
  145. /*float3 preFGD = SAMPLE_TEXTURE2D_LOD(_PreIntegratedLUT, sampler_PreIntegratedLUT, float2(NdotV, brdfData.perceptualRoughness), 0).xyz;
  146. // Denormalize the value
  147. preFGD.y = preFGD.y / (1 - preFGD.y);
  148. half3 specularFGD = preFGD.yyy * fresnel0;
  149. // z = FabricLambert
  150. half3 diffuseFGD = preFGD.z;
  151. half reflectivity = preFGD.y;*/
  152. #endif
  153. addData.sheenColor = sheenColor;
  154. // ShadowMask: To ensure backward compatibility we have to avoid using shadowMask input, as it is not present in older shaders
  155. #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
  156. half4 shadowMask = inputData.shadowMask;
  157. #elif !defined (LIGHTMAP_ON)
  158. half4 shadowMask = unity_ProbesOcclusion;
  159. #else
  160. half4 shadowMask = half4(1, 1, 1, 1);
  161. #endif
  162. //Light mainLight = GetMainLight(inputData.shadowCoord);
  163. Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, shadowMask);
  164. half3 mainLightColor = mainLight.color;
  165. // SSAO
  166. #if defined(_SCREEN_SPACE_OCCLUSION)
  167. AmbientOcclusionFactor aoFactor = GetScreenSpaceAmbientOcclusion(inputData.normalizedScreenSpaceUV);
  168. mainLight.color *= aoFactor.directAmbientOcclusion;
  169. occlusion = min(occlusion, aoFactor.indirectAmbientOcclusion);
  170. #endif
  171. MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));
  172. half NdotL = saturate(dot(inputData.normalWS, mainLight.direction ));
  173. half3 color = GlobalIllumination(brdfData, inputData.bakedGI, occlusion, addData.anisoReflectionNormal, inputData.viewDirectionWS);
  174. color += LightingPhysicallyBased_LuxCloth(brdfData, addData, mainLight, inputData.normalWS, inputData.viewDirectionWS, NdotL);
  175. #if defined(_SCATTERING)
  176. half transPower = translucency.y;
  177. half3 transLightDir = mainLight.direction + inputData.normalWS * translucency.w;
  178. half transDot = dot( transLightDir, -inputData.viewDirectionWS );
  179. transDot = exp2(saturate(transDot) * transPower - transPower);
  180. color += brdfData.diffuse * transDot * (1.0h - NdotL) * mainLightColor * lerp(1.0h, mainLight.shadowAttenuation, translucency.z) * translucency.x * 4;
  181. #endif
  182. #ifdef _ADDITIONAL_LIGHTS
  183. uint pixelLightCount = GetAdditionalLightsCount();
  184. for (uint i = 0u; i < pixelLightCount; ++i)
  185. {
  186. // Light light = GetAdditionalPerObjectLight(index, positionWS); // here; shadowAttenuation = 1.0;
  187. // URP 10: We have to use the new GetAdditionalLight function
  188. Light light = GetAdditionalLight(i, inputData.positionWS, shadowMask);
  189. half3 lightColor = light.color;
  190. #if defined(_SCREEN_SPACE_OCCLUSION)
  191. light.color *= aoFactor.directAmbientOcclusion;
  192. #endif
  193. NdotL = saturate(dot(inputData.normalWS, light.direction ));
  194. color += LightingPhysicallyBased_LuxCloth(brdfData, addData, light, inputData.normalWS, inputData.viewDirectionWS, NdotL);
  195. // translucency
  196. #if defined(_SCATTERING)
  197. transPower = translucency.y;
  198. transLightDir = light.direction + inputData.normalWS * translucency.w;
  199. transDot = dot( transLightDir, -inputData.viewDirectionWS );
  200. transDot = exp2(saturate(transDot) * transPower - transPower);
  201. color += brdfData.diffuse * transDot * (1.0h - NdotL) * lightColor * lerp(1.0h, light.shadowAttenuation, translucency.z) * light.distanceAttenuation * translucency.x * 4;
  202. #endif
  203. }
  204. #endif
  205. #ifdef _ADDITIONAL_LIGHTS_VERTEX
  206. color += inputData.vertexLighting * brdfData.diffuse;
  207. #endif
  208. color += emission;
  209. return half4(color, alpha);
  210. }
  211. #endif