当前位置: 首页 > news >正文

真实景观渲染技巧【Three.js】

受到一些很棒的 three.js 演示、与 covid 相关的旅行禁令以及可能在 pinterest 上花太多时间看美丽的旅行照片的启发——我开始看看我是否可以使用 three.js 和r3f在浏览器中渲染一个令人信服的风景场景。

在这里插入图片描述

推荐:将 NSDT场景编辑器 加入你的3D开发工具链。

在过去一个月左右的时间里,我一直在尝试不同的方法,并在互联网上搜索有关如何使用浏览器技术渲染半现实景观的技巧。 我发现它很有价值,但也比我预期的要难得多。

我整理了一份简短指南,总结了我从 A 到 B 所使用的技巧和技巧:
在这里插入图片描述

TLDR:
我使用特定于地形的自定义实用程序扩展了 three.js 标准材质。 这种经过修改的材质使用多种纹理来为地形着色、塑造和照亮地形。 我对这些纹理中的一些进行平铺和分层,以确保地形在更大的观看距离范围内看起来不错。

我选择从一个名为 world creator 的图形用户界面生成和导出地形数据。在线演示可以访问这里,源码托管在GitHub。

1、技术

我将这篇文章结构化为我用来改进渲染的技术列表,而不是冗长的教程。 对于每一种技术,我都会提供一个简短的描述,如果你不熟悉它,这应该可以帮助你定位。 我还将提供一个提示/技巧部分,该部分应该阐明我如何在示例场景中使用该技术。 我希望这将使它对不同技能水平的人更容易浏览和有用。

动机限制:

  • 你的几何图形越多,gpu 必须做的工作就越多。 如果没有尖端的几何虚拟化技术,在当前的硬件上不可能以 100% 的保真度实时渲染地形大小的对象。
  • 我们可以在合理时间内下载的纹理大小有限制
  • 可以使用 webGL 移动到 gpu 内存中的纹理纹理的大小是有限制的。 在旧手机上它可以低至 1024x1024
  • webGL 允许你在单个对象上使用的纹理数量有限制(16)

工具:

  • React(抱歉我忍不住)
  • Three.js(很棒的3d渲染库)
  • React-three-fiber(让你在 jsx 中使用 three.js)
  • World Creator(用于制作渲染场景所需的各种纹理)

React + r3f 并不是绝对必要的,但将这些概念应用到 vanilla three.js 设置中应该很容易。 另请注意,World creator 不是免费的,但有很多替代方法可以生成高度图等。

2、高度/位移图

高度图将地形的垂直高度编码为从 0(黑色)到 1(白色)的像素值。 Three.js 内置处理位移的代码(顶点着色器)。 位移贴图(displacement map)可用于 3d 对象,但对于风景,我只使用了一个简单的平面。 最主要的是确保你的比例与生成高度图的任何程序或工具相匹配。 可以使用 displacementScale 和 displacementBias 来使 three.js 的比例匹配。

高度图是这样的图像:

在这里插入图片描述

提示:对于高度图中的每个像素,你至少需要对平面进行一次细分,否则three.js 着色器将不会有一个关联的顶点来定位。

技巧:除非相机靠近地面,否则高度图不需要特别高分辨率。 在上面的示例中,我使用了 1024*1024 高度图。 使地形看起来不错的大部分细节都来自法线贴图和漫反射贴图。

限制:2d 高度图无法表示 3d 地形细节,如洞穴或悬垂。

3、大气雾

过度简化天空“是蓝色的”,所以当你看它实际上把它背后的东西染成蓝色。 雾在 three.js 场景中是一种常见的技术,但它在风景中尤为重要,因为它可以帮助观众理解山丘、树木等的规模和排列:

<fog attach="fog" args={["#74bbd0", 300, 1800]} />

注意:使用的材质需要知道如何正确渲染雾。 如果你不扩展 three.js 材质,这将不会自动工作。

4、HDRI 照明

HDRI(高动态范围图像)是一种环绕场景的大纹理,可作为 PBR 材质的更逼真光源。 我喜欢光线具有更自然的方向和颜色,但找到适合我的场景的光线有点费力。 也就是说,我认为这是值得的,因为照明设置是对场景质量和气氛影响最大的因素之一。

在这里插入图片描述

// I used the Environment component from Drei with one of the preset HDRIs
import { Environment } from "@react-three/drei"export default Landscape(){return (// landape mesh ect...// hdri<Environment preset="park" />)
}

提示:

  • polyhaven 是 HDRI 的重要来源网站。
  • 尝试使用不同的 HDRI 和环境光级别。

技巧:尝试使用标准网格材质的 normalScale、 envMapIntensity 和 metalness 参数。 它们使你可以对对比度、颜色深度和亮度进行大量控制。

5、SPLAT纹理

对于大多数 3d 对象,我们使用称为漫反射纹理的单一纹理来应用颜色。 如果我们放大到接近地形大小的对象,这很快就会崩溃,因为每次将其尺寸加倍时,图像的文件大小/内存影响不会线性缩放。 在地形大小的对象上应用单个漫反射纹理会变得模糊或过大。

从逻辑上讲,我们应该能够通过混合和重复多个较小的纹理来解决这个问题,每个纹理对应一种地形类型(草地、泥地、岩石等)。

纹理splat是一种方法。 它的工作原理是获取多个纹理并将它们与另一个称为 splat 纹理的纹理中的颜色通道相关联。 splat 纹理中的一个像素被渲染为 100x100 图像 - 取决于我们的纹理大小和它们重复的次数 - 使得 splat 纹理明显小于相同细节级别的漫反射纹理。

这是 splat 纹理:
在这里插入图片描述

例如,如果 splat 中的像素是纯红色,那么我们将该区域渲染为泥土,如果它是纯绿色,则将其渲染为草地,如果它是红色和绿色的混合,那么我们可以线性组合瓷砖纹理的 rgb 值以 更自然地融合在草地和泥泞地区之间。 混合对于防止它看起来像 Minecraft 地图至关重要。

// inside the main function of the fragment shader ...
vec4 diffuse1 = texture2D(uDiffuse1, uv * 100.0);
vec4 diffuse2 = texture2D(uDiffuse2, uv * 100.0);
vec4 splat1 = texture2D(uSplat1, uv);vec4 color = diffuse1 * splat1.r + diffuse2 * splat1.g;diffuseColor = vec4( color.rgb, opacity );

提示:World creator 以 TGA 格式导出 splat 纹理,我以前从未听说过这种格式,并且发现使用起来有些困难,但幸运的是,Three.js 示例包含一个 TGA 加载器,可以处理将 .tga 文件加载到数据纹理中。

局限性:纹理平铺会导致明显的纹理重复,我们将在下面解决:

6、隐藏纹理重复

虽然这样做很容易,但没有什么要求我们将纹理放置在会产生不良平铺效果的网格图案类型中。 Inigo Quilez 有一篇关于修复纹理重复的多种方法的好文章,我在我的场景中使用了它。

简单的说,该技术本质上归结为使用随机噪声纹理和一些数学来更有机地在网格表面上无缝地放置和混合纹理。
在这里插入图片描述

// use instead of texture2D
vec4 textureNoTile( sampler2D samp, vec2 uv ){// sample variation patternfloat k = texture2D( uNoise, 0.005*uv ).x; // cheap (cache friendly) lookup// compute indexfloat l = k*8.0;float f = fract(l);float ia = floor(l);float ib = ia + 1.0;// offsets for the different virtual patternsfloat v = 0.4;vec2 offa = sin(vec2(3.0,7.0)*ia); // can replace with any other hashvec2 offb = sin(vec2(3.0,7.0)*ib); // can replace with any other hash// compute derivatives for mip-mappingvec2 dx = dFdx(uv), dy = dFdy(uv);// sample the two closest virtual patternsvec3 cola = texture2DGradEXT( samp, uv + v*offa, dx, dy ).xyz;vec3 colb = texture2DGradEXT( samp, uv + v*offb, dx, dy ).xyz;// // interpolate between the two virtual patternsvec3 col = mix( cola, colb, smoothstep(0.2,0.8,f-0.1*sum(cola-colb)) );return vec4(col,1.0);
}

7、法线贴图

他们让我们在给定点对表面的“正常”角度进行编码。 这有点 hack,但它有助于确定从该物体反射到相机的光量,使我们能够平滑或创建额外的细节,而无需渲染额外的三角形。 同样,这是 THREE.js 物理材质中内置的内容。

在这里插入图片描述

提示:在岩石等细节物体上使用法线贴图比使用你能找到的最高分辨率漫反射纹理重要得多。

8、多层次的法线

World Creator 导出整个地形的法线贴图,但也导出我们在景观中平铺的岩石纹理的法线贴图:
在这里插入图片描述

理想情况下,场景将受益于宏观悬崖面法线以及水平法线的更细微的凹凸和裂缝。 不幸的是,如果只是将法线纹理添加在一起,它们会变得浑浊和/或在某些地方会出现超级亮点或暗点。

Stephen Hill 对问题和可能的解决方案有很好的总结 , 它给着色器增加了一些复杂性,但在我看来这是值得的:

在这里插入图片描述


// adapted from original article so more than two normals can be blended
vec4 blend_normals(vec4 n1, vec4 n2){vec3 t = n1.xyz*vec3( 2,  2, 2) + vec3(-1, -1,  0);vec3 u = n2.xyz*vec3(-2, -2, 2) + vec3( 1,  1, -1);vec3 r = t*dot(t, u) /t.z -u;return vec4((r), 1.0) * 0.5 + 0.5;
}//usage:
vec4 blend = blend_normals(n1, n2);
vec4 triblend = blend_normals(blend, n3);

提示:当以不同的比例重复时,使用多个法线往往效果最好。 尽管上述技术在数学上比简单的线性组合更正确,但我发现应用多个相同大小的法线最终看起来就像随机噪声。 在演示岩石中,我使用一个大的用于景观细节,一个中等的用于岩石中的峭壁,一个小的用于额外的凹凸纹理。

9、未来的改进

实施基于四叉树的细节系统和纹理流以在相机附近渲染更高清晰度的纹理可以提高质量并减少初始加载时间。

用于渲染摇曳的草地或渲染摄像机附近的苔藓的植被系统也有助于提高场景的保真度,使你可以使用第三人称控制器在地图上四处走动。


原文链接:Three渲染真实景观 — BimAnt

相关文章:

真实景观渲染技巧【Three.js】

受到一些很棒的 three.js 演示、与 covid 相关的旅行禁令以及可能在 pinterest 上花太多时间看美丽的旅行照片的启发——我开始看看我是否可以使用 three.js 和r3f在浏览器中渲染一个令人信服的风景场景。 推荐&#xff1a;将 NSDT场景编辑器 加入你的3D开发工具链。 在过去一个…...

MySQL知识汇总:MySQL函数CASE WHEN用法详解

Case When的两种简单用法 用法一&#xff1a; CASE seasonWHEN Spring THEN 春天 WHEN Summer THEN 夏天 WHEN autumn THEN 秋天 else 冬天 end 用法二&#xff1a; CASE WHEN season Spring THEN 春天WHEN season Summer THEN 夏天WHEN season autumn THEN 秋天 els…...

Python学习-----模块1.0(模块的简介、定义与使用)

目录 前言&#xff1a; 1.什么是模块 2.模块的分类 &#xff08;1&#xff09;内置模块 &#xff08;2&#xff09;第三方模块 &#xff08;3&#xff09;自定义模块 3.模块的使用 4.自定义模块 5.模块和执行文件的判断 前言&#xff1a; 今天就开始讲Python中的模块篇…...

Linux进程学习【二】

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f38a;每篇一句&#xff1a; 图片来源 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 Perseverance is not a long race; it is many short races one after another…...

我问chatGPT,在JavaScript中构造函数和类的区别

问&#xff1a;构造器函数和面向中的类是同样的东西吗|&#xff1f; 答&#xff1a;构造器函数和面向对象中的类并不是同样的东西&#xff0c;它们之间有些许不同。 在面向对象编程中&#xff0c;类是一种抽象的概念&#xff0c;它描述了一类具有相同属性和行为的对象。类可以…...

软考高级-信息系统管理师之沟通管理(最新版)

项目沟通管理 1、项目沟通管理基础项目沟通管理的重要性项目沟通管理相关理论2、规划沟通管理3、管理沟通4、控制沟通项目沟通管理的技术和工具1、项目沟通管理基础 项目沟通管理的重要性 1、与1T项目成功有关的最重要的四个因素是:主管层的支持、用户参与、有经验的项目经理…...

PyQt5 自定义富文本编辑器

介绍 一款使用PyQt5和网页端框架wangEditor集成的富文本编辑器 代码片段 PyQt5客户端 与网页端建立连接def create_connect(self):self.web_view QWebEngineView()self.bridge JSBridge(self.web_view.page())self.web_view.load(QUrl.fromLocalFile(self.editor_path))w…...

【高可用系统架构设计】SLA服务可用性4个9是什么意思?如何保证服务的高可用性 HA(High Availability)?...

如何保证服务的高可用性 HA&#xff08;High Availability&#xff09;?高可用HA&#xff08;High Availability&#xff09;是分布式系统架构设计中必须考虑的因素之一&#xff0c;它通常是指&#xff0c;通过设计减少系统不能提供服务的时间。方法论上&#xff0c;高可用是通…...

微服务架构设计模式-(14)面向生产环境

生产环境要求 应用安全 数据权限 服务可配置性 不同环境的配置不一样&#xff0c;不能写死代码&#xff0c;所以要配置 可观测性 需要日志系统 应用安全 四个方面 身份验证 验证主体的身份解决方案 单体 cookie 微服务中 API Gateway 访问令牌 不透明令牌透明令牌&#xff…...

HTML5新增用法

新增语义化标签 并无特殊含义&#xff0c;是语义&#xff01;语义&#xff01;语义&#xff01; <header> 头部区域 <nav> 导航区域 <main> 主体区域 <article> 内部标签 <section> 块级标签 <aside> 侧边栏标签 <footer> 尾部…...

富足金字塔:人的努力是为了扩大选择的范围

人的努力是为了扩大选择的范围&#xff0c;这是熵减的另一种表述。富足金字塔代表着人生的三重境界。第一层是温饱。人需要食物、水、住所。第二层是品质。能源、ICT、教育带来更有品质的生活&#xff0c;如智能门锁、智能马桶、扫地机、洗碗机、洗衣烘衣机。第三层是梦想。包括…...

C++类基础(十七)

类的继承——补充知识 ● public 与 private 继承&#xff08;C Public, Protected and Private Inheritance&#xff09; 改变了类所继承的成员的访问权限 //公有继承 struct Base { public:int x; private:int y; protected:int z; }; struct Derive : public Base //公有继承…...

LeetCode刷题复盘笔记—一文搞懂贪心算法之56. 合并区间(贪心算法系列第十四篇)

今日主要总结一下可以使用贪心算法解决的一道题目&#xff0c;56. 合并区间 题目&#xff1a;56. 合并区间 Leetcode题目地址 题目描述&#xff1a; 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间…...

Andriod入门级开发

这学期有个课设&#xff0c;我们组我负责一个手机APP的开发&#xff0c;虽然刚开始说要实现什么智能导航&#xff0c;类似高德地图那种&#xff0c;但最后阉割的只剩一个Socket通信了&#xff0c;因为之前没有接触过&#xff08;可能之后也不会再接触&#xff09;&#xff0c;记…...

DCL 数据控制语言

1、简介 DCL英文全称是Data Control Language(数据控制语言)&#xff0c;用来管理数据库用户、控制数据库的访问权限。 2、管理用户 2.1 查询用户 select * from mysql.user;查询的结果如下: 其中 Host代表当前用户访问的主机, 如果为localhost, 仅代表只能够在当前本机访问…...

全网超详细的下载与安装VMware虚拟机以及为什么要安装VMware虚拟机

文章目录1. 文章引言2. 下载VMware3. 安装VMware1. 文章引言 我们使用最多的系统是windows系统&#xff0c;因为&#xff0c;国内电脑厂商的操作系统(os)基本是windows系统&#xff0c;比如华为、联想、华硕等电脑。 但线上的服务器大多是Linux系统&#xff0c;而我们经常使用…...

Python获取zabbix问题触发器

背景&#xff1a;阿里云的ECS服务器因为阿里云升级插件&#xff0c;导致安全防护程序重启&#xff0c;产生不同的端口。导致低自动发现注册的端口 大量报警。 解决&#xff1a;杀掉关于因为非业务 变更的端口检测的触发器。 相关文档&#xff1a; Zabbix监控之主机端口监控自…...

原型链污染

目录 前置知识 原型对象 prototype和__proto__的区别 原型链概念 原型链的继承 原型 链污染 原型链污染原理 javascript中可能会存在原型链污染的危险函数 原型链污染的实际应用 JavaScript中可以触发弹窗的函数 前置知识 原型对象 在JavaScript中&#xff0c;每个函…...

ClickHouse详解

一、概念ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。OLAP场景的关键特征绝大多数是读请求数据以相当大的批次(> 1000行)更新&#xff0c;而不是单行更新;或者根本没有更新。已添加到数据库的数据不能修改。对于读取&#xff0c;从数据库中提取相当多的…...

02_Docker 安装

02_Docker 安装 文章目录02_Docker 安装2.1 安装 Docker 的先决条件2.2 在 Ubuntu 和 Debain 中安装 Docker2.2.1 检查前提条件1. 内核2.检查 Device Manager2.2 安装 DockerDocker 支持非常多的Linux平台&#xff0c;包括Ubuntu和RHEL&#xff0c;除此之外&#xff0c;Docker还…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天&#xff0c;通信网络的角色正变得愈发关键。 2025年6月6日&#xff0c;为期三天的华南国际工业博览会在深圳国际会展中心&#xff08;宝安&#xff09;圆满落幕。作为国内工业通信领域的技术型企业&#xff0c;光路科技&#xff08;Fiberroad&…...

Python训练营-Day26-函数专题1:函数定义与参数

题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一个名为 calculate_circle_area 的函数&#xff0c;该函数接收圆的半径 radius 作为参数&#xff0c;并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求&#xff1a;函数接收一个位置参数 radi…...

简约商务通用宣传年终总结12套PPT模版分享

IOS风格企业宣传PPT模版&#xff0c;年终工作总结PPT模版&#xff0c;简约精致扁平化商务通用动画PPT模版&#xff0c;素雅商务PPT模版 简约商务通用宣传年终总结12套PPT模版分享:商务通用年终总结类PPT模版https://pan.quark.cn/s/ece1e252d7df...