目录
URP默认材质下光源阴影:
1.UniversalRenderPipelineAsset 设置阴影质量以及阴影开关
2.光源设置阴影
3.材质设置为接收阴影
顶点投射阴影:
角色名
P_Hero_Swordman_Swordman_001
https://zhuanlan.zhihu.com/p/31504088
思路1:
Shadow Map 投射到Plane上,map以外的地方透明 Planer
思路2:
让被投影的材质可以接收阴影
参考:
https://www.jianshu.com/p/a8e4dd93d7d6
Planer
https://zhuanlan.zhihu.com/p/31504088
https://blog.csdn.net/yinfourever/article/details/108646426
https://blog.csdn.net/linjf520/article/details/112979847
理论:
https://zhuanlan.zhihu.com/p/94491734
完整参考:
Properties
{
_LightDir2("_LightDir", Vector) = (0, 1, 1, 0.1)
_ShadowColor2("_ShadowColor", Color) = (0, 0, 0, 1)
_ShadowFalloff2("_ShadowFalloff", Float) = 0
}
//阴影pass
Pass
{
Name "Shadow"
Tags
{
"Queue" = "Transparent"
"RenderType" = "Transparent"
"RenderPipeline" = "UniversalPipeline"
"LightMode" = "UniversalForwardOnly"
}
//用使用模板测试以保证alpha显示正确
Stencil
{
Ref 0
Comp equal
Pass incrWrap
Fail keep
ZFail keep
}
//透明混合模式
Blend SrcAlpha OneMinusSrcAlpha
ZTest Less
//ZWrite Always
//关闭深度写入
ZWrite on
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
float4 color : COLOR;
};
float4 _LightDir2;
float4 _ShadowColor2;
float _ShadowFalloff2;
float3 ShadowProjectPos(float4 vertPos)
{
float3 shadowPos;
//得到顶点的世界空间坐标
float3 worldPos = mul(unity_ObjectToWorld, vertPos).xyz;
//灯光方向
float3 lightDir = normalize(_LightDir2.xyz);
//阴影的世界空间坐标(低于地面的部分不做改变)
shadowPos.y = min(worldPos.y, _LightDir2.w);
shadowPos.xz = worldPos.xz - lightDir.xz * max(0, worldPos.y - _LightDir2.w) / lightDir.y;
return shadowPos;
}
v2f vert(appdata v)
{
v2f o;
//得到阴影的世界空间坐标
float3 shadowPos = ShadowProjectPos(v.vertex);
//转换到裁切空间
o.vertex = UnityWorldToClipPos(shadowPos);
//得到中心点世界坐标
float3 center = float3(unity_ObjectToWorld[0].w, _LightDir2.w, unity_ObjectToWorld[2].w);
//计算阴影衰减
float falloff = 1 - saturate(distance(shadowPos, center) * _ShadowFalloff2);
//阴影颜色
o.color = _ShadowColor2;
o.color.a *= falloff;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return i.color;
}
ENDHLSL
}
URP下多Pass 渲染
每一个Pass 需要不同LightMode,否则Pass无效
https://blog.csdn.net/TGB666/article/details/122266277
URP下多光源阴影
https://zhuanlan.zhihu.com/p/158172358
https://www.jianshu.com/p/a8e4dd93d7d6
https://blog.csdn.net/zakerhero/article/details/106274331
阴影接收
最简单的阴影接收 叠加Diffuse
Shader "URP/MultiLightShadow"
{
Properties
{
_Diffuse("Diffuse", Color) = (1, 1, 1, 1)
}
SubShader
{
Pass
{
Tags
{
"RenderType" = "Opaque"
"RenderPipeline" = "UniversalPipeline"
"LightMode" = "UniversalForward"
}
HLSLPROGRAM
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
float4 _Diffuse;
// 接收阴影所需关键字
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile _ _SHADOWS_SOFT
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attributes
{
float4 positionOS: POSITION;
};
struct Varyings
{
float4 positionCS: POSITION;//或者 SV_POSITION
float3 positionWS: TEXCOORD0;
};
Varyings vert(Attributes v)
{
Varyings o;
// 获取不同空间下坐标信息
VertexPositionInputs positionInputs = GetVertexPositionInputs(v.positionOS.xyz);
o.positionCS = positionInputs.positionCS;
o.positionWS = positionInputs.positionWS;
return o;
}
half4 frag(Varyings input) : SV_Target
{
// 获取阴影坐标
float4 shadowCoord = TransformWorldToShadowCoord(input.positionWS.xyz);
//使用HLSL的函数获取主光源数据
Light mainLight = GetMainLight(shadowCoord);
half3 diffuse = mainLight.color * mainLight.distanceAttenuation * mainLight.shadowAttenuation * _Diffuse
.rgb;
return half4(diffuse, 1.0);
}
ENDHLSL
}
}
FallBack "Packages/com.unity.render-pipelines.universal/FallbackError"
}
阴影投射
AES 新建一个PBR Shader,拷过去即可
最简单的阴影投射
//下面计算阴影的Pass可以直接通过使用URP内置的Pass计算
//UsePass "Universal Render Pipeline/Lit/ShadowCaster"
// or
// 计算阴影的Pass
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
Cull Off
ZWrite On
ZTest LEqual
HLSLPROGRAM
// 设置关键字
#pragma shader_feature _ALPHATEST_ON
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
float3 _LightDirection;
struct Attributes
{
float4 positionOS: POSITION;
float3 normalOS: NORMAL;
};
struct Varyings
{
float4 positionCS: SV_POSITION;
};
// 获取裁剪空间下的阴影坐标
float4 GetShadowPositionHClips(Attributes input)
{
float3 positionWS = TransformObjectToWorld(input.positionOS.xyz);
float3 normalWS = TransformObjectToWorldNormal(input.normalOS);
// 获取阴影专用裁剪空间下的坐标
float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection));
// 判断是否是在DirectX平台翻转过坐标
#if UNITY_REVERSED_Z
positionCS.z = min(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
#else
positionCS.z = max(positionCS.z, positionCS.w * UNITY_NEAR_CLIP_VALUE);
#endif
return positionCS;
}
Varyings vert(Attributes input)
{
Varyings output;
output.positionCS = GetShadowPositionHClips(input);
return output;
}
half4 frag(Varyings input): SV_TARGET
{
return 0;
}
ENDHLSL
}