1 | /**
|
---|
2 | * @author mikael emtinger / http://gomo.se/
|
---|
3 | * @author alteredq / http://alteredqualia.com/
|
---|
4 | */
|
---|
5 |
|
---|
6 | THREE.SpritePlugin = function () {
|
---|
7 |
|
---|
8 | var _gl, _renderer, _texture;
|
---|
9 |
|
---|
10 | var vertices, faces, vertexBuffer, elementBuffer;
|
---|
11 | var program, attributes, uniforms;
|
---|
12 |
|
---|
13 | this.init = function ( renderer ) {
|
---|
14 |
|
---|
15 | _gl = renderer.context;
|
---|
16 | _renderer = renderer;
|
---|
17 |
|
---|
18 | vertices = new Float32Array( [
|
---|
19 | - 0.5, - 0.5, 0, 0,
|
---|
20 | 0.5, - 0.5, 1, 0,
|
---|
21 | 0.5, 0.5, 1, 1,
|
---|
22 | - 0.5, 0.5, 0, 1
|
---|
23 | ] );
|
---|
24 |
|
---|
25 | faces = new Uint16Array( [
|
---|
26 | 0, 1, 2,
|
---|
27 | 0, 2, 3
|
---|
28 | ] );
|
---|
29 |
|
---|
30 | vertexBuffer = _gl.createBuffer();
|
---|
31 | elementBuffer = _gl.createBuffer();
|
---|
32 |
|
---|
33 | _gl.bindBuffer( _gl.ARRAY_BUFFER, vertexBuffer );
|
---|
34 | _gl.bufferData( _gl.ARRAY_BUFFER, vertices, _gl.STATIC_DRAW );
|
---|
35 |
|
---|
36 | _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
|
---|
37 | _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, faces, _gl.STATIC_DRAW );
|
---|
38 |
|
---|
39 | program = createProgram();
|
---|
40 |
|
---|
41 | attributes = {
|
---|
42 | position: _gl.getAttribLocation ( program, 'position' ),
|
---|
43 | uv: _gl.getAttribLocation ( program, 'uv' )
|
---|
44 | };
|
---|
45 |
|
---|
46 | uniforms = {
|
---|
47 | uvOffset: _gl.getUniformLocation( program, 'uvOffset' ),
|
---|
48 | uvScale: _gl.getUniformLocation( program, 'uvScale' ),
|
---|
49 |
|
---|
50 | rotation: _gl.getUniformLocation( program, 'rotation' ),
|
---|
51 | scale: _gl.getUniformLocation( program, 'scale' ),
|
---|
52 |
|
---|
53 | color: _gl.getUniformLocation( program, 'color' ),
|
---|
54 | map: _gl.getUniformLocation( program, 'map' ),
|
---|
55 | opacity: _gl.getUniformLocation( program, 'opacity' ),
|
---|
56 |
|
---|
57 | modelViewMatrix: _gl.getUniformLocation( program, 'modelViewMatrix' ),
|
---|
58 | projectionMatrix: _gl.getUniformLocation( program, 'projectionMatrix' ),
|
---|
59 |
|
---|
60 | fogType: _gl.getUniformLocation( program, 'fogType' ),
|
---|
61 | fogDensity: _gl.getUniformLocation( program, 'fogDensity' ),
|
---|
62 | fogNear: _gl.getUniformLocation( program, 'fogNear' ),
|
---|
63 | fogFar: _gl.getUniformLocation( program, 'fogFar' ),
|
---|
64 | fogColor: _gl.getUniformLocation( program, 'fogColor' ),
|
---|
65 |
|
---|
66 | alphaTest: _gl.getUniformLocation( program, 'alphaTest' )
|
---|
67 | };
|
---|
68 |
|
---|
69 | var canvas = document.createElement( 'canvas' );
|
---|
70 | canvas.width = 8;
|
---|
71 | canvas.height = 8;
|
---|
72 |
|
---|
73 | var context = canvas.getContext( '2d' );
|
---|
74 | context.fillStyle = '#ffffff';
|
---|
75 | context.fillRect( 0, 0, canvas.width, canvas.height );
|
---|
76 |
|
---|
77 | _texture = new THREE.Texture( canvas );
|
---|
78 | _texture.needsUpdate = true;
|
---|
79 |
|
---|
80 | };
|
---|
81 |
|
---|
82 | this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
|
---|
83 |
|
---|
84 | var sprites = scene.__webglSprites,
|
---|
85 | nSprites = sprites.length;
|
---|
86 |
|
---|
87 | if ( ! nSprites ) return;
|
---|
88 |
|
---|
89 | // setup gl
|
---|
90 |
|
---|
91 | _gl.useProgram( program );
|
---|
92 |
|
---|
93 | _gl.enableVertexAttribArray( attributes.position );
|
---|
94 | _gl.enableVertexAttribArray( attributes.uv );
|
---|
95 |
|
---|
96 | _gl.disable( _gl.CULL_FACE );
|
---|
97 | _gl.enable( _gl.BLEND );
|
---|
98 |
|
---|
99 | _gl.bindBuffer( _gl.ARRAY_BUFFER, vertexBuffer );
|
---|
100 | _gl.vertexAttribPointer( attributes.position, 2, _gl.FLOAT, false, 2 * 8, 0 );
|
---|
101 | _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 );
|
---|
102 |
|
---|
103 | _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
|
---|
104 |
|
---|
105 | _gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
|
---|
106 |
|
---|
107 | _gl.activeTexture( _gl.TEXTURE0 );
|
---|
108 | _gl.uniform1i( uniforms.map, 0 );
|
---|
109 |
|
---|
110 | var oldFogType = 0;
|
---|
111 | var sceneFogType = 0;
|
---|
112 | var fog = scene.fog;
|
---|
113 |
|
---|
114 | if ( fog ) {
|
---|
115 |
|
---|
116 | _gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
|
---|
117 |
|
---|
118 | if ( fog instanceof THREE.Fog ) {
|
---|
119 |
|
---|
120 | _gl.uniform1f( uniforms.fogNear, fog.near );
|
---|
121 | _gl.uniform1f( uniforms.fogFar, fog.far );
|
---|
122 |
|
---|
123 | _gl.uniform1i( uniforms.fogType, 1 );
|
---|
124 | oldFogType = 1;
|
---|
125 | sceneFogType = 1;
|
---|
126 |
|
---|
127 | } else if ( fog instanceof THREE.FogExp2 ) {
|
---|
128 |
|
---|
129 | _gl.uniform1f( uniforms.fogDensity, fog.density );
|
---|
130 |
|
---|
131 | _gl.uniform1i( uniforms.fogType, 2 );
|
---|
132 | oldFogType = 2;
|
---|
133 | sceneFogType = 2;
|
---|
134 |
|
---|
135 | }
|
---|
136 |
|
---|
137 | } else {
|
---|
138 |
|
---|
139 | _gl.uniform1i( uniforms.fogType, 0 );
|
---|
140 | oldFogType = 0;
|
---|
141 | sceneFogType = 0;
|
---|
142 |
|
---|
143 | }
|
---|
144 |
|
---|
145 |
|
---|
146 | // update positions and sort
|
---|
147 |
|
---|
148 | var i, sprite, material, fogType, scale = [];
|
---|
149 |
|
---|
150 | for( i = 0; i < nSprites; i ++ ) {
|
---|
151 |
|
---|
152 | sprite = sprites[ i ];
|
---|
153 | material = sprite.material;
|
---|
154 |
|
---|
155 | if ( sprite.visible === false ) continue;
|
---|
156 |
|
---|
157 | sprite._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
|
---|
158 | sprite.z = - sprite._modelViewMatrix.elements[ 14 ];
|
---|
159 |
|
---|
160 | }
|
---|
161 |
|
---|
162 | sprites.sort( painterSortStable );
|
---|
163 |
|
---|
164 | // render all sprites
|
---|
165 |
|
---|
166 | for( i = 0; i < nSprites; i ++ ) {
|
---|
167 |
|
---|
168 | sprite = sprites[ i ];
|
---|
169 |
|
---|
170 | if ( sprite.visible === false ) continue;
|
---|
171 |
|
---|
172 | material = sprite.material;
|
---|
173 |
|
---|
174 | _gl.uniform1f( uniforms.alphaTest, material.alphaTest );
|
---|
175 | _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite._modelViewMatrix.elements );
|
---|
176 |
|
---|
177 | scale[ 0 ] = sprite.scale.x;
|
---|
178 | scale[ 1 ] = sprite.scale.y;
|
---|
179 |
|
---|
180 | if ( scene.fog && material.fog ) {
|
---|
181 |
|
---|
182 | fogType = sceneFogType;
|
---|
183 |
|
---|
184 | } else {
|
---|
185 |
|
---|
186 | fogType = 0;
|
---|
187 |
|
---|
188 | }
|
---|
189 |
|
---|
190 | if ( oldFogType !== fogType ) {
|
---|
191 |
|
---|
192 | _gl.uniform1i( uniforms.fogType, fogType );
|
---|
193 | oldFogType = fogType;
|
---|
194 |
|
---|
195 | }
|
---|
196 |
|
---|
197 | if ( material.map !== null ) {
|
---|
198 |
|
---|
199 | _gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y );
|
---|
200 | _gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y );
|
---|
201 |
|
---|
202 | } else {
|
---|
203 |
|
---|
204 | _gl.uniform2f( uniforms.uvOffset, 0, 0 );
|
---|
205 | _gl.uniform2f( uniforms.uvScale, 1, 1 );
|
---|
206 |
|
---|
207 | }
|
---|
208 |
|
---|
209 | _gl.uniform1f( uniforms.opacity, material.opacity );
|
---|
210 | _gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
|
---|
211 |
|
---|
212 | _gl.uniform1f( uniforms.rotation, material.rotation );
|
---|
213 | _gl.uniform2fv( uniforms.scale, scale );
|
---|
214 |
|
---|
215 | _renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
|
---|
216 | _renderer.setDepthTest( material.depthTest );
|
---|
217 | _renderer.setDepthWrite( material.depthWrite );
|
---|
218 |
|
---|
219 | if ( material.map && material.map.image && material.map.image.width ) {
|
---|
220 |
|
---|
221 | _renderer.setTexture( material.map, 0 );
|
---|
222 |
|
---|
223 | } else {
|
---|
224 |
|
---|
225 | _renderer.setTexture( _texture, 0 );
|
---|
226 |
|
---|
227 | }
|
---|
228 |
|
---|
229 | _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
|
---|
230 |
|
---|
231 | }
|
---|
232 |
|
---|
233 | // restore gl
|
---|
234 |
|
---|
235 | _gl.enable( _gl.CULL_FACE );
|
---|
236 |
|
---|
237 | };
|
---|
238 |
|
---|
239 | function createProgram () {
|
---|
240 |
|
---|
241 | var program = _gl.createProgram();
|
---|
242 |
|
---|
243 | var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
|
---|
244 | var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
|
---|
245 |
|
---|
246 | _gl.shaderSource( vertexShader, [
|
---|
247 |
|
---|
248 | 'precision ' + _renderer.getPrecision() + ' float;',
|
---|
249 |
|
---|
250 | 'uniform mat4 modelViewMatrix;',
|
---|
251 | 'uniform mat4 projectionMatrix;',
|
---|
252 | 'uniform float rotation;',
|
---|
253 | 'uniform vec2 scale;',
|
---|
254 | 'uniform vec2 uvOffset;',
|
---|
255 | 'uniform vec2 uvScale;',
|
---|
256 |
|
---|
257 | 'attribute vec2 position;',
|
---|
258 | 'attribute vec2 uv;',
|
---|
259 |
|
---|
260 | 'varying vec2 vUV;',
|
---|
261 |
|
---|
262 | 'void main() {',
|
---|
263 |
|
---|
264 | 'vUV = uvOffset + uv * uvScale;',
|
---|
265 |
|
---|
266 | 'vec2 alignedPosition = position * scale;',
|
---|
267 |
|
---|
268 | 'vec2 rotatedPosition;',
|
---|
269 | 'rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;',
|
---|
270 | 'rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;',
|
---|
271 |
|
---|
272 | 'vec4 finalPosition;',
|
---|
273 |
|
---|
274 | 'finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );',
|
---|
275 | 'finalPosition.xy += rotatedPosition;',
|
---|
276 | 'finalPosition = projectionMatrix * finalPosition;',
|
---|
277 |
|
---|
278 | 'gl_Position = finalPosition;',
|
---|
279 |
|
---|
280 | '}'
|
---|
281 |
|
---|
282 | ].join( '\n' ) );
|
---|
283 |
|
---|
284 | _gl.shaderSource( fragmentShader, [
|
---|
285 |
|
---|
286 | 'precision ' + _renderer.getPrecision() + ' float;',
|
---|
287 |
|
---|
288 | 'uniform vec3 color;',
|
---|
289 | 'uniform sampler2D map;',
|
---|
290 | 'uniform float opacity;',
|
---|
291 |
|
---|
292 | 'uniform int fogType;',
|
---|
293 | 'uniform vec3 fogColor;',
|
---|
294 | 'uniform float fogDensity;',
|
---|
295 | 'uniform float fogNear;',
|
---|
296 | 'uniform float fogFar;',
|
---|
297 | 'uniform float alphaTest;',
|
---|
298 |
|
---|
299 | 'varying vec2 vUV;',
|
---|
300 |
|
---|
301 | 'void main() {',
|
---|
302 |
|
---|
303 | 'vec4 texture = texture2D( map, vUV );',
|
---|
304 |
|
---|
305 | 'if ( texture.a < alphaTest ) discard;',
|
---|
306 |
|
---|
307 | 'gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );',
|
---|
308 |
|
---|
309 | 'if ( fogType > 0 ) {',
|
---|
310 |
|
---|
311 | 'float depth = gl_FragCoord.z / gl_FragCoord.w;',
|
---|
312 | 'float fogFactor = 0.0;',
|
---|
313 |
|
---|
314 | 'if ( fogType == 1 ) {',
|
---|
315 |
|
---|
316 | 'fogFactor = smoothstep( fogNear, fogFar, depth );',
|
---|
317 |
|
---|
318 | '} else {',
|
---|
319 |
|
---|
320 | 'const float LOG2 = 1.442695;',
|
---|
321 | 'float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );',
|
---|
322 | 'fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );',
|
---|
323 |
|
---|
324 | '}',
|
---|
325 |
|
---|
326 | 'gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );',
|
---|
327 |
|
---|
328 | '}',
|
---|
329 |
|
---|
330 | '}'
|
---|
331 |
|
---|
332 | ].join( '\n' ) );
|
---|
333 |
|
---|
334 | _gl.compileShader( vertexShader );
|
---|
335 | _gl.compileShader( fragmentShader );
|
---|
336 |
|
---|
337 | _gl.attachShader( program, vertexShader );
|
---|
338 | _gl.attachShader( program, fragmentShader );
|
---|
339 |
|
---|
340 | _gl.linkProgram( program );
|
---|
341 |
|
---|
342 | return program;
|
---|
343 |
|
---|
344 | };
|
---|
345 |
|
---|
346 | function painterSortStable ( a, b ) {
|
---|
347 |
|
---|
348 | if ( a.z !== b.z ) {
|
---|
349 |
|
---|
350 | return b.z - a.z;
|
---|
351 |
|
---|
352 | } else {
|
---|
353 |
|
---|
354 | return b.id - a.id;
|
---|
355 |
|
---|
356 | }
|
---|
357 |
|
---|
358 | };
|
---|
359 |
|
---|
360 | };
|
---|