shader 反射 水面_Unity海洋shader笔记①

本文介绍了在Unity中创建海洋水效渲染的Shader实现过程,包括使用Gerstner波形叠加生成水面波浪,以及水面颜色的渲染,涉及反射、折射、菲涅尔效应等。作者通过详细步骤展示了如何处理反射、折射分量,以及添加高光和次表面散射效果,同时讨论了实时性能优化和未来可能的改进方向,如LOD和水下效果。
摘要由CSDN通过智能技术生成

不久前玩了神秘海域4和盗贼之海,对游戏中形状生动颜色通透的大海产生了兴趣,于是开始查着资料学习自己动手写一个海洋的水效渲染。这个shader基本是边学边写的,编写过程中我学到了很多新的知识。

目前的效果:

2b0e3f7f15b4?utm_campaign=maleskine

2b0e3f7f15b4?utm_campaign=maleskine

2b0e3f7f15b4?utm_campaign=maleskine

波形

主要参考了GPU Gems的Chapter 1。

Chapter 1. Effective Water Simulation from Physical Models

实时水面模拟与渲染

海面波形是由多个不同频率分量单个波形叠加起来的,相对较为真实的方法是对真实采样的海面波形做FFT得到一个二维频谱,再在应用程序中通过IFFT还原为水波的高度数据。不过在此我还是先使用一种较为简单并且能直观地在GPU中计算的叠加Gerstner波的方法。使用这种波顶点会不仅有高度分量y的变化,同时在xz平面也会有一定的位移,我们在控制xz平面顶点位移大小的同时也控制了波峰是尖还是平缓。

Shader中我使用了12种不同波长,每种波长的分量是6个方向不同的同频率波的叠加,于是最后用72个波的叠加得到了目前的效果。

水面颜色渲染

总体上来讲我们将得到的颜色分为反射分量,折射分量以及加性的高光分量,折射和反射分量的比重用菲涅尔效应的公式计算。这里采用了一种快速菲涅尔方法:

float R_0 = (_AirRefractiveIndex - _WaterRefractiveIndex) / (_AirRefractiveIndex + _WaterRefractiveIndex);

R_0 *= R_0;

return R_0 + (1.0 - R_0) * pow((1.0 - saturate(dot(I, N))), _FresnelPower);

反射分量

在应用了波形和法线贴图后,海水的表面就不再是镜面,因此完全正确的反射颜色就不再是镜面反射。当然我们仍然可以计算正确反射的天空盒子颜色,但是由于这里采样的只有天空盒子于是其他物体便不会出现在反射中。然而正确不是首要考虑的因素,在这里我仍然使用了镜面反射的反射贴图。

获取镜面贴图的方式非常直观,直接在当前相机关于水平面的对称位置再生成一个(视线也对称)相机采样即可。注意这里为了只正确反射水面上的物体,我们需要将对生成的对称相机的近端裁剪平面修改为水面。在脚本中使用cam.CalculateObliqueMatrix(clipPlane)可以得到以clipPlane(clipPlane参考系是观察空间)为近端裁剪平面的相机投影矩阵,然后再设置相机投影矩阵为得到的这个矩阵即可。具体运算较为复杂,我参考了斜视

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值