提交 782bf526 编写于 作者: M Mugen87

WebGLRenderer: Removed WebGLSpriteRenderer

上级 8e39dd1d
......@@ -25,8 +25,8 @@ function SpriteMaterial( parameters ) {
this.rotation = 0;
this.fog = false;
this.lights = false;
this.transparent = true;
this.setValues( parameters );
......
......@@ -2,6 +2,10 @@ import { Vector2 } from '../math/Vector2.js';
import { Vector3 } from '../math/Vector3.js';
import { Matrix4 } from '../math/Matrix4.js';
import { Object3D } from '../core/Object3D.js';
import { BufferGeometry } from '../core/BufferGeometry.js';
import { InterleavedBuffer } from '../core/InterleavedBuffer.js';
import { InterleavedBufferAttribute } from '../core/InterleavedBufferAttribute.js';
import { TrianglesDrawMode } from '../constants.js';
import { SpriteMaterial } from '../materials/SpriteMaterial.js';
/**
......@@ -16,9 +20,12 @@ function Sprite( material ) {
this.type = 'Sprite';
this.material = ( material !== undefined ) ? material : new SpriteMaterial();
this.geometry = SpriteGeometry;
this.center = new Vector2( 0.5, 0.5 );
this.drawMode = TrianglesDrawMode;
}
Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
......@@ -141,5 +148,27 @@ Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
} );
//
var SpriteGeometry = ( function () {
var geometry = new BufferGeometry();
var float32Array = new Float32Array( [
- 0.5, - 0.5, 0, 0, 0,
0.5, - 0.5, 0, 1, 0,
0.5, 0.5, 0, 1, 1,
- 0.5, 0.5, 0, 0, 1
] );
var interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
geometry.addAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
geometry.addAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
return geometry;
} )();
export { Sprite };
......@@ -37,7 +37,6 @@ import { WebGLProperties } from './webgl/WebGLProperties.js';
import { WebGLRenderLists } from './webgl/WebGLRenderLists.js';
import { WebGLRenderStates } from './webgl/WebGLRenderStates.js';
import { WebGLShadowMap } from './webgl/WebGLShadowMap.js';
import { WebGLSpriteRenderer } from './webgl/WebGLSpriteRenderer.js';
import { WebGLState } from './webgl/WebGLState.js';
import { WebGLTextures } from './webgl/WebGLTextures.js';
import { WebGLUniforms } from './webgl/WebGLUniforms.js';
......@@ -234,7 +233,6 @@ function WebGLRenderer( parameters ) {
var programCache, renderLists, renderStates;
var background, morphtargets, bufferRenderer, indexedBufferRenderer;
var spriteRenderer;
var utils;
......@@ -274,8 +272,6 @@ function WebGLRenderer( parameters ) {
bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info );
indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info );
spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities );
info.programs = programCache.programs;
_this.context = _gl;
......@@ -766,7 +762,7 @@ function WebGLRenderer( parameters ) {
//
if ( object.isMesh ) {
if ( object.isMesh || object.isSprite ) {
if ( material.wireframe === true ) {
......@@ -1130,6 +1126,7 @@ function WebGLRenderer( parameters ) {
var opaqueObjects = currentRenderList.opaque;
var transparentObjects = currentRenderList.transparent;
var spritesObjects = currentRenderList.sprites;
if ( scene.overrideMaterial ) {
......@@ -1137,6 +1134,7 @@ function WebGLRenderer( parameters ) {
if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial );
if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial );
if ( spritesObjects.length ) renderObjects( spritesObjects, scene, camera, overrideMaterial );
} else {
......@@ -1148,13 +1146,11 @@ function WebGLRenderer( parameters ) {
if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera );
}
// custom renderers
//
var spritesArray = currentRenderState.state.spritesArray;
if ( spritesObjects.length ) renderObjects( spritesObjects, scene, camera );
spriteRenderer.render( spritesArray, scene, camera );
}
// Generate mipmap if we're using any kind of mipmap filtering
......@@ -1264,7 +1260,19 @@ function WebGLRenderer( parameters ) {
if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
currentRenderState.pushSprite( object );
if ( sortObjects ) {
_vector3.setFromMatrixPosition( object.matrixWorld )
.applyMatrix4( _projScreenMatrix );
var material = object.material;
}
var geometry = objects.update( object );
var material = object.material;
currentRenderList.push( object, geometry, material, _vector3.z, null );
}
......@@ -1872,6 +1880,10 @@ function WebGLRenderer( parameters ) {
refreshUniformsPoints( m_uniforms, material );
} else if ( material.isSpriteMaterial ) {
refreshUniformsSprites( m_uniforms, material );
} else if ( material.isShadowMaterial ) {
m_uniforms.color.value = material.color;
......@@ -1896,6 +1908,12 @@ function WebGLRenderer( parameters ) {
}
if ( material.isSpriteMaterial ) {
p_uniforms.setValue( _gl, 'center', object.center );
}
// common matrices
p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
......@@ -2080,6 +2098,27 @@ function WebGLRenderer( parameters ) {
}
function refreshUniformsSprites( uniforms, material ) {
uniforms.diffuse.value = material.color;
uniforms.opacity.value = material.opacity;
uniforms.rotation.value = material.rotation;
uniforms.map.value = material.map;
if ( material.map !== null ) {
if ( material.map.matrixAutoUpdate === true ) {
material.map.updateMatrix();
}
uniforms.uvTransform.value.copy( material.map.matrix );
}
}
function refreshUniformsFog( uniforms, fog ) {
uniforms.fogColor.value = fog.color;
......
......@@ -112,6 +112,8 @@ import points_frag from './ShaderLib/points_frag.glsl';
import points_vert from './ShaderLib/points_vert.glsl';
import shadow_frag from './ShaderLib/shadow_frag.glsl';
import shadow_vert from './ShaderLib/shadow_vert.glsl';
import sprite_frag from './ShaderLib/sprite_frag.glsl';
import sprite_vert from './ShaderLib/sprite_vert.glsl';
export var ShaderChunk = {
alphamap_fragment: alphamap_fragment,
......@@ -227,5 +229,7 @@ export var ShaderChunk = {
points_frag: points_frag,
points_vert: points_vert,
shadow_frag: shadow_frag,
shadow_vert: shadow_vert
shadow_vert: shadow_vert,
sprite_frag: sprite_frag,
sprite_vert: sprite_vert
};
......@@ -162,6 +162,18 @@ var ShaderLib = {
},
sprite: {
uniforms: UniformsUtils.merge( [
UniformsLib.sprite,
UniformsLib.fog
] ),
vertexShader: ShaderChunk.sprite_vert,
fragmentShader: ShaderChunk.sprite_frag
},
/* -------------------------------------------------------------------------
// Cube map shader
------------------------------------------------------------------------- */
......
......@@ -182,6 +182,17 @@ var UniformsLib = {
map: { value: null },
uvTransform: { value: new Matrix3() }
},
sprite: {
diffuse: { value: new Color( 0xeeeeee ) },
opacity: { value: 1.0 },
center: { value: new Vector2( 0.5, 0.5 ) },
rotation: { value: 0.0 },
map: { value: null },
uvTransform: { value: new Matrix3() }
}
};
......
......@@ -22,7 +22,8 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
LineBasicMaterial: 'basic',
LineDashedMaterial: 'dashed',
PointsMaterial: 'points',
ShadowMaterial: 'shadow'
ShadowMaterial: 'shadow',
SpriteMaterial: 'sprite'
};
var parameterNames = [
......
......@@ -46,6 +46,25 @@ function reversePainterSortStable( a, b ) {
}
function painterSortStableSprites( a, b ) {
if ( a.renderOrder !== b.renderOrder ) {
return a.renderOrder - b.renderOrder;
} else if ( a.z !== b.z ) {
return b.z - a.z;
} else {
return b.id - a.id;
}
}
function WebGLRenderList() {
var renderItems = [];
......@@ -53,6 +72,7 @@ function WebGLRenderList() {
var opaque = [];
var transparent = [];
var sprites = [];
function init() {
......@@ -60,6 +80,7 @@ function WebGLRenderList() {
opaque.length = 0;
transparent.length = 0;
sprites.length = 0;
}
......@@ -95,7 +116,15 @@ function WebGLRenderList() {
}
( material.transparent === true ? transparent : opaque ).push( renderItem );
if ( object.isSprite ) {
sprites.push( renderItem );
} else {
( material.transparent === true ? transparent : opaque ).push( renderItem );
}
renderItemsIndex ++;
......@@ -105,12 +134,14 @@ function WebGLRenderList() {
if ( opaque.length > 1 ) opaque.sort( painterSortStable );
if ( transparent.length > 1 ) transparent.sort( reversePainterSortStable );
if ( sprites.length > 1 ) sprites.sort( painterSortStableSprites );
}
return {
opaque: opaque,
transparent: transparent,
sprites: sprites,
init: init,
push: push,
......
......@@ -10,13 +10,11 @@ function WebGLRenderState() {
var lightsArray = [];
var shadowsArray = [];
var spritesArray = [];
function init() {
lightsArray.length = 0;
shadowsArray.length = 0;
spritesArray.length = 0;
}
......@@ -32,12 +30,6 @@ function WebGLRenderState() {
}
function pushSprite( sprite ) {
spritesArray.push( sprite );
}
function setupLights( camera ) {
lights.setup( lightsArray, shadowsArray, camera );
......@@ -47,7 +39,6 @@ function WebGLRenderState() {
var state = {
lightsArray: lightsArray,
shadowsArray: shadowsArray,
spritesArray: spritesArray,
lights: lights
};
......@@ -58,8 +49,7 @@ function WebGLRenderState() {
setupLights: setupLights,
pushLight: pushLight,
pushShadow: pushShadow,
pushSprite: pushSprite
pushShadow: pushShadow
};
}
......
/**
* @author mikael emtinger / http://gomo.se/
* @author alteredq / http://alteredqualia.com/
*/
import { CanvasTexture } from '../../textures/CanvasTexture.js';
import { Vector3 } from '../../math/Vector3.js';
import { Quaternion } from '../../math/Quaternion.js';
function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) {
var vertexBuffer, elementBuffer;
var program, attributes, uniforms;
var texture;
// decompose matrixWorld
var spritePosition = new Vector3();
var spriteRotation = new Quaternion();
var spriteScale = new Vector3();
function init() {
var 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
] );
var 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' ),
center: gl.getUniformLocation( program, 'center' ),
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' ),
fogDepth: gl.getUniformLocation( program, 'fogDepth' ),
alphaTest: gl.getUniformLocation( program, 'alphaTest' )
};
var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
canvas.width = 8;
canvas.height = 8;
var context = canvas.getContext( '2d' );
context.fillStyle = 'white';
context.fillRect( 0, 0, 8, 8 );
texture = new CanvasTexture( canvas );
}
this.render = function ( sprites, scene, camera ) {
if ( sprites.length === 0 ) return;
// setup gl
if ( program === undefined ) {
init();
}
state.useProgram( program );
state.initAttributes();
state.enableAttribute( attributes.position );
state.enableAttribute( attributes.uv );
state.disableUnusedAttributes();
state.disable( gl.CULL_FACE );
state.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 );
state.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.isFog ) {
gl.uniform1f( uniforms.fogNear, fog.near );
gl.uniform1f( uniforms.fogFar, fog.far );
gl.uniform1i( uniforms.fogType, 1 );
oldFogType = 1;
sceneFogType = 1;
} else if ( fog.isFogExp2 ) {
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
for ( var i = 0, l = sprites.length; i < l; i ++ ) {
var sprite = sprites[ i ];
sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
sprite.z = - sprite.modelViewMatrix.elements[ 14 ];
}
sprites.sort( painterSortStable );
// render all sprites
var scale = [];
var center = [];
for ( var i = 0, l = sprites.length; i < l; i ++ ) {
var sprite = sprites[ i ];
var material = sprite.material;
if ( material.visible === false ) continue;
sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined );
gl.uniform1f( uniforms.alphaTest, material.alphaTest );
gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements );
sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale );
scale[ 0 ] = spriteScale.x;
scale[ 1 ] = spriteScale.y;
center[ 0 ] = sprite.center.x - 0.5;
center[ 1 ] = sprite.center.y - 0.5;
var fogType = 0;
if ( scene.fog && material.fog ) {
fogType = sceneFogType;
}
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.center, center );
gl.uniform2fv( uniforms.scale, scale );
state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
state.buffers.depth.setTest( material.depthTest );
state.buffers.depth.setMask( material.depthWrite );
state.buffers.color.setMask( material.colorWrite );
textures.setTexture2D( material.map || texture, 0 );
gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined );
}
// restore gl
state.enable( gl.CULL_FACE );
state.reset();
};
function createProgram() {
var program = gl.createProgram();
var vertexShader = gl.createShader( gl.VERTEX_SHADER );
var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
gl.shaderSource( vertexShader, [
'precision ' + capabilities.precision + ' float;',
'#define SHADER_NAME ' + 'SpriteMaterial',
'uniform mat4 modelViewMatrix;',
'uniform mat4 projectionMatrix;',
'uniform float rotation;',
'uniform vec2 center;',
'uniform vec2 scale;',
'uniform vec2 uvOffset;',
'uniform vec2 uvScale;',
'attribute vec2 position;',
'attribute vec2 uv;',
'varying vec2 vUV;',
'varying float fogDepth;',
'void main() {',
' vUV = uvOffset + uv * uvScale;',
' vec2 alignedPosition = ( position - center ) * scale;',
' vec2 rotatedPosition;',
' rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;',
' rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;',
' vec4 mvPosition;',
' mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );',
' mvPosition.xy += rotatedPosition;',
' gl_Position = projectionMatrix * mvPosition;',
' fogDepth = - mvPosition.z;',
'}'
].join( '\n' ) );
gl.shaderSource( fragmentShader, [
'precision ' + capabilities.precision + ' float;',
'#define SHADER_NAME ' + 'SpriteMaterial',
'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;',
'varying float fogDepth;',
'void main() {',
' vec4 texture = texture2D( map, vUV );',
' gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );',
' if ( gl_FragColor.a < alphaTest ) discard;',
' if ( fogType > 0 ) {',
' float fogFactor = 0.0;',
' if ( fogType == 1 ) {',
' fogFactor = smoothstep( fogNear, fogFar, fogDepth );',
' } else {',
' const float LOG2 = 1.442695;',
' fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );',
' fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );',
' }',
' gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, 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.renderOrder !== b.renderOrder ) {
return a.renderOrder - b.renderOrder;
} else if ( a.z !== b.z ) {
return b.z - a.z;
} else {
return b.id - a.id;
}
}
}
export { WebGLSpriteRenderer };
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册