|
|
|
|
|
|
half3 direction; |
|
|
|
half3 color; |
|
|
|
half attenuation; |
|
|
|
half realtimeAttenuation; |
|
|
|
half subtractiveModeAttenuation; |
|
|
|
}; |
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
return atten * atten; |
|
|
|
} |
|
|
|
|
|
|
|
half4 GetLightDirectionAndRealtimeAttenuation(LightInput lightInput, float3 positionWS) |
|
|
|
half4 GetLightDirectionAndAttenuation(LightInput lightInput, float3 positionWS) |
|
|
|
{ |
|
|
|
half4 directionAndAttenuation; |
|
|
|
float3 posToLightVec = lightInput.position.xyz - positionWS * lightInput.position.w; |
|
|
|
|
|
|
return directionAndAttenuation; |
|
|
|
} |
|
|
|
|
|
|
|
half4 GetMainLightDirectionAndRealtimeAttenuation(LightInput lightInput, float3 positionWS) |
|
|
|
half4 GetMainLightDirectionAndAttenuation(LightInput lightInput, float3 positionWS) |
|
|
|
{ |
|
|
|
half4 directionAndAttenuation; |
|
|
|
|
|
|
|
|
|
|
directionAndAttenuation = GetLightDirectionAndRealtimeAttenuation(lightInput, positionWS); |
|
|
|
directionAndAttenuation = GetLightDirectionAndAttenuation(lightInput, positionWS); |
|
|
|
// Cookies and shadows are only computed for main light |
|
|
|
// Cookies are only computed for main light |
|
|
|
directionAndAttenuation.w *= RealtimeShadowAttenuation(positionWS); |
|
|
|
|
|
|
|
return directionAndAttenuation; |
|
|
|
} |
|
|
|
|
|
|
lightInput.spotDirection = _MainLightSpotDir; |
|
|
|
lightInput.spotAttenuation = _MainLightSpotAttenuation; |
|
|
|
|
|
|
|
half4 directionAndRealtimeAttenuation = GetMainLightDirectionAndRealtimeAttenuation(lightInput, positionWS); |
|
|
|
half4 directionAndRealtimeAttenuation = GetMainLightDirectionAndAttenuation(lightInput, positionWS); |
|
|
|
light.realtimeAttenuation = directionAndRealtimeAttenuation.w; |
|
|
|
light.attenuation = MixRealtimeAndBakedOcclusion(light.realtimeAttenuation, lightInput.distanceAttenuation.w); |
|
|
|
light.attenuation = directionAndRealtimeAttenuation.w; |
|
|
|
light.subtractiveModeAttenuation = lightInput.distanceAttenuation.w; |
|
|
|
light.color = lightInput.color; |
|
|
|
|
|
|
|
return light; |
|
|
|
|
|
|
lightInput.spotDirection = _AdditionalLightSpotDir[lightIndex]; |
|
|
|
lightInput.spotAttenuation = _AdditionalLightSpotAttenuation[lightIndex]; |
|
|
|
|
|
|
|
half4 directionAndRealtimeAttenuation = GetLightDirectionAndRealtimeAttenuation(lightInput, positionWS); |
|
|
|
half4 directionAndRealtimeAttenuation = GetLightDirectionAndAttenuation(lightInput, positionWS); |
|
|
|
light.realtimeAttenuation = directionAndRealtimeAttenuation.w; |
|
|
|
light.attenuation = MixRealtimeAndBakedOcclusion(light.realtimeAttenuation, lightInput.distanceAttenuation.w); |
|
|
|
light.attenuation = directionAndRealtimeAttenuation.w; |
|
|
|
light.subtractiveModeAttenuation = lightInput.distanceAttenuation.w; |
|
|
|
light.color = lightInput.color; |
|
|
|
|
|
|
|
return light; |
|
|
|
|
|
|
|
|
|
|
half3 SubtractDirectMainLightFromLightmap(Light mainLight, half3 normalWS, half3 bakedGI) |
|
|
|
{ |
|
|
|
#if defined(_MAIN_LIGHT_DIRECTIONAL) && defined(_MIXED_LIGHTING_SUBTRACTIVE) && defined(LIGHTMAP_ON) && defined(_SHADOWS_ENABLED) |
|
|
|
// Let's try to make realtime shadows work on a surface, which already contains |
|
|
|
// baked lighting and shadowing from the main sun light. |
|
|
|
// Summary: |
|
|
|
|
|
|
// 1) Gives good estimate of illumination as if light would've been shadowed during the bake. |
|
|
|
// Preserves bounce and other baked lights |
|
|
|
// No shadows on the geometry facing away from the light |
|
|
|
half shadowStrength = _ShadowData.x; |
|
|
|
half shadowStrength = GetShadowStrength(); |
|
|
|
half3 estimatedLightContributionMaskedByInverseOfShadow = lambert * (1.0 - mainLight.realtimeAttenuation); |
|
|
|
half3 estimatedLightContributionMaskedByInverseOfShadow = lambert * (1.0 - mainLight.attenuation); |
|
|
|
half3 subtractedLightmap = bakedGI - estimatedLightContributionMaskedByInverseOfShadow; |
|
|
|
|
|
|
|
// 2) Allows user to define overall ambient of the scene and control situation when realtime shadow becomes too dark. |
|
|
|
|
|
|
// 3) Pick darkest color |
|
|
|
return min(bakedGI, realtimeShadow); |
|
|
|
#endif |
|
|
|
|
|
|
|
return bakedGI; |
|
|
|
} |
|
|
|
|
|
|
|
half3 GlobalIllumination(BRDFData brdfData, half3 bakedGI, half occlusion, half3 normalWS, half3 viewDirectionWS) |
|
|
|
|
|
|
return EnvironmentBRDF(brdfData, indirectDiffuse, indirectSpecular, fresnelTerm); |
|
|
|
} |
|
|
|
|
|
|
|
void MixRealtimeAndBakedGI(inout Light light, half3 normalWS, inout half3 bakedGI, half4 shadowMask) |
|
|
|
{ |
|
|
|
#if defined(_MAIN_LIGHT_DIRECTIONAL) && defined(_MIXED_LIGHTING_SUBTRACTIVE) && defined(LIGHTMAP_ON) && defined(_SHADOWS_ENABLED) |
|
|
|
bakedGI = SubtractDirectMainLightFromLightmap(light, normalWS, bakedGI); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if defined(LIGHTMAP_ON) |
|
|
|
#if defined(_MIXED_LIGHTING_SHADOWMASK) |
|
|
|
// TODO: |
|
|
|
#elif defined(_MIXED_LIGHTING_SUBTRACTIVE) |
|
|
|
// Subtractive Light mode has direct light contribution baked into lightmap for mixed lights. |
|
|
|
// We need to remove direct realtime contribution from mixed lights |
|
|
|
// subtractiveModeBakedOcclusion is set 0.0 if this light occlusion was baked in the lightmap, 1.0 otherwise. |
|
|
|
light.attenuation *= light.subtractiveModeAttenuation; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
// Lighting Functions // |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
{ |
|
|
|
Light light = GetLight(lightIter, positionWS); |
|
|
|
|
|
|
|
half3 lightColor = light.color * light.realtimeAttenuation; |
|
|
|
half3 lightColor = light.color * light.attenuation; |
|
|
|
vertexLightColor += LightingLambert(lightColor, light.direction, normalWS); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
// Fragment Functions // |
|
|
|
// Used by ShaderGraph and others builtin renderers // |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
half4 LightweightFragmentPBR(float3 positionWS, half3 normalWS, half3 viewDirectionWS, |
|
|
|
half4 LightweightFragmentPBR(float3 positionWS, half3 normalWS, half3 viewDirectionWS, half4 shadowCoord, |
|
|
|
half3 bakedGI, half3 vertexLighting, half3 albedo, half metallic, half3 specular, |
|
|
|
half smoothness, half occlusion, half3 emission, half alpha) |
|
|
|
{ |
|
|
|
|
|
|
Light mainLight = GetMainLight(positionWS); |
|
|
|
bakedGI = SubtractDirectMainLightFromLightmap(mainLight, normalWS, bakedGI); |
|
|
|
mainLight.attenuation *= RealtimeShadowAttenuation(positionWS, shadowCoord); |
|
|
|
|
|
|
|
MixRealtimeAndBakedGI(mainLight, normalWS, bakedGI, half4(0, 0, 0, 0)); |
|
|
|
half3 color = GlobalIllumination(brdfData, bakedGI, occlusion, normalWS, viewDirectionWS); |
|
|
|
color += LightingPhysicallyBased(brdfData, mainLight, normalWS, viewDirectionWS); |
|
|
|
|
|
|
|
|
|
|
return half4(color, alpha); |
|
|
|
} |
|
|
|
|
|
|
|
half4 LightweightFragmentLambert(float3 positionWS, half3 normalWS, half3 viewDirectionWS, |
|
|
|
half4 LightweightFragmentLambert(float3 positionWS, half3 normalWS, half3 viewDirectionWS, half4 shadowCoord, |
|
|
|
half3 indirectDiffuse = SubtractDirectMainLightFromLightmap(mainLight, normalWS, bakedGI); |
|
|
|
mainLight.attenuation *= RealtimeShadowAttenuation(positionWS, shadowCoord); |
|
|
|
MixRealtimeAndBakedGI(mainLight, normalWS, bakedGI, half4(0, 0, 0, 0)); |
|
|
|
|
|
|
|
half3 diffuseColor = lambert * mainLight.attenuation + indirectDiffuse; |
|
|
|
half3 diffuseColor = lambert * mainLight.attenuation + bakedGI; |
|
|
|
|
|
|
|
#ifdef _ADDITIONAL_LIGHTS |
|
|
|
int pixelLightCount = GetPixelLightCount(); |
|
|
|
|
|
|
return half4(finalColor, alpha); |
|
|
|
} |
|
|
|
|
|
|
|
half4 LightweightFragmentBlinnPhong(float3 positionWS, half3 normalWS, half3 viewDirectionWS, |
|
|
|
half4 LightweightFragmentBlinnPhong(float3 positionWS, half3 normalWS, half3 viewDirectionWS, half4 shadowCoord, |
|
|
|
half3 indirectDiffuse = SubtractDirectMainLightFromLightmap(mainLight, normalWS, bakedGI); |
|
|
|
mainLight.attenuation *= RealtimeShadowAttenuation(positionWS, shadowCoord); |
|
|
|
MixRealtimeAndBakedGI(mainLight, normalWS, bakedGI, half4(0, 0, 0, 0)); |
|
|
|
half3 diffuseColor = indirectDiffuse + LightingLambert(attenuatedLightColor, mainLight.direction, normalWS); |
|
|
|
half3 diffuseColor = bakedGI + LightingLambert(attenuatedLightColor, mainLight.direction, normalWS); |
|
|
|
half3 specularColor = LightingSpecular(attenuatedLightColor, mainLight.direction, normalWS, viewDirectionWS, specularGloss, shininess); |
|
|
|
|
|
|
|
#ifdef _ADDITIONAL_LIGHTS |
|
|
|