关于程序员:ThreeJS-入门如何渲染出第一个3D图形

30次阅读

共计 4438 个字符,预计需要花费 12 分钟才能阅读完成。

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 多平台公布

正文完
 0