浅析如何创建一个Three.js实例

第一个 3D 案例

之前介绍了three.js开发前准备:详见Three.js应用场景以及开发前准备工作

下面就介绍如何利用three.js开发一个实例。

入门 Three.js 的第一步,就是认识

  • 场景 Scene、
  • 相机 Camera、
  • 渲染器 Renderer

三个基本概念。

场景相机渲染器.png

场景 Scene

文档地址

场景能够让 什么地方摆放什么东西来交给 three.js 来渲染 ,这是 放置物体灯光摄像机的地方

构造器

Scene()

创建一个新的场景对象。

属性

  • .background : Object 若不为空,在渲染场景的时候将设置背景,且背景总是首先被渲染的。 可以设置一个用于的“clear”的 Color(颜色) 、一个覆盖 canvas 的 Texture(纹理) , 或是 a cubemap as a CubeTexture or an equirectangular as a Texture。 默认值为 null
  • .backgroundBlurriness(.Background 模糊度) : Float 设置背景的模糊度。仅影响分配给 Scene.background 的环境贴图。有效输入是介于 0 和 1 之间的浮点值。 默认值为 0
  • .environment : Texture 若该值不为 null,则该纹理贴图将会被设为场景中所有物理材质的环境贴图。 然而,该属性不能够覆盖已存在的、已分配给 MeshStandardMaterial.envMap 的贴图。 默认为 null
  • .fog : Fog 一个 fog 实例定义了影响场景中的每个物体的雾的类型。 默认值为 null
  • .isScene : Boolean 只读标志,用于检查给定对象是否属于“场景”类型。
  • .overrideMaterial Material 如果不为空,它将强制场景中的每个物体使用这里的材质来渲染。 默认值为 null

方法

.toJSON : Object

meta -- 包含有元数据的对象,例如场景中的的纹理或图片。 将 scene 对象转换为 three.js JSON Object/Scene format(three.js JSON 物体/场景格式)。

创建三维场景 Scene

可以把 三维场景 Scene (opens new window)对象理解为虚拟的 3D 场景,用来表示模拟生活中的真实三维场景,或者说三维世界。

具体步骤

  • 第一步:定义物体形状 -- 几何体 Geometry :

Three.js 提供了各种各样的几何体 API,用来表示三维物体的几何形状。

https://threejs.org/docs/index.html?q=geometry

文档搜索 关键词 geometry 可以看到 threejs 提供各种几何体 相关 API,具体使用方法,也可以参考文档。

//创建一个长方体几何对象Geometry
const geometry = new THREE.BoxGeometry(100, 100, 100);
  • 第二步:设置物体外观 -- 材质 Material

如果想 定义物体的外观效果 ,比如颜色,就需要通过材质 Material 相关的 API 实现。

文档搜索 关键词 Material 可以看到 threejs 提供各种材质 Material 相关的 API。

threejs 不同材质渲染效果不同

https://threejs.org/docs/index.html?q=Materia

//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial({
    color: 0xff0000,//0xff0000设置材质颜色为红色
});
  • 第三步:创建一个物体 -- 网格模型 Mesh

实际生活中有各种各样的物体,在 threejs 中可以通过 网格模型 Mesh (opens new window)表示一个虚拟的物体,比如一个箱子、一个鼠标。

https://threejs.org/docs/index.html?q=Mesh#api/zh/objects/Mesh

// 两个参数分别为几何体geometry、材质material
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh

模型位置.position

实际生活中,一个物体往往是有位置的,对于 threejs 而言也是一样的,可以通过位置属性 .position 定义 网格模型 Mesh 在三维场景 Scene 中的位置

//设置网格模型在三维空间中的位置坐标,默认是坐标原点

mesh.position.set(0,10,0);
  • 第四步:添加物体到场景中 .add()

在 threejs 中创建了一个表示物体的虚拟对象 Mesh,需要通过.add()方法,把网格模型 mesh 添加到三维场景 scene 中。

scene.add(mesh);

案例代码--创建一个三维场景

import * as THREE from 'three';

// 创建一个3维度场景
const scene = new THREE.Scene()

// 定义一个几何体,长宽高都是100
const geometry = new THREE.BoxGeometry(100, 100, 100);

// 定义一个基础网格材质(MeshBasicMaterial),设置为红色
const material = new THREE.MeshBasicMaterial({
    color: 0xff000 // 红色材质
})

// 创建要给网格模型,用来表示生活中的物体
const mesh = new THREE.Mesh(geometry,material)

//设置网格模型在三维空间中的位置坐标,默认是坐标原点
mesh.position.set(0,10,0);

// 把mesh添加到场景中
scene.add(mesh);

透视投影相机

Threejs 如果想把三维场景 Scene 渲染到 web 网页上,还需要定义一个虚拟相机 Camera

就像生活中想获得一张照片,需要一台用来拍照的相机。

文档搜索 关键词 Camera 可以看到 threejs 提供各种材质 Camera 相关的 API。

透视投影相机 PerspectiveCamera

透视投影相机 PerspectiveCamera 本质上就是在模拟人眼观察这个世界的规律。

构造器

PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )

参数介绍:

PerspectiveCamera( fov, aspect, near, far )
  • fov — 摄像机视锥体垂直视野角度
  • aspect — 摄像机视锥体长宽比
  • near — 摄像机视锥体近端面
  • far — 摄像机视锥体远端面
参数 含义 默认值
fov 相机视锥体竖直方向视野角度 50
aspect 相机视锥体水平方向和竖直方向长度比,一般设置为 Canvas 画布宽高比 width / height 1
near 相机视锥体近裁截面相对相机距离 0.1
far 相机视锥体远裁截面相对相机距离,far-near 构成了视锥体高度方向 2000

实例化一个透视投影相机对象

// 实例化一个透视投影相机对象
const camera = new THREE.PerspectiveCamera();

相机位置.position

生活中用相机拍照,相机位置不同,拍照结果也不同,threejs 中虚拟相机同样如此。

比如有一间房子,拿着相机站在房间里面,看到的是房间内部,站在房子外面看到的是房子外面效果。

相机对象 Camera 具有位置属性 .position,通过位置属性.position 可以设置相机的位置。

//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
camera.position.set(200, 200, 200);

相机观察目标.lookAt()

用相机拍照需要控制相机的拍照目标,具体说相机镜头对准哪个物体或说哪个坐标。

对于 threejs 相机而言,就是设置.lookAt()方法的参数,指定一个 3D 坐标。

//相机观察目标指向Threejs 3D空间中某个位置
camera.lookAt(0, 0, 0); //坐标原点

camera.lookAt(0, 10, 0);  //y轴上位置10

camera.lookAt(mesh.position);//指向mesh对应的位置

透视投影相机 PerspectiveCamera:视锥体

透视投影相机的四个参数 fov, aspect, near, far 构成一个 四棱台 3D 空间,被称为 视锥体,只有视锥体之内的物体,才会渲染出来,视锥体范围之外的物体不会显示在 Canvas 画布上。

// width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
const width = 800; //宽度
const height = 500; //高度
// 30:视场角度, width / height:Canvas画布宽高比, 1:近裁截面, 3000:远裁截面
const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);

定义相机渲染输出的画布尺寸

生活中相机拍照的照片是有大小的,对于 threejs 而言一样,需要定义相机在网页上输出的 Canvas 画布(照片)尺寸,大小可以根据需要定义,这里先随机定义一个尺寸。

Canvas 画布:会把 threejs 虚拟相机渲染三维场景在浏览器网页上呈现的结果称为 Canvas 画布。

// 定义相机输出画布的尺寸(单位:像素px)
const width = 800; //宽度
const height = 500; //高度

渲染器

有了景物相机,那么如果想获得一张照片,就需要拿着相机,按一下,完成拍照。

对于 threejs 而言,如果完成“咔”这个拍照动作,就需要一个新的对象,也就是 WebGL 渲染器WebGLRenderer (opens new window)

https://threejs.org/docs/index.html?q=WebGLRenderer#api/zh/renderers/WebGLRenderer

构造器

WebGLRenderer( parameters : Object )

parameters - (可选) 该对象的属性定义了渲染器的行为。也可以完全不传参数。在所有情况下,当缺少参数时,它将采用合理的默认值。

WebGL 渲染器 WebGLRenderer

通过 WebGL 渲染器 WebGLRenderer (opens new window)可以实例化一个 WebGL 渲染器对象。

// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();

设置 Canvas 画布尺寸.setSize()

// 定义threejs输出画布的尺寸(单位:像素px)
const width = 800; //宽度
const height = 500; //高度
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)

渲染器渲染方法.render()

渲染器 WebGLRenderer 执行 渲染方法.render() 就可以生成一个 Canvas 画布(照片),并把三维场景 Scene 呈现在 canvas 画布上面,可以把.render()理解为相机的拍照动作。

renderer.render(scene, camera); //执行渲染操作

渲染器 Canvas 画布属性.domElement

渲染器 WebGLRenderer 通 过属性.domElement 可以获得渲染方法.render()生成的 Canvas 画布,.domElement 本质上就是一个 HTML 元素:Canvas 画布。

document.body.appendChild(renderer.domElement);

Canvas 画布插入到任意 HTML 元素中

index.html

<div id="webgl" style="margin-top: 200px;margin-left: 100px;"></div>

main.js

document.getElementById('webgl').appendChild(renderer.domElement);

尾声

全部代码

index.html

<!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>001-第一个3D案例</title>
</head>

<body>
    <div id="webgl" style="margin-top: 50px;margin-left: 100px;"></div>
    <!-- 具体路径配置,根据自己文件目录设置,我的是课件中源码形式 -->
<script type="importmap">
    {
        "imports": {
            "three": "../build/three.module.js"
        }
    }
</script>

    <script type="module" src="./main.js">
    </script>
</body>

</html>

main.js

import * as THREE from 'three';

// 创建一个3维度场景
const scene = new THREE.Scene()

// 给3维度场景添加物体
/**
 * 第一步:定义物体形状 -- 几何体Geometry : https://threejs.org/docs/index.html?q=geometry
 * 第二步:物体外观 -- 材质Material https://threejs.org/docs/index.html?q=Materia 文档搜索关键词geometry可以看到threejs提供各种几何体相关API
 * 第三步:创建一个物体 -- 网格模型Mesh https://threejs.org/docs/index.html?q=Mesh#api/zh/objects/Mesh
 * 第四步:添加物体到场景中  .add()
 */

// 定义一个几何体,长宽高都是100
const geometry = new THREE.BoxGeometry(100, 100, 100);

// 定义一个基础网格材质(MeshBasicMaterial),设置为红色
const material = new THREE.MeshBasicMaterial({
    color: 0xff0000 // 红色材质
})

// 创建要给网格模型,用来表示生活中的物体
const mesh = new THREE.Mesh(geometry,material)

//设置网格模型在三维空间中的位置坐标,默认是坐标原点
mesh.position.set(0,10,0);

// 把mesh添加到场景中
scene.add(mesh);

/**
 * 定义相机
 */

// 定义相机输出画布的尺寸(单位:像素px)
const width = 600; //宽度
const height = 400; //高度
// 30:视场角度, width / height:Canvas画布宽高比, 1:近裁截面, 3000:远裁截面

// 实例化一个透视投影相机对象
const camera = new THREE.PerspectiveCamera(100, width / height, 1, 3000);

// 根据需要设置相机位置具体值
camera.position.set(200, 200, 200);

// 相机的视线,观察目标点坐标 相机观察目标指向Threejs 3D空间中某个位置
camera.lookAt(0, 0, 0); //坐标原点
// camera.lookAt(mesh.position); //指向网格模型mesh

/**
 * 创建webGL渲染器 对象
 */

// 创建webGL渲染器 对象
const renderer = new THREE.WebGLRenderer();
// 定义threejs输出画布的尺寸(单位:像素px)

renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
renderer.render(scene, camera); //执行渲染操作

// 把渲染结果canvas画布,也就是照片提案加到网页中
document.getElementById('webgl').appendChild(renderer.domElement);

参考地址

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

推荐阅读更多精彩内容

  • Three.js 1.Three.js 介绍 OpenGL(英语:Open Graphics Library,译名...
    GuitarHusky阅读 2,449评论 0 1
  • Threejs 为什么? webGL太难用,太复杂! 但是现代浏览器都支持 WebGL 这样我们就不必使用 Fla...
    强某某阅读 5,990评论 1 21
  • 1.重用Material和Geometry 2.不在render()中实例化或是赋值操作 3.粒子系统代替粒子 4...
    bbh123阅读 4,592评论 1 3
  • 这篇文章是给第一次接触three.js[https://threejs.org/]或者看过教程但对thre...
    lorelei47阅读 559评论 0 0
  • 1.什么是Three.js Three.js是一款WebGL三维引擎,在所有WebGL引擎中,Three.js是国...
    浮若年华_7a56阅读 201评论 0 0