博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Shader进阶】Pass块的Tags标签——LightMode之ShadowCaster
阅读量:541 次
发布时间:2019-03-07

本文共 4771 字,大约阅读时间需要 15 分钟。

目录


一、效果图和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介绍

转载地址:http://jrucz.baihongyu.com/

你可能感兴趣的文章