123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- /**
- * @author mikael emtinger / http://gomo.se/
- * @author alteredq / http://alteredqualia.com/
- */
- THREE.LensFlarePlugin = function ( ) {
- var _gl, _renderer, _lensFlare = {};
- this.init = function ( renderer ) {
- _gl = renderer.context;
- _renderer = renderer;
- _lensFlare.vertices = new Float32Array( 8 + 8 );
- _lensFlare.faces = new Uint16Array( 6 );
- var i = 0;
- _lensFlare.vertices[ i++ ] = -1; _lensFlare.vertices[ i++ ] = -1; // vertex
- _lensFlare.vertices[ i++ ] = 0; _lensFlare.vertices[ i++ ] = 0; // uv... etc.
- _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = -1;
- _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 0;
- _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 1;
- _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 1;
- _lensFlare.vertices[ i++ ] = -1; _lensFlare.vertices[ i++ ] = 1;
- _lensFlare.vertices[ i++ ] = 0; _lensFlare.vertices[ i++ ] = 1;
- i = 0;
- _lensFlare.faces[ i++ ] = 0; _lensFlare.faces[ i++ ] = 1; _lensFlare.faces[ i++ ] = 2;
- _lensFlare.faces[ i++ ] = 0; _lensFlare.faces[ i++ ] = 2; _lensFlare.faces[ i++ ] = 3;
- // buffers
- _lensFlare.vertexBuffer = _gl.createBuffer();
- _lensFlare.elementBuffer = _gl.createBuffer();
- _gl.bindBuffer( _gl.ARRAY_BUFFER, _lensFlare.vertexBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, _lensFlare.vertices, _gl.STATIC_DRAW );
- _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.elementBuffer );
- _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.faces, _gl.STATIC_DRAW );
- // textures
- _lensFlare.tempTexture = _gl.createTexture();
- _lensFlare.occlusionTexture = _gl.createTexture();
- _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
- _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGB, 16, 16, 0, _gl.RGB, _gl.UNSIGNED_BYTE, null );
- _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
- _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
- _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST );
- _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST );
- _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture );
- _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, 16, 16, 0, _gl.RGBA, _gl.UNSIGNED_BYTE, null );
- _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
- _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
- _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST );
- _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST );
- if ( _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ) <= 0 ) {
- _lensFlare.hasVertexTexture = false;
- _lensFlare.program = createProgram( THREE.ShaderFlares[ "lensFlare" ] );
- } else {
- _lensFlare.hasVertexTexture = true;
- _lensFlare.program = createProgram( THREE.ShaderFlares[ "lensFlareVertexTexture" ] );
- }
- _lensFlare.attributes = {};
- _lensFlare.uniforms = {};
- _lensFlare.attributes.vertex = _gl.getAttribLocation ( _lensFlare.program, "position" );
- _lensFlare.attributes.uv = _gl.getAttribLocation ( _lensFlare.program, "uv" );
- _lensFlare.uniforms.renderType = _gl.getUniformLocation( _lensFlare.program, "renderType" );
- _lensFlare.uniforms.map = _gl.getUniformLocation( _lensFlare.program, "map" );
- _lensFlare.uniforms.occlusionMap = _gl.getUniformLocation( _lensFlare.program, "occlusionMap" );
- _lensFlare.uniforms.opacity = _gl.getUniformLocation( _lensFlare.program, "opacity" );
- _lensFlare.uniforms.color = _gl.getUniformLocation( _lensFlare.program, "color" );
- _lensFlare.uniforms.scale = _gl.getUniformLocation( _lensFlare.program, "scale" );
- _lensFlare.uniforms.rotation = _gl.getUniformLocation( _lensFlare.program, "rotation" );
- _lensFlare.uniforms.screenPosition = _gl.getUniformLocation( _lensFlare.program, "screenPosition" );
- _lensFlare.attributesEnabled = false;
- };
- /*
- * Render lens flares
- * Method: renders 16x16 0xff00ff-colored points scattered over the light source area,
- * reads these back and calculates occlusion.
- * Then _lensFlare.update_lensFlares() is called to re-position and
- * update transparency of flares. Then they are rendered.
- *
- */
- this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
- var flares = scene.__webglFlares,
- nFlares = flares.length;
- if ( ! nFlares ) return;
- var tempPosition = new THREE.Vector3();
- var invAspect = viewportHeight / viewportWidth,
- halfViewportWidth = viewportWidth * 0.5,
- halfViewportHeight = viewportHeight * 0.5;
- var size = 16 / viewportHeight,
- scale = new THREE.Vector2( size * invAspect, size );
- var screenPosition = new THREE.Vector3( 1, 1, 0 ),
- screenPositionPixels = new THREE.Vector2( 1, 1 );
- var uniforms = _lensFlare.uniforms,
- attributes = _lensFlare.attributes;
- // set _lensFlare program and reset blending
- _gl.useProgram( _lensFlare.program );
- if ( ! _lensFlare.attributesEnabled ) {
- _gl.enableVertexAttribArray( _lensFlare.attributes.vertex );
- _gl.enableVertexAttribArray( _lensFlare.attributes.uv );
- _lensFlare.attributesEnabled = true;
- }
- // loop through all lens flares to update their occlusion and positions
- // setup gl and common used attribs/unforms
- _gl.uniform1i( uniforms.occlusionMap, 0 );
- _gl.uniform1i( uniforms.map, 1 );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, _lensFlare.vertexBuffer );
- _gl.vertexAttribPointer( attributes.vertex, 2, _gl.FLOAT, false, 2 * 8, 0 );
- _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 );
- _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.elementBuffer );
- _gl.disable( _gl.CULL_FACE );
- _gl.depthMask( false );
- var i, j, jl, flare, sprite;
- for ( i = 0; i < nFlares; i ++ ) {
- size = 16 / viewportHeight;
- scale.set( size * invAspect, size );
- // calc object screen position
- flare = flares[ i ];
- tempPosition.set( flare.matrixWorld.elements[12], flare.matrixWorld.elements[13], flare.matrixWorld.elements[14] );
- camera.matrixWorldInverse.multiplyVector3( tempPosition );
- camera.projectionMatrix.multiplyVector3( tempPosition );
- // setup arrays for gl programs
- screenPosition.copy( tempPosition )
- screenPositionPixels.x = screenPosition.x * halfViewportWidth + halfViewportWidth;
- screenPositionPixels.y = screenPosition.y * halfViewportHeight + halfViewportHeight;
- // screen cull
- if ( _lensFlare.hasVertexTexture || (
- screenPositionPixels.x > 0 &&
- screenPositionPixels.x < viewportWidth &&
- screenPositionPixels.y > 0 &&
- screenPositionPixels.y < viewportHeight ) ) {
- // save current RGB to temp texture
- _gl.activeTexture( _gl.TEXTURE1 );
- _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
- _gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGB, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
- // render pink quad
- _gl.uniform1i( uniforms.renderType, 0 );
- _gl.uniform2f( uniforms.scale, scale.x, scale.y );
- _gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
- _gl.disable( _gl.BLEND );
- _gl.enable( _gl.DEPTH_TEST );
- _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
- // copy result to occlusionMap
- _gl.activeTexture( _gl.TEXTURE0 );
- _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture );
- _gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
- // restore graphics
- _gl.uniform1i( uniforms.renderType, 1 );
- _gl.disable( _gl.DEPTH_TEST );
- _gl.activeTexture( _gl.TEXTURE1 );
- _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
- _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
- // update object positions
- flare.positionScreen.copy( screenPosition )
- if ( flare.customUpdateCallback ) {
- flare.customUpdateCallback( flare );
- } else {
- flare.updateLensFlares();
- }
- // render flares
- _gl.uniform1i( uniforms.renderType, 2 );
- _gl.enable( _gl.BLEND );
- for ( j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) {
- sprite = flare.lensFlares[ j ];
- if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) {
- screenPosition.x = sprite.x;
- screenPosition.y = sprite.y;
- screenPosition.z = sprite.z;
- size = sprite.size * sprite.scale / viewportHeight;
- scale.x = size * invAspect;
- scale.y = size;
- _gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
- _gl.uniform2f( uniforms.scale, scale.x, scale.y );
- _gl.uniform1f( uniforms.rotation, sprite.rotation );
- _gl.uniform1f( uniforms.opacity, sprite.opacity );
- _gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
- _renderer.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
- _renderer.setTexture( sprite.texture, 1 );
- _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
- }
- }
- }
- }
- // restore gl
- _gl.enable( _gl.CULL_FACE );
- _gl.enable( _gl.DEPTH_TEST );
- _gl.depthMask( true );
- };
- function createProgram ( shader ) {
- var program = _gl.createProgram();
- var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
- var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
- _gl.shaderSource( fragmentShader, shader.fragmentShader );
- _gl.shaderSource( vertexShader, shader.vertexShader );
- _gl.compileShader( fragmentShader );
- _gl.compileShader( vertexShader );
- _gl.attachShader( program, fragmentShader );
- _gl.attachShader( program, vertexShader );
- _gl.linkProgram( program );
- return program;
- };
- };
|