+++ date = "2024-03-19" tags = ["vrm", "threejs"] title = "three.jsでbloomを有効にする" slug = "vrm" +++ リファクタリングの一環としてweb周りで作ったものを整理しています。 - https://git.syui.ai/ai/vrm ただ、整理といいつつ、ほとんど新しい実装を試していて、コード自体はきれいになっていません。 以前は、`three-vrm:v0.6`で作成されたプロジェクトのforkを使用していましたが、なかなかに複雑で古いpackageを使用していたので、イチから作り直しました。 `three-vrm:v2.1`にして、`node:v21`, `yarn:v1.22`を使っています。 ## bloom ぼんやりと発光させるには、bloomを有効にしなければなりません。 ただし、threeに入っているexampleはメンテナンスされていません。別のものを使ったほうが良いでしょう。 ```sh $ yarn add postprocessing ``` ```js:src/index.ts //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によっては動かないことがあるらしいので、そのときは以下を設定してください。 ```js:src/index.ts import { WebGLRenderer } from "three"; const renderer = new WebGLRenderer({ powerPreference: "high-performance", antialias: false, stencil: false, depth: false }); ``` ## progress progress-barを出します。既に用意されているらしいので、それを使います。 ```js:src/index.ts // 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' }; ``` ```html:dist/index.html ``` ```css:dist/css/style.css 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; } ```