Lux URP Hair Core.hlsl 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #ifndef HAIR_CORE_INCLUDED
  2. #define HAIR_CORE_INCLUDED
  3. //--------------------------------------
  4. // Vertex shader
  5. VertexOutput LitPassVertex(VertexInput input)
  6. {
  7. VertexOutput output = (VertexOutput)0;
  8. UNITY_SETUP_INSTANCE_ID(input);
  9. UNITY_TRANSFER_INSTANCE_ID(input, output);
  10. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
  11. VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
  12. VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);
  13. float3 viewDirWS = GetCameraPositionWS() - vertexInput.positionWS;
  14. half3 vertexLight = VertexLighting(vertexInput.positionWS, normalInput.normalWS);
  15. half fogFactor = ComputeFogFactor(vertexInput.positionCS.z);
  16. output.uv.xy = input.texcoord;
  17. // Hair lighting always needs tangent
  18. output.viewDirWS = viewDirWS;
  19. output.normalWS = normalInput.normalWS;
  20. float sign = input.tangentOS.w * GetOddNegativeScale();
  21. output.tangentWS = float4(normalInput.tangentWS.xyz, sign);
  22. OUTPUT_LIGHTMAP_UV(input.lightmapUV, unity_LightmapST, output.lightmapUV);
  23. OUTPUT_SH(output.normalWS.xyz, output.vertexSH);
  24. output.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
  25. #if defined(REQUIRES_WORLD_SPACE_POS_INTERPOLATOR)
  26. output.positionWS = vertexInput.positionWS;
  27. #endif
  28. #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
  29. output.shadowCoord = GetShadowCoord(vertexInput);
  30. #endif
  31. output.positionCS = vertexInput.positionCS;
  32. output.color = input.color;
  33. // output.screenPos = ComputeScreenPos(output.positionCS);
  34. return output;
  35. }
  36. //--------------------------------------
  37. // Fragment shader and functions
  38. float Dither32(float2 Pos, float frameIndexMod4)
  39. {
  40. uint3 k0 = uint3(13, 5, 15);
  41. float Ret = dot(float3(Pos.xy, frameIndexMod4 + 0.5f), k0 / 32.0f);
  42. return frac(Ret);
  43. }
  44. inline void InitializeHairLitSurfaceData(float2 uv, half4 vertexColor, out SurfaceDescription outSurfaceData)
  45. {
  46. half4 albedoAlpha = SampleAlbedoAlpha(uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap));
  47. outSurfaceData.alpha = Alpha(albedoAlpha.a, _BaseColor, _Cutoff);
  48. // a2c sharpened
  49. // (col.a - _Cutoff) / max(fwidth(col.a), 0.0001) + 0.5;
  50. // float2 ditherUV = screenPos.xy / screenPos.w;
  51. // ditherUV *= _ScreenParams.xy * _Dither_TexelSize.xy;
  52. // half BlueNoise = SAMPLE_TEXTURE2D(_Dither, sampler_Dither, ditherUV).a;
  53. // clip(albedoAlpha.a - clamp(BlueNoise, 0.1, _Cutoff));
  54. // outSurfaceData.alpha = 1;
  55. //clip( albedoAlpha.a - Dither32( screenPos.xy / screenPos.w * _ScreenParams.xy, _FrameIndexMod4 ));
  56. outSurfaceData.albedo = albedoAlpha.rgb; // * _BaseColor.rgb; // * vertexColor.rgb;
  57. outSurfaceData.metallic = 0;
  58. outSurfaceData.specular = _SpecColor.rgb;
  59. // Normal Map
  60. #if defined (_NORMALMAP)
  61. outSurfaceData.normalTS = SampleNormal(uv, TEXTURE2D_ARGS(_BumpMap, sampler_BumpMap), _BumpScale);
  62. #else
  63. outSurfaceData.normalTS = half3(0,0,1);
  64. #endif
  65. //outSurfaceData.occlusion = lerp(1.0h, SSSAOSample.a, _OcclusionStrength);
  66. #if defined(_MASKMAP)
  67. half4 MaskMapSample = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, uv);
  68. outSurfaceData.occlusion = MaskMapSample.g; //lerp(1.0h, SSSAOSample.a, _OcclusionStrength);
  69. outSurfaceData.shift = MaskMapSample.b;
  70. #else
  71. outSurfaceData.occlusion = 1;
  72. outSurfaceData.shift = 1;
  73. #endif
  74. outSurfaceData.smoothness = _Smoothness;
  75. outSurfaceData.emission = 0;
  76. }
  77. void InitializeInputData(VertexOutput input, half3 normalTS, out InputData inputData)
  78. {
  79. inputData = (InputData)0;
  80. #if defined(REQUIRES_WORLD_SPACE_POS_INTERPOLATOR)
  81. inputData.positionWS = input.positionWS;
  82. #endif
  83. half3 viewDirWS = SafeNormalize(input.viewDirWS);
  84. float sgn = input.tangentWS.w; // should be either +1 or -1
  85. float3 bitangent = sgn * cross(input.normalWS.xyz, input.tangentWS.xyz);
  86. inputData.normalWS = TransformTangentToWorld(normalTS, half3x3(input.tangentWS.xyz, bitangent, input.normalWS.xyz));
  87. inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS);
  88. inputData.viewDirectionWS = viewDirWS;
  89. #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
  90. inputData.shadowCoord = input.shadowCoord;
  91. #elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
  92. inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
  93. #else
  94. inputData.shadowCoord = float4(0, 0, 0, 0);
  95. #endif
  96. inputData.fogCoord = input.fogFactorAndVertexLight.x;
  97. inputData.vertexLighting = input.fogFactorAndVertexLight.yzw;
  98. inputData.bakedGI = SAMPLE_GI(input.lightmapUV, input.vertexSH, inputData.normalWS);
  99. //inputData.normalizedScreenSpaceUV = input.positionCS.xy;
  100. inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(input.positionCS);
  101. }
  102. half4 LitPassFragment(VertexOutput input
  103. #if defined(_ENABLEVFACE)
  104. , half facing : VFACE
  105. #endif
  106. ) : SV_Target
  107. {
  108. UNITY_SETUP_INSTANCE_ID(input);
  109. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  110. // Get the surface description
  111. SurfaceDescription surfaceData;
  112. InitializeHairLitSurfaceData(input.uv.xy, input.color, surfaceData);
  113. // Handle VFACE
  114. #if defined(_ENABLEVFACE)
  115. surfaceData.normalTS.z *= facing;
  116. #endif
  117. // Prepare surface data (like bring normal into world space and get missing inputs like gi
  118. InputData inputData;
  119. InitializeInputData(input, surfaceData.normalTS, inputData);
  120. #if defined(_RIMLIGHTING)
  121. half rim = saturate(1.0h - saturate( dot(inputData.normalWS, inputData.viewDirectionWS) ) );
  122. half power = _RimPower;
  123. UNITY_BRANCH if(_RimFrequency > 0 ) {
  124. half perPosition = lerp(0.0h, 1.0h, dot(1.0h, frac(UNITY_MATRIX_M._m03_m13_m23) * 2.0h - 1.0h ) * _RimPerPositionFrequency ) * 3.1416h;
  125. power = lerp(power, _RimMinPower, (1.0h + sin(_Time.y * _RimFrequency + perPosition) ) * 0.5h );
  126. }
  127. surfaceData.emission += pow(rim, power) * _RimColor.rgb * _RimColor.a;
  128. #endif
  129. // Apply lighting
  130. half4 color = LuxURPHairFragment(
  131. inputData,
  132. input.tangentWS.xyz,
  133. surfaceData.albedo * lerp(_SecondaryColor.rgb, _BaseColor.rgb, input.color.a),
  134. surfaceData.specular,
  135. surfaceData.occlusion,
  136. surfaceData.emission,
  137. surfaceData.albedo, // noise
  138. _SpecularShift * surfaceData.shift,
  139. _SpecularTint.rgb,
  140. _SpecularExponent * surfaceData.smoothness,
  141. _SecondarySpecularShift * surfaceData.shift,
  142. _SecondarySpecularTint.rgb,
  143. _SecondarySpecularExponent * surfaceData.smoothness,
  144. _RimTransmissionIntensity,
  145. _AmbientReflection
  146. );
  147. color.a = surfaceData.alpha;
  148. // Add fog
  149. color.rgb = MixFog(color.rgb, inputData.fogCoord);
  150. return color;
  151. }
  152. #endif