国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

入門 Three.js 之后,我真的把一輛車“塞進(jìn)了”瀏覽器里面……

開發(fā) 前端
canvas?的?API?主要用來繪制?2D 圖形,但是在日常的開發(fā)中,除了?2D?圖形之外,還存在一些?3D?的圖形,那么想要繪制?3D?圖形就需要使用到 WebGL。

最近有很多同學(xué)特別關(guān)注 WebGL 和 ThreeJS 的知識(shí),通過 ThreeJS 我們可以完成很多酷炫的 3D 效果。

所以,咱們今天就花上 一個(gè)多小時(shí) 的時(shí)間,借助 ThreeJS的一個(gè)官方示例,來看下,對(duì)于我們前端開發(fā)者而言,如何快速的入門,并完成一個(gè)酷炫的 ThreeJS 項(xiàng)目。

該項(xiàng)目可以直接通過 https://webgl.web.lgdsunday.club/ 進(jìn)行訪問:

圖片圖片

那么廢話不多說,讓我們開始吧~

視頻版直達(dá):https://www.bilibili.com/video/BV139CGYqEa4/ 

圖片圖片

1.canvas、OpenGL、WebGL 到底都是干嘛的

我們知道 canvas 本質(zhì)上是一個(gè) html 標(biāo)簽,它額外提供了一些 API 用來進(jìn)行繪制。

canvas 的 API 主要用來繪制 2D 圖形,但是在日常的開發(fā)中,除了 2D 圖形之外,還存在一些 3D 的圖形,那么想要繪制 3D 圖形就需要使用到 WebGL。

WebGL 是一個(gè)  JavaScript API,可在任何兼容的 Web 瀏覽器中渲染高性能的交互式 3D 和 2D 圖形,而無需使用插件。


注意: 有些瀏覽器是可能不支持 WebGL 的。我們可以通過這個(gè) 網(wǎng)站 來檢測(cè)你的瀏覽器是否支持  WebGL 。

如果你使用的是  Chrome ,但是依然提示不支持,那么可以在 Chrome 中開啟 硬件加速 以獲得支持。

WebGL 中提供了很多的 API 方法,這些方法和 OpenGL 提供的方法是非常相似的。


OpenGL (Open Graphics Library) 是一套用來渲染 2D 和 3D 矢量圖形的跨語言的、跨平臺(tái)的應(yīng)用程序接口 (API) . 這種接口通常用來與圖形處理單元 (GPU) 交互,來達(dá)到 硬件加速渲染 的目的。

WebGL 正是利用了 瀏覽器中的圖形加速硬件(如GPU)來進(jìn)行圖形渲染(這也是為什么我們必須要開啟 瀏覽器硬件加速 的原因)。它通過JavaScript 與 HTML5的Canvas元素進(jìn)行交互,并提供了在Web上展示復(fù)雜的3D圖形和交互式體驗(yàn)的能力。

本章的內(nèi)容,我們總結(jié)來說:

Canvas 提供了一個(gè)基本的2D渲染環(huán)境,OpenGL 是一個(gè)跨平臺(tái)的圖形編程接口規(guī)范,而 WebGL 是基于OpenGL ESJavaScript API,用于在Web瀏覽器中進(jìn)行高性能的3D圖形渲染。WebGL可以看作是在Canvas上使用OpenGL ES進(jìn)行3D渲染的一種實(shí)現(xiàn)方式。

2.WebGL 框架 three.js 初體驗(yàn)-理論篇

在上一小節(jié)中,我們初步了解了 canvasOpenGL 和 WebGL 之間的關(guān)系,我們知道 WebGL 本質(zhì)上是基于 OpenGL API 的一個(gè) 3D 圖形渲染的實(shí)現(xiàn)方式。

但是,如果我們直接基于 WebGL 原生 API 進(jìn)行項(xiàng)目開發(fā)的話,那么使用起來會(huì)比較復(fù)雜。所以在日常的企業(yè)開發(fā)中,我們都會(huì) WebGL 框架來進(jìn)行開發(fā)。

基于 WebGL 的框架其實(shí)非常多,這些框架在視頻中,我們不一個(gè)一個(gè)介紹,大家感興趣的話,可以看一下課程講義:


  1. Three.js: JavaScript 3D 渲染庫(kù),它封裝了底層的 WebGL API,提供了簡(jiǎn)化的接口和功能,可在 Web 上創(chuàng)建和展示 3D 場(chǎng)景
  2. Babylon.js : 一個(gè)功能強(qiáng)大的 WebGL 渲染引擎,它專注于游戲開發(fā)和實(shí)時(shí)圖形應(yīng)用
  3. A-Frame: 一個(gè)基于 Three.js 的 WebVR 框架,它能創(chuàng)建虛擬現(xiàn)實(shí)(VR)和增強(qiáng)現(xiàn)實(shí)(AR)的交互體驗(yàn)
  4. PlayCanvas: 一個(gè)面向游戲開發(fā)的 WebGL 引擎,它提供了可視化的場(chǎng)景編輯器和強(qiáng)大的腳本編輯器,使開發(fā)者能夠創(chuàng)建高性能的 HTML5 游戲。

而我們接下來,主要要說的其實(shí)就是 Three.js。

threejs 是目前國(guó)內(nèi)使用率最多的 JavaScript 3D 渲染庫(kù),它提供了 非常完善的文檔 來幫助我們完成 3D 渲染的開發(fā)。

那么接下來,咱們就創(chuàng)建一個(gè)項(xiàng)目,然后在這個(gè)項(xiàng)目中為大家演示 threejs 的導(dǎo)入和最基礎(chǔ)的用法。

  • 利用 vue-cli 創(chuàng)建項(xiàng)目:
vue create threejs-car
  • 配置項(xiàng)如下:
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, CSS Pre-processors
? Choose a version of Vue.js that you want to start the project with 3.x
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with dart-sass)
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
  • 安裝 threejs 到項(xiàng)目:
cnpm install --save three@0.152.2

那么接下來,咱們就在 App.vue 中利用 threejs 繪制出一個(gè)基本的正方體。

圖片圖片

整個(gè)正方體的繪制,咱們將分成兩個(gè)小節(jié)來說明:理論篇 和 實(shí)戰(zhàn)篇

這一小節(jié),咱們先說理論。讓大家對(duì) threejs 中的一些基礎(chǔ)概念有一個(gè)大概的認(rèn)知。

首先,先導(dǎo)入  threejs

// 導(dǎo)入整個(gè) three.js核心庫(kù)
import * as THREE from 'three'

接下來,我們先了解一些 threejs 中的基本概念:

  • 場(chǎng)景 Scene:它表示要繪制的內(nèi)容,是整個(gè) threejs 繪制的基礎(chǔ)
  • 相機(jī) camera:相機(jī)分為很多種,咱們這里主要使用 PerspectiveCamera 透視相機(jī)。它是一個(gè)最常用的相機(jī)模式,主要可以模擬人眼看到的效果
  • 渲染器 renderer:它的作用比較簡(jiǎn)單,主要用來渲染場(chǎng)景
  • 幾何體 Geometry:要渲染的物體形狀。物體形狀有非常多,咱們這里主要使用立方體 BoxGeometry
  • 材質(zhì) material:為物體賦予一些材質(zhì),比如是光滑的鏡面,還是粗糙的表面。咱們這里主要使用的是基礎(chǔ)材質(zhì) MeshBasicMaterial
  • 網(wǎng)格基類 mesh:將幾何體與材質(zhì)合并成基類。最后可以加入到場(chǎng)景中
  • 渲染函數(shù) renderer.render :利用渲染器的渲染函數(shù),可以根據(jù)場(chǎng)景和攝像頭進(jìn)行渲染
  • 重繪函數(shù) requestAnimationFrame:它與渲染函數(shù)配合,可以重復(fù)進(jìn)行渲染,即:生成動(dòng)畫

最后匯總成一句話:

threejs 本質(zhì)上是:利用 renderer.render 渲染函數(shù),渲染指定的 scene 和 camerascene中可以放置任何的幾何體與材質(zhì)。當(dāng)渲染函數(shù)與 requestAnimationFrame 配合時(shí),可以產(chǎn)生動(dòng)畫。

3.WebGL 框架 three.js 初體驗(yàn)-實(shí)戰(zhàn)篇

在上一小節(jié)中,我們明確了 threejs 中的一些基本概念,那么接下來咱們就根據(jù)所學(xué)的概念,來完成一個(gè)基礎(chǔ)的正方體渲染。

整個(gè)正方體渲染分為三大步進(jìn)行:

  • 創(chuàng)建場(chǎng)景、相機(jī)、渲染器,并把生成的 canvas 添加到 body 中
  • 創(chuàng)建立方體,并把它加入到場(chǎng)景中
  • 渲染場(chǎng)景

以下是具體代碼:

<template>
 <div></div>
</template>

<script setup>
// 導(dǎo)入整個(gè) three.js核心庫(kù)
import * as THREE from 'three'

// 第一大步:創(chuàng)建場(chǎng)景、相機(jī)、渲染器,并把生成的 canvas 添加到 body 中
// 1. 場(chǎng)景:渲染 threejs 內(nèi)容的地方
const scene = new THREE.Scene()
// 2. 相機(jī):用來模擬人眼所看到的的場(chǎng)景
/**
 * 參數(shù):
 * 1. 視野垂直角度 fov — 能夠看到的場(chǎng)景范圍
 * 2. 長(zhǎng)寬比 aspect ratio - 當(dāng)前攝像機(jī)的長(zhǎng)寬比
 * 3. 近截面 near - 比近截面近的,用戶看不到
 * 4. 遠(yuǎn)截面 far - 比遠(yuǎn)截面遠(yuǎn)的,用戶看不到
 */
const camera = new THREE.PerspectiveCamera(
 75,
 window.innerWidth / window.innerHeight,
 0.1,
 1000
)
// 為 camera 設(shè)置攝像縱深
camera.position.z = 2
// 3. 渲染器:用來渲染 3D 場(chǎng)景
const renderer = new THREE.WebGLRenderer()

// 4. webgl 的渲染會(huì)輸出的 canvas 中,這里用來設(shè)置 canvas 的大小
renderer.setSize(window.innerWidth, window.innerHeight)
// 5. 將生成的 canvas 標(biāo)簽插入到 body 中
document.body.appendChild(renderer.domElement)

// 第二大步:創(chuàng)建立方體,并把它加入到場(chǎng)景中

// 1. BoxGeometry是四邊形的原始幾何類,三個(gè)參數(shù)分別為:
/**
 * width — X軸上面的寬度,默認(rèn)值為1。
 * height — Y軸上面的高度,默認(rèn)值為1。
 * depth — Z軸上面的深度,默認(rèn)值為1。
 */
const geometry = new THREE.BoxGeometry(1, 1, 1)
// 2. material 一個(gè)具備簡(jiǎn)單著色的基礎(chǔ)材質(zhì)。表示為立方體的材質(zhì)
const material = new THREE.MeshBasicMaterial({ color: 0x3f7b9d })
// 3. Mesh 一個(gè)網(wǎng)格類,將材質(zhì)與四邊形合并
const cube = new THREE.Mesh(geometry, material)
// 4. 將當(dāng)前生成的立方體加入到場(chǎng)景中
scene.add(cube)

// 第三大步:渲染場(chǎng)景

// 1. 創(chuàng)建一個(gè)方法,通過 requestAnimationFrame 重復(fù)回調(diào)這個(gè)方法
function animate() {
 // 2. requestAnimationFrame:是 JS 原生 API,它會(huì)根據(jù)屏幕刷新率來回調(diào)指定方法
 requestAnimationFrame(animate)

 // 3. 不斷修改 cube 的角度,產(chǎn)生旋轉(zhuǎn)的效果
 cube.rotation.x += 0.01
 cube.rotation.y += 0.01

 // 4. 利用渲染器的 render 方法重復(fù)渲染場(chǎng)景
 renderer.render(scene, camera)
}
animate()
</script>

4.threejs 配置解碼器載入 glb 格式 3D 模型

那么這一小節(jié),咱們就導(dǎo)入一個(gè) 3D 模型,利用 threejs 進(jìn)行渲染。同時(shí)構(gòu)建出最終的 html 結(jié)構(gòu)。

首先,咱們需要先導(dǎo)入一些資料(可以從源碼中獲取):

然后 復(fù)制 上一小節(jié)的 App.vue,重命名為 01:基礎(chǔ)幾何體渲染.vue 。然后在原有的 App.vue 中對(duì)代碼進(jìn)行重構(gòu):

首先是構(gòu)建出對(duì)應(yīng)的 html 結(jié)構(gòu):

<template>
 <div>
  <div id="info">
   <h2>
    請(qǐng)確保你的瀏覽器支持 WebGL,可以點(diǎn)擊
    <a  target="_blank">這里</a>
    進(jìn)行檢測(cè)。如果不支持,可百度處理方案。
   </h2>
   <br /><br />
   <span class="colorPicker">
    <input id="body-color" type="color" value="#ff0000" />
    <br />
    車身
   </span>
   <span class="colorPicker">
    <input id="details-color" type="color" value="#ffffff" />
    <br />
    輪轂
   </span>
   <span class="colorPicker">
    <input id="glass-color" type="color" value="#ffffff" />
    <br />
    玻璃
   </span>
  </div>

  <div id="container"></div>
 </div>
</template>

<style lang="scss">
body {
 color: #bbbbbb;
 background: #333333;
 text-align: center;
 overflow: hidden;
}

a {
 color: #08f;
}

.colorPicker {
 display: inline-block;
 margin: 0 10px;
}
</style>

如果想要導(dǎo)入 glb 格式 的 3D 模型,那么我們需要借助兩個(gè)東西:

  • 新的 webpack-loader:因?yàn)?nbsp;webpack 默認(rèn)只能處理 js 文件,所以想要處理 glb 文件的話,那么需要安裝 file-loader,并進(jìn)行配置:
cnpm i --save-dev file-loader@6.2.0

在 vue.config.js 中配置對(duì)應(yīng)的 loader

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
chainWebpack: (config) => {
    config.module
        .rule('glb')
        .test(/\.(glb|gltf|hdr)$/)
        .use('file-loader')
        .loader('file-loader')
        .options({
            name: 'assets/[name].[hash:8].[ext]'
        })
        .end()
}
})
  • 使用新的 threejs API ,包括 DRACOLoader  和 GLTFLoader 。

DRACOLoader:它是一個(gè)使用 Draco 庫(kù)壓縮的幾何加載器 ,咱們需要借助它的 setDecoderPath 方法來指定 DRACO 解碼器的路徑

GLTFLoader:該 loader 是加載 gltf 文件的 loader。glTF(gl傳輸格式)是一種開放格式的規(guī)范 ,可以高效的加載 3D 內(nèi)容。咱們資源中的 .glb 文件就屬于 3D 內(nèi)容 的一部分。

那么明確好了這兩塊內(nèi)容之后,接下來咱們完成對(duì)應(yīng)得代碼:

<script setup>
// 導(dǎo)入Vue的onMounted鉤子函數(shù)
import { onMounted } from 'vue'
// 導(dǎo)入Three.js庫(kù)
import * as THREE from 'three'
// 導(dǎo)入GLTF模型加載器
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
// 導(dǎo)入DRACO解碼器加載器
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'

// 定義相機(jī)、場(chǎng)景、渲染器對(duì)象
let camera, scene, renderer

function init() {
 // 獲取容器元素
 const container = document.getElementById('container')

 // 創(chuàng)建場(chǎng)景對(duì)象
 scene = new THREE.Scene()
 // 設(shè)置場(chǎng)景的背景顏色為黑色
 scene.background = new THREE.Color(0x333333)

 // 創(chuàng)建透視相機(jī)對(duì)象
 camera = new THREE.PerspectiveCamera(
  40,
  window.innerWidth / window.innerHeight,
  0.1,
  100
 )
 // 為 camera 設(shè)置攝像縱深
 camera.position.set(1, 1, 10)

 // 創(chuàng)建WebGL渲染器對(duì)象,啟用抗鋸齒(更平滑)
 renderer = new THREE.WebGLRenderer({ antialias: true })
 // 設(shè)置渲染器的大小
 renderer.setSize(window.innerWidth, window.innerHeight)
 // 設(shè)置渲染循環(huán)函數(shù)(代替 requestAnimationFrame 的替代函數(shù))
 renderer.setAnimationLoop(render)
 // 將渲染器的畫布元素添加到容器中
 container.appendChild(renderer.domElement)

 // 創(chuàng)建DRACO解碼器加載器對(duì)象
 const dracoLoader = new DRACOLoader()

 // 設(shè)置DRACO解碼器的路徑
 dracoLoader.setDecoderPath('decoder/')

 // 創(chuàng)建GLTF模型加載器對(duì)象
 const loader = new GLTFLoader()
 // 設(shè)置模型加載器的DRACO解碼器
 loader.setDRACOLoader(dracoLoader)

 // 加載 3D 文件
 loader.load(require('@/assets/ferrari.glb').default, function (gltf) {
  // 獲取加載的模型對(duì)象
  const carModel = gltf.scene.children[0]

  // 將車輛模型添加到場(chǎng)景中
  scene.add(carModel)
 })
}

/**
 * 渲染
 */
function render() {
  // 更新控制器
  controls.update()
  
 // 渲染場(chǎng)景
 renderer.render(scene, camera)
}

// 在掛載時(shí)調(diào)用初始化函數(shù)
onMounted(() => {
 init()
})
</script>

此時(shí)運(yùn)行項(xiàng)目,我們可以看到一個(gè)黑色的車子輪廓。

圖片圖片

5.添加控制器,讓模型支持 360°

我們這一小節(jié),希望可以調(diào)整車輛的角度,讓模型支持 360° 旋轉(zhuǎn)。

那么想要支持這樣的功能,咱們需要借助另外一個(gè) threejs API 叫做 OrbitControls 軌道控制器

具體代碼如下:

// 導(dǎo)入軌道控制器OrbitControls
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'

// 定義控制器對(duì)象
let controls

function init () {
  .....
  // 創(chuàng)建軌道控制器對(duì)象
 controls = new OrbitControls(camera, container)
 // 啟用阻尼效果
 controls.enableDamping = true
 // 設(shè)置控制器能夠縮放的最大距離
 controls.maxDistance = 9
 // 設(shè)置控制器的焦點(diǎn)位置
 controls.target.set(0, 0.5, 0)
 // 更新控制器
 controls.update()
  .....
}

6.添加材質(zhì),并基于 RGBELoader 為 3D 模型增加環(huán)境貼圖

現(xiàn)在咱們的模型已經(jīng)可以進(jìn)行 360° 旋轉(zhuǎn)了,但是它現(xiàn)在還比較難看,所以接下來,咱們就需要給它添加一些 “顏色”,讓他變得更加漂亮。

那么想要達(dá)到這個(gè)目的,需要分成兩步去做:

  • 通過 RGBELoader 添加環(huán)境貼圖
  • 通過 Material 渲染物理材質(zhì)

那么首先,咱們先做第一步: 通過 RGBELoader 添加環(huán)境貼圖

RGBELoader 允許你從文件中加載HDR圖像,并將其用作Three.js場(chǎng)景中的環(huán)境貼圖。這對(duì)于創(chuàng)建逼真的照明效果非常有用,因?yàn)镠DR圖像能夠捕捉到真實(shí)世界中的光照細(xì)節(jié)和環(huán)境反射。

// 導(dǎo)入HDR貼圖加載器
  import { RGBELoader } from 'three/addons/loaders/RGBELoader.js'

 // 加載HDR貼圖作為場(chǎng)景的環(huán)境貼圖
 scene.environment = new RGBELoader().load(
  require('@/assets/venice_sunset_1k.hdr').default
 )
 // 設(shè)置環(huán)境貼圖的映射方式為球形映射
 scene.environment.mapping = THREE.EquirectangularReflectionMapping

現(xiàn)在車身應(yīng)該具備一個(gè)基礎(chǔ)顏色。

接下來我們來處理第二步,通過 Material 渲染物理材質(zhì), 讓他具備反光效果:

  • 創(chuàng)建對(duì)應(yīng)材質(zhì):
// 材料設(shè)置
// 創(chuàng)建車身材質(zhì)對(duì)象,設(shè)置顏色和物理屬性
const bodyMaterial = new THREE.MeshPhysicalMaterial({
    color: 0xff0000,
    metalness: 1.0,
    roughness: 0.5,
    clearcoat: 1.0,
    clearcoatRoughness: 0.03,
    sheen: 0.5
})

// 創(chuàng)建細(xì)節(jié)材質(zhì)對(duì)象,設(shè)置顏色和物理屬性
const detailsMaterial = new THREE.MeshStandardMaterial({
    color: 0xffffff,
    metalness: 1.0,
    roughness: 0.5
})

// 創(chuàng)建玻璃材質(zhì)對(duì)象,設(shè)置顏色和物理屬性
const glassMaterial = new THREE.MeshPhysicalMaterial({
    color: 0xffffff,
    metalness: 0.25,
    roughness: 0,
    transmission: 1.0
})
  • 在 loader.load 中,設(shè)置對(duì)應(yīng)材質(zhì):
// 加載 3D 文件
loader.load(require('@/assets/ferrari.glb').default, function (gltf) {
    // 獲取加載的模型對(duì)象
    const carModel = gltf.scene.children[0]

    // 設(shè)置車身部分的材質(zhì)為車身材質(zhì)
    carModel.getObjectByName('body').material = bodyMaterial

    // rim_xx 參考 glb 文件配置
    // 設(shè)置前左輪輞的材質(zhì)為細(xì)節(jié)材質(zhì)
    carModel.getObjectByName('rim_fl').material = detailsMaterial
    // 設(shè)置前右輪輞的材質(zhì)為細(xì)節(jié)材質(zhì)
    carModel.getObjectByName('rim_fr').material = detailsMaterial
    // 設(shè)置后右輪輞的材質(zhì)為細(xì)節(jié)材質(zhì)
    carModel.getObjectByName('rim_rr').material = detailsMaterial
    // 設(shè)置后左輪輞的材質(zhì)為細(xì)節(jié)材質(zhì)
    carModel.getObjectByName('rim_rl').material = detailsMaterial
    // 設(shè)置車輛細(xì)節(jié)部分的材質(zhì)為細(xì)節(jié)材質(zhì)
    carModel.getObjectByName('trim').material = detailsMaterial
    // 設(shè)置玻璃部分的材質(zhì)為玻璃材質(zhì)
    carModel.getObjectByName('glass').material = glassMaterial

    // 將車輛模型添加到場(chǎng)景中
    scene.add(carModel)
})

這樣,咱們的車輛模型就具備了一個(gè)基本的反光效果,會(huì)非常漂亮。

7.根據(jù) GridHelper 設(shè)置網(wǎng)格動(dòng)態(tài)效果

現(xiàn)在咱們的車輛本身已經(jīng)非常好看的,那么這一小節(jié),咱們就構(gòu)建一個(gè)地面網(wǎng)格效果,并且讓網(wǎng)格具備一個(gè)動(dòng)態(tài)后移的動(dòng)效。

想要構(gòu)建網(wǎng)格效果,那么我們需要通過 THREE.GridHelper 類構(gòu)建:

// 定義網(wǎng)格幫助器對(duì)象
let grid

function init () {
  // 創(chuàng)建網(wǎng)格幫助器對(duì)象,設(shè)置網(wǎng)格的大小和顏色
 grid = new THREE.GridHelper(20, 40, 0xffffff, 0xffffff)
 // 設(shè)置網(wǎng)格材質(zhì)的透明度
 grid.material.opacity = 0.2
 // 禁用網(wǎng)格材質(zhì)的深度寫入
 grid.material.depthWrite = false
 // 設(shè)置網(wǎng)格材質(zhì)為透明材質(zhì)
 grid.material.transparent = true
 // 將網(wǎng)格幫助器添加到場(chǎng)景中
 scene.add(grid)

}

那么此時(shí),咱們將具備一個(gè)地面網(wǎng)格。

我們可以調(diào)整 camera 的角度,讓車輛位置更好看一些:

// 設(shè)置相機(jī)位置
camera.position.set(4.25, 1.4, -4.5)

最后,我們可以在被 持續(xù)回調(diào) 的 render 函數(shù)中,動(dòng)態(tài)修改 z軸 的值:

/**
 * 渲染
 */
function render() {
 // 獲取當(dāng)前時(shí)間:https://developer.mozilla.org/zh-CN/docs/Web/API/Performance/now
 const time = -performance.now() / 1000
 // 設(shè)置網(wǎng)格的位置
 grid.position.z = -time % 1

 // 渲染場(chǎng)景
 ......
}

這樣,咱們可以得到一個(gè)持續(xù)后撤的地面效果。

8.構(gòu)建車輪模型組,讓車輪轉(zhuǎn)起來

現(xiàn)在地面可以持續(xù)后撤了,但是車輪還是固定死的,所以這一小節(jié),咱們就要讓車輪可以轉(zhuǎn)動(dòng)起來。

在項(xiàng)目中,每一個(gè)車輪都是一個(gè)單獨(dú)的模型,我們可以通過:

carModel.getObjectByName('wheel_fl')

獲取 前左 車輪。

然后可以在 render 函數(shù)中 通過 車輪.rotation.x = time * Math.PI * 2 讓它轉(zhuǎn)動(dòng)。

所以,我們?nèi)绻胍屗膫€(gè)車輪全部轉(zhuǎn)動(dòng),那么就需要構(gòu)建一個(gè)數(shù)組,然后循環(huán)數(shù)組達(dá)到轉(zhuǎn)動(dòng)的效果:

// 定義一個(gè)數(shù)組用于存儲(chǔ)車輪模型對(duì)象
const wheels = []

在 load 中:

// 將車輛的四個(gè)車輪模型對(duì)象添加到數(shù)組中
wheels.push(
 carModel.getObjectByName('wheel_fl'),
 carModel.getObjectByName('wheel_fr'),
 carModel.getObjectByName('wheel_rl'),
 carModel.getObjectByName('wheel_rr')
)

在 render 函數(shù)中:

// 設(shè)置車輪的旋轉(zhuǎn)角度
for (let i = 0; i < wheels.length; i++) {
 wheels[i].rotation.x = time * Math.PI * 2
}

那么此時(shí),就模擬出了一個(gè)車輛移動(dòng)的效果。

9.監(jiān)聽選擇器的變化,修改車身配置

這一小節(jié),咱們來完成 修改車身顏色 的功能。

所謂的修改車身顏色,其實(shí)本質(zhì)上就是利用 Material.color.set(色值) 方法重新設(shè)置色值。

明確了這一點(diǎn)之后,下面的實(shí)現(xiàn)就會(huì)非常簡(jiǎn)單了:

// 獲取車身顏色輸入框元素
 const bodyColorInput = document.getElementById('body-color')
 // 監(jiān)聽車身顏色輸入框的變化,設(shè)置車身材質(zhì)的顏色
 bodyColorInput.addEventListener('input', function () {
  bodyMaterial.color.set(this.value)
 })

 // 獲取細(xì)節(jié)顏色輸入框元素
 const detailsColorInput = document.getElementById('details-color')
 // 監(jiān)聽細(xì)節(jié)顏色輸入框的變化,設(shè)置細(xì)節(jié)材質(zhì)的顏色
 detailsColorInput.addEventListener('input', function () {
  detailsMaterial.color.set(this.value)
 })

 // 獲取玻璃顏色輸入框元素
 const glassColorInput = document.getElementById('glass-color')
 // 監(jiān)聽玻璃顏色輸入框的變化,設(shè)置玻璃材質(zhì)的顏色
 glassColorInput.addEventListener('input', function () {
  glassMaterial.color.set(this.value)
 })

那么此時(shí),咱們就可以直接修改車身配置了。

10.創(chuàng)建陰影貼圖,讓場(chǎng)景更加真實(shí)

現(xiàn)在咱們的功能其實(shí)已經(jīng)大致完成了。

最后還剩下一個(gè)小功能,就是車身下的陰影效果:

圖片圖片

有了這個(gè)效果之后,會(huì)讓整體變得更加立體。

而想要構(gòu)建出這個(gè)效果,那么需要使用 THREE.TextureLoader ,加載陰影圖:

// 車輛設(shè)置
// 加載車輛陰影貼圖
const shadow = new THREE.TextureLoader().load(
 require('@/assets/ferrari_ao.png')
)

然后利用 mesh 構(gòu)建出 **平面幾何 PlaneGeometry**,并把它添加到 carModel 中:

// 陰影配置
// 創(chuàng)建陰影平面模型
const mesh = new THREE.Mesh(
 new THREE.PlaneGeometry(0.655 * 4, 1.3 * 4),
 new THREE.MeshBasicMaterial({
  map: shadow,
    // 混合
  blending: THREE.MultiplyBlending,
    // 映射
  toneMapped: false,
    // 透明
  transparent: true
 })
)
// 設(shè)置陰影平面模型的旋轉(zhuǎn)角度
mesh.rotation.x = -Math.PI / 2
// 設(shè)置陰影平面模型的渲染順序
mesh.renderOrder = 2
// 將陰影平面模型添加到車輛模型中
carModel.add(mesh)

那么此時(shí),我們就具備了陰影效果。

責(zé)任編輯:武曉燕 來源: 程序員Sunday
相關(guān)推薦

2018-10-22 17:57:28

汽車互聯(lián)

2022-11-02 15:35:35

Condition代碼線程

2023-05-18 07:32:47

Ventoy開源軟件

2017-04-11 00:48:16

銳捷公交無線Wi-Fi

2021-01-03 14:43:43

深度學(xué)習(xí)人工智能視頻

2021-11-22 06:14:45

Three.js3D 渲染花瓣雨

2011-08-31 13:54:36

ipadSculpt 123D

2021-12-03 07:27:30

全景瀏覽Three.js

2025-02-28 08:40:28

ZooKeeperSpringBoot計(jì)費(fèi)系統(tǒng)

2022-07-15 13:09:33

Three.js前端

2021-04-23 16:40:49

Three.js前端代碼

2022-05-21 23:46:16

自動(dòng)駕駛雷達(dá)傳感器

2017-05-08 11:41:37

WebGLThree.js

2022-03-07 09:20:00

JavaScripThree.jsNFT

2019-12-04 12:33:48

程序員技術(shù)設(shè)計(jì)

2021-04-30 07:42:37

Windows10操作系統(tǒng)微軟

2025-06-17 08:15:00

VTK.jsThree.js3D

2025-02-27 09:49:32

2019-11-29 09:30:37

Three.js3D前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

麻豆精品国产91久久久久久| 国产美女一区二区| 亚洲欧美成人网| 久草.com| 国产v日产∨综合v精品视频| 精品欧美一区二区在线观看视频| 欧美五码在线| 综合久久五月天| 樱桃视频成人在线观看| 欧美一区二区三区视频在线观看 | 任你弄精品视频免费观看| 亚洲欧美色图片| 伦理av在线| 精品欧美一区二区久久| 国产精品实拍| 精品欧美一区二区三区精品久久| av大大超碰在线| 欧美日韩国产系列| 午夜免费播放观看在线视频| 在线精品视频免费播放| 伪装者免费全集在线观看| 亚洲成人中文在线| 美女永久在线网站| 狠狠色香婷婷久久亚洲精品| 性欧美精品孕妇| 欧美在线|欧美| 成人a在线视频免费观看| 欧美一区二区三区喷汁尤物| 午夜伦理大片视频在线观看| 欧美视频日韩视频在线观看| 很黄的网站在线观看| 亚洲精品在线电影| 午夜激情在线播放| 日韩一区二区三区xxxx| 精品国产亚洲一区二区在线观看| 欧美激情xxxx性bbbb| 久久中文字幕导航| 国产日韩欧美视频| 亚洲人成高清| 成人在线视频一区二区三区| 成人av中文字幕| qvod激情图片| 欧美一a一片一级一片| 波多野结衣视频一区二区| 深夜福利国产精品| 色爱综合av| 狠狠爱一区二区三区| 国产做a爰片久久毛片| 午夜免费高清视频| 日本韩国欧美一区二区三区| 青草在线视频在线观看| 一区二区亚洲欧洲国产日韩| 欧美一级全黄| 欧美精品在线一区| 91麻豆swag| 婷婷亚洲一区二区三区| 日韩精品一区二区在线观看| av一级久久| av一区二区三区在线观看| 国产一区二区三区四区五区入口| 九九热精品在线播放| 欧美亚洲愉拍一区二区| av在线播放一区| 成人网页在线免费观看| 国产精品99久久久久久久vr| 国产.com| 亚洲乱码一区二区| 欧美日韩性在线观看| 亚洲人成77777| 最新高清无码专区| 国产探花视频在线观看| 97久久久免费福利网址| 久久精品卡一| 国产高潮av| 日韩精品极品视频| 俺要去色综合狠狠| 国产激情片在线观看| 亚洲国产精品欧美一二99| 91资源在线观看| 国产精品69av| 国产成人一区二区精品非洲| 在线播放av网站| 久久精品国产99国产精品澳门 | 国产真实乱偷精品视频免| 波多野结衣在线中文| 亚洲丁香婷深爱综合| 欧美伦理在线视频| 国产精品国三级国产av| 狠狠躁夜夜躁人人爽超碰91| 国产高清视频一区二区| 欧美一区二区影视| 亚洲一区在线电影| 91成人在线网站| 亚洲欧洲精品一区二区三区波多野1战4| 一区二区在线免费观看| 精品肉辣文txt下载| 久久一区二区精品| 亚洲图片自拍偷拍| 999精品视频在线观看| 久久精品一二三区| 国产精品久久久久久亚洲毛片| 三级资源在线| 99九九视频| 亚洲欧洲制服丝袜| 曰本一区二区| 日本五级黄色片| 欧美精品一区二区在线观看| 欧美日本一区二区视频在线观看| 超清福利视频| 欧美大片免费观看| 成人黄色av网站在线| 免费在线看电影| 国产精品美女xx| 午夜精品一区二区三区电影天堂 | 日韩精品视频一二三| 中文字幕免费精品一区高清| 999在线观看精品免费不卡网站| 91精品久久久久久9s密挑| 97福利一区二区| 国产精品伦一区| 91成人午夜| 色乱码一区二区三区在线| 久久精品夜夜夜夜夜久久| 精品无人码麻豆乱码1区2区| 啪啪免费视频一区| 日本视频一区在线观看| 欧美精品日韩精品| 一区二区91| 在线观看麻豆蜜桃| 国产高清精品一区二区三区| 亚洲va中文字幕| 欧洲激情综合| 一级在线视频| 亚洲一区二区在线| 色综合夜色一区| 日韩午夜激情| 精品精品导航| 波多野结衣 作品| 久久这里有精品| 中文字幕一区在线观看| 天堂在线精品| 一级二级三级在线观看| 国产在线观看精品一区二区三区| 欧美日韩国产在线播放| 亚洲欧美日韩高清在线| 国产福利第一视频在线播放| 久久综合入口| 精品亚洲夜色av98在线观看| 国产a级毛片一区| jazzjazz国产精品久久| 可以看美女隐私的网站| 丁香五月网久久综合| 91精品免费在线| 国产成人av自拍| 久久99精品国产自在现线| 99久热re在线精彩视频| 国产精品久久久久久久免费大片| 日韩视频永久免费| 成人网在线播放| 欧美亚洲高清| 日本动漫理论片在线观看网站| 国产a级片网站| 日韩av电影在线网| 欧美剧在线免费观看网站| 国产精品亚洲а∨天堂免在线| 丁香婷婷成人| 亚洲成a人v欧美综合天堂麻豆| 亚洲成年人专区| 97久久久久久| 91精品久久久久久久久99蜜臂 | 欧美一级二级三级| 亚洲韩国青草视频| 国产精品系列在线| 99久久视频| 波多视频一区| 最近中文字幕mv第三季歌词| 欧美日韩在线一二三| 波霸ol色综合久久| 色综合久久中文综合久久牛| 国产在线视频一区二区三区| 亚洲综合福利| 91在线三级| 啊啊啊啊啊啊啊视频在线播放| 久久本道综合色狠狠五月| 色七七影院综合| 色综合久久久久综合体桃花网| 国产精品一二三四区| 免费欧美视频| 大胆人体一区二区| 视频在线91| av久久久久久| 成人淫片在线看| 在线精品91av| 欧美视频精品在线| 国产精品国产a级| 国内成人自拍视频| 一区二区三区毛片免费| 久久天堂久久| 乱人伦视频在线| 搞黄视频免费在线观看|