基于三平面映射的地形纹理化【Triplanar Mapping】

你可能遇到过这样的地形:悬崖陡峭的一侧的纹理拉伸得如此之大,以至于看起来不切实际。 也许你有一个程序化生成的世界,你无法对其进行 UV 展开和纹理处理。
在这里插入图片描述

推荐:用 NSDT编辑器 快速搭建可编程3D场景

三平面映射(Triplanar Mapping)提供了一种优雅的技术来解决这些问题,并为你提供来自任何角度或任何复杂形状的逼真纹理。 在本文中我们将了解该技术,查看代码,并了解使用三平面映射时的一些优点、缺点和其他可能性。

1、地形纹理化的UV问题

最常见的问题是纹理拉伸,尤其是在地形方面。 问题在于正在纹理化的对象的 UV 坐标。 对于地形,UV 坐标分布在网格中,在 X-Y 平面上均匀分布,如下所示:
在这里插入图片描述

上图中的UV 布局未考虑地形的高度差并导致拉伸。 你可以采取措施,通过仔细展开 UV 坐标来均匀陡峭多边形的区域,但这会导致结果不太理想。 你仍然有扭曲的纹理,并且一些图块(例如中间的图块)被压缩。
在这里插入图片描述

你也可能无法展开网格物体 UV 坐标:可以通过程序生成地形或形状。 也许你的形状中有一个洞穴系统或洞。

我们可以使用三平面映射技术(也称为“三平面纹理”)来解决这些问题。

2、基于Triplanar映射的地形纹理化

首先,让我们再次查看应用了三平面映射的地形:

在这里插入图片描述

使用三平面映射的地形

现在好多了! 拉伸消失了,陡峭的斜坡看起来更加真实。

Triplanar映射通过在 3 个不同的方向(X、Y 和 Z 轴)上渲染纹理 3 次来实现此目的。 想象一个盒子。 首先,纹理从正 X 轴向下投影到负 X 轴。 面向 X 轴方向的任何片段(几何体的像素)都会应用纹理。 Y轴和Z轴也进行同样的处理。

这些渲染混合在一起。 因此,一半面向 X 轴、一半面向 Z 轴的片段将占用一半的 X 轴渲染和一半的 Z 轴渲染。 如果片段的 90% 面向 X 轴,则它会接收 90% 的 X 轴渲染,而仅接收 10% 的 Z 轴渲染。 就像拿3个喷雾罐,从顶部、侧面、正面喷射。

在这里插入图片描述

从 3 个角度投射的纹理

所有这些都是在材质的片段着色器中完成的。 它本质上对几何体进行 3 次纹理处理,每个方向一次,然后混合结果。

Triplanar映射根本不使用 UV 坐标。 相反,它使用实际的世界坐标。 知道了这一点,我们来看看代码。

第一部分计算每个方向的混合因子:

// in wNorm is the world-space normal of the fragment 
vec3 blending = abs( wNorm );
blending = normalize(max(blending, 0.00001)); // Force weights to sum to 1.0 
float b = (blending.x + blending.y + blending.z);
blending /= vec3(b, b, b);

这里它采用片段的世界空间法线(它将被标准化,并且每个分量将在 -1 和 1 的范围内),我们将其设为绝对值。 我们不关心法线是否面向 -X 或 X,只要它位于 X 轴即可。 如果我们确实担心绝对方向,我们就会从前、后、左、右、上、下绘制形状; 比我们需要的多3倍。

接下来我们强制它在 0 到 1 的范围内,因此我们最终得到每个轴分量的百分比乘数。 如果法线在 Y 轴上朝上,我们得到的 Y 值为 1,它会得到所有 Y 轴绘画,而其他轴的值为 0,不会得到任何结果。

这是最困难的部分。 接下来,我们将三个混合值 (x,y,z) 与该纹理坐标处的纹理混合。 请记住,纹理坐标位于世界空间中:

vec4 xaxis = texture2D( rockTexture, coords.yz);
vec4 yaxis = texture2D( rockTexture, coords.xz);
vec4 zaxis = texture2D( rockTexture, coords.xy);
// blend the results of the 3 planar projections. 
vec4 tex = xaxis * blending.x + xaxis * blending.y + zaxis * blending.z;

我们终于得到它了。 tex是片段的最终颜色,从 3 个轴混合 3 次。

将比例因子应用于纹理会非常方便,因为你无疑会想要缩放它:

// in float scale 
vec4 xaxis = texture2D( rockTexture, coords.yz * scale);
vec4 yaxis = texture2D( rockTexture, coords.xz * scale);
vec4 zaxis = texture2D( rockTexture, coords.xy * scale);
vec4 tex = xaxis * blending.x + xaxis * blending.y + zaxis * blending.z;

3、法线的处理方法

如果你使用三平面映射和法线贴图,还需要对片段着色器中的法线应用相同的过程,如下所示:

vec4 xaxis = texture2D( rockNormalTexture, coords.yz * scale);
vec4 yaxis = texture2D( rockNormalTexture, coords.xz * scale);
vec4 zaxis = texture2D( rockNormalTexture, coords.xy * scale);
vec4 tex = xaxis * blending.x + xaxis * blending.y + zaxis * blending.z;

小技巧:
可以创建 getTriPlanarBlend() 函数来计算漫反射、法线和镜面纹理的混合。

4、Triplanar映射的问题

你将遇到的第一个问题是性能。 几何体的片段将被渲染 3 次,每个方向一次。 这意味着颜色和照明计算(法线)将被重复然后混合。 如果已经有空闲帧问题,可能不想使用三平面映射。

下一个重大问题是 45 度角的混合,尤其是在使用纹理泼溅的地方不同纹理重叠的情况。 你可以从角点再执行 4 次渲染,但这样做所带来的性能损失可能不值得。 你可以尝试与深度图混合,这是一种有时用于纹理泼溅的技术。

在这里插入图片描述

可见的透明重叠

5、结束语

现在我们理解了三平面贴图的工作原理及其用途。 但它还有许多其他应用程序,可以稍微改变它以产生有趣的结果。

如前所述,程序化地形是该技术的良好候选者。 洞穴、悬崖和复杂的熔岩隧道现在很容易纹理化。 你甚至可以根据一些随机或伪随机(噪声)例程来影响使用的纹理。 标高甚至坡度可以决定使用什么纹理。

通过修改例程以仅从顶部(y 轴)投影纹理并将混合值牢固地限制在可接受的范围内,即 10%,那么你可以在场景中所有物体的顶部渲染雪。 使用相同的技术,原子爆炸可以烧焦从某个世界坐标原点辐射出的所有物体,但基于原点的角度并使用暗烧纹理。


原文链接:地形纹理Triplanar映射 — BimAnt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/130050.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【可视化大屏】用该软件,无代码,更易用

奥威BI系统是一种自助式BI数据可视化工具,它可以在无代码的情况下,通过简单的拖拉拽实现数据可视化,并支持多种数据源接入,包括各类数据库、Excel、API接口等,只需简单的输入数据源连接地址即可,操作非常方…

[UE虚幻引擎] DTCopyFile 插件说明 – 使用蓝图拷贝复制文件 (Windows)

本插件可以在虚幻引擎中使用蓝图对系统的其他文件进行拷贝复制操作。 1. 节点说明 Async Copy File ​ 异步复制文件 Param Source File : 要复制的源文件的完整路径。Param Target File : 要复制的目标文件的完整路径。Param Force Copy : 如果为true,则如果目标…

大模型部署手记(13)LLaMa2+Chinese-LLaMA-Plus-2-7B+Windows+LangChain+摘要问答

1.简介: 组织机构:Meta(Facebook) 代码仓:GitHub - facebookresearch/llama: Inference code for LLaMA models 模型:chinese-alpaca-2-7b-hf、text2vec-large-chinese 下载:使用百度网盘和…

手机没电用日语怎么说?你会吗?柯桥常用日语学习

手机没电在日语里可以表达为: 1. スマホの電池が切れた。 直接使用“電池が切れる”来表示电池没有电了。 2. スマホのバッテリーが空に15857575376なった。 “バッテリーが空になる”也是表示电量耗尽的常用表达。 3. 充電が必要だ。 “充電が必要”意思是需要充电。 4…

linux 安装下载conda并创建虚拟环境

目录 1. 下载安装2. 创建虚拟环境1. 下载安装 在window操作系统中下载anconda包,并通过scp传输到ubuntu操作系统 具体anconda包在如下界面: anconda包 目录 博主选择了最新的包:Anaconda3-2023.09-0-Linux-x86_64.sh 通过scp传输到ubuntu操作系统中: 并在ubuntu操作系…

微信小程序--》从模块小程序项目案例23.10.09

配置导航栏 导航栏是小程序的门户,用户进来第一眼看到的便是导航栏,其起着对当前小程序主题的概括。而我们 新建的小程序 时,第一步变开始配置导航栏。如下: 配置tabBar 因为配置tabBar需要借助字体图标,我这里平常喜…

读懂MCU产品选型表

读懂MCU产品选型表 产品状态 MP:Mass Production(大规模生产) - 这表示产品已经进入了大规模生产阶段,可以大量生产并提供给市场。UD:Under Development(开发中) - 这表示产品目前正在开发阶段…

京东数据分析平台:2023年8月京东奶粉行业品牌销售排行榜

鲸参谋监测的京东平台8月份奶粉市场销售数据已出炉! 鲸参谋数据显示,8月份京东平台上奶粉的销售量将近700万件,环比增长约15%,同比则下滑约19%;销售额将近23亿元,环比增长约4%,同比则下滑约3%。…

leetCode 167.两数之和 || - 输入有序数组 双指针解法

167. 两数之和 II - 输入有序数组 - 力扣(LeetCode) 给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] …

KWin、libdrm、DRM从上到下全过程 —— drmModeAddFBxxx(2)

接前一篇文章:KWin、libdrm、DRM从上到下全过程 —— drmModeAddFBxxx(1) 上回书说到drmModeAddFB、drmModeAddFB2和drmModeAddFB2WithModifiers函数最终“三分归一统”,在内核层统一调用到drm_mode_addfb2函数。 这里我们先不急…

从零开始的C++(八)

1.类和模版的补充: 1、本质:原本由程序员自己写的一些高度重复的函数改由编译器来写。 模版实例化:编译阶段生成函数;分为隐式调用和显示调用两种,隐式调用是由编译器根据传入参数的类型来决定模版的类型&#xff0c…

maven依赖下载失败原因分析;_remote.repositories简述

概述 我的maven版本3.6.3 有时在下载maven依赖时,提示某个仓库中没有对应依赖,此时去提示的仓库上找,的确没有,那么通常会加入mirror拦截一下依赖请求,指向到mirrot中的仓库,但是此时仍提示相同的错误。 …