WebGLRenderer.js 131.1 KB
Newer Older
N
Nicolas Garcia Belmonte 已提交
1 2 3
/**
 * @author supereggbert / http://www.paulbrunt.co.uk/
 * @author mrdoob / http://mrdoob.com/
4
 * @author alteredq / http://alteredqualia.com/
5
 * @author szimek / https://github.com/szimek/
N
Nicolas Garcia Belmonte 已提交
6 7
 */

8
THREE.WebGLRenderer = function ( parameters ) {
M
Mr.doob 已提交
9

10 11 12
	// By default you can use just up to 4 directional / point lights total.
	// ANGLE implementation (Chrome/Firefox on Windows) is bound to
	// 10 varying vectors due to DirectX9 limitation.
M
Mr.doob 已提交
13

14
	var _this = this,
15
	_gl, _programs = [],
16 17
	_currentProgram = null,
	_currentFramebuffer = null,
18
	_currentDepthMask = true,
M
Mr.doob 已提交
19

A
alteredq 已提交
20
	// gl state cache
21

22 23
	_oldDoubleSided = null,
	_oldFlipSided = null,
A
alteredq 已提交
24
	_oldBlending = null,
A
alteredq 已提交
25
	_oldDepth = null,
26 27 28
	_oldPolygonOffset = null,
	_oldPolygonOffsetFactor = null,
	_oldPolygonOffsetUnits = null,
M
Mikael Emtinger 已提交
29
	_cullEnabled = true,
30

31 32 33 34 35
	_viewportX = 0,
	_viewportY = 0,
	_viewportWidth = 0,
	_viewportHeight = 0,

36
	// camera matrices caches
37 38

	_frustum = [
39 40 41 42 43 44 45 46
		new THREE.Vector4(),
		new THREE.Vector4(),
		new THREE.Vector4(),
		new THREE.Vector4(),
		new THREE.Vector4(),
		new THREE.Vector4()
	 ],

47
	_projScreenMatrix = new THREE.Matrix4(),
48
	_projectionMatrixArray = new Float32Array( 16 ),
49
	_viewMatrixArray = new Float32Array( 16 ),
50

51
	_vector3 = new THREE.Vector4(),
52

A
alteredq 已提交
53
	// light arrays cache
54

A
alteredq 已提交
55 56
	_lights = {

57
		ambient: [ 0, 0, 0 ],
A
alteredq 已提交
58
		directional: { length: 0, colors: new Array(), positions: new Array() },
59
		point: { length: 0, colors: new Array(), positions: new Array(), distances: new Array() }
A
alteredq 已提交
60 61 62

	},

63
	// parameters
64

65
	parameters = parameters || {},
M
Mr.doob 已提交
66

67 68
	_canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
	_stencil = parameters.stencil !== undefined ? parameters.stencil : true,
69
	_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
70 71 72
	_antialias = parameters.antialias !== undefined ? parameters.antialias : false,
	_clearColor = parameters.clearColor !== undefined ? new THREE.Color( parameters.clearColor ) : new THREE.Color( 0x000000 ),
	_clearAlpha = parameters.clearAlpha !== undefined ? parameters.clearAlpha : 0;
73
	_maxLights = parameters.maxLights !== undefined ? parameters.maxLights : 4;
M
Mr.doob 已提交
74

75 76 77
	this.data = {

		vertices: 0,
78 79
		faces: 0,
		drawCalls: 0
80

81
	};
M
Mr.doob 已提交
82

83
	this.maxMorphTargets = 8;
N
Nicolas Garcia Belmonte 已提交
84 85
	this.domElement = _canvas;
	this.autoClear = true;
86
	this.sortObjects = true;
N
Nicolas Garcia Belmonte 已提交
87

88 89 90 91 92 93 94 95 96 97 98
	// shadow map

	this.shadowMapBias = 0.0039;
	this.shadowMapDarkness = 0.5;
	this.shadowMapWidth = 512;
	this.shadowMapHeight = 512;

	this.shadowCameraNear = 1;
	this.shadowCameraFar = 5000;
	this.shadowCameraFov = 50;

99
	this.shadowMap = [];
100
	this.shadowMapEnabled = false;
101
	this.shadowMapSoft = true;
102

M
Mr.doob 已提交
103
	var _cameraLight, _shadowMatrix = [];
104 105 106 107

	var depthShader = THREE.ShaderLib[ "depthRGBA" ];
	var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );

M
Mr.doob 已提交
108
	var _depthMaterial = new THREE.MeshShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } );
109

M
Mr.doob 已提交
110
	var _depthMaterialMorph = new THREE.MeshShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true } );
111 112 113 114

	_depthMaterial._shadowPass = true;
	_depthMaterialMorph._shadowPass = true;

115 116 117 118
	// Init GL

	try {

119
		if ( ! ( _gl = _canvas.getContext( 'experimental-webgl', { antialias: _antialias, stencil: _stencil, preserveDrawingBuffer: _preserveDrawingBuffer } ) ) ) {
120 121 122 123 124

			throw 'Error creating WebGL context.';

		}

M
Mr.doob 已提交
125 126 127 128 129 130 131 132
		console.log(
			navigator.userAgent + " | " +
			_gl.getParameter( _gl.VERSION ) + " | " +
			_gl.getParameter( _gl.VENDOR ) + " | " +
			_gl.getParameter( _gl.RENDERER ) + " | " +
			_gl.getParameter( _gl.SHADING_LANGUAGE_VERSION )
		);

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
	} catch ( error ) {

		console.error( error );

	}

	_gl.clearColor( 0, 0, 0, 1 );
	_gl.clearDepth( 1 );

	_gl.enable( _gl.DEPTH_TEST );
	_gl.depthFunc( _gl.LEQUAL );

	_gl.frontFace( _gl.CCW );
	_gl.cullFace( _gl.BACK );
	_gl.enable( _gl.CULL_FACE );

	_gl.enable( _gl.BLEND );
	_gl.blendEquation( _gl.FUNC_ADD );
	_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA );

	_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );

	_cullEnabled = true;

	//
M
Mr.doob 已提交
158

159 160
	this.context = _gl;

A
alteredq 已提交
161
	var _supportsVertexTextures = ( maxVertexTextures() > 0 );
M
Mikael Emtinger 已提交
162

M
Mikael Emtinger 已提交
163
	// prepare sprites
M
Mr.doob 已提交
164 165

	var _sprite = {};
M
Mikael Emtinger 已提交
166 167 168 169 170

	_sprite.vertices = new Float32Array( 8 + 8 );
	_sprite.faces    = new Uint16Array( 6 );

	i = 0;
M
Mr.doob 已提交
171 172 173 174 175 176 177 178 179 180 181 182

	_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
M
Mikael Emtinger 已提交
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204

	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 = _gl.createProgram();
	_gl.attachShader( _sprite.program, getShader( "fragment", THREE.ShaderLib.sprite.fragmentShader ));
	_gl.attachShader( _sprite.program, getShader( "vertex",   THREE.ShaderLib.sprite.vertexShader   ));
	_gl.linkProgram( _sprite.program );

	_sprite.attributes = {};
	_sprite.uniforms = {};
205 206 207 208 209 210 211 212 213 214 215 216 217 218
	_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.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" );
M
Mikael Emtinger 已提交
219

M
Mr.doob 已提交
220 221
	//_gl.enableVertexAttribArray( _sprite.attributes.position );
	//_gl.enableVertexAttribArray( _sprite.attributes.uv );
M
Mikael Emtinger 已提交
222

M
Mr.doob 已提交
223
	var _spriteAttributesEnabled = false;
M
Mikael Emtinger 已提交
224

N
Nicolas Garcia Belmonte 已提交
225 226 227 228
	this.setSize = function ( width, height ) {

		_canvas.width = width;
		_canvas.height = height;
229

230 231 232
		this.setViewport( 0, 0, _canvas.width, _canvas.height );

	};
N
Nicolas Garcia Belmonte 已提交
233

234
	this.setViewport = function ( x, y, width, height ) {
235

236 237
		_viewportX = x;
		_viewportY = y;
238

239 240
		_viewportWidth = width;
		_viewportHeight = height;
241

242
		_gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
243

N
Nicolas Garcia Belmonte 已提交
244
	};
245

246
	this.setScissor = function ( x, y, width, height ) {
N
Nicolas Garcia Belmonte 已提交
247

248
		_gl.scissor( x, y, width, height );
249

250
	};
251

252
	this.enableScissorTest = function ( enable ) {
253

254 255 256 257
		if ( enable )
			_gl.enable( _gl.SCISSOR_TEST );
		else
			_gl.disable( _gl.SCISSOR_TEST );
258

259
	};
260

261
	this.enableDepthBufferWrite = function ( enable ) {
262

263
		_currentDepthMask = enable;
264 265 266
		_gl.depthMask( enable );

	};
267

268
	this.setClearColorHex = function ( hex, alpha ) {
269

270 271 272 273
		_clearColor.setHex( hex );
		_clearAlpha = alpha;

		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
274

275
	};
A
alteredq 已提交
276

277
	this.setClearColor = function ( color, alpha ) {
A
alteredq 已提交
278

279 280 281 282
		_clearColor.copy( color );
		_clearAlpha = alpha;

		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
A
alteredq 已提交
283 284

	};
285

N
Nicolas Garcia Belmonte 已提交
286 287
	this.clear = function () {

M
Mikael Emtinger 已提交
288
		_gl.clear( _gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT | _gl.STENCIL_BUFFER_BIT );
N
Nicolas Garcia Belmonte 已提交
289 290 291

	};

292
	this.getContext = function() {
293

294
		return _gl;
295

296
	};
M
Mr.doob 已提交
297

A
alteredq 已提交
298
	function setupLights ( program, lights ) {
299

300 301
		var l, ll, light, n,
		r = 0, g = 0, b = 0,
302
		color, position, intensity, distance,
M
Mr.doob 已提交
303

304
		zlights = _lights,
M
Mr.doob 已提交
305

306
		dcolors = zlights.directional.colors,
307
		dpositions = zlights.directional.positions,
308

309
		pcolors = zlights.point.colors,
310
		ppositions = zlights.point.positions,
311
		pdistances = zlights.point.distances,
312

313 314
		dlength = 0,
		plength = 0,
315

316 317
		doffset = 0,
		poffset = 0;
M
Mr.doob 已提交
318

319
		for ( l = 0, ll = lights.length; l < ll; l++ ) {
320

321
			light = lights[ l ];
322
			color = light.color;
323

324 325
			position = light.position;
			intensity = light.intensity;
326
			distance = light.distance;
327 328 329

			if ( light instanceof THREE.AmbientLight ) {

330 331 332
				r += color.r;
				g += color.g;
				b += color.b;
M
Mr.doob 已提交
333

334
			} else if ( light instanceof THREE.DirectionalLight ) {
335

336
				doffset = dlength * 3;
337

338
				dcolors[ doffset ]     = color.r * intensity;
339 340
				dcolors[ doffset + 1 ] = color.g * intensity;
				dcolors[ doffset + 2 ] = color.b * intensity;
341

342
				dpositions[ doffset ]     = position.x;
343 344
				dpositions[ doffset + 1 ] = position.y;
				dpositions[ doffset + 2 ] = position.z;
345

346
				dlength += 1;
M
Mr.doob 已提交
347

348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
			} else if ( light instanceof THREE.SpotLight ) { // hack, not a proper spotlight

				doffset = dlength * 3;

				dcolors[ doffset ]     = color.r * intensity;
				dcolors[ doffset + 1 ] = color.g * intensity;
				dcolors[ doffset + 2 ] = color.b * intensity;

				n = 1 / position.length();

				dpositions[ doffset ]     = position.x * n;
				dpositions[ doffset + 1 ] = position.y * n;
				dpositions[ doffset + 2 ] = position.z * n;

				dlength += 1;

364 365
			} else if( light instanceof THREE.PointLight ) {

366
				poffset = plength * 3;
367

368
				pcolors[ poffset ]     = color.r * intensity;
369 370
				pcolors[ poffset + 1 ] = color.g * intensity;
				pcolors[ poffset + 2 ] = color.b * intensity;
371

372
				ppositions[ poffset ]     = position.x;
373 374
				ppositions[ poffset + 1 ] = position.y;
				ppositions[ poffset + 2 ] = position.z;
M
Mr.doob 已提交
375

376 377
				pdistances[ plength ] = distance;

378
				plength += 1;
M
Mr.doob 已提交
379

380 381 382
			}

		}
383

384 385
		// null eventual remains from removed lights
		// (this is to avoid if in shader)
386

387 388
		for( l = dlength * 3; l < dcolors.length; l++ ) dcolors[ l ] = 0.0;
		for( l = plength * 3; l < pcolors.length; l++ ) pcolors[ l ] = 0.0;
M
Mr.doob 已提交
389

390 391
		zlights.point.length = plength;
		zlights.directional.length = dlength;
M
Mr.doob 已提交
392

393 394 395
		zlights.ambient[ 0 ] = r;
		zlights.ambient[ 1 ] = g;
		zlights.ambient[ 2 ] = b;
M
Mr.doob 已提交
396

397
	};
M
Mr.doob 已提交
398

399
	function createParticleBuffers ( geometry ) {
M
Mr.doob 已提交
400

401 402
		geometry.__webglVertexBuffer = _gl.createBuffer();
		geometry.__webglColorBuffer = _gl.createBuffer();
M
Mr.doob 已提交
403

404
	};
M
Mr.doob 已提交
405

406
	function createLineBuffers( geometry ) {
M
Mr.doob 已提交
407

408 409
		geometry.__webglVertexBuffer = _gl.createBuffer();
		geometry.__webglColorBuffer = _gl.createBuffer();
M
Mr.doob 已提交
410

411
	};
412

413
	function createRibbonBuffers( geometry ) {
A
alteredq 已提交
414

415 416
		geometry.__webglVertexBuffer = _gl.createBuffer();
		geometry.__webglColorBuffer = _gl.createBuffer();
A
alteredq 已提交
417 418 419

	};

420
	function createMeshBuffers( geometryGroup ) {
M
Mr.doob 已提交
421

422 423 424 425 426 427
		geometryGroup.__webglVertexBuffer = _gl.createBuffer();
		geometryGroup.__webglNormalBuffer = _gl.createBuffer();
		geometryGroup.__webglTangentBuffer = _gl.createBuffer();
		geometryGroup.__webglColorBuffer = _gl.createBuffer();
		geometryGroup.__webglUVBuffer = _gl.createBuffer();
		geometryGroup.__webglUV2Buffer = _gl.createBuffer();
428

429 430 431 432 433 434 435 436 437
		geometryGroup.__webglSkinVertexABuffer = _gl.createBuffer();
		geometryGroup.__webglSkinVertexBBuffer = _gl.createBuffer();
		geometryGroup.__webglSkinIndicesBuffer = _gl.createBuffer();
		geometryGroup.__webglSkinWeightsBuffer = _gl.createBuffer();

		geometryGroup.__webglFaceBuffer = _gl.createBuffer();
		geometryGroup.__webglLineBuffer = _gl.createBuffer();

		if ( geometryGroup.numMorphTargets ) {
438

439
			var m, ml;
440

M
Mr.doob 已提交
441
			geometryGroup.__webglMorphTargetsBuffers = [];
442

443
			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
444 445 446

				geometryGroup.__webglMorphTargetsBuffers.push( _gl.createBuffer() );

447 448 449
			}

		}
M
Mr.doob 已提交
450

451
	};
452

453
	function initLineBuffers ( geometry ) {
M
Mr.doob 已提交
454

455 456 457
		var nvertices = geometry.vertices.length;

		geometry.__vertexArray = new Float32Array( nvertices * 3 );
458
		geometry.__colorArray = new Float32Array( nvertices * 3 );
M
Mr.doob 已提交
459

460
		geometry.__webglLineCount = nvertices;
M
Mr.doob 已提交
461

462
	};
M
Mr.doob 已提交
463

464
	function initRibbonBuffers ( geometry ) {
A
alteredq 已提交
465 466 467 468 469 470

		var nvertices = geometry.vertices.length;

		geometry.__vertexArray = new Float32Array( nvertices * 3 );
		geometry.__colorArray = new Float32Array( nvertices * 3 );

471
		geometry.__webglVertexCount = nvertices;
A
alteredq 已提交
472 473

	};
474

475
	function initParticleBuffers ( geometry, object ) {
476 477 478 479

		var nvertices = geometry.vertices.length;

		geometry.__vertexArray = new Float32Array( nvertices * 3 );
A
alteredq 已提交
480
		geometry.__colorArray = new Float32Array( nvertices * 3 );
481

482
		geometry.__sortArray = [];
483

484
		geometry.__webglParticleCount = nvertices;
485

486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
		geometry.__materials = object.materials;

		// custom attributes

		var m, ml, material;

		for ( m = 0, ml = object.materials.length; m < ml; m ++ ) {

			material = object.materials[ m ];

			if ( material.attributes ) {

				if ( geometry.__webglCustomAttributes === undefined ) {

					geometry.__webglCustomAttributes = {};

				}

				for ( a in material.attributes ) {

					// Do a shallow copy of the attribute object so different geometryGroup chunks use different
					// attribute buffers which are correctly indexed in the setMeshBuffers function

					// Not sure how to best translate this into non-indexed arrays
					// used for particles, as there are no geometry chunks here
					// Probably could be simplified

					originalAttribute = material.attributes[ a ];

					attribute = {};

					for ( property in originalAttribute ) {

						attribute[ property ] = originalAttribute[ property ];

					}

					if( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {

						attribute.__webglInitialized = true;

						size = 1;		// "f" and "i"

						if( attribute.type === "v2" ) size = 2;
						else if( attribute.type === "v3" ) size = 3;
						else if( attribute.type === "v4" ) size = 4;
						else if( attribute.type === "c"  ) size = 3;

						attribute.size = size;
						attribute.array = new Float32Array( nvertices * size );
						attribute.buffer = _gl.createBuffer();
						attribute.buffer.belongsToAttribute = a;

						originalAttribute.needsUpdate = true;
						attribute.__original = originalAttribute;

					}

					geometry.__webglCustomAttributes[ a ] = attribute;

				}

			}

		}

552 553
	};

554
	function initMeshBuffers ( geometryGroup, object ) {
M
Mr.doob 已提交
555

M
Mikael Emtinger 已提交
556
		var f, fl, fi, face,
557
		m, ml, size,
558 559 560 561 562
		nvertices = 0, ntris = 0, nlines = 0,

		uvType,
		vertexColorType,
		normalType,
563 564
		materials, material,
		attribute, property, originalAttribute,
565 566 567 568

		geometry = object.geometry,
		obj_faces = geometry.faces,
		chunk_faces = geometryGroup.faces;
M
Mr.doob 已提交
569

570
		for ( f = 0, fl = chunk_faces.length; f < fl; f++ ) {
M
Mr.doob 已提交
571

572 573
			fi = chunk_faces[ f ];
			face = obj_faces[ fi ];
M
Mr.doob 已提交
574

575
			if ( face instanceof THREE.Face3 ) {
M
Mr.doob 已提交
576

577 578 579
				nvertices += 3;
				ntris += 1;
				nlines += 3;
M
Mr.doob 已提交
580

581
			} else if ( face instanceof THREE.Face4 ) {
M
Mr.doob 已提交
582

583 584
				nvertices += 4;
				ntris += 2;
585
				nlines += 4;
M
Mr.doob 已提交
586

587
			}
M
Mr.doob 已提交
588

589
		}
590 591

		materials = unrollGroupMaterials( geometryGroup, object );
M
Mr.doob 已提交
592

593 594 595 596 597 598 599
		// this will not work if materials would change in run-time
		// it should be refreshed every frame
		// but need to do unrollGroupMaterials
		// more properly without push to array
		// like unrollBufferMaterials

		geometryGroup.__materials = materials;
600

601 602
		uvType = bufferGuessUVType( materials, geometryGroup, object );
		normalType = bufferGuessNormalType( materials, geometryGroup, object );
A
alteredq 已提交
603 604
		vertexColorType = bufferGuessVertexColorType( materials, geometryGroup, object );

605
		//console.log("uvType",uvType, "normalType",normalType, "vertexColorType",vertexColorType, object, geometryGroup, materials );
M
Mr.doob 已提交
606

607
		geometryGroup.__vertexArray = new Float32Array( nvertices * 3 );
608

609
		if ( normalType ) {
M
Mr.doob 已提交
610

611
			geometryGroup.__normalArray = new Float32Array( nvertices * 3 );
M
Mr.doob 已提交
612

613
		}
614

615
		if ( geometry.hasTangents ) {
616

617
			geometryGroup.__tangentArray = new Float32Array( nvertices * 4 );
618

619
		}
620

621
		if ( vertexColorType ) {
622

623
			geometryGroup.__colorArray = new Float32Array( nvertices * 3 );
M
Mr.doob 已提交
624

625
		}
M
Mr.doob 已提交
626

627
		if ( uvType ) {
628

629
			if ( geometry.faceUvs.length > 0 || geometry.faceVertexUvs.length > 0 ) {
630

631 632 633 634 635
				geometryGroup.__uvArray = new Float32Array( nvertices * 2 );

			}

			if ( geometry.faceUvs.length > 1 || geometry.faceVertexUvs.length > 1 ) {
636

637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
				geometryGroup.__uv2Array = new Float32Array( nvertices * 2 );

			}

		}

		if ( object.geometry.skinWeights.length && object.geometry.skinIndices.length ) {

			geometryGroup.__skinVertexAArray = new Float32Array( nvertices * 4 );
			geometryGroup.__skinVertexBArray = new Float32Array( nvertices * 4 );
			geometryGroup.__skinIndexArray = new Float32Array( nvertices * 4 );
			geometryGroup.__skinWeightArray = new Float32Array( nvertices * 4 );

		}

M
Mikael Emtinger 已提交
652
		geometryGroup.__faceArray = new Uint16Array( ntris * 3 + ( object.geometry.edgeFaces ? object.geometry.edgeFaces.length * 2 * 3 : 0 ));
653
		geometryGroup.__lineArray = new Uint16Array( nlines * 2 );
M
Mr.doob 已提交
654

655 656
		if ( geometryGroup.numMorphTargets ) {

M
Mr.doob 已提交
657
			geometryGroup.__morphTargetsArrays = [];
658

659
			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
660

661 662
				geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );

663 664 665
			}

		}
666

667
		geometryGroup.__needsSmoothNormals = ( normalType == THREE.SmoothShading );
668

669 670 671 672
		geometryGroup.__uvType = uvType;
		geometryGroup.__vertexColorType = vertexColorType;
		geometryGroup.__normalType = normalType;

673 674
		geometryGroup.__webglFaceCount = ntris * 3 + ( object.geometry.edgeFaces ? object.geometry.edgeFaces.length * 2 * 3 : 0 );
		geometryGroup.__webglLineCount = nlines * 2;
675

M
Mr.doob 已提交
676

677
		// custom attributes
M
Mr.doob 已提交
678 679 680

		for ( m = 0, ml = materials.length; m < ml; m ++ ) {

681 682 683
			material = materials[ m ];

			if ( material.attributes ) {
M
Mr.doob 已提交
684

685 686 687 688 689
				if ( geometryGroup.__webglCustomAttributes === undefined ) {

					geometryGroup.__webglCustomAttributes = {};

				}
690

691 692 693 694 695 696
				for ( a in material.attributes ) {

					// Do a shallow copy of the attribute object so different geometryGroup chunks use different
					// attribute buffers which are correctly indexed in the setMeshBuffers function

					originalAttribute = material.attributes[ a ];
M
Mr.doob 已提交
697

698
					attribute = {};
699 700 701 702 703

					for ( property in originalAttribute ) {

						attribute[ property ] = originalAttribute[ property ];

704
					}
M
Mr.doob 已提交
705

706
					if( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
707

708
						attribute.__webglInitialized = true;
709

710
						size = 1;		// "f" and "i"
711

712 713 714 715
						if( attribute.type === "v2" ) size = 2;
						else if( attribute.type === "v3" ) size = 3;
						else if( attribute.type === "v4" ) size = 4;
						else if( attribute.type === "c"  ) size = 3;
716

717 718 719
						attribute.size = size;
						attribute.array = new Float32Array( nvertices * size );
						attribute.buffer = _gl.createBuffer();
720
						attribute.buffer.belongsToAttribute = a;
M
Mr.doob 已提交
721

722 723
						originalAttribute.needsUpdate = true;
						attribute.__original = originalAttribute;
724

725
					}
726 727 728 729 730 731

					geometryGroup.__webglCustomAttributes[ a ] = attribute;

				}

			}
M
Mr.doob 已提交
732

733
		}
734

735 736
		geometryGroup.__inittedArrays = true;

737
	};
M
Mr.doob 已提交
738

739

740
	function setMeshBuffers( geometryGroup, object, hint, dispose ) {
741

742 743 744 745 746 747 748
		if ( ! geometryGroup.__inittedArrays ) {

			// console.log( object );
			return;

		}

M
Mr.doob 已提交
749
		var f, fl, fi, face,
750 751 752 753 754 755 756 757 758 759 760 761 762
		vertexNormals, faceNormal, normal,
		vertexColors, faceColor,
		vertexTangents,
		uvType, vertexColorType, normalType,
		uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4,
		c1, c2, c3, c4,
		sw1, sw2, sw3, sw4,
		si1, si2, si3, si4,
		sa1, sa2, sa3, sa4,
		sb1, sb2, sb3, sb4,
		m, ml, i,
		vn, uvi, uv2i,
		vk, vkl, vka,
763
		a,
M
Mr.doob 已提交
764

765
		vertexIndex = 0,
766

767 768
		offset = 0,
		offset_uv = 0,
769
		offset_uv2 = 0,
770 771 772 773
		offset_face = 0,
		offset_normal = 0,
		offset_tangent = 0,
		offset_line = 0,
774
		offset_color = 0,
A
alteredq 已提交
775
		offset_skin = 0,
776
		offset_morphTarget = 0,
777
		offset_custom = 0,
778
		offset_customSrc = 0,
M
Mr.doob 已提交
779

780 781
		value,

782 783 784 785 786 787
		vertexArray = geometryGroup.__vertexArray,
		uvArray = geometryGroup.__uvArray,
		uv2Array = geometryGroup.__uv2Array,
		normalArray = geometryGroup.__normalArray,
		tangentArray = geometryGroup.__tangentArray,
		colorArray = geometryGroup.__colorArray,
788

789 790 791 792
		skinVertexAArray = geometryGroup.__skinVertexAArray,
		skinVertexBArray = geometryGroup.__skinVertexBArray,
		skinIndexArray = geometryGroup.__skinIndexArray,
		skinWeightArray = geometryGroup.__skinWeightArray,
M
Mr.doob 已提交
793

794 795
		morphTargetsArrays = geometryGroup.__morphTargetsArrays,

796 797
		customAttributes = geometryGroup.__webglCustomAttributes,
		customAttribute,
798

799 800
		faceArray = geometryGroup.__faceArray,
		lineArray = geometryGroup.__lineArray,
M
Mr.doob 已提交
801

802
		needsSmoothNormals = geometryGroup.__needsSmoothNormals,
803

804
		vertexColorType = geometryGroup.__vertexColorType,
A
alteredq 已提交
805 806
		uvType = geometryGroup.__uvType,
		normalType = geometryGroup.__normalType,
807

808
		geometry = object.geometry, // this is shared for all chunks
809

810
		dirtyVertices = geometry.__dirtyVertices,
811 812 813
		dirtyElements = geometry.__dirtyElements,
		dirtyUvs = geometry.__dirtyUvs,
		dirtyNormals = geometry.__dirtyNormals,
814
		dirtyTangents = geometry.__dirtyTangents,
815
		dirtyColors = geometry.__dirtyColors,
816
		dirtyMorphTargets = geometry.__dirtyMorphTargets,
M
Mr.doob 已提交
817

818
		vertices = geometry.vertices,
819
		chunk_faces = geometryGroup.faces,
820
		obj_faces = geometry.faces,
821

822 823
		obj_uvs  = geometry.faceVertexUvs[ 0 ],
		obj_uvs2 = geometry.faceVertexUvs[ 1 ],
824

A
alteredq 已提交
825
		obj_colors = geometry.colors,
826

A
alteredq 已提交
827 828 829
		obj_skinVerticesA = geometry.skinVerticesA,
		obj_skinVerticesB = geometry.skinVerticesB,
		obj_skinIndices = geometry.skinIndices,
830
		obj_skinWeights = geometry.skinWeights,
831

832
		morphTargets = geometry.morphTargets;
833

834
		if ( customAttributes ) {
M
Mr.doob 已提交
835

836
			for ( a in customAttributes ) {
M
Mr.doob 已提交
837

838
				customAttributes[ a ].offset = 0;
839
				customAttributes[ a ].offsetSrc = 0;
M
Mr.doob 已提交
840

841 842
			}

M
Mr.doob 已提交
843
		}
844 845


846
		for ( f = 0, fl = chunk_faces.length; f < fl; f ++ ) {
M
Mr.doob 已提交
847

848 849
			fi = chunk_faces[ f ];
			face = obj_faces[ fi ];
850 851

			if ( obj_uvs ) {
A
alteredq 已提交
852 853 854 855

				uv = obj_uvs[ fi ];

			}
856 857 858

			if ( obj_uvs2 ) {

A
alteredq 已提交
859 860 861
				uv2 = obj_uvs2[ fi ];

			}
M
Mr.doob 已提交
862

863
			vertexNormals = face.vertexNormals;
864
			faceNormal = face.normal;
865

866 867
			vertexColors = face.vertexColors;
			faceColor = face.color;
868

869
			vertexTangents = face.vertexTangents;
870 871 872

			if ( face instanceof THREE.Face3 ) {

873
				if ( dirtyVertices ) {
M
Mr.doob 已提交
874

875 876 877
					v1 = vertices[ face.a ].position;
					v2 = vertices[ face.b ].position;
					v3 = vertices[ face.c ].position;
M
Mr.doob 已提交
878

879 880 881
					vertexArray[ offset ]     = v1.x;
					vertexArray[ offset + 1 ] = v1.y;
					vertexArray[ offset + 2 ] = v1.z;
M
Mr.doob 已提交
882

883 884 885
					vertexArray[ offset + 3 ] = v2.x;
					vertexArray[ offset + 4 ] = v2.y;
					vertexArray[ offset + 5 ] = v2.z;
886

887 888 889
					vertexArray[ offset + 6 ] = v3.x;
					vertexArray[ offset + 7 ] = v3.y;
					vertexArray[ offset + 8 ] = v3.z;
M
Mr.doob 已提交
890

891
					offset += 9;
M
Mr.doob 已提交
892

893
				}
894

895
				if ( customAttributes ) {
M
Mr.doob 已提交
896

897
					for ( a in customAttributes ) {
M
Mr.doob 已提交
898

899
						customAttribute = customAttributes[ a ];
M
Mr.doob 已提交
900

901
						if ( customAttribute.__original.needsUpdate ) {
M
Mr.doob 已提交
902

903
							offset_custom = customAttribute.offset;
904
							offset_customSrc = customAttribute.offsetSrc;
M
Mr.doob 已提交
905

906 907 908
							if ( customAttribute.size === 1 ) {

								if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
M
Mr.doob 已提交
909

910
									customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
911 912
									customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
									customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
913 914 915

								} else if ( customAttribute.boundTo === "faces" ) {

916 917 918 919 920
									value = customAttribute.value[ offset_customSrc ];

									customAttribute.array[ offset_custom ] 	   = value;
									customAttribute.array[ offset_custom + 1 ] = value;
									customAttribute.array[ offset_custom + 2 ] = value;
921

922 923 924 925
									customAttribute.offsetSrc ++;

								} else if ( customAttribute.boundTo === "faceVertices" ) {

926
									customAttribute.array[ offset_custom ] 	   = customAttribute.value[ offset_customSrc ];
927 928
									customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ offset_customSrc + 1 ];
									customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ offset_customSrc + 2 ];
929

930
									customAttribute.offsetSrc += 3;
931

932
								}
M
Mr.doob 已提交
933

934
								customAttribute.offset += 3;
M
Mr.doob 已提交
935

936
							} else {
M
Mr.doob 已提交
937

938 939
								if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {

940 941 942
									v1 = customAttribute.value[ face.a ];
									v2 = customAttribute.value[ face.b ];
									v3 = customAttribute.value[ face.c ];
943 944 945

								} else if ( customAttribute.boundTo === "faces" ) {

946 947 948 949 950
									value = customAttribute.value[ offset_customSrc ];

									v1 = value;
									v2 = value;
									v3 = value;
951

952 953 954 955
									customAttribute.offsetSrc ++;

								} else if ( customAttribute.boundTo === "faceVertices" ) {

956
									v1 = customAttribute.value[ offset_customSrc ];
957 958
									v2 = customAttribute.value[ offset_customSrc + 1 ];
									v3 = customAttribute.value[ offset_customSrc + 2 ];
959

960
									customAttribute.offsetSrc += 3;
961

962
								}
M
Mr.doob 已提交
963

964 965

								if ( customAttribute.size === 2 ) {
M
Mr.doob 已提交
966

967
									customAttribute.array[ offset_custom ] 	   = v1.x;
M
Mr.doob 已提交
968
									customAttribute.array[ offset_custom + 1 ] = v1.y;
969

M
Mr.doob 已提交
970 971
									customAttribute.array[ offset_custom + 2 ] = v2.x;
									customAttribute.array[ offset_custom + 3 ] = v2.y;
972

M
Mr.doob 已提交
973
									customAttribute.array[ offset_custom + 4 ] = v3.x;
974
									customAttribute.array[ offset_custom + 5 ] = v3.y;
M
Mr.doob 已提交
975

976
									customAttribute.offset += 6;
M
Mr.doob 已提交
977

978 979 980
								} else if ( customAttribute.size === 3 ) {

									if ( customAttribute.type === "c" ) {
M
Mr.doob 已提交
981

982
										customAttribute.array[ offset_custom ] 	   = v1.r;
983 984
										customAttribute.array[ offset_custom + 1 ] = v1.g;
										customAttribute.array[ offset_custom + 2 ] = v1.b;
985

986 987 988
										customAttribute.array[ offset_custom + 3 ] = v2.r;
										customAttribute.array[ offset_custom + 4 ] = v2.g;
										customAttribute.array[ offset_custom + 5 ] = v2.b;
989

990 991 992
										customAttribute.array[ offset_custom + 6 ] = v3.r;
										customAttribute.array[ offset_custom + 7 ] = v3.g;
										customAttribute.array[ offset_custom + 8 ] = v3.b;
993

994
									} else {
995

996
										customAttribute.array[ offset_custom ] 	   = v1.x;
997 998
										customAttribute.array[ offset_custom + 1 ] = v1.y;
										customAttribute.array[ offset_custom + 2 ] = v1.z;
999

1000 1001 1002
										customAttribute.array[ offset_custom + 3 ] = v2.x;
										customAttribute.array[ offset_custom + 4 ] = v2.y;
										customAttribute.array[ offset_custom + 5 ] = v2.z;
1003

1004 1005 1006
										customAttribute.array[ offset_custom + 6 ] = v3.x;
										customAttribute.array[ offset_custom + 7 ] = v3.y;
										customAttribute.array[ offset_custom + 8 ] = v3.z;
1007

1008
									}
M
Mr.doob 已提交
1009

1010
									customAttribute.offset += 9;
M
Mr.doob 已提交
1011

1012
								} else {
M
Mr.doob 已提交
1013

1014
									customAttribute.array[ offset_custom  ] 	= v1.x;
M
Mr.doob 已提交
1015 1016 1017
									customAttribute.array[ offset_custom + 1  ] = v1.y;
									customAttribute.array[ offset_custom + 2  ] = v1.z;
									customAttribute.array[ offset_custom + 3  ] = v1.w;
1018

M
Mr.doob 已提交
1019 1020 1021 1022
									customAttribute.array[ offset_custom + 4  ] = v2.x;
									customAttribute.array[ offset_custom + 5  ] = v2.y;
									customAttribute.array[ offset_custom + 6  ] = v2.z;
									customAttribute.array[ offset_custom + 7  ] = v2.w;
1023

M
Mr.doob 已提交
1024
									customAttribute.array[ offset_custom + 8  ] = v3.x;
1025 1026 1027
									customAttribute.array[ offset_custom + 9  ] = v3.y;
									customAttribute.array[ offset_custom + 10 ] = v3.z;
									customAttribute.array[ offset_custom + 11 ] = v3.w;
M
Mr.doob 已提交
1028

1029
									customAttribute.offset += 12;
M
Mr.doob 已提交
1030

1031
								}
M
Mr.doob 已提交
1032

1033
							}
M
Mr.doob 已提交
1034

1035
						}
M
Mr.doob 已提交
1036

1037
					}
M
Mr.doob 已提交
1038

1039 1040 1041
				}


1042
				if ( dirtyMorphTargets ) {
1043 1044 1045

					for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) {

1046 1047 1048
						v1 = morphTargets[ vk ].vertices[ face.a ].position;
						v2 = morphTargets[ vk ].vertices[ face.b ].position;
						v3 = morphTargets[ vk ].vertices[ face.c ].position;
1049

1050
						vka = morphTargetsArrays[ vk ];
1051

1052
						vka[ offset_morphTarget ] 	  = v1.x;
1053 1054
						vka[ offset_morphTarget + 1 ] = v1.y;
						vka[ offset_morphTarget + 2 ] = v1.z;
1055

1056 1057 1058
						vka[ offset_morphTarget + 3 ] = v2.x;
						vka[ offset_morphTarget + 4 ] = v2.y;
						vka[ offset_morphTarget + 5 ] = v2.z;
1059

1060 1061 1062
						vka[ offset_morphTarget + 6 ] = v3.x;
						vka[ offset_morphTarget + 7 ] = v3.y;
						vka[ offset_morphTarget + 8 ] = v3.z;
1063

1064 1065
					}

1066
					offset_morphTarget += 9;
1067

1068 1069
				}

A
alteredq 已提交
1070 1071 1072
				if ( obj_skinWeights.length ) {

					// weights
1073

A
alteredq 已提交
1074 1075 1076
					sw1 = obj_skinWeights[ face.a ];
					sw2 = obj_skinWeights[ face.b ];
					sw3 = obj_skinWeights[ face.c ];
1077

A
alteredq 已提交
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
					skinWeightArray[ offset_skin ]     = sw1.x;
					skinWeightArray[ offset_skin + 1 ] = sw1.y;
					skinWeightArray[ offset_skin + 2 ] = sw1.z;
					skinWeightArray[ offset_skin + 3 ] = sw1.w;

					skinWeightArray[ offset_skin + 4 ] = sw2.x;
					skinWeightArray[ offset_skin + 5 ] = sw2.y;
					skinWeightArray[ offset_skin + 6 ] = sw2.z;
					skinWeightArray[ offset_skin + 7 ] = sw2.w;

					skinWeightArray[ offset_skin + 8 ]  = sw3.x;
					skinWeightArray[ offset_skin + 9 ]  = sw3.y;
					skinWeightArray[ offset_skin + 10 ] = sw3.z;
					skinWeightArray[ offset_skin + 11 ] = sw3.w;

					// indices
1094

A
alteredq 已提交
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114
					si1 = obj_skinIndices[ face.a ];
					si2 = obj_skinIndices[ face.b ];
					si3 = obj_skinIndices[ face.c ];

					skinIndexArray[ offset_skin ]     = si1.x;
					skinIndexArray[ offset_skin + 1 ] = si1.y;
					skinIndexArray[ offset_skin + 2 ] = si1.z;
					skinIndexArray[ offset_skin + 3 ] = si1.w;

					skinIndexArray[ offset_skin + 4 ] = si2.x;
					skinIndexArray[ offset_skin + 5 ] = si2.y;
					skinIndexArray[ offset_skin + 6 ] = si2.z;
					skinIndexArray[ offset_skin + 7 ] = si2.w;

					skinIndexArray[ offset_skin + 8 ]  = si3.x;
					skinIndexArray[ offset_skin + 9 ]  = si3.y;
					skinIndexArray[ offset_skin + 10 ] = si3.z;
					skinIndexArray[ offset_skin + 11 ] = si3.w;

					// vertices A
1115

A
alteredq 已提交
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
					sa1 = obj_skinVerticesA[ face.a ];
					sa2 = obj_skinVerticesA[ face.b ];
					sa3 = obj_skinVerticesA[ face.c ];

					skinVertexAArray[ offset_skin ]     = sa1.x;
					skinVertexAArray[ offset_skin + 1 ] = sa1.y;
					skinVertexAArray[ offset_skin + 2 ] = sa1.z;
					skinVertexAArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader

					skinVertexAArray[ offset_skin + 4 ] = sa2.x;
					skinVertexAArray[ offset_skin + 5 ] = sa2.y;
					skinVertexAArray[ offset_skin + 6 ] = sa2.z;
					skinVertexAArray[ offset_skin + 7 ] = 1;

					skinVertexAArray[ offset_skin + 8 ]  = sa3.x;
					skinVertexAArray[ offset_skin + 9 ]  = sa3.y;
					skinVertexAArray[ offset_skin + 10 ] = sa3.z;
					skinVertexAArray[ offset_skin + 11 ] = 1;

					// vertices B
1136

A
alteredq 已提交
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
					sb1 = obj_skinVerticesB[ face.a ];
					sb2 = obj_skinVerticesB[ face.b ];
					sb3 = obj_skinVerticesB[ face.c ];

					skinVertexBArray[ offset_skin ]     = sb1.x;
					skinVertexBArray[ offset_skin + 1 ] = sb1.y;
					skinVertexBArray[ offset_skin + 2 ] = sb1.z;
					skinVertexBArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader

					skinVertexBArray[ offset_skin + 4 ] = sb2.x;
					skinVertexBArray[ offset_skin + 5 ] = sb2.y;
					skinVertexBArray[ offset_skin + 6 ] = sb2.z;
					skinVertexBArray[ offset_skin + 7 ] = 1;

					skinVertexBArray[ offset_skin + 8 ]  = sb3.x;
					skinVertexBArray[ offset_skin + 9 ]  = sb3.y;
					skinVertexBArray[ offset_skin + 10 ] = sb3.z;
					skinVertexBArray[ offset_skin + 11 ] = 1;

					offset_skin += 12;
1157

A
alteredq 已提交
1158
				}
1159

1160 1161 1162
				if ( dirtyColors && vertexColorType ) {

					if ( vertexColors.length == 3 && vertexColorType == THREE.VertexColors ) {
1163

1164 1165 1166 1167 1168
						c1 = vertexColors[ 0 ];
						c2 = vertexColors[ 1 ];
						c3 = vertexColors[ 2 ];

					} else {
1169

1170 1171 1172 1173 1174
						c1 = faceColor;
						c2 = faceColor;
						c3 = faceColor;

					}
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186

					colorArray[ offset_color ]     = c1.r;
					colorArray[ offset_color + 1 ] = c1.g;
					colorArray[ offset_color + 2 ] = c1.b;

					colorArray[ offset_color + 3 ] = c2.r;
					colorArray[ offset_color + 4 ] = c2.g;
					colorArray[ offset_color + 5 ] = c2.b;

					colorArray[ offset_color + 6 ] = c3.r;
					colorArray[ offset_color + 7 ] = c3.g;
					colorArray[ offset_color + 8 ] = c3.b;
1187

1188 1189 1190 1191
					offset_color += 9;

				}

1192
				if ( dirtyTangents && geometry.hasTangents ) {
1193

1194 1195 1196
					t1 = vertexTangents[ 0 ];
					t2 = vertexTangents[ 1 ];
					t3 = vertexTangents[ 2 ];
1197

1198 1199 1200 1201
					tangentArray[ offset_tangent ]     = t1.x;
					tangentArray[ offset_tangent + 1 ] = t1.y;
					tangentArray[ offset_tangent + 2 ] = t1.z;
					tangentArray[ offset_tangent + 3 ] = t1.w;
M
Mr.doob 已提交
1202

1203 1204 1205 1206
					tangentArray[ offset_tangent + 4 ] = t2.x;
					tangentArray[ offset_tangent + 5 ] = t2.y;
					tangentArray[ offset_tangent + 6 ] = t2.z;
					tangentArray[ offset_tangent + 7 ] = t2.w;
M
Mr.doob 已提交
1207

1208 1209 1210 1211
					tangentArray[ offset_tangent + 8 ]  = t3.x;
					tangentArray[ offset_tangent + 9 ]  = t3.y;
					tangentArray[ offset_tangent + 10 ] = t3.z;
					tangentArray[ offset_tangent + 11 ] = t3.w;
M
Mr.doob 已提交
1212

1213
					offset_tangent += 12;
M
Mr.doob 已提交
1214

1215 1216
				}

A
alteredq 已提交
1217
				if ( dirtyNormals && normalType ) {
M
Mr.doob 已提交
1218

1219 1220 1221
					if ( vertexNormals.length == 3 && needsSmoothNormals ) {

						for ( i = 0; i < 3; i ++ ) {
1222

1223
							vn = vertexNormals[ i ];
M
Mr.doob 已提交
1224

1225 1226 1227
							normalArray[ offset_normal ]     = vn.x;
							normalArray[ offset_normal + 1 ] = vn.y;
							normalArray[ offset_normal + 2 ] = vn.z;
M
Mr.doob 已提交
1228

1229
							offset_normal += 3;
M
Mr.doob 已提交
1230

1231
						}
M
Mr.doob 已提交
1232

1233
					} else {
1234

1235
						for ( i = 0; i < 3; i ++ ) {
1236

1237 1238 1239
							normalArray[ offset_normal ]     = faceNormal.x;
							normalArray[ offset_normal + 1 ] = faceNormal.y;
							normalArray[ offset_normal + 2 ] = faceNormal.z;
M
Mr.doob 已提交
1240

1241
							offset_normal += 3;
M
Mr.doob 已提交
1242

1243
						}
M
Mr.doob 已提交
1244 1245

					}
M
Mr.doob 已提交
1246

1247 1248
				}

A
alteredq 已提交
1249
				if ( dirtyUvs && uv !== undefined && uvType ) {
1250

M
Mr.doob 已提交
1251 1252
					for ( i = 0; i < 3; i ++ ) {

1253
						uvi = uv[ i ];
M
Mr.doob 已提交
1254

1255 1256
						uvArray[ offset_uv ]     = uvi.u;
						uvArray[ offset_uv + 1 ] = uvi.v;
M
Mr.doob 已提交
1257

1258
						offset_uv += 2;
M
Mr.doob 已提交
1259

M
Mr.doob 已提交
1260
					}
1261 1262 1263

				}

A
alteredq 已提交
1264
				if ( dirtyUvs && uv2 !== undefined && uvType ) {
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278

					for ( i = 0; i < 3; i ++ ) {

						uv2i = uv2[ i ];

						uv2Array[ offset_uv2 ]     = uv2i.u;
						uv2Array[ offset_uv2 + 1 ] = uv2i.v;

						offset_uv2 += 2;

					}

				}

1279
				if ( dirtyElements ) {
M
Mr.doob 已提交
1280

1281
					faceArray[ offset_face ] 	 = vertexIndex;
1282 1283
					faceArray[ offset_face + 1 ] = vertexIndex + 1;
					faceArray[ offset_face + 2 ] = vertexIndex + 2;
M
Mr.doob 已提交
1284

1285
					offset_face += 3;
M
Mr.doob 已提交
1286

1287 1288
					lineArray[ offset_line ]     = vertexIndex;
					lineArray[ offset_line + 1 ] = vertexIndex + 1;
M
Mr.doob 已提交
1289

1290 1291
					lineArray[ offset_line + 2 ] = vertexIndex;
					lineArray[ offset_line + 3 ] = vertexIndex + 2;
M
Mr.doob 已提交
1292

1293 1294
					lineArray[ offset_line + 4 ] = vertexIndex + 1;
					lineArray[ offset_line + 5 ] = vertexIndex + 2;
M
Mr.doob 已提交
1295

1296
					offset_line += 6;
1297

1298
					vertexIndex += 3;
M
Mr.doob 已提交
1299

1300
				}
M
Mr.doob 已提交
1301

1302 1303 1304

			} else if ( face instanceof THREE.Face4 ) {

1305
				if ( dirtyVertices ) {
M
Mr.doob 已提交
1306

1307 1308 1309 1310
					v1 = vertices[ face.a ].position;
					v2 = vertices[ face.b ].position;
					v3 = vertices[ face.c ].position;
					v4 = vertices[ face.d ].position;
M
Mr.doob 已提交
1311

1312 1313 1314
					vertexArray[ offset ]     = v1.x;
					vertexArray[ offset + 1 ] = v1.y;
					vertexArray[ offset + 2 ] = v1.z;
M
Mr.doob 已提交
1315

1316 1317 1318
					vertexArray[ offset + 3 ] = v2.x;
					vertexArray[ offset + 4 ] = v2.y;
					vertexArray[ offset + 5 ] = v2.z;
1319

1320 1321 1322
					vertexArray[ offset + 6 ] = v3.x;
					vertexArray[ offset + 7 ] = v3.y;
					vertexArray[ offset + 8 ] = v3.z;
1323

1324
					vertexArray[ offset + 9 ]  = v4.x;
1325 1326
					vertexArray[ offset + 10 ] = v4.y;
					vertexArray[ offset + 11 ] = v4.z;
M
Mr.doob 已提交
1327

1328
					offset += 12;
M
Mr.doob 已提交
1329

1330
				}
1331

1332
				if ( customAttributes ) {
M
Mr.doob 已提交
1333

1334
					for ( a in customAttributes ) {
M
Mr.doob 已提交
1335

1336 1337
						customAttribute = customAttributes[ a ];

1338
						if ( customAttribute.__original.needsUpdate ) {
1339 1340

							offset_custom = customAttribute.offset;
1341
							offset_customSrc = customAttribute.offsetSrc;
M
Mr.doob 已提交
1342

1343 1344 1345
							if ( customAttribute.size === 1 ) {

								if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
M
Mr.doob 已提交
1346

1347
									customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
1348 1349
									customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
									customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
A
alteredq 已提交
1350
									customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ face.d ];
1351 1352 1353

								} else if ( customAttribute.boundTo === "faces" ) {

1354
									value = customAttribute.value[ offset_customSrc ];
1355

1356 1357 1358 1359 1360 1361
									customAttribute.array[ offset_custom ] 	   = value;
									customAttribute.array[ offset_custom + 1 ] = value;
									customAttribute.array[ offset_custom + 2 ] = value;
									customAttribute.array[ offset_custom + 3 ] = value;

									customAttribute.offsetSrc ++;
1362 1363 1364

								} else if ( customAttribute.boundTo === "faceVertices" ) {

1365
									customAttribute.array[ offset_custom ] 	   = customAttribute.value[ offset_customSrc ];
1366 1367
									customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ offset_customSrc + 1 ];
									customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ offset_customSrc + 2 ];
A
alteredq 已提交
1368
									customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ offset_customSrc + 3 ];
1369

1370
									customAttribute.offsetSrc += 4;
1371

1372
								}
M
Mr.doob 已提交
1373

1374
								customAttribute.offset += 4;
M
Mr.doob 已提交
1375

1376
							} else {
M
Mr.doob 已提交
1377

1378 1379
								if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {

1380 1381 1382 1383
									v1 = customAttribute.value[ face.a ];
									v2 = customAttribute.value[ face.b ];
									v3 = customAttribute.value[ face.c ];
									v4 = customAttribute.value[ face.d ];
1384 1385 1386

								} else if ( customAttribute.boundTo === "faces" ) {

1387
									value = customAttribute.value[ offset_customSrc ];
1388

1389 1390 1391 1392 1393 1394
									v1 = value;
									v2 = value;
									v3 = value;
									v4 = value;

									customAttribute.offsetSrc ++;
1395 1396 1397

								} else if ( customAttribute.boundTo === "faceVertices" ) {

1398
									v1 = customAttribute.value[ offset_customSrc ];
1399 1400 1401
									v2 = customAttribute.value[ offset_customSrc + 1 ];
									v3 = customAttribute.value[ offset_customSrc + 2 ];
									v4 = customAttribute.value[ offset_customSrc + 3 ];
1402

1403
									customAttribute.offsetSrc += 4;
1404

1405 1406
								}

M
Mr.doob 已提交
1407

1408
								if ( customAttribute.size === 2 ) {
M
Mr.doob 已提交
1409

1410
									customAttribute.array[ offset_custom ] 	   = v1.x;
M
Mr.doob 已提交
1411
									customAttribute.array[ offset_custom + 1 ] = v1.y;
1412

M
Mr.doob 已提交
1413 1414
									customAttribute.array[ offset_custom + 2 ] = v2.x;
									customAttribute.array[ offset_custom + 3 ] = v2.y;
1415

M
Mr.doob 已提交
1416
									customAttribute.array[ offset_custom + 4 ] = v3.x;
1417
									customAttribute.array[ offset_custom + 5 ] = v3.y;
1418

M
Mr.doob 已提交
1419
									customAttribute.array[ offset_custom + 6 ] = v4.x;
1420
									customAttribute.array[ offset_custom + 7 ] = v4.y;
M
Mr.doob 已提交
1421

1422
									customAttribute.offset += 8;
M
Mr.doob 已提交
1423

1424 1425 1426
								} else if ( customAttribute.size === 3 ) {

									if ( customAttribute.type === "c" ) {
M
Mr.doob 已提交
1427

1428
										customAttribute.array[ offset_custom  ] 	= v1.r;
1429 1430
										customAttribute.array[ offset_custom + 1  ] = v1.g;
										customAttribute.array[ offset_custom + 2  ] = v1.b;
1431

1432 1433 1434
										customAttribute.array[ offset_custom + 3  ] = v2.r;
										customAttribute.array[ offset_custom + 4  ] = v2.g;
										customAttribute.array[ offset_custom + 5  ] = v2.b;
1435

1436 1437 1438
										customAttribute.array[ offset_custom + 6  ] = v3.r;
										customAttribute.array[ offset_custom + 7  ] = v3.g;
										customAttribute.array[ offset_custom + 8  ] = v3.b;
1439

1440 1441 1442 1443 1444
										customAttribute.array[ offset_custom + 9  ] = v4.r;
										customAttribute.array[ offset_custom + 10 ] = v4.g;
										customAttribute.array[ offset_custom + 11 ] = v4.b;

									} else {
1445

1446
										customAttribute.array[ offset_custom  ] 	= v1.x;
1447 1448
										customAttribute.array[ offset_custom + 1  ] = v1.y;
										customAttribute.array[ offset_custom + 2  ] = v1.z;
1449

1450 1451 1452
										customAttribute.array[ offset_custom + 3  ] = v2.x;
										customAttribute.array[ offset_custom + 4  ] = v2.y;
										customAttribute.array[ offset_custom + 5  ] = v2.z;
1453

1454 1455 1456
										customAttribute.array[ offset_custom + 6  ] = v3.x;
										customAttribute.array[ offset_custom + 7  ] = v3.y;
										customAttribute.array[ offset_custom + 8  ] = v3.z;
1457

1458 1459 1460
										customAttribute.array[ offset_custom + 9  ] = v4.x;
										customAttribute.array[ offset_custom + 10 ] = v4.y;
										customAttribute.array[ offset_custom + 11 ] = v4.z;
1461

1462
									}
M
Mr.doob 已提交
1463

1464
									customAttribute.offset += 12;
M
Mr.doob 已提交
1465

1466
								} else {
M
Mr.doob 已提交
1467

1468
									customAttribute.array[ offset_custom  ] 	= v1.x;
M
Mr.doob 已提交
1469 1470 1471
									customAttribute.array[ offset_custom + 1  ] = v1.y;
									customAttribute.array[ offset_custom + 2  ] = v1.z;
									customAttribute.array[ offset_custom + 3  ] = v1.w;
1472

M
Mr.doob 已提交
1473 1474 1475 1476
									customAttribute.array[ offset_custom + 4  ] = v2.x;
									customAttribute.array[ offset_custom + 5  ] = v2.y;
									customAttribute.array[ offset_custom + 6  ] = v2.z;
									customAttribute.array[ offset_custom + 7  ] = v2.w;
1477

M
Mr.doob 已提交
1478
									customAttribute.array[ offset_custom + 8  ] = v3.x;
1479 1480 1481
									customAttribute.array[ offset_custom + 9  ] = v3.y;
									customAttribute.array[ offset_custom + 10 ] = v3.z;
									customAttribute.array[ offset_custom + 11 ] = v3.w;
1482

M
Mr.doob 已提交
1483
									customAttribute.array[ offset_custom + 12 ] = v4.x;
1484 1485 1486
									customAttribute.array[ offset_custom + 13 ] = v4.y;
									customAttribute.array[ offset_custom + 14 ] = v4.z;
									customAttribute.array[ offset_custom + 15 ] = v4.w;
M
Mr.doob 已提交
1487

1488
									customAttribute.offset += 16;
M
Mr.doob 已提交
1489

1490
								}
M
Mr.doob 已提交
1491

1492
							}
M
Mr.doob 已提交
1493

1494
						}
M
Mr.doob 已提交
1495

1496
					}
M
Mr.doob 已提交
1497

1498 1499 1500
				}


1501
				if ( dirtyMorphTargets ) {
1502

1503
					for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) {
1504

1505 1506 1507 1508
						v1 = morphTargets[ vk ].vertices[ face.a ].position;
						v2 = morphTargets[ vk ].vertices[ face.b ].position;
						v3 = morphTargets[ vk ].vertices[ face.c ].position;
						v4 = morphTargets[ vk ].vertices[ face.d ].position;
1509

1510
						vka = morphTargetsArrays[ vk ];
1511

1512
						vka[ offset_morphTarget ] 	  = v1.x;
1513 1514
						vka[ offset_morphTarget + 1 ] = v1.y;
						vka[ offset_morphTarget + 2 ] = v1.z;
1515

1516 1517 1518
						vka[ offset_morphTarget + 3 ] = v2.x;
						vka[ offset_morphTarget + 4 ] = v2.y;
						vka[ offset_morphTarget + 5 ] = v2.z;
1519

1520 1521 1522
						vka[ offset_morphTarget + 6 ] = v3.x;
						vka[ offset_morphTarget + 7 ] = v3.y;
						vka[ offset_morphTarget + 8 ] = v3.z;
1523

1524
						vka[ offset_morphTarget + 9 ]  = v4.x;
1525 1526
						vka[ offset_morphTarget + 10 ] = v4.y;
						vka[ offset_morphTarget + 11 ] = v4.z;
1527

1528 1529
					}

1530
					offset_morphTarget += 12;
1531

1532 1533
				}

A
alteredq 已提交
1534 1535 1536
				if ( obj_skinWeights.length ) {

					// weights
1537

A
alteredq 已提交
1538 1539 1540 1541
					sw1 = obj_skinWeights[ face.a ];
					sw2 = obj_skinWeights[ face.b ];
					sw3 = obj_skinWeights[ face.c ];
					sw4 = obj_skinWeights[ face.d ];
1542

A
alteredq 已提交
1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563
					skinWeightArray[ offset_skin ]     = sw1.x;
					skinWeightArray[ offset_skin + 1 ] = sw1.y;
					skinWeightArray[ offset_skin + 2 ] = sw1.z;
					skinWeightArray[ offset_skin + 3 ] = sw1.w;

					skinWeightArray[ offset_skin + 4 ] = sw2.x;
					skinWeightArray[ offset_skin + 5 ] = sw2.y;
					skinWeightArray[ offset_skin + 6 ] = sw2.z;
					skinWeightArray[ offset_skin + 7 ] = sw2.w;

					skinWeightArray[ offset_skin + 8 ]  = sw3.x;
					skinWeightArray[ offset_skin + 9 ]  = sw3.y;
					skinWeightArray[ offset_skin + 10 ] = sw3.z;
					skinWeightArray[ offset_skin + 11 ] = sw3.w;

					skinWeightArray[ offset_skin + 12 ] = sw4.x;
					skinWeightArray[ offset_skin + 13 ] = sw4.y;
					skinWeightArray[ offset_skin + 14 ] = sw4.z;
					skinWeightArray[ offset_skin + 15 ] = sw4.w;

					// indices
1564

A
alteredq 已提交
1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590
					si1 = obj_skinIndices[ face.a ];
					si2 = obj_skinIndices[ face.b ];
					si3 = obj_skinIndices[ face.c ];
					si4 = obj_skinIndices[ face.d ];

					skinIndexArray[ offset_skin ]     = si1.x;
					skinIndexArray[ offset_skin + 1 ] = si1.y;
					skinIndexArray[ offset_skin + 2 ] = si1.z;
					skinIndexArray[ offset_skin + 3 ] = si1.w;

					skinIndexArray[ offset_skin + 4 ] = si2.x;
					skinIndexArray[ offset_skin + 5 ] = si2.y;
					skinIndexArray[ offset_skin + 6 ] = si2.z;
					skinIndexArray[ offset_skin + 7 ] = si2.w;

					skinIndexArray[ offset_skin + 8 ]  = si3.x;
					skinIndexArray[ offset_skin + 9 ]  = si3.y;
					skinIndexArray[ offset_skin + 10 ] = si3.z;
					skinIndexArray[ offset_skin + 11 ] = si3.w;

					skinIndexArray[ offset_skin + 12 ] = si4.x;
					skinIndexArray[ offset_skin + 13 ] = si4.y;
					skinIndexArray[ offset_skin + 14 ] = si4.z;
					skinIndexArray[ offset_skin + 15 ] = si4.w;

					// vertices A
1591

A
alteredq 已提交
1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617
					sa1 = obj_skinVerticesA[ face.a ];
					sa2 = obj_skinVerticesA[ face.b ];
					sa3 = obj_skinVerticesA[ face.c ];
					sa4 = obj_skinVerticesA[ face.d ];

					skinVertexAArray[ offset_skin ]     = sa1.x;
					skinVertexAArray[ offset_skin + 1 ] = sa1.y;
					skinVertexAArray[ offset_skin + 2 ] = sa1.z;
					skinVertexAArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader

					skinVertexAArray[ offset_skin + 4 ] = sa2.x;
					skinVertexAArray[ offset_skin + 5 ] = sa2.y;
					skinVertexAArray[ offset_skin + 6 ] = sa2.z;
					skinVertexAArray[ offset_skin + 7 ] = 1;

					skinVertexAArray[ offset_skin + 8 ]  = sa3.x;
					skinVertexAArray[ offset_skin + 9 ]  = sa3.y;
					skinVertexAArray[ offset_skin + 10 ] = sa3.z;
					skinVertexAArray[ offset_skin + 11 ] = 1;

					skinVertexAArray[ offset_skin + 12 ] = sa4.x;
					skinVertexAArray[ offset_skin + 13 ] = sa4.y;
					skinVertexAArray[ offset_skin + 14 ] = sa4.z;
					skinVertexAArray[ offset_skin + 15 ] = 1;

					// vertices B
1618

A
alteredq 已提交
1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638
					sb1 = obj_skinVerticesB[ face.a ];
					sb2 = obj_skinVerticesB[ face.b ];
					sb3 = obj_skinVerticesB[ face.c ];
					sb4 = obj_skinVerticesB[ face.d ];

					skinVertexBArray[ offset_skin ]     = sb1.x;
					skinVertexBArray[ offset_skin + 1 ] = sb1.y;
					skinVertexBArray[ offset_skin + 2 ] = sb1.z;
					skinVertexBArray[ offset_skin + 3 ] = 1; // pad for faster vertex shader

					skinVertexBArray[ offset_skin + 4 ] = sb2.x;
					skinVertexBArray[ offset_skin + 5 ] = sb2.y;
					skinVertexBArray[ offset_skin + 6 ] = sb2.z;
					skinVertexBArray[ offset_skin + 7 ] = 1;

					skinVertexBArray[ offset_skin + 8 ]  = sb3.x;
					skinVertexBArray[ offset_skin + 9 ]  = sb3.y;
					skinVertexBArray[ offset_skin + 10 ] = sb3.z;
					skinVertexBArray[ offset_skin + 11 ] = 1;

1639 1640
					skinVertexBArray[ offset_skin + 12 ] = sb4.x;
					skinVertexBArray[ offset_skin + 13 ] = sb4.y;
A
alteredq 已提交
1641 1642 1643
					skinVertexBArray[ offset_skin + 14 ] = sb4.z;
					skinVertexBArray[ offset_skin + 15 ] = 1;

1644 1645
					offset_skin += 16;

A
alteredq 已提交
1646
				}
1647

1648 1649 1650
				if ( dirtyColors && vertexColorType ) {

					if ( vertexColors.length == 4 && vertexColorType == THREE.VertexColors ) {
1651

1652 1653 1654 1655 1656 1657
						c1 = vertexColors[ 0 ];
						c2 = vertexColors[ 1 ];
						c3 = vertexColors[ 2 ];
						c4 = vertexColors[ 3 ];

					} else {
1658

1659 1660 1661 1662 1663 1664
						c1 = faceColor;
						c2 = faceColor;
						c3 = faceColor;
						c4 = faceColor;

					}
1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676

					colorArray[ offset_color ]     = c1.r;
					colorArray[ offset_color + 1 ] = c1.g;
					colorArray[ offset_color + 2 ] = c1.b;

					colorArray[ offset_color + 3 ] = c2.r;
					colorArray[ offset_color + 4 ] = c2.g;
					colorArray[ offset_color + 5 ] = c2.b;

					colorArray[ offset_color + 6 ] = c3.r;
					colorArray[ offset_color + 7 ] = c3.g;
					colorArray[ offset_color + 8 ] = c3.b;
1677

1678 1679 1680
					colorArray[ offset_color + 9 ]  = c4.r;
					colorArray[ offset_color + 10 ] = c4.g;
					colorArray[ offset_color + 11 ] = c4.b;
1681

1682 1683
					offset_color += 12;

1684 1685
				}

1686
				if ( dirtyTangents && geometry.hasTangents ) {
1687

1688 1689 1690 1691
					t1 = vertexTangents[ 0 ];
					t2 = vertexTangents[ 1 ];
					t3 = vertexTangents[ 2 ];
					t4 = vertexTangents[ 3 ];
1692

1693 1694 1695 1696
					tangentArray[ offset_tangent ]     = t1.x;
					tangentArray[ offset_tangent + 1 ] = t1.y;
					tangentArray[ offset_tangent + 2 ] = t1.z;
					tangentArray[ offset_tangent + 3 ] = t1.w;
M
Mr.doob 已提交
1697

1698 1699 1700 1701
					tangentArray[ offset_tangent + 4 ] = t2.x;
					tangentArray[ offset_tangent + 5 ] = t2.y;
					tangentArray[ offset_tangent + 6 ] = t2.z;
					tangentArray[ offset_tangent + 7 ] = t2.w;
M
Mr.doob 已提交
1702

1703 1704
					tangentArray[ offset_tangent + 8 ]  = t3.x;
					tangentArray[ offset_tangent + 9 ]  = t3.y;
1705 1706
					tangentArray[ offset_tangent + 10 ] = t3.z;
					tangentArray[ offset_tangent + 11 ] = t3.w;
M
Mr.doob 已提交
1707

1708 1709 1710 1711
					tangentArray[ offset_tangent + 12 ] = t4.x;
					tangentArray[ offset_tangent + 13 ] = t4.y;
					tangentArray[ offset_tangent + 14 ] = t4.z;
					tangentArray[ offset_tangent + 15 ] = t4.w;
M
Mr.doob 已提交
1712

1713
					offset_tangent += 16;
M
Mr.doob 已提交
1714

1715
				}
M
Mr.doob 已提交
1716

M
Mr.doob 已提交
1717
				if ( dirtyNormals && normalType ) {
M
Mr.doob 已提交
1718

1719
					if ( vertexNormals.length == 4 && needsSmoothNormals ) {
1720

1721
						for ( i = 0; i < 4; i ++ ) {
1722

1723
							vn = vertexNormals[ i ];
M
Mr.doob 已提交
1724

1725 1726 1727
							normalArray[ offset_normal ]     = vn.x;
							normalArray[ offset_normal + 1 ] = vn.y;
							normalArray[ offset_normal + 2 ] = vn.z;
M
Mr.doob 已提交
1728

1729
							offset_normal += 3;
M
Mr.doob 已提交
1730

1731
						}
M
Mr.doob 已提交
1732

1733
					} else {
1734

1735
						for ( i = 0; i < 4; i ++ ) {
1736

1737 1738 1739
							normalArray[ offset_normal ]     = faceNormal.x;
							normalArray[ offset_normal + 1 ] = faceNormal.y;
							normalArray[ offset_normal + 2 ] = faceNormal.z;
M
Mr.doob 已提交
1740

1741
							offset_normal += 3;
M
Mr.doob 已提交
1742

1743
						}
M
Mr.doob 已提交
1744 1745

					}
M
Mr.doob 已提交
1746

1747 1748
				}

A
alteredq 已提交
1749
				if ( dirtyUvs && uv !== undefined && uvType ) {
1750

M
Mr.doob 已提交
1751 1752
					for ( i = 0; i < 4; i ++ ) {

1753
						uvi = uv[ i ];
M
Mr.doob 已提交
1754

1755 1756
						uvArray[ offset_uv ]     = uvi.u;
						uvArray[ offset_uv + 1 ] = uvi.v;
M
Mr.doob 已提交
1757

1758
						offset_uv += 2;
M
Mr.doob 已提交
1759

M
Mr.doob 已提交
1760
					}
1761 1762

				}
1763

A
alteredq 已提交
1764
				if ( dirtyUvs && uv2 !== undefined && uvType ) {
1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777

					for ( i = 0; i < 4; i ++ ) {

						uv2i = uv2[ i ];

						uv2Array[ offset_uv2 ]     = uv2i.u;
						uv2Array[ offset_uv2 + 1 ] = uv2i.v;

						offset_uv2 += 2;

					}

				}
M
Mr.doob 已提交
1778

1779
				if ( dirtyElements ) {
M
Mr.doob 已提交
1780

1781
					faceArray[ offset_face ]     = vertexIndex;
1782 1783
					faceArray[ offset_face + 1 ] = vertexIndex + 1;
					faceArray[ offset_face + 2 ] = vertexIndex + 3;
M
Mr.doob 已提交
1784

1785 1786 1787
					faceArray[ offset_face + 3 ] = vertexIndex + 1;
					faceArray[ offset_face + 4 ] = vertexIndex + 2;
					faceArray[ offset_face + 5 ] = vertexIndex + 3;
M
Mr.doob 已提交
1788

1789
					offset_face += 6;
M
Mr.doob 已提交
1790

1791 1792
					lineArray[ offset_line ]     = vertexIndex;
					lineArray[ offset_line + 1 ] = vertexIndex + 1;
M
Mr.doob 已提交
1793

1794
					lineArray[ offset_line + 2 ] = vertexIndex;
1795
					lineArray[ offset_line + 3 ] = vertexIndex + 3;
M
Mr.doob 已提交
1796

1797 1798
					lineArray[ offset_line + 4 ] = vertexIndex + 1;
					lineArray[ offset_line + 5 ] = vertexIndex + 2;
M
Mr.doob 已提交
1799

1800 1801
					lineArray[ offset_line + 6 ] = vertexIndex + 2;
					lineArray[ offset_line + 7 ] = vertexIndex + 3;
M
Mr.doob 已提交
1802

1803
					offset_line += 8;
M
Mr.doob 已提交
1804

1805
					vertexIndex += 4;
M
Mr.doob 已提交
1806

1807
				}
M
Mr.doob 已提交
1808

1809
			}
M
Mr.doob 已提交
1810

1811 1812
		}

1813
		if ( dirtyVertices ) {
M
Mr.doob 已提交
1814

1815
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
1816
			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
M
Mr.doob 已提交
1817

1818
		}
M
Mr.doob 已提交
1819

1820
		if ( customAttributes ) {
M
Mr.doob 已提交
1821

1822
			for ( a in customAttributes ) {
M
Mr.doob 已提交
1823

1824 1825
				customAttribute = customAttributes[ a ];

1826
				if ( customAttribute.__original.needsUpdate ) {
1827 1828 1829 1830 1831 1832 1833 1834 1835 1836

					_gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
					_gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );

				}

			}

		}

1837
		if ( dirtyMorphTargets ) {
1838 1839 1840 1841

			for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) {

				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ vk ] );
1842
				_gl.bufferData( _gl.ARRAY_BUFFER, morphTargetsArrays[ vk ], hint );
1843

1844
			}
1845

1846 1847
		}

1848
		if ( dirtyColors && offset_color > 0 ) {
1849

1850
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
1851 1852 1853
			_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );

		}
1854

1855
		if ( dirtyNormals ) {
M
Mr.doob 已提交
1856

1857
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
1858
			_gl.bufferData( _gl.ARRAY_BUFFER, normalArray, hint );
M
Mr.doob 已提交
1859

1860 1861
		}

1862
		if ( dirtyTangents && geometry.hasTangents ) {
1863

1864
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
1865
			_gl.bufferData( _gl.ARRAY_BUFFER, tangentArray, hint );
M
Mr.doob 已提交
1866

1867
		}
1868

1869
		if ( dirtyUvs && offset_uv > 0 ) {
M
Mr.doob 已提交
1870

1871
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
1872
			_gl.bufferData( _gl.ARRAY_BUFFER, uvArray, hint );
M
Mr.doob 已提交
1873

1874
		}
M
Mr.doob 已提交
1875

1876 1877
		if ( dirtyUvs && offset_uv2 > 0 ) {

1878
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
1879 1880 1881 1882
			_gl.bufferData( _gl.ARRAY_BUFFER, uv2Array, hint );

		}

1883
		if ( dirtyElements ) {
M
Mr.doob 已提交
1884

1885
			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
1886
			_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, faceArray, hint );
1887

1888
			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
1889
			_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, lineArray, hint );
M
Mr.doob 已提交
1890

1891
		}
1892

1893
		if ( offset_skin > 0 ) {
1894

1895
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexABuffer );
A
alteredq 已提交
1896 1897
			_gl.bufferData( _gl.ARRAY_BUFFER, skinVertexAArray, hint );

1898
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexBBuffer );
A
alteredq 已提交
1899 1900
			_gl.bufferData( _gl.ARRAY_BUFFER, skinVertexBArray, hint );

1901
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
A
alteredq 已提交
1902 1903
			_gl.bufferData( _gl.ARRAY_BUFFER, skinIndexArray, hint );

1904
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
A
alteredq 已提交
1905
			_gl.bufferData( _gl.ARRAY_BUFFER, skinWeightArray, hint );
1906

A
alteredq 已提交
1907
		}
1908

1909
		if ( dispose ) {
1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925

			delete geometryGroup.__inittedArrays;
			delete geometryGroup.__colorArray;
			delete geometryGroup.__normalArray;
			delete geometryGroup.__tangentArray;
			delete geometryGroup.__uvArray;
			delete geometryGroup.__uv2Array;
			delete geometryGroup.__faceArray;
			delete geometryGroup.__vertexArray;
			delete geometryGroup.__lineArray;
			delete geometryGroup.__skinVertexAArray;
			delete geometryGroup.__skinVertexBArray;
			delete geometryGroup.__skinIndexArray;
			delete geometryGroup.__skinWeightArray;

		}
1926

1927
	};
1928

1929
	function setLineBuffers ( geometry, hint ) {
M
Mr.doob 已提交
1930

1931
		var v, c, vertex, offset,
1932 1933 1934 1935
		vertices = geometry.vertices,
		colors = geometry.colors,
		vl = vertices.length,
		cl = colors.length,
M
Mr.doob 已提交
1936

1937 1938
		vertexArray = geometry.__vertexArray,
		colorArray = geometry.__colorArray,
1939

1940 1941
		dirtyVertices = geometry.__dirtyVertices,
		dirtyColors = geometry.__dirtyColors;
M
Mr.doob 已提交
1942

1943
		if ( dirtyVertices ) {
M
Mr.doob 已提交
1944

1945
			for ( v = 0; v < vl; v ++ ) {
M
Mr.doob 已提交
1946

1947
				vertex = vertices[ v ].position;
M
Mr.doob 已提交
1948

1949
				offset = v * 3;
M
Mr.doob 已提交
1950

1951 1952 1953
				vertexArray[ offset ]     = vertex.x;
				vertexArray[ offset + 1 ] = vertex.y;
				vertexArray[ offset + 2 ] = vertex.z;
M
Mr.doob 已提交
1954

1955 1956
			}

1957
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
A
alteredq 已提交
1958 1959
			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );

1960
		}
M
Mr.doob 已提交
1961

1962 1963
		if ( dirtyColors ) {

1964
			for ( c = 0; c < cl; c ++ ) {
1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975

				color = colors[ c ];

				offset = c * 3;

				colorArray[ offset ]     = color.r;
				colorArray[ offset + 1 ] = color.g;
				colorArray[ offset + 2 ] = color.b;

			}

1976
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
1977 1978 1979 1980
			_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );

		}

1981
	};
M
Mr.doob 已提交
1982

1983
	function setRibbonBuffers ( geometry, hint ) {
A
alteredq 已提交
1984 1985

		var v, c, vertex, offset,
1986 1987 1988 1989
		vertices = geometry.vertices,
		colors = geometry.colors,
		vl = vertices.length,
		cl = colors.length,
A
alteredq 已提交
1990

1991 1992
		vertexArray = geometry.__vertexArray,
		colorArray = geometry.__colorArray,
1993

1994 1995
		dirtyVertices = geometry.__dirtyVertices,
		dirtyColors = geometry.__dirtyColors;
A
alteredq 已提交
1996 1997 1998

		if ( dirtyVertices ) {

1999
			for ( v = 0; v < vl; v ++ ) {
A
alteredq 已提交
2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010

				vertex = vertices[ v ].position;

				offset = v * 3;

				vertexArray[ offset ]     = vertex.x;
				vertexArray[ offset + 1 ] = vertex.y;
				vertexArray[ offset + 2 ] = vertex.z;

			}

2011
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
A
alteredq 已提交
2012 2013 2014 2015 2016 2017
			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );

		}

		if ( dirtyColors ) {

2018
			for ( c = 0; c < cl; c ++ ) {
A
alteredq 已提交
2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029

				color = colors[ c ];

				offset = c * 3;

				colorArray[ offset ]     = color.r;
				colorArray[ offset + 1 ] = color.g;
				colorArray[ offset + 2 ] = color.b;

			}

2030
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
A
alteredq 已提交
2031 2032 2033 2034 2035
			_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );

		}

	};
2036

2037
	function setParticleBuffers ( geometry, hint, object ) {
2038

A
alteredq 已提交
2039
		var v, c, vertex, offset,
2040 2041
		vertices = geometry.vertices,
		vl = vertices.length,
2042

2043 2044
		colors = geometry.colors,
		cl = colors.length,
2045

2046 2047
		vertexArray = geometry.__vertexArray,
		colorArray = geometry.__colorArray,
2048

2049
		sortArray = geometry.__sortArray,
2050

2051 2052
		dirtyVertices = geometry.__dirtyVertices,
		dirtyElements = geometry.__dirtyElements,
2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068
		dirtyColors = geometry.__dirtyColors,

		customAttributes = geometry.__webglCustomAttributes,
		a, ca, cal, v1,
		offset_custom,
		customAttribute;

		if ( customAttributes ) {

			for ( a in customAttributes ) {

				customAttributes[ a ].offset = 0;

			}

		}
2069

2070
		if ( object.sortParticles ) {
2071

2072
			_projScreenMatrix.multiplySelf( object.matrixWorld );
2073

2074 2075 2076
			for ( v = 0; v < vl; v++ ) {

				vertex = vertices[ v ].position;
2077

2078 2079
				_vector3.copy( vertex );
				_projScreenMatrix.multiplyVector3( _vector3 );
2080

2081
				sortArray[ v ] = [ _vector3.z, v ];
2082

2083
			}
2084

2085
			sortArray.sort( function( a, b ) { return b[ 0 ] - a[ 0 ]; } );
2086

2087
			for ( v = 0; v < vl; v++ ) {
2088

2089
				vertex = vertices[ sortArray[v][1] ].position;
2090

2091
				offset = v * 3;
2092

2093 2094 2095
				vertexArray[ offset ]     = vertex.x;
				vertexArray[ offset + 1 ] = vertex.y;
				vertexArray[ offset + 2 ] = vertex.z;
2096

2097
			}
2098

2099
			for ( c = 0; c < cl; c ++ ) {
2100

A
alteredq 已提交
2101
				offset = c * 3;
2102

A
alteredq 已提交
2103 2104 2105 2106 2107
				color = colors[ sortArray[c][1] ];

				colorArray[ offset ]     = color.r;
				colorArray[ offset + 1 ] = color.g;
				colorArray[ offset + 2 ] = color.b;
2108

2109
			}
2110

2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180
			if ( customAttributes ) {

				for ( a in customAttributes ) {

					customAttribute = customAttributes[ a ];

					cal = customAttribute.value.length;

					for ( ca = 0; ca < cal; ca ++ ) {

						index = sortArray[ca][1];

						offset_custom = customAttribute.offset;

						if ( customAttribute.size === 1 ) {

							if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {

								customAttribute.array[ offset_custom ] = customAttribute.value[ index ];

							}

						} else {

							if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {

								v1 = customAttribute.value[ index ];

							}

							if ( customAttribute.size === 2 ) {

								customAttribute.array[ offset_custom ] 	   = v1.x;
								customAttribute.array[ offset_custom + 1 ] = v1.y;

							} else if ( customAttribute.size === 3 ) {

								if ( customAttribute.type === "c" ) {

									customAttribute.array[ offset_custom ] 	   = v1.r;
									customAttribute.array[ offset_custom + 1 ] = v1.g;
									customAttribute.array[ offset_custom + 2 ] = v1.b;

								} else {

									customAttribute.array[ offset_custom ] 	   = v1.x;
									customAttribute.array[ offset_custom + 1 ] = v1.y;
									customAttribute.array[ offset_custom + 2 ] = v1.z;

								}

							} else {

								customAttribute.array[ offset_custom ] 		= v1.x;
								customAttribute.array[ offset_custom + 1  ] = v1.y;
								customAttribute.array[ offset_custom + 2  ] = v1.z;
								customAttribute.array[ offset_custom + 3  ] = v1.w;

							}

						}

						customAttribute.offset += customAttribute.size;

					}

				}

			}

2181

2182
		} else {
2183

2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196
			if ( dirtyVertices ) {

				for ( v = 0; v < vl; v++ ) {

					vertex = vertices[ v ].position;

					offset = v * 3;

					vertexArray[ offset ]     = vertex.x;
					vertexArray[ offset + 1 ] = vertex.y;
					vertexArray[ offset + 2 ] = vertex.z;

				}
2197 2198

			}
2199

A
alteredq 已提交
2200
			if ( dirtyColors ) {
2201

2202
				for ( c = 0; c < cl; c ++ ) {
A
alteredq 已提交
2203 2204 2205 2206 2207 2208 2209 2210 2211

					color = colors[ c ];

					offset = c * 3;

					colorArray[ offset ]     = color.r;
					colorArray[ offset + 1 ] = color.g;
					colorArray[ offset + 2 ] = color.b;

2212
				}
2213

A
alteredq 已提交
2214
			}
2215

2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288
			if ( customAttributes ) {

				for ( a in customAttributes ) {

					customAttribute = customAttributes[ a ];

					if ( customAttribute.__original.needsUpdate ) {

						cal = customAttribute.value.length;

						for ( ca = 0; ca < cal; ca ++ ) {

							offset_custom = customAttribute.offset;

							if ( customAttribute.size === 1 ) {

								if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {

									customAttribute.array[ offset_custom ] = customAttribute.value[ ca ];

								}

							} else {

								if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {

									v1 = customAttribute.value[ ca ];

								}

								if ( customAttribute.size === 2 ) {

									customAttribute.array[ offset_custom ] 	   = v1.x;
									customAttribute.array[ offset_custom + 1 ] = v1.y;

								} else if ( customAttribute.size === 3 ) {

									if ( customAttribute.type === "c" ) {

										customAttribute.array[ offset_custom ] 	   = v1.r;
										customAttribute.array[ offset_custom + 1 ] = v1.g;
										customAttribute.array[ offset_custom + 2 ] = v1.b;


									} else {

										customAttribute.array[ offset_custom ] 	   = v1.x;
										customAttribute.array[ offset_custom + 1 ] = v1.y;
										customAttribute.array[ offset_custom + 2 ] = v1.z;

									}

								} else {

									customAttribute.array[ offset_custom ] 		= v1.x;
									customAttribute.array[ offset_custom + 1  ] = v1.y;
									customAttribute.array[ offset_custom + 2  ] = v1.z;
									customAttribute.array[ offset_custom + 3  ] = v1.w;

								}

							}

							customAttribute.offset += customAttribute.size;

						}

					}

				}

			}

2289
		}
2290

A
alteredq 已提交
2291
		if ( dirtyVertices || object.sortParticles ) {
2292

2293
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
A
alteredq 已提交
2294
			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
2295

A
alteredq 已提交
2296
		}
2297

A
alteredq 已提交
2298
		if ( dirtyColors || object.sortParticles ) {
2299

2300
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
A
alteredq 已提交
2301
			_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
2302

A
alteredq 已提交
2303
		}
2304

2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322
		if ( customAttributes ) {

			for ( a in customAttributes ) {

				customAttribute = customAttributes[ a ];

				if ( customAttribute.__original.needsUpdate || object.sortParticles ) {

					_gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
					_gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );

				}

			}

		}


2323
	};
M
Mr.doob 已提交
2324

2325
	function setMaterialShaders( material, shaders ) {
2326

2327
		material.uniforms = THREE.UniformsUtils.clone( shaders.uniforms );
2328 2329
		material.vertexShader = shaders.vertexShader;
		material.fragmentShader = shaders.fragmentShader;
2330

M
Mr.doob 已提交
2331
	};
2332

2333
	function refreshUniformsCommon( uniforms, material ) {
M
Mr.doob 已提交
2334

M
Mr.doob 已提交
2335
		uniforms.diffuse.value = material.color;
A
alteredq 已提交
2336
		uniforms.opacity.value = material.opacity;
M
Mr.doob 已提交
2337

A
alteredq 已提交
2338
		uniforms.map.texture = material.map;
2339
		if ( material.map ) {
M
Mr.doob 已提交
2340

2341 2342 2343
			uniforms.offsetRepeat.value.set( material.map.offset.x, material.map.offset.y, material.map.repeat.x, material.map.repeat.y );

		}
2344

2345
		uniforms.lightMap.texture = material.lightMap;
2346

2347
		uniforms.envMap.texture = material.envMap;
A
alteredq 已提交
2348
		uniforms.reflectivity.value = material.reflectivity;
2349
		uniforms.refractionRatio.value = material.refractionRatio;
A
alteredq 已提交
2350
		uniforms.combine.value = material.combine;
2351
		uniforms.useRefract.value = material.envMap && material.envMap.mapping instanceof THREE.CubeRefractionMapping;
2352

2353
	};
2354

2355
	function refreshUniformsLine( uniforms, material ) {
2356

M
Mr.doob 已提交
2357
		uniforms.diffuse.value = material.color;
A
alteredq 已提交
2358
		uniforms.opacity.value = material.opacity;
2359 2360

	};
M
Mr.doob 已提交
2361

2362
	function refreshUniformsParticle( uniforms, material ) {
2363

M
Mr.doob 已提交
2364
		uniforms.psColor.value = material.color;
A
alteredq 已提交
2365 2366
		uniforms.opacity.value = material.opacity;
		uniforms.size.value = material.size;
M
Mr.doob 已提交
2367
		uniforms.scale.value = _canvas.height / 2.0; // TODO: Cache this.
2368

A
alteredq 已提交
2369
		uniforms.map.texture = material.map;
2370

A
alteredq 已提交
2371
	};
2372

2373
	function refreshUniformsFog( uniforms, fog ) {
2374

M
Mr.doob 已提交
2375
		uniforms.fogColor.value = fog.color;
2376

A
alteredq 已提交
2377
		if ( fog instanceof THREE.Fog ) {
2378

A
alteredq 已提交
2379 2380
			uniforms.fogNear.value = fog.near;
			uniforms.fogFar.value = fog.far;
2381

A
alteredq 已提交
2382
		} else if ( fog instanceof THREE.FogExp2 ) {
2383

A
alteredq 已提交
2384
			uniforms.fogDensity.value = fog.density;
2385 2386

		}
2387

2388 2389
	};

2390
	function refreshUniformsPhong( uniforms, material ) {
M
Mr.doob 已提交
2391

M
Mr.doob 已提交
2392 2393
		uniforms.ambient.value = material.ambient;
		uniforms.specular.value = material.specular;
A
alteredq 已提交
2394
		uniforms.shininess.value = material.shininess;
M
Mr.doob 已提交
2395

2396
	};
M
Mr.doob 已提交
2397 2398


2399
	function refreshUniformsLights( uniforms, lights ) {
M
Mr.doob 已提交
2400

A
alteredq 已提交
2401 2402
		uniforms.enableLighting.value = lights.directional.length + lights.point.length;
		uniforms.ambientLightColor.value = lights.ambient;
2403

A
alteredq 已提交
2404 2405
		uniforms.directionalLightColor.value = lights.directional.colors;
		uniforms.directionalLightDirection.value = lights.directional.positions;
2406

A
alteredq 已提交
2407 2408
		uniforms.pointLightColor.value = lights.point.colors;
		uniforms.pointLightPosition.value = lights.point.positions;
2409
		uniforms.pointLightDistance.value = lights.point.distances;
M
Mr.doob 已提交
2410

A
alteredq 已提交
2411
	};
M
Mr.doob 已提交
2412

2413 2414 2415 2416
	function refreshUniformsShadow( uniforms, material ) {

		if ( uniforms.shadowMatrix ) {

2417 2418 2419 2420 2421 2422 2423
			for ( var i = 0; i < _shadowMatrix.length; i ++ ) {

				uniforms.shadowMatrix.value[ i ] = _shadowMatrix[ i ];
				uniforms.shadowMap.texture[ i ] = _this.shadowMap[ i ];


			}
2424 2425 2426 2427 2428 2429 2430 2431

			uniforms.shadowDarkness.value = _this.shadowMapDarkness;
			uniforms.shadowBias.value = _this.shadowMapBias;

		}

	};

2432
	this.initMaterial = function ( material, lights, fog, object ) {
M
Mr.doob 已提交
2433

2434
		var u, a, identifiers, i, parameters, maxLightCount, maxBones, maxShadows, shaderID;
2435

A
alteredq 已提交
2436
		if ( material instanceof THREE.MeshDepthMaterial ) {
2437

2438
			shaderID = 'depth';
2439

A
alteredq 已提交
2440
		} else if ( material instanceof THREE.MeshNormalMaterial ) {
2441

2442
			shaderID = 'normal';
2443

A
alteredq 已提交
2444
		} else if ( material instanceof THREE.MeshBasicMaterial ) {
2445

2446
			shaderID = 'basic';
2447

A
alteredq 已提交
2448
		} else if ( material instanceof THREE.MeshLambertMaterial ) {
M
Mr.doob 已提交
2449

2450
			shaderID = 'lambert';
M
Mr.doob 已提交
2451

A
alteredq 已提交
2452
		} else if ( material instanceof THREE.MeshPhongMaterial ) {
M
Mr.doob 已提交
2453

2454
			shaderID = 'phong';
M
Mr.doob 已提交
2455

A
alteredq 已提交
2456
		} else if ( material instanceof THREE.LineBasicMaterial ) {
M
Mr.doob 已提交
2457

2458
			shaderID = 'basic';
2459

A
alteredq 已提交
2460
		} else if ( material instanceof THREE.ParticleBasicMaterial ) {
2461

2462 2463 2464 2465 2466 2467 2468
			shaderID = 'particle_basic';

		}

		if ( shaderID ) {

			setMaterialShaders( material, THREE.ShaderLib[ shaderID ] );
2469

A
alteredq 已提交
2470
		}
2471

2472 2473
		// heuristics to create shader parameters according to lights in the scene
		// (not to blow over maxLights budget)
M
Mr.doob 已提交
2474

2475
		maxLightCount = allocateLights( lights );
2476

2477 2478
		maxShadows = allocateShadows( lights );

2479
		maxBones = allocateBones( object );
M
Mr.doob 已提交
2480

2481
		parameters = {
2482

M
Mr.doob 已提交
2483
			map: !!material.map, envMap: !!material.envMap, lightMap: !!material.lightMap,
2484
			vertexColors: material.vertexColors,
2485 2486 2487
			fog: fog, sizeAttenuation: material.sizeAttenuation,
			skinning: material.skinning,
			morphTargets: material.morphTargets,
2488
			maxMorphTargets: this.maxMorphTargets,
2489
			maxDirLights: maxLightCount.directional, maxPointLights: maxLightCount.point,
2490
			maxBones: maxBones,
2491
			shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow,
2492 2493 2494
			shadowMapSoft: this.shadowMapSoft,
			shadowMapWidth: this.shadowMapWidth,
			shadowMapHeight: this.shadowMapHeight,
2495 2496
			maxShadows: maxShadows,
			alphaTest: material.alphaTest
2497

2498
		};
M
Mikael Emtinger 已提交
2499

2500
		material.program = buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, parameters );
2501

2502
		var attributes = material.program.attributes;
2503

2504
		if ( attributes.position >= 0 ) _gl.enableVertexAttribArray( attributes.position );
2505 2506 2507
		if ( attributes.color >= 0 ) _gl.enableVertexAttribArray( attributes.color );
		if ( attributes.normal >= 0 ) _gl.enableVertexAttribArray( attributes.normal );
		if ( attributes.tangent >= 0 ) _gl.enableVertexAttribArray( attributes.tangent );
2508

2509 2510 2511
		if ( material.skinning &&
			 attributes.skinVertexA >=0 && attributes.skinVertexB >= 0 &&
			 attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
2512

2513 2514 2515 2516
			_gl.enableVertexAttribArray( attributes.skinVertexA );
			_gl.enableVertexAttribArray( attributes.skinVertexB );
			_gl.enableVertexAttribArray( attributes.skinIndex );
			_gl.enableVertexAttribArray( attributes.skinWeight );
2517

2518
		}
2519

2520
		if ( material.attributes ) {
M
Mr.doob 已提交
2521

2522
			for ( a in material.attributes ) {
M
Mr.doob 已提交
2523

2524
				if( attributes[ a ] !== undefined && attributes[ a ] >= 0 ) _gl.enableVertexAttribArray( attributes[ a ] );
M
Mr.doob 已提交
2525

2526
			}
M
Mr.doob 已提交
2527

2528
		}
2529

2530
		if ( material.morphTargets ) {
2531

2532
			material.numSupportedMorphTargets = 0;
2533

2534
			var id, base = "morphTarget";
2535

2536
			for ( i = 0; i < this.maxMorphTargets; i ++ ) {
2537

2538
				id = base + i;
2539

2540
				if ( attributes[ id ] >= 0 ) {
2541

2542 2543
					_gl.enableVertexAttribArray( attributes[ id ] );
					material.numSupportedMorphTargets ++;
2544

2545
				}
2546

2547
			}
2548

2549
		}
M
Mr.doob 已提交
2550

2551
	};
2552

2553
	function setProgram( camera, lights, fog, material, object ) {
2554

2555
		if ( ! material.program ) {
2556 2557 2558 2559

			_this.initMaterial( material, lights, fog, object );

		}
M
Mr.doob 已提交
2560

2561 2562 2563 2564 2565 2566
		if ( material.morphTargets ) {

			if ( ! object.__webglMorphTargetInfluences ) {

				object.__webglMorphTargetInfluences = new Float32Array( _this.maxMorphTargets );

2567
				for ( var i = 0, il = _this.maxMorphTargets; i < il; i ++ ) {
2568 2569 2570 2571 2572 2573 2574 2575 2576

					object.__webglMorphTargetInfluences[ i ] = 0;

				}

			}

		}

2577
		var program = material.program,
A
alteredq 已提交
2578 2579
			p_uniforms = program.uniforms,
			m_uniforms = material.uniforms;
2580

2581
		if ( program != _currentProgram ) {
M
Mr.doob 已提交
2582

M
Mr.doob 已提交
2583
			_gl.useProgram( program );
2584
			_currentProgram = program;
2585

M
Mr.doob 已提交
2586
		}
2587

2588 2589
		_gl.uniformMatrix4fv( p_uniforms.projectionMatrix, false, _projectionMatrixArray );

A
alteredq 已提交
2590
		// refresh uniforms common to several materials
2591 2592

		if ( fog && (
A
alteredq 已提交
2593 2594
			 material instanceof THREE.MeshBasicMaterial ||
			 material instanceof THREE.MeshLambertMaterial ||
2595
			 material instanceof THREE.MeshPhongMaterial ||
A
alteredq 已提交
2596
			 material instanceof THREE.LineBasicMaterial ||
2597 2598
			 material instanceof THREE.ParticleBasicMaterial ||
			 material.fog )
A
alteredq 已提交
2599
			) {
2600

A
alteredq 已提交
2601
			refreshUniformsFog( m_uniforms, fog );
2602 2603

		}
M
Mr.doob 已提交
2604

M
Mr.doob 已提交
2605
		if ( material instanceof THREE.MeshPhongMaterial ||
2606 2607
			 material instanceof THREE.MeshLambertMaterial ||
			 material.lights ) {
2608

A
alteredq 已提交
2609
			setupLights( program, lights );
A
alteredq 已提交
2610
			refreshUniformsLights( m_uniforms, _lights );
M
Mr.doob 已提交
2611 2612 2613

		}

2614 2615 2616
		if ( material instanceof THREE.MeshBasicMaterial ||
			 material instanceof THREE.MeshLambertMaterial ||
			 material instanceof THREE.MeshPhongMaterial ) {
M
Mr.doob 已提交
2617

A
alteredq 已提交
2618
			refreshUniformsCommon( m_uniforms, material );
M
Mr.doob 已提交
2619

A
alteredq 已提交
2620
		}
M
Mr.doob 已提交
2621

A
alteredq 已提交
2622
		// refresh single material specific uniforms
2623

2624
		if ( material instanceof THREE.LineBasicMaterial ) {
M
Mr.doob 已提交
2625

A
alteredq 已提交
2626
			refreshUniformsLine( m_uniforms, material );
2627

A
alteredq 已提交
2628
		} else if ( material instanceof THREE.ParticleBasicMaterial ) {
2629

A
alteredq 已提交
2630
			refreshUniformsParticle( m_uniforms, material );
2631

A
alteredq 已提交
2632
		} else if ( material instanceof THREE.MeshPhongMaterial ) {
M
Mr.doob 已提交
2633

A
alteredq 已提交
2634
			refreshUniformsPhong( m_uniforms, material );
M
Mr.doob 已提交
2635

A
alteredq 已提交
2636
		} else if ( material instanceof THREE.MeshDepthMaterial ) {
M
Mr.doob 已提交
2637

2638 2639
			m_uniforms.mNear.value = camera.near;
			m_uniforms.mFar.value = camera.far;
A
alteredq 已提交
2640
			m_uniforms.opacity.value = material.opacity;
2641

A
alteredq 已提交
2642
		} else if ( material instanceof THREE.MeshNormalMaterial ) {
2643

A
alteredq 已提交
2644
			m_uniforms.opacity.value = material.opacity;
2645 2646 2647 2648 2649 2650 2651

		}

		if ( object.receiveShadow && ! material._shadowPass ) {

			refreshUniformsShadow( m_uniforms, material );

2652
		}
2653

A
alteredq 已提交
2654
		// load common uniforms
2655

A
alteredq 已提交
2656 2657
		loadUniformsGeneric( program, m_uniforms );
		loadUniformsMatrices( p_uniforms, object );
2658

A
alteredq 已提交
2659 2660
		// load material specific uniforms
		// (shader material also gets them for the sake of genericity)
2661

A
alteredq 已提交
2662 2663
		if ( material instanceof THREE.MeshShaderMaterial ||
			 material instanceof THREE.MeshPhongMaterial ||
2664
			 material.envMap ) {
2665

2666
			if( p_uniforms.cameraPosition !== null ) {
M
Mr.doob 已提交
2667

2668
				_gl.uniform3f( p_uniforms.cameraPosition, camera.position.x, camera.position.y, camera.position.z );
M
Mr.doob 已提交
2669

2670
			}
2671

2672
		}
2673

A
alteredq 已提交
2674
		if ( material instanceof THREE.MeshShaderMaterial ||
2675
			 material.envMap ||
2676 2677
			 material.skinning ||
			 object.receiveShadow ) {
2678

2679
			if ( p_uniforms.objectMatrix !== null ) {
M
Mr.doob 已提交
2680

2681
				_gl.uniformMatrix4fv( p_uniforms.objectMatrix, false, object._objectMatrixArray );
M
Mr.doob 已提交
2682

2683
			}
2684

A
alteredq 已提交
2685
		}
2686

A
alteredq 已提交
2687 2688
		if ( material instanceof THREE.MeshPhongMaterial ||
			 material instanceof THREE.MeshLambertMaterial ||
A
alteredq 已提交
2689
			 material instanceof THREE.MeshShaderMaterial ||
2690 2691
			 material.skinning ) {

2692
			if( p_uniforms.viewMatrix !== null ) {
M
Mr.doob 已提交
2693

2694
				_gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, _viewMatrixArray );
M
Mr.doob 已提交
2695 2696

			}
2697

A
alteredq 已提交
2698
		}
2699

2700
		if ( material.skinning ) {
2701

2702
			loadUniformsSkinning( p_uniforms, object );
2703

A
alteredq 已提交
2704
		}
2705

A
alteredq 已提交
2706
		return program;
2707

A
alteredq 已提交
2708
	};
2709

2710
	function renderBuffer( camera, lights, fog, material, geometryGroup, object ) {
A
alteredq 已提交
2711

2712 2713
		if ( material.opacity == 0 ) return;

2714
		var program, attributes, linewidth, primitives, a, attribute;
A
alteredq 已提交
2715

A
alteredq 已提交
2716
		program = setProgram( camera, lights, fog, material, object );
2717

2718
		attributes = program.attributes;
M
Mr.doob 已提交
2719

2720
		// vertices
M
Mr.doob 已提交
2721

2722
		if ( !material.morphTargets && attributes.position >= 0 ) {
2723 2724

			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
2725
			_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
2726

2727
		} else {
2728

2729 2730 2731 2732 2733
			if ( object.morphTargetBase ) {

				setupMorphTargets( material, geometryGroup, object );

			}
2734

2735 2736
		}

2737 2738 2739

		// custom attributes

2740 2741
		// Use the per-geometryGroup custom attribute arrays which are setup in initMeshBuffers

2742
		if ( geometryGroup.__webglCustomAttributes ) {
M
Mr.doob 已提交
2743

2744
			for( a in geometryGroup.__webglCustomAttributes ) {
M
Mr.doob 已提交
2745

2746
				if( attributes[ a ] >= 0 ) {
M
Mr.doob 已提交
2747

2748
					attribute = geometryGroup.__webglCustomAttributes[ a ];
M
Mr.doob 已提交
2749

2750 2751
					_gl.bindBuffer( _gl.ARRAY_BUFFER, attribute.buffer );
					_gl.vertexAttribPointer( attributes[ a ], attribute.size, _gl.FLOAT, false, 0, 0 );
M
Mr.doob 已提交
2752

2753
				}
M
Mr.doob 已提交
2754

2755
			}
M
Mr.doob 已提交
2756

2757
		}
2758 2759


2760
/*		if ( material.attributes ) {
2761 2762 2763

			for( a in material.attributes ) {

2764
				if( attributes[ a ] !== undefined && attributes[ a ] >= 0 ) {
2765 2766 2767

					attribute = material.attributes[ a ];

2768
					if( attribute.buffer ) {
M
Mr.doob 已提交
2769

2770 2771 2772 2773
						_gl.bindBuffer( _gl.ARRAY_BUFFER, attribute.buffer );
						_gl.vertexAttribPointer( attributes[ a ], attribute.size, _gl.FLOAT, false, 0, 0 );

					}
2774 2775 2776 2777 2778

				}

			}

2779
		}*/
2780 2781


2782

A
alteredq 已提交
2783 2784 2785 2786
		// colors

		if ( attributes.color >= 0 ) {

2787
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
2788
			_gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
A
alteredq 已提交
2789 2790 2791

		}

2792
		// normals
M
Mr.doob 已提交
2793

2794
		if ( attributes.normal >= 0 ) {
2795

2796
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
2797
			_gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
2798

2799
		}
2800

2801 2802 2803
		// tangents

		if ( attributes.tangent >= 0 ) {
2804

2805
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
2806
			_gl.vertexAttribPointer( attributes.tangent, 4, _gl.FLOAT, false, 0, 0 );
2807

2808
		}
2809

2810
		// uvs
M
Mr.doob 已提交
2811

M
Mr.doob 已提交
2812 2813
		if ( attributes.uv >= 0 ) {

2814
			if ( geometryGroup.__webglUVBuffer ) {
2815

2816
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
2817
				_gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
2818

2819
				_gl.enableVertexAttribArray( attributes.uv );
2820

2821
			} else {
2822

2823
				_gl.disableVertexAttribArray( attributes.uv );
M
Mr.doob 已提交
2824

2825
			}
2826 2827 2828

		}

2829 2830
		if ( attributes.uv2 >= 0 ) {

2831
			if ( geometryGroup.__webglUV2Buffer ) {
2832

2833
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845
				_gl.vertexAttribPointer( attributes.uv2, 2, _gl.FLOAT, false, 0, 0 );

				_gl.enableVertexAttribArray( attributes.uv2 );

			} else {

				_gl.disableVertexAttribArray( attributes.uv2 );

			}

		}

2846
		if ( material.skinning &&
2847
			 attributes.skinVertexA >= 0 && attributes.skinVertexB >= 0 &&
A
alteredq 已提交
2848
			 attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
2849

2850
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexABuffer );
A
alteredq 已提交
2851 2852
			_gl.vertexAttribPointer( attributes.skinVertexA, 4, _gl.FLOAT, false, 0, 0 );

2853
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexBBuffer );
A
alteredq 已提交
2854 2855
			_gl.vertexAttribPointer( attributes.skinVertexB, 4, _gl.FLOAT, false, 0, 0 );

2856
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
A
alteredq 已提交
2857 2858
			_gl.vertexAttribPointer( attributes.skinIndex, 4, _gl.FLOAT, false, 0, 0 );

2859
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
A
alteredq 已提交
2860
			_gl.vertexAttribPointer( attributes.skinWeight, 4, _gl.FLOAT, false, 0, 0 );
2861

A
alteredq 已提交
2862
		}
2863

2864
		// render mesh
M
Mr.doob 已提交
2865

2866
		if ( object instanceof THREE.Mesh ) {
2867

2868
			// wireframe
2869

2870
			if ( material.wireframe ) {
M
Mr.doob 已提交
2871

2872
				_gl.lineWidth( material.wireframeLinewidth );
2873 2874
				_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
				_gl.drawElements( _gl.LINES, geometryGroup.__webglLineCount, _gl.UNSIGNED_SHORT, 0 );
2875

2876
			// triangles
2877

2878
			} else {
2879

2880 2881 2882
				_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
				_gl.drawElements( _gl.TRIANGLES, geometryGroup.__webglFaceCount, _gl.UNSIGNED_SHORT, 0 );

2883
			}
2884

2885 2886
			_this.data.vertices += geometryGroup.__webglFaceCount;
			_this.data.faces += geometryGroup.__webglFaceCount / 3;
2887
			_this.data.drawCalls ++;
2888

2889
		// render lines
2890

2891
		} else if ( object instanceof THREE.Line ) {
2892

2893
			primitives = ( object.type == THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES;
M
Mr.doob 已提交
2894

2895
			_gl.lineWidth( material.linewidth );
2896
			_gl.drawArrays( primitives, 0, geometryGroup.__webglLineCount );
2897

2898 2899
			_this.data.drawCalls ++;

2900
		// render particles
2901

2902
		} else if ( object instanceof THREE.ParticleSystem ) {
2903

2904
			_gl.drawArrays( _gl.POINTS, 0, geometryGroup.__webglParticleCount );
2905

2906 2907
			_this.data.drawCalls ++;

A
alteredq 已提交
2908
		// render ribbon
2909

A
alteredq 已提交
2910
		} else if ( object instanceof THREE.Ribbon ) {
2911

2912
			_gl.drawArrays( _gl.TRIANGLE_STRIP, 0, geometryGroup.__webglVertexCount );
2913

2914 2915
			_this.data.drawCalls ++;

2916 2917 2918 2919
		}

	};

M
Mikael Emtinger 已提交
2920

M
Mikael Emtinger 已提交
2921
	function setupMorphTargets( material, geometryGroup, object ) {
2922

M
Mikael Emtinger 已提交
2923
		// set base
2924

M
Mikael Emtinger 已提交
2925
		var attributes = material.program.attributes;
2926

2927
		if ( object.morphTargetBase !== - 1 ) {
2928 2929

			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ object.morphTargetBase ] );
M
Mikael Emtinger 已提交
2930
			_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
2931

2932
		} else if ( attributes.position >= 0 ) {
2933 2934

			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
M
Mikael Emtinger 已提交
2935
			_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
2936

M
Mikael Emtinger 已提交
2937
		}
2938

2939
		if ( object.morphTargetForcedOrder.length ) {
M
Mikael Emtinger 已提交
2940 2941

			// set forced order
2942

M
Mikael Emtinger 已提交
2943 2944 2945
			var m = 0;
			var order = object.morphTargetForcedOrder;
			var influences = object.morphTargetInfluences;
2946 2947 2948 2949

			while ( m < material.numSupportedMorphTargets && m < order.length ) {

				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ] );
M
Mikael Emtinger 已提交
2950 2951
				_gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );

2952
				object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ] ];
2953 2954 2955

				m ++;
			}
2956

M
Mikael Emtinger 已提交
2957
		} else {
2958

M
Mikael Emtinger 已提交
2959
			// find most influencing
2960

M
Mikael Emtinger 已提交
2961
			var used = [];
2962
			var candidateInfluence = - 1;
M
Mikael Emtinger 已提交
2963 2964 2965 2966
			var candidate = 0;
			var influences = object.morphTargetInfluences;
			var i, il = influences.length;
			var m = 0;
2967

2968
			if ( object.morphTargetBase !== - 1 ) {
2969

M
Mikael Emtinger 已提交
2970
				used[ object.morphTargetBase ] = true;
2971

M
Mikael Emtinger 已提交
2972
			}
2973 2974 2975

			while ( m < material.numSupportedMorphTargets ) {

2976
				for ( i = 0; i < il; i ++ ) {
2977 2978 2979

					if ( !used[ i ] && influences[ i ] > candidateInfluence ) {

M
Mikael Emtinger 已提交
2980 2981
						candidate = i;
						candidateInfluence = influences[ candidate ];
2982

M
Mikael Emtinger 已提交
2983
					}
2984

M
Mikael Emtinger 已提交
2985
				}
2986 2987

				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ candidate ] );
M
Mikael Emtinger 已提交
2988
				_gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
2989 2990 2991

				object.__webglMorphTargetInfluences[ m ] = candidateInfluence;

M
Mikael Emtinger 已提交
2992 2993
				used[ candidate ] = 1;
				candidateInfluence = -1;
2994
				m ++;
2995

M
Mikael Emtinger 已提交
2996
			}
2997

M
Mikael Emtinger 已提交
2998 2999 3000
		}

		// load updated influences uniform
3001

3002
		if( material.program.uniforms.morphTargetInfluences !== null ) {
M
Mr.doob 已提交
3003

3004
			_gl.uniform1fv( material.program.uniforms.morphTargetInfluences, object.__webglMorphTargetInfluences );
M
Mr.doob 已提交
3005

3006 3007
		}

M
Mikael Emtinger 已提交
3008 3009 3010
	}


3011
	function renderBufferImmediate( object, program, shading ) {
3012

3013 3014
		if ( ! object.__webglVertexBuffer ) object.__webglVertexBuffer = _gl.createBuffer();
		if ( ! object.__webglNormalBuffer ) object.__webglNormalBuffer = _gl.createBuffer();
3015

A
alteredq 已提交
3016
		if ( object.hasPos ) {
3017

3018 3019 3020 3021
			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglVertexBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
			_gl.enableVertexAttribArray( program.attributes.position );
			_gl.vertexAttribPointer( program.attributes.position, 3, _gl.FLOAT, false, 0, 0 );
3022

A
alteredq 已提交
3023
		}
3024

A
alteredq 已提交
3025
		if ( object.hasNormal ) {
3026

3027
			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer );
3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055

			if ( shading == THREE.FlatShading ) {

				var nx, ny, nz,
					nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz,
					normalArray,
					i, il = object.count * 3;

				for( i = 0; i < il; i += 9 ) {

					normalArray = object.normalArray;

					nax  = normalArray[ i ];
					nay  = normalArray[ i + 1 ];
					naz  = normalArray[ i + 2 ];

					nbx  = normalArray[ i + 3 ];
					nby  = normalArray[ i + 4 ];
					nbz  = normalArray[ i + 5 ];

					ncx  = normalArray[ i + 6 ];
					ncy  = normalArray[ i + 7 ];
					ncz  = normalArray[ i + 8 ];

					nx = ( nax + nbx + ncx ) / 3;
					ny = ( nay + nby + ncy ) / 3;
					nz = ( naz + nbz + ncz ) / 3;

M
Mr.doob 已提交
3056
					normalArray[ i ] 	 = nx;
3057 3058 3059
					normalArray[ i + 1 ] = ny;
					normalArray[ i + 2 ] = nz;

M
Mr.doob 已提交
3060
					normalArray[ i + 3 ] = nx;
3061 3062 3063
					normalArray[ i + 4 ] = ny;
					normalArray[ i + 5 ] = nz;

M
Mr.doob 已提交
3064
					normalArray[ i + 6 ] = nx;
3065 3066 3067 3068 3069 3070 3071
					normalArray[ i + 7 ] = ny;
					normalArray[ i + 8 ] = nz;

				}

			}

3072 3073 3074
			_gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
			_gl.enableVertexAttribArray( program.attributes.normal );
			_gl.vertexAttribPointer( program.attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
3075

A
alteredq 已提交
3076
		}
3077

A
alteredq 已提交
3078
		_gl.drawArrays( _gl.TRIANGLES, 0, object.count );
3079

A
alteredq 已提交
3080
		object.count = 0;
3081

A
alteredq 已提交
3082
	};
3083

3084
	function setObjectFaces( object ) {
3085

3086
		if ( _oldDoubleSided != object.doubleSided ) {
3087

3088
			if( object.doubleSided ) {
3089

3090
				_gl.disable( _gl.CULL_FACE );
3091

3092
			} else {
3093

A
alteredq 已提交
3094
				_gl.enable( _gl.CULL_FACE );
3095

A
alteredq 已提交
3096
			}
3097

3098
			_oldDoubleSided = object.doubleSided;
3099

3100
		}
3101

3102
		if ( _oldFlipSided != object.flipSided ) {
3103

3104 3105 3106 3107
			if( object.flipSided ) {

				_gl.frontFace( _gl.CW );

3108
			} else {
3109 3110 3111 3112

				_gl.frontFace( _gl.CCW );

			}
3113

3114
			_oldFlipSided = object.flipSided;
3115 3116

		}
3117

3118
	};
3119

3120
	function setDepthTest( test ) {
3121

A
alteredq 已提交
3122 3123 3124
		if ( _oldDepth != test ) {

			if( test ) {
3125

A
alteredq 已提交
3126
				_gl.enable( _gl.DEPTH_TEST );
3127

A
alteredq 已提交
3128
			} else {
3129

A
alteredq 已提交
3130
				_gl.disable( _gl.DEPTH_TEST );
3131

A
alteredq 已提交
3132
			}
3133

A
alteredq 已提交
3134 3135 3136
			_oldDepth = test;

		}
3137

A
alteredq 已提交
3138
	};
M
Mr.doob 已提交
3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167

	function setPolygonOffset ( polygonoffset, factor, units ) {

		if ( _oldPolygonOffset != polygonoffset ) {

			if ( polygonoffset ) {

				_gl.enable( _gl.POLYGON_OFFSET_FILL );

			} else {

				_gl.disable( _gl.POLYGON_OFFSET_FILL );

			}

			_oldPolygonOffset = polygonoffset;

		}

		if ( polygonoffset && ( _oldPolygonOffsetFactor != factor || _oldPolygonOffsetUnits != units ) ) {

			_gl.polygonOffset( factor, units );

			_oldPolygonOffsetFactor = factor;
			_oldPolygonOffsetUnits = units;

		}

	};
3168

3169
	function computeFrustum( m ) {
3170 3171 3172 3173 3174 3175 3176 3177 3178

		_frustum[ 0 ].set( m.n41 - m.n11, m.n42 - m.n12, m.n43 - m.n13, m.n44 - m.n14 );
		_frustum[ 1 ].set( m.n41 + m.n11, m.n42 + m.n12, m.n43 + m.n13, m.n44 + m.n14 );
		_frustum[ 2 ].set( m.n41 + m.n21, m.n42 + m.n22, m.n43 + m.n23, m.n44 + m.n24 );
		_frustum[ 3 ].set( m.n41 - m.n21, m.n42 - m.n22, m.n43 - m.n23, m.n44 - m.n24 );
		_frustum[ 4 ].set( m.n41 - m.n31, m.n42 - m.n32, m.n43 - m.n33, m.n44 - m.n34 );
		_frustum[ 5 ].set( m.n41 + m.n31, m.n42 + m.n32, m.n43 + m.n33, m.n44 + m.n34 );

		var i, plane;
3179

A
alteredq 已提交
3180
		for ( i = 0; i < 6; i ++ ) {
3181 3182 3183 3184 3185 3186 3187

			plane = _frustum[ i ];
			plane.divideScalar( Math.sqrt( plane.x * plane.x + plane.y * plane.y + plane.z * plane.z ) );

		}

	};
3188

3189
	function isInFrustum( object ) {
3190

3191
		var distance, matrix = object.matrixWorld,
3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203
		radius = - object.geometry.boundingSphere.radius * Math.max( object.scale.x, Math.max( object.scale.y, object.scale.z ) );

		for ( var i = 0; i < 6; i ++ ) {

			distance = _frustum[ i ].x * matrix.n14 + _frustum[ i ].y * matrix.n24 + _frustum[ i ].z * matrix.n34 + _frustum[ i ].w;
			if ( distance <= radius ) return false;

		}

		return true;

	};
3204

3205
	function addToFixedArray( where, what ) {
3206

3207 3208
		where.list[ where.count ] = what;
		where.count += 1;
3209

3210
	};
3211

3212
	function unrollImmediateBufferMaterials( globject ) {
3213

3214 3215 3216 3217 3218 3219 3220
		var i, l, m, ml, material,
			object = globject.object,
			opaque = globject.opaque,
			transparent = globject.transparent;

		transparent.count = 0;
		opaque.count = 0;
3221

3222
		for ( m = 0, ml = object.materials.length; m < ml; m ++ ) {
3223 3224

			material = object.materials[ m ];
3225
			material.transparent ? addToFixedArray( transparent, material ) : addToFixedArray( opaque, material );
3226

3227
		}
3228

3229
	};
3230

3231
	function unrollBufferMaterials( globject ) {
3232

3233 3234 3235 3236 3237 3238 3239 3240
		var i, l, m, ml, material, meshMaterial,
			object = globject.object,
			buffer = globject.buffer,
			opaque = globject.opaque,
			transparent = globject.transparent;

		transparent.count = 0;
		opaque.count = 0;
3241

3242
		for ( m = 0, ml = object.materials.length; m < ml; m ++ ) {
3243 3244 3245 3246 3247

			meshMaterial = object.materials[ m ];

			if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {

3248
				for ( i = 0, l = buffer.materials.length; i < l; i ++ ) {
3249 3250

					material = buffer.materials[ i ];
3251
					if ( material ) material.transparent ? addToFixedArray( transparent, material ) : addToFixedArray( opaque, material );
3252 3253 3254 3255 3256 3257

				}

			} else {

				material = meshMaterial;
3258
				if ( material ) material.transparent ? addToFixedArray( transparent, material ) : addToFixedArray( opaque, material );
3259

3260 3261 3262
			}

		}
3263

3264
	};
3265

3266
	function painterSort( a, b ) {
3267

3268
		return b.z - a.z;
3269 3270

	};
3271

3272 3273 3274
	function renderShadowMap( scene, camera ) {

		var i, il, light,
3275 3276
			j = 0,
			shadowMap, shadowMatrix,
3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294
			oil,
			material,
			o, ol, webglObject, object,
			lights = scene.lights,
			fog = null;

		if ( ! _cameraLight ) {

			_cameraLight = new THREE.Camera( _this.shadowCameraFov, camera.aspect, _this.shadowCameraNear, _this.shadowCameraFar );

		}

		for ( i = 0, il = lights.length; i < il; i ++ ) {

			light = lights[ i ];

			if ( light instanceof THREE.SpotLight && light.castShadow ) {

3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310
				if ( ! _this.shadowMap[ j ] ) {

					var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
					_this.shadowMap[ j ] = new THREE.WebGLRenderTarget( _this.shadowMapWidth, _this.shadowMapHeight, pars );

				}

				if ( ! _shadowMatrix[ j ] ) {

					_shadowMatrix[ j ] = new THREE.Matrix4();

				}

				shadowMap = _this.shadowMap[ j ];
				shadowMatrix = _shadowMatrix[ j ];

3311 3312 3313 3314 3315 3316 3317 3318 3319
				_cameraLight.position.copy( light.position );
				_cameraLight.target.position.copy( light.target.position );

				_cameraLight.update( undefined, true );

				scene.update( undefined, false, _cameraLight );

				// compute shadow matrix

3320 3321 3322 3323
				shadowMatrix.set( 0.5, 0.0, 0.0, 0.5,
								  0.0, 0.5, 0.0, 0.5,
								  0.0, 0.0, 0.5, 0.5,
								  0.0, 0.0, 0.0, 1.0 );
3324

3325 3326
				shadowMatrix.multiplySelf( _cameraLight.projectionMatrix );
				shadowMatrix.multiplySelf( _cameraLight.matrixWorldInverse );
3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337

				// render shadow map

				_cameraLight.matrixWorldInverse.flattenToArray( _viewMatrixArray );
				_cameraLight.projectionMatrix.flattenToArray( _projectionMatrixArray );

				_projScreenMatrix.multiply( _cameraLight.projectionMatrix, _cameraLight.matrixWorldInverse );
				computeFrustum( _projScreenMatrix );

				_this.initWebGLObjects( scene );

3338
				setRenderTarget( shadowMap );
3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400

				// using arbitrary clear color in depth pass
				// creates variance in shadows

				_gl.clearColor( 1, 1, 1, 1 );
				//_gl.clearColor( 0, 0, 0, 1 );

				_this.clear();

				_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );


				// set matrices & frustum culling

				ol = scene.__webglObjects.length;
				oil = scene.__webglObjectsImmediate.length;

				for ( o = 0; o < ol; o ++ ) {

					webglObject = scene.__webglObjects[ o ];
					object = webglObject.object;

					if ( object.visible && object.castShadow ) {

						if ( ! ( object instanceof THREE.Mesh ) || isInFrustum( object ) ) {

							object.matrixWorld.flattenToArray( object._objectMatrixArray );

							setupMatrices( object, _cameraLight, false );

							webglObject.render = true;

						} else {

							webglObject.render = false;

						}

					} else {

						webglObject.render = false;

					}

				}

				setDepthTest( true );
				setBlending( THREE.NormalBlending ); // maybe blending should be just disabled?

				//_gl.cullFace( _gl.FRONT );

				for ( o = 0; o < ol; o ++ ) {

					webglObject = scene.__webglObjects[ o ];

					if ( webglObject.render ) {

						object = webglObject.object;
						buffer = webglObject.buffer;

						setObjectFaces( object );

3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413
						if ( object.customDepthMaterial ) {

							material =  object.customDepthMaterial;

						} else if ( object.geometry.morphTargets.length ) {

							material =  _depthMaterialMorph;

						} else {

							material = _depthMaterial;

						}
3414 3415 3416 3417 3418 3419 3420 3421

						renderBuffer( _cameraLight, lights, fog, material, buffer, object );

					}

				}


3422
				for ( o = 0; o < oil; o ++ ) {
3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447

					webglObject = scene.__webglObjectsImmediate[ o ];
					object = webglObject.object;

					if ( object.visible && object.castShadow ) {

						if( object.matrixAutoUpdate ) {

							object.matrixWorld.flattenToArray( object._objectMatrixArray );

						}

						setupMatrices( object, _cameraLight, false );

						setObjectFaces( object );

						program = setProgram( _cameraLight, lights, fog, _depthMaterial, object );
						object.render( function( object ) { renderBufferImmediate( object, program, _depthMaterial.shading ); } );

					}

				}

				//_gl.cullFace( _gl.BACK );

3448 3449
				j ++;

3450 3451 3452 3453 3454 3455
			}

		}

	};

3456
	this.render = function( scene, camera, renderTarget, forceClear ) {
3457

A
alteredq 已提交
3458
		var i, program, opaque, transparent, material,
3459
			o, ol, oil, webglObject, object, buffer,
A
alteredq 已提交
3460
			lights = scene.lights,
N
Nicholas Kinsey 已提交
3461
			fog = scene.fog;
3462

3463 3464
		if ( this.shadowMapEnabled ) renderShadowMap( scene, camera );

3465 3466
		_this.data.vertices = 0;
		_this.data.faces = 0;
3467
		_this.data.drawCalls = 0;
3468

3469
		camera.matrixAutoUpdate && camera.update( undefined, true );
3470

3471
		scene.update( undefined, false, camera );
M
Mr.doob 已提交
3472

M
Mr.doob 已提交
3473
		camera.matrixWorldInverse.flattenToArray( _viewMatrixArray );
3474
		camera.projectionMatrix.flattenToArray( _projectionMatrixArray );
M
Mr.doob 已提交
3475

M
Mr.doob 已提交
3476
		_projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
3477
		computeFrustum( _projScreenMatrix );
3478

A
alteredq 已提交
3479
		this.initWebGLObjects( scene );
M
Mr.doob 已提交
3480

A
alteredq 已提交
3481
		setRenderTarget( renderTarget );
M
Mr.doob 已提交
3482

A
alteredq 已提交
3483
		if ( this.autoClear || forceClear ) {
M
Mr.doob 已提交
3484

3485
			this.clear();
M
Mr.doob 已提交
3486

3487 3488
		}

3489
		// set matrices
3490

3491
		ol = scene.__webglObjects.length;
3492

3493
		for ( o = 0; o < ol; o ++ ) {
M
Mr.doob 已提交
3494

3495 3496
			webglObject = scene.__webglObjects[ o ];
			object = webglObject.object;
M
Mr.doob 已提交
3497

3498
			if ( object.visible ) {
3499 3500

				if ( ! ( object instanceof THREE.Mesh ) || isInFrustum( object ) ) {
3501

3502
					object.matrixWorld.flattenToArray( object._objectMatrixArray );
3503

3504
					setupMatrices( object, camera, true );
3505

3506
					unrollBufferMaterials( webglObject );
3507

3508
					webglObject.render = true;
3509

3510
					if ( this.sortObjects ) {
3511

3512
						if ( webglObject.object.renderDepth ) {
M
Mr.doob 已提交
3513

3514
							webglObject.z = webglObject.object.renderDepth;
M
Mr.doob 已提交
3515

3516
						} else {
M
Mr.doob 已提交
3517

3518 3519
							_vector3.copy( object.position );
							_projScreenMatrix.multiplyVector3( _vector3 );
M
Mr.doob 已提交
3520

3521
							webglObject.z = _vector3.z;
M
Mr.doob 已提交
3522

3523
						}
3524

3525
					}
3526

3527
				} else {
3528

3529
					webglObject.render = false;
3530

3531
				}
3532

3533
			} else {
3534

3535
				webglObject.render = false;
3536

3537
			}
3538

3539
		}
3540

3541
		if ( this.sortObjects ) {
3542

3543
			scene.__webglObjects.sort( painterSort );
3544

3545
		}
3546

3547
		oil = scene.__webglObjectsImmediate.length;
3548

3549
		for ( o = 0; o < oil; o ++ ) {
3550

3551 3552
			webglObject = scene.__webglObjectsImmediate[ o ];
			object = webglObject.object;
3553

3554
			if ( object.visible ) {
3555 3556 3557

				if( object.matrixAutoUpdate ) {

3558
					object.matrixWorld.flattenToArray( object._objectMatrixArray );
3559

A
alteredq 已提交
3560
				}
3561

3562
				setupMatrices( object, camera, true );
3563

3564
				unrollImmediateBufferMaterials( webglObject );
3565

3566
			}
3567

3568
		}
A
alteredq 已提交
3569

M
Mr.doob 已提交
3570
		if ( scene.overrideMaterial ) {
3571

M
Mr.doob 已提交
3572 3573
			setDepthTest( scene.overrideMaterial.depthTest );
			setBlending( scene.overrideMaterial.blending );
3574

M
Mr.doob 已提交
3575
			for ( o = 0; o < ol; o ++ ) {
M
Mr.doob 已提交
3576

M
Mr.doob 已提交
3577 3578 3579
				webglObject = scene.__webglObjects[ o ];

				if ( webglObject.render ) {
3580

M
Mr.doob 已提交
3581 3582
					object = webglObject.object;
					buffer = webglObject.buffer;
3583

M
Mr.doob 已提交
3584 3585 3586 3587 3588 3589 3590 3591
					setObjectFaces( object );

					renderBuffer( camera, lights, fog, scene.overrideMaterial, buffer, object );

				}

			}

3592
			for ( o = 0; o < oil; o ++ ) {
M
Mr.doob 已提交
3593 3594

				webglObject = scene.__webglObjectsImmediate[ o ];
3595
				object = webglObject.object;
3596

M
Mr.doob 已提交
3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610
				if ( object.visible ) {

					setObjectFaces( object );

					program = setProgram( camera, lights, fog, scene.overrideMaterial, object );
					object.render( function( object ) { renderBufferImmediate( object, program, scene.overrideMaterial.shading ); } );

				}

			}

		} else {

			// opaque pass
3611
			// (front-to-back order)
M
Mr.doob 已提交
3612 3613 3614

			setBlending( THREE.NormalBlending );

3615
			for ( o = ol - 1; o >= 0; o -- ) {
M
Mr.doob 已提交
3616 3617 3618 3619 3620 3621 3622 3623 3624 3625

				webglObject = scene.__webglObjects[ o ];

				if ( webglObject.render ) {

					object = webglObject.object;
					buffer = webglObject.buffer;
					opaque = webglObject.opaque;

					setObjectFaces( object );
3626

M
Mr.doob 已提交
3627
					for ( i = 0; i < opaque.count; i ++ ) {
3628

M
Mr.doob 已提交
3629
						material = opaque.list[ i ];
3630

M
Mr.doob 已提交
3631 3632 3633 3634 3635
						setDepthTest( material.depthTest );
						setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
						renderBuffer( camera, lights, fog, material, buffer, object );

					}
3636

3637
				}
3638 3639 3640

			}

M
Mr.doob 已提交
3641
			// opaque pass (immediate simulator)
3642

M
Mr.doob 已提交
3643
			for ( o = 0; o < oil; o++ ) {
3644

M
Mr.doob 已提交
3645 3646
				webglObject = scene.__webglObjectsImmediate[ o ];
				object = webglObject.object;
3647

M
Mr.doob 已提交
3648
				if ( object.visible ) {
3649

M
Mr.doob 已提交
3650
					opaque = webglObject.opaque;
3651

M
Mr.doob 已提交
3652
					setObjectFaces( object );
3653

M
Mr.doob 已提交
3654
					for( i = 0; i < opaque.count; i++ ) {
3655

M
Mr.doob 已提交
3656
						material = opaque.list[ i ];
3657

M
Mr.doob 已提交
3658 3659
						setDepthTest( material.depthTest );
						setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
3660

M
Mr.doob 已提交
3661 3662
						program = setProgram( camera, lights, fog, material, object );
						object.render( function( object ) { renderBufferImmediate( object, program, material.shading ); } );
3663

M
Mr.doob 已提交
3664
					}
3665

3666
				}
3667

A
alteredq 已提交
3668
			}
3669

M
Mr.doob 已提交
3670
			// transparent pass
3671
			// (back-to-front order)
A
alteredq 已提交
3672

M
Mr.doob 已提交
3673
			for ( o = 0; o < ol; o ++ ) {
3674

M
Mr.doob 已提交
3675
				webglObject = scene.__webglObjects[ o ];
3676

M
Mr.doob 已提交
3677
				if ( webglObject.render ) {
3678

M
Mr.doob 已提交
3679 3680 3681
					object = webglObject.object;
					buffer = webglObject.buffer;
					transparent = webglObject.transparent;
3682

M
Mr.doob 已提交
3683
					setObjectFaces( object );
3684

M
Mr.doob 已提交
3685
					for ( i = 0; i < transparent.count; i ++ ) {
3686

M
Mr.doob 已提交
3687
						material = transparent.list[ i ];
3688

M
Mr.doob 已提交
3689 3690 3691
						setBlending( material.blending );
						setDepthTest( material.depthTest );
						setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
3692

M
Mr.doob 已提交
3693
						renderBuffer( camera, lights, fog, material, buffer, object );
3694

M
Mr.doob 已提交
3695
					}
3696

3697
				}
3698

3699
			}
M
Mr.doob 已提交
3700

M
Mr.doob 已提交
3701
			// transparent pass (immediate simulator)
M
Mr.doob 已提交
3702

M
Mr.doob 已提交
3703
			for ( o = 0; o < oil; o++ ) {
3704

M
Mr.doob 已提交
3705 3706
				webglObject = scene.__webglObjectsImmediate[ o ];
				object = webglObject.object;
3707

M
Mr.doob 已提交
3708
				if ( object.visible ) {
3709

M
Mr.doob 已提交
3710
					transparent = webglObject.transparent;
3711

M
Mr.doob 已提交
3712
					setObjectFaces( object );
3713

M
Mr.doob 已提交
3714
					for ( i = 0; i < transparent.count; i ++ ) {
3715

M
Mr.doob 已提交
3716
						material = transparent.list[ i ];
3717

M
Mr.doob 已提交
3718 3719 3720
						setBlending( material.blending );
						setDepthTest( material.depthTest );
						setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
3721

M
Mr.doob 已提交
3722 3723
						program = setProgram( camera, lights, fog, material, object );
						object.render( function( object ) { renderBufferImmediate( object, program, material.shading ); } );
3724

M
Mr.doob 已提交
3725
					}
3726

3727
				}
3728

3729
			}
3730

3731
		}
3732

M
Mikael Emtinger 已提交
3733
		// render 2d
3734

M
Mikael Emtinger 已提交
3735
		if ( scene.__webglSprites.length ) {
3736

3737
			renderSprites( scene, camera );
3738

M
Mikael Emtinger 已提交
3739 3740
		}

M
Mikael Emtinger 已提交
3741 3742 3743 3744 3745 3746 3747 3748
		// Generate mipmap if we're using any kind of mipmap filtering

		if ( renderTarget && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) {

			updateRenderTargetMipmap( renderTarget );

		}

3749
		//_gl.finish();
3750

M
Mikael Emtinger 已提交
3751 3752
	};

3753 3754
	/*
	 * Render sprites
M
Mr.doob 已提交
3755
	 *
3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771
	 */

	function renderSprites( scene, camera ) {

		var o, ol, object;
		var attributes = _sprite.attributes;
		var uniforms = _sprite.uniforms;
		var anyCustom = false;
		var invAspect = _viewportHeight / _viewportWidth;
		var size, scale = [];
		var screenPosition;
		var halfViewportWidth = _viewportWidth * 0.5;
		var halfViewportHeight = _viewportHeight * 0.5;
		var mergeWith3D = true;

		// setup gl
3772

3773 3774
		_gl.useProgram( _sprite.program );
		_currentProgram = _sprite.program;
3775
		_oldBlending = -1;
3776
		_oldDepth = -1;
3777

M
Mr.doob 已提交
3778
		if ( !_spriteAttributesEnabled ) {
3779

M
Mr.doob 已提交
3780 3781
			_gl.enableVertexAttribArray( _sprite.attributes.position );
			_gl.enableVertexAttribArray( _sprite.attributes.uv );
3782

M
Mr.doob 已提交
3783 3784 3785
			_spriteAttributesEnabled = true;

		}
3786

3787
		_gl.disable( _gl.CULL_FACE );
3788
		_gl.enable( _gl.BLEND );
3789
		_gl.depthMask( true );
3790 3791 3792 3793 3794 3795

		_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 );
3796

3797 3798 3799 3800
		_gl.uniformMatrix4fv( uniforms.projectionMatrix, false, _projectionMatrixArray );

		_gl.activeTexture( _gl.TEXTURE0 );
		_gl.uniform1i( uniforms.map, 0 );
3801

3802
		// update positions and sort
3803

3804
		for( o = 0, ol = scene.__webglSprites.length; o < ol; o++ ) {
3805

3806
			object = scene.__webglSprites[ o ];
3807

3808
			if( !object.useScreenCoordinates ) {
3809

3810 3811
				object._modelViewMatrix.multiplyToArray( camera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
				object.z = -object._modelViewMatrix.n34;
3812

3813
			} else {
3814

3815
				object.z = -object.position.z;
3816

3817
			}
3818

3819 3820 3821
		}

		scene.__webglSprites.sort( painterSort );
3822 3823

		// render all non-custom shader sprites
3824 3825

		for ( o = 0, ol = scene.__webglSprites.length; o < ol; o++ ) {
3826 3827 3828

			object = scene.__webglSprites[ o ];

3829 3830 3831 3832 3833
			if ( object.material === undefined ) {

				if ( object.map && object.map.image && object.map.image.width ) {

					if ( object.useScreenCoordinates ) {
3834 3835

						_gl.uniform1i( uniforms.useScreenCoordinates, 1 );
M
Mr.doob 已提交
3836
						_gl.uniform3f( uniforms.screenPosition, ( object.position.x - halfViewportWidth  ) / halfViewportWidth,
3837 3838
																( halfViewportHeight - object.position.y ) / halfViewportHeight,
																  Math.max( 0, Math.min( 1, object.position.z )));
3839

3840 3841
					} else {

3842

3843 3844 3845 3846

						_gl.uniform1i( uniforms.useScreenCoordinates, 0 );
						_gl.uniform1i( uniforms.affectedByDistance, object.affectedByDistance ? 1 : 0 );
						_gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object._modelViewMatrixArray );
3847

3848
					}
3849

3850
					size = object.map.image.width / ( object.scaleByViewport ? _viewportHeight : 1 );
3851
					scale[ 0 ] = size * invAspect * object.scale.x;
3852
					scale[ 1 ] = size * object.scale.y;
3853

3854 3855 3856 3857 3858 3859 3860
					_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.uniform1f( uniforms.rotation, object.rotation );
					_gl.uniform2fv( uniforms.scale, scale );

3861 3862
					if ( object.mergeWith3D && !mergeWith3D ) {

3863 3864
						_gl.enable( _gl.DEPTH_TEST );
						mergeWith3D = true;
3865 3866 3867

					} else if ( !object.mergeWith3D && mergeWith3D ) {

3868 3869
						_gl.disable( _gl.DEPTH_TEST );
						mergeWith3D = false;
3870

3871
					}
3872

3873 3874
					setBlending( object.blending );
					setTexture( object.map, 0 );
3875

3876 3877
					_gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
				}
3878

3879
			} else {
3880

3881
				anyCustom = true;
3882

3883
			}
3884

3885 3886 3887 3888 3889
		}


		// loop through all custom

3890 3891 3892
		/*
		if( anyCustom ) {

3893
		}
3894
		*/
3895 3896 3897 3898 3899 3900 3901 3902 3903

		// restore gl

		_gl.enable( _gl.CULL_FACE );
		_gl.enable( _gl.DEPTH_TEST );
		_gl.depthMask( _currentDepthMask );

	}

3904
	function setupMatrices( object, camera, computeNormalMatrix ) {
3905

3906
		object._modelViewMatrix.multiplyToArray( camera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
3907 3908 3909 3910 3911 3912

		if ( computeNormalMatrix ) {

			THREE.Matrix4.makeInvert3x3( object._modelViewMatrix ).transposeIntoArray( object._normalMatrixArray );

		}
3913

M
Mr.doob 已提交
3914
	}
3915

A
alteredq 已提交
3916
	this.initWebGLObjects = function ( scene ) {
3917

3918
		if ( !scene.__webglObjects ) {
3919

3920 3921
			scene.__webglObjects = [];
			scene.__webglObjectsImmediate = [];
M
Mikael Emtinger 已提交
3922
			scene.__webglSprites = [];
3923

3924 3925
		}

M
Mr.doob 已提交
3926
		while ( scene.__objectsAdded.length ) {
3927

M
Mr.doob 已提交
3928 3929
			addObject( scene.__objectsAdded[ 0 ], scene );
			scene.__objectsAdded.splice( 0, 1 );
3930 3931 3932

		}

M
Mr.doob 已提交
3933
		while ( scene.__objectsRemoved.length ) {
3934

M
Mr.doob 已提交
3935 3936
			removeObject( scene.__objectsRemoved[ 0 ], scene );
			scene.__objectsRemoved.splice( 0, 1 );
3937 3938

		}
3939

A
alteredq 已提交
3940
		// update must be called after objects adding / removal
M
Mr.doob 已提交
3941

A
alteredq 已提交
3942 3943
		for ( var o = 0, ol = scene.__webglObjects.length; o < ol; o ++ ) {

M
Mr.doob 已提交
3944
			updateObject( scene.__webglObjects[ o ].object, scene );
A
alteredq 已提交
3945 3946

		}
3947

3948
	};
3949

3950
	function addObject( object, scene ) {
3951

3952
		var g, geometry, geometryGroup;
M
Mr.doob 已提交
3953

3954
		if ( object._modelViewMatrix == undefined ) {
3955

3956
			object._modelViewMatrix = new THREE.Matrix4();
3957

3958 3959 3960
			object._normalMatrixArray = new Float32Array( 9 );
			object._modelViewMatrixArray = new Float32Array( 16 );
			object._objectMatrixArray = new Float32Array( 16 );
3961

3962
			object.matrixWorld.flattenToArray( object._objectMatrixArray );
M
Mr.doob 已提交
3963

3964
		}
A
alteredq 已提交
3965

3966
		if ( object instanceof THREE.Mesh ) {
A
alteredq 已提交
3967

3968 3969 3970 3971 3972 3973 3974 3975
			geometry = object.geometry;

			if ( geometry.geometryGroups == undefined ) {

				sortFacesByMaterial( geometry );

			}

3976
			// create separate VBOs per geometry chunk
A
alteredq 已提交
3977

3978
			for ( g in geometry.geometryGroups ) {
A
alteredq 已提交
3979

3980
				geometryGroup = geometry.geometryGroups[ g ];
M
Mr.doob 已提交
3981

3982
				// initialise VBO on the first access
M
Mr.doob 已提交
3983

3984
				if ( ! geometryGroup.__webglVertexBuffer ) {
M
Mr.doob 已提交
3985

3986 3987
					createMeshBuffers( geometryGroup );
					initMeshBuffers( geometryGroup, object );
A
alteredq 已提交
3988

3989
					geometry.__dirtyVertices = true;
3990
					geometry.__dirtyMorphTargets = true;
3991 3992 3993 3994 3995
					geometry.__dirtyElements = true;
					geometry.__dirtyUvs = true;
					geometry.__dirtyNormals = true;
					geometry.__dirtyTangents = true;
					geometry.__dirtyColors = true;
M
Mr.doob 已提交
3996

3997
				}
3998

M
Mr.doob 已提交
3999
				addBuffer( scene.__webglObjects, geometryGroup, object );
4000

4001
			}
M
Mr.doob 已提交
4002

A
alteredq 已提交
4003 4004
		} else if ( object instanceof THREE.Ribbon ) {

4005 4006
			geometry = object.geometry;

4007
			if( ! geometry.__webglVertexBuffer ) {
A
alteredq 已提交
4008 4009 4010 4011 4012 4013 4014 4015 4016

				createRibbonBuffers( geometry );
				initRibbonBuffers( geometry );

				geometry.__dirtyVertices = true;
				geometry.__dirtyColors = true;

			}

M
Mr.doob 已提交
4017
			addBuffer( scene.__webglObjects, geometry, object );
A
alteredq 已提交
4018

4019
		} else if ( object instanceof THREE.Line ) {
M
Mr.doob 已提交
4020

4021 4022
			geometry = object.geometry;

4023
			if( ! geometry.__webglVertexBuffer ) {
M
Mr.doob 已提交
4024

4025 4026
				createLineBuffers( geometry );
				initLineBuffers( geometry );
M
Mr.doob 已提交
4027

4028 4029
				geometry.__dirtyVertices = true;
				geometry.__dirtyColors = true;
M
Mr.doob 已提交
4030

4031
			}
M
Mr.doob 已提交
4032

M
Mr.doob 已提交
4033
			addBuffer( scene.__webglObjects, geometry, object );
4034

A
alteredq 已提交
4035 4036 4037 4038
		} else if ( object instanceof THREE.ParticleSystem ) {

			geometry = object.geometry;

4039
			if ( ! geometry.__webglVertexBuffer ) {
A
alteredq 已提交
4040 4041

				createParticleBuffers( geometry );
4042
				initParticleBuffers( geometry, object );
A
alteredq 已提交
4043 4044 4045

				geometry.__dirtyVertices = true;
				geometry.__dirtyColors = true;
4046

4047
			}
4048

M
Mr.doob 已提交
4049
			addBuffer( scene.__webglObjects, geometry, object );
M
Mr.doob 已提交
4050

A
alteredq 已提交
4051 4052 4053 4054
		} else if ( THREE.MarchingCubes !== undefined && object instanceof THREE.MarchingCubes ) {

			addBufferImmediate( scene.__webglObjectsImmediate, object );

4055
		} else if ( object instanceof THREE.Sprite ) {
4056

4057
			scene.__webglSprites.push( object );
4058

4059
		}
4060

4061
		/*else if ( object instanceof THREE.Particle ) {
A
alteredq 已提交
4062 4063 4064 4065 4066

		}*/

	};

4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117
	function areCustomAttributesDirty( geometryGroup ) {

		var a, m, ml, material, materials;

		materials = geometryGroup.__materials;

		for ( m = 0, ml = materials.length; m < ml; m ++ ) {

			material = materials[ m ];

			if ( material.attributes ) {

				for ( a in material.attributes ) {

					if ( material.attributes[ a ].needsUpdate ) return true;

				}

			}

		}


		return false;

	};

	function clearCustomAttributes( geometryGroup ) {

		var a, m, ml, material, materials;

		materials = geometryGroup.__materials;

		for ( m = 0, ml = materials.length; m < ml; m ++ ) {

			material = materials[ m ];

			if ( material.attributes ) {

				for ( a in material.attributes ) {

					material.attributes[ a ].needsUpdate = false;

				}

			}

		}

	};

4118
	function updateObject( object, scene ) {
A
alteredq 已提交
4119

4120
		var g, geometry, geometryGroup, a, customAttributeDirty;
A
alteredq 已提交
4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131

		if ( object instanceof THREE.Mesh ) {

			geometry = object.geometry;

			// check all geometry groups

			for ( g in geometry.geometryGroups ) {

				geometryGroup = geometry.geometryGroups[ g ];

4132
				customAttributeDirty = areCustomAttributesDirty( geometryGroup );
4133

4134
				if ( geometry.__dirtyVertices || geometry.__dirtyMorphTargets || geometry.__dirtyElements ||
4135 4136
					 geometry.__dirtyUvs || geometry.__dirtyNormals ||
					 geometry.__dirtyColors || geometry.__dirtyTangents || customAttributeDirty ) {
A
alteredq 已提交
4137

4138
					setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, !geometry.dynamic );
A
alteredq 已提交
4139 4140 4141 4142 4143

				}

			}

4144
			geometry.__dirtyVertices = false;
4145
			geometry.__dirtyMorphTargets = false;
A
alteredq 已提交
4146 4147 4148 4149
			geometry.__dirtyElements = false;
			geometry.__dirtyUvs = false;
			geometry.__dirtyNormals = false;
			geometry.__dirtyTangents = false;
4150
			geometry.__dirtyColors = false;
M
Mr.doob 已提交
4151

4152 4153
			clearCustomAttributes( geometryGroup );

A
alteredq 已提交
4154
		} else if ( object instanceof THREE.Ribbon ) {
M
Mr.doob 已提交
4155

4156 4157
			geometry = object.geometry;

A
alteredq 已提交
4158
			if( geometry.__dirtyVertices || geometry.__dirtyColors ) {
M
Mr.doob 已提交
4159

A
alteredq 已提交
4160
				setRibbonBuffers( geometry, _gl.DYNAMIC_DRAW );
4161

A
alteredq 已提交
4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173
			}

			geometry.__dirtyVertices = false;
			geometry.__dirtyColors = false;

		} else if ( object instanceof THREE.Line ) {

			geometry = object.geometry;

			if( geometry.__dirtyVertices ||  geometry.__dirtyColors ) {

				setLineBuffers( geometry, _gl.DYNAMIC_DRAW );
4174

4175
			}
4176

A
alteredq 已提交
4177 4178 4179 4180 4181 4182 4183
			geometry.__dirtyVertices = false;
			geometry.__dirtyColors = false;

		} else if ( object instanceof THREE.ParticleSystem ) {

			geometry = object.geometry;

4184 4185 4186
			customAttributeDirty = areCustomAttributesDirty( geometry );

			if ( geometry.__dirtyVertices || geometry.__dirtyColors || object.sortParticles || customAttributeDirty ) {
M
Mr.doob 已提交
4187

4188
				setParticleBuffers( geometry, _gl.DYNAMIC_DRAW, object );
M
Mr.doob 已提交
4189

4190
			}
M
Mr.doob 已提交
4191

4192 4193
			geometry.__dirtyVertices = false;
			geometry.__dirtyColors = false;
M
Mr.doob 已提交
4194

4195 4196
			clearCustomAttributes( geometry );

4197
		}/* else if ( THREE.MarchingCubes !== undefined && object instanceof THREE.MarchingCubes ) {
4198

A
alteredq 已提交
4199
			// it updates itself in render callback
4200 4201

		} else if ( object instanceof THREE.Particle ) {
4202 4203

		}*/
4204

4205 4206 4207 4208 4209 4210
		/*
		delete geometry.vertices;
		delete geometry.faces;
		delete geometryGroup.faces;
		*/

4211
	};
4212

4213
	function removeInstances( objlist, object ) {
M
Mr.doob 已提交
4214

4215
		var o, ol;
M
Mr.doob 已提交
4216

4217
		for ( o = objlist.length - 1; o >= 0; o -- ) {
4218

4219
			if ( objlist[ o ].object == object ) {
4220

4221
				objlist.splice( o, 1 );
4222

4223
			}
4224

4225
		}
M
Mr.doob 已提交
4226

4227
	};
4228

4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244
	function removeInstancesDirect( objlist, object ) {

		var o, ol;

		for ( o = objlist.length - 1; o >= 0; o -- ) {

			if ( objlist[ o ] == object ) {

				objlist.splice( o, 1 );

			}

		}

	};

4245
	function removeObject( object, scene ) {
4246

M
Mr.doob 已提交
4247
		if ( object instanceof THREE.Mesh  ||
4248 4249
			 object instanceof THREE.ParticleSystem ||
			 object instanceof THREE.Ribbon ||
4250
			 object instanceof THREE.Line ) {
4251

4252
			removeInstances( scene.__webglObjects, object );
4253

4254
		} else if ( object instanceof THREE.Sprite ) {
M
Mr.doob 已提交
4255

4256
			removeInstancesDirect( scene.__webglSprites, object );
M
Mr.doob 已提交
4257

4258
		} else if ( object instanceof THREE.MarchingCubes ) {
4259

4260 4261 4262
			removeInstances( scene.__webglObjectsImmediate, object );

		}
M
Mr.doob 已提交
4263 4264 4265

	};

4266
	function sortFacesByMaterial( geometry ) {
4267 4268 4269 4270 4271 4272 4273

		// TODO
		// Should optimize by grouping faces with ColorFill / ColorStroke materials
		// which could then use vertex color attributes instead of each being
		// in its separate VBO

		var i, l, f, fl, face, material, materials, vertices, mhash, ghash, hash_map = {};
4274
		var numMorphTargets = geometry.morphTargets !== undefined ? geometry.morphTargets.length : 0;
4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316

		geometry.geometryGroups = {};

		function materialHash( material ) {

			var hash_array = [];

			for ( i = 0, l = material.length; i < l; i++ ) {

				if ( material[ i ] == undefined ) {

					hash_array.push( "undefined" );

				} else {

					hash_array.push( material[ i ].id );

				}

			}

			return hash_array.join( '_' );

		}

		for ( f = 0, fl = geometry.faces.length; f < fl; f++ ) {

			face = geometry.faces[ f ];
			materials = face.materials;

			mhash = materialHash( materials );

			if ( hash_map[ mhash ] == undefined ) {

				hash_map[ mhash ] = { 'hash': mhash, 'counter': 0 };

			}

			ghash = hash_map[ mhash ].hash + '_' + hash_map[ mhash ].counter;

			if ( geometry.geometryGroups[ ghash ] == undefined ) {

4317
				geometry.geometryGroups[ ghash ] = { 'faces': [], 'materials': materials, 'vertices': 0, 'numMorphTargets': numMorphTargets };
4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329

			}

			vertices = face instanceof THREE.Face3 ? 3 : 4;

			if ( geometry.geometryGroups[ ghash ].vertices + vertices > 65535 ) {

				hash_map[ mhash ].counter += 1;
				ghash = hash_map[ mhash ].hash + '_' + hash_map[ mhash ].counter;

				if ( geometry.geometryGroups[ ghash ] == undefined ) {

4330
					geometry.geometryGroups[ ghash ] = { 'faces': [], 'materials': materials, 'vertices': 0, 'numMorphTargets': numMorphTargets };
4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342

				}

			}

			geometry.geometryGroups[ ghash ].faces.push( f );
			geometry.geometryGroups[ ghash ].vertices += vertices;

		}

	};

4343
	function addBuffer( objlist, buffer, object ) {
4344

4345 4346 4347 4348 4349
		objlist.push( {
			buffer: buffer, object: object,
			opaque: { list: [], count: 0 },
			transparent: { list: [], count: 0 }
		} );
M
Mr.doob 已提交
4350

4351
	};
4352

4353
	function addBufferImmediate( objlist, object ) {
4354

4355 4356 4357 4358 4359
		objlist.push( {
			object: object,
			opaque: { list: [], count: 0 },
			transparent: { list: [], count: 0 }
		} );
4360

4361
	};
4362

4363
	this.setFaceCulling = function ( cullFace, frontFace ) {
M
Mr.doob 已提交
4364

4365
		if ( cullFace ) {
M
Mr.doob 已提交
4366

4367
			if ( !frontFace || frontFace == "ccw" ) {
M
Mr.doob 已提交
4368

4369
				_gl.frontFace( _gl.CCW );
M
Mr.doob 已提交
4370

4371
			} else {
M
Mr.doob 已提交
4372

4373
				_gl.frontFace( _gl.CW );
M
Mr.doob 已提交
4374

4375
			}
M
Mr.doob 已提交
4376

4377
			if( cullFace == "back" ) {
M
Mr.doob 已提交
4378

4379
				_gl.cullFace( _gl.BACK );
M
Mr.doob 已提交
4380

4381
			} else if( cullFace == "front" ) {
M
Mr.doob 已提交
4382

4383
				_gl.cullFace( _gl.FRONT );
M
Mr.doob 已提交
4384

4385
			} else {
M
Mr.doob 已提交
4386

4387
				_gl.cullFace( _gl.FRONT_AND_BACK );
M
Mr.doob 已提交
4388

4389
			}
M
Mr.doob 已提交
4390

4391
			_gl.enable( _gl.CULL_FACE );
M
Mr.doob 已提交
4392

4393
		} else {
M
Mr.doob 已提交
4394

4395
			_gl.disable( _gl.CULL_FACE );
M
Mr.doob 已提交
4396

4397 4398 4399
		}

	};
N
Nicolas Garcia Belmonte 已提交
4400

4401
	this.supportsVertexTextures = function () {
4402

A
alteredq 已提交
4403
		return _supportsVertexTextures;
4404

4405
	};
4406

4407
	function maxVertexTextures() {
4408

4409 4410 4411
		return _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );

	};
4412

4413
	function buildProgram( shaderID, fragmentShader, vertexShader, uniforms, attributes, parameters ) {
4414

4415
		var p, pl, program, code;
4416
		var chunks = [];
4417 4418 4419

		// Generate code

4420 4421 4422 4423 4424 4425 4426 4427 4428 4429
		if ( shaderID ) {

			chunks.push( shaderID );

		} else {

			chunks.push( fragmentShader );
			chunks.push( vertexShader );

		}
4430 4431 4432

		for ( p in parameters ) {

4433 4434
			chunks.push( p );
			chunks.push( parameters[ p ] );
4435 4436 4437

		}

4438 4439
		code = chunks.join();

4440 4441 4442 4443 4444 4445 4446
		// Check if code has been already compiled

		for ( p = 0, pl = _programs.length; p < pl; p ++ ) {

			if ( _programs[ p ].code == code ) {

				// console.log( "Code already compiled." /*: \n\n" + code*/ );
4447

4448 4449 4450 4451 4452
				return _programs[ p ].program;

			}

		}
4453

4454
		//console.log( "building new program " );
4455 4456 4457

		//

4458
		program = _gl.createProgram();
M
Mr.doob 已提交
4459

4460
		var prefix_vertex = [
M
Mr.doob 已提交
4461

A
alteredq 已提交
4462
			_supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
4463

4464 4465 4466
			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,

4467 4468
			"#define MAX_SHADOWS " + parameters.maxShadows,

4469 4470
			"#define MAX_BONES " + parameters.maxBones,

4471
			parameters.map ? "#define USE_MAP" : "",
4472 4473 4474
			parameters.envMap ? "#define USE_ENVMAP" : "",
			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
			parameters.vertexColors ? "#define USE_COLOR" : "",
4475
			parameters.skinning ? "#define USE_SKINNING" : "",
4476
			parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
4477

4478
			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
4479
			parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
4480

4481 4482
			parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",

M
Mr.doob 已提交
4483 4484 4485
			"uniform mat4 objectMatrix;",
			"uniform mat4 modelViewMatrix;",
			"uniform mat4 projectionMatrix;",
4486 4487
			"uniform mat4 viewMatrix;",
			"uniform mat3 normalMatrix;",
M
Mr.doob 已提交
4488
			"uniform vec3 cameraPosition;",
A
alteredq 已提交
4489 4490 4491

			"uniform mat4 cameraInverseMatrix;",

M
Mr.doob 已提交
4492 4493 4494
			"attribute vec3 position;",
			"attribute vec3 normal;",
			"attribute vec2 uv;",
4495
			"attribute vec2 uv2;",
4496

4497
			"#ifdef USE_COLOR",
4498

4499
				"attribute vec3 color;",
4500

4501 4502
			"#endif",

4503
			"#ifdef USE_MORPHTARGETS",
4504

4505 4506 4507 4508 4509 4510 4511 4512
				"attribute vec3 morphTarget0;",
				"attribute vec3 morphTarget1;",
				"attribute vec3 morphTarget2;",
				"attribute vec3 morphTarget3;",
				"attribute vec3 morphTarget4;",
				"attribute vec3 morphTarget5;",
				"attribute vec3 morphTarget6;",
				"attribute vec3 morphTarget7;",
4513

4514 4515 4516
			"#endif",

			"#ifdef USE_SKINNING",
4517

4518 4519 4520 4521
				"attribute vec4 skinVertexA;",
				"attribute vec4 skinVertexB;",
				"attribute vec4 skinIndex;",
				"attribute vec4 skinWeight;",
4522

4523
			"#endif",
4524

M
Mr.doob 已提交
4525
			""
A
alteredq 已提交
4526

M
Mr.doob 已提交
4527
		].join("\n");
4528

M
Mr.doob 已提交
4529 4530 4531 4532 4533 4534 4535 4536 4537
		var prefix_fragment = [

			"#ifdef GL_ES",
			"precision highp float;",
			"#endif",

			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,

4538 4539
			"#define MAX_SHADOWS " + parameters.maxShadows,

4540 4541
			parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "",

M
Mr.doob 已提交
4542 4543 4544 4545 4546 4547 4548
			parameters.fog ? "#define USE_FOG" : "",
			parameters.fog instanceof THREE.FogExp2 ? "#define FOG_EXP2" : "",

			parameters.map ? "#define USE_MAP" : "",
			parameters.envMap ? "#define USE_ENVMAP" : "",
			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
			parameters.vertexColors ? "#define USE_COLOR" : "",
4549

4550
			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
4551 4552 4553
			parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
			parameters.shadowMapSoft ? "#define SHADOWMAP_WIDTH " + parameters.shadowMapWidth.toFixed( 1 ) : "",
			parameters.shadowMapSoft ? "#define SHADOWMAP_HEIGHT " + parameters.shadowMapHeight.toFixed( 1 ) : "",
M
Mr.doob 已提交
4554 4555 4556 4557 4558 4559 4560

			"uniform mat4 viewMatrix;",
			"uniform vec3 cameraPosition;",
			""

		].join("\n");

4561 4562
		_gl.attachShader( program, getShader( "fragment", prefix_fragment + fragmentShader ) );
		_gl.attachShader( program, getShader( "vertex", prefix_vertex + vertexShader ) );
M
Mr.doob 已提交
4563

M
Mr.doob 已提交
4564
		_gl.linkProgram( program );
N
Nicolas Garcia Belmonte 已提交
4565

M
Mr.doob 已提交
4566
		if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) {
N
Nicolas Garcia Belmonte 已提交
4567

4568
			console.error( "Could not initialise shader\n" + "VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" );
M
Mr.doob 已提交
4569

N
Nicolas Garcia Belmonte 已提交
4570
		}
4571

4572 4573
		//console.log( prefix_fragment + fragmentShader );
		//console.log( prefix_vertex + vertexShader );
M
Mr.doob 已提交
4574

M
Mr.doob 已提交
4575
		program.uniforms = {};
4576
		program.attributes = {};
M
Mr.doob 已提交
4577

4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595
		var identifiers, u, a, i;

		// cache uniform locations

		identifiers = [

			'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition',
			'cameraInverseMatrix', 'boneGlobalMatrices', 'morphTargetInfluences'

		];

		for ( u in uniforms ) {

			identifiers.push( u );

		}

		cacheUniformLocations( program, identifiers );
4596

4597 4598 4599 4600 4601 4602 4603 4604 4605
		// cache attributes locations

		identifiers = [

			"position", "normal", "uv", "uv2", "tangent", "color",
			"skinVertexA", "skinVertexB", "skinIndex", "skinWeight"

		];

4606
		for ( i = 0; i < parameters.maxMorphTargets; i ++ ) {
4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619

			identifiers.push( "morphTarget" + i );

		}

		for ( a in attributes ) {

			identifiers.push( a );

		}

		cacheAttributeLocations( program, identifiers );

4620 4621
		_programs.push( { program: program, code: code } );

M
Mr.doob 已提交
4622
		return program;
M
Mr.doob 已提交
4623

M
Mr.doob 已提交
4624
	};
M
Mr.doob 已提交
4625

4626
	function loadUniformsSkinning( uniforms, object ) {
4627

M
Mr.doob 已提交
4628
		_gl.uniformMatrix4fv( uniforms.cameraInverseMatrix, false, _viewMatrixArray );
A
alteredq 已提交
4629
		_gl.uniformMatrix4fv( uniforms.boneGlobalMatrices, false, object.boneMatrices );
4630

4631
	};
4632

4633

4634
	function loadUniformsMatrices( uniforms, object ) {
4635

A
alteredq 已提交
4636
		_gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object._modelViewMatrixArray );
A
alteredq 已提交
4637 4638 4639 4640 4641 4642

		if ( uniforms.normalMatrix ) {

			_gl.uniformMatrix3fv( uniforms.normalMatrix, false, object._normalMatrixArray );

		}
A
alteredq 已提交
4643 4644

	};
4645

4646
	function loadUniformsGeneric( program, uniforms ) {
M
Mr.doob 已提交
4647

4648
		var u, uniform, value, type, location, texture, i, il, offset;
M
Mr.doob 已提交
4649

M
Mr.doob 已提交
4650
		for( u in uniforms ) {
M
Mr.doob 已提交
4651

4652
			location = program.uniforms[ u ];
4653
			if ( !location ) continue;
M
Mr.doob 已提交
4654

4655
			uniform = uniforms[ u ];
M
Mr.doob 已提交
4656

4657 4658
			type = uniform.type;
			value = uniform.value;
M
Mr.doob 已提交
4659

4660 4661
			// single integer

M
Mr.doob 已提交
4662
			if( type == "i" ) {
M
Mr.doob 已提交
4663

M
Mr.doob 已提交
4664
				_gl.uniform1i( location, value );
M
Mr.doob 已提交
4665

4666 4667
			// single float

M
Mr.doob 已提交
4668
			} else if( type == "f" ) {
M
Mr.doob 已提交
4669

M
Mr.doob 已提交
4670
				_gl.uniform1f( location, value );
4671

4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697
			// single THREE.Vector2

			} else if( type == "v2" ) {

				_gl.uniform2f( location, value.x, value.y );

			// single THREE.Vector3

			} else if( type == "v3" ) {

				_gl.uniform3f( location, value.x, value.y, value.z );

			// single THREE.Vector4

			} else if( type == "v4" ) {

				_gl.uniform4f( location, value.x, value.y, value.z, value.w );

			// single THREE.Color

			} else if( type == "c" ) {

				_gl.uniform3f( location, value.r, value.g, value.b );

			// flat array of floats (JS or typed array)

A
alteredq 已提交
4698 4699 4700
			} else if( type == "fv1" ) {

				_gl.uniform1fv( location, value );
M
Mr.doob 已提交
4701

4702 4703
			// flat array of floats with 3 x N size (JS or typed array)

4704 4705 4706 4707
			} else if( type == "fv" ) {

				_gl.uniform3fv( location, value );

4708
			// array of THREE.Vector3
4709

4710
			} else if( type == "v3v" ) {
4711

4712
				if ( ! uniform._array ) {
4713

4714
					uniform._array = new Float32Array( 3 * value.length );
4715

4716
				}
4717

4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730
				for ( i = 0, il = value.length; i < il; i ++ ) {

					offset = i * 3;

					uniform._array[ offset ] 	 = value[ i ].x;
					uniform._array[ offset + 1 ] = value[ i ].y;
					uniform._array[ offset + 2 ] = value[ i ].z;

				}

				_gl.uniform3fv( location, uniform._array );

			// single THREE.Matrix4
4731

4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742
			} else if( type == "m4" ) {

				if ( ! uniform._array ) {

					uniform._array = new Float32Array( 16 );

				}

				value.flattenToArray( uniform._array );
				_gl.uniformMatrix4fv( location, false, uniform._array );

4743 4744
			// array of THREE.Matrix4

4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760
			} else if( type == "m4v" ) {

				if ( ! uniform._array ) {

					uniform._array = new Float32Array( 16 * value.length );

				}

				for ( i = 0, il = value.length; i < il; i ++ ) {

					value[ i ].flattenToArrayOffset( uniform._array, i * 16 );

				}

				_gl.uniformMatrix4fv( location, false, uniform._array );

4761

4762
			// single THREE.Texture (2d or cube)
M
Mr.doob 已提交
4763

M
Mr.doob 已提交
4764
			} else if( type == "t" ) {
M
Mr.doob 已提交
4765

M
Mr.doob 已提交
4766
				_gl.uniform1i( location, value );
M
Mr.doob 已提交
4767

4768
				texture = uniform.texture;
M
Mr.doob 已提交
4769

4770
				if ( !texture ) continue;
M
Mr.doob 已提交
4771

4772
				if ( texture.image instanceof Array && texture.image.length == 6 ) {
M
Mr.doob 已提交
4773

4774
					setCubeTexture( texture, value );
M
Mr.doob 已提交
4775

A
alteredq 已提交
4776 4777 4778 4779
				} else if ( texture instanceof THREE.WebGLRenderTargetCube ) {

					setCubeTextureDynamic( texture, value );

4780
				} else {
M
Mr.doob 已提交
4781

4782
					setTexture( texture, value );
M
Mr.doob 已提交
4783

4784
				}
M
Mr.doob 已提交
4785

4786 4787
			// array of THREE.Texture (2d)

4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813
			} else if( type == "tv" ) {

				if ( ! uniform._array ) {

					uniform._array = [];

					for( i = 0, il = uniform.texture.length; i < il; i ++ ) {

						uniform._array[ i ] = value + i;

					}

				}

				_gl.uniform1iv( location, uniform._array );

				for( i = 0, il = uniform.texture.length; i < il; i ++ ) {

					texture = uniform.texture[ i ];

					if ( !texture ) continue;

					setTexture( texture, uniform._array[ i ] );

				}

4814
			}
M
Mr.doob 已提交
4815

4816
		}
M
Mr.doob 已提交
4817

4818
	};
M
Mr.doob 已提交
4819

4820
	function setBlending( blending ) {
A
alteredq 已提交
4821 4822

		if ( blending != _oldBlending ) {
4823

A
alteredq 已提交
4824 4825 4826 4827 4828
			switch ( blending ) {

				case THREE.AdditiveBlending:

					_gl.blendEquation( _gl.FUNC_ADD );
4829
					_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE );
A
alteredq 已提交
4830 4831 4832 4833 4834

					break;

				case THREE.SubtractiveBlending:

4835 4836 4837 4838
					// TODO: Find blendFuncSeparate() combination

					_gl.blendEquation( _gl.FUNC_ADD );
					_gl.blendFunc( _gl.ZERO, _gl.ONE_MINUS_SRC_COLOR );
A
alteredq 已提交
4839 4840 4841

					break;

4842 4843 4844
				case THREE.MultiplyBlending:

					// TODO: Find blendFuncSeparate() combination
A
alteredq 已提交
4845 4846

					_gl.blendEquation( _gl.FUNC_ADD );
4847
					_gl.blendFunc( _gl.ZERO, _gl.SRC_COLOR );
A
alteredq 已提交
4848 4849 4850 4851 4852

					break;

				default:

4853 4854
					_gl.blendEquationSeparate( _gl.FUNC_ADD, _gl.FUNC_ADD );
					_gl.blendFuncSeparate( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA );
A
alteredq 已提交
4855 4856

					break;
4857

A
alteredq 已提交
4858
			}
4859

A
alteredq 已提交
4860
			_oldBlending = blending;
4861

A
alteredq 已提交
4862 4863 4864
		}

	};
4865

4866
	function setTextureParameters( textureType, texture, image ) {
4867

4868
		if ( isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ) ) {
M
Mr.doob 已提交
4869

4870 4871
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
M
Mr.doob 已提交
4872

4873 4874
			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
M
Mr.doob 已提交
4875

4876
			_gl.generateMipmap( textureType );
M
Mr.doob 已提交
4877

4878
		} else {
M
Mr.doob 已提交
4879

4880 4881
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
4882

4883 4884
			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
M
Mr.doob 已提交
4885

4886
		}
M
Mr.doob 已提交
4887

4888
	};
4889

4890
	function setTexture( texture, slot ) {
4891

4892
		if ( texture.needsUpdate ) {
A
alteredq 已提交
4893

4894
			if ( ! texture.__webglInit ) {
M
Mr.doob 已提交
4895

4896
				texture.__webglTexture = _gl.createTexture();
4897
				texture.__webglInit = true;
A
alteredq 已提交
4898

4899
			}
M
Mr.doob 已提交
4900

4901
			_gl.activeTexture( _gl.TEXTURE0 + slot );
4902 4903
			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );

4904
			if ( texture instanceof THREE.DataTexture) {
4905 4906

				_gl.texImage2D( _gl.TEXTURE_2D, 0, paramThreeToGL( texture.format ), texture.image.width, texture.image.height, 0, paramThreeToGL( texture.format ), _gl.UNSIGNED_BYTE, texture.image.data );
M
Mr.doob 已提交
4907

A
alteredq 已提交
4908
			} else {
M
Mr.doob 已提交
4909

M
Mr.doob 已提交
4910
				_gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image );
M
Mr.doob 已提交
4911 4912 4913

			}

4914
			setTextureParameters( _gl.TEXTURE_2D, texture, texture.image );
M
Mr.doob 已提交
4915

A
alteredq 已提交
4916
			texture.needsUpdate = false;
4917

4918
		} else {
4919

4920 4921
			_gl.activeTexture( _gl.TEXTURE0 + slot );
			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
4922 4923

		}
M
Mr.doob 已提交
4924

4925
	};
M
Mr.doob 已提交
4926

4927
	function setCubeTexture( texture, slot ) {
4928 4929 4930 4931 4932

		if ( texture.image.length == 6 ) {

			if ( texture.needsUpdate ) {

A
alteredq 已提交
4933
				if ( ! texture.image.__webglTextureCube ) {
4934 4935

					texture.image.__webglTextureCube = _gl.createTexture();
4936

A
alteredq 已提交
4937
				}
4938

A
alteredq 已提交
4939 4940
				_gl.activeTexture( _gl.TEXTURE0 + slot );
				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
4941

A
alteredq 已提交
4942
				for ( var i = 0; i < 6; i ++ ) {
4943

A
alteredq 已提交
4944
					_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image[ i ] );
4945

A
alteredq 已提交
4946
				}
4947

A
alteredq 已提交
4948
				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, texture.image[ 0 ] );
4949

A
alteredq 已提交
4950
				texture.needsUpdate = false;
4951

A
alteredq 已提交
4952
			} else {
4953

A
alteredq 已提交
4954 4955
				_gl.activeTexture( _gl.TEXTURE0 + slot );
				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
4956

A
alteredq 已提交
4957
			}
4958

A
alteredq 已提交
4959
		}
4960

A
alteredq 已提交
4961
	};
4962

A
alteredq 已提交
4963
	function setCubeTextureDynamic( texture, slot ) {
4964

A
alteredq 已提交
4965 4966
		_gl.activeTexture( _gl.TEXTURE0 + slot );
		_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
4967 4968 4969

	};

4970
	function setRenderTarget( renderTexture ) {
4971

A
alteredq 已提交
4972 4973
		var isCube = ( renderTexture instanceof THREE.WebGLRenderTargetCube );

4974
		if ( renderTexture && !renderTexture.__webglFramebuffer ) {
M
Mr.doob 已提交
4975

M
Mikael Emtinger 已提交
4976 4977 4978
			if( renderTexture.depthBuffer === undefined ) renderTexture.depthBuffer = true;
			if( renderTexture.stencilBuffer === undefined ) renderTexture.stencilBuffer = true;

4979 4980
			renderTexture.__webglRenderbuffer = _gl.createRenderbuffer();
			renderTexture.__webglTexture = _gl.createTexture();
4981 4982

			// Setup texture
M
Mr.doob 已提交
4983

A
alteredq 已提交
4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010
			if ( isCube ) {

				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTexture.__webglTexture );

				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTexture, renderTexture );

				renderTexture.__webglFramebuffer = [];

				for ( var i = 0; i < 6; i ++ ) {

					renderTexture.__webglFramebuffer[ i ] = _gl.createFramebuffer();
					_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, paramThreeToGL( renderTexture.format ), renderTexture.width, renderTexture.height, 0, paramThreeToGL( renderTexture.format ), paramThreeToGL( renderTexture.type ), null );

				}


			} else {

				renderTexture.__webglFramebuffer = _gl.createFramebuffer();

				_gl.bindTexture( _gl.TEXTURE_2D, renderTexture.__webglTexture );

				setTextureParameters( _gl.TEXTURE_2D, renderTexture, renderTexture );

				_gl.texImage2D( _gl.TEXTURE_2D, 0, paramThreeToGL( renderTexture.format ), renderTexture.width, renderTexture.height, 0, paramThreeToGL( renderTexture.format ), paramThreeToGL( renderTexture.type ), null );

			}
5011

M
Mikael Emtinger 已提交
5012
			// Setup render and frame buffer
M
Mr.doob 已提交
5013

M
Mikael Emtinger 已提交
5014 5015
			_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTexture.__webglRenderbuffer );

A
alteredq 已提交
5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031

			if ( isCube ) {

				for ( var i = 0; i < 6; ++ i ) {

					_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTexture.__webglFramebuffer[ i ] );
					_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, renderTexture.__webglTexture, 0 );

				}

			} else {

				_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTexture.__webglFramebuffer );
				_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, renderTexture.__webglTexture, 0 );

			}
5032 5033 5034

			if ( renderTexture.depthBuffer && !renderTexture.stencilBuffer ) {

M
Mikael Emtinger 已提交
5035 5036
				_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTexture.width, renderTexture.height );
				_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTexture.__webglRenderbuffer );
5037

M
Mr.doob 已提交
5038
			/* For some reason this is not working. Defaulting to RGBA4.
M
Mikael Emtinger 已提交
5039
			} else if( !renderTexture.depthBuffer && renderTexture.stencilBuffer ) {
5040

M
Mikael Emtinger 已提交
5041 5042 5043 5044
				_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTexture.width, renderTexture.height );
				_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTexture.__webglRenderbuffer );
			*/
			} else if( renderTexture.depthBuffer && renderTexture.stencilBuffer ) {
5045

M
Mikael Emtinger 已提交
5046 5047
				_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTexture.width, renderTexture.height );
				_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTexture.__webglRenderbuffer );
5048

M
Mikael Emtinger 已提交
5049
			} else {
5050

M
Mikael Emtinger 已提交
5051
				_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTexture.width, renderTexture.height );
5052

M
Mikael Emtinger 已提交
5053
			}
5054

5055 5056

			// Release everything
M
Mr.doob 已提交
5057

A
alteredq 已提交
5058 5059 5060 5061 5062 5063 5064 5065 5066 5067
			if ( isCube ) {

				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );

			} else {

				_gl.bindTexture( _gl.TEXTURE_2D, null );

			}

5068 5069
			_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null);
M
Mr.doob 已提交
5070

5071 5072
		}

5073
		var framebuffer, width, height, vx, vy;
M
Mr.doob 已提交
5074

5075
		if ( renderTexture ) {
M
Mr.doob 已提交
5076

A
alteredq 已提交
5077 5078 5079 5080 5081 5082 5083 5084 5085 5086
			if ( isCube ) {

				framebuffer = renderTexture.__webglFramebuffer[ renderTexture.activeCubeFace ];

			} else {

				framebuffer = renderTexture.__webglFramebuffer;

			}

5087 5088
			width = renderTexture.width;
			height = renderTexture.height;
M
Mr.doob 已提交
5089

5090 5091 5092
			vx = 0;
			vy = 0;

5093
		} else {
M
Mr.doob 已提交
5094

5095
			framebuffer = null;
5096 5097
			width = _viewportWidth;
			height = _viewportHeight;
5098 5099
			vx = _viewportX;
			vy = _viewportY;
M
Mr.doob 已提交
5100

5101
		}
M
Mr.doob 已提交
5102

5103
		if ( framebuffer != _currentFramebuffer ) {
M
Mr.doob 已提交
5104

5105
			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
5106
			_gl.viewport( vx, vy, width, height );
M
Mr.doob 已提交
5107

5108
			_currentFramebuffer = framebuffer;
M
Mr.doob 已提交
5109

5110
		}
5111

5112
	};
M
Mr.doob 已提交
5113

5114
	function updateRenderTargetMipmap( renderTarget ) {
M
Mr.doob 已提交
5115

A
alteredq 已提交
5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128
		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {

			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
			_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );

		} else {

			_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
			_gl.generateMipmap( _gl.TEXTURE_2D );
			_gl.bindTexture( _gl.TEXTURE_2D, null );

		}
M
Mr.doob 已提交
5129 5130

	};
5131

5132
	function cacheUniformLocations( program, identifiers ) {
M
Mr.doob 已提交
5133

M
Mr.doob 已提交
5134
		var i, l, id;
M
Mr.doob 已提交
5135

M
Mr.doob 已提交
5136
		for( i = 0, l = identifiers.length; i < l; i++ ) {
M
Mr.doob 已提交
5137

5138 5139
			id = identifiers[ i ];
			program.uniforms[ id ] = _gl.getUniformLocation( program, id );
M
Mr.doob 已提交
5140

M
Mr.doob 已提交
5141
		}
M
Mr.doob 已提交
5142

M
Mr.doob 已提交
5143
	};
M
Mr.doob 已提交
5144

5145
	function cacheAttributeLocations( program, identifiers ) {
5146

5147
		var i, l, id;
M
Mr.doob 已提交
5148

5149
		for( i = 0, l = identifiers.length; i < l; i++ ) {
M
Mr.doob 已提交
5150

5151 5152
			id = identifiers[ i ];
			program.attributes[ id ] = _gl.getAttribLocation( program, id );
M
Mr.doob 已提交
5153

5154
		}
M
Mr.doob 已提交
5155

M
Mr.doob 已提交
5156
	};
M
Mr.doob 已提交
5157

5158
	function getShader( type, string ) {
N
Nicolas Garcia Belmonte 已提交
5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176

		var shader;

		if ( type == "fragment" ) {

			shader = _gl.createShader( _gl.FRAGMENT_SHADER );

		} else if ( type == "vertex" ) {

			shader = _gl.createShader( _gl.VERTEX_SHADER );

		}

		_gl.shaderSource( shader, string );
		_gl.compileShader( shader );

		if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {

5177
			console.error( _gl.getShaderInfoLog( shader ) );
5178
			console.error( string );
N
Nicolas Garcia Belmonte 已提交
5179 5180 5181 5182 5183
			return null;

		}

		return shader;
M
Mr.doob 已提交
5184

5185
	};
N
Nicolas Garcia Belmonte 已提交
5186

5187
	// fallback filters for non-power-of-2 textures
5188

5189
	function filterFallback( f ) {
5190

5191 5192 5193 5194 5195 5196 5197 5198
		switch ( f ) {

			case THREE.NearestFilter:
			case THREE.NearestMipMapNearestFilter:
			case THREE.NearestMipMapLinearFilter: return _gl.NEAREST; break;

			case THREE.LinearFilter:
			case THREE.LinearMipMapNearestFilter:
M
Mr.doob 已提交
5199
			case THREE.LinearMipMapLinearFilter:
M
Mikael Emtinger 已提交
5200
			default:
5201

M
Mikael Emtinger 已提交
5202
				return _gl.LINEAR; break;
5203 5204

		}
5205

5206
	};
5207 5208

	function paramThreeToGL( p ) {
M
Mr.doob 已提交
5209

5210
		switch ( p ) {
M
Mr.doob 已提交
5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223

			case THREE.RepeatWrapping: return _gl.REPEAT; break;
			case THREE.ClampToEdgeWrapping: return _gl.CLAMP_TO_EDGE; break;
			case THREE.MirroredRepeatWrapping: return _gl.MIRRORED_REPEAT; break;

			case THREE.NearestFilter: return _gl.NEAREST; break;
			case THREE.NearestMipMapNearestFilter: return _gl.NEAREST_MIPMAP_NEAREST; break;
			case THREE.NearestMipMapLinearFilter: return _gl.NEAREST_MIPMAP_LINEAR; break;

			case THREE.LinearFilter: return _gl.LINEAR; break;
			case THREE.LinearMipMapNearestFilter: return _gl.LINEAR_MIPMAP_NEAREST; break;
			case THREE.LinearMipMapLinearFilter: return _gl.LINEAR_MIPMAP_LINEAR; break;

5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237
			case THREE.ByteType: return _gl.BYTE; break;
			case THREE.UnsignedByteType: return _gl.UNSIGNED_BYTE; break;
			case THREE.ShortType: return _gl.SHORT; break;
			case THREE.UnsignedShortType: return _gl.UNSIGNED_SHORT; break;
			case THREE.IntType: return _gl.INT; break;
			case THREE.UnsignedShortType: return _gl.UNSIGNED_INT; break;
			case THREE.FloatType: return _gl.FLOAT; break;

			case THREE.AlphaFormat: return _gl.ALPHA; break;
			case THREE.RGBFormat: return _gl.RGB; break;
			case THREE.RGBAFormat: return _gl.RGBA; break;
			case THREE.LuminanceFormat: return _gl.LUMINANCE; break;
			case THREE.LuminanceAlphaFormat: return _gl.LUMINANCE_ALPHA; break;

5238
		}
M
Mr.doob 已提交
5239

5240
		return 0;
M
Mr.doob 已提交
5241

5242 5243
	};

5244
	function isPowerOfTwo( value ) {
5245 5246 5247 5248 5249

		return ( value & ( value - 1 ) ) == 0;

	};

5250
	function materialNeedsSmoothNormals( material ) {
5251 5252 5253

		return material && material.shading != undefined && material.shading == THREE.SmoothShading;

5254
	};
M
Mr.doob 已提交
5255

5256
	function bufferNeedsSmoothNormals( geometryGroup, object ) {
M
Mr.doob 已提交
5257

5258
		var m, ml, i, l, meshMaterial, needsSmoothNormals = false;
M
Mr.doob 已提交
5259

M
Mr.doob 已提交
5260
		for ( m = 0, ml = object.materials.length; m < ml; m++ ) {
5261

M
Mr.doob 已提交
5262
			meshMaterial = object.materials[ m ];
5263 5264 5265

			if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {

5266
				for ( i = 0, l = geometryGroup.materials.length; i < l; i++ ) {
5267

5268
					if ( materialNeedsSmoothNormals( geometryGroup.materials[ i ] ) ) {
5269

5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290
						needsSmoothNormals = true;
						break;

					}

				}

			} else {

				if ( materialNeedsSmoothNormals( meshMaterial ) ) {

					needsSmoothNormals = true;
					break;

				}

			}

			if ( needsSmoothNormals ) break;

		}
M
Mr.doob 已提交
5291

5292
		return needsSmoothNormals;
M
Mr.doob 已提交
5293

5294
	};
M
Mr.doob 已提交
5295

5296
	function unrollGroupMaterials( geometryGroup, object ) {
5297

5298 5299 5300
		var m, ml, i, il,
			material, meshMaterial,
			materials = [];
5301

5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312
		for ( m = 0, ml = object.materials.length; m < ml; m++ ) {

			meshMaterial = object.materials[ m ];

			if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {

				for ( i = 0, l = geometryGroup.materials.length; i < l; i++ ) {

					material = geometryGroup.materials[ i ];

					if ( material ) {
5313

5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332
						materials.push( material );

					}

				}

			} else {

				material = meshMaterial;

				if ( material ) {

					materials.push( material );

				}

			}

		}
5333

5334 5335 5336
		return materials;

	};
5337

5338
	function bufferGuessVertexColorType( materials, geometryGroup, object ) {
5339

5340
		var i, m, ml = materials.length;
5341

5342
		// use vertexColor type from the first material in unrolled materials
5343

M
Mr.doob 已提交
5344
		for ( i = 0; i < ml; i ++ ) {
5345

5346
			m = materials[ i ];
5347

5348
			if ( m.vertexColors ) {
5349

5350 5351 5352
				return m.vertexColors;

			}
5353

5354
		}
5355

5356
		return false;
5357

5358 5359
	};

5360
	function bufferGuessNormalType( materials, geometryGroup, object ) {
5361

5362
		var i, m, ml = materials.length;
5363

5364
		// only MeshBasicMaterial and MeshDepthMaterial don't need normals
5365

M
Mr.doob 已提交
5366
		for ( i = 0; i < ml; i ++ ) {
5367

5368
			m = materials[ i ];
5369

A
alteredq 已提交
5370
			if ( ( m instanceof THREE.MeshBasicMaterial && !m.envMap ) || m instanceof THREE.MeshDepthMaterial ) continue;
5371

5372
			if ( materialNeedsSmoothNormals( m ) ) {
5373

5374 5375 5376 5377 5378 5379 5380 5381 5382
				return THREE.SmoothShading;

			} else {

				return THREE.FlatShading;

			}

		}
5383

5384
		return false;
5385

5386 5387
	};

5388
	function bufferGuessUVType( materials, geometryGroup, object ) {
5389

5390
		var i, m, ml = materials.length;
5391

5392
		// material must use some texture to require uvs
5393

5394
		for ( i = 0; i < ml; i++ ) {
5395

5396
			m = materials[ i ];
5397

A
alteredq 已提交
5398
			if ( m.map || m.lightMap || m instanceof THREE.MeshShaderMaterial ) {
5399

5400
				return true;
5401

5402
			}
5403

5404
		}
5405

5406
		return false;
5407

5408
	};
5409

5410
	function allocateBones( object ) {
5411

5412 5413 5414 5415 5416 5417 5418
		// default for when object is not specified
		// ( for example when prebuilding shader
		//   to be used with multiple objects )
		//
		// 	- leave some extra space for other uniforms
		//  - limit here is ANGLE's 254 max uniform vectors
		//    (up to 54 should be safe)
5419

5420
		var maxBones = 50;
5421

5422
		if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
5423

5424 5425 5426 5427 5428
			maxBones = object.bones.length;

		}

		return maxBones;
5429

5430
	};
5431

5432
	function allocateLights( lights ) {
5433

5434 5435
		var l, ll, light, dirLights, pointLights, maxDirLights, maxPointLights;
		dirLights = pointLights = maxDirLights = maxPointLights = 0;
5436

5437
		for ( l = 0, ll = lights.length; l < ll; l++ ) {
5438

5439
			light = lights[ l ];
5440

5441 5442 5443
			if ( light instanceof THREE.SpotLight ) dirLights ++; // hack, not a proper spotlight
			if ( light instanceof THREE.DirectionalLight ) dirLights ++;
			if ( light instanceof THREE.PointLight ) pointLights ++;
5444

5445
		}
5446

5447
		if ( ( pointLights + dirLights ) <= _maxLights ) {
5448

5449 5450
			maxDirLights = dirLights;
			maxPointLights = pointLights;
5451

5452
		} else {
5453

5454 5455
			maxDirLights = Math.ceil( _maxLights * dirLights / ( pointLights + dirLights ) );
			maxPointLights = _maxLights - maxDirLights;
5456 5457 5458

		}

5459
		return { 'directional' : maxDirLights, 'point' : maxPointLights };
5460 5461

	};
M
Mr.doob 已提交
5462

5463 5464
	function allocateShadows( lights ) {

M
Mr.doob 已提交
5465
		var l, ll, light, maxShadows = 0;
5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479

		for ( l = 0, ll = lights.length; l < ll; l++ ) {

			light = lights[ l ];

			if ( light instanceof THREE.SpotLight && light.castShadow ) maxShadows ++;

		}

		return maxShadows;

	};


A
alteredq 已提交
5480
	/* DEBUG
5481
	function getGLParams() {
M
Mr.doob 已提交
5482

5483
		var params  = {
M
Mr.doob 已提交
5484

5485 5486
			'MAX_VARYING_VECTORS': _gl.getParameter( _gl.MAX_VARYING_VECTORS ),
			'MAX_VERTEX_ATTRIBS': _gl.getParameter( _gl.MAX_VERTEX_ATTRIBS ),
M
Mr.doob 已提交
5487

5488 5489 5490
			'MAX_TEXTURE_IMAGE_UNITS': _gl.getParameter( _gl.MAX_TEXTURE_IMAGE_UNITS ),
			'MAX_VERTEX_TEXTURE_IMAGE_UNITS': _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ),
			'MAX_COMBINED_TEXTURE_IMAGE_UNITS' : _gl.getParameter( _gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ),
M
Mr.doob 已提交
5491

5492 5493 5494
			'MAX_VERTEX_UNIFORM_VECTORS': _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS ),
			'MAX_FRAGMENT_UNIFORM_VECTORS': _gl.getParameter( _gl.MAX_FRAGMENT_UNIFORM_VECTORS )
		}
M
Mr.doob 已提交
5495

5496 5497
		return params;
	};
M
Mr.doob 已提交
5498

5499
	function dumpObject( obj ) {
M
Mr.doob 已提交
5500

5501 5502
		var p, str = "";
		for ( p in obj ) {
M
Mr.doob 已提交
5503

5504
			str += p + ": " + obj[p] + "\n";
M
Mr.doob 已提交
5505

5506
		}
M
Mr.doob 已提交
5507

5508 5509
		return str;
	}
A
alteredq 已提交
5510
	*/
5511
};
5512