Skip to main content

GLSL and THREE.js in React

GLSL and THREE.js in React

THREE.jsはWebGLを用いて3D表現ができるライブラリで、 GLSLファイルもビルドしてくれるのでとてもわくわくできます。 (トップページにglslを利用してます。) 従来のjsだと大規模なアプリになると予期しないことが多く起こるので、 viewに特化したReactのライフサイクル上で安全に構築します。(特にhookだと関数型プログラミングできる。)

ポイント

DOMを直接操作するライブラリなどはReactでは使えないけど、 hookではuseEffect内に処理をかくと, Reactのライフサイクルから隠すことができます. classベースではcomponentDidMountをうまく利用すればできる.)

あと,THREE.jsはmountごとに再実行すると重くなるので、 Reactのライフサイクルと関係ない変数にはuseRefを使うと再renderせずうまくいきます。

useEffect内に初期処理をかき、一度だけ実行されるようにしてます。 特にWebGLRenderer作成時にcanvasを指定させ、 sceneとcameraにはuseRefを使うことであとから変更しても初期処理が再実行されないようにします。

import React, {useState, useRef, useEffect} from 'react'
import * as THREE from "three";

const App = (props) => {
const scene = useRef(new THREE.Scene());
const camera = useRef(new THREE.Camera());
useEffect(()=>{
const canvas = document.getElementById('renderer');
const renderer = new THREE.WebGLRenderer({canvas});
const light = new THREE.DirectionalLight(0xFFFFFF, 1);
light.position.set( 1, 1, 1 );
scene.current.add(light);
/*~~more process~~*/
const render = () => {
requestAnimationFrame( render );
renderer.render( scene.current, camera.current );
}
render();
}, []);
return <canvas id="renderer" style={{position:"fixed",top:0,left:0}}/>
}

GLSLを利用する

glslファイルをfetchでloadし、変数へsetしたとき, 二つ目のuseEffectが実行します. (mount時と,各glslファイルがloadできたときの計三回実行される.) glslに渡すuniformsの値はuseRefで後から変更しても再実行されないようにします。