Lux_Lighting_Toon_V2.hlsl 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. #if !defined(SHADERGRAPH_PREVIEW) || ( defined(LIGHTWEIGHT_LIGHTING_INCLUDED) || defined(UNIVERSAL_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(RECEIVE_SHADOWS_OFF)
  8. #define _RECEIVE_SHADOWS_OFF
  9. #endif
  10. #if defined(LIGHTWEIGHT_LIGHTING_INCLUDED) || defined(UNIVERSAL_LIGHTING_INCLUDED)
  11. half3 LightingSpecular_Toon (Light light, half lightingRemap, half3 normalWS, half3 viewDirectionWS, half3 specular, half specularSmoothness, half smoothness, half specularStep, half specularUpper, bool energyConservation){
  12. float3 halfVec = SafeNormalize( float3(light.direction) + float3(viewDirectionWS));
  13. half NdotH = saturate(dot(normalWS, halfVec));
  14. half modifier = pow(NdotH /* lightingRemap*/, specularSmoothness);
  15. // Normalization? Na, we just multiply by smoothness in the return statement.
  16. // #define ONEOVERTWOPI 0.159155h
  17. // half normalization = (specularSmoothness + 1) * ONEOVERTWOPI;
  18. // Sharpen
  19. half modifierSharpened = smoothstep(specularStep, specularUpper, modifier);
  20. half toonNormalization = (energyConservation) ? smoothness : 1;
  21. return light.color * specular * modifierSharpened * toonNormalization; // * smoothness;
  22. }
  23. half3 LightingSpecularAniso_Toon (Light light, half NdotL, half3 normalWS, half3 viewDirectionWS, half3 tangentWS, half3 bitangentWS, half anisotropy, half3 specular, half specularSmoothness, half smoothness, half specularStep, half specularUpper, bool energyConservation){
  24. // This does not let us fade from isotropic to anisotropic...
  25. // half3 H = SafeNormalize(light.direction + viewDirectionWS);
  26. // half3 T = cross(normalWS, tangent);
  27. // T = lerp(tangent, bitangent, (anisotropy + 1) * 0.5);
  28. // float TdotH = dot(T, H);
  29. // float sinTHSq = saturate(1.0 - TdotH * TdotH);
  30. // float exponent = RoughnessToBlinnPhongSpecularExponent_Lux(1 - smoothness);
  31. // float modifier = dirAttn * pow(sinTHSq, 0.5 * exponent);
  32. // float norm = smoothness; //(exponent + 2) * rcp(2 * PI);
  33. // // Sharpen
  34. // half modifierSharpened = smoothstep(specularStep, specularUpper, modifier);
  35. // half toonNormalization = (energyConservation == 1.0h) ? norm : 1;
  36. // return light.color * specular * modifierSharpened * toonNormalization;
  37. // ///////////////////////////////
  38. //
  39. // GGX "like" distribution in order to be able to fade from isotropic to anisotropic
  40. // We skip visbility here as it is toon lighting.
  41. // NOTE: Further normalization does not help here to fixe the final shape...
  42. float3 H = SafeNormalize(float3(light.direction) + float3(viewDirectionWS));
  43. // TdotH and BdotH should be unclamped here
  44. float TdotH = dot(tangentWS, H);
  45. float BdotH = dot(bitangentWS, H);
  46. float NdotH = dot(normalWS, H);
  47. float roughness = 1.0f - smoothness;
  48. // roughness^2 would be correct here - but in order to get it a bit closer to our blinn phong isotropic specular we go with ^4 instead
  49. roughness *= roughness * roughness * roughness;
  50. float at = roughness * (1.0f + anisotropy);
  51. float ab = roughness * (1.0f - anisotropy);
  52. float a2 = at * ab;
  53. float3 v = float3(ab * TdotH, at * BdotH, a2 * NdotH);
  54. float v2 = dot(v, v);
  55. float w2 = a2 / v2;
  56. half res = half(a2 * w2 * w2 * (1.0f / PI));
  57. // Sharpen
  58. half modifierSharpened = smoothstep(specularStep, specularUpper, res);
  59. half toonNormalization = (energyConservation == 1.0h) ? smoothness : 1.0h;
  60. return light.color * specular * modifierSharpened * toonNormalization;
  61. }
  62. #endif
  63. half aaStep(half compValue, half gradient, half softness){
  64. half change = fwidth(gradient) * softness;
  65. // Base the range of the inverse lerp on the change over two pixels
  66. half lowerEdge = compValue - change;
  67. half upperEdge = compValue + change;
  68. // Do the inverse interpolation
  69. half stepped = (gradient - lowerEdge) / (upperEdge - lowerEdge);
  70. stepped = saturate(stepped);
  71. return stepped;
  72. }
  73. #endif
  74. void Lighting_half(
  75. // Base inputs
  76. float3 positionWS,
  77. half3 viewDirectionWS,
  78. // Normal inputs
  79. half3 normalWS,
  80. half3 tangentWS,
  81. half3 bitangentWS,
  82. half3 normalTS,
  83. // Surface description
  84. half3 albedo,
  85. half3 shadedAlbedo,
  86. half anisotropy,
  87. bool energyConservation,
  88. half3 specular,
  89. half smoothness,
  90. half occlusion,
  91. // Smoothsteps
  92. half steps,
  93. half diffuseStep,
  94. half diffuseFalloff,
  95. half specularStep,
  96. half specularFalloff,
  97. half shadowFalloff,
  98. half shadowBiasDirectional,
  99. half shadowBiasAdditional,
  100. // Colorize shaded parts
  101. half colorizeMainLight,
  102. half colorizeAddLights,
  103. half lightColorContribution,
  104. half addLightFalloff,
  105. // Rim Lighting
  106. half rimPower,
  107. half rimFalloff,
  108. half4 rimColor,
  109. half rimAttenuation,
  110. // Lightmapping
  111. float2 lightMapUV,
  112. // Ramp
  113. Texture2D GradientMap,
  114. float GradientWidth,
  115. SamplerState sampler_Linear,
  116. SamplerState sampler_Point,
  117. bool receiveSSAO,
  118. // Final lit color
  119. out half3 Lighting,
  120. out half3 MetaAlbedo,
  121. out half3 MetaSpecular
  122. )
  123. {
  124. #if defined(SHADERGRAPH_PREVIEW) || ( !defined(LIGHTWEIGHT_LIGHTING_INCLUDED) && !defined(UNIVERSAL_LIGHTING_INCLUDED) )
  125. Lighting = albedo;
  126. MetaAlbedo = half3(0,0,0);
  127. MetaSpecular = half3(0,0,0);
  128. #else
  129. // Real Lighting ----------
  130. half3 tnormal = normalWS;
  131. // Normal mapping
  132. #if defined(NORMAL_ON)
  133. tnormal = TransformTangentToWorld(normalTS, half3x3(tangentWS.xyz, bitangentWS.xyz, normalWS.xyz));
  134. #endif
  135. // Not normalized normals cause uggly specular highlights on mobile. So we always normalize.
  136. #if defined(SPECULAR_ON)
  137. normalWS = normalize(tnormal);
  138. #else
  139. normalWS = NormalizeNormalPerPixel(tnormal);
  140. #endif
  141. normalWS = NormalizeNormalPerPixel(tnormal);
  142. viewDirectionWS = SafeNormalize(viewDirectionWS);
  143. // Remap values - old version
  144. //half diffuseUpper = saturate(diffuseStep + diffuseFalloff);
  145. float4 clipPos = TransformWorldToHClip(positionWS);
  146. // Get Shadow Sampling Coords / Unfortunately per pixel...
  147. #if SHADOWS_SCREEN
  148. float4 shadowCoord = ComputeScreenPos(clipPos);
  149. #else
  150. float4 shadowCoord = TransformWorldToShadowCoord(positionWS);
  151. #endif
  152. // Shadow mask
  153. #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
  154. half4 shadowMask = SAMPLE_SHADOWMASK(lightMapUV);
  155. #elif !defined (LIGHTMAP_ON)
  156. half4 shadowMask = unity_ProbesOcclusion;
  157. #else
  158. half4 shadowMask = half4(1, 1, 1, 1);
  159. #endif
  160. //Light mainLight = GetMainLight(shadowCoord);
  161. Light mainLight = GetMainLight(shadowCoord, positionWS, shadowMask);
  162. // SSAO
  163. #if defined(_SCREEN_SPACE_OCCLUSION)
  164. AmbientOcclusionFactor aoFactor;
  165. aoFactor.indirectAmbientOcclusion = 1;
  166. aoFactor.directAmbientOcclusion = 1;
  167. if(receiveSSAO) {
  168. float4 ndc = clipPos * 0.5f;
  169. float2 normalized = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
  170. normalized /= clipPos.w;
  171. normalized *= _ScreenParams.xy;
  172. // We could also use IN.Screenpos(default) --> ( IN.Screenpos.xy * _ScreenParams.xy)
  173. // HDRP 10.1
  174. normalized = GetNormalizedScreenSpaceUV(normalized);
  175. aoFactor = GetScreenSpaceAmbientOcclusion(normalized);
  176. mainLight.color *= aoFactor.directAmbientOcclusion;
  177. occlusion = min(occlusion, aoFactor.indirectAmbientOcclusion);
  178. //occlusion = smoothstep(diffuseStep, diffuseUpper, occlusion);
  179. }
  180. #endif
  181. // GI Lighting
  182. half3 bakedGI = 0;
  183. #ifdef LIGHTMAP_ON
  184. lightMapUV = lightMapUV * unity_LightmapST.xy + unity_LightmapST.zw;
  185. bakedGI = SAMPLE_GI(lightMapUV, half3(0,0,0), normalWS);
  186. #else
  187. UNITY_BRANCH if(occlusion > 0) {
  188. bakedGI = SampleSH(normalWS) * occlusion;
  189. }
  190. #endif
  191. //mainLight.shadowAttenuation = smoothstep(0.0h, shadowFalloff, mainLight.shadowAttenuation);
  192. mainLight.shadowAttenuation = smoothstep( (1 - shadowFalloff) * shadowFalloff, shadowFalloff, mainLight.shadowAttenuation);
  193. MixRealtimeAndBakedGI(mainLight, normalWS, bakedGI, half4(0, 0, 0, 0));
  194. // Set up Lighting
  195. half lightIntensity = 0;
  196. half3 specularLighting = 0;
  197. half3 rimLighting = 0;
  198. half3 lightColor = 0;
  199. half luminance;
  200. // Adjust tangent and reconstruct bitangent in case anisotropic specular is active as otherwise normal mapping has no effect
  201. #if defined(ANISO_ON) && defined(SPECULAR_ON)
  202. #if defined(NORMAL_ON)
  203. tangentWS = Orthonormalize(tangentWS, normalWS);
  204. #endif
  205. bitangentWS = cross(normalWS, tangentWS);
  206. #endif
  207. // Main Light
  208. // Old version
  209. //half NdotL = saturate(dot(normalWS, mainLight.direction));
  210. //NdotL = smoothstep(diffuseStep, diffuseUpper, NdotL);
  211. // New version which lets you use wrapped around diffuse lighting and shift away shadowed areas if gradient are disabled
  212. //
  213. // Remap old diffuseStep and diffuseFalloff in order to match new function
  214. diffuseStep = diffuseStep + 1.0h;
  215. diffuseFalloff = diffuseFalloff * 4.0h + 1.0h;
  216. half NdotL = dot(normalWS, mainLight.direction);
  217. NdotL = saturate((NdotL + 1.0h) - diffuseStep);
  218. #if !defined(GRADIENT_ON)
  219. // We have to use steps - 1 here!
  220. half oneOverSteps = 1.0h / steps;
  221. half quantizedNdotL = floor(NdotL * steps);
  222. // IMPORTANT: no saturate on the 2nd param: NdotL - 0.01. 0.01 is eyballed.
  223. NdotL = (quantizedNdotL + aaStep(saturate(quantizedNdotL * oneOverSteps), NdotL - 0.01h, diffuseFalloff )) * oneOverSteps;
  224. #else
  225. #if defined(SMOOTHGRADIENT_ON)
  226. NdotL = SAMPLE_TEXTURE2D(GradientMap, sampler_Linear, float2 (NdotL, 0.5f)).r;
  227. #else
  228. float oneOverTexelWidth = rcp(GradientWidth);
  229. half NdotL0 = SAMPLE_TEXTURE2D(GradientMap, sampler_Point, float2 (NdotL, 0.5f)).r ;
  230. half NdotL1 = SAMPLE_TEXTURE2D(GradientMap, sampler_Point, float2 (NdotL + fwidth(NdotL) * oneOverTexelWidth, 0.5f)).r;
  231. NdotL = (NdotL0 + NdotL1) * 0.5h;
  232. #endif
  233. #endif
  234. half atten = NdotL * mainLight.distanceAttenuation * saturate(shadowBiasDirectional + mainLight.shadowAttenuation);
  235. mainLight.color = lerp(Luminance(mainLight.color).xxx, mainLight.color, lightColorContribution.xxx);
  236. // if (colorizeMainLight) {
  237. // lightColor = mainLight.color * mainLight.distanceAttenuation;
  238. // }
  239. // else {
  240. // lightColor = mainLight.color * atten;
  241. // }
  242. lightColor = mainLight.color * lerp(atten, mainLight.distanceAttenuation, colorizeMainLight);
  243. luminance = Luminance(mainLight.color);
  244. lightIntensity += luminance * atten;
  245. // Specular
  246. half specularSmoothness;
  247. half3 spec;
  248. half specularUpper;
  249. #if defined(SPECULAR_ON)
  250. specularSmoothness = exp2(10 * smoothness + 1);
  251. specularUpper = saturate(specularStep + specularFalloff * (1.0h + smoothness));
  252. #if defined(ANISO_ON)
  253. spec = LightingSpecularAniso_Toon (mainLight, NdotL, normalWS, viewDirectionWS, tangentWS, bitangentWS, anisotropy, specular, specularSmoothness, smoothness, specularStep, specularUpper, energyConservation);
  254. #else
  255. spec = LightingSpecular_Toon(mainLight, NdotL, normalWS, viewDirectionWS, specular, specularSmoothness, smoothness, specularStep, specularUpper, energyConservation);
  256. #endif
  257. specularLighting = spec * atten;
  258. #endif
  259. // Rim Lighting
  260. #if defined(RIM_ON)
  261. half rim = saturate(1.0h - saturate( dot(normalWS, viewDirectionWS)) );
  262. //rimLighting = smoothstep(rimPower, rimPower + rimFalloff, rim) * rimColor.rgb;
  263. // Stabilize rim
  264. float delta = fwidth(rim);
  265. rimLighting = smoothstep(rimPower - delta, rimPower + rimFalloff + delta, rim) * rimColor.rgb;
  266. #endif
  267. // Handle additional lights
  268. #ifdef _ADDITIONAL_LIGHTS
  269. uint pixelLightCount = GetAdditionalLightsCount();
  270. for (uint i = 0u; i < pixelLightCount; ++i) {
  271. Light light = GetAdditionalLight(i, positionWS);
  272. #if defined(_SCREEN_SPACE_OCCLUSION)
  273. if(receiveSSAO) {
  274. light.color *= aoFactor.directAmbientOcclusion;
  275. }
  276. #endif
  277. light.shadowAttenuation = smoothstep(0.0h, shadowFalloff, light.shadowAttenuation);
  278. NdotL = dot(normalWS, light.direction);
  279. NdotL = saturate((NdotL + 1.0h) - diffuseStep);
  280. #if !defined(GRADIENT_ON)
  281. half quantizedNdotL = floor(NdotL * steps);
  282. // IMPORTANT: no saturate on the 2nd param: NdotL - 0.01. 0.01 is eyballed.
  283. NdotL = (quantizedNdotL + aaStep(saturate(quantizedNdotL * oneOverSteps), NdotL - 0.01h, diffuseFalloff )) * oneOverSteps;
  284. #else
  285. #if defined(SMOOTHGRADIENT_ON)
  286. NdotL = SAMPLE_TEXTURE2D(GradientMap, sampler_Linear, float2 (NdotL, 0.5f)).r;
  287. #else
  288. NdotL0 = SAMPLE_TEXTURE2D(GradientMap, sampler_Point, float2 (NdotL, 0.5f)).r;
  289. NdotL1 = SAMPLE_TEXTURE2D(GradientMap, sampler_Point, float2 (NdotL + fwidth(NdotL) * oneOverTexelWidth, 0.5f)).r;
  290. NdotL = (NdotL0 + NdotL1) * 0.5h;
  291. #endif
  292. #endif
  293. half distanceAttenuation = (addLightFalloff < 1.0h) ? saturate(light.distanceAttenuation / addLightFalloff) : light.distanceAttenuation;
  294. atten = NdotL * distanceAttenuation * saturate(shadowBiasAdditional + light.shadowAttenuation);
  295. light.color = lerp(Luminance(light.color).xxx, light.color, lightColorContribution.xxx);
  296. // if(colorizeAddLights) {
  297. // lightColor += light.color * light.distanceAttenuation;
  298. // }
  299. // else {
  300. // lightColor += light.color * atten;
  301. // }
  302. lightColor += light.color * lerp(atten, distanceAttenuation, colorizeAddLights);
  303. luminance = Luminance(light.color);
  304. lightIntensity += luminance * atten;
  305. //if (enableSpecular) {
  306. #if defined(SPECULAR_ON)
  307. #if defined(ANISO_ON)
  308. spec = LightingSpecularAniso_Toon (light, NdotL, normalWS, viewDirectionWS, tangentWS, bitangentWS, anisotropy, specular, specularSmoothness, smoothness, specularStep, specularUpper, energyConservation);
  309. #else
  310. spec = LightingSpecular_Toon(light, NdotL, normalWS, viewDirectionWS, specular, specularSmoothness, smoothness, specularStep, specularUpper, energyConservation);
  311. #endif
  312. specularLighting += spec * atten;
  313. #endif
  314. //}
  315. }
  316. #endif
  317. // Combine Lighting
  318. half3 litAlbedo = lerp(shadedAlbedo, albedo, saturate(lightIntensity.xxx));
  319. Lighting =
  320. // ambient diffuse lighting
  321. bakedGI * albedo
  322. // direct diffuse lighting
  323. + ( litAlbedo
  324. // spec and rim lighting
  325. #if defined(SPECULAR_ON)
  326. + specularLighting * lightIntensity
  327. #endif
  328. #if defined(RIM_ON)
  329. + rimLighting * lerp(1.0h, lightIntensity, rimAttenuation)
  330. #endif
  331. ) * lightColor
  332. ;
  333. // Set Albedo for meta pass
  334. #if defined(LIGHTWEIGHT_META_PASS_INCLUDED) || defined(UNIVERSAL_META_PASS_INCLUDED)
  335. Lighting = half3(0,0,0);
  336. MetaAlbedo = albedo;
  337. MetaSpecular = half3(0.02,0.02,0.02);
  338. #else
  339. MetaAlbedo = half3(0,0,0);
  340. MetaSpecular = half3(0,0,0);
  341. #endif
  342. // End Real Lighting ----------
  343. #endif
  344. }
  345. // Unity 2019.1. needs a float version
  346. void Lighting_float(
  347. // Base inputs
  348. float3 positionWS,
  349. half3 viewDirectionWS,
  350. // Normal inputs
  351. half3 normalWS,
  352. half3 tangentWS,
  353. half3 bitangentWS,
  354. half3 normalTS,
  355. // Surface description
  356. half3 albedo,
  357. half3 shadedAlbedo,
  358. half anisotropy,
  359. bool energyConservation,
  360. half3 specular,
  361. half smoothness,
  362. half occlusion,
  363. // Smoothsteps
  364. half steps,
  365. half diffuseStep,
  366. half diffuseFalloff,
  367. half specularStep,
  368. half specularFalloff,
  369. half shadowFalloff,
  370. half shadowBiasDirectional,
  371. half shadowBiasAdditional,
  372. // Colorize shaded parts
  373. half colorizeMainLight,
  374. half colorizeAddLights,
  375. half lightColorContribution,
  376. half addLightFalloff,
  377. // Rim Lighting
  378. half rimPower,
  379. half rimFalloff,
  380. half4 rimColor,
  381. half rimAttenuation,
  382. // Lightmapping
  383. float2 lightMapUV,
  384. // Ramp
  385. Texture2D GradientMap,
  386. float GradientWidth,
  387. SamplerState sampler_Linear,
  388. SamplerState sampler_Point,
  389. bool receiveSSAO,
  390. // Final lit color
  391. out half3 Lighting,
  392. out half3 MetaAlbedo,
  393. out half3 MetaSpecular
  394. )
  395. {
  396. Lighting_half(
  397. positionWS, viewDirectionWS, normalWS, tangentWS, bitangentWS, normalTS,
  398. albedo, shadedAlbedo, anisotropy, energyConservation, specular, smoothness, occlusion,
  399. steps, diffuseStep, diffuseFalloff, specularStep, specularFalloff, shadowFalloff, shadowBiasDirectional, shadowBiasAdditional,
  400. colorizeMainLight, colorizeAddLights, lightColorContribution, addLightFalloff,
  401. rimPower, rimFalloff, rimColor, rimAttenuation,
  402. lightMapUV,
  403. GradientMap, GradientWidth, sampler_Linear, sampler_Point,
  404. receiveSSAO,
  405. Lighting, MetaAlbedo, MetaSpecular
  406. );
  407. }