如果你之前是用buildin pipeline写的shader,其中用了SHADOW_ATTENUATION宏的话,在URP下会失效。
由于官方文档对自定义shader描述不多,所以自己只能去看URP内建的shader源码去看实现方法。
但是URP内建的shader都是用HLSLPROGRAM和ENDHLSL来写的,并且引用文件都是.hlsl。
和之前的CGPROGRAM,还有引用文件类型.cginc有所不同。
所以,如果想引用URP内建的方法和接口,必须得按照它们现在的方式来写。
但经师傅指点,我看到了Unity官方的这一段话:
原来我们一直都是用HLSL来写的shader,并非是cg语言,只是keywords和文件引用没改成HLSL方式的。
所以我们要直接改成HLSL方式的shader还是比较友好的。
具体的操作方法是:
首先把我们的CGPROGRAM、ENDCG分别改成HLSLPROGRAM和ENDHLSL。
接着把#include "UnityCG.cginc"等文件引用改成
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"这种方式,
具体要引用哪些文件,要自己去
Editor\Data\Resources\PackageManager\Editor\com.unity.render-pipelines.universal-7.3.1
目录下,解压包,看具体想引用哪个文件,再把相对路径写上去。
上面只是把cg的方式改成HLSL的方式,下面是具体实现urp的阴影方法:
首先,我看到了这一篇文章:
要写入 ShadowMap,shader必须有 ShadowCaster 这个Pass。
2021年1月28日更新:
加入下面这句代码即可。使用URP自带的ShadowCaster。
UsePass "Universal Render Pipeline/Lit/ShadowCaster"
或者
所以我在shader里加入了这一个pass:
pass {
Tags{ "LightMode" = "ShadowCaster" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 pos : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
return o;
}
float4 frag(v2f i) : SV_Target
{
float4 color;
color.xyz = float3(0.0, 0.0, 0.0);
return color;
}
ENDHLSL
}
确实地面的投影就出现了(地面的shader是URP内建的Lit):
但物体上自己没有阴影,是因为原来的SHADOW_ATTENUATION失效了。
在URP的源代码的upgrade-guide-7-2-0.md文档里,有提到这么一段话:
我翻译一下,就是如果有自定义的shader,想去采样Shadermap贴图,可以用举例的方法:
float4 SHADOW_COORDS = TransformWorldToShadowCoord(i.worldPos);
Light mainLight = GetMainLight(SHADOW_COORDS);
half shadow = mainLight.shadowAttenuation;
要让以上方法生效,必须定义以下的宏:
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
好,物体上的阴影也出现了。效果可以当然可以再调整下,毕竟
half shadow = mainLight.shadowAttenuation;只是个0-1的值,表现还是自己想办法去做过渡之类的。
但是有个问题,这个阴影有锯齿。具体如何解决呢,欢迎大家讨论。我也会想办法解决。
代码例子如下:
Shader "Custom/ToonGroundExam"
{
Properties
{
_MainTex("主贴图", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType" = "Transparent" "Queue" = "Transparent" }
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
Tags
{
"LightMode" = "UniversalForward"
}
Zwrite off
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ Anti_Aliasing_ON
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct appdata
{
float4 vertex : POSITION;
float4 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
float4 _Color;
float4 frag(v2f i) : SV_Target
{
float4 SHADOW_COORDS = TransformWorldToShadowCoord(i.worldPos);
Light mainLight = GetMainLight(SHADOW_COORDS);
half shadow = MainLightRealtimeShadow(SHADOW_COORDS);
return float4(shadow, shadow, shadow,1);
}
ENDHLSL
}
pass {
Name "ShadowCast"
Tags{ "LightMode" = "ShadowCaster" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 pos : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert(appdata v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
float4 frag(v2f i) : SV_Target
{
float4 color;
color.xyz = float3(0.0, 0.0, 0.0);
return color;
}
ENDHLSL
}
}
}