157 lines
6.3 KiB
HLSL
157 lines
6.3 KiB
HLSL
// NOTE: Based on URP Lighting.hlsl which replaced some half3 with floats to avoid lighting artifacts on mobile
|
|
|
|
#ifndef LIGHTWEIGHT_FUZZLIGHTING_INCLUDED
|
|
#define LIGHTWEIGHT_FUZZHLIGHTING_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"
|
|
|
|
real Fuzz(real NdotV, real fuzzPower, real fuzzBias)
|
|
{
|
|
return exp2( (1.0h - NdotV) * fuzzPower - fuzzPower) + fuzzBias;
|
|
}
|
|
|
|
real WrappedDiffuse(real NdotL, real3 normalWS, real3 lightDirectionWS, real wrap)
|
|
{
|
|
return saturate( (dot(normalWS, lightDirectionWS) + wrap) * rcp( (1.0h + wrap) * (1.0h + wrap) ) );
|
|
}
|
|
|
|
// ---------
|
|
|
|
struct AdditionalData {
|
|
half fuzzWrap;
|
|
half fuzz;
|
|
};
|
|
|
|
half3 DirectBDRF_LuxFuzz(BRDFData brdfData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS, half NdotL)
|
|
{
|
|
// Regular Code
|
|
#ifndef _SPECULARHIGHLIGHTS_OFF
|
|
float3 halfDir = SafeNormalize(lightDirectionWS + viewDirectionWS);
|
|
|
|
float NoH = saturate(dot(normalWS, halfDir));
|
|
half LoH = saturate(dot(lightDirectionWS, halfDir));
|
|
|
|
// Standard specular lighting
|
|
float d = NoH * NoH * brdfData.roughness2MinusOne + 1.00001f;
|
|
half LoH2 = LoH * LoH;
|
|
half specularTerm = brdfData.roughness2 / ((d * d) * 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
|
|
|
|
return specularTerm * brdfData.specular + brdfData.diffuse;
|
|
#else
|
|
return brdfData.diffuse;
|
|
#endif
|
|
}
|
|
|
|
half3 LightingPhysicallyBased_LuxFuzz(BRDFData brdfData,
|
|
#if defined(_SIMPLEFUZZ)
|
|
AdditionalData addData,
|
|
#endif
|
|
half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS, half NdotL)
|
|
{
|
|
half3 radiance = lightColor * (lightAttenuation * NdotL);
|
|
#if defined(_SIMPLEFUZZ)
|
|
half wrappedNdotL = WrappedDiffuse(NdotL, normalWS, lightDirectionWS, addData.fuzzWrap);
|
|
#endif
|
|
|
|
return DirectBDRF_LuxFuzz(brdfData, normalWS, lightDirectionWS, viewDirectionWS, NdotL) * radiance
|
|
#if defined(_SIMPLEFUZZ)
|
|
+ (addData.fuzz * brdfData.diffuse) * lightColor * (lightAttenuation * wrappedNdotL )
|
|
#endif
|
|
;
|
|
}
|
|
|
|
half3 LightingPhysicallyBased_LuxFuzz(BRDFData brdfData,
|
|
#if defined(_SIMPLEFUZZ)
|
|
AdditionalData addData,
|
|
#endif
|
|
Light light, half3 normalWS, half3 viewDirectionWS, half NdotL)
|
|
{
|
|
return LightingPhysicallyBased_LuxFuzz(brdfData,
|
|
#if defined(_SIMPLEFUZZ)
|
|
addData,
|
|
#endif
|
|
light.color, light.direction, light.distanceAttenuation * light.shadowAttenuation, normalWS, viewDirectionWS, NdotL);
|
|
}
|
|
|
|
|
|
|
|
half4 LuxURPSimpleFuzzFragmentPBR(InputData inputData, half3 albedo, half metallic, half3 specular,
|
|
half smoothness, half occlusion, half3 emission, half alpha, half4 translucency, half fuzzMask, half fuzzPower, half fuzzBias, half fuzzWrap, half fuzzStrength, half fuzzAmbient)
|
|
{
|
|
|
|
BRDFData brdfData;
|
|
InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
|
|
|
|
Light mainLight = GetMainLight(inputData.shadowCoord);
|
|
MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));
|
|
|
|
half NdotL = saturate(dot(inputData.normalWS, mainLight.direction ));
|
|
|
|
#if defined(_SIMPLEFUZZ)
|
|
AdditionalData addData;
|
|
addData.fuzzWrap = fuzzWrap;
|
|
// We tweak the diffuse to get some ambient fuzz lighting as well.
|
|
half NdotV = saturate(dot(inputData.normalWS, inputData.viewDirectionWS ));
|
|
addData.fuzz = Fuzz(NdotV, fuzzPower, fuzzBias);
|
|
addData.fuzz *= fuzzMask * fuzzStrength;
|
|
half3 diffuse = brdfData.diffuse;
|
|
brdfData.diffuse *= 1.0h + addData.fuzz * fuzzAmbient;
|
|
#endif
|
|
|
|
half3 color = GlobalIllumination(brdfData, inputData.bakedGI, occlusion, inputData.normalWS, inputData.viewDirectionWS);
|
|
#if defined(_SIMPLEFUZZ)
|
|
// Reset diffuse as we want to use WrappedNdotL lighting.
|
|
brdfData.diffuse = diffuse;
|
|
#endif
|
|
|
|
color += LightingPhysicallyBased_LuxFuzz(brdfData,
|
|
#if defined(_SIMPLEFUZZ)
|
|
addData,
|
|
#endif
|
|
mainLight, inputData.normalWS, inputData.viewDirectionWS, NdotL);
|
|
// translucency
|
|
#if defined(_SCATTERING)
|
|
half transPower = translucency.y;
|
|
half3 transLightDir = mainLight.direction + inputData.normalWS * translucency.w;
|
|
half transDot = dot( transLightDir, -inputData.viewDirectionWS );
|
|
transDot = exp2(saturate(transDot) * transPower - transPower);
|
|
color += brdfData.diffuse * transDot * (1.0h - NdotL) * mainLight.color * lerp(1.0h, mainLight.shadowAttenuation, translucency.z) * translucency.x * 4;
|
|
#endif
|
|
|
|
#ifdef _ADDITIONAL_LIGHTS
|
|
uint pixelLightCount = GetAdditionalLightsCount();
|
|
for (uint i = 0u; i < pixelLightCount; ++i)
|
|
{
|
|
Light light = GetAdditionalLight(i, inputData.positionWS);
|
|
NdotL = saturate(dot(inputData.normalWS, light.direction ));
|
|
color += LightingPhysicallyBased_LuxFuzz(brdfData,
|
|
#if defined(_SIMPLEFUZZ)
|
|
addData,
|
|
#endif
|
|
light, inputData.normalWS, inputData.viewDirectionWS, NdotL);
|
|
// translucency
|
|
#if defined(_SCATTERING)
|
|
transPower = translucency.y;
|
|
transLightDir = light.direction + inputData.normalWS * translucency.w;
|
|
transDot = dot( transLightDir, -inputData.viewDirectionWS );
|
|
transDot = exp2(saturate(transDot) * transPower - transPower);
|
|
color += brdfData.diffuse * transDot * (1.0h - NdotL) * light.color * lerp(1.0h, light.shadowAttenuation, translucency.z) * light.distanceAttenuation * translucency.x * 4;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef _ADDITIONAL_LIGHTS_VERTEX
|
|
color += inputData.vertexLighting * brdfData.diffuse;
|
|
#endif
|
|
//color += emission;
|
|
return half4(color, alpha);
|
|
}
|
|
#endif |