王者荣耀地图资源

随风飘摇的小草

Posted by Bob on October 25, 2018

细草微风岸,危樯独夜舟 —— 唐 · 杜甫《旅夜书怀》

吟诗一首,再欣赏一下细草微风渲染效果。 没有录制一个完整循环,抖了一下,附送:Gif录制工具

image

王者荣耀整个地图植被只用了一张512px的Alpha贴图

image

一小块草mesh包含了uv和color,这里color是用来控制权重。

image

把color信息bebug渲染出来(开启下面shader注释color的二行), 可看出草的根部和顶部的摆动权重就是一个0到1的线性的变化,每根草的权重还有一定随机,仅仅用alpha通道来描述。如果做更复杂树的运动,可以R来主干运动,G树叶运动,B树枝运动。 image

草的沿着y轴生长,草的根部是y轴原点保持不动,y轴值越大,运动幅度越大(color.w),然后沿着x和z轴再做一个往复运动,这样就简单模拟出草的摇摆运动,说白了就是一个顶点动画。

image

往复运动,这里用一个正弦波实现。

image

正弦曲线公式可表示为y=Asin(ωx+φ)+k: A,振幅,最高和最低的距离,纵向拉伸压缩的倍数 ω,角速度,用于控制周期大小,单位x中的起伏个数 K,偏距,曲线整体上下偏移量 φ,初相,决定波形与X轴位置关系或横向移动距离(左加右减)

float tv = v.color.z * 3.14;
float offetX = _MiddleX + sin(_Time.y * _XSpeed + tv) * _XPower * v.color.w;

A = _XPower:控制波动效果对整体效果的影响大小。

A_Weight = v.color.w:通过color.w刷的y轴权重,y轴上每个点运动速率有变化,叠加_XPower影响

ωx = _Time.y * _XSpeed:用于控制周期大小,_Time表示时间周期 float4(t/20, t, t2, t3)

K = _MiddleX:曲线整体上下偏移量

φ = tv:通过color.z刷的,这样草运动有一定随机,而不是统一速度摇摆。

如下脑洞分析后人工重写的shader,可能与原始游戏效果有些差异。


Shader "S_Game_Scene/Grass_SWING_NoLightmap"
{
	Properties
	{
		_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
		_Color ("Main Color", Vector) = (1,1,1,1)
		_CutOff ("AlphaTest", Range(0, 1.01)) = 0.5
		_MiddleX ("X中值", Float) = 0
		_MiddleZ ("Z中值", Float) = 0
		_XPower ("X方向摆动幅度", Float) = 1
		_ZPower ("Z方向摆动幅度", Float) = 1
		_XSpeed ("X方向摆动速度", Float) = 1
		_ZSpeed ("Z方向摆动速度", Float) = 1
		_YParam ("Y方向变化比例", Float) = 0.4
	}
	SubShader
	{
		Tags { "QUEUE" = "Transparent" "RenderType" = "Transparent" }
		LOD 100
		ZWrite Off
		Blend SrcAlpha OneMinusSrcAlpha

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			// make fog work
			#pragma multi_compile_fog
			
		
 
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float4 color : COLOR;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				UNITY_FOG_COORDS(1)
				float4 vertex : SV_POSITION;
				//float4 color : COLOR;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			
			fixed4 _Color;
			float _Cutoff;

			float _MiddleX;
			float _MiddleZ;
			float _XPower;
			float _ZPower;
			float _XSpeed;
			float _ZSpeed;
			float _YParam;

			
			v2f vert (appdata v)
			{
				v2f o;
				float4 modPos = float4(0, 0, 0, 0);
				float tv = v.color.z * 3.14;
				modPos.x =  (v.vertex.x + ((_MiddleX + (sin(((_Time.y * _XSpeed) + tv)) * _XPower)) * v.color.w));
				modPos.z =  (v.vertex.z + ((_MiddleZ + (sin(((_Time.y * _ZSpeed) + tv)) * _ZPower)) * v.color.w));
				modPos.y = (v.vertex.y - (sqrt((((modPos.x - v.vertex.x) * (modPos.x - v.vertex.x)) + ((modPos.z - v.vertex.z) * (modPos.z - v.vertex.z)))) * _YParam));
				o.vertex = UnityObjectToClipPos(modPos);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				//o.color = v.color;
				UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}

			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv)*_Color;
				clip(col.a - _Cutoff);
				//col = i.color;
				// apply fog
				UNITY_APPLY_FOG(i.fogCoord, col);
				return col;
			}
			ENDCG
		}
	}
}


属性上主要是x轴和z轴的运动幅度、速度控制

image

通过这个原理可以拓展出水面波纹、旗帜飘扬效果,以后再介绍吧~