码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-09-14 08:17:35      阅读:301      评论:0      收藏:0      [点我收藏+]

标签:unity3d   水体渲染   ocean   海洋渲染   

前篇: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个波

关键代码如下:

                               <span style="font-size:14px;"> 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波

 技术分享

关键代码如下:

<span style="font-size:14px;">    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  http://blog.csdn.net/wolf96


技术分享




版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:unity3d   水体渲染   ocean   海洋渲染   

原文地址:http://blog.csdn.net/wolf96/article/details/48434497

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!