本文共 4771 字,大约阅读时间需要 15 分钟。
目录
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 } }}
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---------------------更新(验证一些内置变量)
位于UnityShaderVariables.cginc的一个内置变量float4
点光源位置:_LightPositionRange.xyz
_LightPositionRange.w是Range的倒数 (0.027),我发现这些数值是进行了四舍五入的(即精度会丢失)
位于UnityShaderVariables.cginc的内置变量float4类型,其中只发现了x分量是光源的Bias值
至于yzw分量,还未知(留坑)
关于Light的Bias介绍另起一文解释:(留链接坑)
转载地址:http://jrucz.baihongyu.com/