EffectComposerでポストプロセッシング
「Three.jsでポストプロセッシング」でポストプロセッシングを試しましたが、Three.jsのEffectComposerを試してみました。※Three.jsはr128を使用しています。
EffectComposerでポストプロセッシング
EffectComposerを使用すると、ポストプロセッシングを簡単に実装できます。また、Three.jsにはカラーハーフトーンやグリッチ、ゴッドレイなどさまざなエフェクトが用意されています。
● ライブラリの読み込み
まず、必要なライブラリを読み込みます。EffectComposer.jsとRenderPass.jsの他に、それぞれから読みこまれている「examples > jsm > postprocessing」の中のShaderPass.js、MaskPass.js、Pass.js、「examples > jsm > shaders」の中のCopyShader.jsが必要になります。また、各ファイルの中のパスを必要に応じて修正します。
import { EffectComposer } from './lib/three_jsm/postprocessing/EffectComposer.js'; import { RenderPass } from './lib/three_jsm/postprocessing/RenderPass.js';
● EffectComposerでポストプロセッシング
「examples > jsm > postprocessing」の中に各エフェクトのファイルがありまが、今回はカラーハーフトーンとグリッチをかけます。カラーハーフトーンとグリッチは、それぞれ「examples > jsm > shaders」の中のHalftoneShader.jsとDigitalGlitch.jsも必要です。エフェクトは複数組み合わせることもできます。
//エフェクトファイルを読み込み import { HalftonePass } from './lib/three_jsm/postprocessing/HalftonePass.js'; import { GlitchPass } from './lib/three_jsm/postprocessing/GlitchPass.js'; //コンポーザーを生成 const composer = new EffectComposer(renderer); //レンダーパスを生成 const renderPass = new RenderPass(scene,camera); //カラーハーフトーンエフェクト const halftonePass = new HalftonePass(); //グリッチエフェクト const glitchPass = new GlitchPass(); //コンポーザーに追加 composer.addPass(renderPass); composer.addPass(halftonePass); composer.addPass(glitchPass); function rendering(){ requestAnimationFrame(rendering); //コンポーザーでレンダリング composer.render(); }
必要なファイルを読み込んだら、コンポーザーを生成し、コンポーザーを使用してレンダリングします。後は、かけたいエフェクトをコンポーザーに追加するだけです。
● オリジナルエフェクトの制作
EffectComposerはオリジナルエフェクトを制作することもできます。詳細は、「How to use post-processing - three.js docs」の最後に書いてあります。
● script.js
必要なライブラリを読み込みます。
<script src="js/preloadjs.min.js"></script> <script src="js/TweenMax.min.js"></script> <script src="js/script.js" type="module"></script>
完成したscript.jsになります。
//=============================================================== // Import Library //=============================================================== import * as THREE from './lib/three_jsm/three.module.js'; import { EffectComposer } from './lib/three_jsm/postprocessing/EffectComposer.js'; import { RenderPass } from './lib/three_jsm/postprocessing/RenderPass.js'; import { HalftonePass } from './lib/three_jsm/postprocessing/HalftonePass.js'; import { GlitchPass } from './lib/three_jsm/postprocessing/GlitchPass.js'; import { OrbitControls } from './lib/three_jsm/OrbitControls.js'; import { scene, camera, container, renderer } from './lib/basescene.js'; //=============================================================== // Init //=============================================================== window.addEventListener('load',function(){ init(); }); let orbitControls; let composer; let sphereContainer; let directionalLight; let time = 0; function init(){ setLoading(); } function setLoading(){ TweenMax.to('.loader',0.1,{opacity:1}); TweenMax.to('#loader_wrapper',1,{ opacity:0, delay:1, onComplete: function(){ document.getElementById('loader_wrapper').style.display = 'none'; TweenMax.to('.loader',0,{opacity:0}); } }); threeWorld(); setLight(); setControll(); rendering(); } //=============================================================== // Create World //=============================================================== function threeWorld(){ renderer.outputEncoding = THREE.sRGBEncoding; sphereContainer = new THREE.Object3D(); scene.add(sphereContainer); for(let i = 0; i < 150; i++){ const h = Math.round((i / 150) * 360); const s = 30; const l = 60; console.log(l); const color = new THREE.Color(`hsl(${h},${s}%,${l}%)`); const geometry = new THREE.SphereGeometry(2,6,6); const material = new THREE.MeshPhysicalMaterial({ color:color, flatShading:true }); const sphere = new THREE.Mesh(geometry,material); const radian = (Math.random() * 360) * Math.PI / 180; const radian2 = (Math.random() * 360) * Math.PI / 180; const x = Math.cos(radian) * Math.cos(radian2) * 15; const y = Math.sin(radian) * 15; const z = Math.cos(radian) * Math.sin(radian2) * 15; const scale = Math.random() * 0.7 + 0.2; sphere.position.set(x,y,z); sphere.scale.set(scale,scale,scale); sphere.rotation.set( Math.random() * 360 * Math.PI / 180, Math.random() * 360 * Math.PI / 180, Math.random() * 360 * Math.PI / 180 ) sphereContainer.add(sphere) } composer = new EffectComposer(renderer); const renderPass = new RenderPass(scene,camera); const halftonePass = new HalftonePass(); const glitchPass = new GlitchPass(); composer.addPass(renderPass); composer.addPass(halftonePass); composer.addPass(glitchPass); } function setLight(){ const ambientlight = new THREE.AmbientLight(0xFFFFFF,0.5); scene.add(ambientlight); directionalLight = new THREE.DirectionalLight(0XFFFFFF,0.8); scene.add(directionalLight); } function setControll(){ document.addEventListener('touchmove',function(e){e.preventDefault();},{passive:false}); orbitControls = new OrbitControls(camera,renderer.domElement); orbitControls.enableDamping = true; orbitControls.dampingFactor = 0.5; } function rendering(){ requestAnimationFrame(rendering); if(orbitControls){ orbitControls.update(); } time++; sphereContainer.rotation.x = time * 0.1 * Math.PI / 180; sphereContainer.rotation.y = time * 0.1 * Math.PI / 180; const radian = time * 0.2 * Math.PI / 180; const radian2 = time * 0.2 * Math.PI / 180; directionalLight.position.x = Math.cos(radian) * Math.cos(radian2) * 10; directionalLight.position.y = Math.sin(radian) * 10; directionalLight.position.z = Math.cos(radian) * Math.sin(radian2) * 10; composer.render(); }
● basescene.js
sceneやcameraなど基本的な設定を管理するbasescene.jsです。
//=============================================================== // Import Library //=============================================================== import * as THREE from './three_jsm/three.module.js'; //=============================================================== // Base scene //=============================================================== let scene,camera,container,renderer; init(); function init(){ scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(50,window.innerWidth/window.innerHeight,1,100); camera.position.set(0,20,20); scene.add(camera); renderer = new THREE.WebGLRenderer({antialias:true}); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth,window.innerHeight); renderer.setClearColor(new THREE.Color(0x000000)); container = document.querySelector('#canvas_vr'); container.appendChild(renderer.domElement); window.addEventListener('resize',function(){ camera.aspect = window.innerWidth/window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth,window.innerHeight); },false); } export { scene, camera, container, renderer }
完成したデモになります。Three.jsのEffectComposerでポストプロセッシングを試してみました。
※グリッチエフェクトをかけているため、画面が激しく点滅します。