最近遊戲《對馬島之魂》發售了。
其中的草地特動效十分先進:
(來自網路)
於是我也萌生了寫乙個動態草地的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需要乘上之前算出的windx
和windy
以使取樣偏移和風向相同。
取樣出的值作為新的風強度來影響頂點。
//隨機飄動+定向波浪(雜訊紋理版本)
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有自動快取的功能,當...