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

相关文章

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

MyBatis-Plus 中 nested() 与 and() 方法详解(最佳实践场景)

《MyBatis-Plus中nested()与and()方法详解(最佳实践场景)》在MyBatis-Plus的条件构造器中,nested()和and()都是用于构建复杂查询条件的关键方法,但... 目录MyBATis-Plus 中nested()与and()方法详解一、核心区别对比二、方法详解1.and()

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

ModelMapper基本使用和常见场景示例详解

《ModelMapper基本使用和常见场景示例详解》ModelMapper是Java对象映射库,支持自动映射、自定义规则、集合转换及高级配置(如匹配策略、转换器),可集成SpringBoot,减少样板... 目录1. 添加依赖2. 基本用法示例:简单对象映射3. 自定义映射规则4. 集合映射5. 高级配置匹

python如何创建等差数列

《python如何创建等差数列》:本文主要介绍python如何创建等差数列的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录python创建等差数列例题运行代码回车输出结果总结python创建等差数列import numpy as np x=int(in

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

怎么用idea创建一个SpringBoot项目

《怎么用idea创建一个SpringBoot项目》本文介绍了在IDEA中创建SpringBoot项目的步骤,包括环境准备(JDK1.8+、Maven3.2.5+)、使用SpringInitializr... 目录如何在idea中创建一个SpringBoot项目环境准备1.1打开IDEA,点击New新建一个项

如何使用Maven创建web目录结构

《如何使用Maven创建web目录结构》:本文主要介绍如何使用Maven创建web目录结构的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录创建web工程第一步第二步第三步第四步第五步第六步第七步总结创建web工程第一步js通过Maven骨架创pytho

MySQL 用户创建与授权最佳实践

《MySQL用户创建与授权最佳实践》在MySQL中,用户管理和权限控制是数据库安全的重要组成部分,下面详细介绍如何在MySQL中创建用户并授予适当的权限,感兴趣的朋友跟随小编一起看看吧... 目录mysql 用户创建与授权详解一、MySQL用户管理基础1. 用户账户组成2. 查看现有用户二、创建用户1. 基

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja