當前位置:編程學習大全網 - 源碼下載 - 地鐵跑酷場景為什麽不能彎曲

地鐵跑酷場景為什麽不能彎曲

來自專欄CRLuo的Shader基礎知識

大場景,遠處景物的閃現會很讓遊玩的玩家出戲。

地鐵跑酷和動森用了不同的方式來抵消這種問題。

之前的內容

UnityShader 基礎(21)-空間漸變-距離剔除透明

介紹了如何利用空間位置“o.WordPos” 進行顏色著色。

這壹節在頂點片段中 修改 "o.vertex”模型坐標數據就可以改變模型形狀。

之前的地鐵跑酷遊戲

整個場景其實是壹條直線,道路的左右彎道,上下坡道,是用Shader彎曲模型頂點做到的。

首先創建兩個控制屬性

_SwerveX("左右彎道", Range(-0.01,0.01)) = 0.0 _SwerveY("上坡下破", Range(-0.01,0.01)) = 0.0

在頂點片段中加入以下修改頂點程序,總***分3步

第壹步,首先把模型空間頂點,轉為世界空間頂點

//獲取模型的空間坐標 float3 WordPos = mul(unity_ObjectToWorld, v.vertex); //----左右坐標作為彎道 ---- //依據Z坐標求平方獲取彎曲曲線,越遠離世界坐標原點,彎曲效果越明顯。 //最後乘以左右彎道彎曲方向,和彎曲強度 WordPos.x +=pow(WordPos.z, 2)*_SwerveX; //方法與上面相同,改變Y軸,獲得上下坡效果 WordPos.y += pow(WordPos.z, 2)*_SwerveY;

第二步,在模型空間下,依據空間坐標修改頂點

//修正模型位置,WordPos 不包含物體自身的空間位移 WordPos -= mul(unity_ObjectToWorld, float4(0, 0, 0, 1));

第三步把修改結果轉回模型空間,修改原始模型數據。

//修改世界頂點轉回物體自身頂點。 v.vertex = mul(unity_WorldToObject, WordPos);

使用效果:

動態效果:

Shader代碼

Shader "CRLuo/CRLuo_Teaching38_Vertex_PathBend_Base" { Properties { _MainTex ("顏色紋理", 2D) = "white" {} _SwerveX("左右彎曲程度", Range(-0.003,0.003)) = 0.0 _SwerveY("上下彎曲程度", Range(-0.003,0.003)) = 0.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; //獲取模型第壹套UV float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; UNITY_FOG_COORDS(4) }; //顏色紋理 sampler2D _MainTex; float _SwerveX; float _SwerveY; v2f vert (appdata v) { v2f o; o.uv = v.uv; //獲取模型的空間坐標 float3 WordPos = mul(unity_ObjectToWorld, v.vertex); //左右左右坐標作為彎道 //依據Z坐標求平方獲取彎曲曲線,越遠離世界坐標原點,彎曲效果越明顯。 //最後乘以左右彎道彎曲方向,和彎曲強度 WordPos.x +=pow(WordPos.z, 2)*_SwerveX; //方法與上面相同,改變Y軸,獲得上下坡效果 WordPos.y += pow(WordPos.z, 2)*_SwerveY; //修正模型位置,WordPos 不包含物體自身的空間位移 WordPos -= mul(unity_ObjectToWorld, float4(0, 0, 0, 1)); //修改世界頂點轉回物體自身頂點。 v.vertex = mul(unity_WorldToObject, WordPos); //轉換為裁切空間 o.vertex = UnityObjectToClipPos(v.vertex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { //獲取顏色貼圖 fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }

動物森友會使用的類似球形的地圖,來抵消模型的突然出現。

可以使用X和Z軸坐標來影響模型點Y的位置。

核心代碼就是

WordPos.x +=pow(WordPos.z, 2)*_SwerveX; WordPos.y += pow(WordPos.z, 2)*_SwerveY;

替換為

//Y軸扭 = 曲依據XZ坐標變化 WordPos.y -= pow(WordPos.x, 2)*_BendY; WordPos.y -= pow(WordPos.z, 2)*_BendY;

使用效果:

動態效果

Shader代碼

Shader "CRLuo/CRLuo_Teaching39_Vertex_WorldBend_Base" { Properties { [NoScaleOffset] _MainTex ("顏色紋理", 2D) = "white" {} _BendY("彎曲程度", Range(0,0.01)) = 0.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; //獲取模型第壹套UV float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; //定義頂點世界變量 float4 WordData : TEXCOORD1; float4 vertex : SV_POSITION; UNITY_FOG_COORDS(4) }; //顏色紋理 sampler2D _MainTex; float _BendY; v2f vert (appdata v) { v2f o; o.uv = v.uv; float3 WordPos = mul(unity_ObjectToWorld, v.vertex); //獲取Y軸坐標 o.WordData.x = WordPos.y; //Y軸扭 = 曲依據XZ坐標變化 WordPos.y -= pow(WordPos.x, 2)*_BendY; WordPos.y -= pow(WordPos.z, 2)*_BendY; //獲取位移位置 WordPos -= mul(unity_ObjectToWorld, float4(0, 0, 0, 1)); //修改世界頂點轉回物體自身頂點。 v.vertex = mul(unity_WorldToObject, WordPos); //轉換為裁切空間 o.vertex = UnityObjectToClipPos(v.vertex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { //獲取顏色貼圖 fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }

後記:

這裏使用了最簡單粗暴的平方曲線來模擬圓弧,

後面會討論更多的曲線公式與算法。

  • 上一篇:求壹個魔獸爭霸關於建築物無限血(無敵)的密碼
  • 下一篇:有沒有好看的小說 最好是古代的 文筆流暢 大氣壹點的
  • copyright 2024編程學習大全網