動態草地的Shaderlab實現方法

2021-10-08 21:23:34 字數 3883 閱讀 7837

最近遊戲《對馬島之魂》發售了。

其中的草地特動效十分先進:

(來自網路)

於是我也萌生了寫乙個動態草地的shader

現如今的許多手遊甚至端遊的草地考慮到硬體消耗,常常把草做成星形或者廣告牌草地

(來自網路)

但是這樣的草地很容易露出破綻,效果也不是特別好,於是這裡我讓每根草都擁有單獨的模型。

實際上更好的方法是做多段的長方形,然後使用mask貼圖指定草地形狀,這樣可以使草地形狀更加圓潤。

完成單個草模型後視情況調整、套用這篇文章中的maya指令碼製作出草叢簇。完成模型的製作。

草地的動態效果初步分為兩個部分:

1、取樣乙個白噪音貼圖通過偏移uv的方式實現草地頂點的隨機抖動

2、根據頂點位置實現草地的波浪

如上面所說,我們先搞乙個四通道的白雜訊貼圖(rgba通道均由白雜訊隨機生成,實際上我們只會任意使用其中兩個通道,甚至乙個)然後用頂點位置+_time作為uv。_windpow為強度控制屬性

float2 samplepos = worldpos.xz / _windpow + _time.x;

fixed4 noisesample = tex2dlod(_noise,float4(samplepos,0,0));

頂點x、y軸的位移函式為

worldpos.x +=_windpow *noisesample.x*v.uv.y;

worldpos.z +=_windpow *noisesample.y*v.uv.y;

我們用兩個取樣出的雜訊分別疊加進入x,y軸中,乘上uv.y是為了

對不同高度的頂點區別處理,讓草尖抖動大於草根。

由於抖動幅度小,這裡暫時不處理頂點y軸。減少運算。

草地的波浪做了兩個版本:

乙個版本是使用正弦函式模擬草地波浪;

第二個版本取樣乙個波浪灰度圖模擬草地波浪;

1、直接使用正弦函式模擬波浪

首先,引入乙個_winddir屬性,用於表示風方向,範圍在0~2π(6.28)中,然後轉為方向

//從方向轉為xy值

half windx = cos(_winddir);

half windy = sin(_winddir);

新的頂點位移函式為:

//下面是無noise波浪方案

worldpos.x +=noisewindpow*noisesample.x*_windpow*v.uv.y/6

+(sin(6*_time.y*_windpow+(windx*worldpos.y+windy*worldpos.z))+1.3)*0.3f*_windpow*windx*v.uv.y;

worldpos.z +=noisewindpow*noisesample.y*_windpow*v.uv.y/6

+(sin(6*_time.y*_windpow+(windx*worldpos.y+windy*worldpos.z))+1.3)*0.3f*_windpow*windy*v.uv.y;

o.col = (sin(6*_time.y*_windpow+windx*worldpos.x+windy*worldpos.z)+1.0)*0.2f;

worldpos.y -= o.col*v.uv.y;

波浪函式增加在之前的隨機飄動函式後(其中所有的數字都是可調的)

在sin函式內6*_time.y*_windpow影響波浪速度,windx*worldpos.y+windy*worldpos.z決定波浪方向。

sin函式外所有數值都只影響波浪強度和範圍。

由於波浪的抖動幅度大,必須要考慮草的高度。這裡也採用正弦函式模擬。方法與上面類似。這裡同時為片面著色器傳入了資料,可以為浪峰和浪谷增加色差。

下圖是效果展示:

這樣的做的波浪一旦處理大範圍草地就會顯得重複單調。所以引入使用一張灰度圖處理波浪的辦法。

2、取樣灰度圖模擬草地波浪

首先對灰度圖進行取樣:

float2 samplenoise = worldpos.xz/50-float2(windx,windy)*(_time.x/0.5+0.7)*_windpow*4;

fixed noisewindpow = tex2dlod(_windnoise,float4(samplenoise,0,0));

noisewindpow += _windpow;

samplenoise中的_time需要乘上之前算出的windxwindy以使取樣偏移和風向相同。

取樣出的值作為新的風強度來影響頂點。

//隨機飄動+定向波浪(雜訊紋理版本)

worldpos.x +=noisewindpow*noisesample.x*v.uv.y/6

+windx*(noisewindpow+1)*v.uv.y/5;

worldpos.z +=noisewindpow*noisesample.y*v.uv.y/6

+windy*(noisewindpow+1)*v.uv.y/5;

//大幅度位移過程中的高度變換

o.col = noisewindpow*0.5f;

worldpos.y -= o.col*v.uv.y;

方法與上乙個波浪相似。甚至更加簡單。

最後就是顏色、陰影接受等功能的實現,這裡就不多說了。

方法需要改進的地方:

1、首先是之前提到的可以採用mask貼圖繪製草

2、草在隨機抖動過程中會變得扭曲,也許可以用法線對頂點移動方向進行一定的限制。

以下是shader原始碼:

shader "sence/grass"

_color("color",color) = (1,1,1,1)

_noise ("noise",2d) = "white"{}

//風_windnoise("windnoise",2d) = "white"{}

_winddir("grassdirection",range(0,6.28)) = 0

_windpow("windpower",range(0,1)) = 1

}subshader

lod 100

pass

;struct v2f

;sampler2d _maintex;

sampler2d _noise;

sampler2d_float _windnoise;

float4 _maintex_st;

half _winddir;

half _windpow;

fixed4 _color;

fixed4 frag (v2f i) : sv_target

endcg}}

}

Shaderlab的基本結構

shaderlab 不區分大小寫,properties中不能加分號 shader name secondtex secondtex 2d subshader tags pass blend srcalpha oneminussrcalpha properties中 maincolor maincol...

goloader golang動態載入的實現

這裡有以前的一些思路 不過改了好多,具體還是要看 這個動態載入庫是很有意思的專案,它直接重用了golang編譯器的輸出,不需要自己寫編譯器,就能支援所有golang的語言特徵,免費使用編譯器的優化。因為這個庫只進行符號重定位,和提供runtime資訊,所有這些邏輯是很少改動的,這樣使得這個庫相容能力...

動態呼叫jQuery UI Dialog的實現方式

前陣子,為了實現動態呼叫jquery ui外掛程式 dialog,費勁腦汁,網上也找不到想要的資料,後來還是想了種方式,先將就著用吧,哈哈。問題很簡單,就是 頁面上有個鏈結 註冊 當點選註冊的時候,動態產生乙個dialog,這個實現起來也是沒問題,關鍵是jquery dialog有自動快取的功能,當...