123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- #if !defined(SHADERGRAPH_PREVIEW) || defined(LIGHTWEIGHT_LIGHTING_INCLUDED)
- // As we do not have access to the vertex lights we will make the shader always sample add lights per pixel
- #if defined(_ADDITIONAL_LIGHTS_VERTEX)
- #undef _ADDITIONAL_LIGHTS_VERTEX
- #define _ADDITIONAL_LIGHTS
- #endif
- #if defined(LIGHTWEIGHT_LIGHTING_INCLUDED) || defined(UNIVERSAL_LIGHTING_INCLUDED)
- struct AdditionalData {
- half coatThickness;
- half3 coatSpecular;
- half3 normalWS;
- half perceptualRoughness;
- half roughness;
- half roughness2;
- half normalizationTerm;
- half roughness2MinusOne; // roughness² - 1.0
- half reflectivity;
- half grazingTerm;
- half specOcclusion;
- bool enableSecondaryLobe;
- };
- half3 DirectBDRF_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS, half NdotL)
- {
- #ifndef _SPECULARHIGHLIGHTS_OFF
-
- float3 halfDir = SafeNormalize(lightDirectionWS + viewDirectionWS);
- half LoH = saturate(dot(lightDirectionWS, halfDir));
- // Base Lobe
- float NoH = saturate(dot(normalWS, halfDir));
- float d = NoH * NoH * brdfData.roughness2MinusOne + 1.00001f;
- half LoH2 = LoH * LoH;
- LoH2 = max(0.1h, LoH2); // as we can reuse it
- half specularTerm = brdfData.roughness2 / ((d * d) * LoH2 /* max(0.1h, LoH2) */ * brdfData.normalizationTerm);
- #if defined (SHADER_API_MOBILE) || defined (SHADER_API_SWITCH)
- specularTerm = specularTerm - HALF_MIN;
- specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
- #endif
- half3 spec = specularTerm * brdfData.specular * NdotL;
- // Coat Lobe
- // From HDRP: Scale base specular
- //#if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
- // [branch]
- // if (addData.coatThickness > 0.0h) {
- //#endif
- half coatF = F_Schlick(addData.reflectivity /*addData.coatSpecular*/ /*CLEAR_COAT_F0*/, LoH) * addData.coatThickness;
- spec *= Sq(1.0h - coatF);
- //spec *= (1.0h - coatF); // as used by filament, na, not really
- NoH = saturate(dot(addData.normalWS, halfDir));
- d = NoH * NoH * addData.roughness2MinusOne + 1.00001f;
- //LoH2 = LoH * LoH; no need to recalculate LoH2!
- specularTerm = addData.roughness2 / ((d * d) * LoH2 /* max(0.1h, LoH2) */ * addData.normalizationTerm);
- #if defined (SHADER_API_MOBILE) || defined (SHADER_API_SWITCH)
- specularTerm = specularTerm - HALF_MIN;
- specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
- #endif
- spec += specularTerm * addData.coatSpecular * saturate(dot(addData.normalWS, lightDirectionWS));
- //#if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
- // }
- //#endif
- half3 color = spec + brdfData.diffuse * NdotL; // * lerp(1.0h, 1.0h - coatF, addData.coatThickness);
- return color;
- #else
- return brdfData.diffuse * NdotL;
- #endif
- }
- half3 LightingPhysicallyBased_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS)
- {
- half NdotL = saturate(dot(normalWS, lightDirectionWS));
- half3 radiance = lightColor * (lightAttenuation); // * NdotL);
- return DirectBDRF_LuxClearCoat(brdfData, addData, normalWS, lightDirectionWS, viewDirectionWS, NdotL) * radiance;
- }
- half3 LightingPhysicallyBased_LuxClearCoat(BRDFData brdfData, AdditionalData addData, Light light, half3 normalWS, half3 viewDirectionWS)
- {
- return LightingPhysicallyBased_LuxClearCoat(brdfData, addData, light.color, light.direction, light.distanceAttenuation * light.shadowAttenuation, normalWS, viewDirectionWS);
- }
- half3 EnvironmentBRDF_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 indirectDiffuse, half3 indirectSpecular, half fresnelTerm)
- {
- half3 c = indirectDiffuse * brdfData.diffuse;
- float surfaceReduction = 1.0 / (addData.roughness2 + 1.0);
- c += surfaceReduction * indirectSpecular * lerp(addData.coatSpecular, addData.grazingTerm, fresnelTerm);
- return c;
- }
- half3 GlobalIllumination_LuxClearCoat(BRDFData brdfData, AdditionalData addData, half3 bakedGI, half occlusion, half3 normalWS, half3 baseNormalWS, half3 viewDirectionWS, half NdotV)
- {
- half3 reflectVector = reflect(-viewDirectionWS, normalWS);
- half fresnelTerm = Pow4(1.0 - NdotV);
- half3 indirectDiffuse = bakedGI * occlusion;
- half3 indirectSpecular = GlossyEnvironmentReflection(reflectVector, addData.perceptualRoughness, addData.specOcclusion);
- half3 res = EnvironmentBRDF_LuxClearCoat(brdfData, addData, indirectDiffuse, indirectSpecular, fresnelTerm);
- //#if defined(_SECONDARYLOBE)
- if (addData.enableSecondaryLobe) {
- #if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
- [branch]
- if (addData.coatThickness > 0.0h) {
- #endif
- reflectVector = reflect(-viewDirectionWS, baseNormalWS);
- indirectSpecular = GlossyEnvironmentReflection(reflectVector, brdfData.perceptualRoughness, 1);
- float surfaceReduction = 1.0 / (brdfData.roughness2 + 1.0);
- res += NdotV * surfaceReduction * indirectSpecular * lerp(brdfData.specular, brdfData.grazingTerm, fresnelTerm);
- #if defined (_MASKMAP) && defined(_STANDARDLIGHTING)
- }
- #endif
- //#endif
- }
- return res;
- }
- half3 f0ClearCoatToSurface_Lux(half3 f0)
- {
- // Approximation of iorTof0(f0ToIor(f0), 1.5)
- // This assumes that the clear coat layer has an IOR of 1.5
- #if defined(SHADER_API_MOBILE)
- return saturate(f0 * (f0 * 0.526868h + 0.529324h) - 0.0482256h);
- #else
- return saturate(f0 * (f0 * (0.941892h - 0.263008h * f0) + 0.346479h) - 0.0285998h);
- #endif
- }
- #endif
- #endif
- void Lighting_half(
- // Base inputs
- float3 positionWS,
- half3 viewDirectionWS,
- // Normal inputs
- half3 normalWS,
- half3 tangentWS,
- half3 bitangentWS,
- bool enableNormalMapping,
- half3 normalTS,
- // Surface description
- half3 albedo, // albedo is baseColor
- half metallic,
- half3 specular,
- half smoothness,
- half occlusion,
- half alpha,
- // Lighting specific inputs
- half clearcoatSmoothness,
- half clearcoatThickness,
- half3 clearcoatSpecular,
-
- half3 secondaryColor,
- bool enableSecondaryColor,
- bool enableSecondaryLobe,
- // Lightmapping
- float2 lightMapUV,
- // Final lit color
- out half3 MetaAlbedo,
- out half3 FinalLighting,
- out half3 MetaSpecular
- )
- {
- //#ifdef SHADERGRAPH_PREVIEW
- #if defined(SHADERGRAPH_PREVIEW) || ( !defined(LIGHTWEIGHT_LIGHTING_INCLUDED) && !defined(UNIVERSAL_LIGHTING_INCLUDED) )
- FinalLighting = albedo;
- MetaAlbedo = half3(0,0,0);
- MetaSpecular = half3(0,0,0);
- #else
- // Real Lighting ----------
- // Cache the geometry normal used by the coat
- half3 vertexNormalWS = NormalizeNormalPerPixel(normalWS);
- if (enableNormalMapping) {
- normalWS = TransformTangentToWorld(normalTS, half3x3(tangentWS.xyz, bitangentWS.xyz, normalWS.xyz));
- }
- normalWS = NormalizeNormalPerPixel(normalWS);
- viewDirectionWS = SafeNormalize(viewDirectionWS);
- // GI Lighting
- half3 bakedGI;
- #ifdef LIGHTMAP_ON
- lightMapUV = lightMapUV * unity_LightmapST.xy + unity_LightmapST.zw;
- bakedGI = SAMPLE_GI(lightMapUV, half3(0,0,0), normalWS);
- #else
- bakedGI = SampleSH(normalWS);
- #endif
- // Clear Coat Lighting
-
- half NdotV = saturate( dot(vertexNormalWS, viewDirectionWS) );
- #if !defined(LIGHTWEIGHT_META_PASS_INCLUDED) && !defined(UNIVERSAL_META_PASS_INCLUDED)
- if(enableSecondaryColor) {
- albedo = lerp(secondaryColor, albedo, NdotV);
- }
- #endif
- BRDFData brdfData;
- InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
- // Adjust specular as we have a transition from coat to material and not air to material
- brdfData.specular = lerp(brdfData.specular, f0ClearCoatToSurface_Lux(brdfData.specular), clearcoatThickness);
- AdditionalData addData;
- addData.coatThickness = clearcoatThickness;
- addData.coatSpecular = clearcoatSpecular;
- addData.normalWS = vertexNormalWS;
- addData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(clearcoatSmoothness);
- addData.roughness = PerceptualRoughnessToRoughness(addData.perceptualRoughness);
- addData.roughness2 = addData.roughness * addData.roughness;
- addData.normalizationTerm = addData.roughness * 4.0h + 2.0h;
- addData.roughness2MinusOne = addData.roughness2 - 1.0h;
- addData.reflectivity = ReflectivitySpecular(clearcoatSpecular);
- addData.grazingTerm = saturate(clearcoatSmoothness + addData.reflectivity);
- addData.specOcclusion = 1;
- addData.enableSecondaryLobe = enableSecondaryLobe;
- float4 clipPos = TransformWorldToHClip(positionWS);
- // Get Shadow Sampling Coords / Unfortunately per pixel...
- #if SHADOWS_SCREEN
- float4 shadowCoord = ComputeScreenPos(clipPos);
- #else
- float4 shadowCoord = TransformWorldToShadowCoord(positionWS);
- #endif
- // Shadow mask
- #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
- half4 shadowMask = SAMPLE_SHADOWMASK(lightMapUV);
- #elif !defined (LIGHTMAP_ON)
- half4 shadowMask = unity_ProbesOcclusion;
- #else
- half4 shadowMask = half4(1, 1, 1, 1);
- #endif
- //Light mainLight = GetMainLight(shadowCoord);
- Light mainLight = GetMainLight(shadowCoord, positionWS, shadowMask);
- // SSAO
- #if defined(_SCREEN_SPACE_OCCLUSION)
- float4 ndc = clipPos * 0.5f;
- float2 normalized = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
- normalized /= clipPos.w;
- normalized *= _ScreenParams.xy;
- // We could also use IN.Screenpos(default) --> ( IN.Screenpos.xy * _ScreenParams.xy)
- // HDRP 10.1
- normalized = GetNormalizedScreenSpaceUV(normalized);
- AmbientOcclusionFactor aoFactor = GetScreenSpaceAmbientOcclusion(normalized);
- mainLight.color *= aoFactor.directAmbientOcclusion;
- occlusion = min(occlusion, aoFactor.indirectAmbientOcclusion);
- #endif
-
- MixRealtimeAndBakedGI(mainLight, normalWS, bakedGI, half4(0, 0, 0, 0));
- // Approximation of refraction on BRDF
- half refractionScale = ((NdotV * 0.5 + 0.5) * NdotV - 1.0) * saturate(1.25 - 1.25 * (1.0 - clearcoatSmoothness)) + 1;
- brdfData.diffuse = lerp(brdfData.diffuse, brdfData.diffuse * refractionScale, clearcoatThickness);
- // GI
- FinalLighting = GlobalIllumination_LuxClearCoat(brdfData, addData, bakedGI, occlusion, addData.normalWS, normalWS, viewDirectionWS, NdotV);
- // Main Light
- FinalLighting += LightingPhysicallyBased_LuxClearCoat(brdfData, addData, mainLight, normalWS, viewDirectionWS);
- // Handle additional lights
- #ifdef _ADDITIONAL_LIGHTS
- uint pixelLightCount = GetAdditionalLightsCount();
- for (uint i = 0u; i < pixelLightCount; ++i) {
- // Light light = GetAdditionalPerObjectLight(index, positionWS); // here; shadowAttenuation = 1.0;
- // URP 10: We have to use the new GetAdditionalLight function
- Light light = GetAdditionalLight(i, positionWS, shadowMask);
- #if defined(_SCREEN_SPACE_OCCLUSION)
- light.color *= aoFactor.directAmbientOcclusion;
- #endif
- FinalLighting += LightingPhysicallyBased_LuxClearCoat(brdfData, addData, light, normalWS, viewDirectionWS);
- }
- #endif
- // Set Albedo for meta pass
- #if defined(LIGHTWEIGHT_META_PASS_INCLUDED) || defined(UNIVERSAL_META_PASS_INCLUDED)
- FinalLighting = half3(0,0,0);
- MetaAlbedo = albedo;
- MetaSpecular = specular;
- #else
- MetaAlbedo = half3(0,0,0);
- MetaSpecular = half3(0,0,0);
- #endif
- // End Real Lighting ----------
- #endif
- }
- // Unity 2019.1. needs a float version
- void Lighting_float(
- // Base inputs
- float3 positionWS,
- half3 viewDirectionWS,
- // Normal inputs
- half3 normalWS,
- half3 tangentWS,
- half3 bitangentWS,
- bool enableNormalMapping,
- half3 normalTS,
- // Surface description
- half3 albedo,
- half metallic,
- half3 specular,
- half smoothness,
- half occlusion,
- half alpha,
- // Lighting specific inputs
- half clearcoatSmoothness,
- half clearcoatThickness,
- half3 clearcoatSpecular,
- half3 secondaryColor,
- bool enableSecondaryColor,
- bool enableSecondaryLobe,
- // Lightmapping
- float2 lightMapUV,
- // Final lit color
- out half3 MetaAlbedo,
- out half3 FinalLighting,
- out half3 MetaSpecular
- )
- {
- Lighting_half(
- positionWS, viewDirectionWS, normalWS, tangentWS, bitangentWS, enableNormalMapping, normalTS,
- albedo, metallic, specular, smoothness, occlusion, alpha,
- clearcoatSmoothness, clearcoatThickness, clearcoatSpecular, secondaryColor, enableSecondaryColor, enableSecondaryLobe,
- lightMapUV, MetaAlbedo, FinalLighting, MetaSpecular);
- }
|