WebGLRenderer.js 39.5 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/
N
Nicolas Garcia Belmonte 已提交
5 6
 */

7
THREE.WebGLRenderer = function ( scene ) {
M
Mr.doob 已提交
8

M
Mr.doob 已提交
9 10
	// Currently you can use just up to 4 directional / point lights total.
	// Chrome barfs on shader linking when there are more than 4 lights :(
M
Mr.doob 已提交
11

12
	// The problem comes from shader using too many varying vectors.
M
Mr.doob 已提交
13

14
	// This is not GPU limitation as the same shader works ok in Firefox
M
Mr.doob 已提交
15
	// and Chrome with "--use-gl=desktop" flag.
16
	
M
Mr.doob 已提交
17
	// Difference comes from Chrome on Windows using by default ANGLE,
18
	// thus going DirectX9 route (while FF uses OpenGL).
19 20
	
	// See http://code.google.com/p/chromium/issues/detail?id=63491
M
Mr.doob 已提交
21

M
Mr.doob 已提交
22
	var _canvas = document.createElement( 'canvas' ), _gl, 
23
	_oldProgram, _uberProgram,
24
	_modelViewMatrix = new THREE.Matrix4(), _normalMatrix,
M
Mr.doob 已提交
25 26 27 28 29
	
	_viewMatrixArray = new Float32Array(16), 
	_modelViewMatrixArray = new Float32Array(16), 
	_projectionMatrixArray = new Float32Array(16), 
	_normalMatrixArray = new Float32Array(9),
M
Mr.doob 已提交
30
	_objectMatrixArray = new Float32Array(16),
M
Mr.doob 已提交
31

M
Mr.doob 已提交
32
	// ubershader material constants
33 34 35 36 37
	
	BASIC = 0, LAMBERT = 1, PHONG = 2, DEPTH = 3, NORMAL = 4, CUBE = 5, 

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

39
	maxLightCount = allocateLights( scene, 4 );
M
Mr.doob 已提交
40

N
Nicolas Garcia Belmonte 已提交
41 42 43 44
	this.domElement = _canvas;
	this.autoClear = true;

	initGL();
45 46 47
	
	_uberProgram = initUbershader( maxLightCount.directional, maxLightCount.point );
	_oldProgram = _uberProgram;
M
Mr.doob 已提交
48

49
	//alert( dumpObject( getGLParams() ) );
M
Mr.doob 已提交
50

N
Nicolas Garcia Belmonte 已提交
51 52 53 54 55 56 57 58 59 60 61 62 63 64
	this.setSize = function ( width, height ) {

		_canvas.width = width;
		_canvas.height = height;
		_gl.viewport( 0, 0, _canvas.width, _canvas.height );

	};

	this.clear = function () {

		_gl.clear( _gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT );

	};

65
	this.setupLights = function ( program, lights ) {
66

67
		var l, ll, light, r, g, b,
A
alteredq 已提交
68
			ambientLights = [], pointLights = [], directionalLights = [],
69
			colors = [], positions = [];
70

71
		_gl.uniform1i( program.uniforms.enableLighting, lights.length );
72

73
		for ( l = 0, ll = lights.length; l < ll; l++ ) {
74

75
			light = lights[ l ];
76 77 78

			if ( light instanceof THREE.AmbientLight ) {

79
				ambientLights.push( light );
80

81
			} else if ( light instanceof THREE.DirectionalLight ) {
82

83
				directionalLights.push( light );
84

85 86
			} else if( light instanceof THREE.PointLight ) {

87
				pointLights.push( light );
M
Mr.doob 已提交
88

89 90 91
			}

		}
M
Mr.doob 已提交
92

93 94
		// sum all ambient lights
		r = g = b = 0.0;
M
Mr.doob 已提交
95

96
		for ( l = 0, ll = ambientLights.length; l < ll; l++ ) {
M
Mr.doob 已提交
97

98 99 100
			r += ambientLights[ l ].color.r;
			g += ambientLights[ l ].color.g;
			b += ambientLights[ l ].color.b;
M
Mr.doob 已提交
101

102
		}
M
Mr.doob 已提交
103

M
Mr.doob 已提交
104
		_gl.uniform3f( program.uniforms.ambientLightColor, r, g, b );
105 106

		// pass directional lights as float arrays
M
Mr.doob 已提交
107

108
		colors = []; positions = [];
M
Mr.doob 已提交
109

110
		for ( l = 0, ll = directionalLights.length; l < ll; l++ ) {
M
Mr.doob 已提交
111

112
			light = directionalLights[ l ];
M
Mr.doob 已提交
113

114 115 116 117 118 119 120
			colors.push( light.color.r * light.intensity );
			colors.push( light.color.g * light.intensity );
			colors.push( light.color.b * light.intensity );

			positions.push( light.position.x );
			positions.push( light.position.y );
			positions.push( light.position.z );
M
Mr.doob 已提交
121

122
		}
M
Mr.doob 已提交
123

124 125
		if ( directionalLights.length ) {

M
Mr.doob 已提交
126 127 128
			_gl.uniform1i(  program.uniforms.directionalLightNumber, directionalLights.length );
			_gl.uniform3fv( program.uniforms.directionalLightDirection, positions );
			_gl.uniform3fv( program.uniforms.directionalLightColor, colors );
M
Mr.doob 已提交
129

130
		}
131

132
		// pass point lights as float arrays
M
Mr.doob 已提交
133

134
		colors = []; positions = [];
M
Mr.doob 已提交
135

136
		for ( l = 0, ll = pointLights.length; l < ll; l++ ) {
M
Mr.doob 已提交
137

138
			light = pointLights[ l ];
M
Mr.doob 已提交
139

140 141 142 143 144 145 146
			colors.push( light.color.r * light.intensity );
			colors.push( light.color.g * light.intensity );
			colors.push( light.color.b * light.intensity );

			positions.push( light.position.x );
			positions.push( light.position.y );
			positions.push( light.position.z );
M
Mr.doob 已提交
147

148
		}
M
Mr.doob 已提交
149

150 151
		if ( pointLights.length ) {

M
Mr.doob 已提交
152 153 154
			_gl.uniform1i(  program.uniforms.pointLightNumber, pointLights.length );
			_gl.uniform3fv( program.uniforms.pointLightPosition, positions );
			_gl.uniform3fv( program.uniforms.pointLightColor, colors );
M
Mr.doob 已提交
155

156
		}
M
Mr.doob 已提交
157

158
	};
159
	
M
Mr.doob 已提交
160
	this.createBuffers = function ( object, g ) {
161

162
		var f, fl, fi, face, vertexNormals, normal, uv, v1, v2, v3, v4, m, ml, i,
163 164 165 166 167 168 169 170

		faceArray = [],
		lineArray = [],

		vertexArray = [],
		normalArray = [],
		uvArray = [],

171
		vertexIndex = 0,
172

M
Mr.doob 已提交
173
		geometryChunk = object.geometry.geometryChunks[ g ],
174

M
Mr.doob 已提交
175
		needsSmoothNormals = bufferNeedsSmoothNormals ( geometryChunk, object );
M
Mr.doob 已提交
176

M
Mr.doob 已提交
177
		for ( f = 0, fl = geometryChunk.faces.length; f < fl; f++ ) {
178

M
Mr.doob 已提交
179
			fi = geometryChunk.faces[ f ];
180 181 182

			face = object.geometry.faces[ fi ];
			vertexNormals = face.vertexNormals;
183
			faceNormal = face.normal;
184 185 186 187 188 189 190 191 192 193 194 195
			uv = object.geometry.uvs[ fi ];

			if ( face instanceof THREE.Face3 ) {

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

				vertexArray.push( v1.x, v1.y, v1.z );
				vertexArray.push( v2.x, v2.y, v2.z );
				vertexArray.push( v3.x, v3.y, v3.z );

196
				if ( vertexNormals.length == 3 && needsSmoothNormals ) {
197

M
Mr.doob 已提交
198 199 200 201 202
					for ( i = 0; i < 3; i ++ ) {

						normalArray.push( vertexNormals[ i ].x, vertexNormals[ i ].y, vertexNormals[ i ].z );

					}
203 204 205

				} else {

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

208
						normalArray.push( faceNormal.x, faceNormal.y, faceNormal.z );
M
Mr.doob 已提交
209 210

					}
211 212 213 214 215

				}

				if ( uv ) {

M
Mr.doob 已提交
216 217 218
					for ( i = 0; i < 3; i ++ ) {

						uvArray.push( uv[ i ].u, uv[ i ].v );
219
						
M
Mr.doob 已提交
220
					}
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245

				}

				faceArray.push( vertexIndex, vertexIndex + 1, vertexIndex + 2 );

				// TODO: don't add lines that already exist (faces sharing edge)

				lineArray.push( vertexIndex, vertexIndex + 1 );
				lineArray.push( vertexIndex, vertexIndex + 2 );
				lineArray.push( vertexIndex + 1, vertexIndex + 2 );

				vertexIndex += 3;

			} else if ( face instanceof THREE.Face4 ) {

				v1 = object.geometry.vertices[ face.a ].position;
				v2 = object.geometry.vertices[ face.b ].position;
				v3 = object.geometry.vertices[ face.c ].position;
				v4 = object.geometry.vertices[ face.d ].position;

				vertexArray.push( v1.x, v1.y, v1.z );
				vertexArray.push( v2.x, v2.y, v2.z );
				vertexArray.push( v3.x, v3.y, v3.z );
				vertexArray.push( v4.x, v4.y, v4.z );

246
				if ( vertexNormals.length == 4 && needsSmoothNormals ) {
247

M
Mr.doob 已提交
248 249 250 251 252
					for ( i = 0; i < 4; i ++ ) {

						normalArray.push( vertexNormals[ i ].x, vertexNormals[ i ].y, vertexNormals[ i ].z );

					}
253 254 255

				} else {

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

258
						normalArray.push( faceNormal.x, faceNormal.y, faceNormal.z );
M
Mr.doob 已提交
259 260

					}
261 262 263 264 265

				}

				if ( uv ) {

M
Mr.doob 已提交
266 267 268
					for ( i = 0; i < 4; i ++ ) {

						uvArray.push( uv[ i ].u, uv[ i ].v );
269
						
M
Mr.doob 已提交
270
					}
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285

				}

				faceArray.push( vertexIndex, vertexIndex + 1, vertexIndex + 2 );
				faceArray.push( vertexIndex, vertexIndex + 2, vertexIndex + 3 );

				// TODO: don't add lines that already exist (faces sharing edge)

				lineArray.push( vertexIndex, vertexIndex + 1 );
				lineArray.push( vertexIndex, vertexIndex + 2 );
				lineArray.push( vertexIndex, vertexIndex + 3 );
				lineArray.push( vertexIndex + 1, vertexIndex + 2 );
				lineArray.push( vertexIndex + 2, vertexIndex + 3 );

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

287
			}
M
Mr.doob 已提交
288
			
289 290 291 292 293 294 295 296
		}

		if ( !vertexArray.length ) {

			return;

		}

M
Mr.doob 已提交
297 298
		geometryChunk.__webGLVertexBuffer = _gl.createBuffer();
		_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLVertexBuffer );
299 300
		_gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( vertexArray ), _gl.STATIC_DRAW );

M
Mr.doob 已提交
301 302
		geometryChunk.__webGLNormalBuffer = _gl.createBuffer();
		_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLNormalBuffer );
303 304
		_gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( normalArray ), _gl.STATIC_DRAW );

305 306 307 308 309 310 311 312
		if ( uvArray.length > 0 ) {
			
			geometryChunk.__webGLUVBuffer = _gl.createBuffer();
			_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLUVBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( uvArray ), _gl.STATIC_DRAW );
			
		}
		
M
Mr.doob 已提交
313 314
		geometryChunk.__webGLFaceBuffer = _gl.createBuffer();
		_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLFaceBuffer );
315 316
		_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( faceArray ), _gl.STATIC_DRAW );

M
Mr.doob 已提交
317 318
		geometryChunk.__webGLLineBuffer = _gl.createBuffer();
		_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLLineBuffer );
319 320
		_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( lineArray ), _gl.STATIC_DRAW );

M
Mr.doob 已提交
321 322
		geometryChunk.__webGLFaceCount = faceArray.length;
		geometryChunk.__webGLLineCount = lineArray.length;
323 324 325

	};

326
	this.renderBuffer = function ( camera, lights, material, geometryChunk ) {
327

328 329
		var mColor, mOpacity, mReflectivity,
			mWireframe, mLineWidth, mBlending,
A
alteredq 已提交
330
			mAmbient, mSpecular, mShininess,
331
			mMap, envMap, mixEnvMap,
M
Mr.doob 已提交
332
			mRefractionRatio, useRefract,
333
			program, u, identifiers, attributes;
334
		
M
Mr.doob 已提交
335

M
Mr.doob 已提交
336 337 338 339 340 341
		if ( material instanceof THREE.MeshShaderMaterial ) {
			
			if ( !material.program ) {
				
				material.program = buildProgram( material.fragment_shader, material.vertex_shader );
				
M
Mr.doob 已提交
342
				identifiers = [ 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition' ];
343 344 345 346 347
				for( u in material.uniforms ) {
					
					identifiers.push(u);
					
				}
M
Mr.doob 已提交
348
				cacheUniformLocations( material.program, identifiers );
349
				cacheAttributeLocations( material.program, [ "position", "normal", "uv" ] );
M
Mr.doob 已提交
350 351 352 353 354 355 356
				
			}
			
			program = material.program;
			
		} else {
			
357
			program = _uberProgram;
M
Mr.doob 已提交
358 359 360 361 362 363 364 365 366
			
		}
		
		if( program != _oldProgram ) {
			
			_gl.useProgram( program );
			_oldProgram = program;
			
		}
367 368 369 370
		
		if ( program == _uberProgram ) {

			this.setupLights( program, lights );
M
Mr.doob 已提交
371
			
372 373 374 375 376 377
		}
		
		this.loadCamera( program, camera );
		this.loadMatrices( program );
		
		
M
Mr.doob 已提交
378 379
		if ( material instanceof THREE.MeshShaderMaterial ) {
			
M
Mr.doob 已提交
380 381 382
			mWireframe = material.wireframe;
			mLineWidth = material.wireframe_linewidth;
			
M
Mr.doob 已提交
383 384
			setUniforms( program, material.uniforms );
			
385 386 387
		} 
		
		if ( material instanceof THREE.MeshPhongMaterial ||
A
alteredq 已提交
388 389
			 material instanceof THREE.MeshLambertMaterial ||
			 material instanceof THREE.MeshBasicMaterial ) {
M
Mr.doob 已提交
390

A
alteredq 已提交
391 392
			mColor = material.color;
			mOpacity = material.opacity;
M
Mr.doob 已提交
393

A
alteredq 已提交
394 395
			mWireframe = material.wireframe;
			mLineWidth = material.wireframe_linewidth;
M
Mr.doob 已提交
396

A
alteredq 已提交
397
			mBlending = material.blending;
M
Mr.doob 已提交
398

A
alteredq 已提交
399
			mMap = material.map;
400
			envMap = material.env_map;
401

402
			mixEnvMap = material.combine == THREE.MixOperation;
403
			mReflectivity = material.reflectivity;
M
Mr.doob 已提交
404

405
			useRefract = material.env_map && material.env_map.mapping instanceof THREE.CubeRefractionMapping;
406
			mRefractionRatio = material.refraction_ratio;
M
Mr.doob 已提交
407

M
Mr.doob 已提交
408
			_gl.uniform4f( program.uniforms.mColor,  mColor.r * mOpacity, mColor.g * mOpacity, mColor.b * mOpacity, mOpacity );
M
Mr.doob 已提交
409

M
Mr.doob 已提交
410 411
			_gl.uniform1i( program.uniforms.mixEnvMap, mixEnvMap );
			_gl.uniform1f( program.uniforms.mReflectivity, mReflectivity );
M
Mr.doob 已提交
412

M
Mr.doob 已提交
413 414
			_gl.uniform1i( program.uniforms.useRefract, useRefract );
			_gl.uniform1f( program.uniforms.mRefractionRatio, mRefractionRatio );
M
Mr.doob 已提交
415

A
alteredq 已提交
416
		}
M
Mr.doob 已提交
417

418
		if ( material instanceof THREE.MeshNormalMaterial ) {
M
Mr.doob 已提交
419

420 421
			mOpacity = material.opacity;
			mBlending = material.blending;
M
Mr.doob 已提交
422

M
Mr.doob 已提交
423
			_gl.uniform1f( program.uniforms.mOpacity, mOpacity );
M
Mr.doob 已提交
424

M
Mr.doob 已提交
425
			_gl.uniform1i( program.uniforms.material, NORMAL );
M
Mr.doob 已提交
426

427
		} else if ( material instanceof THREE.MeshDepthMaterial ) {
M
Mr.doob 已提交
428

429
			mOpacity = material.opacity;
M
Mr.doob 已提交
430

431 432
			mWireframe = material.wireframe;
			mLineWidth = material.wireframe_linewidth;
M
Mr.doob 已提交
433

M
Mr.doob 已提交
434
			_gl.uniform1f( program.uniforms.mOpacity, mOpacity );
M
Mr.doob 已提交
435

M
Mr.doob 已提交
436 437 438
			_gl.uniform1f( program.uniforms.m2Near, material.__2near );
			_gl.uniform1f( program.uniforms.mFarPlusNear, material.__farPlusNear );
			_gl.uniform1f( program.uniforms.mFarMinusNear, material.__farMinusNear );
M
Mr.doob 已提交
439

M
Mr.doob 已提交
440
			_gl.uniform1i( program.uniforms.material, DEPTH );
M
Mr.doob 已提交
441

442
		} else if ( material instanceof THREE.MeshPhongMaterial ) {
443 444 445

			mAmbient  = material.ambient;
			mSpecular = material.specular;
A
alteredq 已提交
446
			mShininess = material.shininess;
M
Mr.doob 已提交
447

M
Mr.doob 已提交
448 449 450
			_gl.uniform4f( program.uniforms.mAmbient,  mAmbient.r,  mAmbient.g,  mAmbient.b,  mOpacity );
			_gl.uniform4f( program.uniforms.mSpecular, mSpecular.r, mSpecular.g, mSpecular.b, mOpacity );
			_gl.uniform1f( program.uniforms.mShininess, mShininess );
M
Mr.doob 已提交
451

M
Mr.doob 已提交
452
			_gl.uniform1i( program.uniforms.material, PHONG );
453

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

M
Mr.doob 已提交
456
			_gl.uniform1i( program.uniforms.material, LAMBERT );
457

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

M
Mr.doob 已提交
460
			_gl.uniform1i( program.uniforms.material, BASIC );
461

M
Mr.doob 已提交
462 463
		} else if ( material instanceof THREE.MeshCubeMaterial ) {

M
Mr.doob 已提交
464
			_gl.uniform1i( program.uniforms.material, CUBE );
M
Mr.doob 已提交
465

M
Mr.doob 已提交
466 467
			envMap = material.env_map;

M
Mr.doob 已提交
468
		}
469
		
A
alteredq 已提交
470
		if ( mMap ) {
471

472 473
			setTexture( mMap, 0 );
			
M
Mr.doob 已提交
474 475
			_gl.uniform1i( program.uniforms.tMap,  0 );
			_gl.uniform1i( program.uniforms.enableMap, 1 );
476

A
alteredq 已提交
477
		} else {
M
Mr.doob 已提交
478

M
Mr.doob 已提交
479
			_gl.uniform1i( program.uniforms.enableMap, 0 );
M
Mr.doob 已提交
480

481
		}
M
Mr.doob 已提交
482

483
		if ( envMap ) {
M
Mr.doob 已提交
484

485 486 487
			setCubeTexture( envMap, 1 );
			
			_gl.uniform1i( program.uniforms.tCube, 1 );
M
Mr.doob 已提交
488
			_gl.uniform1i( program.uniforms.enableCubeMap, 1 );
M
Mr.doob 已提交
489

490
		} else {
M
Mr.doob 已提交
491

M
Mr.doob 已提交
492
			_gl.uniform1i( program.uniforms.enableCubeMap, 0 );
M
Mr.doob 已提交
493

494
		}
M
Mr.doob 已提交
495

496 497
		attributes = program.attributes;
		
498
		// vertices
M
Mr.doob 已提交
499

M
Mr.doob 已提交
500
		_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLVertexBuffer );
501
		_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
502 503

		// normals
M
Mr.doob 已提交
504

M
Mr.doob 已提交
505
		_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLNormalBuffer );
506
		_gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
507 508

		// uvs
M
Mr.doob 已提交
509

510 511 512
		if ( attributes.uv >= 0 ) { 
			
			if ( geometryChunk.__webGLUVBuffer ) {
513

514
				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLUVBuffer );
515

516 517
				_gl.enableVertexAttribArray( attributes.uv );
				_gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
518

519
			} else {
520

521 522 523
				_gl.disableVertexAttribArray( attributes.uv );
				
			}
524 525 526 527

		}

		// render triangles
M
Mr.doob 已提交
528

A
alteredq 已提交
529
		if ( ! mWireframe ) {
530

M
Mr.doob 已提交
531 532
			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLFaceBuffer );
			_gl.drawElements( _gl.TRIANGLES, geometryChunk.__webGLFaceCount, _gl.UNSIGNED_SHORT, 0 );
533 534

		// render lines
M
Mr.doob 已提交
535

A
alteredq 已提交
536
		} else {
537

A
alteredq 已提交
538
			_gl.lineWidth( mLineWidth );
M
Mr.doob 已提交
539 540
			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLLineBuffer );
			_gl.drawElements( _gl.LINES, geometryChunk.__webGLLineCount, _gl.UNSIGNED_SHORT, 0 );
541 542 543 544 545

		}

	};

546
	this.renderPass = function ( camera, lights, object, geometryChunk, blending, transparent ) {
M
Mr.doob 已提交
547

M
Mr.doob 已提交
548
		var i, l, m, ml, material, meshMaterial;
M
Mr.doob 已提交
549

M
Mr.doob 已提交
550
		for ( m = 0, ml = object.material.length; m < ml; m++ ) {
551

M
Mr.doob 已提交
552
			meshMaterial = object.material[ m ];
553

M
Mr.doob 已提交
554
			if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
555

M
Mr.doob 已提交
556
				for ( i = 0, l = geometryChunk.material.length; i < l; i++ ) {
557

M
Mr.doob 已提交
558
					material = geometryChunk.material[ i ];
559
					if ( material && material.blending == blending && ( material.opacity < 1.0 == transparent ) ) {
M
Mr.doob 已提交
560

M
Mr.doob 已提交
561
						this.setBlending( material.blending );
562
						this.renderBuffer( camera, lights, material, geometryChunk );
M
Mr.doob 已提交
563

564 565
					}

M
Mr.doob 已提交
566
				}
567

M
Mr.doob 已提交
568
			} else {
569

M
Mr.doob 已提交
570
				material = meshMaterial;
571
				if ( material && material.blending == blending && ( material.opacity < 1.0 == transparent ) ) {
M
Mr.doob 已提交
572

M
Mr.doob 已提交
573
					this.setBlending( material.blending );
574
					this.renderBuffer( camera, lights, material, geometryChunk );
M
Mr.doob 已提交
575
					
576 577 578
				}

			}
579 580

		}
M
Mr.doob 已提交
581

582
	};
M
Mr.doob 已提交
583
	
M
Mr.doob 已提交
584
	this.render = function( scene, camera ) {
M
Mr.doob 已提交
585

586 587
		var o, ol, webGLObject, object, buffer, 
			lights = scene.lights;
M
Mr.doob 已提交
588

M
Mr.doob 已提交
589
		this.initWebGLObjects( scene );
M
Mr.doob 已提交
590

591 592 593 594 595 596
		if ( this.autoClear ) {

			this.clear();

		}

597
		camera.autoUpdateMatrix && camera.updateMatrix();
598
		
M
Mr.doob 已提交
599
		// opaque pass
M
Mr.doob 已提交
600

M
Mr.doob 已提交
601
		for ( o = 0, ol = scene.__webGLObjects.length; o < ol; o++ ) {
M
Mr.doob 已提交
602

M
Mr.doob 已提交
603
			webGLObject = scene.__webGLObjects[ o ];
604
			
M
Mr.doob 已提交
605 606 607 608
			object = webGLObject.object;
			buffer = webGLObject.buffer;
			
			if ( object.visible ) {
M
Mr.doob 已提交
609

M
Mr.doob 已提交
610
				this.setupMatrices( object, camera );
611
				this.renderPass( camera, lights, object, buffer, THREE.NormalBlending, false );
612 613
				
			}
M
Mr.doob 已提交
614

M
Mr.doob 已提交
615
		}
M
Mr.doob 已提交
616

M
Mr.doob 已提交
617
		// transparent pass
M
Mr.doob 已提交
618

M
Mr.doob 已提交
619
		for ( o = 0, ol = scene.__webGLObjects.length; o < ol; o++ ) {
M
Mr.doob 已提交
620

M
Mr.doob 已提交
621
			webGLObject = scene.__webGLObjects[ o ];
M
Mr.doob 已提交
622

M
Mr.doob 已提交
623 624 625 626
			object = webGLObject.object;
			buffer = webGLObject.buffer;
			
			if ( object.visible ) {
627
				
M
Mr.doob 已提交
628
				this.setupMatrices( object, camera );
629

630 631
				// opaque blended materials
				
632 633
				this.renderPass( camera, lights, object, buffer, THREE.AdditiveBlending, false );
				this.renderPass( camera, lights, object, buffer, THREE.SubtractiveBlending, false );
634 635 636
				
				// transparent blended materials
				
637 638
				this.renderPass( camera, lights, object, buffer, THREE.AdditiveBlending, true );
				this.renderPass( camera, lights, object, buffer, THREE.SubtractiveBlending, true );
639

640 641
				// transparent normal materials
				
642
				this.renderPass( camera, lights, object, buffer, THREE.NormalBlending, true );
643 644
				
			}
M
Mr.doob 已提交
645

M
Mr.doob 已提交
646
		}
M
Mr.doob 已提交
647

M
Mr.doob 已提交
648
	};
M
Mr.doob 已提交
649

M
Mr.doob 已提交
650
	this.initWebGLObjects = function( scene ) {
M
Mr.doob 已提交
651

M
Mr.doob 已提交
652
		var o, ol, object, globject, g, geometryChunk, objmap;
M
Mr.doob 已提交
653

M
Mr.doob 已提交
654
		if ( !scene.__webGLObjects ) {
M
Mr.doob 已提交
655

M
Mr.doob 已提交
656
			scene.__webGLObjects = [];
M
Mr.doob 已提交
657
			scene.__webGLObjectsMap = {};
M
Mr.doob 已提交
658

M
Mr.doob 已提交
659
		}
M
Mr.doob 已提交
660

661 662 663 664
		for ( o = 0, ol = scene.objects.length; o < ol; o++ ) {

			object = scene.objects[ o ];

M
Mr.doob 已提交
665 666 667 668 669 670 671 672
			if ( scene.__webGLObjectsMap[ object.id ] == undefined ) {
				
				scene.__webGLObjectsMap[ object.id ] = {};
				
			}
			
			objmap = scene.__webGLObjectsMap[ object.id ];
			
673 674
			if ( object instanceof THREE.Mesh ) {

M
Mr.doob 已提交
675
				// create separate VBOs per geometry chunk
M
Mr.doob 已提交
676

M
Mr.doob 已提交
677
				for ( g in object.geometry.geometryChunks ) {
M
Mr.doob 已提交
678

M
Mr.doob 已提交
679
					geometryChunk = object.geometry.geometryChunks[ g ];
M
Mr.doob 已提交
680

M
Mr.doob 已提交
681
					// initialise VBO on the first access
M
Mr.doob 已提交
682

M
Mr.doob 已提交
683
					if( ! geometryChunk.__webGLVertexBuffer ) {
M
Mr.doob 已提交
684

M
Mr.doob 已提交
685
						this.createBuffers( object, g );
M
Mr.doob 已提交
686 687

					}
M
Mr.doob 已提交
688 689 690 691 692 693 694 695 696 697 698
					
					// create separate wrapper per each use of VBO
					
					if ( objmap[ g ] == undefined ) {
					
						globject = { buffer: geometryChunk, object: object };
						scene.__webGLObjects.push( globject );
					
						objmap[ g ] = 1;
						
					}
M
Mr.doob 已提交
699

M
Mr.doob 已提交
700
				}
701

M
Mr.doob 已提交
702 703
			}/* else if ( object instanceof THREE.Line ) {

M
Mr.doob 已提交
704
			} else if ( object instanceof THREE.Particle ) {
M
Mr.doob 已提交
705 706 707

			}*/

M
Mr.doob 已提交
708
		}
709 710 711 712 713 714

	};

	this.removeObject = function ( scene, object ) {

		var o, ol, zobject;
715 716 717
		
		for ( o = scene.__webGLObjects.length - 1; o >= 0; o-- ) {
			
M
Mr.doob 已提交
718
			zobject = scene.__webGLObjects[ o ].object;
719 720
			
			if ( object == zobject ) {
721 722 723 724 725 726 727

				scene.__webGLObjects.splice( o, 1 );

			}
			
		}
		
M
Mr.doob 已提交
728
	};
M
Mr.doob 已提交
729

M
Mr.doob 已提交
730
	this.setupMatrices = function ( object, camera ) {
731

M
Mr.doob 已提交
732
		object.autoUpdateMatrix && object.updateMatrix();
733

M
Mr.doob 已提交
734
		_modelViewMatrix.multiply( camera.matrix, object.matrix );
735

M
Mr.doob 已提交
736 737 738
		_viewMatrixArray.set( camera.matrix.flatten() );
		_modelViewMatrixArray.set( _modelViewMatrix.flatten() );
		_projectionMatrixArray.set( camera.projectionMatrix.flatten() );
739

M
Mr.doob 已提交
740
		_normalMatrix = THREE.Matrix4.makeInvert3x3( _modelViewMatrix ).transpose();
M
Mr.doob 已提交
741
		_normalMatrixArray.set( _normalMatrix.m );
742

M
Mr.doob 已提交
743
		_objectMatrixArray.set( object.matrix.flatten() );
M
Mr.doob 已提交
744 745 746 747 748 749 750 751 752
	
	};
	
	this.loadMatrices = function ( program ) {
		
		_gl.uniformMatrix4fv( program.uniforms.viewMatrix, false, _viewMatrixArray );
		_gl.uniformMatrix4fv( program.uniforms.modelViewMatrix, false, _modelViewMatrixArray );
		_gl.uniformMatrix4fv( program.uniforms.projectionMatrix, false, _projectionMatrixArray );
		_gl.uniformMatrix3fv( program.uniforms.normalMatrix, false, _normalMatrixArray );
M
Mr.doob 已提交
753
		_gl.uniformMatrix4fv( program.uniforms.objectMatrix, false, _objectMatrixArray );
M
Mr.doob 已提交
754
		
M
Mr.doob 已提交
755
	};
756

M
Mr.doob 已提交
757 758 759 760 761
	this.loadCamera = function( program, camera ) {
		
		_gl.uniform3f( program.uniforms.cameraPosition, camera.position.x, camera.position.y, camera.position.z );
		
	};
M
Mr.doob 已提交
762

M
Mr.doob 已提交
763
	this.setBlending = function( blending ) {
M
Mr.doob 已提交
764

M
Mr.doob 已提交
765
		switch ( blending ) {
766

M
Mr.doob 已提交
767
			case THREE.AdditiveBlending:
768

M
Mr.doob 已提交
769 770
				_gl.blendEquation( _gl.FUNC_ADD );
				_gl.blendFunc( _gl.ONE, _gl.ONE );
M
Mr.doob 已提交
771

M
Mr.doob 已提交
772
				break;
773

M
Mr.doob 已提交
774
			case THREE.SubtractiveBlending:
775

M
Mr.doob 已提交
776 777
				//_gl.blendEquation( _gl.FUNC_SUBTRACT );
				_gl.blendFunc( _gl.DST_COLOR, _gl.ZERO );
M
Mr.doob 已提交
778

M
Mr.doob 已提交
779
				break;
M
Mr.doob 已提交
780

M
Mr.doob 已提交
781
			default:
M
Mr.doob 已提交
782

M
Mr.doob 已提交
783 784
				_gl.blendEquation( _gl.FUNC_ADD );
				_gl.blendFunc( _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA );
M
Mr.doob 已提交
785

M
Mr.doob 已提交
786
				break;
N
Nicolas Garcia Belmonte 已提交
787
		}
M
Mr.doob 已提交
788

N
Nicolas Garcia Belmonte 已提交
789
	};
M
Mr.doob 已提交
790

M
Mr.doob 已提交
791
	this.setFaceCulling = function ( cullFace, frontFace ) {
M
Mr.doob 已提交
792

793
		if ( cullFace ) {
M
Mr.doob 已提交
794

795
			if ( !frontFace || frontFace == "ccw" ) {
M
Mr.doob 已提交
796

797
				_gl.frontFace( _gl.CCW );
M
Mr.doob 已提交
798

799
			} else {
M
Mr.doob 已提交
800

801
				_gl.frontFace( _gl.CW );
M
Mr.doob 已提交
802
				
803
			}
M
Mr.doob 已提交
804

805
			if( cullFace == "back" ) {
M
Mr.doob 已提交
806

807
				_gl.cullFace( _gl.BACK );
M
Mr.doob 已提交
808

809
			} else if( cullFace == "front" ) {
M
Mr.doob 已提交
810

811
				_gl.cullFace( _gl.FRONT );
M
Mr.doob 已提交
812

813
			} else {
M
Mr.doob 已提交
814

815
				_gl.cullFace( _gl.FRONT_AND_BACK );
M
Mr.doob 已提交
816
				
817
			}
M
Mr.doob 已提交
818

819
			_gl.enable( _gl.CULL_FACE );
M
Mr.doob 已提交
820

821
		} else {
M
Mr.doob 已提交
822

823
			_gl.disable( _gl.CULL_FACE );
M
Mr.doob 已提交
824
		
825 826 827
		}

	};
N
Nicolas Garcia Belmonte 已提交
828 829 830 831 832

	function initGL() {

		try {

U
unknown 已提交
833
			_gl = _canvas.getContext( 'experimental-webgl', { antialias: true} );
N
Nicolas Garcia Belmonte 已提交
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849

		} catch(e) { }

		if (!_gl) {

			alert("WebGL not supported");
			throw "cannot create webgl context";

		}

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

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

850 851
		_gl.frontFace( _gl.CCW );
		_gl.cullFace( _gl.BACK );
852
		_gl.enable( _gl.CULL_FACE );
M
Mr.doob 已提交
853

N
Nicolas Garcia Belmonte 已提交
854
		_gl.enable( _gl.BLEND );
U
unknown 已提交
855
		//_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA );
M
Mr.doob 已提交
856
		//_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE ); // cool!
857
		_gl.blendFunc( _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA );
N
Nicolas Garcia Belmonte 已提交
858 859
		_gl.clearColor( 0, 0, 0, 0 );

860
	};
N
Nicolas Garcia Belmonte 已提交
861

862
	function generateFragmentShader( maxDirLights, maxPointLights ) {
M
Mr.doob 已提交
863

864
		var chunks = [
865

866 867
			maxDirLights   ? "#define MAX_DIR_LIGHTS " + maxDirLights     : "",
			maxPointLights ? "#define MAX_POINT_LIGHTS " + maxPointLights : "",
M
Mr.doob 已提交
868

M
Mr.doob 已提交
869
			"uniform int material;", // 0 - Basic, 1 - Lambert, 2 - Phong, 3 - Depth, 4 - Normal, 5 - Cube
870

A
alteredq 已提交
871
			"uniform bool enableMap;",
872
			"uniform bool enableCubeMap;",
873
			"uniform bool mixEnvMap;",
M
Mr.doob 已提交
874

875 876 877
			"uniform samplerCube tCube;",
			"uniform float mReflectivity;",

A
alteredq 已提交
878
			"uniform sampler2D tMap;",
879
			"uniform vec4 mColor;",
880
			"uniform float mOpacity;",
881

882
			"uniform vec4 mAmbient;",
883
			"uniform vec4 mSpecular;",
884
			"uniform float mShininess;",
885

886 887 888
			"uniform float m2Near;",
			"uniform float mFarPlusNear;",
			"uniform float mFarMinusNear;",
M
Mr.doob 已提交
889

890 891
			"uniform int pointLightNumber;",
			"uniform int directionalLightNumber;",
M
Mr.doob 已提交
892

893 894
			maxDirLights ? "uniform mat4 viewMatrix;" : "",
			maxDirLights ? "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];" : "",
M
Mr.doob 已提交
895

896
			"varying vec3 vNormal;",
897
			"varying vec2 vUv;",
M
Mr.doob 已提交
898

899 900
			"varying vec3 vLightWeighting;",

901
			maxPointLights ? "varying vec3 vPointLightVector[ MAX_POINT_LIGHTS ];"     : "",
M
Mr.doob 已提交
902

903
			"varying vec3 vViewPosition;",
M
Mr.doob 已提交
904

905
			"varying vec3 vReflect;",
M
Mr.doob 已提交
906

M
Mr.doob 已提交
907
			"uniform vec3 cameraPosition;",
M
Mr.doob 已提交
908

909
			"void main() {",
910

A
alteredq 已提交
911
				"vec4 mapColor = vec4( 1.0, 1.0, 1.0, 1.0 );",
912
				"vec4 cubeColor = vec4( 1.0, 1.0, 1.0, 1.0 );",
913

914
				// diffuse map
M
Mr.doob 已提交
915

A
alteredq 已提交
916
				"if ( enableMap ) {",
M
Mr.doob 已提交
917

A
alteredq 已提交
918
					"mapColor = texture2D( tMap, vUv );",
M
Mr.doob 已提交
919

A
alteredq 已提交
920
				"}",
921

922
				// cube map
M
Mr.doob 已提交
923

924
				"if ( enableCubeMap ) {",
M
Mr.doob 已提交
925

926 927 928 929
					"cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );",
					// "cubeColor.r = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) ).r;",
					// "cubeColor.g = textureCube( tCube, vec3( -vReflect.x + 0.005, vReflect.yz ) ).g;",
					// "cubeColor.b = textureCube( tCube, vec3( -vReflect.x + 0.01, vReflect.yz ) ).b;",
M
Mr.doob 已提交
930

931 932
				"}",

M
Mr.doob 已提交
933
				// Cube
M
Mr.doob 已提交
934

M
Mr.doob 已提交
935 936 937 938 939
				"if ( material == 5 ) { ",

					"vec3 wPos = cameraPosition - vViewPosition;",
					"gl_FragColor = textureCube( tCube, vec3( -wPos.x, wPos.yz ) );",

940
				// Normals
M
Mr.doob 已提交
941

M
Mr.doob 已提交
942
				"} else if ( material == 4 ) { ",
M
Mr.doob 已提交
943

944
					"gl_FragColor = vec4( 0.5*normalize( vNormal ) + vec3(0.5, 0.5, 0.5), mOpacity );",
M
Mr.doob 已提交
945

946
				// Depth
M
Mr.doob 已提交
947

948
				"} else if ( material == 3 ) { ",
M
Mr.doob 已提交
949 950

					// this breaks shader validation in Chrome 9.0.576.0 dev
951 952 953 954
					// and also latest continuous build Chromium 9.0.583.0 (66089)
					// (curiously it works in Chrome 9.0.576.0 canary build and Firefox 4b7)
					//"float w = 1.0 - ( m2Near / ( mFarPlusNear - gl_FragCoord.z * mFarMinusNear ) );",
					"float w = 0.5;",
M
Mr.doob 已提交
955

956
					"gl_FragColor = vec4( w, w, w, mOpacity );",
M
Mr.doob 已提交
957

958 959
				// Blinn-Phong
				// based on o3d example
M
Mr.doob 已提交
960 961

				"} else if ( material == 2 ) { ",
962 963 964 965

					"vec3 normal = normalize( vNormal );",
					"vec3 viewPosition = normalize( vViewPosition );",

966
					// point lights
M
Mr.doob 已提交
967

968 969 970
					maxPointLights ? "vec4 pointDiffuse  = vec4( 0.0, 0.0, 0.0, 0.0 );" : "",
					maxPointLights ? "vec4 pointSpecular = vec4( 0.0, 0.0, 0.0, 0.0 );" : "",

971
					maxPointLights ? "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {" : "",
M
Mr.doob 已提交
972

973 974
					maxPointLights ? 	"vec3 pointVector = normalize( vPointLightVector[ i ] );" : "",
					maxPointLights ? 	"vec3 pointHalfVector = normalize( vPointLightVector[ i ] + vViewPosition );" : "",
M
Mr.doob 已提交
975

976 977 978 979 980 981
					maxPointLights ? 	"float pointDotNormalHalf = dot( normal, pointHalfVector );" : "",
					maxPointLights ? 	"float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );" : "",

					// Ternary conditional is from the original o3d shader. Here it produces abrupt dark cutoff artefacts.
					// Using just pow works ok in Chrome, but makes different artefact in Firefox 4.
					// Zeroing on negative pointDotNormalHalf seems to work in both.
M
Mr.doob 已提交
982

983 984
					//"float specularCompPoint = dot( normal, pointVector ) < 0.0 || pointDotNormalHalf < 0.0 ? 0.0 : pow( pointDotNormalHalf, mShininess );",
					//"float specularCompPoint = pow( pointDotNormalHalf, mShininess );",
985
					//"float pointSpecularWeight = pointDotNormalHalf < 0.0 ? 0.0 : pow( pointDotNormalHalf, mShininess );",
986

987 988
					// Ternary conditional inside for loop breaks Chrome shader linking.
					// Must do it with if.
989

990 991 992
					maxPointLights ? 	"float pointSpecularWeight = 0.0;" : "",
					maxPointLights ? 	"if ( pointDotNormalHalf >= 0.0 )" : "",
					maxPointLights ? 		"pointSpecularWeight = pow( pointDotNormalHalf, mShininess );" : "",
M
Mr.doob 已提交
993

A
alteredq 已提交
994
					maxPointLights ? 	"pointDiffuse  += mColor * pointDiffuseWeight;" : "",
995
					maxPointLights ? 	"pointSpecular += mSpecular * pointSpecularWeight;" : "",
M
Mr.doob 已提交
996

997
					maxPointLights ? "}" : "",
998

999 1000 1001 1002
					// directional lights

					maxDirLights ? "vec4 dirDiffuse  = vec4( 0.0, 0.0, 0.0, 0.0 );" : "",
					maxDirLights ? "vec4 dirSpecular = vec4( 0.0, 0.0, 0.0, 0.0 );" : "",
M
Mr.doob 已提交
1003

1004
					maxDirLights ? "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {" : "",
1005

1006
					maxDirLights ?		"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );" : "",
1007

1008 1009
					maxDirLights ? 		"vec3 dirVector = normalize( lDirection.xyz );" : "",
					maxDirLights ? 		"vec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );" : "",
M
Mr.doob 已提交
1010

1011
					maxDirLights ? 		"float dirDotNormalHalf = dot( normal, dirHalfVector );" : "",
1012

M
Mr.doob 已提交
1013 1014
					maxDirLights ? 		"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );" : "",

1015 1016 1017
					maxDirLights ? 		"float dirSpecularWeight = 0.0;" : "",
					maxDirLights ? 		"if ( dirDotNormalHalf >= 0.0 )" : "",
					maxDirLights ? 			"dirSpecularWeight = pow( dirDotNormalHalf, mShininess );" : "",
1018

A
alteredq 已提交
1019
					maxDirLights ? 		"dirDiffuse  += mColor * dirDiffuseWeight;" : "",
1020 1021 1022 1023 1024
					maxDirLights ? 		"dirSpecular += mSpecular * dirSpecularWeight;" : "",

					maxDirLights ? "}" : "",

					// all lights contribution summation
M
Mr.doob 已提交
1025

1026 1027 1028 1029 1030
					"vec4 totalLight = mAmbient;",
					maxDirLights   ? "totalLight += dirDiffuse + dirSpecular;" : "",
					maxPointLights ? "totalLight += pointDiffuse + pointSpecular;" : "",

					// looks nicer with weighting
M
Mr.doob 已提交
1031

1032
					"if ( mixEnvMap ) {",
M
Mr.doob 已提交
1033

1034
						"gl_FragColor = vec4( mix( mapColor.rgb * totalLight.xyz * vLightWeighting, cubeColor.rgb, mReflectivity ), mapColor.a );",
M
Mr.doob 已提交
1035

1036
					"} else {",
M
Mr.doob 已提交
1037

1038
						"gl_FragColor = vec4( mapColor.rgb * cubeColor.rgb * totalLight.xyz * vLightWeighting, mapColor.a );",
M
Mr.doob 已提交
1039

1040
					"}",
M
Mr.doob 已提交
1041

A
alteredq 已提交
1042
				// Lambert: diffuse lighting
M
Mr.doob 已提交
1043 1044

				"} else if ( material == 1 ) {",
1045

M
Mr.doob 已提交
1046
					"if ( mixEnvMap ) {",
M
Mr.doob 已提交
1047

1048
						"gl_FragColor = vec4( mix( mColor.rgb * mapColor.rgb * vLightWeighting, cubeColor.rgb, mReflectivity ), mColor.a * mapColor.a );",
M
Mr.doob 已提交
1049

1050
					"} else {",
M
Mr.doob 已提交
1051

1052
						"gl_FragColor = vec4( mColor.rgb * mapColor.rgb * cubeColor.rgb * vLightWeighting, mColor.a * mapColor.a );",
M
Mr.doob 已提交
1053

1054
					"}",
M
Mr.doob 已提交
1055

A
alteredq 已提交
1056
				// Basic: unlit color / texture
M
Mr.doob 已提交
1057 1058

				"} else {",
1059

1060 1061 1062
					"if ( mixEnvMap ) {",

						"gl_FragColor = mix( mColor * mapColor, cubeColor, mReflectivity );",
M
Mr.doob 已提交
1063

1064 1065 1066
					"} else {",

						"gl_FragColor = mColor * mapColor * cubeColor;",
M
Mr.doob 已提交
1067

1068
					"}",
M
Mr.doob 已提交
1069

1070 1071
				"}",

1072
			"}" ];
M
Mr.doob 已提交
1073

1074
		return chunks.join("\n");
M
Mr.doob 已提交
1075

1076
	};
M
Mr.doob 已提交
1077

1078
	function generateVertexShader( maxDirLights, maxPointLights ) {
M
Mr.doob 已提交
1079

1080
		var chunks = [
M
Mr.doob 已提交
1081

1082 1083
			maxDirLights   ? "#define MAX_DIR_LIGHTS " + maxDirLights     : "",
			maxPointLights ? "#define MAX_POINT_LIGHTS " + maxPointLights : "",
M
Mr.doob 已提交
1084

1085
			"uniform bool enableLighting;",
1086
			"uniform bool useRefract;",
M
Mr.doob 已提交
1087

1088 1089
			"uniform int pointLightNumber;",
			"uniform int directionalLightNumber;",
M
Mr.doob 已提交
1090

1091
			"uniform vec3 ambientLightColor;",
M
Mr.doob 已提交
1092

1093 1094
			maxDirLights ? "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];"     : "",
			maxDirLights ? "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];" : "",
1095

1096 1097
			maxPointLights ? "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];"    : "",
			maxPointLights ? "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];" : "",
1098

1099
			"uniform mat4 viewMatrix;",
1100
			"uniform mat3 normalMatrix;",
1101 1102

			"varying vec3 vNormal;",
1103
			"varying vec2 vUv;",
M
Mr.doob 已提交
1104

1105
			"varying vec3 vLightWeighting;",
1106

1107
			maxPointLights ? "varying vec3 vPointLightVector[ MAX_POINT_LIGHTS ];"     : "",
M
Mr.doob 已提交
1108

1109
			"varying vec3 vViewPosition;",
M
Mr.doob 已提交
1110

1111
			"varying vec3 vReflect;",
1112
			"uniform float mRefractionRatio;",
1113

1114
			"void main(void) {",
1115

1116
				// world space
M
Mr.doob 已提交
1117

M
Mr.doob 已提交
1118
				"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
1119
				"vViewPosition = cameraPosition - mPosition.xyz;",
M
Mr.doob 已提交
1120

A
alteredq 已提交
1121
				// this doesn't work on Mac
M
Mr.doob 已提交
1122 1123
				//"vec3 nWorld = mat3(objectMatrix) * normal;",
				"vec3 nWorld = mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal;",
M
Mr.doob 已提交
1124

1125
				// eye space
M
Mr.doob 已提交
1126

1127
				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
1128
				"vec3 transformedNormal = normalize( normalMatrix * normal );",
1129

1130
				"if ( !enableLighting ) {",
1131

1132
					"vLightWeighting = vec3( 1.0, 1.0, 1.0 );",
1133 1134 1135

				"} else {",

1136
					"vLightWeighting = ambientLightColor;",
M
Mr.doob 已提交
1137

1138
					// directional lights
M
Mr.doob 已提交
1139

1140
					maxDirLights ? "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {" : "",
1141
					maxDirLights ?		"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );" : "",
1142
					maxDirLights ?		"float directionalLightWeighting = max( dot( transformedNormal, normalize(lDirection.xyz ) ), 0.0 );" : "",
1143 1144
					maxDirLights ?		"vLightWeighting += directionalLightColor[ i ] * directionalLightWeighting;" : "",
					maxDirLights ? "}" : "",
M
Mr.doob 已提交
1145

1146
					// point lights
M
Mr.doob 已提交
1147

1148
					maxPointLights ? "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {" : "",
1149 1150 1151 1152 1153
					maxPointLights ? 	"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );" : "",
					maxPointLights ? 	"vPointLightVector[ i ] = normalize( lPosition.xyz - mvPosition.xyz );" : "",
					maxPointLights ? 	"float pointLightWeighting = max( dot( transformedNormal, vPointLightVector[ i ] ), 0.0 );" : "",
					maxPointLights ? 	"vLightWeighting += pointLightColor[ i ] * pointLightWeighting;" : "",
					maxPointLights ? "}" : "",
M
Mr.doob 已提交
1154

1155
				"}",
1156

1157
				"vNormal = transformedNormal;",
1158
				"vUv = uv;",
1159

1160
				"if ( useRefract ) {",
M
Mr.doob 已提交
1161

1162
					"vReflect = refract( normalize(mPosition.xyz - cameraPosition), normalize(nWorld.xyz), mRefractionRatio );",
M
Mr.doob 已提交
1163

1164
				"} else {",
M
Mr.doob 已提交
1165

1166
					"vReflect = reflect( normalize(mPosition.xyz - cameraPosition), normalize(nWorld.xyz) );",
M
Mr.doob 已提交
1167

1168
				"}",
M
Mr.doob 已提交
1169

1170
				"gl_Position = projectionMatrix * mvPosition;",
1171

1172
			"}" ];
M
Mr.doob 已提交
1173

1174
		return chunks.join("\n");
M
Mr.doob 已提交
1175

1176
	};
M
Mr.doob 已提交
1177

M
Mr.doob 已提交
1178 1179 1180 1181
	function buildProgram( fragment_shader, vertex_shader ) {
		
		var program = _gl.createProgram(),
		
M
Mr.doob 已提交
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
		prefix_fragment = [
			"#ifdef GL_ES",
			"precision highp float;",
			"#endif",
			""
		].join("\n"),

		prefix_vertex = [
			"uniform mat4 objectMatrix;",
			"uniform mat4 modelViewMatrix;",
			"uniform mat4 projectionMatrix;",
			"uniform vec3 cameraPosition;",
M
Mr.doob 已提交
1194 1195 1196
			"attribute vec3 position;",
			"attribute vec3 normal;",
			"attribute vec2 uv;",
M
Mr.doob 已提交
1197 1198 1199 1200 1201
			""
		].join("\n");
		
		_gl.attachShader( program, getShader( "fragment", prefix_fragment + fragment_shader ) );
		_gl.attachShader( program, getShader( "vertex", prefix_vertex + vertex_shader ) );
M
Mr.doob 已提交
1202 1203
		
		_gl.linkProgram( program );
N
Nicolas Garcia Belmonte 已提交
1204

M
Mr.doob 已提交
1205
		if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) {
N
Nicolas Garcia Belmonte 已提交
1206

M
Mr.doob 已提交
1207 1208
			alert( "Could not initialise shaders\n"+
					"VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" );
1209
			
N
Nicolas Garcia Belmonte 已提交
1210
		}
M
Mr.doob 已提交
1211 1212
		
		program.uniforms = {};
1213
		program.attributes = {};
M
Mr.doob 已提交
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
		
		return program;
		
	};
	
	function setUniforms( program, uniforms ) {
		
		var u, value, type, location, texture;
		
		for( u in uniforms ) {
			
			type = uniforms[u].type;
			value = uniforms[u].value;
			location = program.uniforms[u];
			
			if( type == "i" ) {
				
				_gl.uniform1i( location, value );
				
			} else if( type == "f" ) {
				
				_gl.uniform1f( location, value );
				
			} else if( type == "t" ) {
			
				_gl.uniform1i( location, value );
				
				texture = uniforms[u].texture;
1242
				
1243 1244 1245
				if ( !texture ) continue;
				
				if ( texture.image instanceof Array && texture.image.length == 6 ) {
1246 1247 1248
					
					setCubeTexture( texture, value );
					
1249
				} else {
1250 1251 1252 1253
					
					setTexture( texture, value );
					
				}
1254 1255 1256 1257 1258 1259
			
			}
			
		}
		
	};
M
Mr.doob 已提交
1260

1261 1262
	function setCubeTexture( texture, slot ) {
		
1263
		if ( texture.image.length == 6 ) {
N
Nicolas Garcia Belmonte 已提交
1264

1265 1266
			if ( !texture.image.__webGLTextureCube &&
				 !texture.image.__cubeMapInitialized && texture.image.loadCount == 6 ) {
M
Mr.doob 已提交
1267

1268
				texture.image.__webGLTextureCube = _gl.createTexture();
N
Nicolas Garcia Belmonte 已提交
1269

1270
				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webGLTextureCube );
1271

1272 1273
				_gl.texParameteri( _gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
				_gl.texParameteri( _gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
M
Mr.doob 已提交
1274

1275 1276
				_gl.texParameteri( _gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_MAG_FILTER, _gl.LINEAR );
				_gl.texParameteri( _gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_MIN_FILTER, _gl.LINEAR_MIPMAP_LINEAR );
M
Mr.doob 已提交
1277

1278
				for ( var i = 0; i < 6; ++i ) {
M
Mr.doob 已提交
1279

1280
					_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image[ i ] );
M
Mr.doob 已提交
1281

1282
				}
M
Mr.doob 已提交
1283

1284
				_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
1285

1286
				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
M
Mr.doob 已提交
1287

1288
				texture.image.__cubeMapInitialized = true;
M
Mr.doob 已提交
1289

M
Mr.doob 已提交
1290
			}
1291 1292 1293 1294

			_gl.activeTexture( _gl.TEXTURE0 + slot );
			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webGLTextureCube );
		
1295
		}
M
Mr.doob 已提交
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
	function setTexture( texture, slot ) {
		
		if ( !texture.__webGLTexture && texture.image.loaded ) {

			texture.__webGLTexture = _gl.createTexture();
			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webGLTexture );
			_gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image );
			
			_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrap_s ) );
			_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrap_t ) );
			
			_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.LINEAR );
			_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.LINEAR_MIPMAP_LINEAR );
			_gl.generateMipmap( _gl.TEXTURE_2D );
			_gl.bindTexture( _gl.TEXTURE_2D, null );

		}

		_gl.activeTexture( _gl.TEXTURE0 + slot );
		_gl.bindTexture( _gl.TEXTURE_2D, texture.__webGLTexture );
		
	};
	
M
Mr.doob 已提交
1322 1323 1324 1325 1326 1327
	function cacheUniformLocations( program, identifiers ) {
		
		var i, l, id;
		
		for( i = 0, l = identifiers.length; i < l; i++ ) {
			
1328 1329
			id = identifiers[ i ];
			program.uniforms[ id ] = _gl.getUniformLocation( program, id );
M
Mr.doob 已提交
1330 1331 1332 1333
			
		}
		
	};
M
Mr.doob 已提交
1334

1335
	function cacheAttributeLocations( program, identifiers ) {
1336

1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
		var i, l, id;
		
		for( i = 0, l = identifiers.length; i < l; i++ ) {
			
			id = identifiers[ i ];
			program.attributes[ id ] = _gl.getAttribLocation( program, id );
			
			if ( program.attributes[ id ] >= 0 ) {
			
				_gl.enableVertexAttribArray( program.attributes[ id ] );
				
			}
		
		}
		
M
Mr.doob 已提交
1352 1353 1354
	};
	
	function initUbershader( maxDirLights, maxPointLights ) {
M
Mr.doob 已提交
1355

M
Mr.doob 已提交
1356
		var vertex_shader = generateVertexShader( maxDirLights, maxPointLights ),
1357 1358
			fragment_shader = generateFragmentShader( maxDirLights, maxPointLights ),
			program;
1359

M
Mr.doob 已提交
1360 1361 1362
		//log ( vertex_shader );
		//log ( fragment_shader );
		
1363
		program = buildProgram( fragment_shader, vertex_shader );
M
Mr.doob 已提交
1364
		
1365
		_gl.useProgram( program );
M
Mr.doob 已提交
1366

M
Mr.doob 已提交
1367 1368 1369 1370
		// matrices
		// lights
		// material properties (Basic / Lambert / Blinn-Phong shader)
		// material properties (Depth)
M
Mr.doob 已提交
1371

1372
		cacheUniformLocations( program, [ 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition',
M
Mr.doob 已提交
1373 1374 1375 1376 1377 1378 1379
										   'enableLighting', 'ambientLightColor',
										   'material', 'mColor', 'mAmbient', 'mSpecular', 'mShininess', 'mOpacity',
										   'enableMap', 'tMap',
										   'enableCubeMap', 'tCube', 'mixEnvMap', 'mReflectivity',
										   'mRefractionRatio', 'useRefract',
										   'm2Near', 'mFarPlusNear', 'mFarMinusNear'
		] );		
1380

M
Mr.doob 已提交
1381

M
Mr.doob 已提交
1382 1383
		if ( maxDirLights ) {
			
1384
			cacheUniformLocations( program, [ 'directionalLightNumber', 'directionalLightColor', 'directionalLightDirection' ] );			
M
Mr.doob 已提交
1385

M
Mr.doob 已提交
1386
		}
1387

M
Mr.doob 已提交
1388
		if ( maxPointLights ) {
M
Mr.doob 已提交
1389

1390
			cacheUniformLocations( program, [ 'pointLightNumber', 'pointLightColor', 'pointLightPosition' ] );			
M
Mr.doob 已提交
1391

M
Mr.doob 已提交
1392
		}
M
Mr.doob 已提交
1393

M
Mr.doob 已提交
1394 1395
		// texture (diffuse map)
		
1396 1397
		_gl.uniform1i( program.uniforms.enableMap, 0 );
		_gl.uniform1i( program.uniforms.tMap, 0 );
M
Mr.doob 已提交
1398

M
Mr.doob 已提交
1399
		// cube texture
M
Mr.doob 已提交
1400

1401 1402 1403
		_gl.uniform1i( program.uniforms.enableCubeMap, 0 );
		_gl.uniform1i( program.uniforms.tCube, 1 ); // it's important to use non-zero texture unit, otherwise it doesn't work
		_gl.uniform1i( program.uniforms.mixEnvMap, 0 );
M
Mr.doob 已提交
1404

M
Mr.doob 已提交
1405 1406
		// refraction
		
1407
		_gl.uniform1i( program.uniforms.useRefract, 0 );
M
Mr.doob 已提交
1408
		
1409
		// attribute arrays
M
Mr.doob 已提交
1410

1411 1412 1413
		cacheAttributeLocations( program, [ "position", "normal", "uv" ] );
		
		return program;
N
Nicolas Garcia Belmonte 已提交
1414

1415
	};
N
Nicolas Garcia Belmonte 已提交
1416 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

	function getShader( type, string ) {

		var shader;

		if ( type == "fragment" ) {

			shader = _gl.createShader( _gl.FRAGMENT_SHADER );

		} else if ( type == "vertex" ) {

			shader = _gl.createShader( _gl.VERTEX_SHADER );

		}

		_gl.shaderSource( shader, string );
		_gl.compileShader( shader );

		if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {

			alert( _gl.getShaderInfoLog( shader ) );
			return null;

		}

		return shader;
M
Mr.doob 已提交
1442

1443
	};
N
Nicolas Garcia Belmonte 已提交
1444

1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455
	function paramThreeToGL( p ) {
	
		switch ( p ) {
		
		case THREE.Repeat: 	  	   return _gl.REPEAT; break;
		case THREE.ClampToEdge:    return _gl.CLAMP_TO_EDGE; break;
		case THREE.MirroredRepeat: return _gl.MIRRORED_REPEAT; break;
		
		}
		
		return 0;
1456 1457 1458 1459 1460 1461 1462
		
	};

	function materialNeedsSmoothNormals( material ) {

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

1463
	};
1464
	
M
Mr.doob 已提交
1465
	function bufferNeedsSmoothNormals( geometryChunk, object ) {
1466 1467 1468 1469 1470 1471 1472 1473 1474
		
		var m, ml, i, l, needsSmoothNormals = false;
		
		for ( m = 0, ml = object.material.length; m < ml; m++ ) {

			meshMaterial = object.material[ m ];

			if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {

M
Mr.doob 已提交
1475
				for ( i = 0, l = geometryChunk.material.length; i < l; i++ ) {
1476

M
Mr.doob 已提交
1477
					if ( materialNeedsSmoothNormals( geometryChunk.material[ i ] ) ) {
1478

1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
						needsSmoothNormals = true;
						break;

					}

				}

			} else {

				if ( materialNeedsSmoothNormals( meshMaterial ) ) {

					needsSmoothNormals = true;
					break;

				}

			}

			if ( needsSmoothNormals ) break;

		}
		
		return needsSmoothNormals;
		
	};
	
	function allocateLights( scene, maxLights ) {

		if ( scene ) {

			var l, ll, light, dirLights = pointLights = maxDirLights = maxPointLights = 0;

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

				light = scene.lights[ l ];

				if ( light instanceof THREE.DirectionalLight ) dirLights++;
				if ( light instanceof THREE.PointLight ) pointLights++;

			}

			if ( ( pointLights + dirLights ) <= maxLights ) {

				maxDirLights = dirLights;
				maxPointLights = pointLights;

			} else {

				maxDirLights = Math.ceil( maxLights * dirLights / ( pointLights + dirLights ) );
				maxPointLights = maxLights - maxDirLights;

			}

			return { 'directional' : maxDirLights, 'point' : maxPointLights };

		}

		return { 'directional' : 1, 'point' : maxLights - 1 };

	};
	
A
alteredq 已提交
1540
	/* DEBUG
1541
	function getGLParams() {
M
Mr.doob 已提交
1542

1543
		var params  = {
M
Mr.doob 已提交
1544

1545 1546
			'MAX_VARYING_VECTORS': _gl.getParameter( _gl.MAX_VARYING_VECTORS ),
			'MAX_VERTEX_ATTRIBS': _gl.getParameter( _gl.MAX_VERTEX_ATTRIBS ),
M
Mr.doob 已提交
1547

1548 1549 1550
			'MAX_TEXTURE_IMAGE_UNITS': _gl.getParameter( _gl.MAX_TEXTURE_IMAGE_UNITS ),
			'MAX_VERTEX_TEXTURE_IMAGE_UNITS': _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ),
			'MAX_COMBINED_TEXTURE_IMAGE_UNITS' : _gl.getParameter( _gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ),
M
Mr.doob 已提交
1551

1552 1553 1554
			'MAX_VERTEX_UNIFORM_VECTORS': _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS ),
			'MAX_FRAGMENT_UNIFORM_VECTORS': _gl.getParameter( _gl.MAX_FRAGMENT_UNIFORM_VECTORS )
		}
M
Mr.doob 已提交
1555

1556 1557
		return params;
	};
M
Mr.doob 已提交
1558

1559
	function dumpObject( obj ) {
M
Mr.doob 已提交
1560

1561 1562
		var p, str = "";
		for ( p in obj ) {
M
Mr.doob 已提交
1563

1564
			str += p + ": " + obj[p] + "\n";
M
Mr.doob 已提交
1565

1566
		}
M
Mr.doob 已提交
1567

1568 1569
		return str;
	}
A
alteredq 已提交
1570 1571
	*/

N
Nicolas Garcia Belmonte 已提交
1572
};