利用ThreeJS實(shí)現(xiàn)孔明燈效果
1.效果圖
2.實(shí)現(xiàn)思路
使用three.js的套路幾乎是固定的:
1 初始化場(chǎng)景(scene)
2.創(chuàng)建透 視相機(jī)(camera)
3.設(shè)置相機(jī)位置(position)
4.創(chuàng)建紋理加載器對(duì)象(texture)
5.創(chuàng)建著色器材質(zhì)(Material)
6.初始化渲染器(WebGLRenderer)
7.設(shè)置渲染尺寸大?。⊿ize)
8.將渲染器添加到body(appendChild)
9.初始化控制器(controls)
10.設(shè)置控制器阻尼(enableDamping)
11.不停地調(diào)用渲染(animate)
ps:萬(wàn)事的開(kāi)頭,你都得先下載引入并初始化three對(duì)象
3.核心代碼
import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; import gsap from "gsap"; import * as dat from "dat.gui"; import vertexShader from "../shaders/flylight/vertex.glsl"; import fragmentShader from "../shaders/flylight/fragment.glsl"; import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; // 目標(biāo):認(rèn)識(shí)shader //創(chuàng)建gui對(duì)象 const gui = new dat.GUI(); // console.log(THREE); // 初始化場(chǎng)景 const scene = new THREE.Scene(); // 創(chuàng)建透 視相機(jī) const camera = new THREE.PerspectiveCamera( 90, window.innerHeight / window.innerHeight, 0.1, 1000 ); // 設(shè)置相機(jī)位置 // object3d具有position,屬性是1個(gè)3維的向量 camera.position.set(0, 0, 2); // 更新攝像頭 camera.aspect = window.innerWidth / window.innerHeight; // 更新攝像機(jī)的投影矩陣 camera.updateProjectionMatrix(); scene.add(camera); // 加入輔助軸,幫助我們查看3維坐標(biāo)軸 // const axesHelper = new THREE.AxesHelper(5); // scene.add(axesHelper); // 加載紋理 // 創(chuàng)建紋理加載器對(duì)象 const rgbeLoader = new RGBELoader(); rgbeLoader.loadAsync("./assets/2k.hdr").then((texture) => { texture.mapping = THREE.EquirectangularReflectionMapping; scene.background = texture; scene.environment = texture; }); // 創(chuàng)建著色器材質(zhì); const shaderMaterial = new THREE.ShaderMaterial({ vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: {}, side: THREE.DoubleSide, // transparent: true, }); // 初始化渲染器 const renderer = new THREE.WebGLRenderer({ alpha: true }); // renderer.shadowMap.enabled = true; // renderer.shadowMap.type = THREE.BasicShadowMap; // renderer.shadowMap.type = THREE.VSMShadowMap; renderer.outputEncoding = THREE.sRGBEncoding; renderer.toneMapping = THREE.ACESFilmicToneMapping; // renderer.toneMapping = THREE.LinearToneMapping; // renderer.toneMapping = THREE.ReinhardToneMapping; // renderer.toneMapping = THREE.CineonToneMapping; renderer.toneMappingExposure = 0.2; const gltfLoader = new GLTFLoader(); let LightBox = null; gltfLoader.load("./assets/model/flyLight.glb", (gltf) => { console.log(gltf); LightBox = gltf.scene.children[1]; LightBox.material = shaderMaterial; for (let i = 0; i < 150; i++) { let flyLight = gltf.scene.clone(true); let x = (Math.random() - 0.5) * 300; let z = (Math.random() - 0.5) * 300; let y = Math.random() * 60 + 25; flyLight.position.set(x, y, z); gsap.to(flyLight.rotation, { y: 2 * Math.PI, duration: 10 + Math.random() * 30, repeat: -1, }); gsap.to(flyLight.position, { x: "+=" + Math.random() * 5, y: "+=" + Math.random() * 20, yoyo: true, duration: 5 + Math.random() * 10, repeat: -1, }); scene.add(flyLight); } }); // 設(shè)置渲染尺寸大小 renderer.setSize(window.innerWidth, window.innerHeight); // 監(jiān)聽(tīng)屏幕大小改變的變化,設(shè)置渲染的尺寸 window.addEventListener("resize", () => { // console.log("resize"); // 更新攝像頭 camera.aspect = window.innerWidth / window.innerHeight; // 更新攝像機(jī)的投影矩陣 camera.updateProjectionMatrix(); // 更新渲染器 renderer.setSize(window.innerWidth, window.innerHeight); // 設(shè)置渲染器的像素比例 renderer.setPixelRatio(window.devicePixelRatio); }); // 將渲染器添加到body document.body.appendChild(renderer.domElement); // 初始化控制器 const controls = new OrbitControls(camera, renderer.domElement); // 設(shè)置控制器阻尼 controls.enableDamping = true; // 設(shè)置自動(dòng)旋轉(zhuǎn) controls.autoRotate = true; controls.autoRotateSpeed = 0.1; controls.maxPolarAngle = (Math.PI / 3) * 2; controls.minPolarAngle = (Math.PI / 3) * 2; const clock = new THREE.Clock(); function animate(t) { controls.update(); const elapsedTime = clock.getElapsedTime(); requestAnimationFrame(animate); // 使用渲染器渲染相機(jī)看這個(gè)場(chǎng)景的內(nèi)容渲染出來(lái) renderer.render(scene, camera); } animate();
到此這篇關(guān)于利用ThreeJS實(shí)現(xiàn)孔明燈效果的文章就介紹到這了,更多相關(guān)ThreeJS孔明燈內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳談js中window.location.search的用法和作用
下面小編就為大家?guī)?lái)一篇詳談js中window.location.search的用法和作用。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02使用JS代碼實(shí)現(xiàn)點(diǎn)擊按鈕下載文件
有時(shí)候我們?cè)诰W(wǎng)頁(yè)上需要增加一個(gè)下載按鈕,讓用戶(hù)能夠點(diǎn)擊后下載頁(yè)面上的資料,那么怎樣才能實(shí)現(xiàn)功能呢?今天小編給大家分享兩種方法實(shí)現(xiàn)js實(shí)現(xiàn)點(diǎn)擊按鈕下載文件,需要的朋友參考下吧2016-11-11javascript 自動(dòng)標(biāo)記來(lái)自搜索結(jié)果頁(yè)的關(guān)鍵字
使用javascript自動(dòng)標(biāo)記來(lái)自搜索結(jié)果頁(yè)的關(guān)鍵字的實(shí)現(xiàn)代碼。2010-01-01怎樣使用?JavaScript?轉(zhuǎn)義字符串中的引號(hào)
要轉(zhuǎn)義字符串中的單引號(hào)或雙引號(hào),需要在字符串內(nèi)容中的每個(gè)單引號(hào)或雙引號(hào)之前使用反斜杠?\?字符,例如?‘that’s?it’,這篇文章主要介紹了如何使用?JavaScript?轉(zhuǎn)義字符串中的引號(hào),需要的朋友可以參考下2023-11-11JavaScript遍歷數(shù)組和對(duì)象的元素簡(jiǎn)單操作示例
這篇文章主要介紹了JavaScript遍歷數(shù)組和對(duì)象的元素簡(jiǎn)單操作,結(jié)合實(shí)例形式分析了javascript數(shù)組與對(duì)象元素遍歷相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2019-07-07JavaScript選擇排序算法原理與實(shí)現(xiàn)方法示例
這篇文章主要介紹了JavaScript選擇排序算法原理與實(shí)現(xiàn)方法,簡(jiǎn)單分析了選擇排序算法的概念、原理并結(jié)合實(shí)例形式分析了JavaScript選擇排序算法的相關(guān)實(shí)現(xiàn)技巧與操作注意事項(xiàng),需要的朋友可以參考下2018-08-08JavaScript異步編程操作實(shí)現(xiàn)介紹
異步(Asynchronous, async)是與同步(Synchronous, sync)相對(duì)的概念。在我們學(xué)習(xí)的傳統(tǒng)單線(xiàn)程編程中,程序的運(yùn)行是同步的,同步不意味著所有步驟同時(shí)運(yùn)行,而是指步驟在一個(gè)控制流序列中按順序執(zhí)行,而異步的概念則是不保證同步的概念2022-09-09