SpritePlugin.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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.sizeAttenuation = _gl.getUniformLocation( _sprite.program, "sizeAttenuation" );
  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. _sprite.uniforms.alphaTest = _gl.getUniformLocation( _sprite.program, "alphaTest" );
  54. };
  55. this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
  56. var sprites = scene.__webglSprites,
  57. nSprites = sprites.length;
  58. if ( ! nSprites ) return;
  59. var attributes = _sprite.attributes,
  60. uniforms = _sprite.uniforms;
  61. var invAspect = viewportHeight / viewportWidth;
  62. var halfViewportWidth = viewportWidth * 0.5,
  63. halfViewportHeight = viewportHeight * 0.5;
  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.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer );
  71. _gl.vertexAttribPointer( attributes.position, 2, _gl.FLOAT, false, 2 * 8, 0 );
  72. _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 );
  73. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer );
  74. _gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
  75. _gl.activeTexture( _gl.TEXTURE0 );
  76. _gl.uniform1i( uniforms.map, 0 );
  77. var oldFogType = 0;
  78. var sceneFogType = 0;
  79. var fog = scene.fog;
  80. if ( fog ) {
  81. _gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
  82. if ( fog instanceof THREE.Fog ) {
  83. _gl.uniform1f( uniforms.fogNear, fog.near );
  84. _gl.uniform1f( uniforms.fogFar, fog.far );
  85. _gl.uniform1i( uniforms.fogType, 1 );
  86. oldFogType = 1;
  87. sceneFogType = 1;
  88. } else if ( fog instanceof THREE.FogExp2 ) {
  89. _gl.uniform1f( uniforms.fogDensity, fog.density );
  90. _gl.uniform1i( uniforms.fogType, 2 );
  91. oldFogType = 2;
  92. sceneFogType = 2;
  93. }
  94. } else {
  95. _gl.uniform1i( uniforms.fogType, 0 );
  96. oldFogType = 0;
  97. sceneFogType = 0;
  98. }
  99. // update positions and sort
  100. var i, sprite, material, screenPosition, size, fogType, scale = [];
  101. for( i = 0; i < nSprites; i ++ ) {
  102. sprite = sprites[ i ];
  103. material = sprite.material;
  104. if ( ! sprite.visible || material.opacity === 0 ) continue;
  105. if ( ! material.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. material = sprite.material;
  117. if ( ! sprite.visible || material.opacity === 0 ) continue;
  118. if ( material.map && material.map.image && material.map.image.width ) {
  119. _gl.uniform1f( uniforms.alphaTest, material.alphaTest );
  120. if ( material.useScreenCoordinates === true ) {
  121. _gl.uniform1i( uniforms.useScreenCoordinates, 1 );
  122. _gl.uniform3f(
  123. uniforms.screenPosition,
  124. ( ( sprite.position.x * _renderer.devicePixelRatio ) - halfViewportWidth ) / halfViewportWidth,
  125. ( halfViewportHeight - ( sprite.position.y * _renderer.devicePixelRatio ) ) / halfViewportHeight,
  126. Math.max( 0, Math.min( 1, sprite.position.z ) )
  127. );
  128. scale[ 0 ] = _renderer.devicePixelRatio;
  129. scale[ 1 ] = _renderer.devicePixelRatio;
  130. } else {
  131. _gl.uniform1i( uniforms.useScreenCoordinates, 0 );
  132. _gl.uniform1i( uniforms.sizeAttenuation, material.sizeAttenuation ? 1 : 0 );
  133. _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite._modelViewMatrix.elements );
  134. scale[ 0 ] = 1;
  135. scale[ 1 ] = 1;
  136. }
  137. if ( scene.fog && material.fog ) {
  138. fogType = sceneFogType;
  139. } else {
  140. fogType = 0;
  141. }
  142. if ( oldFogType !== fogType ) {
  143. _gl.uniform1i( uniforms.fogType, fogType );
  144. oldFogType = fogType;
  145. }
  146. size = 1 / ( material.scaleByViewport ? viewportHeight : 1 );
  147. scale[ 0 ] *= size * invAspect * sprite.scale.x
  148. scale[ 1 ] *= size * sprite.scale.y;
  149. _gl.uniform2f( uniforms.uvScale, material.uvScale.x, material.uvScale.y );
  150. _gl.uniform2f( uniforms.uvOffset, material.uvOffset.x, material.uvOffset.y );
  151. _gl.uniform2f( uniforms.alignment, material.alignment.x, material.alignment.y );
  152. _gl.uniform1f( uniforms.opacity, material.opacity );
  153. _gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
  154. _gl.uniform1f( uniforms.rotation, sprite.rotation );
  155. _gl.uniform2fv( uniforms.scale, scale );
  156. _renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
  157. _renderer.setDepthTest( material.depthTest );
  158. _renderer.setDepthWrite( material.depthWrite );
  159. _renderer.setTexture( material.map, 0 );
  160. _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
  161. }
  162. }
  163. // restore gl
  164. _gl.enable( _gl.CULL_FACE );
  165. };
  166. function createProgram ( shader ) {
  167. var program = _gl.createProgram();
  168. var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
  169. var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
  170. _gl.shaderSource( fragmentShader, shader.fragmentShader );
  171. _gl.shaderSource( vertexShader, shader.vertexShader );
  172. _gl.compileShader( fragmentShader );
  173. _gl.compileShader( vertexShader );
  174. _gl.attachShader( program, fragmentShader );
  175. _gl.attachShader( program, vertexShader );
  176. _gl.linkProgram( program );
  177. return program;
  178. };
  179. function painterSortStable ( a, b ) {
  180. if ( a.z !== b.z ) {
  181. return b.z - a.z;
  182. } else {
  183. return b.id - a.id;
  184. }
  185. };
  186. };