Three.js——创建场景、渲染三维对象、添加灯光、添加阴影、添加雾化

2024-04-02 14:36

本文主要是介绍Three.js——创建场景、渲染三维对象、添加灯光、添加阴影、添加雾化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

个人简介

👀个人主页: 前端杂货铺
🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js🍒Three.js🍖数据结构与算法体系教程

🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

内容参考链接
WebGL专栏WebGL 入门

文章目录

    • 前言
    • 一、创建场景
    • 二、渲染三维对象
    • 三、旋转动画
    • 四、添加灯光
    • 五、添加阴影
    • 六、添加雾化
    • 总结

前言

大家好,这里是前端杂货铺。

原 three.js 专栏

本专栏将以更清晰专业的方式记录并讲解 three.js 相关的基础知识。

在学习的过程中,如若需要深入了解或扩展某些知识,可以自行查阅 => three.js官方文档


一、创建场景

在渲染三维对象之前我们需要以下几个对象:场景(scene)、相机(camera)和渲染器(renderer),这样我们就能透过摄像机渲染出场景。

场景 用于存放我们需要的物体(比如桌子放在房间里,那么此时房间就是场景,桌子就是物体)。

相机 用于拍摄我们场景中的物体,它包括 PerspectiveCamera(透视摄像机:用来模拟人眼所看到的景象,近大远小)和 OrthographicCamera(正交摄像机:渲染的图片中物体的大小都保持不变)。

渲染器 用于把场景和场景里面的物体渲染到我们的屏幕上。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><style>* {margin: 0;padding: 0;}</style>
</head><body><script>// 创建场景const scene = new THREE.Scene();// 创建相机 参数:视野角度、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);// 将渲染器的 canvas 添加到 body 中document.body.appendChild(renderer.domElement);</script>
</body></html>

此时的 renderer 是一个庞大的对象,renderer.domElement 其实就是一个 canvas,它此刻代表着我们屏幕上的黑色场景。

在这里插入图片描述


二、渲染三维对象

我们可以在场景中渲染的三维对象有很多种,比如:立方体、球体、椎体、圆柱体…

接下来,我们在刚刚创建好的场景中添加一个立方体。其实也很简单,我们只需要创建 立方缓冲几何体 实例,然后定义一个材质,最后通过 mesh 网格 构建出来几何体添加到场景中即可。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><style>* {margin: 0;padding: 0;}</style>
</head><body><script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);// 将渲染器的 canvas 添加到 body 中document.body.appendChild(renderer.domElement);// 添加立方体const cubeGeometry = new THREE.BoxGeometry(2, 2, 2);// 创建立方体材质const cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, // 立方体颜色wireframe: true //  是否将几何体渲染为线框});// 基于以三角形为 polygon mesh(多边形网格)的物体的类 => 此时就是立方体const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);// 添加到场景scene.add(cube);// 渲染renderer.render(scene, camera);</script>
</body></html>

在这里插入图片描述

若把 wireframe 置为 false,则渲染出的为几何体

在这里插入图片描述


三、旋转动画

接下来,我们来让刚刚被渲染出来的三维对象旋转起来,看一下它的总体形态。

在此,我们使用 window.requestAnimationFrame(),它会告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

requestAnimatingFrame 相较于 setTimeout 的优点:为了提高性能和电池寿命,在大多数浏览器里,当 requestAnimationFrame() 运行在后台标签页或者隐藏的 <iframe> 里时,requestAnimationFrame() 会被暂停调用以提升性能和电池寿命。(总而言之,requestAnimatingFrame 有更高的效率!)

requestAnimationFrame 通常每秒执行 60 次,相当于每 0.01667s 执行一次,即 60帧。

下面代码中的 rotation 用于控制立方体的绕轴旋转,通过 requestAnimationFrame 设置每单位时间立方体绕 x 轴旋转 0.01,绕 y 轴也旋转 0.01。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><style>* {margin: 0;padding: 0;}</style>
</head><body><script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);console.log(renderer);// 将渲染器的 canvas 添加到 body 中document.body.appendChild(renderer.domElement);// 添加立方体const cubeGeometry = new THREE.BoxGeometry(2, 2, 2);// 创建立方体材质const cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000,wireframe: true});const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);// 添加到场景scene.add(cube);const animation = () => {cube.rotation.x += 0.01;cube.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();</script>
</body></html>

立方体旋转动画


四、添加灯光

接下来,我们在场景中添加一个聚光灯光照 SpotLight(光线从一个点沿一个方向射出,随着光线照射的变远,光线圆锥体的尺寸也逐渐增大)。从而模拟出有光照打在物体上的立体效果。

也很简单,我们只需要创建聚光灯实例,给它传递一个白色,设置合适的位置添加到场景中即可。

需要注意的是:添加灯光时的材质需要改为 MeshLambertMaterial,因为 MeshBasicMaterial 不支持添加材质。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><style>* {margin: 0;padding: 0;}</style>
</head><body><script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 添加立方体const cubeGeometry = new THREE.BoxGeometry(2, 2, 2);// 创建立方体材质const cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000,wireframe: false});const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);// 添加到场景scene.add(cube);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 10);scene.add(spotLight);const animation = () => {cube.rotation.x += 0.01;cube.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();</script>
</body></html>

添加灯光


五、添加阴影

接下来,我们创建一个平面,模拟出实体旋转时映射到平面上的阴影效果。

平面的创建和实体差不多,都是先创建实例和材质,之后通过 mesh 创建出平面,最后调整到合适的位置添加到场景中即可。

此场景中,我们还创建了个球体,总体创建方式都一样。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../lib/three/three.js"></script><style>* {margin: 0;padding: 0;}</style>
</head><body><script>// 创建场景const scene = new THREE.Scene();// 创建相机 视野角度FOV、长宽比、近截面、远截面const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);// 设置相机位置camera.position.set(0, 0, 20);// 创建渲染器const renderer = new THREE.WebGLRenderer();// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 添加立方体const cubeGeometry = new THREE.BoxGeometry(2, 2, 2);// 创建立方体材质const cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000,wireframe: false});const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);// 添加到场景scene.add(cube);// 添加球体const sphereGeometry = new THREE.SphereGeometry(1, 10, 10);// 创建球体材质const sphereMatrial = new THREE.MeshBasicMaterial({color: 0x00ff00,wireframe: true})const sphere = new THREE.Mesh(sphereGeometry, sphereMatrial);sphere.position.x = 3;sphere.position.y = 1;// 添加到场景scene.add(sphere);// 添加平面,用来接收阴影const planeGeometry = new THREE.PlaneGeometry(20, 30);const planeMaterial = new THREE.MeshBasicMaterial({color: 0x999999});const plane = new THREE.Mesh(planeGeometry, planeMaterial);plane.rotateZ(20);plane.position.z = -10;plane.position.x = 3;scene.add(plane);// 添加灯光const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-10, 10, 90);scene.add(spotLight);// 产生阴影cube.castShadow = true;sphere.castShadow = true;// 接收阴影plane.receiveShadow = true;sphere.receiveShadow = true;// 设置灯光开启阴影spotLight.castShadow = true;renderer.shadowMapEnabled = true;const animation = () => {cube.rotation.x += 0.01;cube.rotation.y += 0.01;sphere.rotation.x += 0.01;sphere.rotation.y += 0.01;// 渲染renderer.render(scene, camera);requestAnimationFrame(animation);}animation();</script>
</body></html>

添加物体阴影


六、添加雾化

添加雾化很简单,我们只需要在场景中添加一个 线性雾 实例即可。

// 雾化
scene.fog = new THREE.Fog(0xffffff, 1, 50);

添加雾化


总结

本篇文章我们熟悉了如何创建场景、怎么渲染出三维对象、如何进行灯光、阴影、雾化的添加等。知识点的总体难度较低,这也是 three.js 的强大之处,它暴露出了很多 API 供我们使用,极大的方便了我们对于实体的创建及操作。

更多内容扩展请大家自行查阅 => three.js官方文档,真心推荐读一读!!

好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!


参考资料:

  1. Three.js 官方文档
  2. WebGL+Three.js 入门与实战【作者:慕课网_yancy】

在这里插入图片描述


这篇关于Three.js——创建场景、渲染三维对象、添加灯光、添加阴影、添加雾化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/870239

相关文章

Python打印对象所有属性和值的方法小结

《Python打印对象所有属性和值的方法小结》在Python开发过程中,调试代码时经常需要查看对象的当前状态,也就是对象的所有属性和对应的值,然而,Python并没有像PHP的print_r那样直接提... 目录python中打印对象所有属性和值的方法实现步骤1. 使用vars()和pprint()2. 使

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

MySQL JSON 查询中的对象与数组技巧及查询示例

《MySQLJSON查询中的对象与数组技巧及查询示例》MySQL中JSON对象和JSON数组查询的详细介绍及带有WHERE条件的查询示例,本文给大家介绍的非常详细,mysqljson查询示例相关知... 目录jsON 对象查询1. JSON_CONTAINS2. JSON_EXTRACT3. JSON_TA

Java中实现线程的创建和启动的方法

《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据

Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析

《Spring组件实例化扩展点之InstantiationAwareBeanPostProcessor使用场景解析》InstantiationAwareBeanPostProcessor是Spring... 目录一、什么是InstantiationAwareBeanPostProcessor?二、核心方法解

Java 枚举的基本使用方法及实际使用场景

《Java枚举的基本使用方法及实际使用场景》枚举是Java中一种特殊的类,用于定义一组固定的常量,枚举类型提供了更好的类型安全性和可读性,适用于需要定义一组有限且固定的值的场景,本文给大家介绍Jav... 目录一、什么是枚举?二、枚举的基本使用方法定义枚举三、实际使用场景代替常量状态机四、更多用法1.实现接

java -jar命令运行 jar包时运行外部依赖jar包的场景分析

《java-jar命令运行jar包时运行外部依赖jar包的场景分析》:本文主要介绍java-jar命令运行jar包时运行外部依赖jar包的场景分析,本文给大家介绍的非常详细,对大家的学习或工作... 目录Java -jar命令运行 jar包时如何运行外部依赖jar包场景:解决:方法一、启动参数添加: -Xb

Macos创建python虚拟环境的详细步骤教学

《Macos创建python虚拟环境的详细步骤教学》在macOS上创建Python虚拟环境主要通过Python内置的venv模块实现,也可使用第三方工具如virtualenv,下面小编来和大家简单聊聊... 目录一、使用 python 内置 venv 模块(推荐)二、使用 virtualenv(兼容旧版 P