基于三平面映射的地形纹理化【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
相关文章:
基于三平面映射的地形纹理化【Triplanar Mapping】
你可能遇到过这样的地形:悬崖陡峭的一侧的纹理拉伸得如此之大,以至于看起来不切实际。 也许你有一个程序化生成的世界,你无法对其进行 UV 展开和纹理处理。 推荐:用 NSDT编辑器 快速搭建可编程3D场景 三平面映射(Trip…...
初步了解nodejs语法和web模块
在此, 第一个Node.js实例_js firstnode-CSDN博客 通过node运行一个简单的server.js,实现了一个http服务器; 但是还没有解析server.js的代码,下面看一下; require 指令 在 Node.js 中,使用 require 指令来…...
51单片机+EC11编码器实现可调参菜单+OLED屏幕显示
51单片机+EC11编码器实现可调参菜单+OLED屏幕显示 📍相关篇《stc单片机使用外部中断+EC11编码器实现计数功能》 🎈《STC单片机+EC11编码器实现调节PWM输出占空比》 🌼实际操作效果 🍁整个项目实现框架: 📓EC11接线原理图: 📓项目工程简介 📝仅凭借一个EC11编…...
数据结构刷题训练——二叉树篇(一)
📙作者简介: 清水加冰,目前大二在读,正在学习C/C、Python、操作系统、数据库等。 📘相关专栏:C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。 欢迎点赞 👍…...
2023版 STM32实战5 基本定时器中断
基本定时器简介与特性 -1-时钟可分频 -2-计数模式只可以选择累加 -3-只可以用来定时(含中断) 查看时钟源 如图定时器7的时钟最大为72MHZ 定时时间的计算 通用定时器的时间计算公式为 Tout ((arr1)(psc1&…...
css3实现页面元素抖动效果
html <div id"shake" class"shape">horizontal shake</div>js(vue3) function shake(elemId) {const elem document.getElementById(elemId)console.log(获取el, elem)if (elem) {elem.classList.add(shake)setTimeou…...
[架构之路-232]:操作系统 - 文件系统存储方法汇总
目录 前言: 一、文件系统存储方法基本原理和常见应用案例: 二、Windows FAT文件系统 2.1 概述 三、Linux EXT文件系统 3.1 基本原理 3.2 索引节点表(Inode Table) 3.2.1 索引节点表层次结构 3.2.2 间接索引表的大小和表项…...
简述 AOP 动态代理
一、AopAutoConfiguration 源码: Configuration(proxyBeanMethods false) ConditionalOnProperty(prefix "spring.aop", name "auto", havingValue "true", matchIfMissing true) public class AopAutoConfiguration {Configur…...
机器学习基础之《分类算法(8)—随机森林》
一、什么是集成学习方法 1、定义 集成学习通过建立几个模型组合的来解决单一预测问题。它的工作原理是生成多个分类器/模型,各自独立地学习和作出预测。这些预测最后结合成组合预测,因此优于任何一个单分类的做出预测 谚语:三个臭皮匠顶个诸…...
Python数据攻略-Pandas进行CSV和Excel文件读写
在数据分析的世界里,能够读取和写入不同格式的文件是一项基本而重要的技能。CSV(逗号分隔值)和Excel是两种常见的数据存储格式。它们在商业、科研、教育等多个领域都有广泛应用。 文章目录 读取CSV文件`pd.read_csv()` 文件读取函数的基本用法`DataFrame.to_csv()` 数据写入…...
lv7 嵌入式开发-网络编程开发 13 UNIX域套接字
1 UNIX 域流式套接字 本地地址 struct sockaddr_un {unsigned short sun_family; /* 协议类型 */char sun_path[108]; /* 套接字文件路径 */ };UNIX 域流式套接字的用法和 TCP 套接字基本一致,区别在于使用的协议和地址不同 UNIX 域流式套接字服务器端…...
blender光照系统设置
0)Viewport Shading设置里面的Lighting下面的参数: Scene Lights,Scene World - Scene Lights是指在渲染模式下是否使用场景中的灯光对象来照亮物体。 - Scene World是指在渲染模式下是否使用场景中的世界设置来作为背景和环境光。如果关闭该选项&#…...
华为云云耀云服务器L实例评测|基于canal缓存自动更新流程 SpringBoot项目应用案例和源码
前言 最近华为云云耀云服务器L实例上新,也搞了一台来玩,期间遇到各种问题,在解决问题的过程中学到不少和运维相关的知识。 在之前的博客中,介绍过canal的安装和配置,参考博客 拉取创建canal镜像配置相关参数 & …...
vue3 中使用echarts图表——柱状图
柱状图是比较常用的图形结构,所以我先收集一些精美的柱状图 一、柱状图:设置圆角和颜色 <template><div class"box" ref"chartDom"></div> </template> <script setup> import { ref, onMounted } fr…...
基于Java的家政公司服务平台设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…...
深入了解 PostgreSQL:功能、特性和部署
PostgreSQL,通常简称为Postgres,是一款强大且开源的关系型数据库管理系统(RDBMS),它在数据存储和处理方面提供了广泛的功能和灵活性。本文将详细介绍 PostgreSQL 的功能、特性以及如何部署和使用它。 什么是 PostgreSQ…...
平台项目列表页实现(二)
这里写目录标题 一、顶部盒子设计1. 顶部盒子包含项目列表和添加项目、退出登录2个按钮 二、项目列表盒子设计三、添加项目盒子设计四、退出登录功能实现五、路由导航守卫实现六、展示项目信息七、bug修复1、当项目名称太长或者项目负责人太长,需要一行展示…...
osg实现鼠标框选
目录 1. 需求的提出 2. 具体实现 2.1. 禁止场景跟随鼠标转动 2.2. 矩形框前置绘制 3. 附加说明 3.1. 颜色设置说明 3.2.矩形框显示和隐藏的另一种实现 1. 需求的提出 有时需要在屏幕通过按住键盘上的某个键如Ctrl键且按住鼠标左键,拖出一个矩形,实现框…...
电路原理解题笔记(一)
文章目录 贼基础的知识等效电阻基尔霍夫电流定律电阻电路的一般分析支路电流法节点电压法回路电流法 电路定理叠加定理戴维宁等效电路诺顿等效电路求某电阻值为多少可吸收最大功率。吸收、释放功率 第一个月,对应猴博士的一到五课时。 贼基础的知识电阻电路的等效变…...
分享几个优秀开源免费管理后台模版,建议收藏!
大家好,我是 jonssonyan 今天和大家分享一些免费开源的后台管理页面,帮助大家快速搭建前端页面。为什么要用模板?道理很简单,原因是方便我们快速开发。我们不应该花太多的时间在页面调整上,而应该把精力放在核心逻辑和…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...
