three.js标准网格材质(MeshStandardMaterial)光照、粗糙度、金属度、法线属性介绍

news2024/11/8 21:52:01

在这里插入图片描述
如上图,在前面的章节中我们通过设置物体的纹理和材质实现了一个3d的立体门框的效果
完整代码如下:

import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

// 目标:纹理常用属性 偏移、旋转、重复、中心点
// 1、创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x003261); // 将背景色设置为蓝色

// 2、创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

// 设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera);

// 导入纹理
const textureLoader = new THREE.TextureLoader();
const doorColorTexture = textureLoader.load("./textures/door/color.jpg");
const doorAplhaTexture = textureLoader.load("./textures/door/alpha.jpg");
const doorAoTexture = textureLoader.load(
  "./textures/door/ambientOcclusion.jpg"
);

// 添加物体
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1);
// 材质
const basicMaterial = new THREE.MeshBasicMaterial({
  map: doorColorTexture,
  alphaMap: doorAplhaTexture,
  transparent: true,
  aoMap: doorAoTexture,
  aoMapIntensity: 1
  // opacity: 0.3,
  //   side: THREE.DoubleSide,
});
basicMaterial.side = THREE.DoubleSide;
const cube = new THREE.Mesh(cubeGeometry, basicMaterial);
scene.add(cube);
// 给cube添加第二组uv
cubeGeometry.setAttribute(
  "uv2",
  new THREE.BufferAttribute(cubeGeometry.attributes.uv.array, 2)
);

// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// console.log(renderer);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);

// // 使用渲染器,通过相机将场景渲染进来
// renderer.render(scene, camera);

// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
controls.enableDamping = true;

// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

function render() {
  controls.update();
  renderer.render(scene, camera);
  //   渲染下一帧的时候就会调用render函数
  requestAnimationFrame(render);
}

render();

// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {
  //   console.log("画面变化了");
  // 更新摄像头
  camera.aspect = window.innerWidth / window.innerHeight;
  //   更新摄像机的投影矩阵
  camera.updateProjectionMatrix();

  //   更新渲染器
  renderer.setSize(window.innerWidth, window.innerHeight);
  //   设置渲染器的像素比
  renderer.setPixelRatio(window.devicePixelRatio);
});

接下来我们继续通过设置物体的PBR材质和HDR环境贴图,让这个门框更加的真实

什么是PBR?
PBR代表物理上逼真的渲染,是一种在计算机图形学中用于模拟光线如何从材料反射,折射和吸收的方法。在three.js中,PBR包含使用物理基础渲染代码和材料处理技术来模拟光线和材料之间的物理相互作用,以创建逼真的材料外观和光照效果。这种渲染技术可以提供更真实的阴影,高光,反射和漫反射效果,使场景看起来更加真实。

一、设置光照

在这里插入图片描述
three.js官网中说标准的网络材质是支持PBR的,所以我们将以前的用MeshBasicMaterial生成的材质,改为MeshStandardMaterial

// 材质
const basicMaterial = new THREE.MeshStandardMaterial({
  map: doorColorTexture,
  alphaMap: doorAplhaTexture,
  transparent: true,
  aoMap: doorAoTexture,
  aoMapIntensity: 1
  // opacity: 0.3,
  //   side: THREE.DoubleSide,
});

更改完的效果如图:
在这里插入图片描述
此时上面所有的贴图都看不到了,这是因为通过MeshStandardMaterial生成的标准网络材质需要配合灯光才能显示

如下:

// 环境光
// 参数 1:光源颜色 2:光源强度
const light = new THREE.AmbientLight(0xffffff, 1); // soft white light
scene.add(light);

我们在场景中添加上灯光,效果如图:
在这里插入图片描述
这样我们的门框又可以显示拉。

接下来我们设置一下环境光源,让这个门框有一种处在真实的光照下的效果,

//直线光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(10, 10, 10);
scene.add(directionalLight);

效果如图:
在这里插入图片描述
此时在没有直线光源照射到的背面,就有一种阴影的效果,看上去是不是更加真实了呢?

二、置换贴图,让门框更具立体感

在这里插入图片描述
如上图,这里我们的门框效果还是一个完全的平面图,没有立体效果。
想要门框具有立体效果我们可以使用材质的displacementMap属性进行设置,具体修改如下:


//导入置换贴图
const doorHeightTexture = textureLoader.load("./textures/door/height.jpg");
// 参数:长、宽、高、长分段、宽分段、高分段
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1, 100, 100, 100);
// 材质
const basicMaterial = new THREE.MeshStandardMaterial({
  map: doorColorTexture, // 漫反射贴图
  alphaMap: doorAplhaTexture, // 透明贴图
  transparent: true, // 开启透明 
  aoMap: doorAoTexture, // 环境光遮挡贴图
  aoMapIntensity: 1, // 环境光遮挡贴图强度
  displacementMap: doorHeightTexture, // 置换贴图
  displacementScale: 0.1, // 置换贴图强度
});

添加了displacementMap,displacementScale之后效果如下:
在这里插入图片描述
可以看到门框就有了明显的立体感

三、粗糙度与粗糙度贴图

以上的效果中我们的光源照射到物体上之后,整个物体的光照面全部都亮了,没有那种真实的环境中的反光效果,亮度应该有大小差异。

这个效果我们可以通过设置粗糙度与粗糙度贴图来实现

  • 设置粗糙度roughness
const basicMaterial = new THREE.MeshStandardMaterial({
  map: doorColorTexture, // 漫反射贴图
  alphaMap: doorAplhaTexture, // 透明贴图
  transparent: true, // 开启透明 
  aoMap: doorAoTexture, // 环境光遮挡贴图
  aoMapIntensity: 1, // 环境光遮挡贴图强度
  displacementMap: doorHeightTexture, // 置换贴图
  displacementScale: 0.1, // 置换贴图强度
  roughness: 0, // 粗糙度
});

在这里插入图片描述
roughness:0,就代表非常光滑,所以这是我们可以看到门框上有很明显的反光效果,

  • 设置粗糙度贴图,让合页反光更加逼真
// 导入粗糙度贴图
const roughnessTexture = textureLoader.load("./textures/door/roughness.jpg");

// 添加物体
// 参数:长、宽、高、长分段、宽分段、高分段
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1, 100, 100, 100);
// 材质
const basicMaterial = new THREE.MeshStandardMaterial({
  map: doorColorTexture, // 漫反射贴图
  alphaMap: doorAplhaTexture, // 透明贴图
  transparent: true, // 开启透明 
  aoMap: doorAoTexture, // 环境光遮挡贴图
  aoMapIntensity: 1, // 环境光遮挡贴图强度
  displacementMap: doorHeightTexture, // 置换贴图
  displacementScale: 0.1, // 置换贴图强度
  roughness: 1, // 粗糙度
  roughnessMap: roughnessTexture, // 粗糙度贴图
});

在这里插入图片描述
当同时设置roughness,和roughnessMap时,此时的粗糙度是两者相乘
在这里插入图片描述

四、金属度与金属贴图

从上面的效果图可以看到我们的合页还是白色的,没有那种金属质感,
要设置金属质感,和设置粗糙度差不多,我们配置一下metalness和metalnessMap属性就可以了
在这里插入图片描述

// 导入金属贴图
const metalnessTexture = textureLoader.load("./textures/door/metalness.jpg");

// 添加物体
// 参数:长、宽、高、长分段、宽分段、高分段
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1, 100, 100, 100);
// 材质
const basicMaterial = new THREE.MeshStandardMaterial({
  map: doorColorTexture, // 漫反射贴图
  alphaMap: doorAplhaTexture, // 透明贴图
  transparent: true, // 开启透明 
  aoMap: doorAoTexture, // 环境光遮挡贴图
  aoMapIntensity: 1, // 环境光遮挡贴图强度
  displacementMap: doorHeightTexture, // 置换贴图
  displacementScale: 0.1, // 置换贴图强度
  roughness: 1, // 粗糙度
  roughnessMap: roughnessTexture, // 粗糙度贴图
  metalness: 1, // 金属度
  metalnessMap: metalnessTexture, // 金属度贴图
});

效果如图:
在这里插入图片描述
可以看到,这时门的合页就很有金属质感了。

五、法线贴图

在这里插入图片描述

如上图,这时的灯光反射效果还是不够真实,它是将这一块全部置成了白光,我们期望这里可以有种门框棱角的光照效果,这时需要设置法线,我们使用法线题图来实现

// 导入法线贴图
const normalTexture = textureLoader.load("./textures/door/normal.jpg");

// 添加物体
// 参数:长、宽、高、长分段、宽分段、高分段
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1, 100, 100, 100);
// 材质
const basicMaterial = new THREE.MeshStandardMaterial({
  map: doorColorTexture, // 漫反射贴图
  alphaMap: doorAplhaTexture, // 透明贴图
  transparent: true, // 开启透明 
  aoMap: doorAoTexture, // 环境光遮挡贴图
  aoMapIntensity: 1, // 环境光遮挡贴图强度
  displacementMap: doorHeightTexture, // 置换贴图
  displacementScale: 0.1, // 置换贴图强度
  roughness: 1, // 粗糙度
  roughnessMap: roughnessTexture, // 粗糙度贴图
  metalness: 1, // 金属度
  metalnessMap: metalnessTexture, // 金属度贴图
  normalMap: normalTexture, // 法线贴图
});

设置了之后的效果
在这里插入图片描述
以上就是对物体的材质和纹理设置已达到一种真实环境的3D效果的介绍了,
最终的完整代码如下:

import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

// 目标:纹理常用属性 偏移、旋转、重复、中心点
// 1、创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x003261); // 将背景色设置为蓝色

// 2、创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

// 设置相机位置
camera.position.set(0, 0, 10);
scene.add(camera);

// 导入纹理
const textureLoader = new THREE.TextureLoader();
const doorColorTexture = textureLoader.load("./textures/door/color.jpg");
const doorAplhaTexture = textureLoader.load("./textures/door/alpha.jpg");
const doorAoTexture = textureLoader.load(
  "./textures/door/ambientOcclusion.jpg"
);

//导入置换贴图
const doorHeightTexture = textureLoader.load("./textures/door/height.jpg");
// 导入粗糙度贴图
const roughnessTexture = textureLoader.load("./textures/door/roughness.jpg");
// 导入金属贴图
const metalnessTexture = textureLoader.load("./textures/door/metalness.jpg");
// 导入法线贴图
const normalTexture = textureLoader.load("./textures/door/normal.jpg");

// 添加物体
// 参数:长、宽、高、长分段、宽分段、高分段
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1, 100, 100, 100);
// 材质
const basicMaterial = new THREE.MeshStandardMaterial({
  map: doorColorTexture, // 漫反射贴图
  alphaMap: doorAplhaTexture, // 透明贴图
  transparent: true, // 开启透明 
  aoMap: doorAoTexture, // 环境光遮挡贴图
  aoMapIntensity: 1, // 环境光遮挡贴图强度
  displacementMap: doorHeightTexture, // 置换贴图
  displacementScale: 0.1, // 置换贴图强度
  roughness: 1, // 粗糙度
  roughnessMap: roughnessTexture, // 粗糙度贴图
  metalness: 1, // 金属度
  metalnessMap: metalnessTexture, // 金属度贴图
  normalMap: normalTexture, // 法线贴图
});
basicMaterial.side = THREE.DoubleSide;
const cube = new THREE.Mesh(cubeGeometry, basicMaterial);
scene.add(cube);
// 给cube添加第二组uv
cubeGeometry.setAttribute(
  "uv2",
  new THREE.BufferAttribute(cubeGeometry.attributes.uv.array, 2)
);

// 灯光
// 环境光
// 参数 1:光源颜色 2:光源强度
const light = new THREE.AmbientLight(0xffffff, 0.5); // soft white light
scene.add(light);
//直线光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(10, 10, 10);
scene.add(directionalLight);

// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);

// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
controls.enableDamping = true;

// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

function render() {
  controls.update();
  renderer.render(scene, camera);
  //   渲染下一帧的时候就会调用render函数
  requestAnimationFrame(render);
}

render();

// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {
  //   console.log("画面变化了");
  // 更新摄像头
  camera.aspect = window.innerWidth / window.innerHeight;
  //   更新摄像机的投影矩阵
  camera.updateProjectionMatrix();

  //   更新渲染器
  renderer.setSize(window.innerWidth, window.innerHeight);
  //   设置渲染器的像素比
  renderer.setPixelRatio(window.devicePixelRatio);
});

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新媒体运营工作总结

新媒体运营工作总结篇1 一、大力提升新媒体平台的关注度。在当前掩盖全校60%的同学的基础上,进一步提高掩盖率,争取在未来一年中到达90%以上。为了增强平台与受众的互动与交流,吸引同学们的关注,可以展开更多同学们喜闻乐见的线上…

macOS FreeBSD 如何刷新 DNS 缓存

macOS FreeBSD 如何刷新 DNS 缓存 全文:如何刷新 DNS 缓存 (macOS, Linux, Windows) Unix Linux Windows 如何刷新 DNS 缓存 (macOS, FreeBSD, RHEL, CentOS, Debian, Ubuntu, Windows) 请访问原文链接:https://sysin.org/blog/how-to-flush-dns-cach…

(动态规划) 5. 最长回文子串 ——【Leetcode每日一题】

❓ 5. 最长回文子串 难度:中等 给你一个字符串 s,找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。 示例 1: 输入:s “babad” 输出:“bab” 解释&#xff1a…

Pytest+Webdriver+Alluer的UI自动化测试框架

作为web自动化的入门学习,搭建框架练习下 一、熟悉项目的测试框架的整体目录 二、 PIP安装完所需框架 1、编写main.py import pytestif __name__ __main__:#pytest.main() # 遍历相同目录下的所以test开头的用例#生成测试报告 #一次执行所有接口测试用例&…

【消费战略方法论】3W消费战略作业方法

3W消费战略 以消费者为核心导向的 品牌战略 品牌本质上属于消费者,消费者是品牌战略的核心。所有品牌工作都应把握一个标准,即是否围绕着消费者,是否对消费者有价值。一切的品牌战略、策略、创意、营销等工作都应该是为了“消费者”而设…

【Java|多线程与高并发】定时器(Timer)详解

文章目录 1. 前言2. 定时器的基本使用3. 实现定时器4. 优化上述的定时器代码5. 总结 1. 前言 在Java中,定时器Timer类是用于执行定时任务的工具类。它允许你安排一个任务在未来的某个时间点执行,或者以固定的时间间隔重复执行。 在服务器开发中,客户端向…

原型模式(Prototype)

定义 原型是一种创建型设计模式,使你能够复制已有对象,而又无需使代码依赖它们所属的类。 别名 克隆(Clone)。 前言 1. 问题 如果你有一个对象,并希望生成与其完全相同的一个复制品,你该如何实现呢&a…

基于工业智能网关的设备运维管理平台有何功能?

工业物联网平台作为监控工业设备和工业环境的智能应用,整合边缘和云端的数据优势,在制造业领域得到越来越丰富的应用。 在工业制造生产过程中,常常分为人、机、料、法、环等五大要素,其中机器设备的安全稳定运行时保证工厂生产效…

58同城AI Lab在WeNet中开源GPU热词增强功能

01 前言 端到端语音识别系统在足够多数据上训练后,往往能达到不错的识别效果,然而在实际应用场景中,对于不常见的专有名词,例如人名、产品名、小区名等,往往容易识别错误,此类问题需要快速修复&#xff0c…

DNS是什么?DNS的工作流程

79. DNS是什么? DNS(Domain Name System)是一种用于将域名解析为相应IP地址的分布式命名系统,了解DNS对于理解域名解析原理和优化网络请求非常重要。本篇文章将介绍DNS的概念、工作原理以及在前端开发中的应用,帮助前…

正则表达式-捕获组,命名捕获组,非捕获组

正则表达式的作用 测试目标字符串是否符合规则 返回true/false按照规则从目标字符串提取内容 返回匹配的数组 在线测试工具 regex101: build, test, and debug regexRegular expression tester with syntax highlighting, explanation, cheat sheet for PHP/PCRE, Python, …

java适配达梦数据库

目录 一、数据库安装 二、数据库可视化工具 三、数据迁移 四、工程适配 新增maven依赖 配置文件修改 基于flyway的数据库版本管理 五、注意事项 一、数据库安装 官方文档:安装前准备 | 达梦技术文档 这里有一个点需要注意,如果你之前的数据库或…

【Java高级语法】(十六)方法引用:掌握Java中的方法引用,简化代码的实用指南~

Java高级语法详解之方法引用 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法形式3.2 案例 4️⃣ 应用场景5️⃣ 注意事项🌾 总结 1️⃣ 概念 方法引用是Java编程语言中的一个重要特性,它首次出现在Java 8版本中。这一特性旨在简化函数式编程中使用Lambd…

【博客675】prometheus生产上易犯的错误

prometheus生产上易犯的错误 Mistake 1: Cardinality bombs 这是每个人在开始使用 Prometheus 时至少会遇到一次的经典陷阱。一旦您发现 Prometheus 基于标签的数据模型的有用性,您可能会想按各种有用的标签维度来拆分指标,直到您创建的时间序列超出 P…

【QT】枚举用到的宏详解:Q_ENUM,Q_FLAG,Q_DECLARE_FLAGS,Q_DECLARE_OPERATORS_FOR_FLAGS

目录 1. Q_ENUM宏 与 QMetaEnum类1.1 Q_ENUM宏的作用1.2 使用Q_ENUM注意的问题1.3 在写有关枚举的代码时,我们可能遇到这种情况:需要用到枚举的字符串,该怎么办?1.4 下面通过一段简单的代码来说明Q_ENUM的作用 2. Q_FLAG宏2.1 Q_F…

【SpringMVC】| 拦截器(含源码分析)

目录 拦截器 1. 拦截器的介绍 2. 拦截器的三个抽象方法 3. 拦截器的使用 4. 多个拦截器的执行顺序 Java核心技术大会 文末福利(Java核心技术卷) 拦截器 拦截器能拦截请求,前面学习的过滤器也能拦截请求,那两者有什么区别…

【数据结构与算法C++实现】1、异或的用法

原视频为左程云的B站教学 文章目录 1 异或换值2 求出数组中唯一一个出现奇数次的数3 求出数组中的两个出现奇数次的数 异或: 相同为0,不同为1。 更好的记忆方式: 不进位相加 10010 ^ 01100--------11110性质 0 ^ N N,N ^ N 0…

广电用户画像分析之根据用户行为数据进行筛选与标签添加

在数据处理和分析领域,我们经常需要根据用户的行为数据进行筛选和标签添加,以便更好地理解用户行为和偏好。在本篇博客中,我们将介绍两个示例,展示如何根据用户的收视行为数据和订单信息进行数据处理和分析。 前情提要&#xff1…

创新型影像测量仪器有哪些

走新型工业化之路,加快重塑竞争新优势,离不开更强的创新能力、更高的创新效率。新型工业化道路的基本标志和落脚点是要做到“科技含量高、经济效益好、资源消耗低、环境污染少、人力资源优势得到充分发挥”,并实现这几方面的兼顾和统一。而不…

spring boot 项目实现打包依赖分离

spring boot version 2.7 (理论上是通用的)Maven version 3 打包结果 重要文件以及文件夹解释 lib: 存在当前项目的全部依赖 other:和当前项目的 groupID 不同的依赖 project:和当前项目groupID 相同的依赖 XX-3.0.0-SNAPSHOT.j…