Twitter
2021年05月15日 - Three.js・WebVR

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);

	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でポストプロセッシングを試してみました。
※グリッチエフェクトをかけているため、画面が激しく点滅します。

  • このエントリーをはてなブックマークに追加

関連記事

前の記事へ

Three.jsでポストプロセッシング

次の記事へ

平面から球体へモーフィングする頂点アニメーション