最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

react-three-fiber實(shí)現(xiàn)炫酷3D粒子效果首頁

 更新時(shí)間:2022年08月26日 14:17:40   作者:字節(jié)架構(gòu)前端  
這篇文章主要介紹了react-three-fiber實(shí)現(xiàn)3D粒子效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

背景

初學(xué)者怎么用react-three-fiber實(shí)現(xiàn)一個(gè)炫酷粒子效果的首頁

Three.js工作原理

場景(Scene)、相機(jī)(Camera)和渲染器(Renderer)構(gòu)成了web端展示3D模型的基本腳手架,HTML<canvas>元素則可以讓我們在頁面中看到3D模型。

場景(Scene)

場景是3D模型的載體,可以將場景視為所有 3D 對(duì)象都存在于其中的“小宇宙”。

import { Scene } from 'three';
const scene = new Scene();

場景擁有一個(gè)3D 笛卡爾坐標(biāo)系也是俗稱的右手坐標(biāo)系,它是我們在three.js 中處理可見對(duì)象時(shí)的主要參考框架。

場景的中心是點(diǎn)(0,0,0),也稱為坐標(biāo)原點(diǎn)。每當(dāng)我們創(chuàng)建一個(gè)新對(duì)象并放入場景中時(shí),默認(rèn)是放置在原點(diǎn)。

相機(jī)(Camera)

在場景搭建好之后,我們需要將3D場景轉(zhuǎn)化為人眼2D視角可見的東西,就需要引入相機(jī),進(jìn)行這種轉(zhuǎn)換有很多種相機(jī)模式。對(duì)我們來說,最重要的相機(jī)是透視相機(jī)(PerspectiveCamera),它是模擬人眼視角,從一個(gè)點(diǎn)到物體的視角成像,遵循近大遠(yuǎn)小的原理。

import { PerspectiveCamera } from 'three';
const fov = 75; // 攝像機(jī)視錐體垂直視野角度
const aspect = container.clientWidth / container.clientHeight; //攝像機(jī)視錐體長寬比
const near = 0.1; // 攝像機(jī)視錐體近端面
const far = 100; // 攝像機(jī)視錐體遠(yuǎn)端面
const camera = new PerspectiveCamera(fov, aspect, near, far);

渲染器(renderer)

渲染器通過相機(jī)觀察3D場景,并將看到的東西繪制到<canvas>上,我們把這個(gè)過程叫做渲染。

import { WebGLRenderer } from 'three';
const renderer = new WebGLRenderer();

雖然場景、相機(jī)和渲染器一起為我們提供了 three.js 的基本腳手架。但是我們無法在頁面上看到腳手架的存在。

網(wǎng)格對(duì)象(mesh)

網(wǎng)格是 3D 計(jì)算機(jī)圖形學(xué)中最常見的一種可見對(duì)象,用于顯示各種 3D 對(duì)象。還有其他種類的可見對(duì)象,例如線條、形狀、精靈和粒子等等。

網(wǎng)格一般包含幾何模型和材質(zhì),在創(chuàng)建網(wǎng)格之前,需要?jiǎng)?chuàng)建幾何模型和材質(zhì)。

import { Mesh } from 'three';
const mesh = new Mesh(geometry, material);

幾何模型形狀定義了網(wǎng)格的形狀,而材質(zhì)定義了網(wǎng)格的表面外觀。

基于以上介紹可以寫一個(gè)簡單的three.js demo。

// 場景
const scene = new THREE.Scene();
// 相機(jī)
const camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;
 // 模型
const geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animation );
document.body.appendChild( renderer.domElement );

function animation( time ) {

    mesh.rotation.x = time / 2000;
    mesh.rotation.y = time / 1000;

    renderer.render( scene, camera );
 }

react-three-fiber

react-three-fiber在它的github的readme.md上聲明了三點(diǎn)前提:

  • 在 Threejs 中可以實(shí)現(xiàn)的都可以在react-three-fiber實(shí)現(xiàn)。
  • react-three-fiber沒有額外的開銷,并且由于 Reacts 調(diào)度能力,它在規(guī)模上優(yōu)于 Threejs。
  • react-three-fiber可以跟上three.js的頻繁功能更新,three.js版本添加、刪除或更改功能,無需依賴此庫的更新。

react-three-fiber的生態(tài)系統(tǒng)

畫布(Canvas)

Canvas 組件在幕后做了一些重要的設(shè)置工作:

  • 它設(shè)置了SceneCamera,這是渲染所需的基本構(gòu)建塊
  • 它每幀渲染我們的場景,不需要傳統(tǒng)的渲染循環(huán)
import ReactDOM from 'react-dom'
import { Canvas } from '@react-three/fiber'
function App() {
    return (
    <div id="canvas-container">
      <Canvas />
    </div>)
}
ReactDOM.render(<App />, document.getElementById('root'))

Canvas 響應(yīng)適應(yīng)父節(jié)點(diǎn),因此可以通過更改父節(jié)點(diǎn)的寬度和高度來控制它的大小,在本例中為 #canvas-container。

上面的three.js demo 代碼用react-three-fiber實(shí)現(xiàn)如下:

import React from "react";
import { Canvas } from "react-three-fiber";
import "./styles.css";
export default function App() {
  return (
    <div className="App">
      <Canvas>
        <mesh>
          <boxBufferGeometry />
          <meshPhongMaterial />
        </mesh>
        <ambientLight args={[0xff0000]} intensity={0.1} />
        <directionalLight position={[0, 0, 5]} intensity={0.5} />
      </Canvas>
    </div>
  );
}

3D粒子模型構(gòu)建

首先看一段非常簡單的粒子模型的three.js實(shí)現(xiàn)

// 創(chuàng)建一個(gè)球體幾何對(duì)象
 var geometry = new THREE.SphereGeometry(100, 25, 25); 
// 創(chuàng)建一個(gè)點(diǎn)材質(zhì)對(duì)象 
var material = new THREE.PointsMaterial({
    color: 0x0000ff, //顏色
    size: 3, //點(diǎn)渲染尺寸
});
// 點(diǎn)模型對(duì)象 參數(shù):幾何體 點(diǎn)材質(zhì) 
let point = new THREE.Points(geometry, material); 
// 網(wǎng)格模型添加到場景中
 scene.add(point); 

THREE.Points - 用來創(chuàng)造點(diǎn)的類,也用來批量管理粒子,這個(gè)類的構(gòu)造函數(shù)可以接受兩個(gè)參數(shù),一個(gè)幾何體和一個(gè)材質(zhì),幾何體參數(shù)用來定義粒子的位置坐標(biāo),而材質(zhì)參數(shù)用來格式化粒子.

  • 在threejs的粒子系統(tǒng)中,每個(gè)粒子其實(shí)是一張圖片或者一個(gè)canvas而不是3D的物體。
  • 當(dāng)粒子量級(jí)非常大時(shí),可以用BufferGeometry來代替Geometry的頂點(diǎn),因?yàn)樗梢詫?shù)據(jù)存儲(chǔ)在緩沖區(qū)中,減少數(shù)據(jù)傳遞到GPU的成本,同時(shí)因?yàn)樵诰彌_區(qū),所以更適合靜態(tài)的物體。

實(shí)現(xiàn)思路

  • 定義buffer幾何體,并填充數(shù)據(jù)

創(chuàng)建buffer幾何體

<bufferGeometry attach="geometry"></bufferGeometry>

幾何體定義好之后需要往里填充數(shù)據(jù)。假設(shè)我們的星系是由70000顆星星組成,星系的背景零零散散的有9000顆星星環(huán)繞。我們需要確定各個(gè)點(diǎn)的位置和顏色。背景的星星統(tǒng)一由藍(lán)色的點(diǎn),我們在之后的材質(zhì)里定義顏色,星系的星星使用顏色矩陣。

//背景
const bgStarsPositions = useMemo(() => {
    const bgStarsPositions = new Float32Array(parameters.stars * 3);
    // 背景星星的位置
    for (let j = 0; j < parameters.stars; j++) {
      bgStarsPositions[j * 3 + 0] = (Math.random() - 0.5) * 20;
      bgStarsPositions[j * 3 + 1] = (Math.random() - 0.5) * 20;
      bgStarsPositions[j * 3 + 2] = (Math.random() - 0.5) * 20;
    }
    return bgStarsPositions;
  }, []);
// 星系
const [positions, colors] = useMemo(() => {
    const positions = new Float32Array(parameters.count * 3);
    const colors = new Float32Array(parameters.count * 3);

    const colorInside = new THREE.Color(parameters.insideColor);
    const colorOutside = new THREE.Color(parameters.outsideColor);

    for (let i = 0; i < parameters.count; i++) {
      // 位置
      const x = Math.random() * parameters.radius;
      const branchAngle = ((i % parameters.branches) / parameters.branches) * 2 * Math.PI;
      const spinAngle = x * parameters.spin;

      const randomX = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : -1);
      const randomY = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : -1);
      const randomZ = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1 : -1);

      positions[i * 3] = Math.sin(branchAngle + spinAngle) * x + randomX;
      positions[i * 3 + 1] = randomY;
      positions[i * 3 + 2] = Math.cos(branchAngle + spinAngle) * x + randomZ;

      //顏色

      const mixedColor = colorInside.clone();
      mixedColor.lerp(colorOutside, x / parameters.radius);

      colors[i * 3 + 0] = mixedColor.r;
      colors[i * 3 + 1] = mixedColor.g;
      colors[i * 3 + 2] = mixedColor.b;
    }
    return [positions, colors];
  }, []);

將位置和顏色賦值到buffer幾何體的attribute里

//星系
<bufferGeometry attach="geometry">
    <bufferAttribute
        attachObject={['attributes', 'position']}
        count={70000}
        array={positions}
        itemSize={3}></bufferAttribute>
    <bufferAttribute
        attachObject={['attributes', 'color']}
        count={70000}
        array={colors}
        itemSize={3}></bufferAttribute>
</bufferGeometry>

//背景
<bufferGeometry attach="geometry">
    <bufferAttribute
        attachObject={['attributes', 'position']}
        count={parameters.stars}
        array={bgStarsPositions}
        itemSize={3}></bufferAttribute>
</bufferGeometry>
  • 將buffer幾何體包裹在點(diǎn)模型中,并為每個(gè)點(diǎn)引入材質(zhì)

引入點(diǎn)材質(zhì)

const textureLoader = new THREE.TextureLoader();
const shape = textureLoader.load('1.png');

為每個(gè)點(diǎn),加載材質(zhì)。

// 背景
<points ref={bgstart}>
      <bufferGeometry attach="geometry">
        <bufferAttribute
          attachObject={['attributes', 'position']}
          count={parameters.stars}
          array={bgStarsPositions}
          itemSize={3}></bufferAttribute>
      </bufferGeometry>
      <pointsMaterial
        attach="material"
        size={0.01}
        depthWrite={false}
        sizeAttenuation={true}
        blending={AdditiveBlending}
        color={'#1b3984'}
        transparent={true}
        alphaMap={shape}></pointsMaterial>

</points>
// 星系
<points ref={points}>
      <bufferGeometry attach="geometry">
        <bufferAttribute
          attachObject={['attributes', 'position']}
          count={parameters.count}
          array={positions}
          itemSize={3}></bufferAttribute>
        <bufferAttribute
          attachObject={['attributes', 'color']}
          count={parameters.count}
          array={colors}
          itemSize={3}></bufferAttribute>
      </bufferGeometry>
      <pointsMaterial
        attach="material"
        size={0.01}
        depthWrite={false}
        sizeAttenuation={true}
        blending={AdditiveBlending}
        vertexColors={true}
        transparent={true}
        alphaMap={shape}></pointsMaterial>
</points>
  • 加入旋轉(zhuǎn)動(dòng)畫

//背景
const bgstart = useRef<any>();

useFrame(state => {
    const elapsedTime = state.clock.elapsedTime;
    bgstart.current.rotation.y = -elapsedTime * 0.05;
});
//星系
const points = useRef<any>();

useFrame(state => {
    const elapsedTime = state.clock.elapsedTime;
    points.current.rotation.y = elapsedTime * 0.3;
});

小知識(shí)點(diǎn):useFrame這個(gè)鉤子允許你在每個(gè)渲染的幀上執(zhí)行代碼,比如運(yùn)行效果、更新控件等等。你會(huì)收到狀態(tài)和時(shí)鐘增量。您的回調(diào)函數(shù)將在渲染幀之前被調(diào)用。當(dāng)組件卸載時(shí),它會(huì)自動(dòng)從渲染循環(huán)中取消訂閱。

最后呈現(xiàn)結(jié)果

到此這篇關(guān)于react-three-fiber實(shí)現(xiàn)炫酷3D粒子效果首頁的文章就介紹到這了,更多相關(guān)react 3D粒子內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React修改數(shù)組對(duì)象的注意事項(xiàng)及說明

    React修改數(shù)組對(duì)象的注意事項(xiàng)及說明

    這篇文章主要介紹了React修改數(shù)組對(duì)象的注意事項(xiàng)及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • ChatGLM?集成LangChain工具詳解

    ChatGLM?集成LangChain工具詳解

    這篇文章主要為大家介紹了Svelte和React框架使用比較,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • React中關(guān)于render()的用法及說明

    React中關(guān)于render()的用法及說明

    這篇文章主要介紹了React中關(guān)于render()的用法及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • ReactJS中不同類型的狀態(tài)詳解

    ReactJS中不同類型的狀態(tài)詳解

    這篇文章主要為大家介紹了ReactJS中不同類型的狀態(tài)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • React純前端模擬實(shí)現(xiàn)登錄鑒權(quán)

    React純前端模擬實(shí)現(xiàn)登錄鑒權(quán)

    這篇文章主要為大家詳細(xì)介紹了React純前端模擬實(shí)現(xiàn)登錄鑒權(quán)的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-04-04
  • React組件性能提升實(shí)現(xiàn)方法詳解

    React組件性能提升實(shí)現(xiàn)方法詳解

    這篇文章主要介紹了React組件性能最佳優(yōu)化實(shí)踐分享,React組件性能優(yōu)化的核心是減少渲染真實(shí)DOM節(jié)點(diǎn)的頻率,減少Virtual?DOM比對(duì)的頻率,更多相關(guān)內(nèi)容需要的朋友可以參考一下
    2023-03-03
  • React如何以Hook的方式使用Echarts

    React如何以Hook的方式使用Echarts

    這篇文章主要介紹了React如何以Hook的方式使用Echarts問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Hello?React的組件化方式之React入門小案例演示

    Hello?React的組件化方式之React入門小案例演示

    這篇文章主要介紹了Hello?React的組件化方式-React入門小案例,本文通過Hello?React的案例,?來體驗(yàn)一下React開發(fā)模式,?以及jsx的語法,需要的朋友可以參考下
    2022-10-10
  • 淺談react-native熱更新react-native-pushy集成遇到的問題

    淺談react-native熱更新react-native-pushy集成遇到的問題

    下面小編就為大家?guī)硪黄獪\談react-native熱更新react-native-pushy集成遇到的問題。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • 淺談React前后端同構(gòu)防止重復(fù)渲染

    淺談React前后端同構(gòu)防止重復(fù)渲染

    這篇文章主要介紹了淺談React前后端同構(gòu)防止重復(fù)渲染,首先解釋React前后端同構(gòu)、React首屏渲染的概念。然后通過這2個(gè)概念解決服務(wù)端渲染完成后瀏覽器端重復(fù)渲染的問題。有興趣的可以了解一下
    2018-01-01

最新評(píng)論

台南县| 崇义县| 巨野县| 化州市| 岳普湖县| 读书| 宁陵县| 台湾省| 额尔古纳市| 卫辉市| 分宜县| 博野县| 泰兴市| 漳平市| 青阳县| 元阳县| 夏邑县| 兰西县| 德江县| 灯塔市| 沈丘县| 邻水| 陆川县| 来凤县| 稷山县| 宜宾市| 邹平县| 宣武区| 大方县| 彭阳县| 扶余县| 长汀县| 化德县| 三门峡市| 曲阳县| 阳泉市| 宣威市| 白银市| 双牌县| 柯坪县| 松滋市|