unity3d 制造自己的水體water effect(二)


前篇:unity3d 制造自己的水體water effect(一)

曲面細分:Unity3d 使用DX11的曲面細分

PBR:

講求基本算法

Unity3d 基於物理渲染Physically-Based Rendering之specular BRDF

plus篇

Unity3d 基於物理渲染Physically-Based Rendering之實現
最終篇
Unity3d 基於物理渲染Physically-Based Rendering之最終篇
 

之前一直在用unity4.6寫shader,終於下定決心換unity5,然后發現,unity5的渲染比4強太多,
這次完成之前2月份自制拖着沒解決的normal問題,算出normal真的很簡單。
本次水體分別使用兩種波動算法,一個是ShaderX6 中Szecsi 和 Arman的算法,另一個是Gpu gems1里的Gerstner波算法。然后再用PBR渲染。然后還是曲面細分。
這次的效果:


Szecsi & Arman波動算法

首先來看ShaderX6 中的波動算法:
求波動速度,λ為波長,波長就是波峰到波峰之間的距離,速度v為每秒鍾波峰移動的距離。
    
然后是相函數,k為波動方向,運動方向,垂直於波陣面的水平方向,p為position,t為時間(_Time.y)
 
求得一個波的位移S,a為振幅,振幅就是從水平面到波峰的高度。
 

最終我們的水是多個波組合在一起的,所以最終結果為:
    

 

 

博主整共合了4個波

關鍵代碼如下:

                               vv = sqrt(_G * _Lambda / (2 * _PIE));
				psi = 2 * _PIE / _Lambda *(dot(v.vertex.xyz, _K.xyz) + vv*_Time.y);
				s = lerp(-cos(psi), sin(psi), _A)*0.05;
				p.y += s;
				vv = sqrt(_G * _Lambda2 / (2 * _PIE));
				psi = 2 * _PIE / _Lambda2 *(dot(v.vertex.xyz, _K2.xyz) + vv*_Time.y);
				s = lerp(-cos(psi), sin(psi), _A2)*0.05;

				p.y += s;

				vv = sqrt(_G * _Lambda3 / (2 * _PIE));
				psi = 2 * _PIE / _Lambda3 *(dot(v.vertex.xyz, _K3.xyz) + vv*_Time.y);
				s = lerp(-cos(psi), sin(psi), _A3)*0.1;

				p.y += s;

				vv = sqrt(_G * _Lambda4 / (2 * _PIE));
				psi = 2 * _PIE / _Lambda4 *(dot(v.vertex.xyz, _K4.xyz) + vv*_Time.y);
				s = lerp(-cos(psi), sin(psi), _A4)*0.1;

				p.y += s;

				v.vertex.xyz = p.xyz;</span>



 

 

 

 

產生了波動效果:




加上之前的pbr,可以模擬各種液體

牛奶

血,等等



但是由於曲面細分,離近了看水面上還是有小面的細節,這點有待解決。

Gerstner波

然后Gerstner波

 

關鍵代碼如下:

  float wave(float x, float z, float timer)  
    {  
        float y = 0;  
        float oct = _OCT;  
        float fac = _FAC;  
        float d = sqrt(x * x + z * z);// length(float2(x, z));  
        for (oct; oct>0; oct--)  
        {  
            y -= fac * cos(timer * _SP + (1 / fac) * x * z * _WS);  
            fac /= 2;  
      
        }  
        return 2 * _VS * d * y;  
      
    }  </span>

 

 

 

曲面細分帶來的小面不是很明顯,而且面不用分得很細就能看到平滑的效果

normal的生成

最后我們講講normal的生成,
Normal的生成有復雜的和簡單的,但本質上都是求偏導。
先看復雜的,來自GPU Gems1的42章
首先求出Jacobian
 




舉個例子(直接截圖了^ _ ^):
 
 
是不是很麻煩。。

法線本質上的求法就是這樣的,但是,我們有函數:ddx,ddy這兩個神器
我們只需要求出世界坐標點,worldpos
就可以簡單地求出法線:
N = cross(ddx(worldpos),ddy(worldpos))
方法很簡單,不過別忘記,本質上還是上面的一大串。。。
切記:ddx,ddy只能在fragment shader中使用。

只有漫反射的水體如下:

 

                            --------   by wolf96 、

 

 


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM