3D图形系统概念(创建three.js程序)

实时 3D 应用程序组件

每个 three.js 应用程序的基本组件是场景、相机和渲染器,它们构成了应用程序的基本脚手架。然后在浏览器的画布中看到其结果,HTML的canvas元素。最后是有一个可见的对象,例如网格。除了画布 canvas(特定于浏览器)之外,在three.js系统中都可以找到这些组件。

场景

场景是我们能看到的一切的载体 。可以将其视为存在了所有 3D 对象的一个容器。用来创建场景的 three.js 类简称为 Scene,其构造函数不带参数。创建一个scene实例对象如下:(采用npm下载包的方式引入)

js 复制代码
import { Scene } from 'three';

const scene = new Scene();

场景scene定义了一个名为三维的坐标系,它是我们在 three.js 中处理可见对象时的主要参考框架。场景的中心是点(0,0,0),也称为坐标系的原点。每当创建一个新对象并将其添加到场景中时,该对象将被放置在原点,并且每当移动它时,说的都是在这个坐标系中移动它。

当对象添加到场景中时,它们会被放入场景图中,这是一个树形结构,场景位于顶部。类似于 HTML 页面上元素的结构方式,不同之处在于 HTML 页面是 2D 而场景图是 3D。

添加到场景中的对象存在于场景图中,可见对象的树如下:

Color类来设置场景的背景颜色。

相机

相机用于查看场景这个容器中的3D对象,并将其转换为对我们人眼感觉合理的东西。有几种方法可以将场景图形转换为人类视觉友好的格式,使用称为投影的技术。投影类型有透视投影和正交投影。正交投影对于创建 2D 场景或覆盖 3D 场景的用户界面很有用。但是大部分情况下是使用 HTML 来创建用户界面,并使用 three.js 来创建 3D 场景,所以常用的是透视投影。OrthographicCamera类用于创建正交投影的相机。要使用透视投影查看场景,使用 PerspectiveCamera类。 这种类型的相机是现实世界中相机的 3D 等效物,并使用许多相同的概念和术语,例如视野和纵横比。与场景Scene类不同的是,PerspectiveCamera类构造函数有几个参数。创建一个camera实例对象如下:

js 复制代码
import { PerspectiveCamera } from 'three';

const fov = 35; 
const aspect = container.clientWidth / container.clientHeight;
const near = 0.1;
const far = 100; 
const camera = new PerspectiveCamera(fov, aspect, near, far);

渲染器

如果场景是一个存放3D对象的容器,而相机是一个指向那个容器的望远镜,那么渲染器就是一个观察者,通过望远镜观察并将所看到的东西绘制到<canvas>画布。这个过程叫做渲染 ,得到的图片就是一个渲染效果图。WebGLRenderer类使用 WebGL2来渲染场景。渲染器的构造函数可以接收几个参数,但如果不传参,它们将使用默认值。使用默认参数创建render实例对象:

js 复制代码
import { WebGLRenderer } from 'three';

const renderer = new WebGLRenderer();

网格 Mesh

网格是 3D 计算机图形学中最常见的可见对象,还有其他种类的可见对象,例如Points 点、Line 线条等。

  • Mesh 网格模型创建的物体是由一个个小三角形组成,如下图。这些小三角形又是由三个点确定,需要三个确定的位置,即确定的 xyz
  • Points 模型创建的物体是由一个个点构成,每个点都有自己的位置,Points 相当于点的集合。
  • Line 模型创建的物体是连续的线条,这些线可以理解为是按顺序把所有点连接起来

网格包含几何体和材质

创建一个mesh实例对象:

js 复制代码
import { Mesh } from 'three';

const mesh = new Mesh(geometry, material);

Mesh构造函数有两个参数:几何材质

几何体

可以使用BufferGeometry类创建几何体实例。所有可见对象都离不开点,每一个点都有确定的 x y z坐标。BoxGeometrySphereGeometry等类封装了对这些点的操作,只需要传入长宽高或者半径这些信息,就会创建一个默认的几何体。而BufferGeometry类需要自己去操作所有点信息的方法,可以通过它去设置每一个点的位置,即 position;每一个点的颜色,即 color;每一个点的法向量 normal 等。

当需要一个盒子形状,可以使用 BoxBufferGeometry类,它是 three.js 核心中提供的几个基本形状之一。创建2x2x2盒形几何体实例对象如下:

js 复制代码
import { BoxBufferGeometry } from 'three';

const length = 2;
const width = 2;
const depth = 2;

const geometry = new BoxBufferGeometry(length, width, depth);

构造函数最多需要六个参数,但可以只提供前三个参数,指定盒子的长度、宽度和深度。其他参数将使用默认值。

材料

几何体定义了形状,但材质定义了网格表面的外观 。用 MeshBasicMaterial类,创建基础材质实例对象。更重要的是,不需要在场景中添加任何灯光。MeshBasicMaterial构造函数时省略所有参数将创建默认的白色材质。

js 复制代码
import { MeshBasicMaterial } from 'three';

const material = new MeshBasicMaterial();

MeshBasicMaterial材质属性:

属性 描述
color 颜色: 设置材质的颜色
wireframe 线框: 当此属性设为 true 时,物体将显示为线框。
wireframeLinewidth 线框宽度: 线框模式下,此属性设置线框的宽度。由于WebGLRenderer 不支持该属性,所以无论如何设置该值,线宽始终为1。
wireframeLinecap 线框线端点: 此属性定义线框模式下,顶点间线段的断点如何显示。可选的值有 round(圆)、butt(平)和square(方)三种。默认是 round。对于这个属性的修改结果在实际使用中很难看出来。WebGLRenderer 不支持该属性
wireframeLinejoin 线框连接: 此属性定义线框模式下,线段的连接点如何显示。可选的值有 round(圆)、bevel(斜角)和 miter(尖角)三种。默认是 round。WebGLRenderer 不支持该属性
shading 着色: 此属性定义如何着色。可选的值有 THREE.SmoothShading 和 THREE.FlatShading 两种
vertexColors 顶点颜色: 可以通过此属性为每一个顶点定义不同的颜色。CanvasRenderer 不支持该属性
fox 雾化:此属性指定当前材质是否会受全局雾化效果设置的影响。如果设置成 false,那么全局的雾化效果设置就不会影响当前物体的渲染

材质的分类

常用的材质主要有以下九种:

  • 网格基础材质MeshBasicMaterial:用它赋予几何体一种简单的颜色,或者显示几何体的线框
  • 网格深度材质MeshDepthMaterial:根据网格到相机的距离,这种材质决定如何给网格染色
  • 网格法向材质MeshNormalMaterial:根据物体表面的法向量计算颜色
  • 网格面材质MeshFaceMaterial:这是一个容器,可以在这个容器里为物体的各个表面指定不同的颜色
  • 网格朗伯材质MeshLamberMaterial:这种材质会考虑光照的影响,可以用来创建颜色暗淡、不光亮的物体
  • 网格Phong材质MeshPhongMaterial:这种材质也会考虑光照的影响,而且可以用来创建光亮的物体
  • 着色器材质ShaderMaterial:这种材质允许使用自定义的着色器程序,直接控制顶点的放置方式和像素的着色方式
  • 直线基础材质LineBasicMaterial:这种材质可以用于Line可见对象,从而创建着色器直线
  • 虚线LineDashedMaterial:这种材质跟直线基础材质一样,不过可以用来创建一种虚线效果

材质的共有属性

基础属性:

属性 描述
id 标识符:用来标识材质,在创建时赋值
name 名称:可以通过此属性赋予材质名称
opacity 透明度:定义物体有多透明。与属性 transparent 一起使用才有效。取值范围是 0~1
transparent 决定物体是否透明:如果设为 true,three.js 就会根据 opacity 的值来渲染物体;否则,这个物体就不透明
overdraw 过度绘制:当采用CanvasRenderer类 (画布渲染器)进行渲染时,多边形会被渲染得稍大一点。即当使用这个渲染器画出来的物体有缝隙时,可以将此属性设置为 true
visible 是否可见:定义此材质是否可见。设为 false 时,那么在场景中就看不到该物体
side 侧面:通过此属性,可以决定在几何体的哪一面应用该材质。默认是 THREE.FrontSide (前面 或 外面);还有 THREE.BackSide (后面 或 里面);以及 THREE.DoubleSide (双面 或 双侧)
needsUpdate 是否刷新:对于材质的某些修改,需要告诉 three.js 材质已经改变了。如果这个属性设为 true,three.js 就会使用修改后的材质属性刷新它的缓存

融合属性:

属性 描述
blending 融合:决定物体上的材质如何跟背景融合。融合模式一般是 NormalBlending,在这种模式下只显示材质的上层
blendsrc 融合源: 除了使用标准融合模式外,还可以通过指定 blendsrc、blenddst 及 blendequation 三个属性来创建自定义的融合模式。此属性指定物体(源)如何跟背景(目标)相融合。默认值是 SrcAlphaFactor,即用 alpha(透明度)通道进行融合
blenddst 融合目标: 此属性定义融合时如何使用背景(目标),默认是 OneMinusSrcAlphaFactor,其含义是:目标也使用源的 alpha 通道进行融合,只是用的值是 1 (源的 alpha 通道值)
blendingequation 融合公式: 指定如何使用 blendsrc 和 blenddst 的值。默认方法是 AddEquation,即将两者颜色的值相加。使用这三个属性,就可以创建自定义的融合模式

高级属性:

属性 描述
depthTest 深度测试:这是一个高级WebGL属性,使用这个参数可以打开或关闭GL_DEPTH_TEST参数,该参数决定像素深度是否用来计算新的像素值,通常情况下不必修改这个属性
depthWrite 内部属性,可以用来决定这个材质是否影响WebGL的深度缓存,如果你将一个物体用作二维贴图时,应该将这个属性设置为false,一般不会修改这个属性
polygonOffset 、polygonOffsetFactor、polygonOffsetUnits 通过这些属性可以控制WebGL的POLYGON_OFFSET_FILL功能,一般不需要使用它们
alphaTest 属性的值是一个0~1的数字,表示如果某个像素的alpha值小于这个值,那么像素就不会显示出来

创建three.js程序

创建的每个 three.js 应用程序都需要以下所有这六个步骤:

  1. 初始设置:从 three.js 中导入必要的类,然后获取页面中的canvas元素。
  2. 创建场景:使用 Scene构造函数来创建一个scene实例对象。
  3. 创建相机:主要使用 PerspectiveCamera,因为它绘制的场景视图看起来类似于眼睛看到的真实世界。
  4. 创建可见对象:创建一个简单的盒子形状 Mesh,网格有两个参数几何体和材质
  5. 创建渲染器:责将场景绘制(渲染 )到<canvas>元素中。可以使用 WebGLRenderer
  6. 渲染场景:告诉渲染器使用相机创建场景的静态图片并将该图片输出到<canvas>元素中

初始设置

从 three.js 中导入类和我们创建了一个canvas元素。

vue 复制代码
<script setup lang="ts">
import {ref} from  'vue';
import {
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
} from 'three';
const canvas  = ref();

</script>

<template>
<div ref="canvas"></div>
</template>

<style scoped lang="scss">
</style>

创建场景

vue 复制代码
<script setup lang="ts">
import {ref} from  'vue';
import {
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
} from 'three';
const canvas = ref<HTMLElement | null>(null);
onMounted(() => {
// 创建场景
const scene = new Scene();
// 设置场景的背景颜色
scene.background = new Color('gold');
</script>

<template>
<div ref="canvas"></div>
</template>

<style scoped lang="scss">
</style>

不设置场景的背景颜色,将使用默认颜色,即黑色。上面导入的Color类,将字符串gold作为参数传递给构造函数。指定背景颜色的方法,和 CSS 中一样。

创建相机

PerspectiveCamera构造函数有四个参数:

  • fov视野:相机的视野有多宽,以度为单位。
  • aspect纵横比:场景的宽度与高度的比率。
  • near, 近剪裁平面:任何比这更靠近相机的东西都是不可见的。
  • far远剪裁平面:任何比这更远离相机的东西都是不可见的。

这四个参数一起用于创建一个有边界的空间区域,称之为视锥体

vue 复制代码
<script setup lang="ts">
import {ref} from  'vue';
import {
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
} from 'three';
const canvas = ref<HTMLElement | null>(null);
onMounted(() => {
// 创建场景
const scene = new Scene();
// 设置场景的背景颜色
scene.background = new Color('gold');
// 创建相机并设置其位置
const fov = 35;
const aspect = canvas.value?.clientWidth / canvas.value?.clientHeight;
const near = 0.1;
const far = 100;
const camera = new PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 10);
</script>

<template>
<div ref="canvas"></div>
</template>

<style scoped lang="scss">
</style>

相机的视锥体

如果scene场景是一个永远向四面八方延伸的容器,那么相机的视锥体就是可以看到的部分。在一个顶部被切掉的四边矩形金字塔中当通过PerspectiveCamera查看场景时,截锥体(如下图所示)内的一切都是可见的,而它外面的一切都是不可见的。

在下图中,Near Clipping PlaneFar Clipping Plane之间的区域是相机的视锥。

传递给PerspectiveCamera构造函数的四个参数分别创建了截锥体的一个方面:

  1. 视野定义了平截头体扩展的角度。小视场会产生窄截锥体,而宽视场会产生宽截锥体。
  2. 纵横比将平截头体与场景容器元素相匹配。当我们将其设置为容器的宽度除以其高度时,我们确保可以将类似矩形的平截头体完美的扩展到容器中。如果我们弄错了这个值,场景看起来会伸展和模糊。
  3. 近剪切平面定义了平截头体的小端(最接近相机的点)。
  4. 远剪裁平面定义了平截头体的大端(距相机最远)。

渲染器不会绘制场景中不在平截头体内的任何对象。如果一个物体部分在平截头体体内部,部分在平截头体外部,则外部的部分将被切掉。

定位相机

创建的每个对象最初都位于场景的中心点(0,0,0)位置。 所以添加到场景中的任何对象都将定位在(0,0,0), 都在彼此之上混杂在一起。所以放置相机也是一项重要的技能,但是现在,将其简单地朝向用户的视野,将相机移回Z轴。

js 复制代码
const camera = new PerspectiveCamera(fov, aspect, near, far);
// 方式一:
camera.position.set(0, 0, 10);
// 方式二:
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 10;

设置任何3D对象的位置的方法都是一样的,无论是相机,网格还是其他任何东西。可以将X、Y和Z轴的位置一起设置,或者单独设置 X,Y 和 Z 轴。两种设置位置的方式都会给出相同的结果。位置存储在一个 Vector3类,一个表示 3D 向量的 three.js 类。

创建可见对象

创建了camera实例对象用来查看东西,以及scene实例对象用来把东西放进去。然后是创建需要看到的东西。此处使用 Mesh,网格有两个需要传入的参数:几何体和材质。

创建几何体

网格的几何定义了它的形状。如果需要创建一个盒子形状的几何体,网格将被塑造成一个盒子。如果需要创建一个球形几何体,网格将呈球体形状。

使用BoxGeometry类创建盒子性质的网格。 需要定义三个参数:盒子的宽度、高度和深度。BoxGeometry类应该采用六个参数,但可以省略大部分参数,three.js 会将省略的参数使用默认值填充。

vue 复制代码
<script setup lang="ts">
import {ref} from  'vue';
import {
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
} from 'three';
const canvas = ref<HTMLElement | null>(null);
onMounted(() => {
// 创建场景
const scene = new Scene();
// 设置场景的背景颜色
scene.background = new Color('gold');
// 创建相机并设置其位置
const fov = 35;
const aspect = canvas.value?.clientWidth / canvas.value?.clientHeight;
const near = 0.1;
const far = 100;
const camera = new PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 10);
// 创建2*2*2盒子形状的几何体
const geometry = new BoxGeometry(2, 2, 2);
});
</script>

<template>
<div ref="canvas"></div>
</template>

<style scoped lang="scss">
</style>

如果省略所有参数const geometry = new BoxBufferGeometry();,将得到一个默认框,是1×1×1立方体。

创建材质

材料定义了对象的表面属性,材质就定义了对象 看起来是由什么制成的。几何体告诉网格是一个盒子、一辆汽车或一只猫,而材质描述是一个金属盒子、一辆石质汽车或一只涂成红色的猫。

在 three.js 中有很多材质类型。此处将创建一个 MeshBasicMaterial类型的材质,这是可用的最简单(也是最快)的材质类型。此材质还会忽略场景中的任何灯光,并根据材质的颜色和其他设置为网格着色(阴影),所以可以不用添加任何灯光。就可以在不向构造函数传递任何参数的情况下创建材质,将创建默认的白色材质。

vue 复制代码
<script setup lang="ts">
import {ref} from  'vue';
import {
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
} from 'three';
const canvas = ref<HTMLElement | null>(null);
onMounted(() => {
// 创建场景
const scene = new Scene();
// 设置场景的背景颜色
scene.background = new Color('gold');
// 创建相机并设置其位置
const fov = 35;
const aspect = canvas.value?.clientWidth / canvas.value?.clientHeight;
const near = 0.1;
const far = 100;
const camera = new PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 10);
// 创建2*2*2盒子形状的几何体
const geometry = new BoxGeometry(2, 2, 2);
// 创建默认材质
const material = new MeshBasicMaterial();
});
</script>

<template>
<div ref="canvas"></div>
</template>

<style scoped lang="scss">
</style>

通常需要一盏灯才能看到3D对象,如果使用除MeshBasicMaterial之外的几乎任何其他材质类型,都将无法看到任何东西,因为场景完全处于黑暗中。就像在现实世界中一样,我们通常需要光线才能看到场景中的事物。MeshBasicMaterial是该规则的一个例外。所以如果看不到任何东西,请确保已经在场景中添加了一些灯光,或者暂时将所有材质切换为MeshBasicMaterial

创建网格

当有了几何体和材质,就可以创建网格,将两者都作为参数传入,然后将网格添加到场景中。

vue 复制代码
<script setup lang="ts">
import {ref} from  'vue';
import {
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
} from 'three';
const canvas = ref<HTMLElement | null>(null);
onMounted(() => {
// 创建场景
const scene = new Scene();
// 设置场景的背景颜色
scene.background = new Color('gold');
// 创建相机并设置其位置
const fov = 35;
const aspect = canvas.value?.clientWidth / canvas.value?.clientHeight;
const near = 0.1;
const far = 100;
const camera = new PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 10);
// 创建2*2*2盒子形状的几何体
const geometry = new BoxGeometry(2, 2, 2);
// 创建默认材质
const material = new MeshBasicMaterial();
// 创建网格
const mesh = new Mesh(geometry, material);
// 将网格添加到场景中
scene.add(mesh);
});
</script>

<template>
<div ref="canvas"></div>
</template>

<style scoped lang="scss">
</style>

之后,我们可以随时使用mesh.geometrymesh.material访问几何体和材质。当网格添加到场景中后,如果想删除网格,可以使用scene.remove(mesh)。 一旦网格被添加到场景中,网格就是场景的子节点,场景为网格的父节点。

创建渲染器

three.js 应用程序的最后一个组件是渲染器,它负责将场景绘制(渲染 )到<canvas>元素中。此处使用 WebGLRenderer,还有一些其他渲染器可用作插件,但WebGLRenderer是迄今为止最强大的渲染器,通常是唯一需要的渲染器。创建一个renderer渲染器实例对象,再次使用默认设置。

设置渲染器大小

需要使用容器的宽度和高度告诉渲染器我们的场景大小。使用 CSS 样式选择器使容器占据了整个浏览器窗口的大小,因此场景也将占据整个窗口。

vue 复制代码
<script setup lang="ts">
import {ref} from  'vue';
import {
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
} from 'three';
const canvas = ref<HTMLElement | null>(null);
onMounted(() => {
// 创建场景
const scene = new Scene();
// 设置场景的背景颜色
scene.background = new Color('gold');
// 创建相机并设置其位置
const fov = 35;
const aspect = canvas.value?.clientWidth / canvas.value?.clientHeight;
const near = 0.1;
const far = 100;
const camera = new PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 10);
// 创建2*2*2盒子形状的几何体
const geometry = new BoxGeometry(2, 2, 2);
// 创建默认材质
const material = new MeshBasicMaterial();
// 创建网格
const mesh = new Mesh(geometry, material);
// 将网格添加到场景中
scene.add(mesh);
// 创建渲染器
const renderer = new WebGLRenderer();
// 设置渲染器的大小
renderer.setSize(canvas.value?.clientWidth, canvas.value?.clientHeight);
// 设置设备像素比(DPR)
renderer.setPixelRatio(window.devicePixelRatio);
// 添加canvas元素在页面中
canvas.value?.append(renderer.domElement);
console.log(renderer,99)
console.log(canvas.value)
// 渲染场景
renderer.render(scene, camera);
});
</script>

<template>
<div ref="canvas" id="canvas"></div>
</template>

<style scoped lang="scss">
#canvas {
  width: 100%;
  height: 100%;
}
</style>

将渲染器的大小设置为容器的宽度和高度,如果调整浏览器窗口的大小,窗口的宽度和高度会改变,但画布的大小不会改变。
renderer.setSize它还设置了画布上的宽度、高度和样式属性。

设置设备像素比(DPR)

还需要告诉渲染器设备屏幕的像素比是多少。这是防止 HiDPI 显示器模糊所必需的 (也称为视网膜显示器)。不能忘记设置它,否则场景在测试它的笔记本电脑上可能看起来很棒,但在带有视网膜显示器的移动设备上会模糊。

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue';
import {
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
} from 'three';
const canvas = ref<HTMLElement | null>(null);
// 创建场景
const scene = new Scene();
// 设置场景的背景颜色
scene.background = new Color('gold');
// 创建相机并设置其位置
const fov = 35;
const aspect = canvas.value?.clientWidth / canvas.value?.clientHeight;
const near = 0.1;
const far = 100;
const camera = new PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 10);
// 创建2*2*2盒子形状的几何体
const geometry = new BoxGeometry(2, 2, 2);
// 创建默认材质
const material = new MeshBasicMaterial();
// 创建网格
const mesh = new Mesh(geometry, material);
// 将网格添加到场景中
scene.add(mesh);
// 创建渲染器
const renderer = new WebGLRenderer();
// 设置渲染器的大小
renderer.setSize(canvas.value?.clientWidth, canvas.value?.clientHeight);
// 设置设备像素比(DPR)
renderer.setPixelRatio(window.devicePixelRatio);
</script>

<template>
  <div ref="canvas" id="canvas"></div>
</template>

<style scoped lang="scss">
#canvas {
  width: 100%;
  height: 100%;
}
</style>

<canvas>元素添加到页面

渲染器将从相机的角度将场景绘制到一个<canvas>元素中去。<canvas>元素已经被渲染器实例对象自动创建并存储在renderer.domElement中,但是在看到它之前,需要将它添加到页面中。使用.append操作元素。

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue';
import {
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
} from 'three';
const canvas = ref<HTMLElement | null>(null);
// 创建场景
const scene = new Scene();
// 设置场景的背景颜色
scene.background = new Color('gold');
// 创建相机并设置其位置
const fov = 35;
const aspect = canvas.value?.clientWidth / canvas.value?.clientHeight;
const near = 0.1;
const far = 100;
const camera = new PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 10);
// 创建2*2*2盒子形状的几何体
const geometry = new BoxGeometry(2, 2, 2);
// 创建默认材质
const material = new MeshBasicMaterial();
// 创建网格
const mesh = new Mesh(geometry, material);
// 将网格添加到场景中
scene.add(mesh);
// 创建渲染器
const renderer = new WebGLRenderer();
// 设置渲染器的大小
renderer.setSize(canvas.value?.clientWidth, canvas.value?.clientHeight);
// 设置设备像素比(DPR)
renderer.setPixelRatio(window.devicePixelRatio);
// 添加canvas元素在页面中
canvas.value?.append(renderer.domElement);
</script>

<template>
  <div ref="canvas" id="canvas"></div>
</template>

<style scoped lang="scss">
#canvas {
  width: 100%;
  height: 100%;
}
</style>

渲染场景

渲染场景就是告诉渲染器使用相机创建场景的静态图片并将该图片输出到<canvas>元素中。

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue';
import {
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
} from 'three';
const canvas = ref<HTMLElement | null>(null);
// 创建场景
const scene = new Scene();
// 设置场景的背景颜色
scene.background = new Color('gold');
// 创建相机并设置其位置
const fov = 35;
const aspect = canvas.value?.clientWidth / canvas.value?.clientHeight;
const near = 0.1;
const far = 100;
const camera = new PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 10);
// 创建2*2*2盒子形状的几何体
const geometry = new BoxGeometry(2, 2, 2);
// 创建默认材质
const material = new MeshBasicMaterial();
// 创建网格
const mesh = new Mesh(geometry, material);
// 将网格添加到场景中
scene.add(mesh);
// 创建渲染器
const renderer = new WebGLRenderer();
// 设置渲染器的大小
renderer.setSize(canvas.value?.clientWidth, canvas.value?.clientHeight);
// 设置设备像素比(DPR)
renderer.setPixelRatio(window.devicePixelRatio);
// 添加canvas元素在页面中
canvas.value?.append(renderer.domElement);
// 渲染场景
renderer.render(scene, camera);
</script>

<template>
  <div ref="canvas" id="canvas"></div>
</template>

<style scoped lang="scss">
#canvas {
  width: 100%;
  height: 100%;
}
</style>

如果一切设置正确,将看到金黄色背景下的白色立方体。很难看出它是一个立方体,而看的是一个正方形,之后将解决这个问题。

相关推荐
MossGrower6 小时前
43. Three.js案例-绘制100个立方体
three.js·webglrenderer·perspectivecam·boxgeometry
程序员_三木3 天前
Three.js入门-Raycaster鼠标拾取详解与应用
开发语言·javascript·计算机外设·webgl·three.js
MossGrower4 天前
36. Three.js案例-创建带光照和阴影的球体与平面
3d图形·webgl·three.js·光照与阴影
MossGrower5 天前
34. Three.js案例-创建球体与模糊阴影
webgl·three.js·3d渲染·阴影效果
广东数字化转型5 天前
Three.js相机Camera控件知识梳理
3d·three.js
关山月6 天前
9个学习着色器的GLSL示例
前端·three.js
程序员_三木6 天前
Three.js资源-贴图材质网站推荐
javascript·webgl·three.js·材质·贴图
MossGrower7 天前
37. Three.js案例-绘制部分球体
3d图形·webgl·three.js·球体几何体
关山月7 天前
如何使用Three.js创建3D音频可视化工具
前端·three.js
MossGrower8 天前
35. Three.js案例-创建带阴影的球体与平面
webgl·three.js·阴影·球体