ThreeJS 入门如何渲染出第一个3D图形

ThreeJS 入门如何渲染出第一个3D图形

什么是ThreeJS?

Three.js 是一个用于在Web浏览器上创建和显示交互式 3D 图形的 JavaScript 库。简化了在 Web 上创建基于 WebGL 的 3D 图形的过程。WebGL 是一种在 Web 浏览器中实现硬件加速的 3D 图形渲染的技术。Three.js 通过封装复杂的WebGL API,提供了一个更简单的接口,使得我们能够轻松地在浏览器中创建 3D 场景、模型、动画和交互效果。

渲染一个 3D 图形需要哪些步骤?

要渲染第一个 3D 图形,需要以下几个步骤:

  • 创建场景 scene,使用 THREE.Scene 进行创建。
  • 创建相机 camera,使用 THREE.PerspectiveCamera 进行创建。
  • 创建渲染对象(以立方体为例),并添加到场景 scene 中
  • 创建渲染器 renderer,并进行场景渲染,使用THREE.WebGLRenderer 进行创建。调用渲染器 render 函数将场景 scene 和相机 camera 作为参数进行渲染。

// 插入一个跳转地址,方便查看完整代码

创建场景

在 Three.js 中,使用 THREE.Scene 来创建 scene(场景),scene包含了所有 3D 对象、光源和相机的容器。它是构建和组织 3D 场景的基础。

场景(THREE.Scene)类代表了一个虚拟的 3D 空间,其中可以包含各种对象,例如几何体、模型、灯光等。通过将对象添加到场景中,可以在渲染过程中将它们呈现到屏幕上。

创建一个简单的场景:

import * as THREE from 'three';
const scene = new THREE.Scene();

实例化后的 scene 对象提供一些列的API来对其中的 3D 对象进行管理,如: scene.add(object: Object3D)scene.remove(object: Object3D), scene.traverse(callback: Function) 。还提供对 scene 进行设置和操作的 API 本文暂时未使用到 scene 中其他的API,后续单独写篇文章进行介绍。

创建相机

在 Three.js 中,camera(相机)是用于定义场景中的视角和观察位置的对象。相机确定了渲染器如何将场景中的 3D 对象投影到屏幕上,决定了观察者在场景中看到的内容。使用相机来控制观察者在场景中的位置和视角。在 openGL 中相机的位置固定在(0,0,0)位置,所有的相机移动实际都是对场景中的所有对象进行矩阵变换。
Three.js 提供了多种类型的相机,常用的是透视相机(THREE.PerspectiveCamera)和正交相机(THREE.OrthographicCamera)。

  • 透视相机(THREE.PerspectiveCamera)使用透视投影,模拟了人眼的视觉效果。它具有视场角(FOV)、纵横比、近剪裁面和远剪裁面等属性。视场角决定了场景在相机前方可见的范围,纵横比定义了视图的宽高比,近剪裁面和远剪裁面则定义了相机的可见范围。
  • 正交相机(THREE.OrthographicCamera)使用正交投影,产生了一个没有透视效果的平行投影。它具有左、右、上、下、近、远等属性,用于定义可见区域的范围。

本文使用透视相机创建一个实例:

const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

参数主要如下,THREE.PerspectiveCamera(fov, aspect, near, far)

  • fov: 视场角,表示相机的视角张度,单位是度。
  • aspect: 纵横比,表示渲染区域的宽高比。
  • near: 近剪裁面的距离,表示相机能够看到的最近距离,在近剪裁面之前的3D对象会被裁剪掉。
  • far: 远剪裁面,表示相机能够看到的最远距离。在此之后的对象也会被裁剪掉。

不用担心,后续会专门写篇文章进行详细介绍两相机之间的区别,什么是近剪裁面、远剪裁面以及其距离怎么算的。

创建渲染对象(立方体为)

创建一个正立方体:

// 创建绿色的立方体

// 创建立方体几何体
const geometry = new THREE.BoxGeometry(1,1,1);
// 实例化基础的材质,颜色设置为绿色, rgb 每两个十六进制单位分别表示一个基础元色。
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 生成一个立方体网格对象,传入几何体对象和颜色材质对象
const cube = new THREE.Mesh(geometry, material);
// 将立方体网格对象添加到场景中
scene.add(cube);

这里涉及到三个新的基类分别是 THREE.BoxGeometryTHREE.MeshBasicMaterialTHREE.Mesh

  • THREE.BoxGeometry 立方几何体,用于创建长方体或者立方体。 ThreeJS 提供 8 种 Shape 类用于创建基本几何体和自定义形状。还提供一些可以扩展的基类,我们可以在这个基类的基础上进行其他封装。openGL 提供的图元实际很基础(点,线,线环,线带,三角形,三角扇,三角带,四边形),ThreeJS 进行的大量封装使得我们更好进行形状生成。(_)以后再开篇进行详细介绍。
  • MeshBasicMaterial 基础材质,不受光照影响,只显示颜色。ThreeJS 一共提供了 7 种常用材质对象以及特殊的几种材质比如:粒子材质等。
  • Mesh 网格对象,用于将几何体与材质结合起来。ThreeJS 提供 6 种网格对象支持不同的使用场景。

创建渲染器将 scene 渲染出来

创建一个 WebGLRenderer 渲染器渲染scene:

// 创建一个 webgl 渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器的 size
renderer.setSize(window.innerWidth, window.innerHeight);
// 绑定输出位置
document.body.appendChild(renderer.domElement);
// 将 scene 渲染出来
renderer.render(scene, camera);

渲染器是 ThreeJS 的核心组件,将 scene 场景中的三维对象渲染到屏幕上。ThreeJS 提供了三类常用的渲染器 WebGLRendererCanvasRendererSVGRenderer。预计未来可能会支持 WebGPURenderer 现在 Chrome 已经支持 WebGPU 了并且性能比 Webgl 更好一些(反正隔壁 babyIcon 已经支持了v)。
渲染器主要行为大体如下:

  • 创建渲染上下文
  • 设置渲染参数
  • 渲染 scene
  • 输出渲染结果到载体(通常都是canvas)

至此已经能渲染一个立方体了,接下来补充一丢丢代码让立方体渲染起来。

  const rotateBox = () => {
    // 创建 scene 场景
    const scene = new THREE.Scene();

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

    // 设置相机的z位置为5 ,位置:(0,0,5)
    camera.position.z = 5;

    // 创建绿色立方体
    const geometry = new THREE.BoxGeometry(1, 1, 1);
    const material = new THREE.MeshBasicMaterial({ color: 0x00ffa1 });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    // 创建渲染器
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 让立方体渲染起来
    function animate() {
      requestAnimationFrame(animate);

      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;

      renderer.render(scene, camera);
    }

    animate();
  };

完整代码(我在 react 中运行),方便对每篇文章的 demo 进行管理以及ui交互。代码也可以复制到到 HTML 中执行额外添加一行 threejs库的引入即可:

import React, { useEffect } from 'react';
import * as THREE from 'three';

export default function OneDay() {

  const rotateBox = () => {
    // 创建 scene 场景
    const scene = new THREE.Scene();

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

    // 设置相机的z位置为5 ,位置:(0,0,5)
    camera.position.z = 5;

    // 创建绿色立方体
    const geometry = new THREE.BoxGeometry(1, 1, 1);
    const material = new THREE.MeshBasicMaterial({ color: 0x00ffa1 });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    // 创建渲染器
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 让立方体渲染起来
    function animate() {
      requestAnimationFrame(animate);

      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;

      renderer.render(scene, camera);
    }

    animate();
  };
  
  useEffect(() => {
    rotateBox();
  }, []);

  return <div id="container"></div>
}

立个 flag 后续持续学习更新 threejs 系列文章(每周一篇),欢迎大家关注监督 -

本文由mdnice多平台发布

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,104评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,816评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,697评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,836评论 1 298
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,851评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,441评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,992评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,899评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,457评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,529评论 3 341
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,664评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,346评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,025评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,511评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,611评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,081评论 3 377
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,675评论 2 359

推荐阅读更多精彩内容

  • Three.js 是一款运行在浏览器中的 3D 引擎,你可以用它在 web 中创建各种三维场景,包括了摄影机、光影...
    了无_数据科学阅读 1,569评论 0 0
  • ThreeJS 里元素如下: 1.场景(Scene):是物体、光源等元素的容器, 2.相机(Camera):控制...
    _花阅读 990评论 0 1
  • 一、前言 ThreeJs 封装了 WebGL 进行渲染时所涉及到的相关概念,如光照,材质,纹理以及相机等。除此之外...
    仰简阅读 7,272评论 1 10
  • Threejs 为什么? webGL太难用,太复杂! 但是现代浏览器都支持 WebGL 这样我们就不必使用 Fla...
    强某某阅读 6,065评论 1 21
  • 1、WebGL与threeJS WebGL是一种3D绘图协议,其允许JavaScript和OpenGL ES2.0...
    患者_阅读 20,203评论 1 22