Chango的数学Shader世界(七)水波模拟-透明水面,菲涅尔(Fresnel)效应
目的:
解析,改进,批评一个国外免费透明水面Shader,进一步了解Shader背后的物理原理。
参考:
菲涅尔反射
分析:
我将原水面Shader一再简化,从中抽取最主要的部分,忽略细枝末节,并改掉缺陷,指出不足。
简化版:
1.造型
其中,顶点偏移,也就是波的造型,是用贴图制造的,一目了然:
就是一张高度图经过4方向扰动,乘以波高度。然后它再乘上顶点法线在世界坐标系上的Z轴高度,这个莫名奇妙的操作会使得Normal朝上的顶点的波高更加高,而偏的更加低。我认为编者脑子里也不清楚,所以我修改了,直接乘以(0,0,1)。如果你的高度图只有b通道,这个(0,0,1)都不用乘。
2.Fresnel_Function
再观原材质图,你一定会注意到我们的主角,一个叫Fresnel_Function的节点。
UE4这样起名字,也真是大言不惭,一会我们会说到。
这个节点,涉及到一个现象,菲涅尔效应。国外一般不称为效应,搜索Fresnel equations。
现象倒是很简单:
对着玻璃看,越斜着看,它反射越多,越不透明,越像镜子;
正着看,反射越少,就越透明。
我们在生活中常常见到过这种现象:
(我怀疑夏天远方道路反光,也是这个原因)
总之,这是个在各个材质上都很普遍发生的现象,包括水面。
如果说我们之前的不透明水面本质就是镜子,那我们这次的透明水面本质就是玻璃。
真正的Fresnel方程比较复杂,可脱胎于麦克斯韦电磁学方程。
对于透明物体:
然而UE4的Fresnel_Function节点的方程并不根据实际。它利用视线与平面越垂直,反射越少这一点,进行了粗略模拟。这个方程也是图形学中常见的:
其中V向量是像素点到相机位置的向量,也就是光照模型中常见的View向量,与法线N起点一致。power用来控制效果,显然由于1-V·N在[0,1]间,power越大,那么越垂直于N的V的F才越大。在下图中,也就是当power越来越大,黑色会扩大,而白环会减少,慢慢收缩到最边缘那些法线十分垂直于视线的顶点上(白色为1,黑色为0):
显然这个函数可以用来做边缘光等其他特效。
那么,我们回过头来看透明水波材质。它的Fresnel节点的power赋予了5,十分接近边缘:
注意:
以下简称Fresnel_Fuction(...)为Fresnel(power)。
以下称V垂直于N的情况为“垂视”
3.金属度(Metallic)
原材质给金属度设置的是0。可以理解,因为金属材质不发生菲涅尔效应,而且金属度越高,透明金属材质越丢失BaseColor。但金属度太低,水的透明和反光也就低了一个层次。看下金属度为1的水面,按需求和风格调整即可:
(油腻的反光又出现了)
4.反光度(Specular)
反光直接给1,没什么好说的。给0就失去了波光粼粼的效果。
5.粗糙度(Roughness)
回看透明水波材质。它的粗糙度被设置为:
也就是越垂视的地方粗糙度越为0,完全光滑;其他地方为0.1,也很光滑,但较边缘差了点。
对于对面,从直觉上来说是这样,而且Roughness影响反射光计算,越光滑反射越多,符合菲涅尔效应。
实际效果上对比不明显。
6.不透明度(Opacity)
越垂视,越不透明。也符合菲涅尔效应。
7.折射率(Refraction)
在介质密度不同的表明,光发生折射。从低密度到高密度,折射角小于入射角。
回忆初高中物理,折射率定律。国外更一般叫成斯涅尔定律(Snell's Law):
由于真空密度最低,或者说真空光速最快,所以所有的材质折射率都大于1。
从真空射入某材质:
透明水波Shader认为越垂视,折射率越高,这是对的。首先直觉上,越弯曲的玻璃,折射越厉害。
其次,你可以认为空气与水折射率不变,当入射角变大,那么折射率一定要变大。
或者你可以认为折射率=c/v,在垂视的地方,光路更长,相当于v更小,所以折射率更大了。
8.风格化法线
你可能会发现我们这个水波像是三角透明玻璃组成的,十分风格化。放大之后是这样的:
原因是这个透明水波Shader的法线。
图中用了一个函数称为Shine_func,打开后发现实现十分简单,效果也和迪厅反光球一样:
关键是DDX和DDY是什么?
这个蛋疼的起名让我一开始以为是二阶导数,但明显不对。经过搜索我发现它就是屏幕空间x方向偏导数和y方向偏导数。
问题在于为什么结果它是这样的,而不是我们之前那么顺滑的连续函数。
以DDX为例,就是检查当前像素点(Pixel)在屏幕水平方向上离得最近的左右两个顶点(Vertex),计算从左顶点到右顶点的空间向量,再归一化。
我将这个结果赋予BaseColor,这样看的准一点。
当屏幕向右是世界系y方向时,其值偏向为(0,0,1)。因为屏幕上的顶点从左到右,顶点向y轴方向变化(注意左下角世界坐标系的方向):
当我大致面朝(1,1,0)方向:
注意到方块红面由于在往屏幕右方向走时,顶点世界位置x增大(导数大于0),y不变(导数为0),而z变小(导数为负,负数clamp后为0),其ddx为(1,0,0)
方块上面由于在往屏幕右方向走时,顶点的x,y方向都有增加且一样,ddx为(1,1,0)
当我的屏幕右方向更接近x轴时,方块黄面开始变红:
尽管我们的相机位置一直在变,同一个顶点的DDX和DDY也在变,但其都保持在切平面上,叉乘出来也一定是法线方向。
这里可以看出UE4材质系统的2个缺点:
1.明明与真正的WP无关,但却必须引用这个节点,给读者以误导
2.程序执行顺序对用户不清楚。这里的WP明显是已经经过WPOffset以后的WP了。WPOffset中的WP节点和这里的WP节点明明一样,出来的值却不一样,若不是我们知晓渲染管线流程,就会被搞得怀疑人生。
9.问题一:法线
上面看出来了,叉乘出来的法线应该属于世界坐标系,但我们的材质默认是切线空间法线。原材质连这个都没注意到,所以我说编者脑子不清楚。
你可能记得,材质有个选项可以修改。但因为一个蛋疼的原因,我们不得不手动计算,之后会讲到。我们需要手动将世界坐标系的法线转到切线坐标系。
(上图从左到右分别是原法线,编者原材质水波法线,和我修改后的法线。我猜由于透明水波既没什么阴影,水波的折射是否正确也很难有人看出来,所以这个问题没人注意。)
所幸UE4有节点轻松解决坐标系转换:
10.问题二:折射
看到没有,球下方边缘有很奇怪的折射。
本来是水面折射,怎么会和球有关?既然有“屏幕空间反射”,那么这个折射是不是也是基于屏幕空间算的,然后出的问题呢?
在材质detail中搜索Refraction,我们发现引擎提供2种算法,默认算法是这样的:
简单地来说它警告你不要用于像水面一样的大面积折射面。关于为什么会有这个bug它也没说细说,只说这个是物理模拟。
我选择第二种:
它说这个折射是个假模拟,值给1就是没折射,2就是offset为1的折射。这个offset是啥意思它也没说清楚。还告诉我们必须用切线空间法线,这就是为什么我们之前要手动转换。
蛋疼吗?蛋疼。UE4辣鸡吗?辣鸡。
我更改"折射"为:
因为这个假折射率要比较大,折射效果才明显。没办法,谁叫真折射有Bug呢?咱目前这种情况,就是我写本系列教程的缘由,了解原理,运用原理,避免这种情况。因为弱势,所以被牵着鼻子走,不知道在干什么。很不幸,我因为辣鸡,又碰上了这种情况,成为了一个"能用就行"的乞讨者。
以后有机会尝试改写引擎代码,改写这个折射。
结语:
本篇解析,改进,批评一个国外免费透明水面Shader,对简单的物理和材质系统进行初步了解。
由于能力的不足,在折射问题上最终又成为了一个被拦在原理和实现之外的人。之后提升自己的能力,改变这一状况。
水波模拟系列到此告一段落。
Chango的数学Shader世界(七)水波模拟-透明水面,菲涅尔(Fresnel)效应相关推荐
- Unity shader Note :高级纹理(CubeMap反射折射菲涅尔,Rendermap镜子玻璃,程序纹理)
1.Cubemap–反射折射 使用脚本来创建Cubemap ①通过Camera.RenderToCubemap 把任意位置观察到的场景图制作成一张Cubemap之中 ②脚本使用自定义编译窗体的命令 – ...
- Chango的数学Shader世界(八)光盘模拟-各向异性,光栅衍射
目的: 参考<GPU Gems>,在UE4中尝试以重现光盘Shader,并对书中的方法进行解析,改进,批评. 参考: <GPU Gems> 观察: 我越来越意识到观察现实的重要 ...
- Chango的数学Shader世界(九)流体模拟-散度,梯度,二阶导与拉普拉斯
目的: 参考<GPU Gems>,在UE4中尝试重现2D流体模拟. 本节试图结合场论知识粗略理解Navier–Stokes equations. 参考: <GPU Gems> ...
- Chango的数学Shader世界(十四)细线间断,发光闪烁,TAA削弱处理
目的: 减少游戏中的细线因屏幕分辨率不足和算法采样不足问题,导致的间断,以及相对的自发光闪烁.解决了此问题也附带解决了因TAA导致的细线自发光微弱的问题. 对比视频:https://www.bilib ...
- Chango的数学Shader世界(十五)油画Shader-技术分析,教程纠错
目的: 实现油画后期Shader,探究教程中技术细节,指出错误. 参考: 搜索ue4 paint filter. UE4.21后整合自定义usf 观察: 油画的特点:成块的色块,但又保持清晰的边缘. ...
- Unity Shader 水多种元素的实现(反射、折射、菲涅尔、深浅、浪花/泡沫、水波、可交互)
综合效果 经过各元素叠加 和 程序的审美调参 后的综合效果 交互的水波与边缘浪花的合并需要优化一下 反射 两种方案: cubeMap 以水面对称设一个摄像机 cubeMap 实现:反射探针生成Cube ...
- Unity Shader:实现菲涅尔+色散效果的环境映射以及相关原理解析
文章目录 1,色散在光学中的原理 2,反射的数学计算方法以及用它实现环境映射 3,折射的原理以及色散的实现 4,菲涅尔效果 5,拥有菲涅尔与色散效果的环境映射 1,色散在光学中的原理 复色光 --现实 ...
- Unity Shader:实现菲涅尔+色散效果以及相关原理解析
1,色散在光学中的原理 2,反射的原理以及环境映射的实现 3,折射的原理以及色散的实现 4,菲涅尔效果 5,将菲涅尔与色散效果增加到环境映射中 1,色散在光学中的原理 复色光 --现实生活中 ...
- unity shader 菲涅尔效果
老样子,还是先上效果图: 菲涅尔效果的原理大家可以自己去百度看看,网上有很多,这里就不多说了,我们直接看如何实现这个效果 实现思路: 1.求得视角方向,法线方向(世界空间下) 2.根据菲涅尔效果的公式 ...
最新文章
- 使用verdaccio 搭建npm私有仓库
- 如何将usb摄像头连接到虚拟机vmware ubuntu系统上?
- 洛谷-P2801 教主的魔法 分块
- json web token没有哪个成分_SpringBoot 2.1.4集成JWT实现token验证
- js html5是什么意思,javascript是什么意思
- DAY09 NETWORK Cisco简单不同网络主机通信
- Android控件——HorizontalScrollView使用(一)
- 电子商城战略分析(采用定性与定量分析方法)
- 【Linux】imx6ull Kernel 源码下载和编译环境配置
- 42张动图带你走进神奇的物理世界,超震撼!
- 植物大战僵尸数据修改总结
- 【JS】日期Date如何格式化为年月日yyyy-MM-dd hh:mm:ss
- windows下域名解析及修改hosts文件不起作用的问题解决
- 再读《谁动了我的奶酪》
- java基础(适合零基础)持续更新
- OPENHPC搭建集群
- AI 编程“神器”国产化!华为耗时 8 个月,这个能用中文生成代码的模型诞生了...
- OSS Browser的使用
- Windows 命令
- c#和数据库技术基础之程序设计集散地-数据库