123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /**
- * @author mikael emtinger / http://gomo.se/
- * @author alteredq / http://alteredqualia.com/
- */
- THREE.SpritePlugin = function ( ) {
- var _gl, _renderer, _sprite = {};
- this.init = function ( renderer ) {
- _gl = renderer.context;
- _renderer = renderer;
- _sprite.vertices = new Float32Array( 8 + 8 );
- _sprite.faces = new Uint16Array( 6 );
- var i = 0;
- _sprite.vertices[ i++ ] = -1; _sprite.vertices[ i++ ] = -1; // vertex 0
- _sprite.vertices[ i++ ] = 0; _sprite.vertices[ i++ ] = 0; // uv 0
- _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = -1; // vertex 1
- _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 0; // uv 1
- _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 1; // vertex 2
- _sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 1; // uv 2
- _sprite.vertices[ i++ ] = -1; _sprite.vertices[ i++ ] = 1; // vertex 3
- _sprite.vertices[ i++ ] = 0; _sprite.vertices[ i++ ] = 1; // uv 3
- i = 0;
- _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 1; _sprite.faces[ i++ ] = 2;
- _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 2; _sprite.faces[ i++ ] = 3;
- _sprite.vertexBuffer = _gl.createBuffer();
- _sprite.elementBuffer = _gl.createBuffer();
- _gl.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, _sprite.vertices, _gl.STATIC_DRAW );
- _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer );
- _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _sprite.faces, _gl.STATIC_DRAW );
- _sprite.program = createProgram( THREE.ShaderSprite[ "sprite" ] );
- _sprite.attributes = {};
- _sprite.uniforms = {};
- _sprite.attributes.position = _gl.getAttribLocation ( _sprite.program, "position" );
- _sprite.attributes.uv = _gl.getAttribLocation ( _sprite.program, "uv" );
- _sprite.uniforms.uvOffset = _gl.getUniformLocation( _sprite.program, "uvOffset" );
- _sprite.uniforms.uvScale = _gl.getUniformLocation( _sprite.program, "uvScale" );
- _sprite.uniforms.rotation = _gl.getUniformLocation( _sprite.program, "rotation" );
- _sprite.uniforms.scale = _gl.getUniformLocation( _sprite.program, "scale" );
- _sprite.uniforms.alignment = _gl.getUniformLocation( _sprite.program, "alignment" );
- _sprite.uniforms.color = _gl.getUniformLocation( _sprite.program, "color" );
- _sprite.uniforms.map = _gl.getUniformLocation( _sprite.program, "map" );
- _sprite.uniforms.opacity = _gl.getUniformLocation( _sprite.program, "opacity" );
- _sprite.uniforms.useScreenCoordinates = _gl.getUniformLocation( _sprite.program, "useScreenCoordinates" );
- _sprite.uniforms.sizeAttenuation = _gl.getUniformLocation( _sprite.program, "sizeAttenuation" );
- _sprite.uniforms.screenPosition = _gl.getUniformLocation( _sprite.program, "screenPosition" );
- _sprite.uniforms.modelViewMatrix = _gl.getUniformLocation( _sprite.program, "modelViewMatrix" );
- _sprite.uniforms.projectionMatrix = _gl.getUniformLocation( _sprite.program, "projectionMatrix" );
- _sprite.uniforms.fogType = _gl.getUniformLocation( _sprite.program, "fogType" );
- _sprite.uniforms.fogDensity = _gl.getUniformLocation( _sprite.program, "fogDensity" );
- _sprite.uniforms.fogNear = _gl.getUniformLocation( _sprite.program, "fogNear" );
- _sprite.uniforms.fogFar = _gl.getUniformLocation( _sprite.program, "fogFar" );
- _sprite.uniforms.fogColor = _gl.getUniformLocation( _sprite.program, "fogColor" );
- _sprite.uniforms.alphaTest = _gl.getUniformLocation( _sprite.program, "alphaTest" );
- };
- this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
- var sprites = scene.__webglSprites,
- nSprites = sprites.length;
- if ( ! nSprites ) return;
- var attributes = _sprite.attributes,
- uniforms = _sprite.uniforms;
- var invAspect = viewportHeight / viewportWidth;
- var halfViewportWidth = viewportWidth * 0.5,
- halfViewportHeight = viewportHeight * 0.5;
- // setup gl
- _gl.useProgram( _sprite.program );
- _gl.enableVertexAttribArray( attributes.position );
- _gl.enableVertexAttribArray( attributes.uv );
- _gl.disable( _gl.CULL_FACE );
- _gl.enable( _gl.BLEND );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer );
- _gl.vertexAttribPointer( attributes.position, 2, _gl.FLOAT, false, 2 * 8, 0 );
- _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 );
- _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer );
- _gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
- _gl.activeTexture( _gl.TEXTURE0 );
- _gl.uniform1i( uniforms.map, 0 );
- var oldFogType = 0;
- var sceneFogType = 0;
- var fog = scene.fog;
- if ( fog ) {
- _gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
- if ( fog instanceof THREE.Fog ) {
- _gl.uniform1f( uniforms.fogNear, fog.near );
- _gl.uniform1f( uniforms.fogFar, fog.far );
- _gl.uniform1i( uniforms.fogType, 1 );
- oldFogType = 1;
- sceneFogType = 1;
- } else if ( fog instanceof THREE.FogExp2 ) {
- _gl.uniform1f( uniforms.fogDensity, fog.density );
- _gl.uniform1i( uniforms.fogType, 2 );
- oldFogType = 2;
- sceneFogType = 2;
- }
- } else {
- _gl.uniform1i( uniforms.fogType, 0 );
- oldFogType = 0;
- sceneFogType = 0;
- }
- // update positions and sort
- var i, sprite, material, screenPosition, size, fogType, scale = [];
- for( i = 0; i < nSprites; i ++ ) {
- sprite = sprites[ i ];
- material = sprite.material;
- if ( ! sprite.visible || material.opacity === 0 ) continue;
- if ( ! material.useScreenCoordinates ) {
- sprite._modelViewMatrix.multiply( camera.matrixWorldInverse, sprite.matrixWorld );
- sprite.z = - sprite._modelViewMatrix.elements[ 14 ];
- } else {
- sprite.z = - sprite.position.z;
- }
- }
- sprites.sort( painterSortStable );
- // render all sprites
- for( i = 0; i < nSprites; i ++ ) {
- sprite = sprites[ i ];
- material = sprite.material;
- if ( ! sprite.visible || material.opacity === 0 ) continue;
- if ( material.map && material.map.image && material.map.image.width ) {
- _gl.uniform1f( uniforms.alphaTest, material.alphaTest );
- if ( material.useScreenCoordinates === true ) {
- _gl.uniform1i( uniforms.useScreenCoordinates, 1 );
- _gl.uniform3f(
- uniforms.screenPosition,
- ( ( sprite.position.x * _renderer.devicePixelRatio ) - halfViewportWidth ) / halfViewportWidth,
- ( halfViewportHeight - ( sprite.position.y * _renderer.devicePixelRatio ) ) / halfViewportHeight,
- Math.max( 0, Math.min( 1, sprite.position.z ) )
- );
- scale[ 0 ] = _renderer.devicePixelRatio;
- scale[ 1 ] = _renderer.devicePixelRatio;
- } else {
- _gl.uniform1i( uniforms.useScreenCoordinates, 0 );
- _gl.uniform1i( uniforms.sizeAttenuation, material.sizeAttenuation ? 1 : 0 );
- _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite._modelViewMatrix.elements );
- scale[ 0 ] = 1;
- scale[ 1 ] = 1;
- }
- if ( scene.fog && material.fog ) {
- fogType = sceneFogType;
- } else {
- fogType = 0;
- }
- if ( oldFogType !== fogType ) {
- _gl.uniform1i( uniforms.fogType, fogType );
- oldFogType = fogType;
- }
- size = 1 / ( material.scaleByViewport ? viewportHeight : 1 );
- scale[ 0 ] *= size * invAspect * sprite.scale.x
- scale[ 1 ] *= size * sprite.scale.y;
- _gl.uniform2f( uniforms.uvScale, material.uvScale.x, material.uvScale.y );
- _gl.uniform2f( uniforms.uvOffset, material.uvOffset.x, material.uvOffset.y );
- _gl.uniform2f( uniforms.alignment, material.alignment.x, material.alignment.y );
- _gl.uniform1f( uniforms.opacity, material.opacity );
- _gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
- _gl.uniform1f( uniforms.rotation, sprite.rotation );
- _gl.uniform2fv( uniforms.scale, scale );
- _renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
- _renderer.setDepthTest( material.depthTest );
- _renderer.setDepthWrite( material.depthWrite );
- _renderer.setTexture( material.map, 0 );
- _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
- }
- }
- // restore gl
- _gl.enable( _gl.CULL_FACE );
- };
- 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;
- };
- function painterSortStable ( a, b ) {
- if ( a.z !== b.z ) {
- return b.z - a.z;
- } else {
- return b.id - a.id;
- }
- };
- };
|