Using Vertex Texture Displacement for Realistic Water Rendering(上)

Godot引擎中基于Gerstner波与计算着色器的实时海洋模拟实现 实时渲染技术致力于在有限的计算资源内生成逼真的动态视觉效果,其核心原理在于高效地模拟物理现象并利用GPU并行计算能力。在游戏开发与数字孪生等领域,动态水体的模拟具有极高的技术价值,它能显著提升航海、海岛生存等场景的沉浸感。传统基于CPU或简单顶点动画的方法难以兼顾广阔海面的复杂波动细节与实时性能。本文聚焦于利用Gerstner波理论这一经典流体动力学模型,它通过数学公式高效生成具有尖锐波峰和宽阔波谷的典型海浪形态。为实现海量顶点的实时计算,项目采用计算着色器(Compute Shader)将密集型波浪叠加计 阅读详情

        最近在研究水面渲染,眼看马上要毕业交论文了,还什么都没有弄,大意了~~~。Tessendorf  2001发表的那篇论文真是影响深远,无论FFT还是顶点纹理的实现方法,本质上都是波纹叠加。简单对比了两种实现的demo,顶点纹理的实现CPU占用率确实很少,用任务管理器看大概就30%左右,而FFT的demo只要一开就是100%。不过顶点纹理只有GeForce 6以上的显卡能跑,而且ATI的卡似乎不支持顶点纹理,应该算是它最大的局限性。另外,对LOD的实现来说,也是方法多多,看了几篇论文,实现都不一样,还在研究中-_-#。
        这段时间慢慢把看的文章都翻译整理出来,下面这篇是《GPU Gems 2》中的第18章,讨论了如何使用顶点纹理置换来渲染水面。个人觉得这篇文章讲的不太细致,而且很多问题,比如如何表现水面的深浅、纹理映射,都没有讲,对于法线生成的方法也只是大概提了一下。当然,总的来说,还是值得一看的,特别是文中使用了一种特别的LOD处理,比较有趣。

Using Vertex Texture Displacement for Realistic Water Rendering(上)

 

此教程版权归我所有,仅供个人学习使用,请勿转载,勿用于任何商业用途。
由于本人水平有限,难免出错,不清楚的地方请大家以原著为准。也欢迎大家和我多多交流。
翻译:clayman
Blog:http://blog.youkuaiyun.com/soilwork

         水面在计算机图形学,特别是游戏中,是一种常见的效果。它是增加场景真实性的重要元素之一。但要模拟真实的水面,却是一个难题,因为水面的运动和光学效果都相当复杂。这篇文章描述了游戏Pacific Fighters中,用来渲染水面的技术。

         支持DirectX Shader Model 3.0的硬件提供了许多相当有用的特性,可以用来帮助渲染水面。下面,我们就将讨论如何使用顶点纹理(Vertex Texture)来渲染真实的水面。此外,我们还使用了braching技术来提高渲染效率。

最终的结果,左图使用了displacement mapping,右图则没有

 

1.1水体模型

对水面动画和渲染来说,已经发展出多种方法。其中,最出名也是效果最真实的,就是基于流体动力学和快速傅立叶的方法(FFTs)(比如Tessendorf 2001中描述的)。这些方法可以提供非常真实的渲染效果,但不幸的是他们需要相当大的计算量,因此,不适合于交互式的实时渲染。

此外,现在大多数游戏使用的都是相当简单的模型,大部分方法仅仅是通过改变水面法线创建水面效果。使用这些方法渲染水面,虽然相当高效,但真实度很低,而且并没有真正在水面产生任何波纹。

因此,我需要一种综合了两种方法优点的技术来渲染水面。

 

1.2 实现

         我们的实现中,水面渲染将依赖于法线图(normal map)来进行光照计算。因为法线图可以忠实的重现高频率波形下的所有细节。此外,使用低频率、高振幅的波对水面网格进行扰动。

 

1.2.1 水面模型

         我们的水面模型基于多张,在空间和时间上都进行了分割(tiled)的高度图(height map)的重叠。每张纹理都代表了频谱(spectrum)中的一个“谐波(harmonic)”或者“倍频程(octave)”,和那些使用FFT的方法一样,将把这些纹理叠加到一起。这些纹理就是高度图,每个像素元代表了对应位置的水平高度。

         对于艺术家来说,创建高度图是很简单的:创建它们就和绘制一张简单的灰度图一样。使用高度图,艺术家只需分别绘制单个波纹的形状,就可以可以很容易的控制水面动画。把高度图当作顶点纹理来使用也是很方便的:使用它来置换(displace)顶点的垂直位置是很有效的。

一张用来置换水面位置的高度图

         使用不同的空间和时间缩放比例,混合多张高度图,我们可以获得相当复杂的水面动画效果:

         为了实现真实可信的水面,应该合理的选择参数A、B和i的值,以最小化波纹的重复效果。对于Pacific Fighters来说,我们混合了4张高度图来进行光照计算,其中比例尺较大的两张还将用作置换贴图。这样,我们可以模拟比例尺从 10cm 到 40km 大小的水面。

 

1.2.2 实现细节

         可以把所有需要进行的运算分为两类:几何体置换计算和光照计算。因为水面镶嵌(tessellated)良好,因此,可以把光照计算放到片断(fragment)程序中,而把置换映射放到顶点程序里。当然,把光照计算放到顶点处理阶段也是可以的,特别是对于远处的顶点来说。

         在写这篇文章时,唯一支持顶点纹理的硬件就是GeForce 6系列以及最新的Quadro FX GPU。在这些硬件上,使用顶点纹理有一些特别的限制,只能使用32bit的浮点纹理,只能使用nearest filtering。

 

1.2.3 采样高度图

         我们的实现中,对高度图中的每个顶点进行采样,在顶点程序中计算置换值。对于采样来说,使用了一个放射状的网格,它的中心位于摄像机所在位置。按照这个样子镶嵌的网格,可以让靠近观察者的地方提供更多细节。

下面的公式说明了如何计算放射网格中的顶点位置:

这里i = [ 0….N-1], j = [ 0…..M-1]。我们选择

r0 = a0 = 10cm

rN-1 = a0 + a1( N – 1)4 = 40km

         这种基于距离的镶嵌,提供了一种相当简洁的LOD方法。当然,这里也可以使用其他的地形渲染算法来实现LOD,比如ROAM或者SOAR,但这就需要占用一定的CPU资源进行计算,这完全违背了使用顶点纹理的初衷。

         下面的代码显示了如何在vertex shader中,使用放射形网格对一张高度图进行采样:

float4 main(float4 position :    POSITION,

     uniform sampler2D tex0,

     uniform float4x4 ModelViewProj,

     uniform float4 DMParameters,     // displacement map parameters

     uniform float4 VOFs) : POSITION

{

     //read vertex packed as (cos(),sin(),j)

     float4 INP = position;

     //transform to radial grid vertex

     INP.xy = INP.xy * (pow(INP.z,4) * VOFs.z);

     //find displacement map texture coordinates

     //VOFs.xy ,DMParameters.x - height texture offset and scale

     float2 t = (INP.sy + VOFs.xy) * DMParameters.x;

     //fetch displacement value form texture (lod 0)

     float vDisp = tex2d(tex0, t).x;

     //scale fetched value form 0...1

     //DMParameters.y - water level

     //DMParameters.z - wavy amplitude

     INP.z = DMParameters.y + (vDisp - 0.5) * DMParameters.z;

     //displace current position with water height and project it

     return mul(ModelViewProj,INP);

}

        

1.2.4 质量改进和优化

       Packing Heights for Bilinear Filtering

         顶点纹理拾取(fetch)是相当耗费资源的操作。在GeForce 6系列的硬件上,可以在顶点程序中引入一个顶点纹理拾取器。我们必须最小化在顶点程序中进行纹理拾取的次数。此外,对纹理中的值进行过滤(filtering)也是必须的,否则视觉效果将会大打折扣。

         一般来说,最常见的过滤方法就是双线性过滤和三线性过滤。双线性过滤将对最靠近纹理选取坐标位置处的四个像素元(texels)进行均值计算。三线性过滤则需要对邻近mip层次中的双线性过滤结果进行均值计算,同时根据不同的LOD层次选择每个层次的混合权重。

         由于当前的图形卡无法对顶点纹理中的值进行任何形式的过滤,我们不得不在shader中直接使用数学运算指令来模拟过滤。对于不好的实现来说,即使是最简单的双线性过滤也需要通过通过四次纹理查找来计算一个过滤值,而三线过滤的查找次数更是翻了两倍。

         为了减少过滤时的纹理拾取次数,我们用一种特殊的方法来创建纹理,让一个像素元就包含了一次双线性纹理查找所需要的所有数据。这是一个相当可行的方法,因为高度图本质上就是一张单通道(one-component)的纹理,我们可以把4张高度图打包为一张每个像素元四通道的纹理:

         这里i = [ 0….N-1], j = [ 0…..M-1]。H表示高度图的值,F是过滤函数,A则是打包好的输出纹理。

         下面的代码实现了对顶点纹理进行双线性查找

float tex2D_bilinear4x(uniform sampler2D tex ,

         float4 t,

         float2 Scales)

{

         float size = Scales.x;

         float scale = Scales.y;

         float4 tAB0 = tex2Dbisa(tex, t);

         float 2 f = frac(t.xy * size) ;

         float3 tAB = lerp(tAB0.xy, tAB0.yw, f.x);

         return lerp(tAB.x, tAB.y, f.y);

}

         我们可以把这个方法扩展为三线性过滤。因为三线性过滤需要局部LOD的值,因此,我们把顶点到摄像机的距离作为LOD的近似值。下面的代码实现了对打包之后的顶点纹理进行三线性查找:

float tex2D_trilinear(uniform sampler2D tex

         float4 t,

         float4 Scales)

{

         float fr = frac(t.z);

         t.z -= fr;    // floor(r.zw)

         float Res;

         if(fr < 0.30)

                   Res = tex2D_bilinear4x ( tex , t.xyzz, Scales);

         else if (fr > 0.70)

                   Res = tex2Dbilinear4x( tex , t.xyzz + float4(0,0,1,1), Scales * float2(0.5,2);

         else

         {

                   Res = tex2D_bilinear4x( tex , t.xyzz, Scales);

                   float Res1 = tex2D_bilinear4x( tex , t.xyzz + float4(0,0,1,1), Scales * float2(0.5,2));

                   fr = saturate ( ( fr – 0.30) * ( 1 / ( 0.70 – 0.30)));

                   Res = Res1 * fr + Res * (-fr) ;

         }

         return Res ;

}

         注意,这里我们进一步对三线性纹理选取进行了优化,只对影响较大的两个mip层次区域进行纹理查找。对其他区域来说,直接把他们的LOD值设置为最相邻mip层次的值,从而节约纹理带宽。(未完待续ing~~~)

 

Godot 4中实现FFT海洋渲染:从频谱原理到GPU计算全流程 快速傅里叶变换(FFT)是数字信号处理与计算机图形学中用于高效进行频域与时域转换的核心算法。其原理在于将复杂的波形分解为不同频率的正弦波分量,在频域进行计算后再通过逆变换重构信号,这为模拟自然现象提供了强大的数学工具。在实时渲染领域,FFT技术能高效生成物理准确、细节丰富的动态表面,具有极高的技术价值。它广泛应用于模拟动态水面、云层、地形等需要复杂波谱合成的场景。本文聚焦于利用FFT算法在Godot 4引擎中实现高性能的海洋渲染,深入剖析了如何通过Compute Shader进行GPU并行FFT计算,并结合 阅读详情

相关推荐

移动端水面Shader开发实战:从Gerstner波到性能优化

在移动图形开发中,Shader是实现复杂视觉效果的核心技术,它通过一系列算法指令控制GPU渲染像素的最终表现。其原理在于对光照、纹理、几何变形等基础图形学概念进行数学建模与编程实现。对于移动平台而言,Shader的技术价值尤为突出,它需要在有限的GPU算力、带宽和功耗约束下,最大化视觉表现力,这是决定游戏画面品质与运行流畅度的关键。尤其在开放世界、RPG等手游类型中,水面效果作为重要的环境与交互元素,其Shader的实现方案直接影响到玩家的沉浸感与设备的续航能力。因此,针对移动端特性进行深度优化的专用水面S

weixin_30487201的博客 397

VIBE改进算法

参看《Background subtraction:experiments and improvements for vibe》,总结出来的。 Vibe的改进 Updating factor 由20降低到5或1,可以加快背景学习速度; 区分分割模型和更新背景模型 背景减的目标是获取前景运动目标,大多数情况得到的分割模块就是我们寻找的检测目标,一般情况下都利用获得的前景目...

sunny的专栏 9248

Realistic Water v2.0.3 unity 资源 海洋 大海 地形水插件

Realistic Water v2.0.3 unity 资源 海洋 大海 地形水插件湖泊,池塘/沼泽水和海洋水不再沿任何特定方向流动。 湖泊,河流和海洋都有新的环境声音效果,池塘无声。 瀑布和急流的数量增加了。 冰山和冰块有时会破裂。。。 漂浮在水中的划艇将有动画,水会轻轻地飘荡着。 波浪减慢,重新结构化,现在有一个水音效果。使飞溅/泡沫效果更真实。他们也被添加在天际的海岸一些有意义的地方。额外的波浪也被添加到Solstheim。 大瀑布已经加快了动画,重塑和更多的飞溅颗粒被添加。瀑布雾更有真实感。 泡沫效果已经重塑。 雨的波纹不再滑过水面。他们也被重新打造,透明度增加。

基于YOLOv11的洪水检测与分割模型研究

近年来,全球气候变化导致极端天气事件频发,洪水灾害对人类社会和基础设施的威胁日益加剧。根据联合国减灾署(UNDRR)统计,洪水占全球自然灾害的40%以上,每年造成数千亿美元的经济损失。传统的洪水监测主要依赖卫星遥感和地面传感器,但这些方法存在**时效性差、分辨率低、成本高昂**等局限性。 计算机视觉技术的快速发展为**实时洪水检测**提供了新的解决方案。基于深度学习的目标检测与分割模型能够从监控摄像头、无人机航拍等视觉数据中快速识别洪水区域,为灾害预警、应急响应和灾后评估提供关键支持。

qq1309399183的博客 1589

unity 喷泉粒子特效

unity喷泉粒子特效。unity喷泉资源包Realistic Water Fountain 1.0。有需要的赶紧

菲利普斯海洋:在Unity中使用菲利普斯光谱的海洋

菲利普斯海洋 这是一个使用菲利普斯光谱生成波浪的海洋项目。 大约在2001年的某个时候,杰里·特森多夫(Jerry Tessendorf)发表了一篇名为“模拟海洋水”的论文,其中列出了模拟海洋的所有方法和数学需求。 在本文中,概述了使用菲利普斯光谱的数学运算,而我遇到了一个将数学运算转换为代码的。 他的项目是用C ++编写的,因此只需将其转换为Unity的C#脚本即可。 我保留了所有的数学原理,但是进行了一些更改,并对代码进行了一些重组,现在Fourier变换在其自己的线程上运行,从而大大提高了性能。

一种基于密集深度分离卷积的SAR图像水域分割算法

摘要 SAR图像水域分割在舰船目标检测、灾害监测等军事领域和民用领域具有重要意义。针对传统水域分割算法鲁棒性差、难以准确进行分割等问题,文章首先建立了基于高分三号卫星的SAR图像水域分割数据集,并基于深度学习技术提出了基于密集深度分离卷积的分割技术网络架构,该网络以SAR图像作为输入,通过密集分离卷积和扩张卷积提取图像高维特征,并构造基于双线性差值的上采样解码模块用于输出分割结果。在水域分割数据集上的实验结果表明,与传统方法相比,该方法不仅在分割准确度上有很大提高,在算法的鲁棒性和分割速度上也具有部分优势,

张帅影&RS&DeepLearning 853

解决win11无法安装.net framework 3.5(包括.net2.0和3.0)错误代码:0x80070005

解决win11无法安装.net framework 3.5(包括.net2.0和3.0)错误代码:0x80070005

zeng699304的博客 2万+

【完整源码+数据集+部署教程】水位面图像分割系统源码和数据集:改进yolo11-EMSC

【完整源码+数据集+部署教程】水位面图像分割系统源码和数据集:改进yolo11-EMSC

weixin_43860634的博客 1010

图相似度模型(论文篇)

图相似度模型

weixin_43702653的博客 5747

Kali Linux下John the Ripper实战:从识别yescrypt哈希到破解zip压缩包(保姆级避坑指南)

本文详细介绍了在Kali Linux中使用John the Ripper工具从识别yescrypt哈希到破解zip压缩包的全过程。针对常见的'No password hashes loaded'报错,提供了两种解决方案,并扩展讲解了哈希识别、zip文件破解及性能优化技巧,是安全测试人员的实用指南。

weixin_29323365的博客 236

使用UNet++和TransUNet两种模型进行水体区域分割任务海陆分割数据集 水与陆地分割检测 遥感水体分割数据集 原图(3841张)和对应的分割mask(3841张) 陆地上的水体区域进行图像分割

使用UNet++和TransUNet两种模型进行水体区域分割任务海陆分割数据集 水与陆地分割检测 遥感水体分割数据集 原图(3841张)和对应的分割mask(3841张) 陆地上的水体区域进行图像分割

2401_88440984的博客 1759

ESP32-CAM与Thonny的完美搭配:从烧录到通信的完整流程

本文详细介绍了如何将ESP32-CAM与Thonny IDE完美结合,从固件烧录到通信测试的完整流程。通过硬件连接、MicroPython固件烧录、Thonny环境配置以及摄像头功能开发等步骤,帮助开发者快速搭建高效的物联网开发环境,实现图像采集与无线通信功能。

tomato的博客 1122

Using Vertex Texture Displacement for Realistic Water Rendering(下)

Using Vertex Texture Displacement for Realistic Water Rendering(下)作者: Yuri Kryachko本文版权归原作者所有,仅供个人学习使用,请勿转载,勿用于任何商业用途。由于本人水平有限,难免出错,不清楚的地方请大家以原著为准。也欢迎大家和我多多交流。翻译:claymanBlog:http://blo

Clayman的专栏 5071

Xilinx Blockset Counter计数器模块使用及参数配置

本文详细介绍了Simulink中Xilinx Blockset库Counter模块的使用以及参数说明。

白码王子小张的博客 1094

4 轴穿越机 Mark5 机架全解析:从历史演进到电机桨叶选型指南

本文围绕 4 轴穿越机 Mark5 机架展开,先介绍其发展历程(2018 年初代到 2023 年五代,迭代优化轻量化、刚性与兼容性),再明确其核心参数(轴距 220mm、兼容 4-6 寸桨等)对电机桨叶的约束。 详解电机(KV 值、尺寸、推力等)与桨叶(尺寸、螺距、材质等)选型要点及匹配原则(高 KV 配小桨、低 KV 配大桨),给出推重比、功率等理论计算公式,结合新手练习、花飞、竞速、航拍等场景提供具体选型案例,最后提及安全、成本、法规等注意事项,为爱好者提供全面选型参考。

bother3000的博客 1899

Using Vertex Texture Displacement for Realistic Water Rendering

http://blog.youkuaiyun.com/soilwork/article/details/709869 Using Vertex Texture Displacement for Realistic Water Rendering(上) 分类:GPU程序设计2006-04-24 14:573466人阅读评论(1)收藏举报 floatshader网格fftparam...

weixin_34062329的博客 261

YOLOv8与UNetV2融合:一种面向目标检测与图像分割的混合方法【附核心代码】

我们提出了一种基于YOLOv8和UNetV2相结合的混合架构。该架构利用YOLOv8作为主干进行目标检测,同时在YOLOv8的特征提取过程中,引入UNetV2来进行图像分割任务的增强。在该架构中,YOLOv8负责大范围目标检测和位置预测,而UNetV2则在检测网络的特征图基础上,通过其高效的上下文信息提取和细节恢复能力,进一步优化分割任务。在本文中,我们提出了一种改进YOLOv8的方法,通过引入图像分割网络UNetV2来提高图像分割检测性能。

一键难忘的博客 3524

Using Vertex Texture Displacement for Realistic Water Rendering(转)

最近在研究水面渲染,眼看马上要毕业交论文了,还什么都没有弄,大意了~~~。Tessendorf 2001发表的那篇论文真是影响深远,无论FFT还是顶点纹理的实现方法,本质上都是波纹叠加。简单对比了两种实现的demo,顶点纹理的实现CPU占用率确实很少,用任务管理器看大概就30%左右,而FFT的demo只要一开就是100%。不过顶点纹理只有GeForce 6以上的显卡能跑,而且ATI的卡...

190

Allegro如何把分离的线段变成封闭连续的图形

Allegeo支持把分离的线段变成封闭连续的图形,以下图为例,线段是分离的。Allegro如何把分离的线段变成封闭连续的图形。Find选择other segs 和Lines。Find选择other segs 和Lines。选择shape-compose shape。分离线段已经是连续封闭的shape形式了。框选图形,删除剩下的无用的分离线段。Find选择shapes。鼠标右击选择done。选择delete命令。鼠标右击选择done。

weixin_54787054的博客 6238

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

OpenMontage 中的 Three.js 着色器开发实战:从 ShaderMaterial 到自定义视觉特效

> 本篇指南基于仓库内 `.agents/skills/threejs-shaders/SKILL.md` 技能文档展开,系统讲解 OpenMontage 中 Three.js 自定义着色器的完整知识体系:从 `ShaderMaterial` / `RawShaderMaterial` 的选型、uniform 与 varying 的数据通路,到顶点位移、菲涅尔、边缘光、溶解等常用特效模式,再到 `

gitblog_00746的博客 223

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

如何使用无人船视角水面全景分割与目标检测及usv无人船目标检测数据集进行全景分割和目标检测,船舶语义分割及检测,船舶检测海上目标检测

如何使用无人船视角水面全景分割与目标检测及usv无人船目标检测数据集进行全景分割和目标检测,船舶语义分割及检测,船舶检测海上目标检测

2401_88440984的博客 1798

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【完整源码+数据集+部署教程】水面场景物体图像分割系统: yolov8-seg-C2f-EMSC

【完整源码+数据集+部署教程】水面场景物体图像分割系统: yolov8-seg-C2f-EMSC

2301_78772942的博客 1204

Realistic Water 使用

一、设置无限水 "MoveWaterToCamera" and for “current camera” set your main camera or any object that you assigned to the camera. (Character, ship, etc.) 通过在空间上的投影,你可以用水来创造一个无限的海洋。波浪是在世界空间中计算出来的,所以你可以把水向各个方向移动。要创造一个无限的海洋,你需要设置相机。运动只发生在X轴和Z轴上。水的高度是恒定的。...

奋斗的菇凉的博客 1094

快速傅立叶变换(FFT)的海面模拟

快速傅立叶(FFT)变换的海面模拟 在这篇文章中,我们将根据Tessendorf的论文[1]中的方程来实现统计波浪模型,以模拟海洋水。 使用快速傅立叶变换,我们将能够实现实时交互的帧速率。以下提供两个截图,首先是简单的光照渲染,之后的是网格模型的渲染。 改文章使用了一个高度函数,其中为坐标(x,z)(我们这里令y为高度),时间为t(说明我们的高度会随时间变化)。 其中,是我们...

小龙虾的博客 6029
上一篇: Inside Geometry Instancing(下)
下一篇: Using Vertex Texture Displacement for Realistic Water Rendering(下)
soilwork
博客等级 码龄23年 290粉丝 116原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值