SpritePlugin.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /**
  2. * @author mikael emtinger / http://gomo.se/
  3. * @author alteredq / http://alteredqualia.com/
  4. */
  5. THREE.SpritePlugin = function () {
  6. var _gl, _renderer, _precision, _sprite = {};
  7. this.init = function ( renderer ) {
  8. _gl = renderer.context;
  9. _renderer = renderer;
  10. _precision = renderer.getPrecision();
  11. _sprite.vertices = new Float32Array( 8 + 8 );
  12. _sprite.faces = new Uint16Array( 6 );
  13. var i = 0;
  14. _sprite.vertices[ i++ ] = -0.5; _sprite.vertices[ i++ ] = -0.5; // vertex 0
  15. _sprite.vertices[ i++ ] = 0; _sprite.vertices[ i++ ] = 0; // uv 0
  16. _sprite.vertices[ i++ ] = 0.5; _sprite.vertices[ i++ ] = -0.5; // vertex 1
  17. _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 0; // uv 1
  18. _sprite.vertices[ i++ ] = 0.5; _sprite.vertices[ i++ ] = 0.5; // vertex 2
  19. _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 1; // uv 2
  20. _sprite.vertices[ i++ ] = -0.5; _sprite.vertices[ i++ ] = 0.5; // vertex 3
  21. _sprite.vertices[ i++ ] = 0; _sprite.vertices[ i++ ] = 1; // uv 3
  22. i = 0;
  23. _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 1; _sprite.faces[ i++ ] = 2;
  24. _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 2; _sprite.faces[ i++ ] = 3;
  25. _sprite.vertexBuffer = _gl.createBuffer();
  26. _sprite.elementBuffer = _gl.createBuffer();
  27. _gl.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer );
  28. _gl.bufferData( _gl.ARRAY_BUFFER, _sprite.vertices, _gl.STATIC_DRAW );
  29. _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer );
  30. _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _sprite.faces, _gl.STATIC_DRAW );
  31. _sprite.program = createProgram( THREE.ShaderSprite[ "sprite" ], _precision );
  32. _sprite.attributes = {};
  33. _sprite.uniforms = {};
  34. _sprite.attributes.position = _gl.getAttribLocation ( _sprite.program, "position" );
  35. _sprite.attributes.uv = _gl.getAttribLocation ( _sprite.program, "uv" );
  36. _sprite.uniforms.uvOffset = _gl.getUniformLocation( _sprite.program, "uvOffset" );
  37. _sprite.uniforms.uvScale = _gl.getUniformLocation( _sprite.program, "uvScale" );
  38. _sprite.uniforms.rotation = _gl.getUniformLocation( _sprite.program, "rotation" );
  39. _sprite.uniforms.scale = _gl.getUniformLocation( _sprite.program, "scale" );
  40. _sprite.uniforms.alignment = _gl.getUniformLocation( _sprite.program, "alignment" );
  41. _sprite.uniforms.halfViewport = _gl.getUniformLocation( _sprite.program, "halfViewport" );
  42. _sprite.uniforms.color = _gl.getUniformLocation( _sprite.program, "color" );
  43. _sprite.uniforms.map = _gl.getUniformLocation( _sprite.program, "map" );
  44. _sprite.uniforms.opacity = _gl.getUniformLocation( _sprite.program, "opacity" );
  45. _sprite.uniforms.useScreenCoordinates = _gl.getUniformLocation( _sprite.program, "useScreenCoordinates" );
  46. _sprite.uniforms.sizeAttenuation = _gl.getUniformLocation( _sprite.program, "sizeAttenuation" );
  47. _sprite.uniforms.screenPosition = _gl.getUniformLocation( _sprite.program, "screenPosition" );
  48. _sprite.uniforms.modelViewMatrix = _gl.getUniformLocation( _sprite.program, "modelViewMatrix" );
  49. _sprite.uniforms.projectionMatrix = _gl.getUniformLocation( _sprite.program, "projectionMatrix" );
  50. _sprite.uniforms.fogType = _gl.getUniformLocation( _sprite.program, "fogType" );
  51. _sprite.uniforms.fogDensity = _gl.getUniformLocation( _sprite.program, "fogDensity" );
  52. _sprite.uniforms.fogNear = _gl.getUniformLocation( _sprite.program, "fogNear" );
  53. _sprite.uniforms.fogFar = _gl.getUniformLocation( _sprite.program, "fogFar" );
  54. _sprite.uniforms.fogColor = _gl.getUniformLocation( _sprite.program, "fogColor" );
  55. _sprite.uniforms.alphaTest = _gl.getUniformLocation( _sprite.program, "alphaTest" );
  56. };
  57. this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
  58. var sprites = scene.__webglSprites,
  59. nSprites = sprites.length;
  60. if ( ! nSprites ) return;
  61. var attributes = _sprite.attributes,
  62. uniforms = _sprite.uniforms;
  63. var halfViewportWidth = viewportWidth * 0.5,
  64. halfViewportHeight = viewportHeight * 0.5;
  65. // setup gl
  66. _gl.useProgram( _sprite.program );
  67. _gl.enableVertexAttribArray( attributes.position );
  68. _gl.enableVertexAttribArray( attributes.uv );
  69. _gl.disable( _gl.CULL_FACE );
  70. _gl.enable( _gl.BLEND );
  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.projectionMatrix.elements );
  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, material, screenPosition, fogType, scale = [];
  102. for( i = 0; i < nSprites; i ++ ) {
  103. sprite = sprites[ i ];
  104. material = sprite.material;
  105. if ( ! sprite.visible || material.opacity === 0 ) continue;
  106. if ( ! material.useScreenCoordinates ) {
  107. sprite._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
  108. sprite.z = - sprite._modelViewMatrix.elements[ 14 ];
  109. } else {
  110. sprite.z = - sprite.position.z;
  111. }
  112. }
  113. sprites.sort( painterSortStable );
  114. // render all sprites
  115. for( i = 0; i < nSprites; i ++ ) {
  116. sprite = sprites[ i ];
  117. material = sprite.material;
  118. if ( ! sprite.visible || material.opacity === 0 ) continue;
  119. if ( material.map && material.map.image && material.map.image.width ) {
  120. _gl.uniform1f( uniforms.alphaTest, material.alphaTest );
  121. if ( material.useScreenCoordinates === true ) {
  122. _gl.uniform1i( uniforms.useScreenCoordinates, 1 );
  123. _gl.uniform3f(
  124. uniforms.screenPosition,
  125. ( ( sprite.position.x * _renderer.devicePixelRatio ) - halfViewportWidth ) / halfViewportWidth,
  126. ( halfViewportHeight - ( sprite.position.y * _renderer.devicePixelRatio ) ) / halfViewportHeight,
  127. Math.max( 0, Math.min( 1, sprite.position.z ) )
  128. );
  129. scale[ 0 ] = _renderer.devicePixelRatio * sprite.scale.x;
  130. scale[ 1 ] = _renderer.devicePixelRatio * sprite.scale.y;
  131. } else {
  132. _gl.uniform1i( uniforms.useScreenCoordinates, 0 );
  133. _gl.uniform1i( uniforms.sizeAttenuation, material.sizeAttenuation ? 1 : 0 );
  134. _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite._modelViewMatrix.elements );
  135. scale[ 0 ] = sprite.scale.x;
  136. scale[ 1 ] = sprite.scale.y;
  137. }
  138. if ( scene.fog && material.fog ) {
  139. fogType = sceneFogType;
  140. } else {
  141. fogType = 0;
  142. }
  143. if ( oldFogType !== fogType ) {
  144. _gl.uniform1i( uniforms.fogType, fogType );
  145. oldFogType = fogType;
  146. }
  147. _gl.uniform2f( uniforms.uvScale, material.uvScale.x, material.uvScale.y );
  148. _gl.uniform2f( uniforms.uvOffset, material.uvOffset.x, material.uvOffset.y );
  149. _gl.uniform2f( uniforms.alignment, material.alignment.x, material.alignment.y );
  150. _gl.uniform1f( uniforms.opacity, material.opacity );
  151. _gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
  152. _gl.uniform1f( uniforms.rotation, material.rotation );
  153. _gl.uniform2fv( uniforms.scale, scale );
  154. _gl.uniform2f( uniforms.halfViewport, halfViewportWidth, halfViewportHeight );
  155. _renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
  156. _renderer.setDepthTest( material.depthTest );
  157. _renderer.setDepthWrite( material.depthWrite );
  158. _renderer.setTexture( material.map, 0 );
  159. _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
  160. }
  161. }
  162. // restore gl
  163. _gl.enable( _gl.CULL_FACE );
  164. };
  165. function createProgram ( shader, precision ) {
  166. var program = _gl.createProgram();
  167. var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
  168. var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
  169. var prefix = "precision " + precision + " float;\n";
  170. _gl.shaderSource( fragmentShader, prefix + shader.fragmentShader );
  171. _gl.shaderSource( vertexShader, prefix + 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. };