WebGLRenderer.js 144.9 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
	// constructor parameters
M
Mr.doob 已提交
11

12
	parameters = parameters || {};
M
Mr.doob 已提交
13

14
	var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
15

16
	_precision = parameters.precision !== undefined ? parameters.precision : 'highp',
17

18
	_alpha = parameters.alpha !== undefined ? parameters.alpha : true,
19
	_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
20
	_antialias = parameters.antialias !== undefined ? parameters.antialias : false,
21
	_stencil = parameters.stencil !== undefined ? parameters.stencil : true,
22 23
	_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,

24
	_clearColor = parameters.clearColor !== undefined ? new THREE.Color( parameters.clearColor ) : new THREE.Color( 0x000000 ),
M
Mr.doob 已提交
25 26
	_clearAlpha = parameters.clearAlpha !== undefined ? parameters.clearAlpha : 0,

27
	_maxLights = parameters.maxLights !== undefined ? parameters.maxLights : 4;
28

29
	// public properties
M
Mr.doob 已提交
30

N
Nicolas Garcia Belmonte 已提交
31
	this.domElement = _canvas;
32 33 34
	this.context = null;

	// clearing
M
Mr.doob 已提交
35

N
Nicolas Garcia Belmonte 已提交
36
	this.autoClear = true;
M
Mr.doob 已提交
37 38 39 40
	this.autoClearColor = true;
	this.autoClearDepth = true;
	this.autoClearStencil = true;

41 42
	// scene graph

43
	this.sortObjects = true;
N
Nicolas Garcia Belmonte 已提交
44

45
	this.autoUpdateObjects = true;
46
	this.autoUpdateScene = true;
47 48 49 50 51 52 53

	// physically based shading

	this.gammaInput = false;
	this.gammaOutput = false;
	this.physicallyBasedShading = false;

54 55 56
	// shadow map

	this.shadowMapEnabled = false;
57
	this.shadowMapAutoUpdate = true;
58
	this.shadowMapSoft = true;
A
alteredq 已提交
59
	this.shadowMapCullFrontFaces = true;
A
alteredq 已提交
60 61
	this.shadowMapDebug = false;
	this.shadowMapCascade = false;
62

63
	// morphs
64

65
	this.maxMorphTargets = 8;
A
alteredq 已提交
66
	this.maxMorphNormals = 4;
67

68 69 70 71
	// flags

	this.autoScaleCubemaps = true;

72 73
	// custom render plugins

A
alteredq 已提交
74 75
	this.renderPluginsPre = [];
	this.renderPluginsPost = [];
76

77
	// info
78

79
	this.info = {
80

81
		memory: {
82

83 84 85
			programs: 0,
			geometries: 0,
			textures: 0
86

87
		},
88

89
		render: {
90

91 92
			calls: 0,
			vertices: 0,
93 94
			faces: 0,
			points: 0
95 96 97

		}

98
	};
M
Mr.doob 已提交
99

100
	// internal properties
101

102
	var _this = this,
103

104
	_gl,
105

106
	_programs = [],
107

108
	// internal state cache
109

110 111 112 113
	_currentProgram = null,
	_currentFramebuffer = null,
	_currentMaterialId = -1,
	_currentGeometryGroupHash = null,
114
	_currentCamera = null,
115
	_geometryGroupCounter = 0,
116

117
	// GL state cache
118

119 120
	_oldDoubleSided = null,
	_oldFlipSided = null,
121

122
	_oldBlending = null,
123 124 125 126 127

	_oldBlendEquation = null,
	_oldBlendSrc = null,
	_oldBlendDst = null,

128 129
	_oldDepthTest = null,
	_oldDepthWrite = null,
130

131 132 133
	_oldPolygonOffset = null,
	_oldPolygonOffsetFactor = null,
	_oldPolygonOffsetUnits = null,
134

135
	_oldLineWidth = null,
136

137 138 139 140
	_viewportX = 0,
	_viewportY = 0,
	_viewportWidth = 0,
	_viewportHeight = 0,
A
alteredq 已提交
141 142
	_currentWidth = 0,
	_currentHeight = 0,
143

A
alteredq 已提交
144
	// frustum
M
Mr.doob 已提交
145

A
alteredq 已提交
146
	_frustum = new THREE.Frustum(),
147

148
	 // camera matrices cache
M
Mikael Emtinger 已提交
149

150
	_projScreenMatrix = new THREE.Matrix4(),
A
alteredq 已提交
151
	_projScreenMatrixPS = new THREE.Matrix4(),
M
Mr.doob 已提交
152

153
	_vector3 = new THREE.Vector4(),
M
Mikael Emtinger 已提交
154

155
	// light arrays cache
M
Mikael Emtinger 已提交
156

157 158
	_direction = new THREE.Vector3(),

159
	_lights = {
M
Mr.doob 已提交
160

161 162 163
		ambient: [ 0, 0, 0 ],
		directional: { length: 0, colors: new Array(), positions: new Array() },
		point: { length: 0, colors: new Array(), positions: new Array(), distances: new Array() }
M
Mr.doob 已提交
164

165
	};
M
Mr.doob 已提交
166

167
	// initialize
M
Mikael Emtinger 已提交
168

169
	_gl = initGL();
M
Mikael Emtinger 已提交
170

171
	setDefaultGLState();
M
Mikael Emtinger 已提交
172

173
	this.context = _gl;
M
Mikael Emtinger 已提交
174

175 176 177
	// GPU capabilities

	var _maxVertexTextures = _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ),
A
alteredq 已提交
178
	_maxTextureSize = _gl.getParameter( _gl.MAX_TEXTURE_SIZE ),
179
	_maxCubemapSize = _gl.getParameter( _gl.MAX_CUBE_MAP_TEXTURE_SIZE );
M
Mr.doob 已提交
180

181
	// API
M
Mr.doob 已提交
182

183
	this.getContext = function () {
M
Mr.doob 已提交
184

185
		return _gl;
M
Mr.doob 已提交
186

187
	};
M
Mr.doob 已提交
188

189
	this.supportsVertexTextures = function () {
M
Mikael Emtinger 已提交
190

191
		return _maxVertexTextures > 0;
M
Mikael Emtinger 已提交
192

193
	};
M
Mikael Emtinger 已提交
194

N
Nicolas Garcia Belmonte 已提交
195 196 197 198
	this.setSize = function ( width, height ) {

		_canvas.width = width;
		_canvas.height = height;
199

200 201 202
		this.setViewport( 0, 0, _canvas.width, _canvas.height );

	};
N
Nicolas Garcia Belmonte 已提交
203

204
	this.setViewport = function ( x, y, width, height ) {
205

206 207
		_viewportX = x;
		_viewportY = y;
208

209 210
		_viewportWidth = width;
		_viewportHeight = height;
211

212
		_gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
213

N
Nicolas Garcia Belmonte 已提交
214
	};
215

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

218
		_gl.scissor( x, y, width, height );
219

220
	};
221

222
	this.enableScissorTest = function ( enable ) {
223

M
Mr.doob 已提交
224
		enable ? _gl.enable( _gl.SCISSOR_TEST ) : _gl.disable( _gl.SCISSOR_TEST );
225 226

	};
227

228 229
	// Clearing

230
	this.setClearColorHex = function ( hex, alpha ) {
231

232 233 234 235
		_clearColor.setHex( hex );
		_clearAlpha = alpha;

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

237
	};
A
alteredq 已提交
238

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

241 242 243 244
		_clearColor.copy( color );
		_clearAlpha = alpha;

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

	};
247

M
Mr.doob 已提交
248 249 250 251 252 253 254
	this.getClearColor = function () {

		return _clearColor;

	};

	this.getClearAlpha = function () {
N
Nicolas Garcia Belmonte 已提交
255

M
Mr.doob 已提交
256 257 258 259 260 261 262 263
		return _clearAlpha;

	};

	this.clear = function ( color, depth, stencil ) {

		var bits = 0;

264 265 266
		if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
		if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
		if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
M
Mr.doob 已提交
267 268

		_gl.clear( bits );
N
Nicolas Garcia Belmonte 已提交
269 270 271

	};

272
	this.clearTarget = function ( renderTarget, color, depth, stencil ) {
M
Mr.doob 已提交
273

A
alteredq 已提交
274
		this.setRenderTarget( renderTarget );
275
		this.clear( color, depth, stencil );
M
Mr.doob 已提交
276 277 278

	};

279 280
	// Plugins

A
alteredq 已提交
281
	this.addPostPlugin = function ( plugin ) {
282 283

		plugin.init( this );
A
alteredq 已提交
284
		this.renderPluginsPost.push( plugin );
285 286 287

	};

A
alteredq 已提交
288 289 290 291 292 293
	this.addPrePlugin = function ( plugin ) {

		plugin.init( this );
		this.renderPluginsPre.push( plugin );

	};
294

295 296
	// Deallocation

297 298 299 300 301 302 303 304 305 306 307 308 309 310
	this.deallocateObject = function ( object ) {

		if ( ! object.__webglInit ) return;

		object.__webglInit = false;

		delete object._modelViewMatrix;

		delete object._normalMatrixArray;
		delete object._modelViewMatrixArray;
		delete object._objectMatrixArray;

		if ( object instanceof THREE.Mesh ) {

311
			for ( var g in object.geometry.geometryGroups ) {
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339

				deleteMeshBuffers( object.geometry.geometryGroups[ g ] );

			}

		} else if ( object instanceof THREE.Ribbon ) {

			deleteRibbonBuffers( object.geometry );

		} else if ( object instanceof THREE.Line ) {

			deleteLineBuffers( object.geometry );

		} else if ( object instanceof THREE.ParticleSystem ) {

			deleteParticleBuffers( object.geometry );

		}

	};

	this.deallocateTexture = function ( texture ) {

		if ( ! texture.__webglInit ) return;

		texture.__webglInit = false;
		_gl.deleteTexture( texture.__webglTexture );

M
Mr.doob 已提交
340 341
		_this.info.memory.textures --;

342 343
	};

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
	this.deallocateRenderTarget = function ( renderTarget ) {

		if ( !renderTarget || ! renderTarget.__webglTexture ) return;

		_gl.deleteTexture( renderTarget.__webglTexture );

		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {

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

				_gl.deleteFramebuffer( renderTarget.__webglFramebuffer[ i ] );
				_gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer[ i ] );

			}

		} else {

			_gl.deleteFramebuffer( renderTarget.__webglFramebuffer );
			_gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer );

		}

	};

368
	// Rendering
369

370
	this.updateShadowMap = function ( scene, camera ) {
371

A
alteredq 已提交
372 373 374 375 376 377 378 379
		_currentProgram = null;
		_oldBlending = -1;
		_oldDepthTest = -1;
		_oldDepthWrite = -1;
		_currentGeometryGroupHash = -1;
		_currentMaterialId = -1;

		this.shadowMapPlugin.update( scene, camera );
M
Mr.doob 已提交
380

381
	};
M
Mr.doob 已提交
382

383
	// Internal functions
384

385
	// Buffer allocation
386

387
	function createParticleBuffers ( geometry ) {
388

389 390
		geometry.__webglVertexBuffer = _gl.createBuffer();
		geometry.__webglColorBuffer = _gl.createBuffer();
M
Mr.doob 已提交
391

392
		_this.info.geometries ++;
393

394
	};
395

396
	function createLineBuffers ( geometry ) {
397

398 399
		geometry.__webglVertexBuffer = _gl.createBuffer();
		geometry.__webglColorBuffer = _gl.createBuffer();
400

401
		_this.info.memory.geometries ++;
402

403
	};
404

405
	function createRibbonBuffers ( geometry ) {
406

407 408
		geometry.__webglVertexBuffer = _gl.createBuffer();
		geometry.__webglColorBuffer = _gl.createBuffer();
409

410
		_this.info.memory.geometries ++;
M
Mr.doob 已提交
411

412
	};
413

414
	function createMeshBuffers ( geometryGroup ) {
415

416 417 418 419 420 421
		geometryGroup.__webglVertexBuffer = _gl.createBuffer();
		geometryGroup.__webglNormalBuffer = _gl.createBuffer();
		geometryGroup.__webglTangentBuffer = _gl.createBuffer();
		geometryGroup.__webglColorBuffer = _gl.createBuffer();
		geometryGroup.__webglUVBuffer = _gl.createBuffer();
		geometryGroup.__webglUV2Buffer = _gl.createBuffer();
422

423 424 425 426
		geometryGroup.__webglSkinVertexABuffer = _gl.createBuffer();
		geometryGroup.__webglSkinVertexBBuffer = _gl.createBuffer();
		geometryGroup.__webglSkinIndicesBuffer = _gl.createBuffer();
		geometryGroup.__webglSkinWeightsBuffer = _gl.createBuffer();
427

428 429
		geometryGroup.__webglFaceBuffer = _gl.createBuffer();
		geometryGroup.__webglLineBuffer = _gl.createBuffer();
430

431
		var m, ml;
432

433
		if ( geometryGroup.numMorphTargets ) {
434

435
			geometryGroup.__webglMorphTargetsBuffers = [];
436

437
			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
M
Mr.doob 已提交
438

439
				geometryGroup.__webglMorphTargetsBuffers.push( _gl.createBuffer() );
440 441 442 443 444 445 446 447 448 449 450

			}

		}

		if ( geometryGroup.numMorphNormals ) {

			geometryGroup.__webglMorphNormalsBuffers = [];

			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {

A
alteredq 已提交
451
				geometryGroup.__webglMorphNormalsBuffers.push( _gl.createBuffer() );
452

453
			}
454

455
		}
456

457
		_this.info.memory.geometries ++;
458

459
	};
460

461
	// Buffer deallocation
462

463
	function deleteParticleBuffers ( geometry ) {
464

465 466
		_gl.deleteBuffer( geometry.__webglVertexBuffer );
		_gl.deleteBuffer( geometry.__webglColorBuffer );
467

468
		_this.info.memory.geometries --;
469

470
	};
471

472
	function deleteLineBuffers ( geometry ) {
473

474 475
		_gl.deleteBuffer( geometry.__webglVertexBuffer );
		_gl.deleteBuffer( geometry.__webglColorBuffer );
476

M
Mr.doob 已提交
477 478
		_this.info.memory.geometries --;

479 480
	};

481
	function deleteRibbonBuffers ( geometry ) {
482 483 484 485

		_gl.deleteBuffer( geometry.__webglVertexBuffer );
		_gl.deleteBuffer( geometry.__webglColorBuffer );

M
Mr.doob 已提交
486 487
		_this.info.memory.geometries --;

488 489
	};

490
	function deleteMeshBuffers ( geometryGroup ) {
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506

		_gl.deleteBuffer( geometryGroup.__webglVertexBuffer );
		_gl.deleteBuffer( geometryGroup.__webglNormalBuffer );
		_gl.deleteBuffer( geometryGroup.__webglTangentBuffer );
		_gl.deleteBuffer( geometryGroup.__webglColorBuffer );
		_gl.deleteBuffer( geometryGroup.__webglUVBuffer );
		_gl.deleteBuffer( geometryGroup.__webglUV2Buffer );

		_gl.deleteBuffer( geometryGroup.__webglSkinVertexABuffer );
		_gl.deleteBuffer( geometryGroup.__webglSkinVertexBBuffer );
		_gl.deleteBuffer( geometryGroup.__webglSkinIndicesBuffer );
		_gl.deleteBuffer( geometryGroup.__webglSkinWeightsBuffer );

		_gl.deleteBuffer( geometryGroup.__webglFaceBuffer );
		_gl.deleteBuffer( geometryGroup.__webglLineBuffer );

507 508
		var m, ml;

509 510
		if ( geometryGroup.numMorphTargets ) {

511
			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
512 513

				_gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
514 515 516 517 518 519 520 521 522

			}

		}

		if ( geometryGroup.numMorphNormals ) {

			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {

A
alteredq 已提交
523
				_gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
524 525 526 527 528

			}

		}

529 530 531 532 533 534 535 536 537 538 539

		if ( geometryGroup.__webglCustomAttributesList ) {

			for ( var id in geometryGroup.__webglCustomAttributesList ) {

				_gl.deleteBuffer( geometryGroup.__webglCustomAttributesList[ id ].buffer );

			}

		}

M
Mr.doob 已提交
540 541
		_this.info.memory.geometries --;

542 543
	};

544
	// Buffer initialization
545

A
alteredq 已提交
546
	function initCustomAttributes ( geometry, object ) {
M
Mr.doob 已提交
547

548 549
		var nvertices = geometry.vertices.length;

550
		var material = object.material;
551

552
		if ( material.attributes ) {
553

554
			if ( geometry.__webglCustomAttributesList === undefined ) {
555

556
				geometry.__webglCustomAttributesList = [];
557

558
			}
559

560
			for ( var a in material.attributes ) {
561

562
				var attribute = material.attributes[ a ];
563

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

566
					attribute.__webglInitialized = true;
567

A
alteredq 已提交
568
					var size = 1;		// "f" and "i"
569

570 571 572 573
					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;
574

575
					attribute.size = size;
A
alteredq 已提交
576

577
					attribute.array = new Float32Array( nvertices * size );
A
alteredq 已提交
578

579 580
					attribute.buffer = _gl.createBuffer();
					attribute.buffer.belongsToAttribute = a;
581

582
					attribute.needsUpdate = true;
583

584
				}
585

586
				geometry.__webglCustomAttributesList.push( attribute );
587

588
			}
589

590
		}
591

592
	};
593

594
	function initParticleBuffers ( geometry, object ) {
A
alteredq 已提交
595 596 597 598 599 600

		var nvertices = geometry.vertices.length;

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

601 602 603
		geometry.__sortArray = [];

		geometry.__webglParticleCount = nvertices;
A
alteredq 已提交
604 605 606 607 608

		initCustomAttributes ( geometry, object );

	};

609
	function initLineBuffers ( geometry, object ) {
A
alteredq 已提交
610 611 612 613 614 615

		var nvertices = geometry.vertices.length;

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

616
		geometry.__webglLineCount = nvertices;
A
alteredq 已提交
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632

		initCustomAttributes ( geometry, object );

	};

	function initRibbonBuffers ( geometry ) {

		var nvertices = geometry.vertices.length;

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

		geometry.__webglVertexCount = nvertices;

	};

M
Mr.doob 已提交
633
	function initMeshBuffers ( geometryGroup, object ) {
M
Mr.doob 已提交
634

635 636 637
		var geometry = object.geometry,
			faces3 = geometryGroup.faces3,
			faces4 = geometryGroup.faces4,
M
Mr.doob 已提交
638

639 640 641
			nvertices = faces3.length * 3 + faces4.length * 4,
			ntris     = faces3.length * 1 + faces4.length * 2,
			nlines    = faces3.length * 3 + faces4.length * 4,
642

643
			material = getBufferMaterial( object, geometryGroup ),
644

645 646 647
			uvType = bufferGuessUVType( material ),
			normalType = bufferGuessNormalType( material ),
			vertexColorType = bufferGuessVertexColorType( material );
A
alteredq 已提交
648

649
		//console.log( "uvType", uvType, "normalType", normalType, "vertexColorType", vertexColorType, object, geometryGroup, material );
M
Mr.doob 已提交
650

651
		geometryGroup.__vertexArray = new Float32Array( nvertices * 3 );
652

653
		if ( normalType ) {
M
Mr.doob 已提交
654

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

657
		}
658

659
		if ( geometry.hasTangents ) {
660

661
			geometryGroup.__tangentArray = new Float32Array( nvertices * 4 );
662

663
		}
664

665
		if ( vertexColorType ) {
666

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

669
		}
M
Mr.doob 已提交
670

671
		if ( uvType ) {
672

673
			if ( geometry.faceUvs.length > 0 || geometry.faceVertexUvs.length > 0 ) {
674

675 676 677 678 679
				geometryGroup.__uvArray = new Float32Array( nvertices * 2 );

			}

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

681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
				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 );

		}

696
		geometryGroup.__faceArray = new Uint16Array( ntris * 3 );
697
		geometryGroup.__lineArray = new Uint16Array( nlines * 2 );
M
Mr.doob 已提交
698

699 700
		var m, ml;

701 702
		if ( geometryGroup.numMorphTargets ) {

M
Mr.doob 已提交
703
			geometryGroup.__morphTargetsArrays = [];
704

705
			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
706

707
				geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );
708 709 710 711 712 713 714 715 716 717 718

			}

		}

		if ( geometryGroup.numMorphNormals ) {

			geometryGroup.__morphNormalsArrays = [];

			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {

A
alteredq 已提交
719
				geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) );
720

721 722 723
			}

		}
724

725
		geometryGroup.__webglFaceCount = ntris * 3;
726
		geometryGroup.__webglLineCount = nlines * 2;
727

M
Mr.doob 已提交
728

729
		// custom attributes
M
Mr.doob 已提交
730

731
		if ( material.attributes ) {
732

733
			if ( geometryGroup.__webglCustomAttributesList === undefined ) {
734

735
				geometryGroup.__webglCustomAttributesList = [];
736

737
			}
738

739
			for ( var a in material.attributes ) {
M
Mr.doob 已提交
740

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

744
				var originalAttribute = material.attributes[ a ];
745

746
				var attribute = {};
747

748
				for ( var property in originalAttribute ) {
M
Mr.doob 已提交
749

750
					attribute[ property ] = originalAttribute[ property ];
751

752
				}
753

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

756
					attribute.__webglInitialized = true;
757

758
					var size = 1;		// "f" and "i"
M
Mr.doob 已提交
759

760 761 762 763
					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;
764

765
					attribute.size = size;
A
alteredq 已提交
766

767
					attribute.array = new Float32Array( nvertices * size );
A
alteredq 已提交
768

769 770
					attribute.buffer = _gl.createBuffer();
					attribute.buffer.belongsToAttribute = a;
771

772 773
					originalAttribute.needsUpdate = true;
					attribute.__original = originalAttribute;
774 775 776

				}

777 778
				geometryGroup.__webglCustomAttributesList.push( attribute );

779
			}
M
Mr.doob 已提交
780

781
		}
782

783 784
		geometryGroup.__inittedArrays = true;

785
	};
M
Mr.doob 已提交
786

787
	function getBufferMaterial( object, geometryGroup ) {
788

789
		if ( object.material && ! ( object.material instanceof THREE.MeshFaceMaterial ) ) {
790

791
			return object.material;
792

793
		} else if ( geometryGroup.materialIndex >= 0 ) {
794

795
			return object.geometry.materials[ geometryGroup.materialIndex ];
M
Mr.doob 已提交
796

797
		}
798

799
	};
M
Mr.doob 已提交
800

801
	function materialNeedsSmoothNormals ( material ) {
802

803
		return material && material.shading !== undefined && material.shading === THREE.SmoothShading;
804

805
	};
M
Mr.doob 已提交
806

807
	function bufferGuessNormalType ( material ) {
808

809
		// only MeshBasicMaterial and MeshDepthMaterial don't need normals
810

811
		if ( ( material instanceof THREE.MeshBasicMaterial && !material.envMap ) || material instanceof THREE.MeshDepthMaterial ) {
M
Mr.doob 已提交
812

813
			return false;
814

815
		}
816

817
		if ( materialNeedsSmoothNormals( material ) ) {
818

819
			return THREE.SmoothShading;
M
Mr.doob 已提交
820

821
		} else {
822

823
			return THREE.FlatShading;
824

825
		}
826

827
	};
828

829
	function bufferGuessVertexColorType ( material ) {
830

831
		if ( material.vertexColors ) {
832

833
			return material.vertexColors;
834

835
		}
M
Mr.doob 已提交
836

837
		return false;
M
Mr.doob 已提交
838

839
	};
M
Mr.doob 已提交
840

841
	function bufferGuessUVType ( material ) {
842

843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882
		// material must use some texture to require uvs

		if ( material.map || material.lightMap || material instanceof THREE.ShaderMaterial ) {

			return true;

		}

		return false;

	};

	// Buffer setting

	function setParticleBuffers ( geometry, hint, object ) {

		var v, c, vertex, offset, index, color,

		vertices = geometry.vertices,
		vl = vertices.length,

		colors = geometry.colors,
		cl = colors.length,

		vertexArray = geometry.__vertexArray,
		colorArray = geometry.__colorArray,

		sortArray = geometry.__sortArray,

		dirtyVertices = geometry.__dirtyVertices,
		dirtyElements = geometry.__dirtyElements,
		dirtyColors = geometry.__dirtyColors,

		customAttributes = geometry.__webglCustomAttributesList,
		i, il,
		a, ca, cal, value,
		customAttribute;

		if ( object.sortParticles ) {

A
alteredq 已提交
883 884
			_projScreenMatrixPS.copy( _projScreenMatrix );
			_projScreenMatrixPS.multiplySelf( object.matrixWorld );
885 886 887 888 889 890

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

				vertex = vertices[ v ].position;

				_vector3.copy( vertex );
A
alteredq 已提交
891
				_projScreenMatrixPS.multiplyVector3( _vector3 );
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059

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

			}

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

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

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

				offset = v * 3;

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

			}

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

				offset = c * 3;

				color = colors[ sortArray[c][1] ];

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

			}

			if ( customAttributes ) {

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

					customAttribute = customAttributes[ i ];

					if ( ! ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) ) continue;

					offset = 0;

					cal = customAttribute.value.length;

					if ( customAttribute.size === 1 ) {

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

							index = sortArray[ ca ][ 1 ];

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

						}

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

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

							index = sortArray[ ca ][ 1 ];

							value = customAttribute.value[ index ];

							customAttribute.array[ offset ] 	= value.x;
							customAttribute.array[ offset + 1 ] = value.y;

							offset += 2;

						}

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

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

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

								index = sortArray[ ca ][ 1 ];

								value = customAttribute.value[ index ];

								customAttribute.array[ offset ]     = value.r;
								customAttribute.array[ offset + 1 ] = value.g;
								customAttribute.array[ offset + 2 ] = value.b;

								offset += 3;

							}

						} else {

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

								index = sortArray[ ca ][ 1 ];

								value = customAttribute.value[ index ];

								customAttribute.array[ offset ] 	= value.x;
								customAttribute.array[ offset + 1 ] = value.y;
								customAttribute.array[ offset + 2 ] = value.z;

								offset += 3;

							}

						}

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

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

							index = sortArray[ ca ][ 1 ];

							value = customAttribute.value[ index ];

							customAttribute.array[ offset ]      = value.x;
							customAttribute.array[ offset + 1  ] = value.y;
							customAttribute.array[ offset + 2  ] = value.z;
							customAttribute.array[ offset + 3  ] = value.w;

							offset += 4;

						}

					}

				}

			}

		} else {

			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;

				}

			}

			if ( dirtyColors ) {

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

					color = colors[ c ];

					offset = c * 3;

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

				}

			}

			if ( customAttributes ) {

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

					customAttribute = customAttributes[ i ];

					if ( customAttribute.needsUpdate &&
1060
						 ( customAttribute.boundTo === undefined ||
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387
						   customAttribute.boundTo === "vertices") ) {

						cal = customAttribute.value.length;

						offset = 0;

						if ( customAttribute.size === 1 ) {

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

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

							}

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

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

								value = customAttribute.value[ ca ];

								customAttribute.array[ offset ] 	= value.x;
								customAttribute.array[ offset + 1 ] = value.y;

								offset += 2;

							}

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

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

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

									value = customAttribute.value[ ca ];

									customAttribute.array[ offset ] 	= value.r;
									customAttribute.array[ offset + 1 ] = value.g;
									customAttribute.array[ offset + 2 ] = value.b;

									offset += 3;

								}

							} else {

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

									value = customAttribute.value[ ca ];

									customAttribute.array[ offset ] 	= value.x;
									customAttribute.array[ offset + 1 ] = value.y;
									customAttribute.array[ offset + 2 ] = value.z;

									offset += 3;

								}

							}

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

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

								value = customAttribute.value[ ca ];

								customAttribute.array[ offset ]      = value.x;
								customAttribute.array[ offset + 1  ] = value.y;
								customAttribute.array[ offset + 2  ] = value.z;
								customAttribute.array[ offset + 3  ] = value.w;

								offset += 4;

							}

						}

					}

				}

			}

		}

		if ( dirtyVertices || object.sortParticles ) {

			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );

		}

		if ( dirtyColors || object.sortParticles ) {

			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );

		}

		if ( customAttributes ) {

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

				customAttribute = customAttributes[ i ];

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

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

				}

			}

		}


	};

	function setLineBuffers ( geometry, hint ) {

		var v, c, vertex, offset, color,

		vertices = geometry.vertices,
		colors = geometry.colors,
		vl = vertices.length,
		cl = colors.length,

		vertexArray = geometry.__vertexArray,
		colorArray = geometry.__colorArray,

		dirtyVertices = geometry.__dirtyVertices,
		dirtyColors = geometry.__dirtyColors,

		customAttributes = geometry.__webglCustomAttributesList,

		i, il,
		a, ca, cal, value,
		customAttribute;

		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;

			}

			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );

		}

		if ( dirtyColors ) {

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

				color = colors[ c ];

				offset = c * 3;

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

			}

			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );

		}

		if ( customAttributes ) {

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

				customAttribute = customAttributes[ i ];

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

					offset = 0;

					cal = customAttribute.value.length;

					if ( customAttribute.size === 1 ) {

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

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

						}

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

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

							value = customAttribute.value[ ca ];

							customAttribute.array[ offset ] 	= value.x;
							customAttribute.array[ offset + 1 ] = value.y;

							offset += 2;

						}

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

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

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

								value = customAttribute.value[ ca ];

								customAttribute.array[ offset ] 	= value.r;
								customAttribute.array[ offset + 1 ] = value.g;
								customAttribute.array[ offset + 2 ] = value.b;

								offset += 3;

							}

						} else {

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

								value = customAttribute.value[ ca ];

								customAttribute.array[ offset ] 	= value.x;
								customAttribute.array[ offset + 1 ] = value.y;
								customAttribute.array[ offset + 2 ] = value.z;

								offset += 3;

							}

						}

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

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

							value = customAttribute.value[ ca ];

							customAttribute.array[ offset ] 	 = value.x;
							customAttribute.array[ offset + 1  ] = value.y;
							customAttribute.array[ offset + 2  ] = value.z;
							customAttribute.array[ offset + 3  ] = value.w;

							offset += 4;

						}

					}

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

				}

			}

		}

	};

	function setRibbonBuffers ( geometry, hint ) {

		var v, c, vertex, offset, color,

		vertices = geometry.vertices,
		colors = geometry.colors,
		vl = vertices.length,
		cl = colors.length,

		vertexArray = geometry.__vertexArray,
		colorArray = geometry.__colorArray,

		dirtyVertices = geometry.__dirtyVertices,
		dirtyColors = geometry.__dirtyColors;

		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;

			}

			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );

		}

		if ( dirtyColors ) {

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

				color = colors[ c ];

				offset = c * 3;

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

			}

			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );

		}

	};

1388
	function setMeshBuffers( geometryGroup, object, hint, dispose, material ) {
1389 1390 1391 1392 1393 1394 1395 1396

		if ( ! geometryGroup.__inittedArrays ) {

			// console.log( object );
			return;

		}

1397 1398 1399 1400 1401 1402
		var normalType = bufferGuessNormalType( material ),
		vertexColorType = bufferGuessVertexColorType( material ),
		uvType = bufferGuessUVType( material ),

		needsSmoothNormals = ( normalType === THREE.SmoothShading );

1403 1404 1405 1406
		var f, fl, fi, face,
		vertexNormals, faceNormal, normal,
		vertexColors, faceColor,
		vertexTangents,
A
alteredq 已提交
1407
		uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4,
1408 1409 1410 1411 1412 1413 1414 1415
		c1, c2, c3, c4,
		sw1, sw2, sw3, sw4,
		si1, si2, si3, si4,
		sa1, sa2, sa3, sa4,
		sb1, sb2, sb3, sb4,
		m, ml, i, il,
		vn, uvi, uv2i,
		vk, vkl, vka,
A
alteredq 已提交
1416
		nka, chf, faceVertexNormals,
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
		a,

		vertexIndex = 0,

		offset = 0,
		offset_uv = 0,
		offset_uv2 = 0,
		offset_face = 0,
		offset_normal = 0,
		offset_tangent = 0,
		offset_line = 0,
		offset_color = 0,
		offset_skin = 0,
		offset_morphTarget = 0,
		offset_custom = 0,
		offset_customSrc = 0,

		value,

		vertexArray = geometryGroup.__vertexArray,
		uvArray = geometryGroup.__uvArray,
		uv2Array = geometryGroup.__uv2Array,
		normalArray = geometryGroup.__normalArray,
		tangentArray = geometryGroup.__tangentArray,
		colorArray = geometryGroup.__colorArray,

		skinVertexAArray = geometryGroup.__skinVertexAArray,
		skinVertexBArray = geometryGroup.__skinVertexBArray,
		skinIndexArray = geometryGroup.__skinIndexArray,
		skinWeightArray = geometryGroup.__skinWeightArray,

		morphTargetsArrays = geometryGroup.__morphTargetsArrays,
A
alteredq 已提交
1449
		morphNormalsArrays = geometryGroup.__morphNormalsArrays,
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481

		customAttributes = geometryGroup.__webglCustomAttributesList,
		customAttribute,

		faceArray = geometryGroup.__faceArray,
		lineArray = geometryGroup.__lineArray,

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

		dirtyVertices = geometry.__dirtyVertices,
		dirtyElements = geometry.__dirtyElements,
		dirtyUvs = geometry.__dirtyUvs,
		dirtyNormals = geometry.__dirtyNormals,
		dirtyTangents = geometry.__dirtyTangents,
		dirtyColors = geometry.__dirtyColors,
		dirtyMorphTargets = geometry.__dirtyMorphTargets,

		vertices = geometry.vertices,
		chunk_faces3 = geometryGroup.faces3,
		chunk_faces4 = geometryGroup.faces4,
		obj_faces = geometry.faces,

		obj_uvs  = geometry.faceVertexUvs[ 0 ],
		obj_uvs2 = geometry.faceVertexUvs[ 1 ],

		obj_colors = geometry.colors,

		obj_skinVerticesA = geometry.skinVerticesA,
		obj_skinVerticesB = geometry.skinVerticesB,
		obj_skinIndices = geometry.skinIndices,
		obj_skinWeights = geometry.skinWeights,

A
alteredq 已提交
1482 1483
		morphTargets = geometry.morphTargets,
		morphNormals = geometry.morphNormals;
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505

		if ( dirtyVertices ) {

			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {

				face = obj_faces[ chunk_faces3[ f ] ];

				v1 = vertices[ face.a ].position;
				v2 = vertices[ face.b ].position;
				v3 = vertices[ face.c ].position;

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

				vertexArray[ offset + 3 ] = v2.x;
				vertexArray[ offset + 4 ] = v2.y;
				vertexArray[ offset + 5 ] = v2.z;

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

1507
				offset += 9;
M
Mr.doob 已提交
1508

1509
			}
1510

A
alteredq 已提交
1511
			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
M
Mr.doob 已提交
1512

A
alteredq 已提交
1513
				face = obj_faces[ chunk_faces4[ f ] ];
M
Mr.doob 已提交
1514

A
alteredq 已提交
1515 1516 1517 1518
				v1 = vertices[ face.a ].position;
				v2 = vertices[ face.b ].position;
				v3 = vertices[ face.c ].position;
				v4 = vertices[ face.d ].position;
1519

A
alteredq 已提交
1520 1521 1522
				vertexArray[ offset ]     = v1.x;
				vertexArray[ offset + 1 ] = v1.y;
				vertexArray[ offset + 2 ] = v1.z;
1523

A
alteredq 已提交
1524 1525 1526
				vertexArray[ offset + 3 ] = v2.x;
				vertexArray[ offset + 4 ] = v2.y;
				vertexArray[ offset + 5 ] = v2.z;
1527

A
alteredq 已提交
1528 1529 1530
				vertexArray[ offset + 6 ] = v3.x;
				vertexArray[ offset + 7 ] = v3.y;
				vertexArray[ offset + 8 ] = v3.z;
1531

A
alteredq 已提交
1532 1533 1534
				vertexArray[ offset + 9 ]  = v4.x;
				vertexArray[ offset + 10 ] = v4.y;
				vertexArray[ offset + 11 ] = v4.z;
1535

A
alteredq 已提交
1536
				offset += 12;
1537

A
alteredq 已提交
1538
			}
1539

A
alteredq 已提交
1540 1541
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
M
Mr.doob 已提交
1542

A
alteredq 已提交
1543
		}
M
Mr.doob 已提交
1544

A
alteredq 已提交
1545
		if ( dirtyMorphTargets ) {
M
Mr.doob 已提交
1546

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

1549
				offset_morphTarget = 0;
1550

1551 1552
				for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {

A
alteredq 已提交
1553 1554 1555 1556
					chf = chunk_faces3[ f ];
					face = obj_faces[ chf ];

					// morph positions
M
Mr.doob 已提交
1557

A
alteredq 已提交
1558 1559 1560
					v1 = morphTargets[ vk ].vertices[ face.a ].position;
					v2 = morphTargets[ vk ].vertices[ face.b ].position;
					v3 = morphTargets[ vk ].vertices[ face.c ].position;
M
Mr.doob 已提交
1561

A
alteredq 已提交
1562
					vka = morphTargetsArrays[ vk ];
M
Mr.doob 已提交
1563

A
alteredq 已提交
1564 1565 1566
					vka[ offset_morphTarget ] 	  = v1.x;
					vka[ offset_morphTarget + 1 ] = v1.y;
					vka[ offset_morphTarget + 2 ] = v1.z;
M
Mr.doob 已提交
1567

A
alteredq 已提交
1568 1569 1570
					vka[ offset_morphTarget + 3 ] = v2.x;
					vka[ offset_morphTarget + 4 ] = v2.y;
					vka[ offset_morphTarget + 5 ] = v2.z;
M
Mr.doob 已提交
1571

A
alteredq 已提交
1572 1573 1574
					vka[ offset_morphTarget + 6 ] = v3.x;
					vka[ offset_morphTarget + 7 ] = v3.y;
					vka[ offset_morphTarget + 8 ] = v3.z;
M
Mr.doob 已提交
1575

A
alteredq 已提交
1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
					// morph normals

					if ( material.morphNormals ) {

						if ( needsSmoothNormals ) {

							faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];

							n1 = faceVertexNormals.a;
							n2 = faceVertexNormals.b;
							n3 = faceVertexNormals.c;

						} else {

							n1 = morphNormals[ vk ].faceNormals[ chf ];
							n2 = n1;
							n3 = n1;

						}

						nka = morphNormalsArrays[ vk ];

						nka[ offset_morphTarget ] 	  = n1.x;
						nka[ offset_morphTarget + 1 ] = n1.y;
						nka[ offset_morphTarget + 2 ] = n1.z;

						nka[ offset_morphTarget + 3 ] = n2.x;
						nka[ offset_morphTarget + 4 ] = n2.y;
						nka[ offset_morphTarget + 5 ] = n2.z;

						nka[ offset_morphTarget + 6 ] = n3.x;
						nka[ offset_morphTarget + 7 ] = n3.y;
						nka[ offset_morphTarget + 8 ] = n3.z;

					}

					//

1614
					offset_morphTarget += 9;
1615

1616
				}
1617

1618
				for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
1619

A
alteredq 已提交
1620 1621 1622 1623
					chf = chunk_faces4[ f ];
					face = obj_faces[ chf ];

					// morph positions
1624

1625 1626 1627
					v1 = morphTargets[ vk ].vertices[ face.a ].position;
					v2 = morphTargets[ vk ].vertices[ face.b ].position;
					v3 = morphTargets[ vk ].vertices[ face.c ].position;
A
alteredq 已提交
1628
					v4 = morphTargets[ vk ].vertices[ face.d ].position;
1629

1630
					vka = morphTargetsArrays[ vk ];
1631

1632 1633 1634
					vka[ offset_morphTarget ] 	  = v1.x;
					vka[ offset_morphTarget + 1 ] = v1.y;
					vka[ offset_morphTarget + 2 ] = v1.z;
1635

1636 1637 1638
					vka[ offset_morphTarget + 3 ] = v2.x;
					vka[ offset_morphTarget + 4 ] = v2.y;
					vka[ offset_morphTarget + 5 ] = v2.z;
1639

1640 1641 1642
					vka[ offset_morphTarget + 6 ] = v3.x;
					vka[ offset_morphTarget + 7 ] = v3.y;
					vka[ offset_morphTarget + 8 ] = v3.z;
1643

A
alteredq 已提交
1644 1645 1646 1647
					vka[ offset_morphTarget + 9 ]  = v4.x;
					vka[ offset_morphTarget + 10 ] = v4.y;
					vka[ offset_morphTarget + 11 ] = v4.z;

A
alteredq 已提交
1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691
					// morph normals

					if ( material.morphNormals ) {

						if ( needsSmoothNormals ) {

							faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];

							n1 = faceVertexNormals.a;
							n2 = faceVertexNormals.b;
							n3 = faceVertexNormals.c;
							n4 = faceVertexNormals.d;

						} else {

							n1 = morphNormals[ vk ].faceNormals[ chf ];
							n2 = n1;
							n3 = n1;
							n4 = n1;

						}

						nka = morphNormalsArrays[ vk ];

						nka[ offset_morphTarget ] 	  = n1.x;
						nka[ offset_morphTarget + 1 ] = n1.y;
						nka[ offset_morphTarget + 2 ] = n1.z;

						nka[ offset_morphTarget + 3 ] = n2.x;
						nka[ offset_morphTarget + 4 ] = n2.y;
						nka[ offset_morphTarget + 5 ] = n2.z;

						nka[ offset_morphTarget + 6 ] = n3.x;
						nka[ offset_morphTarget + 7 ] = n3.y;
						nka[ offset_morphTarget + 8 ] = n3.z;

						nka[ offset_morphTarget + 9 ]  = n4.x;
						nka[ offset_morphTarget + 10 ] = n4.y;
						nka[ offset_morphTarget + 11 ] = n4.z;

					}

					//

1692
					offset_morphTarget += 12;
A
alteredq 已提交
1693

1694
				}
A
alteredq 已提交
1695 1696 1697

				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ vk ] );
				_gl.bufferData( _gl.ARRAY_BUFFER, morphTargetsArrays[ vk ], hint );
A
alteredq 已提交
1698

A
alteredq 已提交
1699 1700 1701 1702 1703 1704 1705
				if ( material.morphNormals ) {

					_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ vk ] );
					_gl.bufferData( _gl.ARRAY_BUFFER, morphNormalsArrays[ vk ], hint );

				}

1706
			}
1707

A
alteredq 已提交
1708 1709 1710 1711 1712 1713 1714
		}

		if ( obj_skinWeights.length ) {

			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {

				face = obj_faces[ chunk_faces3[ f ]	];
1715

1716
				// weights
A
alteredq 已提交
1717

1718 1719 1720
				sw1 = obj_skinWeights[ face.a ];
				sw2 = obj_skinWeights[ face.b ];
				sw3 = obj_skinWeights[ face.c ];
A
alteredq 已提交
1721

1722 1723 1724 1725
				skinWeightArray[ offset_skin ]     = sw1.x;
				skinWeightArray[ offset_skin + 1 ] = sw1.y;
				skinWeightArray[ offset_skin + 2 ] = sw1.z;
				skinWeightArray[ offset_skin + 3 ] = sw1.w;
A
alteredq 已提交
1726

1727 1728 1729 1730
				skinWeightArray[ offset_skin + 4 ] = sw2.x;
				skinWeightArray[ offset_skin + 5 ] = sw2.y;
				skinWeightArray[ offset_skin + 6 ] = sw2.z;
				skinWeightArray[ offset_skin + 7 ] = sw2.w;
1731

1732 1733 1734 1735
				skinWeightArray[ offset_skin + 8 ]  = sw3.x;
				skinWeightArray[ offset_skin + 9 ]  = sw3.y;
				skinWeightArray[ offset_skin + 10 ] = sw3.z;
				skinWeightArray[ offset_skin + 11 ] = sw3.w;
A
alteredq 已提交
1736

1737
				// indices
A
alteredq 已提交
1738

1739 1740 1741
				si1 = obj_skinIndices[ face.a ];
				si2 = obj_skinIndices[ face.b ];
				si3 = obj_skinIndices[ face.c ];
A
alteredq 已提交
1742

1743 1744 1745 1746
				skinIndexArray[ offset_skin ]     = si1.x;
				skinIndexArray[ offset_skin + 1 ] = si1.y;
				skinIndexArray[ offset_skin + 2 ] = si1.z;
				skinIndexArray[ offset_skin + 3 ] = si1.w;
A
alteredq 已提交
1747

1748 1749 1750 1751
				skinIndexArray[ offset_skin + 4 ] = si2.x;
				skinIndexArray[ offset_skin + 5 ] = si2.y;
				skinIndexArray[ offset_skin + 6 ] = si2.z;
				skinIndexArray[ offset_skin + 7 ] = si2.w;
1752

1753 1754 1755 1756
				skinIndexArray[ offset_skin + 8 ]  = si3.x;
				skinIndexArray[ offset_skin + 9 ]  = si3.y;
				skinIndexArray[ offset_skin + 10 ] = si3.z;
				skinIndexArray[ offset_skin + 11 ] = si3.w;
A
alteredq 已提交
1757

1758
				// vertices A
A
alteredq 已提交
1759

1760 1761 1762
				sa1 = obj_skinVerticesA[ face.a ];
				sa2 = obj_skinVerticesA[ face.b ];
				sa3 = obj_skinVerticesA[ face.c ];
A
alteredq 已提交
1763

1764 1765 1766 1767
				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
A
alteredq 已提交
1768

1769 1770 1771 1772
				skinVertexAArray[ offset_skin + 4 ] = sa2.x;
				skinVertexAArray[ offset_skin + 5 ] = sa2.y;
				skinVertexAArray[ offset_skin + 6 ] = sa2.z;
				skinVertexAArray[ offset_skin + 7 ] = 1;
1773

1774 1775 1776 1777
				skinVertexAArray[ offset_skin + 8 ]  = sa3.x;
				skinVertexAArray[ offset_skin + 9 ]  = sa3.y;
				skinVertexAArray[ offset_skin + 10 ] = sa3.z;
				skinVertexAArray[ offset_skin + 11 ] = 1;
A
alteredq 已提交
1778

1779
				// vertices B
A
alteredq 已提交
1780

1781 1782 1783
				sb1 = obj_skinVerticesB[ face.a ];
				sb2 = obj_skinVerticesB[ face.b ];
				sb3 = obj_skinVerticesB[ face.c ];
A
alteredq 已提交
1784

1785 1786 1787 1788
				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
A
alteredq 已提交
1789

1790 1791 1792 1793
				skinVertexBArray[ offset_skin + 4 ] = sb2.x;
				skinVertexBArray[ offset_skin + 5 ] = sb2.y;
				skinVertexBArray[ offset_skin + 6 ] = sb2.z;
				skinVertexBArray[ offset_skin + 7 ] = 1;
1794

1795 1796 1797 1798
				skinVertexBArray[ offset_skin + 8 ]  = sb3.x;
				skinVertexBArray[ offset_skin + 9 ]  = sb3.y;
				skinVertexBArray[ offset_skin + 10 ] = sb3.z;
				skinVertexBArray[ offset_skin + 11 ] = 1;
1799

1800
				offset_skin += 12;
1801

1802
			}
1803

A
alteredq 已提交
1804
			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
1805

A
alteredq 已提交
1806
				face = obj_faces[ chunk_faces4[ f ] ];
1807

A
alteredq 已提交
1808
				// weights
1809

A
alteredq 已提交
1810 1811 1812 1813
				sw1 = obj_skinWeights[ face.a ];
				sw2 = obj_skinWeights[ face.b ];
				sw3 = obj_skinWeights[ face.c ];
				sw4 = obj_skinWeights[ face.d ];
1814

A
alteredq 已提交
1815 1816 1817 1818
				skinWeightArray[ offset_skin ]     = sw1.x;
				skinWeightArray[ offset_skin + 1 ] = sw1.y;
				skinWeightArray[ offset_skin + 2 ] = sw1.z;
				skinWeightArray[ offset_skin + 3 ] = sw1.w;
1819

A
alteredq 已提交
1820 1821 1822 1823
				skinWeightArray[ offset_skin + 4 ] = sw2.x;
				skinWeightArray[ offset_skin + 5 ] = sw2.y;
				skinWeightArray[ offset_skin + 6 ] = sw2.z;
				skinWeightArray[ offset_skin + 7 ] = sw2.w;
1824

A
alteredq 已提交
1825 1826 1827 1828
				skinWeightArray[ offset_skin + 8 ]  = sw3.x;
				skinWeightArray[ offset_skin + 9 ]  = sw3.y;
				skinWeightArray[ offset_skin + 10 ] = sw3.z;
				skinWeightArray[ offset_skin + 11 ] = sw3.w;
1829

A
alteredq 已提交
1830 1831 1832 1833
				skinWeightArray[ offset_skin + 12 ] = sw4.x;
				skinWeightArray[ offset_skin + 13 ] = sw4.y;
				skinWeightArray[ offset_skin + 14 ] = sw4.z;
				skinWeightArray[ offset_skin + 15 ] = sw4.w;
1834

A
alteredq 已提交
1835
				// indices
1836

A
alteredq 已提交
1837 1838 1839 1840
				si1 = obj_skinIndices[ face.a ];
				si2 = obj_skinIndices[ face.b ];
				si3 = obj_skinIndices[ face.c ];
				si4 = obj_skinIndices[ face.d ];
1841

A
alteredq 已提交
1842 1843 1844 1845
				skinIndexArray[ offset_skin ]     = si1.x;
				skinIndexArray[ offset_skin + 1 ] = si1.y;
				skinIndexArray[ offset_skin + 2 ] = si1.z;
				skinIndexArray[ offset_skin + 3 ] = si1.w;
1846

A
alteredq 已提交
1847 1848 1849 1850
				skinIndexArray[ offset_skin + 4 ] = si2.x;
				skinIndexArray[ offset_skin + 5 ] = si2.y;
				skinIndexArray[ offset_skin + 6 ] = si2.z;
				skinIndexArray[ offset_skin + 7 ] = si2.w;
M
Mr.doob 已提交
1851

A
alteredq 已提交
1852 1853 1854 1855
				skinIndexArray[ offset_skin + 8 ]  = si3.x;
				skinIndexArray[ offset_skin + 9 ]  = si3.y;
				skinIndexArray[ offset_skin + 10 ] = si3.z;
				skinIndexArray[ offset_skin + 11 ] = si3.w;
M
Mr.doob 已提交
1856

A
alteredq 已提交
1857 1858 1859 1860
				skinIndexArray[ offset_skin + 12 ] = si4.x;
				skinIndexArray[ offset_skin + 13 ] = si4.y;
				skinIndexArray[ offset_skin + 14 ] = si4.z;
				skinIndexArray[ offset_skin + 15 ] = si4.w;
M
Mr.doob 已提交
1861

A
alteredq 已提交
1862
				// vertices A
M
Mr.doob 已提交
1863

A
alteredq 已提交
1864 1865 1866 1867
				sa1 = obj_skinVerticesA[ face.a ];
				sa2 = obj_skinVerticesA[ face.b ];
				sa3 = obj_skinVerticesA[ face.c ];
				sa4 = obj_skinVerticesA[ face.d ];
1868

A
alteredq 已提交
1869 1870 1871 1872
				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
M
Mr.doob 已提交
1873

A
alteredq 已提交
1874 1875 1876 1877
				skinVertexAArray[ offset_skin + 4 ] = sa2.x;
				skinVertexAArray[ offset_skin + 5 ] = sa2.y;
				skinVertexAArray[ offset_skin + 6 ] = sa2.z;
				skinVertexAArray[ offset_skin + 7 ] = 1;
1878

A
alteredq 已提交
1879 1880 1881 1882
				skinVertexAArray[ offset_skin + 8 ]  = sa3.x;
				skinVertexAArray[ offset_skin + 9 ]  = sa3.y;
				skinVertexAArray[ offset_skin + 10 ] = sa3.z;
				skinVertexAArray[ offset_skin + 11 ] = 1;
1883

A
alteredq 已提交
1884 1885 1886 1887
				skinVertexAArray[ offset_skin + 12 ] = sa4.x;
				skinVertexAArray[ offset_skin + 13 ] = sa4.y;
				skinVertexAArray[ offset_skin + 14 ] = sa4.z;
				skinVertexAArray[ offset_skin + 15 ] = 1;
M
Mr.doob 已提交
1888

A
alteredq 已提交
1889
				// vertices B
M
Mr.doob 已提交
1890

A
alteredq 已提交
1891 1892 1893 1894
				sb1 = obj_skinVerticesB[ face.a ];
				sb2 = obj_skinVerticesB[ face.b ];
				sb3 = obj_skinVerticesB[ face.c ];
				sb4 = obj_skinVerticesB[ face.d ];
M
Mr.doob 已提交
1895

A
alteredq 已提交
1896 1897 1898 1899
				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
M
Mr.doob 已提交
1900

A
alteredq 已提交
1901 1902 1903 1904
				skinVertexBArray[ offset_skin + 4 ] = sb2.x;
				skinVertexBArray[ offset_skin + 5 ] = sb2.y;
				skinVertexBArray[ offset_skin + 6 ] = sb2.z;
				skinVertexBArray[ offset_skin + 7 ] = 1;
1905

A
alteredq 已提交
1906 1907 1908 1909
				skinVertexBArray[ offset_skin + 8 ]  = sb3.x;
				skinVertexBArray[ offset_skin + 9 ]  = sb3.y;
				skinVertexBArray[ offset_skin + 10 ] = sb3.z;
				skinVertexBArray[ offset_skin + 11 ] = 1;
1910

A
alteredq 已提交
1911 1912 1913 1914
				skinVertexBArray[ offset_skin + 12 ] = sb4.x;
				skinVertexBArray[ offset_skin + 13 ] = sb4.y;
				skinVertexBArray[ offset_skin + 14 ] = sb4.z;
				skinVertexBArray[ offset_skin + 15 ] = 1;
1915

A
alteredq 已提交
1916
				offset_skin += 16;
M
Mr.doob 已提交
1917

A
alteredq 已提交
1918
			}
M
Mr.doob 已提交
1919

A
alteredq 已提交
1920
			if ( offset_skin > 0 ) {
M
Mr.doob 已提交
1921

A
alteredq 已提交
1922 1923
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexABuffer );
				_gl.bufferData( _gl.ARRAY_BUFFER, skinVertexAArray, hint );
M
Mr.doob 已提交
1924

A
alteredq 已提交
1925 1926 1927 1928 1929 1930 1931 1932
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexBBuffer );
				_gl.bufferData( _gl.ARRAY_BUFFER, skinVertexBArray, hint );

				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
				_gl.bufferData( _gl.ARRAY_BUFFER, skinIndexArray, hint );

				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
				_gl.bufferData( _gl.ARRAY_BUFFER, skinWeightArray, hint );
1933

1934
			}
1935

A
alteredq 已提交
1936
		}
M
Mr.doob 已提交
1937

A
alteredq 已提交
1938
		if ( dirtyColors && vertexColorType ) {
M
Mr.doob 已提交
1939

A
alteredq 已提交
1940
			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
M
Mr.doob 已提交
1941

A
alteredq 已提交
1942
				face = obj_faces[ chunk_faces3[ f ]	];
M
Mr.doob 已提交
1943

A
alteredq 已提交
1944 1945
				vertexColors = face.vertexColors;
				faceColor = face.color;
1946

A
alteredq 已提交
1947
				if ( vertexColors.length === 3 && vertexColorType === THREE.VertexColors ) {
1948

A
alteredq 已提交
1949 1950 1951
					c1 = vertexColors[ 0 ];
					c2 = vertexColors[ 1 ];
					c3 = vertexColors[ 2 ];
1952

A
alteredq 已提交
1953
				} else {
1954

A
alteredq 已提交
1955 1956 1957
					c1 = faceColor;
					c2 = faceColor;
					c3 = faceColor;
1958

A
alteredq 已提交
1959
				}
1960

A
alteredq 已提交
1961 1962 1963
				colorArray[ offset_color ]     = c1.r;
				colorArray[ offset_color + 1 ] = c1.g;
				colorArray[ offset_color + 2 ] = c1.b;
1964

A
alteredq 已提交
1965 1966 1967
				colorArray[ offset_color + 3 ] = c2.r;
				colorArray[ offset_color + 4 ] = c2.g;
				colorArray[ offset_color + 5 ] = c2.b;
1968

A
alteredq 已提交
1969 1970 1971
				colorArray[ offset_color + 6 ] = c3.r;
				colorArray[ offset_color + 7 ] = c3.g;
				colorArray[ offset_color + 8 ] = c3.b;
1972

A
alteredq 已提交
1973
				offset_color += 9;
M
Mr.doob 已提交
1974

A
alteredq 已提交
1975
			}
M
Mr.doob 已提交
1976

A
alteredq 已提交
1977
			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
M
Mr.doob 已提交
1978

A
alteredq 已提交
1979
				face = obj_faces[ chunk_faces4[ f ] ];
M
Mr.doob 已提交
1980

A
alteredq 已提交
1981 1982
				vertexColors = face.vertexColors;
				faceColor = face.color;
M
Mr.doob 已提交
1983

A
alteredq 已提交
1984
				if ( vertexColors.length === 4 && vertexColorType === THREE.VertexColors ) {
M
Mr.doob 已提交
1985

A
alteredq 已提交
1986 1987 1988 1989
					c1 = vertexColors[ 0 ];
					c2 = vertexColors[ 1 ];
					c3 = vertexColors[ 2 ];
					c4 = vertexColors[ 3 ];
1990

A
alteredq 已提交
1991
				} else {
M
Mr.doob 已提交
1992

A
alteredq 已提交
1993 1994 1995 1996
					c1 = faceColor;
					c2 = faceColor;
					c3 = faceColor;
					c4 = faceColor;
M
Mr.doob 已提交
1997

A
alteredq 已提交
1998
				}
1999

A
alteredq 已提交
2000 2001 2002
				colorArray[ offset_color ]     = c1.r;
				colorArray[ offset_color + 1 ] = c1.g;
				colorArray[ offset_color + 2 ] = c1.b;
2003

A
alteredq 已提交
2004 2005 2006
				colorArray[ offset_color + 3 ] = c2.r;
				colorArray[ offset_color + 4 ] = c2.g;
				colorArray[ offset_color + 5 ] = c2.b;
M
Mr.doob 已提交
2007

A
alteredq 已提交
2008 2009 2010
				colorArray[ offset_color + 6 ] = c3.r;
				colorArray[ offset_color + 7 ] = c3.g;
				colorArray[ offset_color + 8 ] = c3.b;
M
Mr.doob 已提交
2011

A
alteredq 已提交
2012 2013 2014
				colorArray[ offset_color + 9 ]  = c4.r;
				colorArray[ offset_color + 10 ] = c4.g;
				colorArray[ offset_color + 11 ] = c4.b;
M
Mr.doob 已提交
2015

A
alteredq 已提交
2016
				offset_color += 12;
2017

2018
			}
2019

A
alteredq 已提交
2020
			if ( offset_color > 0 ) {
M
Mr.doob 已提交
2021

A
alteredq 已提交
2022 2023
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
				_gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
M
Mr.doob 已提交
2024

2025
			}
2026

A
alteredq 已提交
2027
		}
M
Mr.doob 已提交
2028

A
alteredq 已提交
2029
		if ( dirtyTangents && geometry.hasTangents ) {
M
Mr.doob 已提交
2030

A
alteredq 已提交
2031
			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2032

A
alteredq 已提交
2033
				face = obj_faces[ chunk_faces3[ f ]	];
2034

A
alteredq 已提交
2035
				vertexTangents = face.vertexTangents;
M
Mr.doob 已提交
2036

A
alteredq 已提交
2037 2038 2039
				t1 = vertexTangents[ 0 ];
				t2 = vertexTangents[ 1 ];
				t3 = vertexTangents[ 2 ];
2040

A
alteredq 已提交
2041 2042 2043 2044
				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 已提交
2045

A
alteredq 已提交
2046 2047 2048 2049
				tangentArray[ offset_tangent + 4 ] = t2.x;
				tangentArray[ offset_tangent + 5 ] = t2.y;
				tangentArray[ offset_tangent + 6 ] = t2.z;
				tangentArray[ offset_tangent + 7 ] = t2.w;
2050

A
alteredq 已提交
2051 2052 2053 2054
				tangentArray[ offset_tangent + 8 ]  = t3.x;
				tangentArray[ offset_tangent + 9 ]  = t3.y;
				tangentArray[ offset_tangent + 10 ] = t3.z;
				tangentArray[ offset_tangent + 11 ] = t3.w;
2055

A
alteredq 已提交
2056
				offset_tangent += 12;
2057

2058
			}
2059

A
alteredq 已提交
2060
			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2061

A
alteredq 已提交
2062
				face = obj_faces[ chunk_faces4[ f ] ];
2063

A
alteredq 已提交
2064
				vertexTangents = face.vertexTangents;
2065

A
alteredq 已提交
2066 2067 2068 2069
				t1 = vertexTangents[ 0 ];
				t2 = vertexTangents[ 1 ];
				t3 = vertexTangents[ 2 ];
				t4 = vertexTangents[ 3 ];
2070

A
alteredq 已提交
2071 2072 2073 2074
				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 已提交
2075

A
alteredq 已提交
2076 2077 2078 2079
				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 已提交
2080

A
alteredq 已提交
2081 2082 2083 2084
				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 已提交
2085

A
alteredq 已提交
2086 2087 2088 2089
				tangentArray[ offset_tangent + 12 ] = t4.x;
				tangentArray[ offset_tangent + 13 ] = t4.y;
				tangentArray[ offset_tangent + 14 ] = t4.z;
				tangentArray[ offset_tangent + 15 ] = t4.w;
2090

A
alteredq 已提交
2091
				offset_tangent += 16;
2092

A
alteredq 已提交
2093
			}
2094

A
alteredq 已提交
2095 2096
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, tangentArray, hint );
2097

A
alteredq 已提交
2098
		}
2099

A
alteredq 已提交
2100
		if ( dirtyNormals && normalType ) {
2101

A
alteredq 已提交
2102
			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2103

A
alteredq 已提交
2104
				face = obj_faces[ chunk_faces3[ f ]	];
2105

A
alteredq 已提交
2106 2107
				vertexNormals = face.vertexNormals;
				faceNormal = face.normal;
2108

A
alteredq 已提交
2109
				if ( vertexNormals.length === 3 && needsSmoothNormals ) {
2110

A
alteredq 已提交
2111
					for ( i = 0; i < 3; i ++ ) {
M
Mr.doob 已提交
2112

A
alteredq 已提交
2113
						vn = vertexNormals[ i ];
M
Mr.doob 已提交
2114

A
alteredq 已提交
2115 2116 2117
						normalArray[ offset_normal ]     = vn.x;
						normalArray[ offset_normal + 1 ] = vn.y;
						normalArray[ offset_normal + 2 ] = vn.z;
2118

A
alteredq 已提交
2119
						offset_normal += 3;
2120

A
alteredq 已提交
2121
					}
2122

A
alteredq 已提交
2123
				} else {
M
Mr.doob 已提交
2124

A
alteredq 已提交
2125
					for ( i = 0; i < 3; i ++ ) {
M
Mr.doob 已提交
2126

A
alteredq 已提交
2127 2128 2129
						normalArray[ offset_normal ]     = faceNormal.x;
						normalArray[ offset_normal + 1 ] = faceNormal.y;
						normalArray[ offset_normal + 2 ] = faceNormal.z;
2130

A
alteredq 已提交
2131
						offset_normal += 3;
M
Mr.doob 已提交
2132

A
alteredq 已提交
2133
					}
2134

A
alteredq 已提交
2135
				}
2136

A
alteredq 已提交
2137
			}
2138

A
alteredq 已提交
2139
			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2140

A
alteredq 已提交
2141
				face = obj_faces[ chunk_faces4[ f ] ];
2142

A
alteredq 已提交
2143 2144
				vertexNormals = face.vertexNormals;
				faceNormal = face.normal;
2145

A
alteredq 已提交
2146
				if ( vertexNormals.length === 4 && needsSmoothNormals ) {
2147

A
alteredq 已提交
2148
					for ( i = 0; i < 4; i ++ ) {
2149

A
alteredq 已提交
2150
						vn = vertexNormals[ i ];
2151

A
alteredq 已提交
2152 2153 2154
						normalArray[ offset_normal ]     = vn.x;
						normalArray[ offset_normal + 1 ] = vn.y;
						normalArray[ offset_normal + 2 ] = vn.z;
2155

A
alteredq 已提交
2156
						offset_normal += 3;
2157

A
alteredq 已提交
2158
					}
M
Mr.doob 已提交
2159

A
alteredq 已提交
2160
				} else {
2161

A
alteredq 已提交
2162
					for ( i = 0; i < 4; i ++ ) {
2163

A
alteredq 已提交
2164 2165 2166
						normalArray[ offset_normal ]     = faceNormal.x;
						normalArray[ offset_normal + 1 ] = faceNormal.y;
						normalArray[ offset_normal + 2 ] = faceNormal.z;
M
Mr.doob 已提交
2167

A
alteredq 已提交
2168
						offset_normal += 3;
M
Mr.doob 已提交
2169

A
alteredq 已提交
2170
					}
2171

A
alteredq 已提交
2172
				}
2173

A
alteredq 已提交
2174
			}
M
Mr.doob 已提交
2175

A
alteredq 已提交
2176 2177
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, normalArray, hint );
M
Mr.doob 已提交
2178

A
alteredq 已提交
2179
		}
M
Mr.doob 已提交
2180

A
alteredq 已提交
2181
		if ( dirtyUvs && obj_uvs && uvType ) {
2182

A
alteredq 已提交
2183
			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2184

A
alteredq 已提交
2185
				fi = chunk_faces3[ f ];
2186

A
alteredq 已提交
2187 2188
				face = obj_faces[ fi ];
				uv = obj_uvs[ fi ];
2189

A
alteredq 已提交
2190
				if ( uv === undefined ) continue;
2191

A
alteredq 已提交
2192
				for ( i = 0; i < 3; i ++ ) {
2193

A
alteredq 已提交
2194
					uvi = uv[ i ];
2195

A
alteredq 已提交
2196 2197
					uvArray[ offset_uv ]     = uvi.u;
					uvArray[ offset_uv + 1 ] = uvi.v;
M
Mr.doob 已提交
2198

A
alteredq 已提交
2199
					offset_uv += 2;
M
Mr.doob 已提交
2200

A
alteredq 已提交
2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221
				}

			}

			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {

				fi = chunk_faces4[ f ];

				face = obj_faces[ fi ];
				uv = obj_uvs[ fi ];

				if ( uv === undefined ) continue;

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

					uvi = uv[ i ];

					uvArray[ offset_uv ]     = uvi.u;
					uvArray[ offset_uv + 1 ] = uvi.v;

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

2223 2224
				}

2225
			}
2226

A
alteredq 已提交
2227
			if ( offset_uv > 0 ) {
2228

A
alteredq 已提交
2229 2230
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
				_gl.bufferData( _gl.ARRAY_BUFFER, uvArray, hint );
2231

A
alteredq 已提交
2232
			}
2233

A
alteredq 已提交
2234
		}
2235

A
alteredq 已提交
2236
		if ( dirtyUvs && obj_uvs2 && uvType ) {
2237

A
alteredq 已提交
2238
			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2239

A
alteredq 已提交
2240
				fi = chunk_faces3[ f ];
2241

A
alteredq 已提交
2242 2243
				face = obj_faces[ fi ];
				uv2 = obj_uvs2[ fi ];
2244

A
alteredq 已提交
2245 2246 2247 2248 2249 2250 2251 2252 2253 2254
				if ( uv2 === undefined ) continue;

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

					uv2i = uv2[ i ];

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

					offset_uv2 += 2;
2255

2256 2257
				}

A
alteredq 已提交
2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278
			}

			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {

				fi = chunk_faces4[ f ];

				face = obj_faces[ fi ];
				uv2 = obj_uvs2[ fi ];

				if ( uv2 === undefined ) continue;

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

					uv2i = uv2[ i ];

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

					offset_uv2 += 2;

				}
2279

2280
			}
2281

A
alteredq 已提交
2282
			if ( offset_uv2 > 0 ) {
2283

A
alteredq 已提交
2284 2285
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
				_gl.bufferData( _gl.ARRAY_BUFFER, uv2Array, hint );
2286

A
alteredq 已提交
2287
			}
2288

A
alteredq 已提交
2289
		}
2290

A
alteredq 已提交
2291
		if ( dirtyElements ) {
2292

A
alteredq 已提交
2293
			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2294

A
alteredq 已提交
2295
				face = obj_faces[ chunk_faces3[ f ]	];
2296

A
alteredq 已提交
2297 2298 2299
				faceArray[ offset_face ] 	 = vertexIndex;
				faceArray[ offset_face + 1 ] = vertexIndex + 1;
				faceArray[ offset_face + 2 ] = vertexIndex + 2;
2300

A
alteredq 已提交
2301
				offset_face += 3;
2302

A
alteredq 已提交
2303 2304
				lineArray[ offset_line ]     = vertexIndex;
				lineArray[ offset_line + 1 ] = vertexIndex + 1;
2305

A
alteredq 已提交
2306 2307
				lineArray[ offset_line + 2 ] = vertexIndex;
				lineArray[ offset_line + 3 ] = vertexIndex + 2;
2308

A
alteredq 已提交
2309 2310
				lineArray[ offset_line + 4 ] = vertexIndex + 1;
				lineArray[ offset_line + 5 ] = vertexIndex + 2;
2311

A
alteredq 已提交
2312
				offset_line += 6;
2313

A
alteredq 已提交
2314
				vertexIndex += 3;
2315

A
alteredq 已提交
2316
			}
2317

A
alteredq 已提交
2318
			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2319

A
alteredq 已提交
2320
				face = obj_faces[ chunk_faces4[ f ] ];
2321

A
alteredq 已提交
2322 2323 2324
				faceArray[ offset_face ]     = vertexIndex;
				faceArray[ offset_face + 1 ] = vertexIndex + 1;
				faceArray[ offset_face + 2 ] = vertexIndex + 3;
2325

A
alteredq 已提交
2326 2327 2328
				faceArray[ offset_face + 3 ] = vertexIndex + 1;
				faceArray[ offset_face + 4 ] = vertexIndex + 2;
				faceArray[ offset_face + 5 ] = vertexIndex + 3;
2329

A
alteredq 已提交
2330
				offset_face += 6;
2331

A
alteredq 已提交
2332 2333
				lineArray[ offset_line ]     = vertexIndex;
				lineArray[ offset_line + 1 ] = vertexIndex + 1;
2334

A
alteredq 已提交
2335 2336
				lineArray[ offset_line + 2 ] = vertexIndex;
				lineArray[ offset_line + 3 ] = vertexIndex + 3;
2337

A
alteredq 已提交
2338 2339
				lineArray[ offset_line + 4 ] = vertexIndex + 1;
				lineArray[ offset_line + 5 ] = vertexIndex + 2;
2340

A
alteredq 已提交
2341 2342
				lineArray[ offset_line + 6 ] = vertexIndex + 2;
				lineArray[ offset_line + 7 ] = vertexIndex + 3;
2343

A
alteredq 已提交
2344
				offset_line += 8;
2345

A
alteredq 已提交
2346
				vertexIndex += 4;
2347

2348
			}
2349

A
alteredq 已提交
2350 2351
			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
			_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, faceArray, hint );
2352

A
alteredq 已提交
2353 2354
			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
			_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, lineArray, hint );
2355

A
alteredq 已提交
2356
		}
2357

A
alteredq 已提交
2358
		if ( customAttributes ) {
2359

A
alteredq 已提交
2360
			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
2361

2362
				customAttribute = customAttributes[ i ];
2363

2364
				if ( ! customAttribute.__original.needsUpdate ) continue;
2365

2366 2367
				offset_custom = 0;
				offset_customSrc = 0;
2368

2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401
				if ( customAttribute.size === 1 ) {

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

						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {

							face = obj_faces[ chunk_faces3[ f ]	];

							customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
							customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
							customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];

							offset_custom += 3;

						}

						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {

							face = obj_faces[ chunk_faces4[ f ] ];

							customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
							customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
							customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
							customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ face.d ];

							offset_custom += 4;

						}

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

						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {

2402
							value = customAttribute.value[ chunk_faces3[ f ] ];
2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413

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

							offset_custom += 3;

						}

						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {

2414
							value = customAttribute.value[ chunk_faces4[ f ] ];
2415 2416 2417 2418 2419 2420 2421 2422 2423

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

							offset_custom += 4;

						}
2424

2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443
					}

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

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

						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {

							face = obj_faces[ chunk_faces3[ f ]	];

							v1 = customAttribute.value[ face.a ];
							v2 = customAttribute.value[ face.b ];
							v3 = customAttribute.value[ face.c ];

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

							customAttribute.array[ offset_custom + 2 ] = v2.x;
							customAttribute.array[ offset_custom + 3 ] = v2.y;
A
alteredq 已提交
2444

2445 2446
							customAttribute.array[ offset_custom + 4 ] = v3.x;
							customAttribute.array[ offset_custom + 5 ] = v3.y;
A
alteredq 已提交
2447

2448
							offset_custom += 6;
A
alteredq 已提交
2449

2450
						}
A
alteredq 已提交
2451

2452
						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
A
alteredq 已提交
2453

2454
							face = obj_faces[ chunk_faces4[ f ] ];
A
alteredq 已提交
2455

2456 2457 2458 2459
							v1 = customAttribute.value[ face.a ];
							v2 = customAttribute.value[ face.b ];
							v3 = customAttribute.value[ face.c ];
							v4 = customAttribute.value[ face.d ];
A
alteredq 已提交
2460

2461 2462
							customAttribute.array[ offset_custom ] 	   = v1.x;
							customAttribute.array[ offset_custom + 1 ] = v1.y;
A
alteredq 已提交
2463

2464 2465
							customAttribute.array[ offset_custom + 2 ] = v2.x;
							customAttribute.array[ offset_custom + 3 ] = v2.y;
A
alteredq 已提交
2466

2467 2468
							customAttribute.array[ offset_custom + 4 ] = v3.x;
							customAttribute.array[ offset_custom + 5 ] = v3.y;
A
alteredq 已提交
2469

2470 2471
							customAttribute.array[ offset_custom + 6 ] = v4.x;
							customAttribute.array[ offset_custom + 7 ] = v4.y;
A
alteredq 已提交
2472

2473
							offset_custom += 8;
A
alteredq 已提交
2474

2475
						}
A
alteredq 已提交
2476

2477
					} else if ( customAttribute.boundTo === "faces" ) {
A
alteredq 已提交
2478

2479
						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
A
alteredq 已提交
2480

2481
							value = customAttribute.value[ chunk_faces3[ f ] ];
A
alteredq 已提交
2482

2483 2484 2485
							v1 = value;
							v2 = value;
							v3 = value;
A
alteredq 已提交
2486

2487 2488
							customAttribute.array[ offset_custom ] 	   = v1.x;
							customAttribute.array[ offset_custom + 1 ] = v1.y;
A
alteredq 已提交
2489

2490 2491
							customAttribute.array[ offset_custom + 2 ] = v2.x;
							customAttribute.array[ offset_custom + 3 ] = v2.y;
A
alteredq 已提交
2492

2493 2494
							customAttribute.array[ offset_custom + 4 ] = v3.x;
							customAttribute.array[ offset_custom + 5 ] = v3.y;
A
alteredq 已提交
2495

2496
							offset_custom += 6;
A
alteredq 已提交
2497

2498
						}
A
alteredq 已提交
2499

2500
						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
A
alteredq 已提交
2501

2502
							value = customAttribute.value[ chunk_faces4[ f ] ];
A
alteredq 已提交
2503

2504 2505 2506 2507
							v1 = value;
							v2 = value;
							v3 = value;
							v4 = value;
A
alteredq 已提交
2508

2509 2510
							customAttribute.array[ offset_custom ] 	   = v1.x;
							customAttribute.array[ offset_custom + 1 ] = v1.y;
A
alteredq 已提交
2511

2512 2513
							customAttribute.array[ offset_custom + 2 ] = v2.x;
							customAttribute.array[ offset_custom + 3 ] = v2.y;
A
alteredq 已提交
2514

2515 2516
							customAttribute.array[ offset_custom + 4 ] = v3.x;
							customAttribute.array[ offset_custom + 5 ] = v3.y;
A
alteredq 已提交
2517

2518 2519
							customAttribute.array[ offset_custom + 6 ] = v4.x;
							customAttribute.array[ offset_custom + 7 ] = v4.y;
M
Mr.doob 已提交
2520

2521
							offset_custom += 8;
M
Mr.doob 已提交
2522

2523
						}
M
Mr.doob 已提交
2524

M
Mr.doob 已提交
2525
					}
M
Mr.doob 已提交
2526

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

2529
					var pp;
2530

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

2533
						pp = [ "r", "g", "b" ];
M
Mr.doob 已提交
2534

2535
					} else {
M
Mr.doob 已提交
2536

2537
						pp = [ "x", "y", "z" ];
2538

2539
					}
2540

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

2543
						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2544

2545
							face = obj_faces[ chunk_faces3[ f ]	];
2546

2547 2548 2549
							v1 = customAttribute.value[ face.a ];
							v2 = customAttribute.value[ face.b ];
							v3 = customAttribute.value[ face.c ];
2550

2551 2552 2553
							customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
2554

2555 2556 2557
							customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
2558

2559 2560 2561
							customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
M
Mr.doob 已提交
2562

2563
							offset_custom += 9;
M
Mr.doob 已提交
2564

2565
						}
M
Mr.doob 已提交
2566

2567
						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
M
Mr.doob 已提交
2568

2569
							face = obj_faces[ chunk_faces4[ f ] ];
M
Mr.doob 已提交
2570

2571 2572 2573 2574
							v1 = customAttribute.value[ face.a ];
							v2 = customAttribute.value[ face.b ];
							v3 = customAttribute.value[ face.c ];
							v4 = customAttribute.value[ face.d ];
M
Mr.doob 已提交
2575

2576 2577 2578
							customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
M
Mr.doob 已提交
2579

2580 2581 2582
							customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
M
Mr.doob 已提交
2583

2584 2585 2586
							customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
M
Mr.doob 已提交
2587

2588 2589 2590
							customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
M
Mr.doob 已提交
2591

2592
							offset_custom += 12;
M
Mr.doob 已提交
2593

2594
						}
M
Mr.doob 已提交
2595

2596
					} else if ( customAttribute.boundTo === "faces" ) {
M
Mr.doob 已提交
2597

2598
						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2599

2600
							value = customAttribute.value[ chunk_faces3[ f ] ];
2601

2602 2603 2604
							v1 = value;
							v2 = value;
							v3 = value;
M
Mr.doob 已提交
2605

2606 2607 2608
							customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
M
Mr.doob 已提交
2609

2610 2611 2612
							customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
M
Mr.doob 已提交
2613

2614 2615 2616
							customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
M
Mr.doob 已提交
2617

2618
							offset_custom += 9;
M
Mr.doob 已提交
2619

2620
						}
2621

2622
						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
2623

2624
							value = customAttribute.value[ chunk_faces4[ f ] ];
2625

2626 2627 2628 2629
							v1 = value;
							v2 = value;
							v3 = value;
							v4 = value;
2630

2631 2632 2633
							customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
2634

2635 2636 2637
							customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
2638

2639 2640 2641
							customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
2642

2643 2644 2645
							customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
							customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
							customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
2646

2647
							offset_custom += 12;
2648

2649
						}
2650

A
alteredq 已提交
2651
					}
M
Mr.doob 已提交
2652

2653
				} else if ( customAttribute.size === 4 ) {
2654

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

2657
						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
2658

2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720
							face = obj_faces[ chunk_faces3[ f ]	];

							v1 = customAttribute.value[ face.a ];
							v2 = customAttribute.value[ face.b ];
							v3 = customAttribute.value[ face.c ];

							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.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;

							customAttribute.array[ offset_custom + 8  ] = v3.x;
							customAttribute.array[ offset_custom + 9  ] = v3.y;
							customAttribute.array[ offset_custom + 10 ] = v3.z;
							customAttribute.array[ offset_custom + 11 ] = v3.w;

							offset_custom += 12;

						}

						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {

							face = obj_faces[ chunk_faces4[ f ] ];

							v1 = customAttribute.value[ face.a ];
							v2 = customAttribute.value[ face.b ];
							v3 = customAttribute.value[ face.c ];
							v4 = customAttribute.value[ face.d ];

							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.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;

							customAttribute.array[ offset_custom + 8  ] = v3.x;
							customAttribute.array[ offset_custom + 9  ] = v3.y;
							customAttribute.array[ offset_custom + 10 ] = v3.z;
							customAttribute.array[ offset_custom + 11 ] = v3.w;

							customAttribute.array[ offset_custom + 12 ] = v4.x;
							customAttribute.array[ offset_custom + 13 ] = v4.y;
							customAttribute.array[ offset_custom + 14 ] = v4.z;
							customAttribute.array[ offset_custom + 15 ] = v4.w;

							offset_custom += 16;

						}

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

						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {

2721
							value = customAttribute.value[ chunk_faces3[ f ] ];
2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738

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

							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.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;

							customAttribute.array[ offset_custom + 8  ] = v3.x;
							customAttribute.array[ offset_custom + 9  ] = v3.y;
2739 2740
							customAttribute.array[ offset_custom + 10 ] = v3.z;
							customAttribute.array[ offset_custom + 11 ] = v3.w;
A
alteredq 已提交
2741

2742
							offset_custom += 12;
A
alteredq 已提交
2743

2744 2745
						}

2746
						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
A
alteredq 已提交
2747

2748
							value = customAttribute.value[ chunk_faces4[ f ] ];
A
alteredq 已提交
2749

2750 2751 2752 2753
							v1 = value;
							v2 = value;
							v3 = value;
							v4 = value;
A
alteredq 已提交
2754

2755 2756 2757 2758
							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;
2759

2760 2761 2762 2763
							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;
2764

2765 2766 2767 2768
							customAttribute.array[ offset_custom + 8  ] = v3.x;
							customAttribute.array[ offset_custom + 9  ] = v3.y;
							customAttribute.array[ offset_custom + 10 ] = v3.z;
							customAttribute.array[ offset_custom + 11 ] = v3.w;
2769

2770 2771 2772 2773
							customAttribute.array[ offset_custom + 12 ] = v4.x;
							customAttribute.array[ offset_custom + 13 ] = v4.y;
							customAttribute.array[ offset_custom + 14 ] = v4.z;
							customAttribute.array[ offset_custom + 15 ] = v4.w;
2774

2775
							offset_custom += 16;
A
alteredq 已提交
2776

2777
						}
A
alteredq 已提交
2778 2779 2780 2781 2782

					}

				}

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

A
alteredq 已提交
2786 2787 2788 2789
			}

		}

2790
		if ( dispose ) {
2791

2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804
			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;
A
alteredq 已提交
2805

2806
		}
A
alteredq 已提交
2807

2808
	};
A
alteredq 已提交
2809

2810
	// Buffer rendering
A
alteredq 已提交
2811

A
alteredq 已提交
2812
	this.renderBufferImmediate = function ( object, program, shading ) {
A
alteredq 已提交
2813

2814 2815
		if ( ! object.__webglVertexBuffer ) object.__webglVertexBuffer = _gl.createBuffer();
		if ( ! object.__webglNormalBuffer ) object.__webglNormalBuffer = _gl.createBuffer();
A
alteredq 已提交
2816

2817
		if ( object.hasPos ) {
A
alteredq 已提交
2818

2819 2820 2821 2822
			_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 );
A
alteredq 已提交
2823 2824 2825

		}

2826
		if ( object.hasNormal ) {
A
alteredq 已提交
2827

2828
			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer );
A
alteredq 已提交
2829

2830
			if ( shading === THREE.FlatShading ) {
2831

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

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

2839
					normalArray = object.normalArray;
2840

2841 2842 2843
					nax  = normalArray[ i ];
					nay  = normalArray[ i + 1 ];
					naz  = normalArray[ i + 2 ];
2844

2845 2846 2847
					nbx  = normalArray[ i + 3 ];
					nby  = normalArray[ i + 4 ];
					nbz  = normalArray[ i + 5 ];
2848

2849 2850 2851
					ncx  = normalArray[ i + 6 ];
					ncy  = normalArray[ i + 7 ];
					ncz  = normalArray[ i + 8 ];
2852

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

2857 2858 2859
					normalArray[ i ] 	 = nx;
					normalArray[ i + 1 ] = ny;
					normalArray[ i + 2 ] = nz;
2860

2861 2862 2863
					normalArray[ i + 3 ] = nx;
					normalArray[ i + 4 ] = ny;
					normalArray[ i + 5 ] = nz;
2864

2865 2866 2867
					normalArray[ i + 6 ] = nx;
					normalArray[ i + 7 ] = ny;
					normalArray[ i + 8 ] = nz;
2868

2869
				}
2870

2871
			}
2872

2873 2874 2875
			_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 );
2876

2877
		}
2878

2879
		_gl.drawArrays( _gl.TRIANGLES, 0, object.count );
2880

2881
		object.count = 0;
2882

2883
	};
2884

2885 2886 2887 2888
	this.renderBufferDirect = function ( camera, lights, fog, material, geometryGroup, object ) {

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

2889
		var program, attributes, linewidth, primitives, a, attribute;
2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911

		program = setProgram( camera, lights, fog, material, object );

		attributes = program.attributes;

		var updateBuffers = false,
			wireframeBit = material.wireframe ? 1 : 0,
			geometryGroupHash = ( geometryGroup.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;

		if ( geometryGroupHash !== _currentGeometryGroupHash ) {

			_currentGeometryGroupHash = geometryGroupHash;
			updateBuffers = true;

		}

		// render mesh

		if ( object instanceof THREE.Mesh ) {

			var offsets = geometryGroup.offsets;

2912
			for ( var i = 0, il = offsets.length; i < il; ++ i ) {
2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976

				if ( updateBuffers ) {

					// vertices

					_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.vertexPositionBuffer );
					_gl.vertexAttribPointer( attributes.position, geometryGroup.vertexPositionBuffer.itemSize, _gl.FLOAT, false, 0, offsets[ i ].index * 4 * 3 );

					// normals

					if ( attributes.normal >= 0 && geometryGroup.vertexNormalBuffer ) {

						_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.vertexNormalBuffer );
						_gl.vertexAttribPointer( attributes.normal, geometryGroup.vertexNormalBuffer.itemSize, _gl.FLOAT, false, 0, offsets[ i ].index * 4 * 3 );

					}

					// uvs

					if ( attributes.uv >= 0 && geometryGroup.vertexUvBuffer ) {

						if ( geometryGroup.vertexUvBuffer ) {

							_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.vertexUvBuffer );
							_gl.vertexAttribPointer(  attributes.uv, geometryGroup.vertexUvBuffer.itemSize, _gl.FLOAT, false, 0, offsets[ i ].index * 4 * 2 );

							_gl.enableVertexAttribArray( attributes.uv );

						} else {

							_gl.disableVertexAttribArray( attributes.uv );

						}

					}

					// colors

					if ( attributes.color >= 0 && geometryGroup.vertexColorBuffer ) {

						_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.vertexColorBuffer );
						_gl.vertexAttribPointer( attributes.color, geometryGroup.vertexColorBuffer.itemSize, _gl.FLOAT, false, 0, offsets[ i ].index * 4 * 4 );


					}

					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.vertexIndexBuffer );

				}

				// render indexed triangles

				_gl.drawElements( _gl.TRIANGLES, offsets[ i ].count, _gl.UNSIGNED_SHORT, offsets[ i ].start * 2 ); // 2 = Uint16

				_this.info.render.calls ++;
				_this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
				_this.info.render.faces += offsets[ i ].count / 3;

			}

		}

	};

A
alteredq 已提交
2977
	this.renderBuffer = function ( camera, lights, fog, material, geometryGroup, object ) {
2978

2979
		if ( material.opacity === 0 ) return;
2980

2981
		var program, attributes, linewidth, primitives, a, attribute, i, il;
2982

2983
		program = setProgram( camera, lights, fog, material, object );
2984

2985
		attributes = program.attributes;
2986

2987 2988 2989
		var updateBuffers = false,
			wireframeBit = material.wireframe ? 1 : 0,
			geometryGroupHash = ( geometryGroup.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
2990

2991
		if ( geometryGroupHash !== _currentGeometryGroupHash ) {
A
alteredq 已提交
2992

2993 2994
			_currentGeometryGroupHash = geometryGroupHash;
			updateBuffers = true;
2995

2996
		}
2997

2998
		// vertices
2999

3000
		if ( !material.morphTargets && attributes.position >= 0 ) {
3001

3002
			if ( updateBuffers ) {
3003

3004 3005
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
				_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
3006

3007
			}
3008

3009
		} else {
3010

3011
			if ( object.morphTargetBase ) {
3012

3013
				setupMorphTargets( material, geometryGroup, object );
3014

3015
			}
3016

3017
		}
3018

3019

3020
		if ( updateBuffers ) {
3021

3022
			// custom attributes
3023

3024
			// Use the per-geometryGroup custom attribute arrays which are setup in initMeshBuffers
3025

3026
			if ( geometryGroup.__webglCustomAttributesList ) {
3027

3028
				for ( i = 0, il = geometryGroup.__webglCustomAttributesList.length; i < il; i ++ ) {
3029

3030
					attribute = geometryGroup.__webglCustomAttributesList[ i ];
3031

3032
					if( attributes[ attribute.buffer.belongsToAttribute ] >= 0 ) {
3033

3034 3035
						_gl.bindBuffer( _gl.ARRAY_BUFFER, attribute.buffer );
						_gl.vertexAttribPointer( attributes[ attribute.buffer.belongsToAttribute ], attribute.size, _gl.FLOAT, false, 0, 0 );
3036

3037
					}
3038

3039
				}
3040

3041
			}
3042 3043


3044
			// colors
3045

3046
			if ( attributes.color >= 0 ) {
3047

3048 3049
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
				_gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
3050

3051
			}
3052

3053
			// normals
3054

3055
			if ( attributes.normal >= 0 ) {
3056

3057 3058
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
				_gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
3059

3060
			}
3061

3062
			// tangents
3063

3064
			if ( attributes.tangent >= 0 ) {
3065

3066 3067
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
				_gl.vertexAttribPointer( attributes.tangent, 4, _gl.FLOAT, false, 0, 0 );
3068

3069
			}
3070

3071
			// uvs
3072

3073
			if ( attributes.uv >= 0 ) {
3074

3075
				if ( geometryGroup.__webglUVBuffer ) {
3076

3077 3078
					_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
					_gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
3079

3080
					_gl.enableVertexAttribArray( attributes.uv );
3081

3082
				} else {
3083

3084
					_gl.disableVertexAttribArray( attributes.uv );
3085 3086 3087 3088 3089

				}

			}

3090
			if ( attributes.uv2 >= 0 ) {
3091

3092
				if ( geometryGroup.__webglUV2Buffer ) {
3093

3094 3095
					_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
					_gl.vertexAttribPointer( attributes.uv2, 2, _gl.FLOAT, false, 0, 0 );
3096

3097
					_gl.enableVertexAttribArray( attributes.uv2 );
3098

3099
				} else {
3100

3101
					_gl.disableVertexAttribArray( attributes.uv2 );
3102 3103

				}
3104 3105

			}
3106

3107 3108 3109
			if ( material.skinning &&
				 attributes.skinVertexA >= 0 && attributes.skinVertexB >= 0 &&
				 attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
A
alteredq 已提交
3110

3111 3112
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexABuffer );
				_gl.vertexAttribPointer( attributes.skinVertexA, 4, _gl.FLOAT, false, 0, 0 );
A
alteredq 已提交
3113

3114 3115
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinVertexBBuffer );
				_gl.vertexAttribPointer( attributes.skinVertexB, 4, _gl.FLOAT, false, 0, 0 );
A
alteredq 已提交
3116

3117 3118
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
				_gl.vertexAttribPointer( attributes.skinIndex, 4, _gl.FLOAT, false, 0, 0 );
A
alteredq 已提交
3119

3120 3121
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
				_gl.vertexAttribPointer( attributes.skinWeight, 4, _gl.FLOAT, false, 0, 0 );
3122

A
alteredq 已提交
3123
			}
3124

3125
		}
3126

3127
		// render mesh
3128

3129
		if ( object instanceof THREE.Mesh ) {
3130

3131
			// wireframe
3132

3133
			if ( material.wireframe ) {
3134

3135
				setLineWidth( material.wireframeLinewidth );
3136

3137 3138
				if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
				_gl.drawElements( _gl.LINES, geometryGroup.__webglLineCount, _gl.UNSIGNED_SHORT, 0 );
3139

3140
			// triangles
3141

3142
			} else {
3143

3144 3145
				if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
				_gl.drawElements( _gl.TRIANGLES, geometryGroup.__webglFaceCount, _gl.UNSIGNED_SHORT, 0 );
3146

3147
			}
3148

3149 3150 3151
			_this.info.render.calls ++;
			_this.info.render.vertices += geometryGroup.__webglFaceCount;
			_this.info.render.faces += geometryGroup.__webglFaceCount / 3;
3152

3153
		// render lines
3154

3155
		} else if ( object instanceof THREE.Line ) {
3156

3157
			primitives = ( object.type === THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES;
3158

3159
			setLineWidth( material.linewidth );
3160

3161
			_gl.drawArrays( primitives, 0, geometryGroup.__webglLineCount );
3162

3163
			_this.info.render.calls ++;
3164

3165
		// render particles
3166

3167
		} else if ( object instanceof THREE.ParticleSystem ) {
3168

3169
			_gl.drawArrays( _gl.POINTS, 0, geometryGroup.__webglParticleCount );
3170

3171
			_this.info.render.calls ++;
3172
			_this.info.render.points += geometryGroup.__webglParticleCount;
3173

3174
		// render ribbon
3175

3176
		} else if ( object instanceof THREE.Ribbon ) {
3177

3178
			_gl.drawArrays( _gl.TRIANGLE_STRIP, 0, geometryGroup.__webglVertexCount );
3179

3180
			_this.info.render.calls ++;
3181

3182
		}
3183

3184
	};
3185

3186
	function setupMorphTargets ( material, geometryGroup, object ) {
3187

3188
		// set base
3189

3190
		var attributes = material.program.attributes;
3191

3192
		if ( object.morphTargetBase !== - 1 ) {
3193

3194 3195
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ object.morphTargetBase ] );
			_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
3196

3197
		} else if ( attributes.position >= 0 ) {
3198

3199 3200
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
			_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
3201

3202
		}
3203

3204
		if ( object.morphTargetForcedOrder.length ) {
3205

3206
			// set forced order
3207

3208 3209 3210 3211 3212
			var m = 0;
			var order = object.morphTargetForcedOrder;
			var influences = object.morphTargetInfluences;

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

3214 3215 3216
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ] );
				_gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );

A
alteredq 已提交
3217 3218 3219 3220 3221 3222 3223
				if ( material.morphNormals ) {

					_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ order[ m ] ] );
					_gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );

				}

3224 3225 3226
				object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ] ];

				m ++;
3227 3228
			}

3229 3230 3231 3232 3233 3234 3235 3236 3237 3238
		} else {

			// find most influencing

			var used = [];
			var candidateInfluence = - 1;
			var candidate = 0;
			var influences = object.morphTargetInfluences;
			var i, il = influences.length;
			var m = 0;
3239

3240
			if ( object.morphTargetBase !== - 1 ) {
3241

3242
				used[ object.morphTargetBase ] = true;
3243

3244
			}
3245

3246
			while ( m < material.numSupportedMorphTargets ) {
3247

3248
				for ( i = 0; i < il; i ++ ) {
3249

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

3252 3253
						candidate = i;
						candidateInfluence = influences[ candidate ];
3254

3255
					}
3256

3257
				}
3258

3259 3260
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ candidate ] );
				_gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
3261

A
alteredq 已提交
3262 3263 3264 3265 3266 3267 3268
				if ( material.morphNormals ) {

					_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ candidate ] );
					_gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );

				}

3269
				object.__webglMorphTargetInfluences[ m ] = candidateInfluence;
3270

3271 3272 3273
				used[ candidate ] = 1;
				candidateInfluence = -1;
				m ++;
3274 3275 3276 3277 3278

			}

		}

3279
		// load updated influences uniform
3280

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

3283
			_gl.uniform1fv( material.program.uniforms.morphTargetInfluences, object.__webglMorphTargetInfluences );
3284

3285
		}
3286

3287
	};
3288 3289


3290
	function painterSort ( a, b ) {
3291

3292
		return b.z - a.z;
3293

3294
	};
3295

3296
	// Rendering
3297

3298
	this.render = function ( scene, camera, renderTarget, forceClear ) {
3299

3300 3301 3302 3303 3304
		var i, il,

		webglObject, object,
		renderList,

3305
		lights = scene.__lights,
3306
		fog = scene.fog;
M
Mr.doob 已提交
3307

3308
		_currentMaterialId = -1;
3309

A
alteredq 已提交
3310
		// update scene graph
3311

3312
		if ( camera.parent === undefined ) {
3313

3314 3315
			console.warn( 'DEPRECATED: Camera hasn\'t been added to a Scene. Adding it...' );
			scene.add( camera );
3316

3317
		}
3318

3319
		if ( this.autoUpdateScene ) scene.updateMatrixWorld();
3320

A
alteredq 已提交
3321
		// update camera matrices and frustum
A
alteredq 已提交
3322

A
alteredq 已提交
3323 3324
		if ( ! camera._viewMatrixArray ) camera._viewMatrixArray = new Float32Array( 16 );
		if ( ! camera._projectionMatrixArray ) camera._projectionMatrixArray = new Float32Array( 16 );
A
alteredq 已提交
3325

3326
		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
A
alteredq 已提交
3327 3328 3329

		camera.matrixWorldInverse.flattenToArray( camera._viewMatrixArray );
		camera.projectionMatrix.flattenToArray( camera._projectionMatrixArray );
3330

3331
		_projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
A
alteredq 已提交
3332
		_frustum.setFromMatrix( _projScreenMatrix );
3333

A
alteredq 已提交
3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348
		// update WebGL objects

		if ( this.autoUpdateObjects ) this.initWebGLObjects( scene );

		// custom render plugins (pre pass)

		renderPlugins( this.renderPluginsPre, scene, camera );

		//

		_this.info.render.calls = 0;
		_this.info.render.vertices = 0;
		_this.info.render.faces = 0;
		_this.info.render.points = 0;

A
alteredq 已提交
3349
		this.setRenderTarget( renderTarget );
3350

3351
		if ( this.autoClear || forceClear ) {
3352

3353
			this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil );
M
Mr.doob 已提交
3354

3355
		}
M
Mr.doob 已提交
3356

3357
		// set matrices for regular objects (frustum culled)
3358

3359
		renderList = scene.__webglObjects;
3360

3361
		for ( i = 0, il = renderList.length; i < il; i ++ ) {
3362

3363
			webglObject = renderList[ i ];
3364
			object = webglObject.object;
3365

A
alteredq 已提交
3366 3367
			webglObject.render = false;

3368
			if ( object.visible ) {
3369

3370
				if ( ! ( object instanceof THREE.Mesh || object instanceof THREE.ParticleSystem ) || ! ( object.frustumCulled ) || _frustum.contains( object ) ) {
M
Mr.doob 已提交
3371

3372
					object.matrixWorld.flattenToArray( object._objectMatrixArray );
3373

A
alteredq 已提交
3374
					setupMatrices( object, camera );
3375

3376
					unrollBufferMaterial( webglObject );
3377

3378
					webglObject.render = true;
3379

3380
					if ( this.sortObjects ) {
3381

3382
						if ( object.renderDepth ) {
3383

3384
							webglObject.z = object.renderDepth;
M
Mr.doob 已提交
3385

3386
						} else {
M
Mr.doob 已提交
3387

3388
							_vector3.copy( object.matrixWorld.getPosition() );
3389
							_projScreenMatrix.multiplyVector3( _vector3 );
3390

3391
							webglObject.z = _vector3.z;
3392

3393
						}
M
Mr.doob 已提交
3394

3395
					}
M
Mr.doob 已提交
3396

3397
				}
3398 3399

			}
3400 3401 3402

		}

3403
		if ( this.sortObjects ) {
M
Mr.doob 已提交
3404

3405
			renderList.sort( painterSort );
3406

3407
		}
3408

3409
		// set matrices for immediate objects
3410

3411
		renderList = scene.__webglObjectsImmediate;
3412

3413 3414 3415
		for ( i = 0, il = renderList.length; i < il; i ++ ) {

			webglObject = renderList[ i ];
3416
			object = webglObject.object;
3417

3418
			if ( object.visible ) {
3419

3420
				if( object.matrixAutoUpdate ) {
3421

3422
					object.matrixWorld.flattenToArray( object._objectMatrixArray );
M
Mr.doob 已提交
3423

3424
				}
M
Mr.doob 已提交
3425

A
alteredq 已提交
3426
				setupMatrices( object, camera );
M
Mr.doob 已提交
3427

3428
				unrollImmediateBufferMaterial( webglObject );
M
Mr.doob 已提交
3429

3430
			}
M
Mr.doob 已提交
3431

3432
		}
3433

3434
		if ( scene.overrideMaterial ) {
3435

3436 3437 3438 3439 3440 3441
			var material = scene.overrideMaterial;

			this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
			this.setDepthTest( material.depthTest );
			this.setDepthWrite( material.depthWrite );
			setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
3442

3443 3444
			renderObjects( scene.__webglObjects, false, "", camera, lights, fog, true, material );
			renderObjectsImmediate( scene.__webglObjectsImmediate, "", camera, lights, fog, false, material );
M
Mr.doob 已提交
3445

3446
		} else {
3447

3448
			// opaque pass (front-to-back order)
3449

3450
			this.setBlending( THREE.NormalBlending );
3451

3452 3453
			renderObjects( scene.__webglObjects, true, "opaque", camera, lights, fog, false );
			renderObjectsImmediate( scene.__webglObjectsImmediate, "opaque", camera, lights, fog, false );
3454

3455
			// transparent pass (back-to-front order)
3456

3457 3458
			renderObjects( scene.__webglObjects, false, "transparent", camera, lights, fog, true );
			renderObjectsImmediate( scene.__webglObjectsImmediate, "transparent", camera, lights, fog, true );
3459

3460
		}
3461

A
alteredq 已提交
3462
		// custom render plugins (post pass)
3463

A
alteredq 已提交
3464
		renderPlugins( this.renderPluginsPost, scene, camera );
3465 3466


3467
		// Generate mipmap if we're using any kind of mipmap filtering
3468

3469
		if ( renderTarget && renderTarget.generateMipmaps && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) {
3470

3471
			updateRenderTargetMipmap( renderTarget );
3472

3473
		}
3474

3475 3476 3477
		// Ensure depth buffer writing is enabled so it can be cleared on next render

		this.setDepthTest( true );
3478
		this.setDepthWrite( true );
3479

3480
		// _gl.finish();
3481

3482
	};
3483

A
alteredq 已提交
3484 3485 3486 3487 3488 3489 3490
	function renderPlugins( plugins, scene, camera ) {

		if ( ! plugins.length ) return;

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

			_currentProgram = null;
3491
			_currentCamera = null;
A
alteredq 已提交
3492 3493 3494 3495 3496 3497
			_oldBlending = -1;
			_oldDepthTest = -1;
			_oldDepthWrite = -1;
			_currentGeometryGroupHash = -1;
			_currentMaterialId = -1;

A
alteredq 已提交
3498
			plugins[ i ].render( scene, camera, _currentWidth, _currentHeight );
A
alteredq 已提交
3499 3500

			_currentProgram = null;
3501
			_currentCamera = null;
A
alteredq 已提交
3502 3503 3504 3505 3506 3507 3508 3509 3510 3511
			_oldBlending = -1;
			_oldDepthTest = -1;
			_oldDepthWrite = -1;
			_currentGeometryGroupHash = -1;
			_currentMaterialId = -1;

		}

	};

3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547
	function renderObjects ( renderList, reverse, materialType, camera, lights, fog, useBlending, overrideMaterial ) {

		var webglObject, object, buffer, material, start, end, delta;

		if ( reverse ) {

			start = renderList.length - 1;
			end = -1;
			delta = -1;

		} else {

			start = 0;
			end = renderList.length;
			delta = 1;
		}

		for ( var i = start; i !== end; i += delta ) {

			webglObject = renderList[ i ];

			if ( webglObject.render ) {

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

				if ( overrideMaterial ) {

					material = overrideMaterial;

				} else {

					material = webglObject[ materialType ];

					if ( ! material ) continue;

3548
					if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
3549

A
alteredq 已提交
3550
					_this.setDepthTest( material.depthTest );
3551
					_this.setDepthWrite( material.depthWrite );
3552 3553 3554 3555
					setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );

				}

A
alteredq 已提交
3556
				_this.setObjectFaces( object );
3557 3558 3559 3560 3561 3562 3563 3564 3565 3566

				if ( buffer instanceof THREE.BufferGeometry ) {

					_this.renderBufferDirect( camera, lights, fog, material, buffer, object );

				} else {

					_this.renderBuffer( camera, lights, fog, material, buffer, object );

				}
3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594

			}

		}

	};

	function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, useBlending, overrideMaterial ) {

		var webglObject, object, material, program;

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

			webglObject = renderList[ i ];
			object = webglObject.object;

			if ( object.visible ) {

				if ( overrideMaterial ) {

					material = overrideMaterial;

				} else {

					material = webglObject[ materialType ];

					if ( ! material ) continue;

3595
					if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
3596

A
alteredq 已提交
3597
					_this.setDepthTest( material.depthTest );
3598
					_this.setDepthWrite( material.depthWrite );
3599 3600 3601 3602
					setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );

				}

A
alteredq 已提交
3603
				_this.renderImmediateObject( camera, lights, fog, material, object );
3604

A
alteredq 已提交
3605
			}
3606

A
alteredq 已提交
3607
		}
3608

A
alteredq 已提交
3609
	};
3610

A
alteredq 已提交
3611
	this.renderImmediateObject = function ( camera, lights, fog, material, object ) {
3612

A
alteredq 已提交
3613
		var program = setProgram( camera, lights, fog, material, object );
3614

A
alteredq 已提交
3615
		_currentGeometryGroupHash = -1;
3616

A
alteredq 已提交
3617 3618 3619 3620 3621 3622 3623 3624 3625
		_this.setObjectFaces( object );

		if ( object.immediateRenderCallback ) {

			object.immediateRenderCallback( program, _gl, _frustum );

		} else {

			object.render( function( object ) { _this.renderBufferImmediate( object, program, material.shading ); } );
3626 3627 3628 3629 3630

		}

	};

3631
	function unrollImmediateBufferMaterial ( globject ) {
3632

3633 3634
		var object = globject.object,
			material = object.material;
3635

3636
		if ( material.transparent ) {
3637

3638 3639
			globject.transparent = material;
			globject.opaque = null;
3640

3641
		} else {
3642

3643 3644
			globject.opaque = material;
			globject.transparent = null;
3645

3646
		}
A
alteredq 已提交
3647

3648
	};
A
alteredq 已提交
3649

3650
	function unrollBufferMaterial ( globject ) {
A
alteredq 已提交
3651

3652 3653 3654
		var object = globject.object,
			buffer = globject.buffer,
			material, materialIndex, meshMaterial;
3655

3656
		meshMaterial = object.material;
3657

3658
		if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
M
Mr.doob 已提交
3659

3660
			materialIndex = buffer.materialIndex;
3661

3662
			if ( materialIndex >= 0 ) {
3663

3664
				material = object.geometry.materials[ materialIndex ];
M
Mr.doob 已提交
3665

3666
				if ( material.transparent ) {
M
Mr.doob 已提交
3667

3668 3669
					globject.transparent = material;
					globject.opaque = null;
3670

3671
				} else {
3672

3673 3674
					globject.opaque = material;
					globject.transparent = null;
3675

3676
				}
3677

3678
			}
3679

3680
		} else {
3681

3682
			material = meshMaterial;
3683

3684
			if ( material ) {
3685

3686
				if ( material.transparent ) {
M
Mr.doob 已提交
3687

3688 3689
					globject.transparent = material;
					globject.opaque = null;
A
alteredq 已提交
3690

3691
				} else {
3692

3693 3694
					globject.opaque = material;
					globject.transparent = null;
3695

3696
				}
3697

3698
			}
3699

3700
		}
3701

3702
	};
3703

3704
	// Geometry splitting
3705

3706
	function sortFacesByMaterial ( geometry ) {
3707

3708 3709 3710
		var f, fl, face, materialIndex, vertices,
			materialHash, groupHash,
			hash_map = {};
3711

3712
		var numMorphTargets = geometry.morphTargets.length;
3713
		var numMorphNormals = geometry.morphNormals.length;
3714

3715
		geometry.geometryGroups = {};
3716

3717
		for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
3718

3719 3720
			face = geometry.faces[ f ];
			materialIndex = face.materialIndex;
3721

3722
			materialHash = ( materialIndex !== undefined ) ? materialIndex : -1;
3723

3724
			if ( hash_map[ materialHash ] === undefined ) {
3725

3726
				hash_map[ materialHash ] = { 'hash': materialHash, 'counter': 0 };
3727 3728 3729

			}

3730
			groupHash = hash_map[ materialHash ].hash + '_' + hash_map[ materialHash ].counter;
3731

3732
			if ( geometry.geometryGroups[ groupHash ] === undefined ) {
3733

3734
				geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
3735

3736
			}
A
alteredq 已提交
3737

3738
			vertices = face instanceof THREE.Face3 ? 3 : 4;
A
alteredq 已提交
3739

3740
			if ( geometry.geometryGroups[ groupHash ].vertices + vertices > 65535 ) {
A
alteredq 已提交
3741

3742 3743
				hash_map[ materialHash ].counter += 1;
				groupHash = hash_map[ materialHash ].hash + '_' + hash_map[ materialHash ].counter;
A
alteredq 已提交
3744

3745
				if ( geometry.geometryGroups[ groupHash ] === undefined ) {
A
alteredq 已提交
3746

3747
					geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
A
alteredq 已提交
3748

3749
				}
3750

3751
			}
3752

3753
			if ( face instanceof THREE.Face3 ) {
3754

3755
				geometry.geometryGroups[ groupHash ].faces3.push( f );
3756

3757
			} else {
3758

3759
				geometry.geometryGroups[ groupHash ].faces4.push( f );
3760

A
alteredq 已提交
3761
			}
3762

3763
			geometry.geometryGroups[ groupHash ].vertices += vertices;
3764

3765
		}
3766

3767
		geometry.geometryGroupsList = [];
3768

3769
		for ( var g in geometry.geometryGroups ) {
3770

3771
			geometry.geometryGroups[ g ].id = _geometryGroupCounter ++;
3772

3773
			geometry.geometryGroupsList.push( geometry.geometryGroups[ g ] );
3774

3775
		}
3776

3777
	};
3778

3779 3780 3781 3782 3783 3784 3785 3786 3787
	// Objects refresh

	this.initWebGLObjects = function ( scene ) {

		if ( !scene.__webglObjects ) {

			scene.__webglObjects = [];
			scene.__webglObjectsImmediate = [];
			scene.__webglSprites = [];
3788
			scene.__webglFlares = [];
3789 3790

		}
3791

3792
		while ( scene.__objectsAdded.length ) {
3793

3794 3795
			addObject( scene.__objectsAdded[ 0 ], scene );
			scene.__objectsAdded.splice( 0, 1 );
3796

3797
		}
A
alteredq 已提交
3798

3799
		while ( scene.__objectsRemoved.length ) {
3800

3801 3802
			removeObject( scene.__objectsRemoved[ 0 ], scene );
			scene.__objectsRemoved.splice( 0, 1 );
3803

3804
		}
3805

3806
		// update must be called after objects adding / removal
3807

3808
		for ( var o = 0, ol = scene.__webglObjects.length; o < ol; o ++ ) {
3809

3810
			updateObject( scene.__webglObjects[ o ].object );
M
Mr.doob 已提交
3811 3812 3813 3814 3815

		}

	};

3816
	// Objects adding
M
Mr.doob 已提交
3817

3818
	function addObject ( object, scene ) {
A
alteredq 已提交
3819

3820
		var g, geometry, geometryGroup;
3821

3822
		if ( ! object.__webglInit ) {
M
Mr.doob 已提交
3823

3824
			object.__webglInit = true;
M
Mr.doob 已提交
3825

3826
			object._modelViewMatrix = new THREE.Matrix4();
M
Mr.doob 已提交
3827

3828 3829 3830
			object._normalMatrixArray = new Float32Array( 9 );
			object._modelViewMatrixArray = new Float32Array( 16 );
			object._objectMatrixArray = new Float32Array( 16 );
M
Mr.doob 已提交
3831

3832
			object.matrixWorld.flattenToArray( object._objectMatrixArray );
M
Mr.doob 已提交
3833

3834
			if ( object instanceof THREE.Mesh ) {
M
Mr.doob 已提交
3835

3836
				geometry = object.geometry;
M
Mr.doob 已提交
3837

3838
				if ( geometry instanceof THREE.Geometry ) {
M
Mr.doob 已提交
3839

3840
					if ( geometry.geometryGroups === undefined ) {
M
Mr.doob 已提交
3841

3842
						sortFacesByMaterial( geometry );
M
Mr.doob 已提交
3843

3844 3845 3846
					}

					// create separate VBOs per geometry chunk
M
Mr.doob 已提交
3847

3848
					for ( g in geometry.geometryGroups ) {
M
Mr.doob 已提交
3849

3850
						geometryGroup = geometry.geometryGroups[ g ];
M
Mr.doob 已提交
3851

3852
						// initialise VBO on the first access
M
Mr.doob 已提交
3853

3854
						if ( ! geometryGroup.__webglVertexBuffer ) {
3855

3856 3857
							createMeshBuffers( geometryGroup );
							initMeshBuffers( geometryGroup, object );
M
Mr.doob 已提交
3858

3859 3860 3861 3862 3863 3864 3865 3866 3867
							geometry.__dirtyVertices = true;
							geometry.__dirtyMorphTargets = true;
							geometry.__dirtyElements = true;
							geometry.__dirtyUvs = true;
							geometry.__dirtyNormals = true;
							geometry.__dirtyTangents = true;
							geometry.__dirtyColors = true;

						}
M
Mr.doob 已提交
3868

3869
					}
M
Mr.doob 已提交
3870

3871
				}
M
Mr.doob 已提交
3872

3873
			} else if ( object instanceof THREE.Ribbon ) {
M
Mr.doob 已提交
3874

3875
				geometry = object.geometry;
M
Mr.doob 已提交
3876

3877
				if( ! geometry.__webglVertexBuffer ) {
M
Mr.doob 已提交
3878

3879 3880
					createRibbonBuffers( geometry );
					initRibbonBuffers( geometry );
M
Mr.doob 已提交
3881

3882 3883
					geometry.__dirtyVertices = true;
					geometry.__dirtyColors = true;
M
Mr.doob 已提交
3884

3885
				}
M
Mr.doob 已提交
3886

3887
			} else if ( object instanceof THREE.Line ) {
M
Mr.doob 已提交
3888

3889
				geometry = object.geometry;
M
Mr.doob 已提交
3890

3891
				if( ! geometry.__webglVertexBuffer ) {
M
Mr.doob 已提交
3892

3893 3894
					createLineBuffers( geometry );
					initLineBuffers( geometry, object );
M
Mr.doob 已提交
3895

3896 3897
					geometry.__dirtyVertices = true;
					geometry.__dirtyColors = true;
3898

3899
				}
3900

3901
			} else if ( object instanceof THREE.ParticleSystem ) {
3902

3903
				geometry = object.geometry;
3904

3905
				if ( ! geometry.__webglVertexBuffer ) {
3906

3907 3908
					createParticleBuffers( geometry );
					initParticleBuffers( geometry, object );
3909

3910 3911
					geometry.__dirtyVertices = true;
					geometry.__dirtyColors = true;
3912

3913
				}
3914

3915
			}
3916

3917
		}
3918

3919
		if ( ! object.__webglActive ) {
3920

3921
			if ( object instanceof THREE.Mesh ) {
3922

3923
				geometry = object.geometry;
3924

3925 3926 3927 3928 3929 3930 3931 3932 3933
				if ( geometry instanceof THREE.BufferGeometry ) {

					addBuffer( scene.__webglObjects, geometry, object );

				} else {

					for ( g in geometry.geometryGroups ) {

						geometryGroup = geometry.geometryGroups[ g ];
3934

3935
						addBuffer( scene.__webglObjects, geometryGroup, object );
3936

3937
					}
3938

3939
				}
3940

3941 3942 3943
			} else if ( object instanceof THREE.Ribbon ||
						object instanceof THREE.Line ||
						object instanceof THREE.ParticleSystem ) {
3944

3945 3946
				geometry = object.geometry;
				addBuffer( scene.__webglObjects, geometry, object );
3947

3948
			} else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
3949

3950
				addBufferImmediate( scene.__webglObjectsImmediate, object );
3951

3952
			} else if ( object instanceof THREE.Sprite ) {
3953

3954
				scene.__webglSprites.push( object );
3955

3956 3957 3958 3959
			} else if ( object instanceof THREE.LensFlare ) {

				scene.__webglFlares.push( object );

3960 3961
			}

3962
			object.__webglActive = true;
3963

3964
		}
3965

3966
	};
3967

3968
	function addBuffer ( objlist, buffer, object ) {
3969

3970 3971 3972 3973 3974 3975 3976 3977
		objlist.push(
			{
				buffer: buffer,
				object: object,
				opaque: null,
				transparent: null
			}
		);
3978

3979
	};
3980

3981
	function addBufferImmediate ( objlist, object ) {
3982

3983 3984 3985 3986 3987
		objlist.push(
			{
				object: object,
				opaque: null,
				transparent: null
3988
			}
3989
		);
3990

3991
	};
3992

3993
	// Objects updates
3994

3995
	function updateObject ( object ) {
3996

3997 3998
		var geometry = object.geometry,
			geometryGroup, customAttributesDirty, material;
3999

4000
		if ( object instanceof THREE.Mesh ) {
4001

4002 4003
			if ( geometry instanceof THREE.BufferGeometry ) {

4004
				/*
4005 4006 4007
				if ( geometry.__dirtyVertices || geometry.__dirtyElements ||
					 geometry.__dirtyUvs || geometry.__dirtyNormals ||
					 geometry.__dirtyColors  ) {
4008

4009 4010
					// TODO
					// set buffers from typed arrays
4011

4012
				}
4013
				*/
4014

4015 4016 4017 4018 4019
				geometry.__dirtyVertices = false;
				geometry.__dirtyElements = false;
				geometry.__dirtyUvs = false;
				geometry.__dirtyNormals = false;
				geometry.__dirtyColors = false;
4020

4021
			} else {
4022

4023
				// check all geometry groups
4024

4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039
				for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {

					geometryGroup = geometry.geometryGroupsList[ i ];

					material = getBufferMaterial( object, geometryGroup );

					customAttributesDirty = material.attributes && areCustomAttributesDirty( material );

					if ( geometry.__dirtyVertices || geometry.__dirtyMorphTargets || geometry.__dirtyElements ||
						 geometry.__dirtyUvs || geometry.__dirtyNormals ||
						 geometry.__dirtyColors || geometry.__dirtyTangents || customAttributesDirty ) {

						setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, !geometry.dynamic, material );

					}
4040

4041
				}
M
Mr.doob 已提交
4042

4043 4044 4045 4046 4047 4048 4049
				geometry.__dirtyVertices = false;
				geometry.__dirtyMorphTargets = false;
				geometry.__dirtyElements = false;
				geometry.__dirtyUvs = false;
				geometry.__dirtyNormals = false;
				geometry.__dirtyColors = false;
				geometry.__dirtyTangents = false;
4050

4051
				material.attributes && clearCustomAttributes( material );
4052

4053
			}
4054

4055
		} else if ( object instanceof THREE.Ribbon ) {
4056

4057
			if ( geometry.__dirtyVertices || geometry.__dirtyColors ) {
4058

4059
				setRibbonBuffers( geometry, _gl.DYNAMIC_DRAW );
4060

4061
			}
4062

4063 4064
			geometry.__dirtyVertices = false;
			geometry.__dirtyColors = false;
4065

4066
		} else if ( object instanceof THREE.Line ) {
4067

4068
			material = getBufferMaterial( object, geometryGroup );
A
alteredq 已提交
4069

4070
			customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
A
alteredq 已提交
4071

4072
			if ( geometry.__dirtyVertices ||  geometry.__dirtyColors || customAttributesDirty ) {
A
alteredq 已提交
4073

4074
				setLineBuffers( geometry, _gl.DYNAMIC_DRAW );
4075

4076
			}
4077

4078 4079
			geometry.__dirtyVertices = false;
			geometry.__dirtyColors = false;
4080

4081
			material.attributes && clearCustomAttributes( material );
4082

4083
		} else if ( object instanceof THREE.ParticleSystem ) {
4084

4085
			material = getBufferMaterial( object, geometryGroup );
4086

4087
			customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
4088

4089
			if ( geometry.__dirtyVertices || geometry.__dirtyColors || object.sortParticles || customAttributesDirty ) {
4090

4091
				setParticleBuffers( geometry, _gl.DYNAMIC_DRAW, object );
4092

4093
			}
4094

4095 4096
			geometry.__dirtyVertices = false;
			geometry.__dirtyColors = false;
4097

4098
			material.attributes && clearCustomAttributes( material );
4099

4100
		}
4101

4102
	};
4103

4104
	// Objects updates - custom attributes check
4105

4106
	function areCustomAttributesDirty ( material ) {
4107

4108
		for ( var a in material.attributes ) {
4109

4110
			if ( material.attributes[ a ].needsUpdate ) return true;
4111

4112
		}
4113

4114
		return false;
4115

4116
	};
4117

4118 4119 4120
	function clearCustomAttributes ( material ) {

		for ( var a in material.attributes ) {
4121

4122
			material.attributes[ a ].needsUpdate = false;
4123

4124
		}
4125

4126
	};
4127

4128
	// Objects removal
4129

4130
	function removeObject ( object, scene ) {
4131

4132 4133 4134 4135
		if ( object instanceof THREE.Mesh  ||
			 object instanceof THREE.ParticleSystem ||
			 object instanceof THREE.Ribbon ||
			 object instanceof THREE.Line ) {
4136

4137
			removeInstances( scene.__webglObjects, object );
4138

4139
		} else if ( object instanceof THREE.Sprite ) {
4140

4141
			removeInstancesDirect( scene.__webglSprites, object );
4142

4143 4144 4145 4146
		} else if ( object instanceof THREE.LensFlare ) {

			removeInstancesDirect( scene.__webglFlares, object );

4147
		} else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
4148

4149
			removeInstances( scene.__webglObjectsImmediate, object );
4150

4151
		}
4152

4153
		object.__webglActive = false;
4154

4155
	};
4156

4157
	function removeInstances ( objlist, object ) {
4158

4159
		for ( var o = objlist.length - 1; o >= 0; o -- ) {
4160

4161
			if ( objlist[ o ].object === object ) {
4162

4163
				objlist.splice( o, 1 );
4164

4165
			}
4166

4167
		}
4168

4169
	};
4170

4171
	function removeInstancesDirect ( objlist, object ) {
4172

4173
		for ( var o = objlist.length - 1; o >= 0; o -- ) {
4174

4175
			if ( objlist[ o ] === object ) {
4176

4177
				objlist.splice( o, 1 );
4178

4179
			}
4180

4181
		}
4182

4183
	};
4184

4185
	// Materials
4186

4187
	this.initMaterial = function ( material, lights, fog, object ) {
4188

4189
		var u, a, identifiers, i, parameters, maxLightCount, maxBones, maxShadows, shaderID;
4190

4191
		if ( material instanceof THREE.MeshDepthMaterial ) {
M
Mr.doob 已提交
4192

4193
			shaderID = 'depth';
4194

4195
		} else if ( material instanceof THREE.MeshNormalMaterial ) {
4196

4197
			shaderID = 'normal';
M
Mr.doob 已提交
4198

4199
		} else if ( material instanceof THREE.MeshBasicMaterial ) {
M
Mr.doob 已提交
4200

4201
			shaderID = 'basic';
M
Mr.doob 已提交
4202

4203
		} else if ( material instanceof THREE.MeshLambertMaterial ) {
M
Mr.doob 已提交
4204

4205
			shaderID = 'lambert';
M
Mr.doob 已提交
4206

4207
		} else if ( material instanceof THREE.MeshPhongMaterial ) {
4208

4209
			shaderID = 'phong';
4210

4211
		} else if ( material instanceof THREE.LineBasicMaterial ) {
4212

4213
			shaderID = 'basic';
4214

4215
		} else if ( material instanceof THREE.ParticleBasicMaterial ) {
4216

4217
			shaderID = 'particle_basic';
4218 4219 4220

		}

4221
		if ( shaderID ) {
4222

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

4225
		}
4226

4227 4228
		// heuristics to create shader parameters according to lights in the scene
		// (not to blow over maxLights budget)
4229

4230
		maxLightCount = allocateLights( lights );
4231

4232
		maxShadows = allocateShadows( lights );
4233

4234
		maxBones = allocateBones( object );
4235

4236
		parameters = {
4237

4238 4239 4240 4241 4242 4243
			map: !!material.map, envMap: !!material.envMap, lightMap: !!material.lightMap,
			vertexColors: material.vertexColors,
			fog: fog, useFog: material.fog,
			sizeAttenuation: material.sizeAttenuation,
			skinning: material.skinning,
			morphTargets: material.morphTargets,
A
alteredq 已提交
4244
			morphNormals: material.morphNormals,
4245
			maxMorphTargets: this.maxMorphTargets,
A
alteredq 已提交
4246
			maxMorphNormals: this.maxMorphNormals,
4247 4248 4249 4250
			maxDirLights: maxLightCount.directional, maxPointLights: maxLightCount.point,
			maxBones: maxBones,
			shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow,
			shadowMapSoft: this.shadowMapSoft,
A
alteredq 已提交
4251 4252
			shadowMapDebug: this.shadowMapDebug,
			shadowMapCascade: this.shadowMapCascade,
4253 4254 4255
			maxShadows: maxShadows,
			alphaTest: material.alphaTest,
			metal: material.metal,
4256
			perPixel: material.perPixel,
4257
			wrapAround: material.wrapAround,
4258
			doubleSided: object && object.doubleSided
4259

4260
		};
M
Mr.doob 已提交
4261

4262
		material.program = buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, parameters );
4263

4264
		var attributes = material.program.attributes;
4265

4266 4267 4268 4269
		if ( attributes.position >= 0 ) _gl.enableVertexAttribArray( attributes.position );
		if ( attributes.color >= 0 ) _gl.enableVertexAttribArray( attributes.color );
		if ( attributes.normal >= 0 ) _gl.enableVertexAttribArray( attributes.normal );
		if ( attributes.tangent >= 0 ) _gl.enableVertexAttribArray( attributes.tangent );
4270

4271 4272 4273
		if ( material.skinning &&
			 attributes.skinVertexA >=0 && attributes.skinVertexB >= 0 &&
			 attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
M
Mr.doob 已提交
4274

4275 4276 4277 4278
			_gl.enableVertexAttribArray( attributes.skinVertexA );
			_gl.enableVertexAttribArray( attributes.skinVertexB );
			_gl.enableVertexAttribArray( attributes.skinIndex );
			_gl.enableVertexAttribArray( attributes.skinWeight );
M
Mr.doob 已提交
4279 4280

		}
4281

4282
		if ( material.attributes ) {
A
alteredq 已提交
4283

4284
			for ( a in material.attributes ) {
M
Mr.doob 已提交
4285

4286
				if( attributes[ a ] !== undefined && attributes[ a ] >= 0 ) _gl.enableVertexAttribArray( attributes[ a ] );
4287

4288
			}
M
Mr.doob 已提交
4289

4290
		}
M
Mr.doob 已提交
4291

4292
		if ( material.morphTargets ) {
M
Mr.doob 已提交
4293

4294
			material.numSupportedMorphTargets = 0;
4295

4296
			var id, base = "morphTarget";
4297

4298
			for ( i = 0; i < this.maxMorphTargets; i ++ ) {
4299

4300
				id = base + i;
M
Mr.doob 已提交
4301

4302
				if ( attributes[ id ] >= 0 ) {
M
Mr.doob 已提交
4303

4304 4305
					_gl.enableVertexAttribArray( attributes[ id ] );
					material.numSupportedMorphTargets ++;
4306

4307
				}
4308

4309
			}
4310

4311
		}
4312

A
alteredq 已提交
4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333
		if ( material.morphNormals ) {

			material.numSupportedMorphNormals = 0;

			var id, base = "morphNormal";

			for ( i = 0; i < this.maxMorphNormals; i ++ ) {

				id = base + i;

				if ( attributes[ id ] >= 0 ) {

					_gl.enableVertexAttribArray( attributes[ id ] );
					material.numSupportedMorphNormals ++;

				}

			}

		}

4334
		material.uniformsList = [];
4335

4336
		for ( u in material.uniforms ) {
4337

4338
			material.uniformsList.push( [ material.uniforms[ u ], u ] );
4339

4340
		}
M
Mr.doob 已提交
4341

4342
	};
M
Mr.doob 已提交
4343

4344
	function setMaterialShaders( material, shaders ) {
M
Mr.doob 已提交
4345

4346 4347 4348
		material.uniforms = THREE.UniformsUtils.clone( shaders.uniforms );
		material.vertexShader = shaders.vertexShader;
		material.fragmentShader = shaders.fragmentShader;
M
Mr.doob 已提交
4349

4350
	};
M
Mr.doob 已提交
4351

4352
	function setProgram( camera, lights, fog, material, object ) {
4353

A
alteredq 已提交
4354
		if ( ! material.program || material.needsUpdate ) {
4355

4356
			_this.initMaterial( material, lights, fog, object );
A
alteredq 已提交
4357
			material.needsUpdate = false;
4358

4359
		}
4360

4361
		if ( material.morphTargets ) {
4362

4363
			if ( ! object.__webglMorphTargetInfluences ) {
4364

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

4367
				for ( var i = 0, il = _this.maxMorphTargets; i < il; i ++ ) {
4368

4369
					object.__webglMorphTargetInfluences[ i ] = 0;
4370

4371
				}
4372

4373
			}
4374

4375
		}
4376

4377
		var refreshMaterial = false;
4378

4379 4380 4381
		var program = material.program,
			p_uniforms = program.uniforms,
			m_uniforms = material.uniforms;
4382

4383
		if ( program !== _currentProgram ) {
4384

4385 4386
			_gl.useProgram( program );
			_currentProgram = program;
4387

4388
			refreshMaterial = true;
4389

4390
		}
4391

4392
		if ( material.id !== _currentMaterialId ) {
4393

4394 4395
			_currentMaterialId = material.id;
			refreshMaterial = true;
4396

4397
		}
4398

4399
		if ( refreshMaterial || camera !== _currentCamera ) {
4400

A
alteredq 已提交
4401
			_gl.uniformMatrix4fv( p_uniforms.projectionMatrix, false, camera._projectionMatrixArray );
A
alteredq 已提交
4402

4403 4404 4405 4406 4407 4408
			if ( camera !== _currentCamera ) _currentCamera = camera;

		}

		if ( refreshMaterial ) {

4409
			// refresh uniforms common to several materials
4410

4411
			if ( fog && material.fog ) {
4412

4413
				refreshUniformsFog( m_uniforms, fog );
M
Mr.doob 已提交
4414

4415
			}
M
Mr.doob 已提交
4416

4417 4418 4419
			if ( material instanceof THREE.MeshPhongMaterial ||
				 material instanceof THREE.MeshLambertMaterial ||
				 material.lights ) {
4420

4421 4422
				setupLights( program, lights );
				refreshUniformsLights( m_uniforms, _lights );
4423

4424
			}
M
Mr.doob 已提交
4425

4426 4427 4428
			if ( material instanceof THREE.MeshBasicMaterial ||
				 material instanceof THREE.MeshLambertMaterial ||
				 material instanceof THREE.MeshPhongMaterial ) {
M
Mr.doob 已提交
4429

4430
				refreshUniformsCommon( m_uniforms, material );
M
Mr.doob 已提交
4431 4432 4433

			}

4434
			// refresh single material specific uniforms
M
Mr.doob 已提交
4435

4436
			if ( material instanceof THREE.LineBasicMaterial ) {
4437

4438
				refreshUniformsLine( m_uniforms, material );
M
Mr.doob 已提交
4439

4440
			} else if ( material instanceof THREE.ParticleBasicMaterial ) {
M
Mr.doob 已提交
4441

4442
				refreshUniformsParticle( m_uniforms, material );
M
Mr.doob 已提交
4443

4444
			} else if ( material instanceof THREE.MeshPhongMaterial ) {
M
Mr.doob 已提交
4445

4446
				refreshUniformsPhong( m_uniforms, material );
M
Mr.doob 已提交
4447

4448
			} else if ( material instanceof THREE.MeshLambertMaterial ) {
M
Mr.doob 已提交
4449

4450
				refreshUniformsLambert( m_uniforms, material );
M
Mr.doob 已提交
4451

4452
			} else if ( material instanceof THREE.MeshDepthMaterial ) {
M
Mr.doob 已提交
4453

4454 4455 4456
				m_uniforms.mNear.value = camera.near;
				m_uniforms.mFar.value = camera.far;
				m_uniforms.opacity.value = material.opacity;
M
Mr.doob 已提交
4457

4458
			} else if ( material instanceof THREE.MeshNormalMaterial ) {
M
Mr.doob 已提交
4459

4460
				m_uniforms.opacity.value = material.opacity;
M
Mr.doob 已提交
4461

4462
			}
M
Mr.doob 已提交
4463

4464
			if ( object.receiveShadow && ! material._shadowPass ) {
M
Mr.doob 已提交
4465

4466
				refreshUniformsShadow( m_uniforms, lights );
M
Mr.doob 已提交
4467

4468
			}
M
Mr.doob 已提交
4469

4470
			// load common uniforms
M
Mr.doob 已提交
4471

4472
			loadUniformsGeneric( program, material.uniformsList );
M
Mr.doob 已提交
4473

4474 4475
			// load material specific uniforms
			// (shader material also gets them for the sake of genericity)
4476

4477 4478 4479
			if ( material instanceof THREE.ShaderMaterial ||
				 material instanceof THREE.MeshPhongMaterial ||
				 material.envMap ) {
4480

4481
				if ( p_uniforms.cameraPosition !== null ) {
4482

4483 4484
					var position = camera.matrixWorld.getPosition();
					_gl.uniform3f( p_uniforms.cameraPosition, position.x, position.y, position.z );
4485

4486
				}
4487 4488 4489

			}

4490 4491 4492 4493
			if ( material instanceof THREE.MeshPhongMaterial ||
				 material instanceof THREE.MeshLambertMaterial ||
				 material instanceof THREE.ShaderMaterial ||
				 material.skinning ) {
4494

4495
				if ( p_uniforms.viewMatrix !== null ) {
4496

A
alteredq 已提交
4497
					_gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, camera._viewMatrixArray );
4498

4499
				}
4500

4501
			}
M
Mr.doob 已提交
4502

4503
			if ( material.skinning ) {
4504

A
alteredq 已提交
4505
				_gl.uniformMatrix4fv( p_uniforms.boneGlobalMatrices, false, object.boneMatrices );
4506

4507
			}
4508

4509
		}
M
Mr.doob 已提交
4510

4511
		loadUniformsMatrices( p_uniforms, object );
M
Mr.doob 已提交
4512

4513 4514 4515 4516
		if ( material instanceof THREE.ShaderMaterial ||
			 material.envMap ||
			 material.skinning ||
			 object.receiveShadow ) {
M
Mr.doob 已提交
4517

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

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

4522
			}
4523

4524
		}
4525

4526
		return program;
4527

4528
	};
4529

4530
	// Uniforms (refresh uniforms objects)
A
alteredq 已提交
4531

4532
	function refreshUniformsCommon ( uniforms, material ) {
4533

4534
		uniforms.opacity.value = material.opacity;
4535

4536
		if ( _this.gammaInput ) {
4537

4538
			uniforms.diffuse.value.copyGammaToLinear( material.color );
4539

4540
		} else {
4541

4542
			uniforms.diffuse.value = material.color;
4543

4544
		}
4545

4546
		uniforms.map.texture = material.map;
4547

4548
		if ( material.map ) {
4549

4550
			uniforms.offsetRepeat.value.set( material.map.offset.x, material.map.offset.y, material.map.repeat.x, material.map.repeat.y );
M
Mr.doob 已提交
4551

4552
		}
M
Mr.doob 已提交
4553

4554
		uniforms.lightMap.texture = material.lightMap;
4555

4556 4557
		uniforms.envMap.texture = material.envMap;
		uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : -1;
4558

4559
		if ( _this.gammaInput ) {
4560

4561 4562
			//uniforms.reflectivity.value = material.reflectivity * material.reflectivity;
			uniforms.reflectivity.value = material.reflectivity;
M
Mr.doob 已提交
4563

4564
		} else {
4565

4566
			uniforms.reflectivity.value = material.reflectivity;
4567

4568
		}
4569

4570 4571 4572
		uniforms.refractionRatio.value = material.refractionRatio;
		uniforms.combine.value = material.combine;
		uniforms.useRefract.value = material.envMap && material.envMap.mapping instanceof THREE.CubeRefractionMapping;
M
Mr.doob 已提交
4573

4574
	};
M
Mr.doob 已提交
4575

4576
	function refreshUniformsLine ( uniforms, material ) {
M
Mr.doob 已提交
4577

4578 4579
		uniforms.diffuse.value = material.color;
		uniforms.opacity.value = material.opacity;
M
Mr.doob 已提交
4580

4581
	};
M
Mr.doob 已提交
4582

4583
	function refreshUniformsParticle ( uniforms, material ) {
4584

4585 4586 4587 4588
		uniforms.psColor.value = material.color;
		uniforms.opacity.value = material.opacity;
		uniforms.size.value = material.size;
		uniforms.scale.value = _canvas.height / 2.0; // TODO: Cache this.
4589

4590
		uniforms.map.texture = material.map;
4591

4592
	};
4593

4594
	function refreshUniformsFog ( uniforms, fog ) {
4595

4596
		uniforms.fogColor.value = fog.color;
4597

4598
		if ( fog instanceof THREE.Fog ) {
4599

4600 4601
			uniforms.fogNear.value = fog.near;
			uniforms.fogFar.value = fog.far;
4602

4603
		} else if ( fog instanceof THREE.FogExp2 ) {
M
Mikael Emtinger 已提交
4604

4605
			uniforms.fogDensity.value = fog.density;
M
Mikael Emtinger 已提交
4606

4607
		}
M
Mikael Emtinger 已提交
4608

4609
	};
M
Mikael Emtinger 已提交
4610

4611
	function refreshUniformsPhong ( uniforms, material ) {
M
Mikael Emtinger 已提交
4612

4613
		uniforms.shininess.value = material.shininess;
4614

4615
		if ( _this.gammaInput ) {
M
Mikael Emtinger 已提交
4616

4617
			uniforms.ambient.value.copyGammaToLinear( material.ambient );
4618
			uniforms.emissive.value.copyGammaToLinear( material.emissive );
4619
			uniforms.specular.value.copyGammaToLinear( material.specular );
4620

4621
		} else {
4622

4623
			uniforms.ambient.value = material.ambient;
4624
			uniforms.emissive.value = material.emissive;
4625
			uniforms.specular.value = material.specular;
4626

4627
		}
4628

4629 4630 4631 4632 4633 4634
		if ( material.wrapAround ) {

			uniforms.wrapRGB.value.copy( material.wrapRGB );

		}

4635
	};
4636

4637
	function refreshUniformsLambert ( uniforms, material ) {
4638

4639
		if ( _this.gammaInput ) {
4640

4641
			uniforms.ambient.value.copyGammaToLinear( material.ambient );
4642
			uniforms.emissive.value.copyGammaToLinear( material.emissive );
M
Mr.doob 已提交
4643

4644
		} else {
4645

4646
			uniforms.ambient.value = material.ambient;
4647
			uniforms.emissive.value = material.emissive;
4648

4649
		}
4650

4651 4652 4653 4654 4655 4656
		if ( material.wrapAround ) {

			uniforms.wrapRGB.value.copy( material.wrapRGB );

		}

4657
	};
4658

4659
	function refreshUniformsLights ( uniforms, lights ) {
4660

4661
		uniforms.ambientLightColor.value = lights.ambient;
4662

4663 4664
		uniforms.directionalLightColor.value = lights.directional.colors;
		uniforms.directionalLightDirection.value = lights.directional.positions;
4665

4666 4667 4668
		uniforms.pointLightColor.value = lights.point.colors;
		uniforms.pointLightPosition.value = lights.point.positions;
		uniforms.pointLightDistance.value = lights.point.distances;
4669

4670
	};
4671

4672
	function refreshUniformsShadow ( uniforms, lights ) {
M
Mr.doob 已提交
4673

4674
		if ( uniforms.shadowMatrix ) {
4675

4676
			var j = 0;
4677

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

4680
				var light = lights[ i ];
4681

A
alteredq 已提交
4682 4683
				if ( ! light.castShadow ) continue;

4684
				if ( light instanceof THREE.SpotLight || ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) ) {
4685 4686 4687

					uniforms.shadowMap.texture[ j ] = light.shadowMap;
					uniforms.shadowMapSize.value[ j ] = light.shadowMapSize;
4688

4689 4690 4691 4692 4693 4694 4695 4696 4697 4698
					uniforms.shadowMatrix.value[ j ] = light.shadowMatrix;

					uniforms.shadowDarkness.value[ j ] = light.shadowDarkness;
					uniforms.shadowBias.value[ j ] = light.shadowBias;

					j ++;

				}

			}
4699

4700 4701
		}

4702
	};
4703

4704
	// Uniforms (load to GPU)
4705

4706
	function loadUniformsMatrices ( uniforms, object ) {
4707

4708
		_gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object._modelViewMatrixArray );
4709

4710
		if ( uniforms.normalMatrix ) {
4711

4712
			_gl.uniformMatrix3fv( uniforms.normalMatrix, false, object._normalMatrixArray );
4713

4714
		}
4715

4716
	};
4717

4718
	function loadUniformsGeneric ( program, uniforms ) {
4719

4720
		var uniform, value, type, location, texture, i, il, j, jl, offset;
4721

4722
		for( j = 0, jl = uniforms.length; j < jl; j ++ ) {
4723

4724 4725
			location = program.uniforms[ uniforms[ j ][ 1 ] ];
			if ( !location ) continue;
4726

4727
			uniform = uniforms[ j ][ 0 ];
4728

4729 4730
			type = uniform.type;
			value = uniform.value;
4731

4732
			// single integer
4733

4734
			if( type === "i" ) {
4735

4736
				_gl.uniform1i( location, value );
4737

4738
			// single float
4739

4740
			} else if( type === "f" ) {
4741

4742
				_gl.uniform1f( location, value );
4743

4744
			// single THREE.Vector2
4745

4746
			} else if( type === "v2" ) {
4747

4748
				_gl.uniform2f( location, value.x, value.y );
4749

4750
			// single THREE.Vector3
4751

4752
			} else if( type === "v3" ) {
4753

4754
				_gl.uniform3f( location, value.x, value.y, value.z );
4755

4756
			// single THREE.Vector4
4757

4758
			} else if( type === "v4" ) {
4759

4760
				_gl.uniform4f( location, value.x, value.y, value.z, value.w );
4761

4762
			// single THREE.Color
4763

4764
			} else if( type === "c" ) {
4765

4766
				_gl.uniform3f( location, value.r, value.g, value.b );
4767

4768
			// flat array of floats (JS or typed array)
4769

4770
			} else if( type === "fv1" ) {
4771

4772
				_gl.uniform1fv( location, value );
4773

4774
			// flat array of floats with 3 x N size (JS or typed array)
4775

4776
			} else if( type === "fv" ) {
4777

4778
				_gl.uniform3fv( location, value );
4779

4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800
			// array of THREE.Vector2

			} else if( type === "v2v" ) {

				if ( ! uniform._array ) {

					uniform._array = new Float32Array( 2 * value.length );

				}

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

					offset = i * 2;

					uniform._array[ offset ] 	 = value[ i ].x;
					uniform._array[ offset + 1 ] = value[ i ].y;

				}

				_gl.uniform2fv( location, uniform._array );

4801
			// array of THREE.Vector3
4802

4803
			} else if( type === "v3v" ) {
4804

4805
				if ( ! uniform._array ) {
4806

4807
					uniform._array = new Float32Array( 3 * value.length );
M
Mr.doob 已提交
4808

4809
				}
A
alteredq 已提交
4810

4811
				for ( i = 0, il = value.length; i < il; i ++ ) {
A
alteredq 已提交
4812

4813
					offset = i * 3;
4814

4815 4816 4817
					uniform._array[ offset ] 	 = value[ i ].x;
					uniform._array[ offset + 1 ] = value[ i ].y;
					uniform._array[ offset + 2 ] = value[ i ].z;
4818

4819
				}
4820

4821
				_gl.uniform3fv( location, uniform._array );
A
alteredq 已提交
4822

4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844
			// array of THREE.Vector4

			} else if( type == "v4v" ) {

				if ( ! uniform._array ) {

					uniform._array = new Float32Array( 4 * value.length );

				}

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

					offset = i * 4;

					uniform._array[ offset ] 	 = value[ i ].x;
					uniform._array[ offset + 1 ] = value[ i ].y;
					uniform._array[ offset + 2 ] = value[ i ].z;
					uniform._array[ offset + 3 ] = value[ i ].w;

				}

				_gl.uniform4fv( location, uniform._array );
4845

4846
			// single THREE.Matrix4
4847

4848
			} else if( type === "m4" ) {
M
Mr.doob 已提交
4849

4850
				if ( ! uniform._array ) {
A
alteredq 已提交
4851

4852
					uniform._array = new Float32Array( 16 );
4853

4854
				}
4855

4856 4857
				value.flattenToArray( uniform._array );
				_gl.uniformMatrix4fv( location, false, uniform._array );
4858

4859
			// array of THREE.Matrix4
4860

4861
			} else if( type === "m4v" ) {
A
alteredq 已提交
4862

4863 4864 4865
				if ( ! uniform._array ) {

					uniform._array = new Float32Array( 16 * value.length );
A
alteredq 已提交
4866

M
Mr.doob 已提交
4867
				}
M
Mr.doob 已提交
4868

4869
				for ( i = 0, il = value.length; i < il; i ++ ) {
M
Mr.doob 已提交
4870

4871
					value[ i ].flattenToArrayOffset( uniform._array, i * 16 );
M
Mr.doob 已提交
4872

4873
				}
A
alteredq 已提交
4874

4875
				_gl.uniformMatrix4fv( location, false, uniform._array );
M
Mr.doob 已提交
4876

4877

4878
			// single THREE.Texture (2d or cube)
M
Mr.doob 已提交
4879

4880
			} else if( type === "t" ) {
A
alteredq 已提交
4881

4882
				_gl.uniform1i( location, value );
4883

4884
				texture = uniform.texture;
A
alteredq 已提交
4885

4886
				if ( !texture ) continue;
A
alteredq 已提交
4887

4888
				if ( texture.image instanceof Array && texture.image.length === 6 ) {
A
alteredq 已提交
4889

4890
					setCubeTexture( texture, value );
A
alteredq 已提交
4891

4892
				} else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
M
Mr.doob 已提交
4893

4894 4895 4896 4897
					setCubeTextureDynamic( texture, value );

				} else {

4898
					_this.setTexture( texture, value );
4899

M
Mr.doob 已提交
4900
				}
M
Mr.doob 已提交
4901

4902
			// array of THREE.Texture (2d)
M
Mr.doob 已提交
4903

4904
			} else if( type === "tv" ) {
M
Mr.doob 已提交
4905

4906
				if ( ! uniform._array ) {
M
Mr.doob 已提交
4907

4908
					uniform._array = [];
A
alteredq 已提交
4909

4910 4911 4912 4913 4914
					for( i = 0, il = uniform.texture.length; i < il; i ++ ) {

						uniform._array[ i ] = value + i;

					}
A
alteredq 已提交
4915

M
Mr.doob 已提交
4916
				}
A
alteredq 已提交
4917

4918
				_gl.uniform1iv( location, uniform._array );
A
alteredq 已提交
4919

4920
				for( i = 0, il = uniform.texture.length; i < il; i ++ ) {
4921

4922
					texture = uniform.texture[ i ];
4923

4924
					if ( !texture ) continue;
M
Mr.doob 已提交
4925

4926
					_this.setTexture( texture, uniform._array[ i ] );
M
Mr.doob 已提交
4927

M
Mr.doob 已提交
4928
				}
M
Mr.doob 已提交
4929

M
Mr.doob 已提交
4930
			}
M
Mr.doob 已提交
4931

M
Mr.doob 已提交
4932
		}
M
Mr.doob 已提交
4933

4934
	};
M
Mr.doob 已提交
4935

A
alteredq 已提交
4936
	function setupMatrices ( object, camera ) {
M
Mr.doob 已提交
4937

4938
		object._modelViewMatrix.multiplyToArray( camera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
M
Mr.doob 已提交
4939

4940
		var inverseMatrix = THREE.Matrix4.makeInvert3x3( object._modelViewMatrix );
4941

4942
		if ( inverseMatrix ) {
4943

4944
			inverseMatrix.transposeIntoArray( object._normalMatrixArray );
M
Mr.doob 已提交
4945

4946
		}
M
Mr.doob 已提交
4947

A
alteredq 已提交
4948
	};
M
Mr.doob 已提交
4949

4950
	function setupLights ( program, lights ) {
M
Mr.doob 已提交
4951

4952 4953 4954
		var l, ll, light, n,
		r = 0, g = 0, b = 0,
		color, position, intensity, distance,
M
Mr.doob 已提交
4955

4956
		zlights = _lights,
A
alteredq 已提交
4957

4958 4959
		dcolors = zlights.directional.colors,
		dpositions = zlights.directional.positions,
A
alteredq 已提交
4960

4961 4962 4963
		pcolors = zlights.point.colors,
		ppositions = zlights.point.positions,
		pdistances = zlights.point.distances,
4964

4965 4966
		dlength = 0,
		plength = 0,
4967

4968 4969
		doffset = 0,
		poffset = 0;
4970

4971
		for ( l = 0, ll = lights.length; l < ll; l ++ ) {
4972

4973
			light = lights[ l ];
A
alteredq 已提交
4974

A
alteredq 已提交
4975 4976 4977
			if ( light.onlyShadow ) continue;

			color = light.color;
4978 4979
			intensity = light.intensity;
			distance = light.distance;
A
alteredq 已提交
4980

4981
			if ( light instanceof THREE.AmbientLight ) {
4982

4983
				if ( _this.gammaInput ) {
4984

4985 4986 4987
					r += color.r * color.r;
					g += color.g * color.g;
					b += color.b * color.b;
4988

4989
				} else {
4990

4991 4992 4993
					r += color.r;
					g += color.g;
					b += color.b;
4994

4995
				}
4996

4997
			} else if ( light instanceof THREE.DirectionalLight ) {
4998

4999
				doffset = dlength * 3;
5000

5001
				if ( _this.gammaInput ) {
5002

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

5007
				} else {
5008

5009 5010 5011
					dcolors[ doffset ]     = color.r * intensity;
					dcolors[ doffset + 1 ] = color.g * intensity;
					dcolors[ doffset + 2 ] = color.b * intensity;
A
alteredq 已提交
5012

5013
				}
A
alteredq 已提交
5014

5015 5016 5017
				_direction.copy( light.matrixWorld.getPosition() );
				_direction.subSelf( light.target.matrixWorld.getPosition() );
				_direction.normalize();
A
alteredq 已提交
5018

5019 5020 5021
				dpositions[ doffset ]     = _direction.x;
				dpositions[ doffset + 1 ] = _direction.y;
				dpositions[ doffset + 2 ] = _direction.z;
A
alteredq 已提交
5022

5023
				dlength += 1;
A
alteredq 已提交
5024

5025
			} else if( light instanceof THREE.PointLight || light instanceof THREE.SpotLight ) {
M
Mr.doob 已提交
5026

5027
				poffset = plength * 3;
M
Mr.doob 已提交
5028

5029
				if ( _this.gammaInput ) {
5030

5031 5032 5033
					pcolors[ poffset ]     = color.r * color.r * intensity * intensity;
					pcolors[ poffset + 1 ] = color.g * color.g * intensity * intensity;
					pcolors[ poffset + 2 ] = color.b * color.b * intensity * intensity;
A
alteredq 已提交
5034

5035
				} else {
A
alteredq 已提交
5036

5037 5038 5039
					pcolors[ poffset ]     = color.r * intensity;
					pcolors[ poffset + 1 ] = color.g * intensity;
					pcolors[ poffset + 2 ] = color.b * intensity;
A
alteredq 已提交
5040

5041
				}
A
alteredq 已提交
5042

A
alteredq 已提交
5043 5044
				position = light.matrixWorld.getPosition();

5045 5046 5047
				ppositions[ poffset ]     = position.x;
				ppositions[ poffset + 1 ] = position.y;
				ppositions[ poffset + 2 ] = position.z;
A
alteredq 已提交
5048

5049
				pdistances[ plength ] = distance;
A
alteredq 已提交
5050

5051
				plength += 1;
5052

5053
			}
5054

5055
		}
A
alteredq 已提交
5056

5057 5058
		// null eventual remains from removed lights
		// (this is to avoid if in shader)
A
alteredq 已提交
5059

5060 5061
		for ( l = dlength * 3, ll = dcolors.length; l < ll; l ++ ) dcolors[ l ] = 0.0;
		for ( l = plength * 3, ll = pcolors.length; l < ll; l ++ ) pcolors[ l ] = 0.0;
A
alteredq 已提交
5062

5063 5064
		zlights.point.length = plength;
		zlights.directional.length = dlength;
A
alteredq 已提交
5065

5066 5067 5068
		zlights.ambient[ 0 ] = r;
		zlights.ambient[ 1 ] = g;
		zlights.ambient[ 2 ] = b;
5069

5070
	};
M
Mr.doob 已提交
5071

5072
	// GL state setting
M
Mr.doob 已提交
5073

5074
	this.setFaceCulling = function ( cullFace, frontFace ) {
M
Mr.doob 已提交
5075

5076
		if ( cullFace ) {
M
Mr.doob 已提交
5077

5078
			if ( !frontFace || frontFace === "ccw" ) {
5079

5080
				_gl.frontFace( _gl.CCW );
5081

5082
			} else {
5083

5084
				_gl.frontFace( _gl.CW );
M
Mr.doob 已提交
5085

5086
			}
M
Mr.doob 已提交
5087

5088
			if( cullFace === "back" ) {
5089

5090
				_gl.cullFace( _gl.BACK );
5091

5092
			} else if( cullFace === "front" ) {
5093

5094
				_gl.cullFace( _gl.FRONT );
M
Mr.doob 已提交
5095

5096
			} else {
5097

5098
				_gl.cullFace( _gl.FRONT_AND_BACK );
5099

5100
			}
5101

5102
			_gl.enable( _gl.CULL_FACE );
5103

5104
		} else {
5105

5106
			_gl.disable( _gl.CULL_FACE );
5107 5108 5109 5110 5111

		}

	};

A
alteredq 已提交
5112
	this.setObjectFaces = function ( object ) {
5113

5114
		if ( _oldDoubleSided !== object.doubleSided ) {
M
Mr.doob 已提交
5115

5116
			if( object.doubleSided ) {
M
Mr.doob 已提交
5117

5118
				_gl.disable( _gl.CULL_FACE );
M
Mr.doob 已提交
5119

5120
			} else {
5121

5122
				_gl.enable( _gl.CULL_FACE );
5123

5124
			}
5125

5126
			_oldDoubleSided = object.doubleSided;
5127

5128
		}
5129

5130
		if ( _oldFlipSided !== object.flipSided ) {
5131

5132
			if( object.flipSided ) {
5133

5134
				_gl.frontFace( _gl.CW );
5135

5136
			} else {
5137

5138
				_gl.frontFace( _gl.CCW );
5139

5140
			}
5141

5142
			_oldFlipSided = object.flipSided;
5143

5144
		}
5145

5146
	};
5147

A
alteredq 已提交
5148
	this.setDepthTest = function ( depthTest ) {
5149

5150
		if ( _oldDepthTest !== depthTest ) {
5151

5152
			if ( depthTest ) {
5153

5154
				_gl.enable( _gl.DEPTH_TEST );
5155

5156
			} else {
5157

5158
				_gl.disable( _gl.DEPTH_TEST );
5159 5160 5161

			}

5162
			_oldDepthTest = depthTest;
5163

5164
		}
5165

5166
	};
5167

5168
	this.setDepthWrite = function ( depthWrite ) {
A
alteredq 已提交
5169

5170
		if ( _oldDepthWrite !== depthWrite ) {
A
alteredq 已提交
5171

5172 5173
			_gl.depthMask( depthWrite );
			_oldDepthWrite = depthWrite;
A
alteredq 已提交
5174 5175 5176 5177 5178

		}

	};

5179
	function setLineWidth ( width ) {
5180

5181
		if ( width !== _oldLineWidth ) {
5182

5183 5184 5185
			_gl.lineWidth( width );

			_oldLineWidth = width;
5186 5187 5188

		}

5189
	};
5190

5191
	function setPolygonOffset ( polygonoffset, factor, units ) {
5192

5193
		if ( _oldPolygonOffset !== polygonoffset ) {
M
Mr.doob 已提交
5194

5195
			if ( polygonoffset ) {
5196

5197
				_gl.enable( _gl.POLYGON_OFFSET_FILL );
5198

5199
			} else {
5200

5201
				_gl.disable( _gl.POLYGON_OFFSET_FILL );
5202

5203
			}
5204

5205
			_oldPolygonOffset = polygonoffset;
5206

5207
		}
5208

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

5211
			_gl.polygonOffset( factor, units );
M
Mr.doob 已提交
5212

5213 5214
			_oldPolygonOffsetFactor = factor;
			_oldPolygonOffsetUnits = units;
M
Mr.doob 已提交
5215

5216
		}
M
Mr.doob 已提交
5217

5218
	};
M
Mr.doob 已提交
5219

5220
	this.setBlending = function ( blending, blendEquation, blendSrc, blendDst ) {
M
Mr.doob 已提交
5221

5222
		if ( blending !== _oldBlending ) {
M
Mr.doob 已提交
5223

5224
			switch ( blending ) {
M
Mr.doob 已提交
5225

5226
				case THREE.NoBlending:
5227 5228 5229 5230

					_gl.disable( _gl.BLEND );

					break;
5231

5232
				case THREE.AdditiveBlending:
M
Mr.doob 已提交
5233

5234
					_gl.enable( _gl.BLEND );
5235 5236
					_gl.blendEquation( _gl.FUNC_ADD );
					_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE );
M
Mr.doob 已提交
5237

5238
					break;
M
Mr.doob 已提交
5239

5240
				case THREE.SubtractiveBlending:
M
Mr.doob 已提交
5241

5242
					// TODO: Find blendFuncSeparate() combination
5243
					_gl.enable( _gl.BLEND );
5244 5245
					_gl.blendEquation( _gl.FUNC_ADD );
					_gl.blendFunc( _gl.ZERO, _gl.ONE_MINUS_SRC_COLOR );
M
Mr.doob 已提交
5246

5247
					break;
M
Mr.doob 已提交
5248

5249
				case THREE.MultiplyBlending:
M
Mr.doob 已提交
5250

5251
					// TODO: Find blendFuncSeparate() combination
5252
					_gl.enable( _gl.BLEND );
5253 5254
					_gl.blendEquation( _gl.FUNC_ADD );
					_gl.blendFunc( _gl.ZERO, _gl.SRC_COLOR );
M
Mr.doob 已提交
5255

5256
					break;
5257

5258 5259 5260 5261 5262 5263
				case THREE.CustomBlending:

					_gl.enable( _gl.BLEND );

					break;

5264
				default:
N
Nicolas Garcia Belmonte 已提交
5265

5266
					_gl.enable( _gl.BLEND );
5267 5268
					_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 );
5269

5270
					break;
5271

5272
			}
5273

5274
			_oldBlending = blending;
5275

5276
		}
5277

5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304
		if ( blending === THREE.CustomBlending ) {

			if ( blendEquation !== _oldBlendEquation ) {

				_gl.blendEquation( paramThreeToGL( blendEquation ) );

				_oldBlendEquation = blendEquation;

			}

			if ( blendSrc !== _oldBlendSrc || blendDst !== _oldBlendDst ) {

				_gl.blendFunc( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ) );

				_oldBlendSrc = blendSrc;
				_oldBlendDst = blendDst;

			}

		} else {

			_oldBlendEquation = null;
			_oldBlendSrc = null;
			_oldBlendDst = null;

		}

5305
	};
5306

5307 5308 5309
	// Shaders

	function buildProgram ( shaderID, fragmentShader, vertexShader, uniforms, attributes, parameters ) {
5310

5311
		var p, pl, program, code;
5312
		var chunks = [];
5313 5314 5315

		// Generate code

5316 5317 5318 5319 5320 5321 5322 5323 5324 5325
		if ( shaderID ) {

			chunks.push( shaderID );

		} else {

			chunks.push( fragmentShader );
			chunks.push( vertexShader );

		}
5326 5327 5328

		for ( p in parameters ) {

5329 5330
			chunks.push( p );
			chunks.push( parameters[ p ] );
5331 5332 5333

		}

5334 5335
		code = chunks.join();

5336 5337 5338 5339
		// Check if code has been already compiled

		for ( p = 0, pl = _programs.length; p < pl; p ++ ) {

5340
			if ( _programs[ p ].code === code ) {
5341 5342

				// console.log( "Code already compiled." /*: \n\n" + code*/ );
5343

5344 5345 5346 5347 5348
				return _programs[ p ].program;

			}

		}
5349

5350
		//console.log( "building new program " );
5351 5352 5353

		//

5354
		program = _gl.createProgram();
M
Mr.doob 已提交
5355

5356
		var prefix_vertex = [
M
Mr.doob 已提交
5357

5358 5359
			"precision " + _precision + " float;",

5360
			( _maxVertexTextures > 0 ) ? "#define VERTEX_TEXTURES" : "",
5361

5362 5363 5364 5365
			_this.gammaInput ? "#define GAMMA_INPUT" : "",
			_this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
			_this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",

5366 5367 5368
			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,

5369 5370
			"#define MAX_SHADOWS " + parameters.maxShadows,

5371 5372
			"#define MAX_BONES " + parameters.maxBones,

5373
			parameters.map ? "#define USE_MAP" : "",
5374 5375 5376
			parameters.envMap ? "#define USE_ENVMAP" : "",
			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
			parameters.vertexColors ? "#define USE_COLOR" : "",
5377
			parameters.skinning ? "#define USE_SKINNING" : "",
5378
			parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
A
alteredq 已提交
5379
			parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
A
alteredq 已提交
5380
			parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
5381
			parameters.wrapAround ? "#define WRAP_AROUND" : "",
5382
			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
5383

5384
			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
5385
			parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
A
alteredq 已提交
5386 5387
			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
5388

5389 5390
			parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",

M
Mr.doob 已提交
5391 5392 5393
			"uniform mat4 objectMatrix;",
			"uniform mat4 modelViewMatrix;",
			"uniform mat4 projectionMatrix;",
5394 5395
			"uniform mat4 viewMatrix;",
			"uniform mat3 normalMatrix;",
M
Mr.doob 已提交
5396
			"uniform vec3 cameraPosition;",
A
alteredq 已提交
5397

M
Mr.doob 已提交
5398 5399 5400
			"attribute vec3 position;",
			"attribute vec3 normal;",
			"attribute vec2 uv;",
5401
			"attribute vec2 uv2;",
5402

5403
			"#ifdef USE_COLOR",
5404

5405
				"attribute vec3 color;",
5406

5407 5408
			"#endif",

5409
			"#ifdef USE_MORPHTARGETS",
5410

5411 5412 5413 5414
				"attribute vec3 morphTarget0;",
				"attribute vec3 morphTarget1;",
				"attribute vec3 morphTarget2;",
				"attribute vec3 morphTarget3;",
A
alteredq 已提交
5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430

				"#ifdef USE_MORPHNORMALS",

					"attribute vec3 morphNormal0;",
					"attribute vec3 morphNormal1;",
					"attribute vec3 morphNormal2;",
					"attribute vec3 morphNormal3;",

				"#else",

					"attribute vec3 morphTarget4;",
					"attribute vec3 morphTarget5;",
					"attribute vec3 morphTarget6;",
					"attribute vec3 morphTarget7;",

				"#endif",
5431

5432 5433 5434
			"#endif",

			"#ifdef USE_SKINNING",
5435

5436 5437 5438 5439
				"attribute vec4 skinVertexA;",
				"attribute vec4 skinVertexB;",
				"attribute vec4 skinIndex;",
				"attribute vec4 skinWeight;",
5440

5441
			"#endif",
5442

M
Mr.doob 已提交
5443
			""
A
alteredq 已提交
5444

M
Mr.doob 已提交
5445
		].join("\n");
5446

M
Mr.doob 已提交
5447 5448
		var prefix_fragment = [

5449
			"precision " + _precision + " float;",
M
Mr.doob 已提交
5450 5451 5452 5453

			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,

5454 5455
			"#define MAX_SHADOWS " + parameters.maxShadows,

5456 5457
			parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "",

5458 5459 5460 5461
			_this.gammaInput ? "#define GAMMA_INPUT" : "",
			_this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
			_this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",

M
Mr.doob 已提交
5462 5463
			( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
			( parameters.useFog && parameters.fog instanceof THREE.FogExp2 ) ? "#define FOG_EXP2" : "",
M
Mr.doob 已提交
5464 5465 5466 5467 5468

			parameters.map ? "#define USE_MAP" : "",
			parameters.envMap ? "#define USE_ENVMAP" : "",
			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
			parameters.vertexColors ? "#define USE_COLOR" : "",
5469

5470 5471
			parameters.metal ? "#define METAL" : "",
			parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
5472
			parameters.wrapAround ? "#define WRAP_AROUND" : "",
5473
			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
5474

5475
			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
5476
			parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
A
alteredq 已提交
5477 5478
			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
M
Mr.doob 已提交
5479 5480 5481 5482 5483 5484 5485

			"uniform mat4 viewMatrix;",
			"uniform vec3 cameraPosition;",
			""

		].join("\n");

5486 5487
		_gl.attachShader( program, getShader( "fragment", prefix_fragment + fragmentShader ) );
		_gl.attachShader( program, getShader( "vertex", prefix_vertex + vertexShader ) );
M
Mr.doob 已提交
5488

M
Mr.doob 已提交
5489
		_gl.linkProgram( program );
N
Nicolas Garcia Belmonte 已提交
5490

M
Mr.doob 已提交
5491
		if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) {
N
Nicolas Garcia Belmonte 已提交
5492

5493
			console.error( "Could not initialise shader\n" + "VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" );
M
Mr.doob 已提交
5494

N
Nicolas Garcia Belmonte 已提交
5495
		}
5496

5497 5498
		//console.log( prefix_fragment + fragmentShader );
		//console.log( prefix_vertex + vertexShader );
M
Mr.doob 已提交
5499

M
Mr.doob 已提交
5500
		program.uniforms = {};
5501
		program.attributes = {};
M
Mr.doob 已提交
5502

5503 5504 5505 5506
		var identifiers, u, a, i;

		// cache uniform locations

5507
		identifiers = [
5508

5509
			'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition',
A
alteredq 已提交
5510
			'boneGlobalMatrices', 'morphTargetInfluences'
M
Mr.doob 已提交
5511

5512
		];
M
Mr.doob 已提交
5513

5514
		for ( u in uniforms ) {
M
Mr.doob 已提交
5515

5516
			identifiers.push( u );
M
Mr.doob 已提交
5517

5518
		}
M
Mr.doob 已提交
5519

5520
		cacheUniformLocations( program, identifiers );
M
Mr.doob 已提交
5521

5522
		// cache attributes locations
M
Mr.doob 已提交
5523

5524
		identifiers = [
A
alteredq 已提交
5525

5526 5527
			"position", "normal", "uv", "uv2", "tangent", "color",
			"skinVertexA", "skinVertexB", "skinIndex", "skinWeight"
A
alteredq 已提交
5528

5529
		];
M
Mr.doob 已提交
5530

5531
		for ( i = 0; i < parameters.maxMorphTargets; i ++ ) {
M
Mr.doob 已提交
5532

5533
			identifiers.push( "morphTarget" + i );
M
Mr.doob 已提交
5534

5535
		}
5536

A
alteredq 已提交
5537 5538 5539 5540 5541 5542
		for ( i = 0; i < parameters.maxMorphNormals; i ++ ) {

			identifiers.push( "morphNormal" + i );

		}

5543
		for ( a in attributes ) {
5544

5545
			identifiers.push( a );
5546

5547
		}
5548

5549
		cacheAttributeLocations( program, identifiers );
5550

5551
		program.id = _programs.length;
5552

5553
		_programs.push( { program: program, code: code } );
5554

5555
		_this.info.memory.programs = _programs.length;
5556

5557
		return program;
5558

5559
	};
5560

5561
	// Shader parameters cache
5562

5563
	function cacheUniformLocations ( program, identifiers ) {
5564

5565
		var i, l, id;
5566

5567
		for( i = 0, l = identifiers.length; i < l; i ++ ) {
5568

5569 5570
			id = identifiers[ i ];
			program.uniforms[ id ] = _gl.getUniformLocation( program, id );
M
Mr.doob 已提交
5571

5572
		}
M
Mr.doob 已提交
5573

5574
	};
M
Mr.doob 已提交
5575

5576
	function cacheAttributeLocations ( program, identifiers ) {
A
alteredq 已提交
5577

5578
		var i, l, id;
A
alteredq 已提交
5579

5580
		for( i = 0, l = identifiers.length; i < l; i ++ ) {
A
alteredq 已提交
5581

5582 5583
			id = identifiers[ i ];
			program.attributes[ id ] = _gl.getAttribLocation( program, id );
A
alteredq 已提交
5584

5585
		}
5586

5587
	};
A
alteredq 已提交
5588

5589
	function getShader ( type, string ) {
A
alteredq 已提交
5590

5591
		var shader;
5592

5593
		if ( type === "fragment" ) {
A
alteredq 已提交
5594

5595
			shader = _gl.createShader( _gl.FRAGMENT_SHADER );
A
alteredq 已提交
5596

5597
		} else if ( type === "vertex" ) {
A
alteredq 已提交
5598

5599
			shader = _gl.createShader( _gl.VERTEX_SHADER );
A
alteredq 已提交
5600

5601
		}
A
alteredq 已提交
5602

5603 5604
		_gl.shaderSource( shader, string );
		_gl.compileShader( shader );
5605

5606
		if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {
5607

5608 5609 5610
			console.error( _gl.getShaderInfoLog( shader ) );
			console.error( string );
			return null;
5611

A
alteredq 已提交
5612 5613
		}

5614 5615
		return shader;

A
alteredq 已提交
5616
	};
5617

5618 5619
	// Textures

5620 5621 5622 5623 5624 5625 5626

	function isPowerOfTwo ( value ) {

		return ( value & ( value - 1 ) ) === 0;

	};

5627
	function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
5628

5629
		if ( isImagePowerOfTwo ) {
M
Mr.doob 已提交
5630

5631 5632
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
M
Mr.doob 已提交
5633

5634 5635
			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
M
Mr.doob 已提交
5636

5637
		} else {
M
Mr.doob 已提交
5638

5639 5640
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
5641

5642 5643
			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
M
Mr.doob 已提交
5644

5645
		}
M
Mr.doob 已提交
5646

5647
	};
5648

5649
	this.setTexture = function ( texture, slot ) {
5650

5651
		if ( texture.needsUpdate ) {
A
alteredq 已提交
5652

5653
			if ( ! texture.__webglInit ) {
M
Mr.doob 已提交
5654

5655
				texture.__webglInit = true;
5656
				texture.__webglTexture = _gl.createTexture();
A
alteredq 已提交
5657

M
Mr.doob 已提交
5658 5659
				_this.info.memory.textures ++;

5660
			}
M
Mr.doob 已提交
5661

5662
			_gl.activeTexture( _gl.TEXTURE0 + slot );
5663 5664
			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );

5665 5666
			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );

5667 5668
			var image = texture.image,
			isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
5669 5670
			glFormat = paramThreeToGL( texture.format ),
			glType = paramThreeToGL( texture.type );
5671

5672 5673
			setTextureParameters( _gl.TEXTURE_2D, texture, isImagePowerOfTwo );

5674
			if ( texture instanceof THREE.DataTexture ) {
5675

5676
				_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
M
Mr.doob 已提交
5677

A
alteredq 已提交
5678
			} else {
M
Mr.doob 已提交
5679

5680
				_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, texture.image );
M
Mr.doob 已提交
5681 5682 5683

			}

5684
			if ( texture.generateMipmaps && isImagePowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
M
Mr.doob 已提交
5685

A
alteredq 已提交
5686
			texture.needsUpdate = false;
5687

5688
			if ( texture.onUpdate ) texture.onUpdate();
5689

5690
		} else {
5691

5692 5693
			_gl.activeTexture( _gl.TEXTURE0 + slot );
			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
5694 5695

		}
M
Mr.doob 已提交
5696

5697
	};
M
Mr.doob 已提交
5698

5699 5700 5701 5702 5703 5704 5705 5706 5707 5708
	function clampToMaxSize ( image, maxSize ) {

		if ( image.width <= maxSize && image.height <= maxSize ) {

			return image;

		}

		// Warning: Scaling through the canvas will only work with images that use
		// premultiplied alpha.
5709

5710 5711 5712 5713 5714 5715 5716
		var maxDimension = Math.max( image.width, image.height );
		var newWidth = Math.floor( image.width * maxSize / maxDimension );
		var newHeight = Math.floor( image.height * maxSize / maxDimension );

		var canvas = document.createElement( 'canvas' );
		canvas.width = newWidth;
		canvas.height = newHeight;
5717

5718
		var ctx = canvas.getContext( "2d" );
5719 5720
		ctx.drawImage( image, 0, 0, image.width, image.height, 0, 0, newWidth, newHeight );

5721 5722 5723 5724
		return canvas;

	}

5725
	function setCubeTexture ( texture, slot ) {
5726

5727
		if ( texture.image.length === 6 ) {
5728 5729 5730

			if ( texture.needsUpdate ) {

A
alteredq 已提交
5731
				if ( ! texture.image.__webglTextureCube ) {
5732 5733

					texture.image.__webglTextureCube = _gl.createTexture();
5734

A
alteredq 已提交
5735
				}
5736

A
alteredq 已提交
5737 5738
				_gl.activeTexture( _gl.TEXTURE0 + slot );
				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
5739

5740
				var cubeImage = [];
5741

A
alteredq 已提交
5742
				for ( var i = 0; i < 6; i ++ ) {
5743

5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755
					if ( _this.autoScaleCubemaps ) {

						cubeImage[ i ] = clampToMaxSize( texture.image[ i ], _maxCubemapSize );

					} else {

						cubeImage[ i ] = texture.image[ i ];

					}

				}

5756 5757
				var image = cubeImage[ 0 ],
				isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
5758 5759
				glFormat = paramThreeToGL( texture.format ),
				glType = paramThreeToGL( texture.type );
5760

5761 5762
				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );

A
alteredq 已提交
5763
				for ( var i = 0; i < 6; i ++ ) {
5764

5765
					_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
5766

A
alteredq 已提交
5767
				}
5768

5769
				if ( texture.generateMipmaps && isImagePowerOfTwo )	_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
5770

A
alteredq 已提交
5771
				texture.needsUpdate = false;
5772

5773
				if ( texture.onUpdate ) texture.onUpdate();
5774

A
alteredq 已提交
5775
			} else {
5776

A
alteredq 已提交
5777 5778
				_gl.activeTexture( _gl.TEXTURE0 + slot );
				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
5779

A
alteredq 已提交
5780
			}
5781

A
alteredq 已提交
5782
		}
5783

A
alteredq 已提交
5784
	};
5785

5786
	function setCubeTextureDynamic ( texture, slot ) {
5787

A
alteredq 已提交
5788 5789
		_gl.activeTexture( _gl.TEXTURE0 + slot );
		_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
5790 5791 5792

	};

5793 5794 5795
	// Render targets

	function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
5796

5797 5798
		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, renderTarget.__webglTexture, 0 );
A
alteredq 已提交
5799

5800
	};
M
Mr.doob 已提交
5801

5802
	function setupRenderBuffer ( renderbuffer, renderTarget  ) {
M
Mikael Emtinger 已提交
5803

5804
		_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
5805

5806
		if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
M
Mr.doob 已提交
5807

5808 5809
			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
A
alteredq 已提交
5810

5811 5812
		/* For some reason this is not working. Defaulting to RGBA4.
		} else if( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
A
alteredq 已提交
5813

5814 5815 5816 5817
			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTarget.width, renderTarget.height );
			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
		*/
		} else if( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
A
alteredq 已提交
5818

5819 5820
			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
A
alteredq 已提交
5821

5822
		} else {
A
alteredq 已提交
5823

5824
			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
A
alteredq 已提交
5825

5826
		}
A
alteredq 已提交
5827

5828
	};
A
alteredq 已提交
5829

A
alteredq 已提交
5830
	this.setRenderTarget = function ( renderTarget ) {
A
alteredq 已提交
5831

5832
		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
A
alteredq 已提交
5833

5834
		if ( renderTarget && ! renderTarget.__webglFramebuffer ) {
A
alteredq 已提交
5835

5836 5837
			if( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
			if( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
A
alteredq 已提交
5838

5839
			renderTarget.__webglTexture = _gl.createTexture();
A
alteredq 已提交
5840

5841
			// Setup texture, create render and frame buffers
5842

5843 5844
			var isTargetPowerOfTwo = isPowerOfTwo( renderTarget.width ) && isPowerOfTwo( renderTarget.height ),
				glFormat = paramThreeToGL( renderTarget.format ),
5845 5846
				glType = paramThreeToGL( renderTarget.type );

5847
			if ( isCube ) {
M
Mr.doob 已提交
5848

5849 5850
				renderTarget.__webglFramebuffer = [];
				renderTarget.__webglRenderbuffer = [];
M
Mikael Emtinger 已提交
5851

5852
				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
5853
				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
A
alteredq 已提交
5854

5855
				for ( var i = 0; i < 6; i ++ ) {
A
alteredq 已提交
5856

5857 5858
					renderTarget.__webglFramebuffer[ i ] = _gl.createFramebuffer();
					renderTarget.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
A
alteredq 已提交
5859

5860
					_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
A
alteredq 已提交
5861

5862 5863
					setupFrameBuffer( renderTarget.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
					setupRenderBuffer( renderTarget.__webglRenderbuffer[ i ], renderTarget );
A
alteredq 已提交
5864

5865
				}
5866

5867 5868
				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );

5869
			} else {
5870

5871 5872
				renderTarget.__webglFramebuffer = _gl.createFramebuffer();
				renderTarget.__webglRenderbuffer = _gl.createRenderbuffer();
5873

5874
				_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
5875
				setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
5876

5877
				_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
5878

5879 5880
				setupFrameBuffer( renderTarget.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
				setupRenderBuffer( renderTarget.__webglRenderbuffer, renderTarget );
5881

5882 5883
				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );

M
Mikael Emtinger 已提交
5884
			}
5885

5886
			// Release everything
M
Mr.doob 已提交
5887

A
alteredq 已提交
5888 5889 5890 5891 5892 5893 5894 5895 5896 5897
			if ( isCube ) {

				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );

			} else {

				_gl.bindTexture( _gl.TEXTURE_2D, null );

			}

5898 5899
			_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null);
M
Mr.doob 已提交
5900

5901 5902
		}

5903
		var framebuffer, width, height, vx, vy;
M
Mr.doob 已提交
5904

5905
		if ( renderTarget ) {
M
Mr.doob 已提交
5906

A
alteredq 已提交
5907 5908
			if ( isCube ) {

5909
				framebuffer = renderTarget.__webglFramebuffer[ renderTarget.activeCubeFace ];
A
alteredq 已提交
5910 5911 5912

			} else {

5913
				framebuffer = renderTarget.__webglFramebuffer;
A
alteredq 已提交
5914 5915 5916

			}

5917 5918
			width = renderTarget.width;
			height = renderTarget.height;
M
Mr.doob 已提交
5919

5920 5921 5922
			vx = 0;
			vy = 0;

5923
		} else {
M
Mr.doob 已提交
5924

5925
			framebuffer = null;
5926

5927 5928
			width = _viewportWidth;
			height = _viewportHeight;
5929

5930 5931
			vx = _viewportX;
			vy = _viewportY;
M
Mr.doob 已提交
5932

5933
		}
M
Mr.doob 已提交
5934

5935
		if ( framebuffer !== _currentFramebuffer ) {
M
Mr.doob 已提交
5936

5937
			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
5938
			_gl.viewport( vx, vy, width, height );
M
Mr.doob 已提交
5939

5940
			_currentFramebuffer = framebuffer;
M
Mr.doob 已提交
5941

5942
		}
5943

A
alteredq 已提交
5944 5945 5946
		_currentWidth = width;
		_currentHeight = height;

5947
	};
M
Mr.doob 已提交
5948

5949
	function updateRenderTargetMipmap ( renderTarget ) {
M
Mr.doob 已提交
5950

A
alteredq 已提交
5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963
		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 已提交
5964 5965

	};
5966

5967
	// Fallback filters for non-power-of-2 textures
5968

5969
	function filterFallback ( f ) {
5970

5971 5972 5973 5974 5975 5976 5977 5978
		switch ( f ) {

			case THREE.NearestFilter:
			case THREE.NearestMipMapNearestFilter:
			case THREE.NearestMipMapLinearFilter: return _gl.NEAREST; break;

			case THREE.LinearFilter:
			case THREE.LinearMipMapNearestFilter:
M
Mr.doob 已提交
5979
			case THREE.LinearMipMapLinearFilter:
M
Mikael Emtinger 已提交
5980
			default:
5981

M
Mikael Emtinger 已提交
5982
				return _gl.LINEAR; break;
5983 5984

		}
5985

5986
	};
5987

5988 5989
	// Map three.js constants to WebGL constants

5990
	function paramThreeToGL ( p ) {
M
Mr.doob 已提交
5991

5992
		switch ( p ) {
M
Mr.doob 已提交
5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005

			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;

6006 6007 6008 6009 6010
			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;
6011
			case THREE.UnsignedIntType: return _gl.UNSIGNED_INT; break;
6012 6013 6014 6015 6016 6017 6018 6019
			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;

6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036
			case THREE.AddEquation: return _gl.FUNC_ADD; break;
			case THREE.SubtractEquation: return _gl.FUNC_SUBTRACT; break;
			case THREE.ReverseSubtractEquation: return _gl.FUNC_REVERSE_SUBTRACT; break;

			case THREE.ZeroFactor: return _gl.ZERO; break;
			case THREE.OneFactor: return _gl.ONE; break;
			case THREE.SrcColorFactor: return _gl.SRC_COLOR; break;
			case THREE.OneMinusSrcColorFactor: return _gl.ONE_MINUS_SRC_COLOR; break;
			case THREE.SrcAlphaFactor: return _gl.SRC_ALPHA; break;
			case THREE.OneMinusSrcAlphaFactor: return _gl.ONE_MINUS_SRC_ALPHA; break;
			case THREE.DstAlphaFactor: return _gl.DST_ALPHA; break;
			case THREE.OneMinusDstAlphaFactor: return _gl.ONE_MINUS_DST_ALPHA; break;

			case THREE.DstColorFactor: return _gl.DST_COLOR; break;
			case THREE.OneMinusDstColorFactor: return _gl.ONE_MINUS_DST_COLOR; break;
			case THREE.SrcAlphaSaturateFactor: return _gl.SRC_ALPHA_SATURATE; break;

6037
		}
M
Mr.doob 已提交
6038

6039
		return 0;
M
Mr.doob 已提交
6040

6041 6042
	};

6043
	// Allocations
6044

6045
	function allocateBones ( object ) {
6046

6047 6048 6049 6050 6051 6052 6053
		// 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)
6054

6055
		var maxBones = 50;
6056

6057
		if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
6058

6059 6060 6061 6062 6063
			maxBones = object.bones.length;

		}

		return maxBones;
6064

6065
	};
6066

6067
	function allocateLights ( lights ) {
6068

6069 6070
		var l, ll, light, dirLights, pointLights, maxDirLights, maxPointLights;
		dirLights = pointLights = maxDirLights = maxPointLights = 0;
6071

6072
		for ( l = 0, ll = lights.length; l < ll; l++ ) {
6073

6074
			light = lights[ l ];
6075

A
alteredq 已提交
6076 6077
			if ( light.onlyShadow ) continue;

6078 6079
			if ( light instanceof THREE.DirectionalLight ) dirLights ++;
			if ( light instanceof THREE.PointLight ) pointLights ++;
6080
			if ( light instanceof THREE.SpotLight ) pointLights ++;
6081

6082
		}
6083

6084
		if ( ( pointLights + dirLights ) <= _maxLights ) {
6085

6086 6087
			maxDirLights = dirLights;
			maxPointLights = pointLights;
6088

6089
		} else {
6090

6091 6092
			maxDirLights = Math.ceil( _maxLights * dirLights / ( pointLights + dirLights ) );
			maxPointLights = _maxLights - maxDirLights;
6093 6094 6095

		}

6096
		return { 'directional' : maxDirLights, 'point' : maxPointLights };
6097 6098

	};
M
Mr.doob 已提交
6099

6100
	function allocateShadows ( lights ) {
6101

M
Mr.doob 已提交
6102
		var l, ll, light, maxShadows = 0;
6103 6104 6105 6106 6107

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

			light = lights[ l ];

A
alteredq 已提交
6108 6109
			if ( ! light.castShadow ) continue;

6110 6111
			if ( light instanceof THREE.SpotLight ) maxShadows ++;
			if ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) maxShadows ++;
6112 6113 6114 6115 6116 6117 6118

		}

		return maxShadows;

	};

6119
	// Initialization
M
Mr.doob 已提交
6120

6121 6122 6123 6124 6125 6126
	function initGL () {

		var gl;

		try {

6127
			if ( ! ( gl = _canvas.getContext( 'experimental-webgl', { alpha: _alpha, premultipliedAlpha: _premultipliedAlpha, antialias: _antialias, stencil: _stencil, preserveDrawingBuffer: _preserveDrawingBuffer } ) ) ) {
6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171

				throw 'Error creating WebGL context.';

			}

			console.log(
				navigator.userAgent + " | " +
				gl.getParameter( gl.VERSION ) + " | " +
				gl.getParameter( gl.VENDOR ) + " | " +
				gl.getParameter( gl.RENDERER ) + " | " +
				gl.getParameter( gl.SHADING_LANGUAGE_VERSION )
			);

		} catch ( error ) {

			console.error( error );

		}

		return gl;

	};

	function setDefaultGLState () {

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

		_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 );

	};

6172 6173
	// default plugins (order is important)

A
alteredq 已提交
6174 6175 6176 6177 6178
	this.shadowMapPlugin = new THREE.ShadowMapPlugin();
	this.addPrePlugin( this.shadowMapPlugin );

	this.addPostPlugin( new THREE.SpritePlugin() );
	this.addPostPlugin( new THREE.LensFlarePlugin() );
6179

6180
};