SpritePlugin.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /**
  2. * @author mikael emtinger / http://gomo.se/
  3. * @author alteredq / http://alteredqualia.com/
  4. */
  5. THREE.SpritePlugin = function ( ) {
  6. var _gl, _renderer, _sprite = {};
  7. this.init = function ( renderer ) {
  8. _gl = renderer.context;
  9. _renderer = renderer;
  10. _sprite.vertices = new Float32Array( 8 + 8 );
  11. _sprite.faces = new Uint16Array( 6 );
  12. var i = 0;
  13. _sprite.vertices[ i++ ] = -1; _sprite.vertices[ i++ ] = -1; // vertex 0
  14. _sprite.vertices[ i++ ] = 0; _sprite.vertices[ i++ ] = 0; // uv 0
  15. _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = -1; // vertex 1
  16. _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 0; // uv 1
  17. _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 1; // vertex 2
  18. _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 1; // uv 2
  19. _sprite.vertices[ i++ ] = -1; _sprite.vertices[ i++ ] = 1; // vertex 3
  20. _sprite.vertices[ i++ ] = 0; _sprite.vertices[ i++ ] = 1; // uv 3
  21. i = 0;
  22. _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 1; _sprite.faces[ i++ ] = 2;
  23. _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 2; _sprite.faces[ i++ ] = 3;
  24. _sprite.vertexBuffer = _gl.createBuffer();
  25. _sprite.elementBuffer = _gl.createBuffer();
  26. _gl.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer );
  27. _gl.bufferData( _gl.ARRAY_BUFFER, _sprite.vertices, _gl.STATIC_DRAW );
  28. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer );
  29. _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _sprite.faces, _gl.STATIC_DRAW );
  30. _sprite.program = createProgram( THREE.ShaderSprite[ "sprite" ] );
  31. _sprite.attributes = {};
  32. _sprite.uniforms = {};
  33. _sprite.attributes.position = _gl.getAttribLocation ( _sprite.program, "position" );
  34. _sprite.attributes.uv = _gl.getAttribLocation ( _sprite.program, "uv" );
  35. _sprite.uniforms.uvOffset = _gl.getUniformLocation( _sprite.program, "uvOffset" );
  36. _sprite.uniforms.uvScale = _gl.getUniformLocation( _sprite.program, "uvScale" );
  37. _sprite.uniforms.rotation = _gl.getUniformLocation( _sprite.program, "rotation" );
  38. _sprite.uniforms.scale = _gl.getUniformLocation( _sprite.program, "scale" );
  39. _sprite.uniforms.alignment = _gl.getUniformLocation( _sprite.program, "alignment" );
  40. _sprite.uniforms.color = _gl.getUniformLocation( _sprite.program, "color" );
  41. _sprite.uniforms.map = _gl.getUniformLocation( _sprite.program, "map" );
  42. _sprite.uniforms.opacity = _gl.getUniformLocation( _sprite.program, "opacity" );
  43. _sprite.uniforms.useScreenCoordinates = _gl.getUniformLocation( _sprite.program, "useScreenCoordinates" );
  44. _sprite.uniforms.affectedByDistance = _gl.getUniformLocation( _sprite.program, "affectedByDistance" );
  45. _sprite.uniforms.screenPosition = _gl.getUniformLocation( _sprite.program, "screenPosition" );
  46. _sprite.uniforms.modelViewMatrix = _gl.getUniformLocation( _sprite.program, "modelViewMatrix" );
  47. _sprite.uniforms.projectionMatrix = _gl.getUniformLocation( _sprite.program, "projectionMatrix" );
  48. _sprite.uniforms.fogType = _gl.getUniformLocation( _sprite.program, "fogType" );
  49. _sprite.uniforms.fogDensity = _gl.getUniformLocation( _sprite.program, "fogDensity" );
  50. _sprite.uniforms.fogNear = _gl.getUniformLocation( _sprite.program, "fogNear" );
  51. _sprite.uniforms.fogFar = _gl.getUniformLocation( _sprite.program, "fogFar" );
  52. _sprite.uniforms.fogColor = _gl.getUniformLocation( _sprite.program, "fogColor" );
  53. };
  54. this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
  55. var sprites = scene.__webglSprites,
  56. nSprites = sprites.length;
  57. if ( ! nSprites ) return;
  58. var attributes = _sprite.attributes,
  59. uniforms = _sprite.uniforms;
  60. var invAspect = viewportHeight / viewportWidth;
  61. var halfViewportWidth = viewportWidth * 0.5,
  62. halfViewportHeight = viewportHeight * 0.5;
  63. var mergeWith3D = true;
  64. // setup gl
  65. _gl.useProgram( _sprite.program );
  66. _gl.enableVertexAttribArray( attributes.position );
  67. _gl.enableVertexAttribArray( attributes.uv );
  68. _gl.disable( _gl.CULL_FACE );
  69. _gl.enable( _gl.BLEND );
  70. _gl.depthMask( true );
  71. _gl.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer );
  72. _gl.vertexAttribPointer( attributes.position, 2, _gl.FLOAT, false, 2 * 8, 0 );
  73. _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 );
  74. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer );
  75. _gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera._projectionMatrixArray );
  76. _gl.activeTexture( _gl.TEXTURE0 );
  77. _gl.uniform1i( uniforms.map, 0 );
  78. var oldFogType = 0;
  79. var sceneFogType = 0;
  80. var fog = scene.fog;
  81. if ( fog ) {
  82. _gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
  83. if ( fog instanceof THREE.Fog ) {
  84. _gl.uniform1f( uniforms.fogNear, fog.near );
  85. _gl.uniform1f( uniforms.fogFar, fog.far );
  86. _gl.uniform1i( uniforms.fogType, 1 );
  87. oldFogType = 1;
  88. sceneFogType = 1;
  89. } else if ( fog instanceof THREE.FogExp2 ) {
  90. _gl.uniform1f( uniforms.fogDensity, fog.density );
  91. _gl.uniform1i( uniforms.fogType, 2 );
  92. oldFogType = 2;
  93. sceneFogType = 2;
  94. }
  95. } else {
  96. _gl.uniform1i( uniforms.fogType, 0 );
  97. oldFogType = 0;
  98. sceneFogType = 0;
  99. }
  100. // update positions and sort
  101. var i, sprite, screenPosition, size, fogType, scale = [];
  102. for( i = 0; i < nSprites; i ++ ) {
  103. sprite = sprites[ i ];
  104. if ( ! sprite.visible || sprite.opacity === 0 ) continue;
  105. if ( ! sprite.useScreenCoordinates ) {
  106. sprite._modelViewMatrix.multiply( camera.matrixWorldInverse, sprite.matrixWorld );
  107. sprite.z = - sprite._modelViewMatrix.elements[ 14 ];
  108. } else {
  109. sprite.z = - sprite.position.z;
  110. }
  111. }
  112. sprites.sort( painterSortStable );
  113. // render all sprites
  114. for( i = 0; i < nSprites; i ++ ) {
  115. sprite = sprites[ i ];
  116. if ( ! sprite.visible || sprite.opacity === 0 ) continue;
  117. if ( sprite.map && sprite.map.image && sprite.map.image.width ) {
  118. if ( sprite.useScreenCoordinates ) {
  119. _gl.uniform1i( uniforms.useScreenCoordinates, 1 );
  120. _gl.uniform3f(
  121. uniforms.screenPosition,
  122. ( sprite.position.x - halfViewportWidth ) / halfViewportWidth,
  123. ( halfViewportHeight - sprite.position.y ) / halfViewportHeight,
  124. Math.max( 0, Math.min( 1, sprite.position.z ) )
  125. );
  126. } else {
  127. _gl.uniform1i( uniforms.useScreenCoordinates, 0 );
  128. _gl.uniform1i( uniforms.affectedByDistance, sprite.affectedByDistance ? 1 : 0 );
  129. _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite._modelViewMatrix.elements );
  130. }
  131. if ( scene.fog && sprite.fog ) {
  132. fogType = sceneFogType;
  133. } else {
  134. fogType = 0;
  135. }
  136. if ( oldFogType !== fogType ) {
  137. _gl.uniform1i( uniforms.fogType, fogType );
  138. oldFogType = fogType;
  139. }
  140. size = 1 / ( sprite.scaleByViewport ? viewportHeight : 1 );
  141. scale[ 0 ] = size * invAspect * sprite.scale.x;
  142. scale[ 1 ] = size * sprite.scale.y;
  143. _gl.uniform2f( uniforms.uvScale, sprite.uvScale.x, sprite.uvScale.y );
  144. _gl.uniform2f( uniforms.uvOffset, sprite.uvOffset.x, sprite.uvOffset.y );
  145. _gl.uniform2f( uniforms.alignment, sprite.alignment.x, sprite.alignment.y );
  146. _gl.uniform1f( uniforms.opacity, sprite.opacity );
  147. _gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
  148. _gl.uniform1f( uniforms.rotation, sprite.rotation );
  149. _gl.uniform2fv( uniforms.scale, scale );
  150. if ( sprite.mergeWith3D && !mergeWith3D ) {
  151. _gl.enable( _gl.DEPTH_TEST );
  152. mergeWith3D = true;
  153. } else if ( ! sprite.mergeWith3D && mergeWith3D ) {
  154. _gl.disable( _gl.DEPTH_TEST );
  155. mergeWith3D = false;
  156. }
  157. _renderer.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
  158. _renderer.setTexture( sprite.map, 0 );
  159. _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
  160. }
  161. }
  162. // restore gl
  163. _gl.enable( _gl.CULL_FACE );
  164. _gl.enable( _gl.DEPTH_TEST );
  165. _gl.depthMask( true );
  166. };
  167. function createProgram ( shader ) {
  168. var program = _gl.createProgram();
  169. var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
  170. var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
  171. _gl.shaderSource( fragmentShader, shader.fragmentShader );
  172. _gl.shaderSource( vertexShader, shader.vertexShader );
  173. _gl.compileShader( fragmentShader );
  174. _gl.compileShader( vertexShader );
  175. _gl.attachShader( program, fragmentShader );
  176. _gl.attachShader( program, vertexShader );
  177. _gl.linkProgram( program );
  178. return program;
  179. };
  180. function painterSortStable ( a, b ) {
  181. if ( a.z !== b.z ) {
  182. return b.z - a.z;
  183. } else {
  184. return b.id - a.id;
  185. }
  186. };
  187. };