123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- /**
- * @author mikael emtinger / http://gomo.se/
- * @author alteredq / http://alteredqualia.com/
- */
- THREE.SpritePlugin = function () {
- var _gl, _renderer, _texture;
- var vertices, faces, vertexBuffer, elementBuffer;
- var program, attributes, uniforms;
- this.init = function ( renderer ) {
- _gl = renderer.context;
- _renderer = renderer;
- vertices = new Float32Array( [
- - 0.5, - 0.5, 0, 0,
- 0.5, - 0.5, 1, 0,
- 0.5, 0.5, 1, 1,
- - 0.5, 0.5, 0, 1
- ] );
- faces = new Uint16Array( [
- 0, 1, 2,
- 0, 2, 3
- ] );
- vertexBuffer = _gl.createBuffer();
- elementBuffer = _gl.createBuffer();
- _gl.bindBuffer( _gl.ARRAY_BUFFER, vertexBuffer );
- _gl.bufferData( _gl.ARRAY_BUFFER, vertices, _gl.STATIC_DRAW );
- _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
- _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, faces, _gl.STATIC_DRAW );
- program = createProgram();
- attributes = {
- position: _gl.getAttribLocation ( program, 'position' ),
- uv: _gl.getAttribLocation ( program, 'uv' )
- };
- uniforms = {
- uvOffset: _gl.getUniformLocation( program, 'uvOffset' ),
- uvScale: _gl.getUniformLocation( program, 'uvScale' ),
- rotation: _gl.getUniformLocation( program, 'rotation' ),
- scale: _gl.getUniformLocation( program, 'scale' ),
- color: _gl.getUniformLocation( program, 'color' ),
- map: _gl.getUniformLocation( program, 'map' ),
- opacity: _gl.getUniformLocation( program, 'opacity' ),
- modelViewMatrix: _gl.getUniformLocation( program, 'modelViewMatrix' ),
- projectionMatrix: _gl.getUniformLocation( program, 'projectionMatrix' ),
- fogType: _gl.getUniformLocation( program, 'fogType' ),
- fogDensity: _gl.getUniformLocation( program, 'fogDensity' ),
- fogNear: _gl.getUniformLocation( program, 'fogNear' ),
- fogFar: _gl.getUniformLocation( program, 'fogFar' ),
- fogColor: _gl.getUniformLocation( program, 'fogColor' ),
- alphaTest: _gl.getUniformLocation( program, 'alphaTest' )
- };
- var canvas = document.createElement( 'canvas' );
- canvas.width = 8;
- canvas.height = 8;
- var context = canvas.getContext( '2d' );
- context.fillStyle = '#ffffff';
- context.fillRect( 0, 0, canvas.width, canvas.height );
- _texture = new THREE.Texture( canvas );
- _texture.needsUpdate = true;
- };
- this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
- var sprites = scene.__webglSprites,
- nSprites = sprites.length;
- if ( ! nSprites ) return;
- // setup gl
- _gl.useProgram( program );
- _gl.enableVertexAttribArray( attributes.position );
- _gl.enableVertexAttribArray( attributes.uv );
- _gl.disable( _gl.CULL_FACE );
- _gl.enable( _gl.BLEND );
- _gl.bindBuffer( _gl.ARRAY_BUFFER, 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, 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, fogType, scale = [];
- for( i = 0; i < nSprites; i ++ ) {
- sprite = sprites[ i ];
- material = sprite.material;
- if ( sprite.visible === false ) continue;
- sprite._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
- sprite.z = - sprite._modelViewMatrix.elements[ 14 ];
- }
- sprites.sort( painterSortStable );
- // render all sprites
- for( i = 0; i < nSprites; i ++ ) {
- sprite = sprites[ i ];
- if ( sprite.visible === false ) continue;
- material = sprite.material;
- _gl.uniform1f( uniforms.alphaTest, material.alphaTest );
- _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite._modelViewMatrix.elements );
- scale[ 0 ] = sprite.scale.x;
- scale[ 1 ] = sprite.scale.y;
- if ( scene.fog && material.fog ) {
- fogType = sceneFogType;
- } else {
- fogType = 0;
- }
- if ( oldFogType !== fogType ) {
- _gl.uniform1i( uniforms.fogType, fogType );
- oldFogType = fogType;
- }
- if ( material.map !== null ) {
- _gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y );
- _gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y );
- } else {
- _gl.uniform2f( uniforms.uvOffset, 0, 0 );
- _gl.uniform2f( uniforms.uvScale, 1, 1 );
- }
- _gl.uniform1f( uniforms.opacity, material.opacity );
- _gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
- _gl.uniform1f( uniforms.rotation, material.rotation );
- _gl.uniform2fv( uniforms.scale, scale );
- _renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
- _renderer.setDepthTest( material.depthTest );
- _renderer.setDepthWrite( material.depthWrite );
- if ( material.map && material.map.image && material.map.image.width ) {
- _renderer.setTexture( material.map, 0 );
- } else {
- _renderer.setTexture( _texture, 0 );
- }
- _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
- }
- // restore gl
- _gl.enable( _gl.CULL_FACE );
- };
- function createProgram () {
- var program = _gl.createProgram();
- var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
- var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
- _gl.shaderSource( vertexShader, [
- 'precision ' + _renderer.getPrecision() + ' float;',
- 'uniform mat4 modelViewMatrix;',
- 'uniform mat4 projectionMatrix;',
- 'uniform float rotation;',
- 'uniform vec2 scale;',
- 'uniform vec2 uvOffset;',
- 'uniform vec2 uvScale;',
- 'attribute vec2 position;',
- 'attribute vec2 uv;',
- 'varying vec2 vUV;',
- 'void main() {',
- 'vUV = uvOffset + uv * uvScale;',
- 'vec2 alignedPosition = position * scale;',
- 'vec2 rotatedPosition;',
- 'rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;',
- 'rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;',
- 'vec4 finalPosition;',
- 'finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );',
- 'finalPosition.xy += rotatedPosition;',
- 'finalPosition = projectionMatrix * finalPosition;',
- 'gl_Position = finalPosition;',
- '}'
- ].join( '\n' ) );
- _gl.shaderSource( fragmentShader, [
- 'precision ' + _renderer.getPrecision() + ' float;',
- 'uniform vec3 color;',
- 'uniform sampler2D map;',
- 'uniform float opacity;',
- 'uniform int fogType;',
- 'uniform vec3 fogColor;',
- 'uniform float fogDensity;',
- 'uniform float fogNear;',
- 'uniform float fogFar;',
- 'uniform float alphaTest;',
- 'varying vec2 vUV;',
- 'void main() {',
- 'vec4 texture = texture2D( map, vUV );',
- 'if ( texture.a < alphaTest ) discard;',
- 'gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );',
- 'if ( fogType > 0 ) {',
- 'float depth = gl_FragCoord.z / gl_FragCoord.w;',
- 'float fogFactor = 0.0;',
- 'if ( fogType == 1 ) {',
- 'fogFactor = smoothstep( fogNear, fogFar, depth );',
- '} else {',
- 'const float LOG2 = 1.442695;',
- 'float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );',
- 'fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );',
- '}',
- 'gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );',
- '}',
- '}'
- ].join( '\n' ) );
- _gl.compileShader( vertexShader );
- _gl.compileShader( fragmentShader );
- _gl.attachShader( program, vertexShader );
- _gl.attachShader( program, fragmentShader );
- _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;
- }
- };
- };
|