IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> React+Three.js 简单入门 创建简单3D场景 -> 正文阅读

[JavaScript知识库]React+Three.js 简单入门 创建简单3D场景

Three.js 几个重要概念

首先我们简单地了解一下一个3D场景必不可少的三个元素,在后面的章节再对各个元素中再做比较详细的介绍。
在这里插入图片描述

Scene

场景,可以把scene看作一个沙盘,你所要呈现的物体需要把它摆放在场景中。

Camera

摄像机,最终呈现在屏幕上的影像,实际就是站在摄像机的角度去看场景中的物体,可以把它看作是我们的眼睛。

Renderer

渲染器,我们有了一个场景,并且通过摄像机捕获到了这个画面,如何将这个画面呈现到屏幕,这就是渲染器的工作了。形象一点说,比如我看到一个物体,把它画出来给你看,这个画出来就相当于一个渲染的过程。

坐标系

在three.js 中使用的是右手坐标系,何谓右手坐标系
右手坐标系
在场景中摆放物品的位置、设置摄像机的位置等一切与位置有关的,都要参考这个坐标系。

创建一个简单的3D场景

1 引入Three.js

1.首先在项目中安装依赖

npm install --save three

2.在你需要创建3D场景的文件中引入

import * as THREE from 'three'

这个引入不是一劳永逸的,有一些组件需要特殊引入,我们在用到的时候再说

2.初始化

SimpleScene.js (接下来所有代码都写在这个文件)

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

export default class SimpleScene extends Component {

    componentDidMount(){
        this.init()
    }

    init = () => {
        
        const scene = new THREE.Scene()

        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000)
		
        const renderer = new THREE.WebGLRenderer()
        renderer.setSize(window.innerWidth, window.innerHeight)
        renderer.render(scene, camera)
        document.getElementById('stage').appendChild(this.renderer.domElement)

    }

    render() {
        return (
            <div id="stage">
            </div>
        )
    }
}

首先说明一下初始化中我们做了哪些工作:
1.创建一个场景实例 scene,它是我们后面放置物体的空间
2.创建一个透视摄像机实例 camera,不同摄像机特性有所不同,3D场景中比较常用的就是透视摄像机,四个参数分别为:

  • fov(视野角度): 摄像机的视野角度,在相同的距离下,视野角度越大,看见的东西越多,物体在显示器上就越小
  • aspect(宽高比): 渲染窗口的宽高比
  • near(近截面距离): 在摄像机与近截面直接的物体不会被渲染,也就是不可见
  • far(远截面距离): 远截面后的物体不会被渲染

摄像机示意图
3.创建一个渲染器实例,并设置宽高,这里的宽高指的是显示区域的大小,我们这里使它填充整个屏幕,然后设置它要渲染的场景和摄像机,最后将渲染器放入页面的容器中
至此,我们完成了一个3D场景必需三元素的初始化,运行程序
在这里插入图片描述
我们就得到了一片黑暗的空间,接下来我们开始往里面放东西

放置网格模型

网格模型,也就前面所说的物体,一个网格模型由几何体和材质组成

 		const geometry = new THREE.BoxGeometry(1,1,1)
        const material = new THREE.MeshBasicMaterial({color:'red'})
        const mesh = new THREE.Mesh(geometry, material)
        scene.add(mesh)

首先我们创建一个正方体的几何体,这里的几何体可以理解为只是一个骨架,接下来我们要为这个骨架贴上皮,即创建一个材质,这里我们创建的是一个红色的基本材质,最后把骨架和皮组合起来,创建了一个正方体模型,然后就可以把这个模型放进场景中。这时候运行程序,会发现还是一片黑暗。这是因为摄像机默认位置是(0,0,0),模型放置的默认中心位置也是(0,0,0),就是说现在摄像机在模型内部,我们现在把摄像机拉出来

        camera.position.z = 3

就可以看到一个红色正方形
在这里插入图片描述
但是这看起来一点都不3D,这是因为我们现在看到的是正方体的正面,调整一下摄像机的位置,并让它看向正方体

        camera.position.set(3,3,3)
        camera.lookAt(mesh.position)

就可以看到
在这里插入图片描述
有点3D的感觉了,但还是像2D的样子,差了阴影,要产生阴影,就必须有光。

设置灯光

        const pointLight = new THREE.PointLight(0xffffff)
        pointLight.position.set(3,2,1)
        scene.add(pointLight)

为场景添加一个点光源,光的颜色是白色,刷新一下,发现还是这样,没有阴影
在这里插入图片描述
这是材质的问题,MeshBasicMaterial这种材质对光无感,这也是为啥刚才没有设置灯光的情况下,我们仍可以看到这个正方体,现在我们给正方体换一种皮

        const material = new THREE.MeshPhongMaterial({color:'red'})

在这里插入图片描述
现在终于有3D的感觉了,画面偏暗,我们可以增加灯光的强度,或者增加一个环境光

        const ambientLight = new THREE.AmbientLight(0xcccccc, 0.5)
        scene.add(ambientLight)

在这里插入图片描述

让正方体动起来

光看个图片也不够3D,下一步我们让正方体转起来

    animate = () => {
        requestAnimationFrame(this.animate)
        this.mesh.rotation.y += 0.02
        this.renderer.render(this.scene, this.camera)
    }

然后在初始化后调用,就可以看到正方体以y轴为轴心转起来了
??????

?

requestAnimationFrame(this.animate)

这一行代码的作用是使屏幕刷新时调用括号中的函数,这里的刷新指的是指屏幕刷新率的那个刷新,所以每次执行animate,正方体就会沿y轴旋转0.02个单位,如果电脑的刷新频率是60hz的话,一秒内这个函数执行60次,看起来正方体就转了起来,记得在旋转后调用

this.renderer.render(this.scene, this.camera)

不然只是修改了属性,没有渲染。

控制摄像机

光看着小正方体旋转还是不够3D,接下来我们将控制摄像机,全方位观察小正方体

首先需要引入轨道控制器,有了它我们就可以控制摄像机

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

在初始化的代码中,加上

        const controls = new OrbitControls(this.camera, this.renderer.domElement)
        controls.addEventListener('change', this.handleControl)
        this.controls = controls

第一行,声明这个控制器是控制哪个摄像机,在哪个渲染器节点控制摄像机,第二行给控制器添加监听事件,每当我们使用鼠标拖拽或者滚轮时都会触发回调函数,回调函数相当简单:

    handleControl = () => {
        this.renderer.render(this.scene, this.camera)
    }

这样我们就可以控制摄像机了,来看看效果

?

至此,我们的一个非常简单的3D场景就搭建完毕了。

全部代码

import React, { Component } from 'react'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

export default class SimpleScene extends Component {

    componentDidMount(){
        this.init()
        this.animate()
    }

    
    init = () => {
        
        const scene = new THREE.Scene()
        this.scene = scene

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

        const geometry = new THREE.BoxGeometry(1,1,1)
        const material = new THREE.MeshPhongMaterial({color:'red'})
        const mesh = new THREE.Mesh(geometry, material)
        this.mesh = mesh
        scene.add(mesh)

        camera.position.set(3,3,3)
        camera.lookAt(mesh.position)

        const pointLight = new THREE.PointLight(0xffffff,1)
        pointLight.position.set(3,2,1)
        scene.add(pointLight)

        const ambientLight = new THREE.AmbientLight(0xcccccc, 0.5)
        scene.add(ambientLight)

        const renderer = new THREE.WebGLRenderer()
        renderer.setSize(window.innerWidth, window.innerHeight)
        renderer.render(scene, camera)
        this.renderer = renderer
        document.getElementById('stage').appendChild(renderer.domElement)

        const controls = new OrbitControls(this.camera, this.renderer.domElement)
        controls.addEventListener('change', this.handleControl)
        this.controls = controls
    }

    handleControl = () => {
        this.renderer.render(this.scene, this.camera)
    }

    animate = () => {
        requestAnimationFrame(this.animate)
        this.mesh.rotation.y += 0.02
        this.renderer.render(this.scene, this.camera)
    }

    render() {
        return (
            <div id="stage">
            </div>
        )
    }
}

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-25 11:33:33  更:2021-07-25 11:35:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 18:53:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码