首页 > 其他分享 >UE5 材质 Water Shader

UE5 材质 Water Shader

时间:2023-05-23 23:37:40浏览次数:52  
标签:omega sum Shader 折射 times Water UE5 com sin

目标

  • 水有许多特性,本篇将着重实现如下特性
    • 表面涟漪
    • 水深效果
    • 水的反射和折射
    • 海浪
    • 波光的焦散

表面涟漪

初步实现

image-20230520150152153
image

模拟水的运动

  • 现实中水的流动是较为混乱的,但上图的水流动过于统一。我们使用世界坐标的位置进行投影,且让水只在XY平面进行运动
    image-20230520152927951
  • 如何让水的流动混乱呢?很容易想到,我们需要让纹理图在不同方向上进行变换
    image-20230520154703210
    image

水深

影响水透明度的因素

  • 看向水面的角度
  • 水深。水越深,会变得越来越不透明

设置blend mode

  • 因为这里涉及到半透明渲染,我们需要选择"Blend Mode"为"Translucent"
    image-20230520155955692

测量水深

"SceneDepth" & "PixelDepth"

步骤

  • SceneDepth:以相机为视角,返回场景中离它最近的一个物体的距离且忽略透明物体
    image-20230520161006162
  • PixelDepth:以相机为视角,返回它到半透明物体的距离
    image-20230520161223225

实现

  • 初步实现
    image-20230520162419701
    image-20230520162441733

    从上图可以看出这正是我们想要的效果,从浅到深,刚开始有些黑色,然后变白

  • 纠正视角问题

    • 问题
      当我们垂直看去,得到的效果如下
      image-20230520162843968

      当我们水平看去,得到的效果如下
      image-20230520162939926

      可以看出因为角度的问题,求得的深度值也有所不同,角度越偏向水平,得到的深度值越大,透明度越低

    • 原因

      很明显水深并不是"SceneDepth - PixelDepth",而是垂直的深度,这里用相似即可实现
      image-20230520163533817

    • 实现
      image-20230520171132082
      image-20230520171310120
      image-20230520171334922

测量角度

目标

  • 当视角越来越垂直水面,水越来越透明
  • 当视角越来越平行水面,水越来越不透明

实现

水颜色的渐变

目标

  • 因为水的颜色收到深度的影响,因此我们需要创建两种颜色的水,一种代表深处的颜色,一种代表浅处的颜色

实现

image-20230520175855482
image-20230521145104621

以下是水深的全部实现内容
image-20230521145510602

水的反射和折射

UE中的反射

  • UE中的反射有五种不同的实现方法,且许多场景不单单使用一种反射而是多种反射方法相结合。在这里我们介绍其中三种

    • sky box

    • Light Probe(光照探针)

      简单来说,Light Probe给予场景中某个点向它周围收集光照的能力,并记录周围的光照(irradiance map)。随后对某个像素点进行渲染时,利用它附近的probe的光照信息估计该点所受光照
      img

      • 缺点
        • 只适用于静态物体和静态光照
    • 屏幕空间反射(Screen Space Reflections)

      简单来说,Screen Space Reflections以屏幕数据计算反射效果。因为它需要G-Buffer中的normal,所以只适用于延迟渲染

      • 缺点
        • 成本高
        • 只能反射屏幕内的物体,对屏幕外的无效

UE中的折射

  • UE5提供了两种折射模式,一种是基于物理的无normalmap的折射模式"Index of Refraction";另一种是不基于物理的normal的折射模式"Pixel Normal Offset"

  • 这两种模式各有长处

    • Index of Refraction模拟光线在介质间传播时的折射方式。适用于小物体,对于较大的物体很可能会带有瑕疵,因为当前屏幕中的物体的颜色很可能从屏幕外获取

    • Pixel Normal Offset以vertex normal为基础,计算每个pixel的normal和vertex normal的差异来得出折射偏移。适用于较大平面,因为无需从屏幕外读取数据。需要注意的是,若参数"Refraction Depth Bias" > 1,法线将沿平面平移

    • 参数Refraction Depth Bias

      Refraction Depth Bias用于防止距离较近的对象以尖锐的(acute)视角渲染到扭曲的表面。但可能会增加表面和折射位置的距离

启用反射和折射

  • 在根节点处启用"Screen Space Reflections"
    image-20230521153144962
  • 在根节点处选用"pixel normal offset"
    image-20230521153416422

海浪

海浪算法

思想

  • 水体渲染主要运用两个表面的模拟:一个用于表面网格的几何波动,另一个是网格上法线图的扰动。而水面高度由简单的周期波叠加表示
  • 因为水的波纹呈sin分布,所以我们基于简单的sin函数进行叠加可以得到一个连续函数,该函数描述水面上所有点的高度和方向

波的选择

  • 在正式开始前,我们需要了解不同类型的波浪应该用哪种波形
    • 对于受影响生成的波,应使用方向波。对于方向波,波的方向是在风的一定范围内画的
    • 对于平静的水面,生成的波并不是因为风(如瀑布),应使用圆形波。对于圆形波,波中心是在限定范围内任意画的
      image-20230521193006821

为什么选择Gerstner算法?

  • 因为Gerstner算法有一个特性,它将顶点朝着每个浪头顶部移动,从而形成更尖锐的波峰。而这一特性,正是我们所需要的
    img

从sin函数开始

  • 由于sin函数在x轴方向不变,在y轴方向上下移动,使得它形成的面更为圆滑,因此sin函数更适合平静的湖面
参数选择
  • 对于波的形成,我们需要考虑以下几个参数

    1. 波长(\(L\)):world space中波峰到波峰的间距。\(L\)和\(\omega\)(角频率)的关系 \(\omega = \frac{2\pi}{L}\)
    2. 振幅(A):水平面到波峰的间距
    3. 速度(S):波峰每秒移动的距离。为方便将S表示为相位常数\(\varphi = S \frac{2\pi}{L}\)
    4. 方向(D):垂直于波面且的水平向量
  • 波的状态定义为位置(x,y)和时间t的函数:\(W_i(x,y,t) = A_i \times sin(D_i · (x,y) \times \omega_i + t \times \varphi_i)\)

    img

  • 所有波i的总表面:\(W_i(x,y,t) = \sum A_i \times sin(D_i · (x,y) \times \omega_i + t \times \varphi_i)\)

法线和切线
  • 切线和副切线分别是y方向和x方向上的偏导
  • 现有2d平面的任意点\((x,y)\),表面的3d坐标\(p(x,y,t) = (x,y,H(x,y,t))\)
    • 切线即为对y轴求偏导:\(T(x,y) = (0, 1, \frac{\partial}{\partial y}(H(x,y,t))\)
    • 副切线即为对x轴求偏导:\(B(x,y) = (1, 0, \frac{\partial}{\partial x}(H(x,y,t)))\)
    • 法线即为副切线和切线的叉乘:\(N(x,y) = (-\frac{\partial}{\partial x}(H(x,y,t)), -\frac{\partial}{\partial y}(H(x,y,t), 1)\)

Gerstner波

  • Gerstner波有一个特性,它将顶点朝着每个浪头顶部移动,从而形成更尖锐的波峰,这适用于粗犷的海洋
  • Gerstner波中每一个水分子都在做圆周运动,这意味着x,y都在变化(而sin函数只有y变化,x不变),且水分子在波峰聚集,在波谷分散,越靠近水面,圆周运动的半径越大
定义
  • Gerstner波定义

    \(P(x,y,t) = \left(\begin{array}{cc} x + \sum(Q_i A_i \times D_i.x \times cos(\omega_i D_i·(x,y) + \varphi_i t)) \\ y + \sum(Q_iA_i \times D_i.y \times cos(\omega_i D_i·(x,y) + \varphi_i t)) \\ \sum(A_i sin(\omega_i D_i·(x,y) + \varphi_i t)) \end{array}\right)\),其中\(Q_i = \frac{1}{\omega_i A_i}\)

  • 对于单个波i,当\(Q_i = 0\)时,Gerstner波为sin波

    • 使用\(Q_i = \frac{Q}{\omega_i A_i \times numWaves}\)可以控制波的平滑或尖锐程度
    • 需要注意的是,应当避免使用过大的\(Q_i\),这会导致波峰形成环
      img
切线和法线
  • 设 \(WA = \omega_i \times A_i \\ S() = \sin(\omega_i \times D_i · P + \varphi_i t) \\ C() = cos(\omega_i \times D_i · P + \varphi_i t)\)

  • 副切线\(B = \left(\begin{array}{cc} 1-\sum(Q_i \times D_i.x^2 \times WA \times S()) \\ -\sum(Q_i \times D_i.x \times D_i.y \times WA \times S()) \\ \sum(D_i.x \times WA \times C()) \end {array}\right)\)

  • 切线\(T = \left(\begin{array}{cc} -\sum(Q_i \times D_i.x \times D_i.y \times WA \times S()) \\ 1 - \sum(Q_i \times D_i.y^2 \times WA \times S()) \\ \sum(D_i.y \times WA \times C()) \end{array}\right)\)

  • 法线\(N = \left(\begin {array}{cc} -\sum(D_i.x \times WA \times C()) \\ -\sum(D_i.y \times WA \times C()) \\ 1 - \sum(Q_i \times WA \times S()) \end{array}\right)\)

参数
  • 波长

    这里波长的选择不是根据现实而定,而是使用少数几个波达到最大效果。因此我们选择中等的波长,以它的\(\frac{1}{2}\)到\(2\)倍间产生任意波长

  • 波速

    波速与波长L、重力g(国际单位\(9.8m/s^2\))相关:\(S = \sqrt{g \times \frac{2\pi}{L}}\)

  • 振幅

    在Shader中指定一个系数,由美术人员对波长指定对应的合适振幅

  • 方向

    波的运动方向和其他参数完全独立,可以自由选择

实现

  • 解决水面交界的绿线

    从上图可以看到水面和岩石及墙体的交界都有一道绿线,这是由"depth fade"节点造成的。"depth fade"在我们的实现中仅仅用于水的不透明度,但我们却将其用在水的颜色
    image-20230521162239829

  • 降低水和物体交界处的折射效果以交界处的硬线
    image-20230521162527060
    image-20230521174405103
    image-20230521174551698

海浪

  • 将上述公式套一下即可
    image-20230523110918629
    image

波光焦散

目标

  • 在现实中,当太阳照射水面,水面会扭曲这些光纤从而生成特别酷炫的纹理
    image-20230523161227367

原理

  • 对于这种纹理也是可以实现的,实现方式是贴花(decal)

    简单来说,运用在实时渲染中的贴花技术是屏幕空间的延迟贴花——利用现有的G-Buffer,直接将贴花投射在物体表面

  • 运作时间

    写入G-Buffer后,屏幕空间的后处理前

  • 与TBN类似,需要将世界空间转换到贴花空间,这样才能得到正确的贴花位置及其纹理。随后计算投影位置即可

根节点设置

  • 这里我们需要新建一个材质,并将根节点按如下设置
    image-20230523173017968

纹理

image-20230523173218299image-20230523173233120
image-20230523174652224

实现

初步实现

image-20230523173442096image-20230523173543387

加入动画

  • 简单的动画效果
    image-20230523174250523
    image

  • 扭曲效果

    目前的动画太有规律了,但现实中更像没有规律的。因此,我们需要将平移效果带点起伏
    image-20230523175928464
    image

  • 继续优化

    可以看到确实有那味儿了!若为了更好的效果,可以再加一个不同的法线扰动效果
    image-20230523181035090
    image

修正投影

  • 目前,我们的贴花是基于z轴投影的,这会导致z轴的贴花不会有理想效果
    image-20230523181753982
  • 如何修正呢?很简单,三个轴都进行投影
    image-20230523183811632
    image

reference

基于 Probe 的实时全局光照方案(Probe-based Global Illumination) - KillerAery - 博客园 (cnblogs.com)

[Siggraph15]Stochastic Screen-Space Reflections - 知乎 (zhihu.com)

虚幻引擎中的屏幕空间反射 | 虚幻引擎5.0文档 (unrealengine.com)

使用像素法线偏移实现折射 | 虚幻引擎文档 (unrealengine.com)

使用像素法线偏移实现折射 | 虚幻引擎文档 (unrealengine.com)

在虚幻引擎中使用像素法线偏移实现折射 | 虚幻引擎5.1文档 (unrealengine.com)

使用折射 | 虚幻引擎文档 (unrealengine.com)

GPU Gems1

[Game-Programmer-Study-Notes/README.md at master · QianMo/Game-Programmer-Study-Notes · GitHub](https://github.com/QianMo/Game-Programmer-Study-Notes/blob/master/Content/《GPU Gems 1》全书提炼总结/README.md#一、-用物理模型进行高效的水模拟(effective-water-simulation-from-physical-models))

水体渲染之Gerstner波形理解与推导 - 知乎 (zhihu.com)

贴花 | 虚幻引擎文档 (unrealengine.com)

谈谈游戏影视中的贴花decals技术 - 知乎 (zhihu.com)

标签:omega,sum,Shader,折射,times,Water,UE5,com,sin
From: https://www.cnblogs.com/chenglixue/p/17426704.html

相关文章

  • Real-Time Water Waves With Wave Particles - cem yuksel - 2010
    摘要:Thisdissertationdescribesthewaveparticlestechniqueforsimulatingwatersurfacewavesandtwowayfluid-objectinteractionsforreal-timeapplications,suchasvideogames.本文描述了用于模拟水面波的波粒子技术和用于视频游戏等实时应用的双向流体-物体......
  • 【做题记录】CodeForces343D Water Tree
    题面翻译给出一棵以\(1\)为根节点的\(n\)个节点的有根树。每个点有一个权值,初始为\(0\)。\(m\)次操作。操作有\(3\)种:将点\(u\)和其子树上的所有节点的权值改为\(1\)。将点\(u\)到\(1\)的路径上的所有节点的权值改为\(0\)。询问点\(u\)的权值。\(1\le......
  • shader编程基础:画线
    以sin曲线为例,任何函数曲线画法类似。画线原理虽然十分简单,却是复杂图形曲线绘制的基础。uv和smoothstep等函数不清楚请参考跳转链接:shader编程基础:画圆#defineT.01voidmainImage(outvec4fragColor,invec2fragCoord){ vec2uv=(fragCoord.xy-0.5*iResoluti......
  • CF269D - Maximum Waterfall
    比较迷糊,比较乱搞。我们考虑从上往下进行\(dp\),\(dp_i\)表示从顶上水槽\(i\)最多的流量。然后我们发现,每个高度,能用来进行转移的区间一定没有被完全覆盖。也就是,只有在遮挡关系中被覆盖的区间可能被用来转移。同时,每个区间还是有要求的,比如\([1,3]\)的\([2,3]\)部分后来......
  • UE5 材质 布料shader
    前言本篇实现一个简单的布料shader,需要注意的是本篇仅仅模拟布料的外观,但物理上并不是正确的因为还需要改光照目标通过观察缎子、棉布、丝绸可以看出,这些物体有些是中间亮,边缘暗,有些是中间暗,边缘亮,因此我们需要实现控制物体中间和边缘亮度的shader布料算法顽皮狗工作室曾在S......
  • UE5 材质 Flipbook火焰特效
    原理因为游戏为了保证舒适的帧数,通常不能临时计算特效,所以一般是提前将动画做成单独的帧,最后渲染至纹理流程UE5提供的FlipBook节点原理提供uv坐标,time节点,指定行列即可实现FLipBook实现使用的flipbook纹理有五行五列,因此提供一个float=5的节点连接到FlipBook的"......
  • Unity Shader Toggle KeywordEnum Enum 使用
    Shader"Unlit/Custom/Shader05"{Properties{_MainTex("MainTex",2D)="white"{}[Toggle]_INVERT("Invertcolor?",Float)=0//_INVERT必须是大写的_Invert不可以[KeywordEnum(None,Add,M......
  • OpenGL学习笔记-3:编译shader报错: cannot convert from 'const highp float' to 'Frag
    报错信息: ERROR::SHADER_COMPILATION_ERRORoftype:FRAGMENTERROR:0:10:'assign':cannotconvertfrom'consthighpfloat'to'FragUserData4-componentvectorofhighpfloat'-------------------------------------------------......
  • shader变体
    用法以multi_compile为例:Variant.shaderShader"My/Variant/Variant"{SubShader{//...Pass{CGPROGRAM#pragmavertexvert#pragmafragmentfrag#pragmamulti_compil......
  • UE5 程序切出活动窗口/后台运行时掉帧问题
    依次点击“编辑”—>“编辑器偏好设置“—>“通用/性能”,取消选中“后台运行时使用较少CPU”即可,如下图所示: ......