《Unity Shader》11.3.1 续 流动的水流的阴影

本书资源的Scene_11_3_3场景中,我们给出了计算顶点动画的阴影的一个例子。在这个例子中,我们使用了11.3.1节中的大部分代码,模拟一个波动的水流。同时,我们开启了场景中平行光的阴影效果,并添加了一个平面来接收来自"水流"的阴影。

将 Scene_11_3_1另存为 Scene_11_3_3

创建一个Plane,用于接受水流的"阴影"

打开 cast shadows 和 receive shadows

新建一个 Chapter11-VertexAnimationWithShadow.shader

https://github.com/candycat1992/Unity_Shaders_Book/blob/master/Assets/Shaders/Chapter11/Chapter11-VertexAnimationWIthShadow.shader

把 Chapter11-Water.shader 的主代码复制到 Chapter11-VertexAnimationWithShadow.shader 中,再添加 ShadowCaster 的 Pass。

cs 复制代码
Shader "Custom/Chapter11-VertexAnimationWithShadow"
{
    Properties {
        _MainTex ("Main Tex", 2D) = "white" {} //_MainTex是河流纹理
        _Color ("Color Tint", Color) = (1, 1, 1, 1)
        _Magnitude ("Distortion Magnitude", Float) = 1 //_Magnitude用于控制水流波动的幅度
        _Frequency ("Distortion Frequency", Float) = 1 //_Frequency用于控制波动频率
        _InvWaveLength ("Distortion Inverse Wave Length", Float) = 10 //_InvWaveLength用于控制波长的倒数(_InvWaveLength越大,波长越小)
        _Speed ("Speed", Float) = 0.5 //_Speed用于控制河流纹理的移动速度。
    }

    Subshader {
        // Need to disable batching because of the vertex animation
		Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True"}
        //包含了模型空间的顶点动画的Shader,需要取消对该Shader的批处理操作
        Pass {
            Tags { "LightMode"="ForwardBase" }
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off //关闭了深度写入,开启并设置了混合模式,并关闭了剔除功能,渲染所有面(双面渲染)。这是为了让水流的每个面都能显示

            CGPROGRAM  
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc" 
            
            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Color;
            float _Magnitude;
            float _Frequency;
            float _InvWaveLength;
            float _Speed;

            struct a2v {
                float4 vertex : POSITION;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            v2f vert(a2v v) {
                v2f o;

                float4 offset; //计算顶点位移量
                offset.yzw = float3(0.0, 0.0, 0.0); //只希望对顶点的x方向进行位移,因此yzw的位移量被设置为0
                offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
                //利用_Frequency属性和内置的_Time.y变量来控制正弦函数的频率
                //不同位置具有不同的位移,我们对上述结果加上了模型空间下的位置分量,乘以_InvWaveLength来控制波长
                //对结果值乘以_Magnitude属性来控制波动幅度,得到最终的位移。

                o.pos = UnityObjectToClipPos(v.vertex + offset); //位移量添加到顶点位置上,再进行正常的顶点变换即可。

                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.uv +=  float2(0.0, _Time.y * _Speed);  //纹理动画,即使用_Time.y和_Speed来控制在水平方向上的纹理动画

                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                fixed4 c = tex2D(_MainTex, i.uv);
                c.rgb *= _Color.rgb;
                return c;
            }
            ENDCG
        }

            // Pass to render object as a shadow caster
            Pass {
                Tags { "LightMode" = "ShadowCaster" }
                CGPROGRAM
                #pragma vertex vert
			    #pragma fragment frag

                #pragma multi_compile_shadowcaster
                #include "UnityCG.cginc"
                float _Magnitude;
                float _Frequency;
                float _InvWaveLength;
                float _Speed;

                struct v2f { 
                     V2F_SHADOW_CASTER;
                };

                v2f vert(appdata_base v) {
                    v2f o;
                    float4 offset;
                    offset.yzw = float3(0.0, 0.0, 0.0);
                    offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
                    v.vertex = v.vertex + offset;

                    TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
                    return o;
                }

                fixed4 frag(v2f i) : SV_Target {
                    SHADOW_CASTER_FRAGMENT(i)
                }
                ENDCG
            }
    }
    FallBack "VertexLit"
}

创建 VertexAnimationWithShadow.mat,把 Chapter11-VertexAnimationWithShadow赋给 mat,main tex 用和 WaterMat.mat 一样的

调整面板

参数和 WaterMat.mat 一样

在光源的Light组件中开启阴影,选择软阴影

把 VertexAnimationWithShadow 赋给 water_full

打开 cast shadows 和 receive shadows

调整main camera 的视野大小和位置,可以看到阴影

相关推荐
咸鱼永不翻身1 小时前
Unity视频资源压缩详解
unity·游戏引擎·音视频
在路上看风景1 小时前
4.2 OverDraw
unity
在路上看风景2 小时前
1.10 CDN缓存
unity
ellis197011 小时前
Unity插件SafeArea Helper适配异形屏详解
unity
nnsix12 小时前
Unity Physics.Raycast的 QueryTriggerInteraction枚举作用
unity·游戏引擎
地狱为王13 小时前
Cesium for Unity叠加行政区划线
unity·gis·cesium
小贺儿开发21 小时前
Unity3D 八大菜系连连看
游戏·unity·互动·传统文化
在路上看风景1 天前
25. 屏幕像素和纹理像素不匹配
unity
ۓ明哲ڪ1 天前
Unity功能——创建新脚本时自动添加自定义头注释
unity·游戏引擎
熬夜敲代码的小N1 天前
Unity大场景卡顿“急救包”:从诊断到落地的全栈优化方案
java·unity·游戏引擎