【Unity】基于顶点色的海边波浪效果(适用移动端)

2023-10-28

之前曾做过一个unity中带有海边波浪冲刷的海水shader效果,并最初发布在CSDN上,原文链接: http://blog.csdn.net/mobilebbki399/article/details/50493117
不过最初的效果原先仅仅是自己自学shader与练习时实现的,没有考虑过多优化措施,总的来说做的比较水(当时才工作半年多 ~_~|||)


考虑到该效果貌似关注的人挺多的,最近刚好也在项目中使用了该效果的移动版本,因此整理出了Demo分享一下制作经验(Demo Git地址在最下面):


实现过程:
1.使用顶点颜色代替深度图
在原版的效果中,我使用了投影深度图的方式,来计算海水底部到海面的深度差,通过这种方式判断海水的潜水处和深水处,这是一种很常见的实现水体效果的方法,然而这意味着:首先我们需要额外渲染场景的深度图,这个操作对于PC平台而言消耗不大,事实上unity中PC平台默认就是开启深度图渲染的,而对于移动平台,深度图的渲染是关闭的,我们当然可以手动在代码中设置开启,但这意味着额外的drawcall消耗。

因此我考虑使用顶点色的方式来表达海水的深水和潜水处,如下图:

但使用这种方式需要高度依赖海水mesh的顶点数量和顶点分别,以及顶点色的控制,因此存在以下两个问题:
1.绘制顶点色的成本
2.如何控制顶点数量和分布

对于第一个问题,我的实现方式是,在unity中通过编辑器预先从海水mesh顶部往下渲染深度图,并映射到mesh的顶点色,同时增加工具允许美术直接在unity中直观的绘制顶点色,如下:
该纹理在编辑器中渲染并映射到mesh:

提供直接绘制顶点色的工具用于调整效果:



比较棘手的是第二个问题,考虑到如果直接交由美术制作mesh,一方面增加制作成本,另一方面比较不容易把控顶点的分布于数量,因为显然这种基于顶点色的效果依赖顶点数量,但顶点数量过多会增加mesh占用的内存以及渲染性能,而直接由程序生成mesh的话如果顶点过少又无法达到效果,如下:

过少的顶点无法体现出海水波浪效果:


2.Mesh细分的思路
为了解决上述为题,我实现了两种对Mesh根据海陆交界处细分的方法,实际上这两种方法都大量借鉴了比较流行的地形lod技术中的方法(只不过我生成的是静态mesh),其中第一种方法借鉴了GeoMipmapping技术,第二种方法则依靠四叉树来实现:

第一种方式借鉴了GeoMipmapping技术:https://en.wikipedia.org/wiki/Geomipmapping
这是一种常见的地形Lod技术,如下,将地形分成NxN个格子,每个格子给予一个lod值,该lod一般根据视点与该格子的距离计算得到,根据不同的lod决定该Lod的细节:


在地形系统中,一般格子的lod是根据视点与该单元格的距离决定的,距离越远lod越大,网格细节越少。而我这边则是对于接近岸边的Mesh,给予最高Lod(为了方便起见,我这边是最高lod才获得最多的细节),将获得最多的顶点数量,而远离岸边的水域,由于不需要过多细节,则给予较低的Lod,只会产生较少顶点,同时对于会被陆地遮挡的部分,则根本不产生顶点,这样即可保证岸边的浪花具有更多细节,如下改进后生成的网格:


被陆地遮挡部分不会产生多余的三角形


主要原理首先在渲染的深度图中额外增加一个通道渲染陆地和海水的交界处,然后将贴图划分成指定大小的网格,通过判断每个网格像素的极差简单判断该网格是否位于海水与陆地的交界处,如下标红点的网格即为交界处:


交界处的网格将获得最大Lod,和它相邻的网格的Lod则依次递减。

比较麻烦的地方在于不同lod的网格如何进行衔接,我的做法是根据不同lod的网格之间的衔接,网格中会发生变化的只有边缘处的三角,且只有低Lod与高Lod衔接时需要进行衔接处计算,因此容易找到衔接处的规律:

这种做法仍然存在不足之处,首先网格中的海水部分和陆地部分的像素占比是不同的,仅依靠极差并不一定准确,如下,蓝色箭头所指的网格实际上仅有一小部分为陆地,但仍然会分配到最大Lod,而紫色箭头所指的网格尽管完全位于海水处,但靠陆地非常近,却依然无法得到最大Lod:



第二种方式则是考虑使用四叉树的方式,先根据划分的最小单元格作为叶子节点(单元格数量只能为2的n次方个),并标记处位于海陆接缝处的节点:


然后进行递归,将每四个节点合并为一个新节点,对于四个节点都不为边界处网格的情况,可以合并为一个完整四边形,如下:


最终可以生成更少的顶点:



GitHub地址请访问博客原文:http://www.lsngo.net/2018/03/22/unity_seawave_vertexcolor/


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Unity】基于顶点色的海边波浪效果(适用移动端) 的相关文章

  • Unity中URP下的指数雾

    文章目录 前言 一 指数雾 雾效因子 1 FOG EXP 2 FOG EXP2 二 MixFog 1 ComputeFogIntensity 雾效强度计算 2 lerp fogColor fragColor fogIntensity 雾效颜
  • 在 Threejs 平面上渲染 TMX 地图

    使用新代码更新了问题 我正在尝试编写一个 WebGL 着色器来绘制TMX层 https github com bjorn tiled wiki TMX Map Format 从 Tiled 编辑器导出 我正在使用 THREE js 创建一个
  • Android 中图像的填充图案

    下面给出了两个图像 我将第一个图像称为帧图像 将第二个图像称为帧图像 这里 fst 是我的线性布局 我将帧图像设置为它的背景图像 现在我想在帧图像的白色区域中填充图案图像 帧图像的外部区域是透明的 内部区域是白色的 我如何在我的框架图像中填
  • 游戏开发常见操作梳理之小地图的制作

    游戏中一般存在小地图系统 实际上就是设置一个新的摄像机放置在玩家的正上方 然后在小地图上显示新摄像机看见的东西就可以了 在小地图上一般存在放大地图和缩小地图的按钮可以方便放大和缩小地图 这些操作是如何实现的呢 接下来直接上核心代码 usin
  • 游戏开发中常见系统梳理之背包系统的实现一

    游戏中几乎都存在大大小小的背包系统 接下来我将讲述背包系统具体是如何实现的 完整源码 以下是使用unity NGUI实现 使用txt配置的方法 后续更新UGUI Json实现的背包系统敬请期待 背包中的物品我们常常将其制作成预设体 通过改变
  • Qt3D默认制服和属性

    我开始学习通过 QML 使用着色器 但找不到任何讨论传递给着色器的默认统一和属性值的参考资料 在某些示例中 我们可以看到其中的几个 例如顶点位置 or 模型视图投影 这也被传递为mvp 但是没有包含我们可以使用的所有变量的清晰列表 在调查
  • 使用 LibGDX 的法线贴图 GLSL

    我尝试使用 LibGDX 实现法线贴图 因此 当我在顶点着色器中计算漫反射和镜面反射颜色时 我得到了一些积极的结果 至少我这么认为 顶点着色器 attribute vec4 a position attribute vec2 a texCo
  • 尝试制定一种算法,将图像附加到该主题

    我实际上正在尝试制作一种看起来像三次贝塞尔曲线的算法 但我想知道是否有更简单的解决方案 这就是我想要的 该图的长度为 1 高度为 1 红线是我的实际输入 黄点是给定的参数 我们可以称之为 扭曲 介于 0 和 1 之间 绿线就是我想要的结果
  • Directx 11,将多个纹理发送到着色器

    使用此代码我可以将一个纹理发送到着色器 devcon gt PSSetShaderResources 0 1 pTexture 当然 我通过以下方式制作了 pTexture D3DX11CreateShaderResourceViewFro
  • OpenGL Phong 光照:镜面高光错误

    我的 OpenGL 中的 Phong 光照着色器似乎有一个奇怪的问题 镜面高光出现在对象的错误一侧 手头的问题 正如您所看到的 镜面高光出现在立方体的另一侧 从灯光的角度来看 也出现在立方体垂直边缘的角上 它应该只出现在最靠近灯光的一侧 立
  • 用于在基于着色器的游戏中进行渲染的 OO 架构

    在构建游戏引擎时 我一直遇到这个问题 我的类希望看起来像这样 interface Entity draw class World draw for e in entities e draw 这只是伪代码 大致展示了绘图是如何发生的 每个实体
  • OpenGL 实现多通道

    我在移植一些已成功实现的代码时遇到问题着色玩具 https www shadertoy com view XdyfWK对于桌面 OpenGL 问题是我需要创建一个 FrameBufferObject FBO 以便我可以进行离屏计算 稍后将其
  • Three.js 使用 WebRTC 并应用 Shader

    我不知道如何将着色器应用于具有视频纹理的 Three js 对象 我一直在使用 webRTC 和 Three js 并使用标准材质成功将视频纹理映射到网格上 var material new THREE MeshBasicMaterial
  • 为什么我不能使用uniform1f而不是uniform4f来设置vec4制服?

    我通过以下方式逐步学习WebGL这本书 https sites google com site webglbook 我尝试通过使用缓冲区来绘制三个点 gl ARRAY BUFFER 而不是循环 正如我之前在本书的其他示例中所做的那样 var
  • 在Unity中如何使两个精灵的重叠区域透明?

    在Unity中如何使两个精灵的重叠区域透明 你能写一个关于它的着色器吗 经过一些研究 我了解到我应该使用模板缓冲区 但我不知道如何使用 这对我来说至关重要 我必须在 6 天内完成这个学校项目 请帮忙 示例图片 就这样 请记住这是我第一次使用
  • glUseProgram(0) 的作用是什么?

    OpenGL 文档为glUseProgram https www khronos org registry OpenGL Refpages gl4 html glUseProgram xhtml声称用参数调用它zero将导致着色器执行的结果
  • 您应该如何有效地批处理复杂的网格?

    渲染复杂网格的最佳方法是什么 我在下面写了不同的解决方案 想知道您对它们有何看法 让我们举个例子 如何渲染 Crytek Sponza 网格 PS 我不使用Ubershader 只使用单独的着色器 如果您通过以下链接下载网格 http gr
  • 更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3

    我正在尝试更改 Qt OpenGL 示例以使用更现代的 opengl 版本 330 似乎合适 所以我做了 在 main cpp 上设置版本和配置文件 设置着色器版本 更改着色器以使用统一 它现在构建没有任何错误 但我只看到一个空白窗口 我错
  • 在 Ubuntu 中与未编译的着色器链接

    我需要加载 glsl 来绘制一些东西 我的环境是Ubuntu 13 04 因此它不存在GLuint InitShader GLuint GLuint 这是我的对象创建 预链接步骤和链接的配置 不幸的是 它仍然出现错误 该错误与未编译的着色器
  • 在 QML 中控制纹理 3D 对象的不透明度

    我对 QML 中的 Qt 3D 有点陌生 我正在尝试控制 Qt 3D 的不透明度textured3D 对象 我正在使用简单qml3d https github com tripolskypetr simpleqml3d测试项目来做到这一点

随机推荐

  • 【华为OD机试】不开心的小朋友(C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 题目描述 游乐场里增加了一批摇摇车 非常受小朋友欢迎 但是每辆摇摇车同时只能有一个小朋友使用 如果没有
  • 信号与系统——初识到理解(第五章——傅立叶变换的应用)

    目录 第五章 傅立叶变换的应用 信号与系统的时频域特性 5 1 傅立叶变换的模和相位表示 5 2 无失真传输系统 讨论连续情况 离散时足以整数约束即可 5 3 系统相位 5 4 群时延 采样 5 5 通信中对信号的加工 5 6 冲击串采样
  • SM2可以使用私钥加密吗

    是的 SM2可以使用私钥加密 SM2是一种非对称加密算法 它使用公钥和私钥对数据进行加密和解密 私钥是保存在本地的密钥 只有拥有私钥的人才能使用它来加密数据或对已加密的数据进行解密 SM2的私钥加密功能可以用来保护数据的安全性 防止数据在传
  • 文件上传漏洞

    文件上传 文件上传是现代互联网常见的功能 允许用户上传图片 视频 及其他类型文件 向用户提供的功能越多 Web受攻击的风险就越大 文件上传漏洞 上传文件时 如果未对上传的文件进行严格的验证和过滤 就容易造成文件上传漏洞 上传脚本文件 包括a
  • 大数据学习01 -Linux 的简单使用

    1 NAT 网络地址转换 默认使用VMnet8 1 原理 子网掩码 和IP进行与操作 可以得到对应的子网IP 在那个网段上 IP 哪台机制 网关 路由器的IP dns 去dbs服务器查找域名对应的IP 常用命令 修改主机名 vi etc s
  • 13.罗马数字转整数

    这题转成字符数组后遍历就是了 罗马数字包含以下七种字符 I V X L C D 和 M 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如 罗马数字 2 写做 II 即为两个并列的 1 12 写做 X
  • 2023华为OD机试 报数游戏(Python)

    题目 输入 输入一个整数 n 代表有多少人 n 小于 1000 输出 告诉我最后剩下的那个人原来是第几个 示例 输入 2 输出 2 解释 两人围成一圈 第一个人数到3就走了 所以最后剩的是第二个人 理解 想象这样一个游戏 大家围成一圈 从第
  • C++:sort函数

    sort函数用于C 中 对给定区间所有元素进行排序 默认为升序 也可进行降序排序 sort函数进行排序的时间复杂度为n log2n 比冒泡之类的排序算法效率要高 使用sort函数要包含头文件为 include
  • Nginx实现四层代理与七层代理

    目录 一 实验环境准备 1 准备三台服务器 2 安装nginx环境 3 启动nginx环境 二 设置Nginx七层代理 1 proxy代理服务器配置 轮询 2 设置加权轮询 3 健康检测功能 4 解决重复登录问题 源地址哈希ip hash
  • 透视投影

    11
  • Idea使用Maven编译scala和打包jar

    下面Maven的pom文件
  • DBhelper的使用

    建立一个DbHelper cs类文件 复制内容 using System using System Data using System Data SqlClient using System Configuration using Syst
  • FreeImage例子

    http www pudn com downloads525 sourcecode windows detail2176862 html include OpenJPEG h include unistd h OpenJPEG OpenJP
  • fabric链码的编写-入门

    链码的编写 前言 fabric链码的编写较简单 在熟悉了基本结构和相关API之后就可上手编写 但是要多多练习 提高编写链码的速度和正确度 学习步骤 1 熟悉链码的基本结构 2 熟练链码相关API 3 练习 练习 练习 参考链接 https
  • day16 二叉树

    LeetCode110 平衡二叉树 二叉树的左右高度相差不超过1即可 package algor trainingcamp import algor junior algor tree TreeNode author lizhe versi
  • 循环的嵌套之求素数

    循环嵌套 前 学习了三种循环 while do while for 这三种循环往往会嵌套在 起才能更好的解决问题 就是我们所说的 循环嵌套 下面我们有一个经典的列题来将嵌套引用 找出100 200之间的素数 并打印在屏幕上 注 素数 称质数
  • Web项目中读取web目录下的readme.txt文本文档

    在Web项目中 读取web目录下upload文件夹里的readme txt文本文档 其中保存了字符 Hello World 具体的情况如下图所示 实现代码如下 package servlet import javax servlet Ser
  • 严重 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.StandardConte 一个或多个筛选器启动失败 idea(已解决)

    这是在整合SSM框架时遇到的bug Tomcat可以启动却不能自动跳转到主页 Connected to server 2020 08 09 03 46 21 864 Artifact ssmbuild war exploded Artifa
  • npm全局安装路径是哪儿呢?

    一般npm全局安装 npm install g xxx的xxx路径在哪儿呢 C Users user AppData Roaming npm node modules
  • 【Unity】基于顶点色的海边波浪效果(适用移动端)

    之前曾做过一个unity中带有海边波浪冲刷的海水shader效果 并最初发布在CSDN上 原文链接 http blog csdn net mobilebbki399 article details 50493117 不过最初的效果原先仅仅是