three.js 细一万倍教程 从入门到精通(三)

目录

五、详解PBR材质纹理

5.1、详解PBR物理渲染

5.2、标准网格材质与光照物理效果

5.3、置换贴图与顶点细分设置

5.4、设置粗糙度与粗糙度贴图

5.5、设置金属度与金属贴图

5.6、法线贴图应用

5.7、如何获取各种类型纹理贴图

5.8、纹理加载进度情况

单张图片加载

多张图片加载

5.9、详解环境贴图

5.10、经纬线映射贴图与HDR

经纬线映射贴图

HDR

六、详解灯光与阴影

6.1、灯光与阴影的关系与设置

6.2、平行光阴影属性与阴影相机原理


五、详解PBR材质纹理

5.1、详解PBR物理渲染

灯光属性:直接照明、间接照明、直接高光、间接高光、阴影、环境光闭塞。

表面属性:基础色、法线、高光、粗糙度、金属度。

5.2、标准网格材质与光照物理效果

案例1:【环境光】照射物体

// 灯光(环境光)
// 参数分别为光的颜色和光的强度
const light = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(light)

案例2:【平行光】照射物体

// 直线光源
const directionaLight = new THREE.DirectionalLight(0xffffff, 0.5);
// 设置光从哪个位置直射
directionaLight.position.set(10, 10, 10);
scene.add(directionaLight)

5.3、置换贴图与顶点细分设置

首先准备一张贴图

黑色还是不动,浅灰格外突出,特别是门把手和两块铁片要突出。

// 导入纹理
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 cubeGeometry = new THREE.BoxGeometry(1, 1, 1, 200, 200);
// 材质
const material = new THREE.MeshStandardMaterial({color: "#ffff00",map: doorColorTexture,alphaMap: doorAplhaTexture,transparent: true,aoMap: doorAoTexture,aoMapIntensity: 1,displacementMap: doorHeightTexture,displacementScale: 0.1 // 默认是1,深浅度,0.1代表稍微突出一点
})
const cube = new THREE.Mesh(cubeGeometry, material);
scene.add(cube);// 灯光(环境光)
// 参数分别为光的颜色和光的强度
const light = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(light)

5.4、设置粗糙度与粗糙度贴图

// 添加物体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1, 200, 200);
// 材质
const material = new THREE.MeshStandardMaterial({color: "#ffff00",map: doorColorTexture,alphaMap: doorAplhaTexture,transparent: true,aoMap: doorAoTexture,aoMapIntensity: 1,displacementMap: doorHeightTexture,displacementScale: 0.1,roughness: 0 // 设置粗糙度为0,直接光滑到底
})
const cube = new THREE.Mesh(cubeGeometry, material);
scene.add(cube);// 灯光(环境光)
// 参数分别为光的颜色和光的强度
const light = new THREE.AmbientLight(0xffffff);
scene.add(light)// 直线光源
const directionaLight = new THREE.DirectionalLight(0xffffff);
// 设置光从哪个位置直射
directionaLight.position.set(10, 10, 10);
scene.add(directionaLight)

假如我们想单独设置金属片粗糙,门光滑怎么办?

使用粗糙度贴图

白色代表粗糙度为1,黑色代表粗糙度为0。

5.5、设置金属度与金属贴图

现在我们想让金属片完全像金属,门不用。

准备金属贴图

黑色完全不用金属材质,而白色完全用金属材质。

// 导入纹理
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 doorRoughnessTexture = textureLoader.load("./textures/door/roughness.jpg");
// 金属贴图
const doorMetalnessTexture = textureLoader.load("./textures/door/metalness.jpg");// 添加物体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1, 200, 200);
// 材质
const material = new THREE.MeshStandardMaterial({color: "#ffff00",map: doorColorTexture,alphaMap: doorAplhaTexture,transparent: true,aoMap: doorAoTexture,aoMapIntensity: 1,displacementMap: doorHeightTexture,displacementScale: 0.1,// roughness: 0, // 设置粗糙度为0,直接光滑到底roughnessMap: doorRoughnessTexture,metalness: 1, // 金属度打满metalnessMap: doorMetalnessTexture // 引入金属贴图
})
const cube = new THREE.Mesh(cubeGeometry, material);
scene.add(cube);// 灯光(环境光)
// 参数分别为光的颜色和光的强度
const light = new THREE.AmbientLight(0xffffff);
scene.add(light)// 直线光源
const directionaLight = new THREE.DirectionalLight(0xffffff);
// 设置光从哪个位置直射
directionaLight.position.set(10, 10, 10);
scene.add(directionaLight)

5.6、法线贴图应用

上一节中虽然体现出了金属的质感,但还不够完美,我们发现在光折射的时候,门和金属片并没有凹凸不平的样子,都是一个平面的感觉。

我们再引入一个凹凸感(法线)的贴图

每个颜色都代表不同的朝向,相同的颜色相同朝向。

5.7、如何获取各种类型纹理贴图

网站:Poliigon - Textures, Models and HDRIs for 3D rendering

我们下载个免费的,解压一下

5.8、纹理加载进度情况

单张图片加载

let event = {}
// 单张纹理图的加载进度(color.jpg)
event.onLoad = function () {console.log("图片加载完成");
}
event.onProgress = function (e) {console.log("图片加载进度", e)
}
event.onError = function (e) {console.log("图片加载出现错误", e)
}// 导入纹理
const textureLoader = new THREE.TextureLoader();
const doorColorTexture = textureLoader.load("./textures/door/color.jpg", event.onLoad, event.onProgress, event.onError);

多张图片加载

let event = {}
event.onLoad = function () {console.log("图片加载完成");
}
event.onProgress = function (url, num, total) {console.log("图片加载路径", url)console.log("图片加载进度", num)console.log("图片总数", total)console.log("图片加载进度百分比", (num / total * 100).toFixed(2))
}
event.onError = function (e) {console.log("图片加载出现错误", e)
}// 设置加载管理器
const loadingManager = new THREE.LoadingManager(event.onLoad, event.onProgress, event.onError);// 导入纹理
const textureLoader = new THREE.TextureLoader(loadingManager);
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 doorRoughnessTexture = textureLoader.load("./textures/door/roughness.jpg");
// 金属贴图
const doorMetalnessTexture = textureLoader.load("./textures/door/metalness.jpg");
// 法线贴图
const doorNormalTexture = textureLoader.load("./textures/door/normal.jpg");

5.9、详解环境贴图

// 设置cube纹理加载器
const cubeTextureLoader = new THREE.CubeTextureLoader();
const envMapTexture = cubeTextureLoader.load(["./textures/environmentMaps/1/px.jpg","./textures/environmentMaps/1/nx.jpg","./textures/environmentMaps/1/py.jpg","./textures/environmentMaps/1/ny.jpg","./textures/environmentMaps/1/pz.jpg","./textures/environmentMaps/1/nz.jpg",
]);
const sphereGeometry = new THREE.SphereGeometry(1, 20, 20);
const material = new THREE.MeshStandardMaterial({metalness: 0.7, // 金属材质roughness: 0.1, // 光滑度envMap: envMapTexture, // 导入环境贴图
});
const sphere = new THREE.Mesh(sphereGeometry, material);
scene.add(sphere);

5.10、经纬线映射贴图与HDR

经纬线映射贴图

HDR

import {RGBELoader} from 'three/examples/jsm/loaders/RGBELoader'// 加载HDR环境图
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("./textures/hdr/002.hdr").then((texture) => {// 如果不设置映射mapping。则HDR环境图不会动texture.mapping = THREE.EquirectangularReflectionMapping;scene.background = texture;// 设置环境图(物体小球)scene.environment = texture;
});

六、详解灯光与阴影

6.1、灯光与阴影的关系与设置

目标:灯光与阴影

1、材质要满足对光照有反应。

2、设置渲染器开启阴影的计算 renderer.shadowMap.enabled = true;

3、设置光照投射阴影 directionaLight.castShadow = true;

4、设置物体投射阴影 sphere.castShadow = true;

5、设置物体接收阴影 plane.receiveShadow = true;

// 圆
const sphereGeometry = new THREE.SphereGeometry(1, 20, 20);
const material = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(sphereGeometry, material);
// 投射阴影
sphere.castShadow = true;
scene.add(sphere);// 创建平面
const planeGeometry = new THREE.PlaneGeometry(10, 10);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 接收阴影
plane.receiveShadow = true;
scene.add(plane);// 直线光源
const directionaLight = new THREE.DirectionalLight(0xffffff, 0.5);
// 设置光从哪个位置直射
directionaLight.position.set(10, 10, 10);
// 设置该平行光会产生动态阴影
directionaLight.castShadow = true;
scene.add(directionaLight);// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true;
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);

6.2、平行光阴影属性与阴影相机原理

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

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

相关文章

Windows 平台下NDK/CMAKE编译自己程序命令行

CMAKE_BUILD_TYPE 编译类型(Debug、Release) CMAKE_TOOLCHAIN_FILE 指定 Android 编译工具链文件 CMAKE_SYSTEM_NAME 系统名称:不要改变:值(Android) ANDROID_NATIVE_API_LEVEL 安卓原…

Transformer实战-系列教程17:DETR 源码解读4(Joiner类/PositionEmbeddingSine类/位置编码/backbone)

🚩🚩🚩Transformer实战-系列教程总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 点我下载源码 DETR 算法解读 DETR 源码解读1(项目配置/CocoDetection类) …

数据结构-并查集

并查集原理 在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个 单元素集合,然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询一 个元素归属于那个集合的运算。适合于描述这类…

Matplotlib Figure与Axes速成:核心技能一网打尽

Matplotlib Figure与Axes速成:核心技能一网打尽 🌵文章目录🌵 🌳引言🌳🌳 一、Figure(图形)🌳🍁1. 创建Figure🍁🍁2. 添加Axes&#…

NARF关键点提取原理简介

一、NARF2D边缘点探测的矩形平面的边长s和计算点p和上邻域的距离所用的k值 二、障碍物边缘和阴影边缘 三、NARF边缘点探测 四、NARF借助边缘点信息进行关键点检测 本人也是参考其他博主,以及这份英文文献写的(毕竟是英文文献,部分翻译肯定有些误差&…

一探Lepton Search究竟

2024年1月25日,阿里巴巴原技术副总裁在 Twitter 上称用不到 500 行 Python 代码实现了 AI 对话搜索引擎,并在27日附上了开源地址:https://github.com/leptonai/search_with_lepton,截止春节期间已经5.8K的Star。 Twitter截图 Comm…

Spring Security学习(四)——登陆认证(包括自定义登录页)

前言 和前面的文章隔了很长时间才更新Spring Security系列,主要原因一个是之前太忙了,把项目都忙完了,赶上春节假期,就慢慢研究。Spring Security的体系非常复杂,一口吃不了热豆腐,没办法速成,…

第10讲投票创建页面实现

投票创建页面实现 文件选择上传组件 uni-file-picker 扩展组件 安装 https://ext.dcloud.net.cn/plugin?nameuni-file-picker 日期选择器uni-datetime-picker组件 安装 https://ext.dcloud.net.cn/plugin?nameuni-datetime-picker iconfont小图标 https://www.iconfont…

【数据结构与算法】判断二叉树是否完全二叉树

递归方式判断二叉树是否完全二叉树 bool TreeComplete(TreeNode* root) {if (root ! NULL) {if (root->left NULL && root->right ! NULL) {return false; // 左子树空}else if (root->left NULL && root->right NULL) {return true; // 左右子…

【力扣每日一题】力扣987二叉树的垂序遍历

题目来源 力扣987二叉树的垂序遍历 题目概述 给你二叉树的根结点 root ,请你设计算法计算二叉树的 垂序遍历 序列。 对位于 (row, col) 的每个结点而言,其左右子结点分别位于 (row 1, col - 1) 和 (row 1, col 1) 。树的根结点位于 (0, 0) 。 二…

仰暮计划|“​他们艰苦半生,但真的希望祖国安祥,山河无恙”

自述,自赎 我没有在那个年代生活过,我一出生就是盛世中国,看遍了祖国的大好河山。但我没想到,走了这么远的路,吃了这么多的苦的爷爷会一直跟我说“不是国家不好,只是中国的钱拿去还债了,过了那…

代码随想录算法训练营Day56|583. 两个字符串的删除操作、72. 编辑距离

目录 583. 两个字符串的删除操作 前言 思路 算法实现 法二 72. 编辑距离 前言 思路 算法实现 总结 583. 两个字符串的删除操作 题目链接 文章链接 前言 本题与上一题不同的子序列相比,变化就是两个字符串都可以进行删除操作了。 思路 利用动规五部曲进…

【AI视野·今日Robot 机器人论文速览 第七十九期】Thu, 18 Jan 2024

AI视野今日CS.Robotics 机器人学论文速览 Thu, 18 Jan 2024 Totally 43 papers 👉上期速览✈更多精彩请移步主页 Daily Robotics Papers CognitiveDog: Large Multimodal Model Based System to Translate Vision and Language into Action of Quadruped Robot Aut…

哈希表 ?

哈希表 首先什么是 哈希表,哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。 哈希表是根据关键码的值而直接进行访问的数据结构。 这么这官方的解释…

【C++初阶:类和对象(下篇)】初始化列表 | static成员 | 友元

目录 一、构造函数构造函数体赋值🐾初始化列表🐾💦 explicit关键字 二、static成员🐾概念**💦 关于静态的特性** 三、友元💦 **友元函数**💦 **友元类** **四、内部类** 一、构造函数 构造函数…

Spark的timestamp 数据时间问题

使用Spark来处理国际业务数据,涉及到数据时区转换,在实际项目中出现时区转换问题。 使用代码: spark.conf.set("spark.sql.session.timeZone", "Asia/Hong_Kong") spark.selectExpr("date_format(eff_dt, yyyyMMdd…

VM和Linux安装

VM和Linux安装 一、下载VM 1.官网地址:https://www.vmware.com/cn.html 2.其他地址:http://ww7.nocmd.com/windows/740.html 许可证这个,大家可以自己上网搜索,很容易就搜索到就可以使用了 上面内容就是安装VM的步骤 安…

30. 异常

异常 1. 概述2. Throwable 方法2.1 概述2.2 代码示例 3. 异常分类4. 异常处理方式4.1 JVM默认处理异常4.2 自己处理(捕获异常)try...catch4.2.1 概述4.2.2 灵魂四问 4.3 抛出处理(throw和throws) 5. 自定义异常5.1 概述5.2 代码示例 6. 异常注意事项 文章…

代码随想录算法训练营第三十一天 |基础知识,455.分发饼干,376.摆动序列,53.最大子序和(已补充)

基础知识: 题目分类大纲如下: #算法公开课 《代码随想录》算法视频公开课(opens new window):贪心算法理论基础!(opens new window),相信结合视频再看本篇题解,更有助于大家对本题的理解。 #什么是贪心 贪心的本质…

C语言——oj刷题——回文字符串

问题: 实现一个函数,判断一个字符串是否为回文字符串。 回文字符串是指正读和反读都相同的字符串。例如,"level"、"radar"和"madam"都是回文字符串。 要解决这个问题,我们可以使用两个指针分别指向…