123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- // NOTE: Based on URP Lighting.hlsl which replaced some half3 with floats to avoid lighting artifacts on mobile
- #ifndef UNIVERSAL_TOONLIGHTING_INCLUDED
- #define UNIVERSAL_TOONLIGHTING_INCLUDED
- #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
- #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl"
- #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl"
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
- // Toon
- TEXTURE2D(_GradientMap); float4 _GradientMap_TexelSize;
- SAMPLER(s_point_clamp_sampler);
- SAMPLER(s_linear_clamp_sampler);
- // ///////////////////////////////////////////////////////////
- //
- // Custom functions
- half3 LightingSpecular_Toon (Light light, half lightingRemap, half3 normalWS, half3 viewDirectionWS, half3 specular, half specularSmoothness, half smoothness, half specularStep, half specularUpper, bool energyConservation){
- float3 halfVec = SafeNormalize( float3(light.direction) + float3(viewDirectionWS));
- half NdotH = saturate(dot(normalWS, halfVec));
- half modifier = pow(NdotH /* lightingRemap*/, specularSmoothness);
- // Normalization? Na, we just multiply by smoothness in the return statement.
- // #define ONEOVERTWOPI 0.159155h
- // half normalization = (specularSmoothness + 1) * ONEOVERTWOPI;
- // Sharpen
- half modifierSharpened = smoothstep(specularStep, specularUpper, modifier);
- half toonNormalization = (energyConservation == 1.0h) ? smoothness : 1;
- return light.color * specular * modifierSharpened * toonNormalization; // * smoothness;
- }
- 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){
- // This does not let us fade from isotropic to anisotropic...
- // half3 H = SafeNormalize(light.direction + viewDirectionWS);
- // half3 T = cross(normalWS, tangent);
- // T = lerp(tangent, bitangent, (anisotropy + 1) * 0.5);
- // float TdotH = dot(T, H);
- // float sinTHSq = saturate(1.0 - TdotH * TdotH);
- // float exponent = RoughnessToBlinnPhongSpecularExponent_Lux(1 - smoothness);
- // float modifier = dirAttn * pow(sinTHSq, 0.5 * exponent);
- // float norm = smoothness; //(exponent + 2) * rcp(2 * PI);
- // // Sharpen
- // half modifierSharpened = smoothstep(specularStep, specularUpper, modifier);
- // half toonNormalization = (energyConservation == 1.0h) ? norm : 1;
- // return light.color * specular * modifierSharpened * toonNormalization;
- // ///////////////////////////////
- //
- // GGX "like" distribution in order to be able to fade from isotropic to anisotropic
- // We skip visbility here as it is toon lighting.
- // NOTE: Further normalization does not help here to fixe the final shape...
- float3 H = SafeNormalize(float3(light.direction) + float3(viewDirectionWS));
- // TdotH and BdotH should be unclamped here
- float TdotH = dot(tangentWS, H);
- float BdotH = dot(bitangentWS, H);
- float NdotH = dot(normalWS, H);
- float roughness = 1.0f - smoothness;
-
- // 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
- roughness *= roughness * roughness * roughness;
- float at = roughness * (1.0f + anisotropy);
- float ab = roughness * (1.0f - anisotropy);
-
- float a2 = at * ab;
- float3 v = float3(ab * TdotH, at * BdotH, a2 * NdotH);
-
- float v2 = dot(v, v);
- float w2 = a2 / v2;
- half res = half(a2 * w2 * w2 * (1.0f / PI));
- // Sharpen
- half modifierSharpened = smoothstep(specularStep, specularUpper, res);
- half toonNormalization = (energyConservation == 1.0h) ? smoothness : 1.0h;
- return light.color * specular * modifierSharpened * toonNormalization;
- }
- // https://www.ronja-tutorials.com/2019/11/29/fwidth.html
- half aaStep(half compValue, half gradient, half softness){
- half change = fwidth(gradient) * softness;
- // Base the range of the inverse lerp on the change over two pixels
- half lowerEdge = compValue - change;
- half upperEdge = compValue + change;
- // Do the inverse interpolation
- half stepped = (gradient - lowerEdge) / (upperEdge - lowerEdge);
- stepped = saturate(stepped);
- return stepped;
- }
- half4 LuxURPToonFragmentPBR(InputData inputData,
- #if defined(_ANISOTROPIC) && !defined(_SPECULARHIGHLIGHTS_OFF)
- half3 tangentWS,
- half anisotropy,
- #endif
- half3 albedo, half3 shadedAlbedo,
- half metallic, half3 specular,
- half steps, half diffuseStep, half diffuseFalloff,
- half energyConservation, half specularStep, half specularFalloff,
- half mainLightAttenContribution, half addLightAttenContribution, half lightColorContribution, half addLightFalloff,
- half shadowFalloff, half shadowBiasDirectional, half shadowBiasAdditional,
- half3 toonRimColor, half toonRimPower, half toonRimFallOff, half toonRimAttenuation,
- half smoothness, half occlusion, half3 emission, half alpha
- )
- {
- BRDFData brdfData;
- // We can't use our specular here as it can be anything. So we simply use the default dielectric value here.
- InitializeBRDFData(albedo, metallic, kDieletricSpec.rgb, smoothness, alpha, brdfData);
- // ShadowMask: To ensure backward compatibility we have to avoid using shadowMask input, as it is not present in older shaders
- #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
- half4 shadowMask = inputData.shadowMask;
- #elif !defined (LIGHTMAP_ON)
- half4 shadowMask = unity_ProbesOcclusion;
- #else
- half4 shadowMask = half4(1, 1, 1, 1);
- #endif
-
- //Light mainLight = GetMainLight(inputData.shadowCoord);
- Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, shadowMask);
- // SSAO
- #if defined(_SCREEN_SPACE_OCCLUSION)
- #if defined(_SSAO_ENABLED)
- AmbientOcclusionFactor aoFactor = GetScreenSpaceAmbientOcclusion(inputData.normalizedScreenSpaceUV);
- mainLight.color *= aoFactor.directAmbientOcclusion;
- occlusion = min(occlusion, aoFactor.indirectAmbientOcclusion);
- #endif
- #endif
-
- mainLight.shadowAttenuation = smoothstep( (1 - shadowFalloff) * shadowFalloff, shadowFalloff, mainLight.shadowAttenuation);
- MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));
- // We really do not want any reflections
- #if defined(_ENVIRONMENTREFLECTIONS_OFF)
- _GlossyEnvironmentColor.rgb = half3(0,0,0);
- #endif
- // Global Illumination
- half3 GI = GlobalIllumination(brdfData, inputData.bakedGI, occlusion, inputData.normalWS, inputData.viewDirectionWS);
- // Set up Lighting
- half lightIntensity = 0.0h;
- half3 specularLighting = 0.0h;
- half3 rimLighting = 0.0h;
- half3 lightColor = 0.0h;
- half luminance;
- // Adjust tangent and reconstruct bitangent in case anisotropic specular is active as otherwise normal mapping has no effect
- #if defined(_ANISOTROPIC) && !defined(_SPECULARHIGHLIGHTS_OFF)
- #if defined(_NORMALMAP)
- tangentWS = Orthonormalize(tangentWS, inputData.normalWS);
- #endif
- half3 bitangentWS = cross(inputData.normalWS, tangentWS);
- #endif
- // Main Light
- // Remap old diffuseStep and diffuseFalloff in order to match new function
- diffuseStep = diffuseStep + 1.0h;
- diffuseFalloff = diffuseFalloff * 4.0h + 1.0h;
- half NdotL = dot(inputData.normalWS, mainLight.direction);
- NdotL = saturate((NdotL + 1.0h) - diffuseStep);
- #if !defined(_RAMP_SMOOTHSAMPLING) && !defined(_RAMP_POINTSAMPLING)
- // We have to use steps - 1 here!
- half oneOverSteps = 1.0h / steps;
- half quantizedNdotL = floor(NdotL * steps);
- // IMPORTANT: no saturate on the 2nd param: NdotL - 0.01. 0.01 is eyballed.
- NdotL = (quantizedNdotL + aaStep(saturate(quantizedNdotL * oneOverSteps), NdotL - 0.01h, diffuseFalloff )) * oneOverSteps;
- #else
- #if defined(_RAMP_SMOOTHSAMPLING)
- NdotL = SAMPLE_TEXTURE2D(_GradientMap, s_linear_clamp_sampler, float2 (NdotL, 0.5f)).r;
- #else
- half NdotL0 = SAMPLE_TEXTURE2D(_GradientMap, s_point_clamp_sampler, float2 (NdotL, 0.5f)).r;
- half NdotL1 = SAMPLE_TEXTURE2D(_GradientMap, s_point_clamp_sampler, float2 (NdotL + fwidth(NdotL) * _GradientMap_TexelSize.x, 0.5f)).r;
- NdotL = (NdotL0 + NdotL1) * 0.5h;
- #endif
- #endif
- half atten = NdotL * mainLight.distanceAttenuation * saturate(shadowBiasDirectional + mainLight.shadowAttenuation);
- mainLight.color = lerp(Luminance(mainLight.color).xxx, mainLight.color, lightColorContribution.xxx);
- // #if defined(_COLORIZEMAIN)
- // lightColor = mainLight.color * mainLight.distanceAttenuation;
- // #else
- // lightColor = mainLight.color * atten;
- // #endif
- lightColor = mainLight.color * lerp(atten, mainLight.distanceAttenuation, mainLightAttenContribution);
- luminance = Luminance(mainLight.color);
- lightIntensity += luminance * atten;
- // Specular
- #if !defined(_SPECULARHIGHLIGHTS_OFF)
- half specularSmoothness;
- half3 spec;
- half specularUpper;
- specularSmoothness = exp2(10 * smoothness + 1);
- specularUpper = saturate(specularStep + specularFalloff * (1.0h + smoothness));
- #if defined(_ANISOTROPIC)
- spec = LightingSpecularAniso_Toon (mainLight, NdotL, inputData.normalWS, inputData.viewDirectionWS, tangentWS, bitangentWS, anisotropy, specular, specularSmoothness, smoothness, specularStep, specularUpper, energyConservation);
- #else
- spec = LightingSpecular_Toon(mainLight, NdotL, inputData.normalWS, inputData.viewDirectionWS, specular, specularSmoothness, smoothness, specularStep, specularUpper, energyConservation);
- #endif
- specularLighting = spec * atten;
- #endif
- // Rim
- #if defined(_TOONRIM)
- half rim = saturate(1.0h - saturate( dot(inputData.normalWS, inputData.viewDirectionWS)) );
- //rimLighting = smoothstep(rimPower, rimPower + rimFalloff, rim) * rimColor.rgb;
- // Stabilize rim
- float delta = fwidth(rim);
- rimLighting = smoothstep(toonRimPower - delta, toonRimPower + toonRimFallOff + delta, rim) * toonRimColor.rgb;
- #endif
- // Additional lights
- #ifdef _ADDITIONAL_LIGHTS
- uint pixelLightCount = GetAdditionalLightsCount();
- for (uint i = 0u; i < pixelLightCount; ++i) {
- Light light = GetAdditionalLight(i, inputData.positionWS);
- #if defined(_SCREEN_SPACE_OCCLUSION)
- #if defined(_SSAO_ENABLED)
- light.color *= aoFactor.directAmbientOcclusion;
- #endif
- #endif
- //light.shadowAttenuation = smoothstep(0.0h, shadowFalloff, light.shadowAttenuation);
- light.shadowAttenuation = smoothstep( (1.0h - shadowFalloff) * shadowFalloff, shadowFalloff, light.shadowAttenuation);
-
- NdotL = dot(inputData.normalWS, light.direction);
- NdotL = saturate((NdotL + 1.0h) - diffuseStep);
- #if !defined(_RAMP_SMOOTHSAMPLING) && !defined(_RAMP_POINTSAMPLING)
- half quantizedNdotL = floor(NdotL * steps);
- // IMPORTANT: no saturate on the 2nd param: NdotL - 0.01. 0.01 is eyballed.
- NdotL = (quantizedNdotL + aaStep(saturate(quantizedNdotL * oneOverSteps), NdotL - 0.01h, diffuseFalloff )) * oneOverSteps;
- #else
- #if defined(_RAMP_SMOOTHSAMPLING)
- NdotL = SAMPLE_TEXTURE2D(_GradientMap, s_linear_clamp_sampler, float2 (NdotL, 0.5f)).r;
- #else
- half NdotL0 = SAMPLE_TEXTURE2D(_GradientMap, s_point_clamp_sampler, float2 (NdotL, 0.5f)).r;
- half NdotL1 = SAMPLE_TEXTURE2D(_GradientMap, s_point_clamp_sampler, float2 (NdotL + fwidth(NdotL) * _GradientMap_TexelSize.x, 0.5f)).r;
- NdotL = (NdotL0 + NdotL1) * 0.5h;
- #endif
- #endif
- // No smoothstep here! as is totally fucks up the distanceAttenuation: It is not linear!
- //half distanceAttenuation = smoothstep(0, addLightFalloff, light.distanceAttenuation);
- half distanceAttenuation = (addLightFalloff < 1.0h) ? saturate(light.distanceAttenuation / addLightFalloff) : light.distanceAttenuation;
- atten = NdotL * distanceAttenuation * saturate(shadowBiasAdditional + light.shadowAttenuation);
- light.color = lerp(Luminance(light.color).xxx, light.color, lightColorContribution.xxx);
- // #if defined(_COLORIZEADD)
- // lightColor += light.color * light.distanceAttenuation;
- // #else
- // lightColor += light.color * atten;
- // #endif
- lightColor += light.color * lerp(atten, distanceAttenuation, addLightAttenContribution);
- luminance = Luminance(light.color);
- lightIntensity += luminance * atten;
- #if !defined(_SPECULARHIGHLIGHTS_OFF)
- #if defined(_ANISOTROPIC)
- spec = LightingSpecularAniso_Toon (light, NdotL, inputData.normalWS, inputData.viewDirectionWS, tangentWS, bitangentWS, anisotropy, specular, specularSmoothness, smoothness, specularStep, specularUpper, energyConservation);
- #else
- spec = LightingSpecular_Toon(light, NdotL, inputData.normalWS, inputData.viewDirectionWS, specular, specularSmoothness, smoothness, specularStep, specularUpper, energyConservation);
- #endif
- specularLighting += spec * atten;
- #endif
- }
- #endif
- // Combine Lighting
- half3 litAlbedo = lerp(shadedAlbedo, albedo, saturate(lightIntensity.xxx) );
- //lightColor = 1;
- half3 Lighting =
- // ambient diffuse lighting
- GI
- //inputData.bakedGI * albedo //litAlbedo
- // direct diffuse lighting
- + litAlbedo * lightColor
- // spec lighting
- #if !defined(_SPECULARHIGHLIGHTS_OFF)
- + (specularLighting * lightIntensity * lightColor)
- #endif
- // rim lighting
- #if defined(_TOONRIM)
- + rimLighting * lerp(1.0h, lightIntensity, toonRimAttenuation)
- #endif
- // old version multiplied rim with lightColor ...
- //#if !defined(_SPECULARHIGHLIGHTS_OFF)
- // )
- //#endif
- // * lightColor
- ;
- #ifdef _ADDITIONAL_LIGHTS_VERTEX
- Lighting += inputData.vertexLighting * albedo;
- #endif
- Lighting += emission;
- return half4(Lighting, alpha);
- }
- #endif
|