Commit 5c0cbaf5 authored by alteredq's avatar alteredq

Moved sprite handling into plugin.

Work in progress. Still just experimenting. Probably some auto-adding of plugins would be useful.
parent 0eaeaad4
/**
* @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++ ] = 1; // uv 0
_sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = -1; // vertex 1
_sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 1; // uv 1
_sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 1; // vertex 2
_sprite.vertices[ i++ ] = 1; _sprite.vertices[ i++ ] = 0; // uv 2
_sprite.vertices[ i++ ] = -1; _sprite.vertices[ i++ ] = 1; // vertex 3
_sprite.vertices[ i++ ] = 0; _sprite.vertices[ i++ ] = 0; // 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.affectedByDistance = _gl.getUniformLocation( _sprite.program, "affectedByDistance" );
_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.attributesEnabled = false;
};
this.render = function ( scene, camera, viewportWidth, viewportHeight, projectionMatrixArray ) {
var o, ol, object;
var attributes = _sprite.attributes;
var uniforms = _sprite.uniforms;
var invAspect = viewportHeight / viewportWidth;
var size, scale = [];
var screenPosition;
var halfViewportWidth = viewportWidth * 0.5;
var halfViewportHeight = viewportHeight * 0.5;
var mergeWith3D = true;
// setup gl
_gl.useProgram( _sprite.program );
_currentProgram = _sprite.program;
if ( ! _sprite.attributesEnabled ) {
_gl.enableVertexAttribArray( attributes.position );
_gl.enableVertexAttribArray( attributes.uv );
_sprite.attributesEnabled = true;
}
_gl.disable( _gl.CULL_FACE );
_gl.enable( _gl.BLEND );
_gl.depthMask( true );
_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, projectionMatrixArray );
_gl.activeTexture( _gl.TEXTURE0 );
_gl.uniform1i( uniforms.map, 0 );
// update positions and sort
for( o = 0, ol = scene.__webglSprites.length; o < ol; o ++ ) {
object = scene.__webglSprites[ o ];
if ( !object.visible || object.opacity === 0 ) continue;
if( !object.useScreenCoordinates ) {
object._modelViewMatrix.multiplyToArray( camera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
object.z = -object._modelViewMatrix.n34;
} else {
object.z = -object.position.z;
}
}
scene.__webglSprites.sort( painterSort );
// render all sprites
for ( o = 0, ol = scene.__webglSprites.length; o < ol; o ++ ) {
object = scene.__webglSprites[ o ];
if ( !object.visible || object.opacity === 0 ) continue;
if ( object.map && object.map.image && object.map.image.width ) {
if ( object.useScreenCoordinates ) {
_gl.uniform1i( uniforms.useScreenCoordinates, 1 );
_gl.uniform3f( uniforms.screenPosition, ( object.position.x - halfViewportWidth ) / halfViewportWidth,
( halfViewportHeight - object.position.y ) / halfViewportHeight,
Math.max( 0, Math.min( 1, object.position.z )));
} else {
_gl.uniform1i( uniforms.useScreenCoordinates, 0 );
_gl.uniform1i( uniforms.affectedByDistance, object.affectedByDistance ? 1 : 0 );
_gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object._modelViewMatrixArray );
}
size = object.map.image.width / ( object.scaleByViewport ? viewportHeight : 1 );
scale[ 0 ] = size * invAspect * object.scale.x;
scale[ 1 ] = size * object.scale.y;
_gl.uniform2f( uniforms.uvScale, object.uvScale.x, object.uvScale.y );
_gl.uniform2f( uniforms.uvOffset, object.uvOffset.x, object.uvOffset.y );
_gl.uniform2f( uniforms.alignment, object.alignment.x, object.alignment.y );
_gl.uniform1f( uniforms.opacity, object.opacity );
_gl.uniform3f( uniforms.color, object.color.r, object.color.g, object.color.b );
_gl.uniform1f( uniforms.rotation, object.rotation );
_gl.uniform2fv( uniforms.scale, scale );
if ( object.mergeWith3D && !mergeWith3D ) {
_gl.enable( _gl.DEPTH_TEST );
mergeWith3D = true;
} else if ( !object.mergeWith3D && mergeWith3D ) {
_gl.disable( _gl.DEPTH_TEST );
mergeWith3D = false;
}
_renderer.setBlending( object.blending );
_renderer.setTexture( object.map, 0 );
_gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
}
}
// restore gl
_gl.enable( _gl.CULL_FACE );
_gl.enable( _gl.DEPTH_TEST );
_gl.depthMask( true );
};
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 painterSort ( a, b ) {
return b.z - a.z;
};
};
\ No newline at end of file
/**
* @author mikael emtinger / http://gomo.se/
*
*/
THREE.ShaderSprite = {
'sprite': {
vertexShader: [
"uniform int useScreenCoordinates;",
"uniform int affectedByDistance;",
"uniform vec3 screenPosition;",
"uniform mat4 modelViewMatrix;",
"uniform mat4 projectionMatrix;",
"uniform float rotation;",
"uniform vec2 scale;",
"uniform vec2 alignment;",
"uniform vec2 uvOffset;",
"uniform vec2 uvScale;",
"attribute vec2 position;",
"attribute vec2 uv;",
"varying vec2 vUV;",
"void main() {",
"vUV = uvOffset + uv * uvScale;",
"vec2 alignedPosition = position + alignment;",
"vec2 rotatedPosition;",
"rotatedPosition.x = ( cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y ) * scale.x;",
"rotatedPosition.y = ( sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y ) * scale.y;",
"vec4 finalPosition;",
"if( useScreenCoordinates != 0 ) {",
"finalPosition = vec4( screenPosition.xy + rotatedPosition, screenPosition.z, 1.0 );",
"} else {",
"finalPosition = projectionMatrix * modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );",
"finalPosition.xy += rotatedPosition * ( affectedByDistance == 1 ? 1.0 : finalPosition.z );",
"}",
"gl_Position = finalPosition;",
"}"
].join( "\n" ),
fragmentShader: [
"#ifdef GL_ES",
"precision highp float;",
"#endif",
"uniform vec3 color;",
"uniform sampler2D map;",
"uniform float opacity;",
"varying vec2 vUV;",
"void main() {",
"vec4 texture = texture2D( map, vUV );",
"gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );",
"}"
].join( "\n" )
}
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment