449 lines
20 KiB
HLSL
449 lines
20 KiB
HLSL
#ifndef UNIVERSAL_SKINLIGHTING_INCLUDED
|
|
#define UNIVERSAL_SKINLIGHTING_INCLUDED
|
|
|
|
|
|
TEXTURE2D(_SkinLUT); SAMPLER(sampler_SkinLUT); float4 _SkinLUT_TexelSize;
|
|
|
|
half3 GlobalIllumination(BRDFData brdfData, half3 bakedGI, half occlusion, float3 positionWS, half3 normalWS, half3 viewDirectionWS, float2 normalizedScreenSpaceUV,
|
|
half specOcclusion)
|
|
{
|
|
half3 reflectVector = reflect(-viewDirectionWS, normalWS);
|
|
half fresnelTerm = Pow4(1.0 - saturate(dot(normalWS, viewDirectionWS)));
|
|
|
|
half3 indirectDiffuse = bakedGI * occlusion;
|
|
half3 indirectSpecular = GlossyEnvironmentReflection(
|
|
reflectVector, positionWS, brdfData.perceptualRoughness, occlusion, normalizedScreenSpaceUV) * specOcclusion;
|
|
|
|
half3 color = EnvironmentBRDF(brdfData, indirectDiffuse, indirectSpecular, fresnelTerm);
|
|
|
|
// Debug
|
|
if (IsOnlyAOLightingFeatureEnabled())
|
|
{
|
|
color = occlusion.xxx; // "Base white" for AO debug lighting mode // Lux: We return occlusion here
|
|
}
|
|
|
|
return color;
|
|
}
|
|
|
|
inline half GammaToLinearSpace(half sRGB)
|
|
{
|
|
// Approximate version from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html
|
|
return sRGB * (sRGB * (sRGB * 0.305306011h + 0.682171111h) + 0.012522878h);
|
|
}
|
|
|
|
half3 LightingPhysicallyBasedSkin(BRDFData brdfData, half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS, half NdotL, half NdotLUnclamped, half curvature, half skinMask)
|
|
{
|
|
//half3 radiance = lightColor * NdotL;
|
|
half3 diffuseLighting = brdfData.diffuse * SAMPLE_TEXTURE2D_LOD(_SkinLUT, sampler_SkinLUT, float2( (NdotLUnclamped * 0.5 + 0.5), curvature), 0).rgb;
|
|
diffuseLighting = lerp(brdfData.diffuse * NdotL, diffuseLighting, skinMask);
|
|
// return ( DirectBDRF_Lux(brdfData, normalWS, lightDirectionWS, viewDirectionWS) * NdotL + diffuseLighting ) * lightColor * lightAttenuation;
|
|
#ifndef _SPECULARHIGHLIGHTS_OFF
|
|
half specularTerm = DirectBRDFSpecular(brdfData, normalWS, lightDirectionWS, viewDirectionWS);
|
|
return ( specularTerm * brdfData.specular * NdotL + diffuseLighting ) * lightColor * lightAttenuation;
|
|
#else
|
|
return diffuseLighting * lightColor * lightAttenuation;
|
|
#endif
|
|
}
|
|
|
|
half3 LightingPhysicallyBasedSkin(BRDFData brdfData, Light light, half3 normalWS, half3 viewDirectionWS, half NdotL, half NdotLUnclamped, half curvature, half skinMask)
|
|
{
|
|
return LightingPhysicallyBasedSkin(brdfData, light.color, light.direction, light.distanceAttenuation * light.shadowAttenuation, normalWS, viewDirectionWS, NdotL, NdotLUnclamped, curvature, skinMask);
|
|
}
|
|
|
|
|
|
half4 URPSkinFragmentPBR(InputData inputData, SurfaceData surfaceData,
|
|
half4 translucency, half AmbientReflection, half3 subsurfaceColor, half curvature, half skinMask, half maskbyshadowstrength, half backScatter)
|
|
{
|
|
BRDFData brdfData;
|
|
InitializeBRDFData(surfaceData, brdfData);
|
|
|
|
#if defined(DEBUG_DISPLAY)
|
|
half4 debugColor;
|
|
if (CanDebugOverrideOutputColor(inputData, surfaceData, brdfData, debugColor)) {
|
|
return debugColor;
|
|
}
|
|
#endif
|
|
|
|
half4 shadowMask = CalculateShadowMask(inputData);
|
|
AmbientOcclusionFactor aoFactor = CreateAmbientOcclusionFactor(inputData, surfaceData);
|
|
uint meshRenderingLayers = GetMeshRenderingLayer();
|
|
Light mainLight = GetMainLight(inputData, shadowMask, aoFactor);
|
|
|
|
// NOTE: We don't apply AO to the GI here because it's done in the lighting calculation below...
|
|
MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI);
|
|
//MixRealtimeAndBakedGI(mainLight, diffuseNormalWS, inputData.bakedGI);
|
|
|
|
LightingData lightingData = CreateLightingData(inputData, surfaceData);
|
|
|
|
lightingData.giColor = GlobalIllumination(
|
|
brdfData, inputData.bakedGI, aoFactor.indirectAmbientOcclusion,
|
|
inputData.positionWS, inputData.normalWS, inputData.viewDirectionWS, inputData.normalizedScreenSpaceUV, AmbientReflection
|
|
);
|
|
// Backscattering
|
|
#if defined(_BACKSCATTER) && !defined(DEBUG_DISPLAY)
|
|
lightingData.giColor += backScatter * SampleSH(-inputData.normalWS) * surfaceData.albedo * aoFactor.indirectAmbientOcclusion * translucency.x * subsurfaceColor * skinMask;
|
|
#endif
|
|
|
|
#if defined(_LIGHT_LAYERS)
|
|
if (IsMatchingLightLayer(mainLight.layerMask, meshRenderingLayers))
|
|
#endif
|
|
{
|
|
half3 mainLightColor = mainLight.color;
|
|
half NdotLUnclamped = dot(inputData.normalWS, mainLight.direction);
|
|
half NdotL = saturate( dot(inputData.normalWS, mainLight.direction) );
|
|
lightingData.mainLightColor = LightingPhysicallyBasedSkin(brdfData, mainLight, inputData.normalWS, inputData.viewDirectionWS, NdotL, NdotLUnclamped, curvature, skinMask);
|
|
|
|
// Subsurface 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);
|
|
lightingData.mainLightColor += skinMask * subsurfaceColor * transDot * (1.0 - saturate(NdotLUnclamped)) * mainLightColor * lerp(1.0, mainLight.shadowAttenuation, translucency.z) * translucency.x;
|
|
|
|
}
|
|
|
|
#if defined(_ADDITIONAL_LIGHTS)
|
|
uint pixelLightCount = GetAdditionalLightsCount();
|
|
|
|
#if USE_FORWARD_PLUS
|
|
for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++)
|
|
{
|
|
FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK
|
|
Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
|
|
#ifdef _LIGHT_LAYERS
|
|
if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
|
|
#endif
|
|
{
|
|
half3 lightColor = light.color;
|
|
half NdotLUnclamped = dot(inputData.normalWS, light.direction);
|
|
half NdotL = saturate( dot(inputData.normalWS, light.direction) );
|
|
lightingData.additionalLightsColor += LightingPhysicallyBasedSkin(brdfData, light, inputData.normalWS, inputData.viewDirectionWS, NdotL, NdotLUnclamped, curvature, skinMask);
|
|
|
|
// Subsurface Scattering
|
|
int index = lightIndex;
|
|
half4 shadowParams = GetAdditionalLightShadowParams(index);
|
|
#if !defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
|
|
lightColor *= lerp(1, 0, maskbyshadowstrength);
|
|
#else
|
|
// half isPointLight = shadowParams.z;
|
|
lightColor *= lerp(1, shadowParams.x, maskbyshadowstrength);
|
|
#endif
|
|
|
|
half transPower = translucency.y;
|
|
half3 transLightDirA = light.direction + inputData.normalWS * translucency.w;
|
|
half transDotA = dot( transLightDirA, -inputData.viewDirectionWS );
|
|
transDotA = exp2(saturate(transDotA) * transPower - transPower);
|
|
lightingData.additionalLightsColor += skinMask * subsurfaceColor * transDotA * (1.0 - saturate(NdotLUnclamped)) * lightColor * lerp(1.0, light.shadowAttenuation, translucency.z) * light.distanceAttenuation * translucency.x;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
LIGHT_LOOP_BEGIN(pixelLightCount)
|
|
Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
|
|
|
|
#if defined(_LIGHT_LAYERS)
|
|
if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
|
|
#endif
|
|
{
|
|
half3 lightColor = light.color;
|
|
half NdotLUnclamped = dot(inputData.normalWS, light.direction);
|
|
half NdotL = saturate( dot(inputData.normalWS, light.direction) );
|
|
lightingData.additionalLightsColor += LightingPhysicallyBasedSkin(brdfData, light, inputData.normalWS, inputData.viewDirectionWS, NdotL, NdotLUnclamped, curvature, skinMask);
|
|
|
|
// Subsurface Scattering
|
|
int index = lightIndex;
|
|
//int index = GetPerObjectLightIndex(lightIndex);
|
|
half4 shadowParams = GetAdditionalLightShadowParams(index);
|
|
#if !defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
|
|
lightColor *= lerp(1, 0, maskbyshadowstrength);
|
|
#else
|
|
// half isPointLight = shadowParams.z;
|
|
lightColor *= lerp(1, shadowParams.x, maskbyshadowstrength);
|
|
#endif
|
|
|
|
half transPower = translucency.y;
|
|
half3 transLightDirA = light.direction + inputData.normalWS * translucency.w;
|
|
half transDotA = dot( transLightDirA, -inputData.viewDirectionWS );
|
|
transDotA = exp2(saturate(transDotA) * transPower - transPower);
|
|
lightingData.additionalLightsColor += skinMask * subsurfaceColor * transDotA * (1.0 - saturate(NdotLUnclamped)) * lightColor * lerp(1.0, light.shadowAttenuation, translucency.z) * light.distanceAttenuation * translucency.x;
|
|
}
|
|
LIGHT_LOOP_END
|
|
#endif
|
|
|
|
#ifdef _ADDITIONAL_LIGHTS_VERTEX
|
|
lightingData.vertexLightingColor += inputData.vertexLighting * brdfData.diffuse;
|
|
#endif
|
|
|
|
return CalculateFinalColor(lightingData, surfaceData.alpha);
|
|
}
|
|
|
|
#endif
|
|
|
|
#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"
|
|
|
|
// Ref: https://knarkowicz.wordpress.com/2018/01/04/cloth-shading/
|
|
real D_CharlieNoPI_Lux(real NdotH, real roughness)
|
|
{
|
|
float invR = rcp(roughness);
|
|
float cos2h = NdotH * NdotH;
|
|
float sin2h = 1.0 - cos2h;
|
|
// Note: We have sin^2 so multiply by 0.5 to cancel it
|
|
return (2.0 + invR) * PositivePow(sin2h, invR * 0.5) / 2.0;
|
|
}
|
|
|
|
/* real D_Charlie_Lux(real NdotH, real roughness)
|
|
{
|
|
return INV_PI * D_CharlieNoPI_Lux(NdotH, roughness);
|
|
} */
|
|
|
|
// We use V_Ashikhmin instead of V_Charlie in practice for game due to the cost of V_Charlie
|
|
real V_Ashikhmin_Lux(real NdotL, real NdotV)
|
|
{
|
|
// Use soft visibility term introduce in: Crafting a Next-Gen Material Pipeline for The Order : 1886
|
|
return 1.0 / (4.0 * (NdotL + NdotV - NdotL * NdotV));
|
|
}
|
|
|
|
// A diffuse term use with fabric done by tech artist - empirical
|
|
real FabricLambertNoPI_Lux(real roughness)
|
|
{
|
|
return lerp(1.0, 0.5, roughness);
|
|
}
|
|
|
|
real FabricLambert_Lux(real roughness)
|
|
{
|
|
return INV_PI * FabricLambertNoPI_Lux(roughness);
|
|
}
|
|
|
|
// ---------
|
|
|
|
struct AdditionalData {
|
|
half3 tangentWS;
|
|
half3 bitangentWS;
|
|
float partLambdaV;
|
|
half roughnessT;
|
|
half roughnessB;
|
|
half3 anisoReflectionNormal;
|
|
};
|
|
|
|
half3 DirectBDRF_LuxCloth(BRDFData brdfData, AdditionalData addData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS, half NdotL)
|
|
{
|
|
#ifndef _SPECULARHIGHLIGHTS_OFF
|
|
float3 lightDirectionWSFloat3 = float3(lightDirectionWS);
|
|
float3 halfDir = SafeNormalize(lightDirectionWSFloat3 + float3(viewDirectionWS));
|
|
|
|
float NoH = saturate(dot(float3(normalWS), halfDir));
|
|
half LoH = half(saturate(dot(lightDirectionWSFloat3, halfDir)));
|
|
|
|
half NdotV = saturate(dot(normalWS, viewDirectionWS ));
|
|
|
|
float3 tangentWS = float3(addData.tangentWS);
|
|
float3 bitangentWS = float3(addData.bitangentWS);
|
|
|
|
float TdotH = dot(tangentWS, halfDir);
|
|
float TdotL = dot(tangentWS, lightDirectionWSFloat3);
|
|
float BdotH = dot(bitangentWS, halfDir);
|
|
float BdotL = dot(bitangentWS, lightDirectionWSFloat3);
|
|
|
|
half3 F = F_Schlick(brdfData.specular, LoH); // 1.91: was float3
|
|
|
|
//float TdotV = dot(tangentWS, viewDirectionWS);
|
|
//float BdotV = dot(bitangentWS, viewDirectionWS);
|
|
|
|
float DV = DV_SmithJointGGXAniso(
|
|
TdotH, BdotH, NoH, NdotV, TdotL, BdotL, NdotL,
|
|
addData.roughnessT, addData.roughnessB, addData.partLambdaV
|
|
);
|
|
half3 specularLighting = F * DV;
|
|
|
|
//return float4(normalWS, 1);
|
|
return specularLighting + brdfData.diffuse;
|
|
|
|
#else
|
|
|
|
return brdfData.diffuse;
|
|
|
|
#endif
|
|
}
|
|
|
|
half3 LightingPhysicallyBased_LuxCloth(BRDFData brdfData, AdditionalData addData, half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS, half NdotL)
|
|
{
|
|
half3 radiance = lightColor * (lightAttenuation * NdotL);
|
|
return DirectBDRF_LuxCloth(brdfData, addData, normalWS, lightDirectionWS, viewDirectionWS, NdotL) * radiance;
|
|
}
|
|
|
|
half3 LightingPhysicallyBased_LuxCloth(BRDFData brdfData, AdditionalData addData, Light light, half3 normalWS, half3 viewDirectionWS, half NdotL)
|
|
{
|
|
return LightingPhysicallyBased_LuxCloth(brdfData, addData, light.color, light.direction, light.distanceAttenuation * light.shadowAttenuation, normalWS, viewDirectionWS, NdotL);
|
|
}
|
|
|
|
// As we need both normals here - otherwise kept in sync with latest URP function
|
|
half3 GlobalIllumination_LuxAniso(BRDFData brdfData, BRDFData brdfDataClearCoat, float clearCoatMask,
|
|
half3 bakedGI, half occlusion, float3 positionWS,
|
|
half3 anisoReflectionNormal,
|
|
half3 normalWS, half3 viewDirectionWS, float2 normalizedScreenSpaceUV)
|
|
{
|
|
half3 reflectVector = reflect(-viewDirectionWS, anisoReflectionNormal);
|
|
half NoV = saturate(dot(normalWS, viewDirectionWS));
|
|
half fresnelTerm = Pow4(1.0 - NoV);
|
|
|
|
half3 indirectDiffuse = bakedGI;
|
|
half3 indirectSpecular = GlossyEnvironmentReflection(reflectVector, positionWS, brdfData.perceptualRoughness, 1.0h, normalizedScreenSpaceUV);
|
|
|
|
half3 color = EnvironmentBRDF(brdfData, indirectDiffuse, indirectSpecular, fresnelTerm);
|
|
|
|
if (IsOnlyAOLightingFeatureEnabled())
|
|
{
|
|
color = half3(1,1,1); // "Base white" for AO debug lighting mode
|
|
}
|
|
|
|
#if defined(_CLEARCOAT) || defined(_CLEARCOATMAP)
|
|
half3 coatIndirectSpecular = GlossyEnvironmentReflection(reflectVector, positionWS, brdfDataClearCoat.perceptualRoughness, 1.0h, normalizedScreenSpaceUV);
|
|
// TODO: "grazing term" causes problems on full roughness
|
|
half3 coatColor = EnvironmentBRDFClearCoat(brdfDataClearCoat, clearCoatMask, coatIndirectSpecular, fresnelTerm);
|
|
|
|
// Blend with base layer using khronos glTF recommended way using NoV
|
|
// Smooth surface & "ambiguous" lighting
|
|
// NOTE: fresnelTerm (above) is pow4 instead of pow5, but should be ok as blend weight.
|
|
half coatFresnel = kDielectricSpec.x + kDielectricSpec.a * fresnelTerm;
|
|
return (color * (1.0 - coatFresnel * clearCoatMask) + coatColor) * occlusion;
|
|
#else
|
|
return color * occlusion;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
half4 LuxURPClothFragmentPBR(InputData inputData, SurfaceData surfaceData, half3 tangentWS, half anisotropy, half4 translucency, half metallic)
|
|
{
|
|
BRDFData brdfData;
|
|
InitializeBRDFData(surfaceData, brdfData);
|
|
|
|
// Do not apply energy conservtion
|
|
half oneMinusReflectivity = OneMinusReflectivityMetallic(surfaceData.metallic);
|
|
half reflectivity = half(1.0) - oneMinusReflectivity;
|
|
half3 brdfDiffuse = surfaceData.albedo * oneMinusReflectivity;
|
|
half3 brdfSpecular = lerp(kDieletricSpec.rgb * surfaceData.specular, surfaceData.albedo * metallic, surfaceData.metallic);
|
|
//half3 brdfSpecular = lerp(float3(1,0,0), float3(0,1,0), surfaceData.metallic);
|
|
brdfData.diffuse = brdfDiffuse;
|
|
brdfData.specular = brdfSpecular;
|
|
|
|
// Debugging
|
|
#if defined(DEBUG_DISPLAY)
|
|
half4 debugColor;
|
|
if (CanDebugOverrideOutputColor(inputData, surfaceData, brdfData, debugColor))
|
|
{
|
|
return debugColor;
|
|
}
|
|
#endif
|
|
|
|
AdditionalData addData;
|
|
tangentWS = Orthonormalize(tangentWS, inputData.normalWS);
|
|
addData.tangentWS = tangentWS;
|
|
addData.bitangentWS = cross(inputData.normalWS, tangentWS);
|
|
|
|
// We do not apply ClampRoughnessForAnalyticalLights here
|
|
addData.roughnessT = brdfData.roughness * (1 + anisotropy);
|
|
addData.roughnessB = brdfData.roughness * (1 - anisotropy);
|
|
float TdotV = dot(addData.tangentWS, inputData.viewDirectionWS);
|
|
float BdotV = dot(addData.bitangentWS, inputData.viewDirectionWS);
|
|
float NdotV = dot(inputData.normalWS, inputData.viewDirectionWS);
|
|
// partLambdaV should be 0.0f in case of cotton wool
|
|
addData.partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, addData.roughnessT, addData.roughnessB);
|
|
half3 grainDirWS = (anisotropy >= 0.0) ? addData.bitangentWS : addData.tangentWS;
|
|
half stretch = abs(anisotropy) * saturate(1.5h * sqrt(brdfData.perceptualRoughness));
|
|
addData.anisoReflectionNormal = GetAnisotropicModifiedNormal(grainDirWS, inputData.normalWS, inputData.viewDirectionWS, stretch);
|
|
half iblPerceptualRoughness = brdfData.perceptualRoughness * saturate(1.2 - abs(anisotropy));
|
|
|
|
// Override perceptual roughness for ambient specular reflections
|
|
brdfData.perceptualRoughness = iblPerceptualRoughness;
|
|
|
|
// Only used for reflections - so we skip it
|
|
/*float3 preFGD = SAMPLE_TEXTURE2D_LOD(_PreIntegratedLUT, sampler_PreIntegratedLUT, float2(NdotV, brdfData.perceptualRoughness), 0).xyz;
|
|
// Denormalize the value
|
|
preFGD.y = preFGD.y / (1 - preFGD.y);
|
|
half3 specularFGD = preFGD.yyy * fresnel0;
|
|
// z = FabricLambert
|
|
half3 diffuseFGD = preFGD.z;
|
|
half reflectivity = preFGD.y;*/
|
|
|
|
half4 shadowMask = CalculateShadowMask(inputData);
|
|
AmbientOcclusionFactor aoFactor = CreateAmbientOcclusionFactor(inputData, surfaceData);
|
|
uint meshRenderingLayers = GetMeshRenderingLayer();
|
|
|
|
Light mainLight = GetMainLight(inputData, shadowMask, aoFactor);
|
|
half3 mainLightColor = mainLight.color;
|
|
|
|
MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI);
|
|
|
|
LightingData lightingData = CreateLightingData(inputData, surfaceData);
|
|
|
|
// NOTE: We use addData.anisoReflectionNormal here!
|
|
lightingData.giColor = GlobalIllumination_LuxAniso(
|
|
brdfData,
|
|
brdfData, // brdfDataClearCoat
|
|
0, // surfaceData.clearCoatMask,
|
|
inputData.bakedGI,
|
|
aoFactor.indirectAmbientOcclusion,
|
|
inputData.positionWS,
|
|
addData.anisoReflectionNormal,
|
|
inputData.normalWS,
|
|
inputData.viewDirectionWS,
|
|
inputData.normalizedScreenSpaceUV
|
|
);
|
|
|
|
half NdotL;
|
|
|
|
#if defined(_LIGHT_LAYERS)
|
|
if (IsMatchingLightLayer(mainLight.layerMask, meshRenderingLayers))
|
|
#endif
|
|
{
|
|
NdotL = saturate(dot(inputData.normalWS, mainLight.direction ));
|
|
lightingData.mainLightColor = LightingPhysicallyBased_LuxCloth(brdfData, addData, mainLight, inputData.normalWS, inputData.viewDirectionWS, NdotL);
|
|
}
|
|
|
|
#ifdef _ADDITIONAL_LIGHTS
|
|
uint pixelLightCount = GetAdditionalLightsCount();
|
|
|
|
#if USE_FORWARD_PLUS
|
|
for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++)
|
|
{
|
|
FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK
|
|
Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
|
|
#ifdef _LIGHT_LAYERS
|
|
if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
|
|
#endif
|
|
{
|
|
half3 lightColor = light.color;
|
|
NdotL = saturate(dot(inputData.normalWS, light.direction ));
|
|
lightingData.additionalLightsColor += LightingPhysicallyBased_LuxCloth(brdfData, addData, light, inputData.normalWS, inputData.viewDirectionWS, NdotL);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
LIGHT_LOOP_BEGIN(pixelLightCount)
|
|
Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
|
|
#if defined(_LIGHT_LAYERS)
|
|
if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
|
|
#endif
|
|
{
|
|
half3 lightColor = light.color;
|
|
NdotL = saturate(dot(inputData.normalWS, light.direction ));
|
|
lightingData.additionalLightsColor += LightingPhysicallyBased_LuxCloth(brdfData, addData, light, inputData.normalWS, inputData.viewDirectionWS, NdotL);
|
|
}
|
|
LIGHT_LOOP_END
|
|
#endif
|
|
|
|
#ifdef _ADDITIONAL_LIGHTS_VERTEX
|
|
lightingData.vertexLightingColor += inputData.vertexLighting * brdfData.diffuse;
|
|
#endif
|
|
|
|
//return float4(inputData.normalTS, 1);
|
|
return CalculateFinalColor(lightingData, surfaceData.alpha);
|
|
//return brdfData.perceptualRoughness;
|
|
}
|