LensFlarePlugin.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /**
  2. * @author mikael emtinger / http://gomo.se/
  3. * @author alteredq / http://alteredqualia.com/
  4. */
  5. THREE.LensFlarePlugin = function ( ) {
  6. var _gl, _renderer, _lensFlare = {};
  7. this.init = function ( renderer ) {
  8. _gl = renderer.context;
  9. _renderer = renderer;
  10. _lensFlare.vertices = new Float32Array( 8 + 8 );
  11. _lensFlare.faces = new Uint16Array( 6 );
  12. var i = 0;
  13. _lensFlare.vertices[ i++ ] = -1; _lensFlare.vertices[ i++ ] = -1; // vertex
  14. _lensFlare.vertices[ i++ ] = 0; _lensFlare.vertices[ i++ ] = 0; // uv... etc.
  15. _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = -1;
  16. _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 0;
  17. _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 1;
  18. _lensFlare.vertices[ i++ ] = 1; _lensFlare.vertices[ i++ ] = 1;
  19. _lensFlare.vertices[ i++ ] = -1; _lensFlare.vertices[ i++ ] = 1;
  20. _lensFlare.vertices[ i++ ] = 0; _lensFlare.vertices[ i++ ] = 1;
  21. i = 0;
  22. _lensFlare.faces[ i++ ] = 0; _lensFlare.faces[ i++ ] = 1; _lensFlare.faces[ i++ ] = 2;
  23. _lensFlare.faces[ i++ ] = 0; _lensFlare.faces[ i++ ] = 2; _lensFlare.faces[ i++ ] = 3;
  24. // buffers
  25. _lensFlare.vertexBuffer = _gl.createBuffer();
  26. _lensFlare.elementBuffer = _gl.createBuffer();
  27. _gl.bindBuffer( _gl.ARRAY_BUFFER, _lensFlare.vertexBuffer );
  28. _gl.bufferData( _gl.ARRAY_BUFFER, _lensFlare.vertices, _gl.STATIC_DRAW );
  29. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.elementBuffer );
  30. _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.faces, _gl.STATIC_DRAW );
  31. // textures
  32. _lensFlare.tempTexture = _gl.createTexture();
  33. _lensFlare.occlusionTexture = _gl.createTexture();
  34. _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
  35. _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGB, 16, 16, 0, _gl.RGB, _gl.UNSIGNED_BYTE, null );
  36. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
  37. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
  38. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST );
  39. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST );
  40. _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture );
  41. _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, 16, 16, 0, _gl.RGBA, _gl.UNSIGNED_BYTE, null );
  42. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
  43. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
  44. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST );
  45. _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST );
  46. if ( _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ) <= 0 ) {
  47. _lensFlare.hasVertexTexture = false;
  48. _lensFlare.program = createProgram( THREE.ShaderFlares[ "lensFlare" ] );
  49. } else {
  50. _lensFlare.hasVertexTexture = true;
  51. _lensFlare.program = createProgram( THREE.ShaderFlares[ "lensFlareVertexTexture" ] );
  52. }
  53. _lensFlare.attributes = {};
  54. _lensFlare.uniforms = {};
  55. _lensFlare.attributes.vertex = _gl.getAttribLocation ( _lensFlare.program, "position" );
  56. _lensFlare.attributes.uv = _gl.getAttribLocation ( _lensFlare.program, "uv" );
  57. _lensFlare.uniforms.renderType = _gl.getUniformLocation( _lensFlare.program, "renderType" );
  58. _lensFlare.uniforms.map = _gl.getUniformLocation( _lensFlare.program, "map" );
  59. _lensFlare.uniforms.occlusionMap = _gl.getUniformLocation( _lensFlare.program, "occlusionMap" );
  60. _lensFlare.uniforms.opacity = _gl.getUniformLocation( _lensFlare.program, "opacity" );
  61. _lensFlare.uniforms.color = _gl.getUniformLocation( _lensFlare.program, "color" );
  62. _lensFlare.uniforms.scale = _gl.getUniformLocation( _lensFlare.program, "scale" );
  63. _lensFlare.uniforms.rotation = _gl.getUniformLocation( _lensFlare.program, "rotation" );
  64. _lensFlare.uniforms.screenPosition = _gl.getUniformLocation( _lensFlare.program, "screenPosition" );
  65. _lensFlare.attributesEnabled = false;
  66. };
  67. /*
  68. * Render lens flares
  69. * Method: renders 16x16 0xff00ff-colored points scattered over the light source area,
  70. * reads these back and calculates occlusion.
  71. * Then _lensFlare.update_lensFlares() is called to re-position and
  72. * update transparency of flares. Then they are rendered.
  73. *
  74. */
  75. this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
  76. var flares = scene.__webglFlares,
  77. nFlares = flares.length;
  78. if ( ! nFlares ) return;
  79. var tempPosition = new THREE.Vector3();
  80. var invAspect = viewportHeight / viewportWidth,
  81. halfViewportWidth = viewportWidth * 0.5,
  82. halfViewportHeight = viewportHeight * 0.5;
  83. var size = 16 / viewportHeight,
  84. scale = new THREE.Vector2( size * invAspect, size );
  85. var screenPosition = new THREE.Vector3( 1, 1, 0 ),
  86. screenPositionPixels = new THREE.Vector2( 1, 1 );
  87. var uniforms = _lensFlare.uniforms,
  88. attributes = _lensFlare.attributes;
  89. // set _lensFlare program and reset blending
  90. _gl.useProgram( _lensFlare.program );
  91. if ( ! _lensFlare.attributesEnabled ) {
  92. _gl.enableVertexAttribArray( _lensFlare.attributes.vertex );
  93. _gl.enableVertexAttribArray( _lensFlare.attributes.uv );
  94. _lensFlare.attributesEnabled = true;
  95. }
  96. // loop through all lens flares to update their occlusion and positions
  97. // setup gl and common used attribs/unforms
  98. _gl.uniform1i( uniforms.occlusionMap, 0 );
  99. _gl.uniform1i( uniforms.map, 1 );
  100. _gl.bindBuffer( _gl.ARRAY_BUFFER, _lensFlare.vertexBuffer );
  101. _gl.vertexAttribPointer( attributes.vertex, 2, _gl.FLOAT, false, 2 * 8, 0 );
  102. _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 );
  103. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.elementBuffer );
  104. _gl.disable( _gl.CULL_FACE );
  105. _gl.depthMask( false );
  106. var i, j, jl, flare, sprite;
  107. for ( i = 0; i < nFlares; i ++ ) {
  108. size = 16 / viewportHeight;
  109. scale.set( size * invAspect, size );
  110. // calc object screen position
  111. flare = flares[ i ];
  112. tempPosition.set( flare.matrixWorld.elements[12], flare.matrixWorld.elements[13], flare.matrixWorld.elements[14] );
  113. camera.matrixWorldInverse.multiplyVector3( tempPosition );
  114. camera.projectionMatrix.multiplyVector3( tempPosition );
  115. // setup arrays for gl programs
  116. screenPosition.copy( tempPosition )
  117. screenPositionPixels.x = screenPosition.x * halfViewportWidth + halfViewportWidth;
  118. screenPositionPixels.y = screenPosition.y * halfViewportHeight + halfViewportHeight;
  119. // screen cull
  120. if ( _lensFlare.hasVertexTexture || (
  121. screenPositionPixels.x > 0 &&
  122. screenPositionPixels.x < viewportWidth &&
  123. screenPositionPixels.y > 0 &&
  124. screenPositionPixels.y < viewportHeight ) ) {
  125. // save current RGB to temp texture
  126. _gl.activeTexture( _gl.TEXTURE1 );
  127. _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
  128. _gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGB, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
  129. // render pink quad
  130. _gl.uniform1i( uniforms.renderType, 0 );
  131. _gl.uniform2f( uniforms.scale, scale.x, scale.y );
  132. _gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
  133. _gl.disable( _gl.BLEND );
  134. _gl.enable( _gl.DEPTH_TEST );
  135. _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
  136. // copy result to occlusionMap
  137. _gl.activeTexture( _gl.TEXTURE0 );
  138. _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture );
  139. _gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
  140. // restore graphics
  141. _gl.uniform1i( uniforms.renderType, 1 );
  142. _gl.disable( _gl.DEPTH_TEST );
  143. _gl.activeTexture( _gl.TEXTURE1 );
  144. _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
  145. _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
  146. // update object positions
  147. flare.positionScreen.copy( screenPosition )
  148. if ( flare.customUpdateCallback ) {
  149. flare.customUpdateCallback( flare );
  150. } else {
  151. flare.updateLensFlares();
  152. }
  153. // render flares
  154. _gl.uniform1i( uniforms.renderType, 2 );
  155. _gl.enable( _gl.BLEND );
  156. for ( j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) {
  157. sprite = flare.lensFlares[ j ];
  158. if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) {
  159. screenPosition.x = sprite.x;
  160. screenPosition.y = sprite.y;
  161. screenPosition.z = sprite.z;
  162. size = sprite.size * sprite.scale / viewportHeight;
  163. scale.x = size * invAspect;
  164. scale.y = size;
  165. _gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
  166. _gl.uniform2f( uniforms.scale, scale.x, scale.y );
  167. _gl.uniform1f( uniforms.rotation, sprite.rotation );
  168. _gl.uniform1f( uniforms.opacity, sprite.opacity );
  169. _gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
  170. _renderer.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
  171. _renderer.setTexture( sprite.texture, 1 );
  172. _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
  173. }
  174. }
  175. }
  176. }
  177. // restore gl
  178. _gl.enable( _gl.CULL_FACE );
  179. _gl.enable( _gl.DEPTH_TEST );
  180. _gl.depthMask( true );
  181. };
  182. function createProgram ( shader ) {
  183. var program = _gl.createProgram();
  184. var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
  185. var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
  186. _gl.shaderSource( fragmentShader, shader.fragmentShader );
  187. _gl.shaderSource( vertexShader, shader.vertexShader );
  188. _gl.compileShader( fragmentShader );
  189. _gl.compileShader( vertexShader );
  190. _gl.attachShader( program, fragmentShader );
  191. _gl.attachShader( program, vertexShader );
  192. _gl.linkProgram( program );
  193. return program;
  194. };
  195. };