Three.jsでシーン全体をぼかす(ポストエフェクトでブラー) calmbooks Follow 2015-02-02 17:31:40 License: MIT License Fork2 Fav8 View5266 Play Stop Reload Fullscreen Smart Phone Fork tree Readme ES6 209 lines HTML 3 lines CSS 18 lines こないだお仕事で実装したやつをjsdoitに残す。 Three.jsでシーン全体をぼかす(ポストエフェクトでブラー) three.js r66 (function( win, doc, THREE ) { //----------------------- // Shader //----------------------- var BLUR_VERTEX_SHADER = ` varying vec2 vUV; void main() { vUV = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; var BLUR_FRAGMENT_SHADER = ` uniform sampler2D texture; uniform vec2 renderSize; uniform float blur; uniform int useBlur; varying vec2 vUV; vec4 getBlurColor( vec4 destColor ) { const int blurPixel = 10; const int blurW = blurPixel; const int blurH = blurPixel; float maxLevel = float((blurPixel - 1) / 2); float total = 0.0; for( int y = 0; y < blurH; ++y ) { for( int x = 0; x < blurW; ++x ) { if( x != 0 || y != 0 ) { int addX = x - (blurW - 1) / 2; int addY = y - (blurH - 1) / 2; float level = max(abs(float(addX)), abs(float(addY))) - 1.0; float b = blur * maxLevel - level; b = clamp(b, 0.0, 1.0); float surroundX= float(addX) * 3.0 / renderSize.x; float surroundY = float(addY) * 3.0 / renderSize.y; destColor += texture2D(texture, (vUV + vec2(surroundX, surroundY))) * b; total += b; } } } return destColor / (total + 1.0); } void main() { vec4 destColor = vec4(0,0,0,0); destColor += texture2D(texture, vUV); if( useBlur == 1 ) { destColor = getBlurColor(destColor); } gl_FragColor = destColor; } `; //----------------------- // BlurRenderer //----------------------- class BlurRenderer extends THREE.WebGLRenderer { constructor( canvas ) { super({ antialias : false, canvas : canvas }); this.setClearColor(0x222222, 1); } setup( width, height ) { this.stageWidth = width; this.stageHeight = height; this.renderTarget = new THREE.WebGLRenderTarget(this.stageWidth, this.stageHeight); this.setSize(this.stageWidth, this.stageHeight); this.screenScene = new THREE.Scene(); this.screenCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 10); this.screenCamera.position.set(0, 0, 0); this.screenCamera.lookAt( new THREE.Vector3(0, 0, -1) ); var geo = new THREE.PlaneGeometry(2, 2, 2, 2); var uniforms = { texture : { type : "t", value : this.renderTarget }, renderSize : { type : "v2", value : new THREE.Vector2(this.stageWidth, this.stageHeight) }, blur : { type : "f", value : 0 }, useBlur : { type : "i", value : 0 } }; var mat = new THREE.ShaderMaterial({ uniforms : uniforms, vertexShader : BLUR_VERTEX_SHADER, fragmentShader : BLUR_FRAGMENT_SHADER }); this.screenMesh = new THREE.Mesh(geo, mat); this.screenMesh.position.set(0, 0, -1); this.screenScene.add(this.screenCamera); this.screenScene.add(this.screenMesh); } setBlur( val ) { this.screenMesh.material.uniforms.blur.value = val; } setUseBlur( bool ) { this.screenMesh.material.uniforms.useBlur.value = bool ? 1 : 0; } update( scene, camera ) { this.render(scene, camera, this.renderTarget); this.render(this.screenScene, this.screenCamera); } }; //----------------------- // Main //----------------------- class Main { constructor() {} setup() { this.canvas = doc.getElementById("c"); this.renderer = new BlurRenderer(this.canvas); this.renderer.setup(465,465); this.renderer.setUseBlur(true); this.scene = new THREE.Scene(); this.setCamera(); this.setLight(); this.setBox(); this.setRangeEvent(); this.setUpdate(); } setCamera() { this.camera = new THREE.PerspectiveCamera( 80, 465/465, 0.1, 1000); this.camera.position.set(0,1,2); this.camera.lookAt(new THREE.Vector3(0,0,0)); } setLight() { this.light = new THREE.PointLight(); this.light.position.set(0,1,2); this.ambientLight = new THREE.AmbientLight(0x222222); this.scene.add(this.light, this.ambientLight); } setBox() { this.boxTexture = THREE.ImageUtils.loadTexture("http://jsrun.it/assets/c/y/E/s/cyEsA.png") this.boxGeometry = new THREE.BoxGeometry(1,1,1); this.boxMaterial = new THREE.MeshLambertMaterial({ map: this.boxTexture }); this.boxMesh = new THREE.Mesh(this.boxGeometry,this.boxMaterial); this.scene.add(this.boxMesh); } setUpdate() { this.rotate = 0; this.update(); } update() { this.rotate += this.d2r(1); this.boxMesh.rotation.set(this.rotate,this.rotate,0); this.renderer.update(this.scene, this.camera); requestAnimationFrame(this.update.bind(this)); } d2r( val ) { return val * (Math.PI / 180); } setRangeEvent() { var self = this; var range = doc.getElementById("blurRange"); range.addEventListener("input", function( e ) { var val = Number(e.target.value); self.renderer.setBlur(val/100); }); this.renderer.setBlur(Number(range.value)/100); } } //----------------------- // Initialize //----------------------- win.addEventListener("load", function() { var main = new Main(); main.setup(); }); })(window, document, THREE); <input type="range" id="blurRange" value="50" /> <canvas id="c"></canvas> Three.jsでシーン全体をぼかす(ポストエフェクトでブラー) * { margin: 0; padding: 0; } canvas { display: block; margin: 0 auto; } #blurRange { display: block; position: absolute; z-index: 5; top: 10px; left: 50%; margin-left: -200px; width: 400px; } こないだお仕事で実装したやつをjsdoitに残す。 (function( win, doc, THREE ) { //----------------------- // Shader //----------------------- var BLUR_VERTEX_SHADER = ` varying vec2 vUV; void main() { vUV = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; var BLUR_FRAGMENT_SHADER = ` uniform sampler2D texture; uniform vec2 renderSize; uniform float blur; uniform int useBlur; varying vec2 vUV; vec4 getBlurColor( vec4 destColor ) { const int blurPixel = 10; const int blurW = blurPixel; const int blurH = blurPixel; float maxLevel = float((blurPixel - 1) / 2); float total = 0.0; for( int y = 0; y < blurH; ++y ) { for( int x = 0; x < blurW; ++x ) { if( x != 0 || y != 0 ) { int addX = x - (blurW - 1) / 2; int addY = y - (blurH - 1) / 2; float level = max(abs(float(addX)), abs(float(addY))) - 1.0; float b = blur * maxLevel - level; b = clamp(b, 0.0, 1.0); float surroundX= float(addX) * 3.0 / renderSize.x; float surroundY = float(addY) * 3.0 / renderSize.y; destColor += texture2D(texture, (vUV + vec2(surroundX, surroundY))) * b; total += b; } } } return destColor / (total + 1.0); } void main() { vec4 destColor = vec4(0,0,0,0); destColor += texture2D(texture, vUV); if( useBlur == 1 ) { destColor = getBlurColor(destColor); } gl_FragColor = destColor; } `; //----------------------- // BlurRenderer //----------------------- class BlurRenderer extends THREE.WebGLRenderer { constructor( canvas ) { super({ antialias : false, canvas : canvas }); this.setClearColor(0x222222, 1); } setup( width, height ) { this.stageWidth = width; this.stageHeight = height; this.renderTarget = new THREE.WebGLRenderTarget(this.stageWidth, this.stageHeight); this.setSize(this.stageWidth, this.stageHeight); this.screenScene = new THREE.Scene(); this.screenCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 10); this.screenCamera.position.set(0, 0, 0); this.screenCamera.lookAt( new THREE.Vector3(0, 0, -1) ); var geo = new THREE.PlaneGeometry(2, 2, 2, 2); var uniforms = { texture : { type : "t", value : this.renderTarget }, renderSize : { type : "v2", value : new THREE.Vector2(this.stageWidth, this.stageHeight) }, blur : { type : "f", value : 0 }, useBlur : { type : "i", value : 0 } }; var mat = new THREE.ShaderMaterial({ uniforms : uniforms, vertexShader : BLUR_VERTEX_SHADER, fragmentShader : BLUR_FRAGMENT_SHADER }); this.screenMesh = new THREE.Mesh(geo, mat); this.screenMesh.position.set(0, 0, -1); this.screenScene.add(this.screenCamera); this.screenScene.add(this.screenMesh); } setBlur( val ) { this.screenMesh.material.uniforms.blur.value = val; } setUseBlur( bool ) { this.screenMesh.material.uniforms.useBlur.value = bool ? 1 : 0; } update( scene, camera ) { this.render(scene, camera, this.renderTarget); this.render(this.screenScene, this.screenCamera); } }; //----------------------- // Main //----------------------- class Main { constructor() {} setup() { this.canvas = doc.getElementById("c"); this.renderer = new BlurRenderer(this.canvas); this.renderer.setup(465,465); this.renderer.setUseBlur(true); this.scene = new THREE.Scene(); this.setCamera(); this.setLight(); this.setBox(); this.setRangeEvent(); this.setUpdate(); } setCamera() { this.camera = new THREE.PerspectiveCamera( 80, 465/465, 0.1, 1000); this.camera.position.set(0,1,2); this.camera.lookAt(new THREE.Vector3(0,0,0)); } setLight() { this.light = new THREE.PointLight(); this.light.position.set(0,1,2); this.ambientLight = new THREE.AmbientLight(0x222222); this.scene.add(this.light, this.ambientLight); } setBox() { this.boxTexture = THREE.ImageUtils.loadTexture("http://jsrun.it/assets/c/y/E/s/cyEsA.png") this.boxGeometry = new THREE.BoxGeometry(1,1,1); this.boxMaterial = new THREE.MeshLambertMaterial({ map: this.boxTexture }); this.boxMesh = new THREE.Mesh(this.boxGeometry,this.boxMaterial); this.scene.add(this.boxMesh); } setUpdate() { this.rotate = 0; this.update(); } update() { this.rotate += this.d2r(1); this.boxMesh.rotation.set(this.rotate,this.rotate,0); this.renderer.update(this.scene, this.camera); requestAnimationFrame(this.update.bind(this)); } d2r( val ) { return val * (Math.PI / 180); } setRangeEvent() { var self = this; var range = doc.getElementById("blurRange"); range.addEventListener("input", function( e ) { var val = Number(e.target.value); self.renderer.setBlur(val/100); }); this.renderer.setBlur(Number(range.value)/100); } } //----------------------- // Initialize //----------------------- win.addEventListener("load", function() { var main = new Main(); main.setup(); }); })(window, document, THREE); <input type="range" id="blurRange" value="50" /> <canvas id="c"></canvas> * { margin: 0; padding: 0; } canvas { display: block; margin: 0 auto; } #blurRange { display: block; position: absolute; z-index: 5; top: 10px; left: 50%; margin-left: -200px; width: 400px; } use an iframe compat browser, deer Play on jsdo.it games Author Share ブログに埋め込む QR Tag Download Complete! Description What kind of game? こないだお仕事で実装したやつをjsdoitに残す。 Control Device Smartphone Controllerjsdo.it WebSocket Controller» Mouse Keyboard Touch Device Fullscreen Activated Inactivated jsdo.it games から削除する Submit Author calmbooks URLhttp://calmbooks.tumblr.com Tweet Default Panel Auto play Screenshot Readme JavaScript HTML CSS Size Width: px Height: px code <script type="text/javascript" src="http://jsdo.it/blogparts/m2J1/js"></script> library&test Discussion Questions on this code? Tags library&test Favorite by tsubao ichiyaman cx20 siouxcitizen djankey moonblogger kimmy Shingo.Tajim Forked sort by latest page views favorite forked forked: Three.jsでシーン全体をぼかす(ポスト ohisama1 00 307 175/4/18 library&test forked: Three.jsでシーン全体をぼかす(ポスト Biske 00 881 211/3/18 library&test