WEB/WebGL

[WebGL] Three.js - Bloom Shader

AlrepondTech 2017. 11. 1. 19:33
반응형

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

출처: http://cinema4dr12.tistory.com/794

[WebGL] Bloom Shader

이번 예제는 Bloom Shader 구현에 관한 것이다.또한 Shader Code는 Alfred Qualia에게 저작권이 있음을 알려둔다:Visit Alfred Qualia's Web Page.
[Download Project]

14-04-shader-bloom.zip
다운로드

 

FULL SCREEN

 

 

[Operations]

Mouse Left Button Click & Drag: Camera Rotating

Mouse Wheel: Camera Zoom In & Out

Mouse Right Button Click & Drag: Camera Panning


[main.js]

// standard global variables var container, scene, camera, renderer, controls, stats; var keyboard = new THREEx.KeyboardState(); var clock = new THREE.Clock(); // custom global variables var cube, gui; var shaderActive = "none"; // variables for shader var composer, finalPass; init(); animate(); // FUNCTIONS function init() { // SCENE scene = new THREE.Scene(); // CAMERA var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight; var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000; camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR); scene.add(camera); camera.position.set(0,150,400); camera.lookAt(scene.position); // RENDERER if ( Detector.webgl ) renderer = new THREE.WebGLRenderer( {antialias:true} ); else renderer = new THREE.CanvasRenderer(); renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT); container = document.getElementById( 'ThreeJS' ); container.appendChild( renderer.domElement ); renderer.shadowMapEnabled = true; renderer.shadowMapSoft = true; // EVENTS THREEx.WindowResize(renderer, camera); THREEx.FullScreen.bindKey({ charCode : 'f'.charCodeAt(0) }); // CONTROLS controls = new THREE.OrbitControls( camera, renderer.domElement ); // STATS stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.bottom = '0px'; stats.domElement.style.zIndex = 100; container.appendChild( stats.domElement ); // LIGHT var light = new THREE.PointLight(0xffffff); light.position.set(0,250,0); scene.add(light); var dirLight = new THREE.DirectionalLight(0xffc051); dirLight.position.set(-250,500,-150); dirLight.shadowDarkness = 0.95; dirLight.intensity = 2; dirLight.castShadow = true; // enable shadow casting ability for the light scene.add(dirLight); // FLOOR var floorTexture = new THREE.ImageUtils.loadTexture( 'img/Wood_floor.jpg' ); floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping; floorTexture.repeat.set( 1, 1 ); var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } ); var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10); var floor = new THREE.Mesh(floorGeometry, floorMaterial); floor.position.y = -0.5; floor.rotation.x = Math.PI / 2; floor.receiveShadow = true; scene.add(floor); // SKYBOX/FOG var materialArray = []; materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'img/px.jpg' ) })); materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'img/nx.jpg' ) })); materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'img/py.jpg' ) })); materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'img/ny.jpg' ) })); materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'img/pz.jpg' ) })); materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'img/nz.jpg' ) })); for (var i = 0; i < 6; i++) materialArray[i].side = THREE.BackSide; var skyboxMaterial = new THREE.MeshFaceMaterial( materialArray ); var skyboxGeom = new THREE.CubeGeometry( 5000, 5000, 5000, 1, 1, 1 ); var skybox = new THREE.Mesh( skyboxGeom, skyboxMaterial ); scene.add( skybox ); //////////// // CUSTOM // //////////// var cubeGeometry = new THREE.CubeGeometry( 50, 50, 50 ); var cubeTexture = new THREE.ImageUtils.loadTexture( 'img/0.png' ); var cubeMaterial = new THREE.MeshBasicMaterial( { map: cubeTexture } ); var cube = new THREE.Mesh( cubeGeometry, cubeMaterial ); cube.position.set(-50,25,0); cube.castShadow = true; scene.add(cube); var cubeGeometry1 = new THREE.CubeGeometry( 50, 50, 50 ); var cubeTexture1 = new THREE.ImageUtils.loadTexture( 'img/4.png' ); var cubeMaterial1 = new THREE.MeshBasicMaterial( { map: cubeTexture1 } ); var cube1 = new THREE.Mesh( cubeGeometry1, cubeMaterial1 ); cube1.position.set(-150,25,0); cube1.castShadow = true; scene.add(cube1); var cubeGeometry2 = new THREE.CubeGeometry( 50, 50, 50 ); var cubeTexture2 = new THREE.ImageUtils.loadTexture( 'img/9.png' ); var cubeMaterial2 = new THREE.MeshBasicMaterial( { map: cubeTexture2 } ); var cube2 = new THREE.Mesh( cubeGeometry2, cubeMaterial2 ); cube2.position.set(150,25,0); cube2.castShadow = true; scene.add(cube2); var sphereGeometry = new THREE.SphereGeometry( 50, 32, 16 ); var sphereTexture = new THREE.ImageUtils.loadTexture( 'img/8.png' ); var sphereMaterial = new THREE.MeshBasicMaterial( { map: sphereTexture } ); var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); sphere.position.set(50, 50, -50); sphere.castShadow = true; scene.add(sphere); ///////////////////// // POST-PROCESSING // ///////////////////// // GUI setup gui = new dat.GUI(); parameters = { sepiaAmount: 0.9, vignetteOffset: 1.5, vignetteDarkness: 1.6, dotscreenAngle: 0.5, dotscreenScale: 0.8, bloomStrength: 1.3, bloomFactor: 1.0, horizBlur: 1.25, vertiBlur: 1.25, useShaderNone: function() { setupShaderNone(); }, useShaderBloom: function() { setupShaderBloom(); } }; gui.add( parameters, 'useShaderNone' ).name("Display Original Scene"); var folderBloom = gui.addFolder('Bloom'); var bloomStrengthGUI = folderBloom.add( parameters, 'bloomStrength' ).min(0).max(3).step(0.01).name("Strength").listen(); bloomStrengthGUI.onChange( function(value) { setupShaderBloom(); } ); var bloomFactorGUI = folderBloom.add( parameters, 'bloomFactor' ).min(0.1).max(2.0).step(0.01).name("Factor").listen(); bloomFactorGUI.onChange( function(value) { setupShaderBloom(); } ); folderBloom.add( parameters, 'useShaderBloom' ).name("Use Bloom Shader"); folderBloom.open(); setupShaderNone(); } function setupShaderNone() { shaderActive = "none"; } function setupShaderBloom() { composer = new THREE.EffectComposer( renderer ); composer.addPass( new THREE.RenderPass( scene, camera ) ); // https://github.com/mrdoob/three.js/issues/1065 // this method changes default kernel/sigma values by the same factor var effectBloom = new THREE.BloomPass( parameters.bloomStrength, parameters.bloomFactor * 25, parameters.bloomFactor * 4.0 ); composer.addPass( effectBloom ); var effectCopy = new THREE.ShaderPass( THREE.CopyShader ); effectCopy.renderToScreen = true; composer.addPass( effectCopy ); shaderActive = "bloom"; } function animate() { requestAnimationFrame( animate ); render(); update(); } function update() { if ( keyboard.pressed("z") ) { // do something } controls.update(); stats.update(); } function render() { if ( shaderActive == "none" ) renderer.render( scene, camera ); else composer.render(); }
[BloomPass.js]/** * @author alteredq / http://alteredqualia.com/ */ THREE.BloomPass = function ( strength, kernelSize, sigma, resolution ) { strength = ( strength !== undefined ) ? strength : 1; kernelSize = ( kernelSize !== undefined ) ? kernelSize : 25; sigma = ( sigma !== undefined ) ? sigma : 4.0; resolution = ( resolution !== undefined ) ? resolution : 256; // render targets var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat }; this.renderTargetX = new THREE.WebGLRenderTarget( resolution, resolution, pars ); this.renderTargetY = new THREE.WebGLRenderTarget( resolution, resolution, pars ); // copy material if ( THREE.CopyShader === undefined ) console.error( "THREE.BloomPass relies on THREE.CopyShader" ); var copyShader = THREE.CopyShader; this.copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms ); this.copyUniforms[ "opacity" ].value = strength; this.materialCopy = new THREE.ShaderMaterial( { uniforms: this.copyUniforms, vertexShader: copyShader.vertexShader, fragmentShader: copyShader.fragmentShader, blending: THREE.AdditiveBlending, transparent: true } ); // convolution material if ( THREE.ConvolutionShader === undefined ) console.error( "THREE.BloomPass relies on THREE.ConvolutionShader" ); var convolutionShader = THREE.ConvolutionShader; this.convolutionUniforms = THREE.UniformsUtils.clone( convolutionShader.uniforms ); this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurx; this.convolutionUniforms[ "cKernel" ].value = THREE.ConvolutionShader.buildKernel( sigma ); this.materialConvolution = new THREE.ShaderMaterial( { uniforms: this.convolutionUniforms, vertexShader: convolutionShader.vertexShader, fragmentShader: convolutionShader.fragmentShader, defines: { "KERNEL_SIZE_FLOAT": kernelSize.toFixed( 1 ), "KERNEL_SIZE_INT": kernelSize.toFixed( 0 ) } } ); this.enabled = true; this.needsSwap = false; this.clear = false; }; THREE.BloomPass.prototype = { render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) { if ( maskActive ) renderer.context.disable( renderer.context.STENCIL_TEST ); // Render quad with blured scene into texture (convolution pass 1) THREE.EffectComposer.quad.material = this.materialConvolution; this.convolutionUniforms[ "tDiffuse" ].value = readBuffer; this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurX; renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, this.renderTargetX, true ); // Render quad with blured scene into texture (convolution pass 2) this.convolutionUniforms[ "tDiffuse" ].value = this.renderTargetX; this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurY; renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, this.renderTargetY, true ); // Render original scene with superimposed blur to texture THREE.EffectComposer.quad.material = this.materialCopy; this.copyUniforms[ "tDiffuse" ].value = this.renderTargetY; if ( maskActive ) renderer.context.enable( renderer.context.STENCIL_TEST ); renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, readBuffer, this.clear ); } }; THREE.BloomPass.blurX = new THREE.Vector2( 0.001953125, 0.0 ); THREE.BloomPass.blurY = new THREE.Vector2( 0.0, 0.001953125 );

 

=================================

=================================

=================================

 

 

 

반응형

'WEB > WebGL' 카테고리의 다른 글

[WebGL] Three.js - Path Tracing  (0) 2017.11.01
[WebGL] Three.js - Blur Shader  (0) 2017.11.01
[WebGL] Three.js - Dot-Screen Shader  (0) 2017.11.01
[WebGL] Three.js - Vignette Shader  (0) 2017.11.01
[WebGL] Three.js - Embedded HTML  (0) 2017.11.01