浏览代码

Computing shadow coord in vertex when not using cascades.

/main
Felipe Lira 7 年前
当前提交
cfca3b82
共有 5 个文件被更改,包括 122 次插入60 次删除
  1. 72
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Lighting.hlsl
  2. 45
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLit.hlsl
  3. 44
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl
  4. 2
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardParticles.shader
  5. 19
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardTerrain.shader

72
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Lighting.hlsl


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

45
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLit.hlsl


float3 posWS : TEXCOORD2;
half3 normal : TEXCOORD3;
#if _NORMALMAP
#ifdef _NORMALMAP
half3 tangent : TEXCOORD4;
half3 binormal : TEXCOORD5;
#endif

#ifdef _SHADOWS_ENABLED
half4 shadowCoord : TEXCOORD8;
#endif
float4 clipPos : SV_POSITION;
};

half fogFactor = ComputeFogFactor(o.clipPos.z);
o.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
#if defined(_SHADOWS_ENABLED) && !defined(_SHADOWS_CASCADE)
o.shadowCoord = ComputeShadowCoord(o.posWS.xyz);
#endif
return o;
}

SurfaceData surfaceData;
InitializeStandardLitSurfaceData(IN.uv, surfaceData);
#if _NORMALMAP
#ifdef _NORMALMAP
half3 indirectDiffuse = SampleGI(IN.lightmapUVOrVertexSH, normalWS);
float fogFactor = IN.fogFactorAndVertexLight.x;
half3 bakedGI = SampleGI(IN.lightmapUVOrVertexSH, normalWS);
half fogFactor = IN.fogFactorAndVertexLight.x;
half3 vertexLighting = IN.fogFactorAndVertexLight.yzw;
float3 positionWS = IN.posWS.xyz;
half4 color = LightweightFragmentPBR(IN.posWS.xyz, normalWS, IN.viewDir, indirectDiffuse, IN.fogFactorAndVertexLight.yzw, surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.occlusion, surfaceData.emission, surfaceData.alpha);
half3 viewDirectionWS = IN.viewDir;
half4 shadowCoord = half4(0, 0, 0, 0);
#ifdef _SHADOWS_ENABLED
shadowCoord = IN.shadowCoord;
#endif
BRDFData brdfData;
InitializeBRDFData(surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.alpha, brdfData);
half4 color = LightweightFragmentPBR(positionWS, normalWS, viewDirectionWS, shadowCoord, bakedGI, vertexLighting,
surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.occlusion, surfaceData.emission, surfaceData.alpha);
ApplyFog(color.rgb, fogFactor);
return color;
}

AlphaDiscard(alpha, _Cutoff);
#if _NORMALMAP
#ifdef _NORMALMAP
half3 normalTangent = Normal(uv);
half3 normalWS = TangentToWorldNormal(normalTangent, IN.tangent, IN.binormal, IN.normal);
#else

half4 shadowCoord = half4(0, 0, 0, 0);
#ifdef _SHADOWS_ENABLED
shadowCoord = IN.shadowCoord;
#endif
half3 emission = Emission(uv);
half3 viewDirectionWS = SafeNormalize(IN.viewDir.xyz);

#if _VERTEX_LIGHTS
#ifdef _VERTEX_LIGHTS
diffuseGI += IN.fogFactorAndVertexLight.yzw;
#endif

#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
half4 specularGloss = SpecularGloss(uv, diffuseAlpha.a);
return LightweightFragmentBlinnPhong(positionWS, normalWS, viewDirectionWS, fogFactor, diffuseGI, diffuse, specularGloss, shininess, emission, alpha);
return LightweightFragmentBlinnPhong(positionWS, normalWS, viewDirectionWS, shadowCoord, fogFactor, diffuseGI, diffuse, specularGloss, shininess, emission, alpha);
return LightweightFragmentLambert(positionWS, normalWS, viewDirectionWS, fogFactor, diffuseGI, diffuse, emission, alpha);
return LightweightFragmentLambert(positionWS, normalWS, viewDirectionWS, shadowCoord, fogFactor, diffuseGI, diffuse, emission, alpha);
#endif
};

44
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl


half4 _ShadowOffset2;
half4 _ShadowOffset3;
half4 _ShadowData; // (x: shadowStrength)
half4 _ShadowmapSize; // (xy: width and height, zw: 1/width and 1/height)
half4 _ShadowmapSize; // (xy: 1/width and 1/height, zw: width and height)
inline half SampleShadowmap(float4 shadowCoord)
inline half SampleShadowmap(half4 shadowCoord)
{
#if defined(_SHADOWS_PERSPECTIVE)
shadowCoord.xyz = shadowCoord.xyz /= shadowCoord.w;

return (shadowCoord.x <= 0 || shadowCoord.x >= 1 || shadowCoord.y <= 0 || shadowCoord.y >= 1 || shadowCoord.z >= 1) ? 1.0 : attenuation;
}
inline half ComputeCascadeIndex(float3 wpos)
inline half ComputeCascadeIndex(float3 positionWS)
float3 fromCenter0 = wpos.xyz - _DirShadowSplitSpheres[0].xyz;
float3 fromCenter1 = wpos.xyz - _DirShadowSplitSpheres[1].xyz;
float3 fromCenter2 = wpos.xyz - _DirShadowSplitSpheres[2].xyz;
float3 fromCenter3 = wpos.xyz - _DirShadowSplitSpheres[3].xyz;
float3 fromCenter0 = positionWS.xyz - _DirShadowSplitSpheres[0].xyz;
float3 fromCenter1 = positionWS.xyz - _DirShadowSplitSpheres[1].xyz;
float3 fromCenter2 = positionWS.xyz - _DirShadowSplitSpheres[2].xyz;
float3 fromCenter3 = positionWS.xyz - _DirShadowSplitSpheres[3].xyz;
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
half4 weights = half4(distances2 < _DirShadowSplitSphereRadii);

}
inline float4 ComputeShadowCoord(float3 positionWS, half cascadeIndex = 0)
half4 ComputeShadowCoord(float3 positionWS)
half cascadeIndex = ComputeCascadeIndex(positionWS);
return mul(_WorldToShadow[cascadeIndex], float4(positionWS, 1.0));
#endif

inline half RealtimeShadowAttenuation(float3 positionWS)
half GetShadowStrength()
{
return _ShadowData.x;
}
half RealtimeShadowAttenuation(float3 positionWS)
half cascadeIndex = ComputeCascadeIndex(positionWS);
float4 shadowCoord = ComputeShadowCoord(positionWS, cascadeIndex);
half4 shadowCoord = ComputeShadowCoord(positionWS);
half MixRealtimeAndBakedOcclusion(half realtimeAttenuation, half subtractiveModeBakedOcclusion, half4 shadowMaskModeBakedOcclusion = half4(0, 0, 0, 0))
half RealtimeShadowAttenuation(float3 positionWS, half4 shadowCoord)
#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.
return realtimeAttenuation * subtractiveModeBakedOcclusion;
#if !defined(_SHADOWS_ENABLED)
return 1.0;
#ifdef _SHADOWS_CASCADE
shadowCoord = ComputeShadowCoord(positionWS);
return realtimeAttenuation;
return SampleShadowmap(shadowCoord);
}
#endif

2
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardParticles.shader


#endif
half3 zero = half3(0.0, 0.0, 0.0);
half4 color = LightweightFragmentPBR(positionWS, normalWS, viewDirWS, /*indirectDiffuse*/ zero, /*vertex lighting*/ zero, surfaceData.albedo,
half4 color = LightweightFragmentPBR(positionWS, normalWS, viewDirWS, half4(0, 0, 0, 0), /*indirectDiffuse*/ zero, /*vertex lighting*/ zero, surfaceData.albedo,
surfaceData.metallic, /* specularColor */ zero, surfaceData.smoothness, surfaceData.occlusion, surfaceData.emission, surfaceData.alpha);
ApplyFog(color.rgb, fogFactor);
return color;

19
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardTerrain.shader


#endif
half4 fogFactorAndVertexLight : TEXCOORD6; // x: fogFactor, yzw: vertex light
float3 positionWS : TEXCOORD7;
#ifdef _SHADOWS_ENABLED
half4 shadowCoord : TEXCOORD8;
#endif
float4 clipPos : SV_POSITION;
};

VertexOutput SplatmapVert(VertexInput v)
{
VertexOutput o;
VertexOutput o = (VertexOutput)0;
float3 positionWS = TransformObjectToWorld(v.vertex.xyz);
float4 clipPos = TransformWorldToHClip(positionWS);

o.fogFactorAndVertexLight.yzw = VertexLighting(positionWS, o.normal);
o.positionWS = positionWS;
o.clipPos = clipPos;
#if defined(_SHADOWS_ENABLED) && !defined(_SHADOWS_CASCADE)
o.shadowCoord = ComputeShadowCoord(o.positionWS.xyz);
#endif
return o;
}

indirectDiffuse = SampleLightmap(IN.uvControlAndLM.zw, normalWS);
#endif
half4 shadowCoord = half4(0, 0, 0, 0);
#ifdef _SHADOWS_ENABLED
shadowCoord = IN.shadowCoord;
#endif
half4 color = LightweightFragmentPBR(IN.positionWS, normalWS, viewDirectionWS, indirectDiffuse,
half4 color = LightweightFragmentPBR(IN.positionWS, normalWS, viewDirectionWS, shadowCoord, indirectDiffuse,
IN.fogFactorAndVertexLight.yzw, albedo, metallic, specular, smoothness, /* occlusion */ 1.0, /* emission */ half3(0, 0, 0), alpha);
ApplyFog(color.rgb, fogFactor);

正在加载...
取消
保存