2024-03-19 / @syui

vrm , threejs

three.jsでbloomを有効にする

リファクタリングの一環としてweb周りで作ったものを整理しています。

ただ、整理といいつつ、ほとんど新しい実装を試していて、コード自体はきれいになっていません。

以前は、three-vrm:v0.6で作成されたプロジェクトのforkを使用していましたが、なかなかに複雑で古いpackageを使用していたので、イチから作り直しました。

three-vrm:v2.1にして、node:v21, yarn:v1.22を使っています。

bloom

ぼんやりと発光させるには、bloomを有効にしなければなりません。

ただし、threeに入っているexampleはメンテナンスされていません。別のものを使ったほうが良いでしょう。

$ yarn add postprocessing
//import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
//import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass';
//import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass";
// https://github.com/pmndrs/postprocessing
import { BloomEffect, EffectComposer, EffectPass, RenderPass } from "postprocessing";

const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));
composer.addPass(new EffectPass(camera, new BloomEffect()));

requestAnimationFrame(function render() {

	requestAnimationFrame(render);
	composer.render();

});

注意としては、WebGLRendererのoptionによっては動かないことがあるらしいので、そのときは以下を設定してください。

import { WebGLRenderer } from "three";

const renderer = new WebGLRenderer({
	powerPreference: "high-performance",
	antialias: false,
	stencil: false,
	depth: false
});

progress

progress-barを出します。既に用意されているらしいので、それを使います。

// https://sbcode.net/threejs/progress-indicator
let manager = new THREE.LoadingManager();
let progressBar = document.getElementById('progressBar') as HTMLProgressElement

// https://threejs.org/docs/#api/en/loaders/managers/LoadingManager
manager.onStart = function ( url, itemsLoaded, itemsTotal ) {
    //console.log( 'Started loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' );
    progressBar.style.display = 'block'
        let percentComplete = (itemsLoaded / itemsTotal) * 100
        progressBar.value = percentComplete === Infinity ? 100 : percentComplete
};
manager.onLoad = function ( ) {
    //console.log( 'Loading complete!');
    progressBar.style.display = 'none'
};
manager.onProgress = function ( url, itemsLoaded, itemsTotal ) {
    let percentComplete = (itemsLoaded / itemsTotal) * 100
        progressBar.value = percentComplete === Infinity ? 100 : percentComplete
        //console.log( 'Loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' );
};
manager.onError = function ( url ) {
    //console.log( 'There was an error loading ' + url );
    progressBar.style.display = 'block'
};
<progress value="0" max="100" id="progressBar"></progress>
progress {
	width: 100%;
	height:8px;
	position: absolute;
	border-radius: 0px;
}

::-webkit-progress-bar {
	border-radius: 0px;
	background-color: #e6e6fa;
}

::-webkit-progress-value {
  background-color: #4682b4;
}