【Shader进阶】Pass块的Tags标签——LightMode之ShadowCaster

目录

一、效果图和Shader

二、ShadowCaster讲解

_LightPositionRange

unity_LightShadowBias

2020年5月5日00:02:45更新:补坑Bias介绍


一、效果图和Shader

Shader "Unlit/ShadowCasterTest"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
		_Color("Color", Color) = (1,1,1,1)
	}
	SubShader
	{
		Tags { "RenderType" = "Opaque" }
		LOD 100

		Pass
		{
			Tags
			{
				"LightMode" = "ForwardBase"
			}
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag			
			#pragma multi_compile_fwdbase

			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 pos : SV_POSITION;
				float3 normal : NORMAL;
				float4 worldPos : TEXCOORD1;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _Color;

			v2f vert(appdata v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				o.normal = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				fixed3 normal = normalize(i.normal);
				fixed3 lightDir = UnityWorldSpaceLightDir(i.worldPos.xyz);
				fixed3 albedo = col.rgb * UNITY_LIGHTMODEL_AMBIENT.xyz * _Color.rgb;  //纹理颜色 环境颜色 自定义颜色混合
				fixed3 diff = albedo * _LightColor0.rgb * saturate(dot(normal, lightDir));//再混合平行光颜色 进行漫反射系数相乘
				return fixed4(diff, 1);
			}
			ENDCG
		}
		//投射阴影的Pass 即本章节主题:ShadowCaster
		Pass
		{
			Tags{
				"LightMode" = "ShadowCaster"
			}
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_shadowcaster

			#include "UnityCG.cginc"

			struct appdata {
				float4 vertex : POSITION;
				float4 uv : TEXCOORD0;
			};

			struct v2f {
				V2F_SHADOW_CASTER;
			};

			v2f vert(appdata v) {
				v2f o;
				TRANSFER_SHADOW_CASTER(o);
				return o;
			}
			fixed4 frag(v2f i) : SV_Target {
				SHADOW_CASTER_FRAGMENT(i)
			}
			ENDCG
		}
	}
}

二、ShadowCaster讲解

1、LightMode="ShadowCaster" 
把物体的深度信息渲染到阴影映射纹理(shadowmap)或一张深度纹理中

2、#pragma_compile_shadowcaster (未知,留坑)                

3、V2F_SHADOW_CASTER
它是一个在UnityCG.cginc声明的宏,作用是声明投射阴影所需的参数,如下:

// Declare all data needed for shadow caster pass output (any shadow directions/depths/distances as needed),
// plus clip space position.
#define V2F_SHADOW_CASTER V2F_SHADOW_CASTER_NOPOS UNITY_POSITION(pos)

有两种情况:①当投射阴影是相对于点光源时 ②相对于其他光源时(如平行光和聚光灯)
①:#define V2F_SHADOW_CASTER_NOPOS float3 vec : TEXCOORD0;
②:#define V2F_SHADOW_CASTER_NOPOS
是的,你没看错,②的情况是一个空的宏。那么①声明的float3 vec是什么?后面解释。
UNITY_POSITION(pos):float4 pos : SV_POSITION; 

4、TRANSFER_SHADOW_CASTER(o);  // o是指v2f类型的对象,即顶点着色器的输出结构体(片元着色器的输入结构体)

// Vertex shader part, legacy. No support for normal offset shadows - because
// that would require vertex normals, which might not be present in user-written shaders.
#define TRANSFER_SHADOW_CASTER(o) TRANSFER_SHADOW_CASTER_NOPOS_LEGACY(o,o.pos)

 它是一个在UnityCG.cginc声明的宏,作用于没有法线偏移的阴影情况下。同样有①和②情况(同上)
①:#define TRANSFER_SHADOW_CASTER_NOPOS_LEGACY(o,opos)
o.vec = mul(unity_ObjectToWorld, v.vertex).xyz - _LightPositionRange.xyz;
opos = UnityObjectToClipPos(v.vertex);
②:#define TRANSFER_SHADOW_CASTER_NOPOS_LEGACY(o,opos) 
        opos = UnityObjectToClipPos(v.vertex.xyz); 
        opos = UnityApplyLinearShadowBias(opos);

//暂时还未看懂,日后再理清
float4 UnityApplyLinearShadowBias(float4 clipPos)
{
#if defined(UNITY_REVERSED_Z)
    // We use max/min instead of clamp to ensure proper handling of the rare case
    // where both numerator and denominator are zero and the fraction becomes NaN.
    clipPos.z += max(-1, min(unity_LightShadowBias.x / clipPos.w, 0));
    float clamped = min(clipPos.z, clipPos.w*UNITY_NEAR_CLIP_VALUE);
#else
    clipPos.z += saturate(unity_LightShadowBias.x/clipPos.w);
    float clamped = max(clipPos.z, clipPos.w*UNITY_NEAR_CLIP_VALUE);
#endif
    clipPos.z = lerp(clipPos.z, clamped, unity_LightShadowBias.y);
    return clipPos;
}

5、SHADOW_CASTER_FRAGMENT(i)
它是一个在UnityCG.cginc的宏,参数是v2f类型,如下:

①:#define SHADOW_CASTER_FRAGMENT(i) return UnityEncodeCubeShadowDepth ((length(i.vec) + unity_LightShadowBias.x) * _LightPositionRange.w);

float4 UnityEncodeCubeShadowDepth (float z)
{
    #ifdef UNITY_USE_RGBA_FOR_POINT_SHADOWS
    return EncodeFloatRGBA (min(z, 0.999));
    #else
    return z;
    #endif
}

②:#define SHADOW_CASTER_FRAGMENT(i) return 0;

这里可以看出来,点光源的情况是光源和顶点的向量长度与阴影深度值成正比关系,其他两个系数暂且未知(留坑)
unity_LightShadowBias:  光源的Bias参数值(其作用下方解释)
_LightPositionRange:  xyz = pos, w = 1/range xyz是点光源位置xyz, w是点光源影响半径倒数。(下方验证)

 从这里你已经隐约猜测到,点光源的奇葩情况如下动态图:

 

结论:点光源离物体越远阴影越明显,聚光灯离物体越近阴影越明显 

-------------------2020年4月26日15:36:36---------------------更新(验证一些内置变量)

_LightPositionRange

位于UnityShaderVariables.cginc的一个内置变量float4

点光源位置:_LightPositionRange.xyz 

_LightPositionRange.w是Range的倒数 (0.027),我发现这些数值是进行了四舍五入的(即精度会丢失)

unity_LightShadowBias

位于UnityShaderVariables.cginc的内置变量float4类型,其中只发现了x分量是光源的Bias值

 

至于yzw分量,还未知(留坑)

关于Light的Bias介绍另起一文解释:(留链接坑)

2020年5月5日00:02:45更新:补坑Bias介绍

https://blog.csdn.net/qq_39574690/article/details/105772719

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值