WebGLRenderer.js 39.7 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 23
	var _canvas = document.createElement( 'canvas' ), _gl, 
	_program, _oldProgram,
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();
M
Mr.doob 已提交
45
	initUbershader( maxLightCount.directional, maxLightCount.point );
M
Mr.doob 已提交
46

47
	//alert( dumpObject( getGLParams() ) );
M
Mr.doob 已提交
48

N
Nicolas Garcia Belmonte 已提交
49 50 51 52 53 54 55 56 57 58 59 60 61 62
	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 );

	};

M
Mr.doob 已提交
63
	this.setupLights = function ( program, scene ) {
64

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

M
Mr.doob 已提交
69
		_gl.uniform1i( program.uniforms.enableLighting, scene.lights.length );
70 71 72 73 74 75 76

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

			light = scene.lights[ l ];

			if ( light instanceof THREE.AmbientLight ) {

77
				ambientLights.push( light );
78

79
			} else if ( light instanceof THREE.DirectionalLight ) {
80

81
				directionalLights.push( light );
82

83 84
			} else if( light instanceof THREE.PointLight ) {

85
				pointLights.push( light );
M
Mr.doob 已提交
86

87 88 89
			}

		}
M
Mr.doob 已提交
90

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

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

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

100
		}
M
Mr.doob 已提交
101

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

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

106
		colors = []; positions = [];
M
Mr.doob 已提交
107

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

110
			light = directionalLights[ l ];
M
Mr.doob 已提交
111

112 113 114 115 116 117 118
			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 已提交
119

120
		}
M
Mr.doob 已提交
121

122 123
		if ( directionalLights.length ) {

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

128
		}
129

130
		// pass point lights as float arrays
M
Mr.doob 已提交
131

132
		colors = []; positions = [];
M
Mr.doob 已提交
133

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

136
			light = pointLights[ l ];
M
Mr.doob 已提交
137

138 139 140 141 142 143 144
			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 已提交
145

146
		}
M
Mr.doob 已提交
147

148 149
		if ( pointLights.length ) {

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

154
		}
M
Mr.doob 已提交
155

156
	};
157
	
158 159
	this.createBuffers = function ( object, mf ) {

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

		faceArray = [],
		lineArray = [],

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

169
		vertexIndex = 0,
170

171
		materialFaceGroup = object.materialFaceGroup[ mf ],
172

173
		needsSmoothNormals = bufferNeedsSmoothNormals ( materialFaceGroup, object );
M
Mr.doob 已提交
174

175 176 177 178 179 180
		for ( f = 0, fl = materialFaceGroup.faces.length; f < fl; f++ ) {

			fi = materialFaceGroup.faces[f];

			face = object.geometry.faces[ fi ];
			vertexNormals = face.vertexNormals;
181
			faceNormal = face.normal;
182 183 184 185 186 187 188 189 190 191 192 193
			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 );

194
				if ( vertexNormals.length == 3 && needsSmoothNormals ) {
195

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

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

					}
201 202 203

				} else {

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

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

					}
209 210 211 212 213

				}

				if ( uv ) {

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

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

				}

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

244
				if ( vertexNormals.length == 4 && needsSmoothNormals ) {
245

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

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

					}
251 252 253

				} else {

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

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

					}
259 260 261 262 263

				}

				if ( uv ) {

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

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

				}

				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 已提交
284

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
			}
		}

		if ( !vertexArray.length ) {

			return;

		}

		materialFaceGroup.__webGLVertexBuffer = _gl.createBuffer();
		_gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLVertexBuffer );
		_gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( vertexArray ), _gl.STATIC_DRAW );

		materialFaceGroup.__webGLNormalBuffer = _gl.createBuffer();
		_gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLNormalBuffer );
		_gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( normalArray ), _gl.STATIC_DRAW );

		materialFaceGroup.__webGLUVBuffer = _gl.createBuffer();
		_gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLUVBuffer );
		_gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( uvArray ), _gl.STATIC_DRAW );

		materialFaceGroup.__webGLFaceBuffer = _gl.createBuffer();
		_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLFaceBuffer );
		_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( faceArray ), _gl.STATIC_DRAW );

		materialFaceGroup.__webGLLineBuffer = _gl.createBuffer();
		_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLLineBuffer );
		_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( lineArray ), _gl.STATIC_DRAW );

		materialFaceGroup.__webGLFaceCount = faceArray.length;
		materialFaceGroup.__webGLLineCount = lineArray.length;

	};

M
Mr.doob 已提交
319
	this.renderBuffer = function ( camera, material, materialFaceGroup ) {
320

321 322
		var mColor, mOpacity, mReflectivity,
			mWireframe, mLineWidth, mBlending,
A
alteredq 已提交
323
			mAmbient, mSpecular, mShininess,
324
			mMap, envMap, mixEnvMap,
M
Mr.doob 已提交
325 326
			mRefractionRatio, useRefract,
			program, u, identifiers;
327
		
M
Mr.doob 已提交
328

M
Mr.doob 已提交
329 330 331 332 333 334
		if ( material instanceof THREE.MeshShaderMaterial ) {
			
			if ( !material.program ) {
				
				material.program = buildProgram( material.fragment_shader, material.vertex_shader );
				
M
Mr.doob 已提交
335
				identifiers = [ 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition' ];
M
Mr.doob 已提交
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
				for( u in material.uniforms ) identifiers.push(u);
				cacheUniformLocations( material.program, identifiers );
				cacheAttributeLocations( material.program );
				
			}
			
			program = material.program;
			
		} else {
			
			program = _program;
			
		}
		
		if( program != _oldProgram ) {
			
			_gl.useProgram( program );
			_oldProgram = program;
			
		}
			
		if ( material instanceof THREE.MeshShaderMaterial ) {
			
			setUniforms( program, material.uniforms );
			this.loadCamera( program, camera );
			this.loadMatrices( program );
			
		} else if ( material instanceof THREE.MeshPhongMaterial ||
A
alteredq 已提交
364 365
			 material instanceof THREE.MeshLambertMaterial ||
			 material instanceof THREE.MeshBasicMaterial ) {
M
Mr.doob 已提交
366

A
alteredq 已提交
367 368
			mColor = material.color;
			mOpacity = material.opacity;
M
Mr.doob 已提交
369

A
alteredq 已提交
370 371
			mWireframe = material.wireframe;
			mLineWidth = material.wireframe_linewidth;
M
Mr.doob 已提交
372

A
alteredq 已提交
373
			mBlending = material.blending;
M
Mr.doob 已提交
374

A
alteredq 已提交
375
			mMap = material.map;
376
			envMap = material.env_map;
377 378 379

			mixEnvMap = material.combine == THREE.Mix;
			mReflectivity = material.reflectivity;
M
Mr.doob 已提交
380

M
Mr.doob 已提交
381
			useRefract = material.env_map && material.env_map.mapping == THREE.RefractionMapping;
382
			mRefractionRatio = material.refraction_ratio;
M
Mr.doob 已提交
383

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

M
Mr.doob 已提交
386 387
			_gl.uniform1i( program.uniforms.mixEnvMap, mixEnvMap );
			_gl.uniform1f( program.uniforms.mReflectivity, mReflectivity );
M
Mr.doob 已提交
388

M
Mr.doob 已提交
389 390
			_gl.uniform1i( program.uniforms.useRefract, useRefract );
			_gl.uniform1f( program.uniforms.mRefractionRatio, mRefractionRatio );
M
Mr.doob 已提交
391

A
alteredq 已提交
392
		}
M
Mr.doob 已提交
393

394
		if ( material instanceof THREE.MeshNormalMaterial ) {
M
Mr.doob 已提交
395

396 397
			mOpacity = material.opacity;
			mBlending = material.blending;
M
Mr.doob 已提交
398

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

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

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

405
			mOpacity = material.opacity;
M
Mr.doob 已提交
406

407 408
			mWireframe = material.wireframe;
			mLineWidth = material.wireframe_linewidth;
M
Mr.doob 已提交
409

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

M
Mr.doob 已提交
412 413 414
			_gl.uniform1f( program.uniforms.m2Near, material.__2near );
			_gl.uniform1f( program.uniforms.mFarPlusNear, material.__farPlusNear );
			_gl.uniform1f( program.uniforms.mFarMinusNear, material.__farMinusNear );
M
Mr.doob 已提交
415

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

418
		} else if ( material instanceof THREE.MeshPhongMaterial ) {
419 420 421

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

M
Mr.doob 已提交
424 425 426
			_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 已提交
427

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

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

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

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

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

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

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

M
Mr.doob 已提交
442 443
			envMap = material.env_map;

M
Mr.doob 已提交
444
		}
445
		
A
alteredq 已提交
446
		if ( mMap ) {
447

448
			if ( !material.map.__webGLTexture && material.map.image.loaded ) {
449

450 451
				material.map.__webGLTexture = _gl.createTexture();
				_gl.bindTexture( _gl.TEXTURE_2D, material.map.__webGLTexture );
452 453 454 455 456
				_gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, material.map.image );
				
				_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, paramThreeToGL( material.map.wrap_s ) );
				_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, paramThreeToGL( material.map.wrap_t ) );
				
457 458 459 460 461 462 463 464
				_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 );
465
			_gl.bindTexture( _gl.TEXTURE_2D, material.map.__webGLTexture );
M
Mr.doob 已提交
466
			_gl.uniform1i( program.uniforms.tMap,  0 );
467

M
Mr.doob 已提交
468
			_gl.uniform1i( program.uniforms.enableMap, 1 );
469

A
alteredq 已提交
470
		} else {
M
Mr.doob 已提交
471

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

474
		}
M
Mr.doob 已提交
475

476
		if ( envMap ) {
M
Mr.doob 已提交
477 478 479 480 481 482 483

			if ( material.env_map && material.env_map instanceof THREE.TextureCube &&
			material.env_map.image.length == 6 ) {

				if ( !material.env_map.image.__webGLTextureCube &&
				!material.env_map.image.__cubeMapInitialized && material.env_map.image.loadCount == 6 ) {

M
Mr.doob 已提交
484
					material.env_map.image.__webGLTextureCube = _gl.createTexture();
M
Mr.doob 已提交
485

M
Mr.doob 已提交
486
					_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, material.env_map.image.__webGLTextureCube );
M
Mr.doob 已提交
487

488 489
					_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 已提交
490

491 492
					_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 已提交
493 494 495 496 497

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

						_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, material.env_map.image[ i ] );

498
					}
M
Mr.doob 已提交
499

500
					_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
M
Mr.doob 已提交
501

502
					_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
M
Mr.doob 已提交
503

M
Mr.doob 已提交
504
					material.env_map.image.__cubeMapInitialized = true;
M
Mr.doob 已提交
505

506
				}
M
Mr.doob 已提交
507

508
				_gl.activeTexture( _gl.TEXTURE1 );
M
Mr.doob 已提交
509
				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, material.env_map.image.__webGLTextureCube );
M
Mr.doob 已提交
510
				_gl.uniform1i( program.uniforms.tCube,  1 );
M
Mr.doob 已提交
511

512
			}
M
Mr.doob 已提交
513

M
Mr.doob 已提交
514
			_gl.uniform1i( program.uniforms.enableCubeMap, 1 );
M
Mr.doob 已提交
515

516
		} else {
M
Mr.doob 已提交
517

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

520
		}
M
Mr.doob 已提交
521

522
		// vertices
M
Mr.doob 已提交
523

524
		_gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLVertexBuffer );
M
Mr.doob 已提交
525
		_gl.vertexAttribPointer( program.position, 3, _gl.FLOAT, false, 0, 0 );
526 527

		// normals
M
Mr.doob 已提交
528

529
		_gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLNormalBuffer );
M
Mr.doob 已提交
530
		_gl.vertexAttribPointer( program.normal, 3, _gl.FLOAT, false, 0, 0 );
531 532

		// uvs
M
Mr.doob 已提交
533

A
alteredq 已提交
534
		if ( mMap ) {
535 536 537

			_gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLUVBuffer );

M
Mr.doob 已提交
538 539
			_gl.enableVertexAttribArray( program.uv );
			_gl.vertexAttribPointer( program.uv, 2, _gl.FLOAT, false, 0, 0 );
540 541 542

		} else {

M
Mr.doob 已提交
543
			_gl.disableVertexAttribArray( program.uv );
544 545 546 547

		}

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

A
alteredq 已提交
549
		if ( ! mWireframe ) {
550 551 552 553 554

			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLFaceBuffer );
			_gl.drawElements( _gl.TRIANGLES, materialFaceGroup.__webGLFaceCount, _gl.UNSIGNED_SHORT, 0 );

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

A
alteredq 已提交
556
		} else {
557

A
alteredq 已提交
558
			_gl.lineWidth( mLineWidth );
559 560 561 562 563 564 565
			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLLineBuffer );
			_gl.drawElements( _gl.LINES, materialFaceGroup.__webGLLineCount, _gl.UNSIGNED_SHORT, 0 );

		}

	};

M
Mr.doob 已提交
566
	this.renderPass = function ( camera, object, materialFaceGroup, blending, transparent ) {
M
Mr.doob 已提交
567

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

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

M
Mr.doob 已提交
572
			meshMaterial = object.material[ m ];
573

M
Mr.doob 已提交
574
			if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
575

M
Mr.doob 已提交
576
				for ( i = 0, l = materialFaceGroup.material.length; i < l; i++ ) {
577

M
Mr.doob 已提交
578
					material = materialFaceGroup.material[ i ];
579
					if ( material && material.blending == blending && ( material.opacity < 1.0 == transparent ) ) {
M
Mr.doob 已提交
580

M
Mr.doob 已提交
581
						this.setBlending( material.blending );
M
Mr.doob 已提交
582
						this.renderBuffer( camera, material, materialFaceGroup );
M
Mr.doob 已提交
583

584 585
					}

M
Mr.doob 已提交
586
				}
587

M
Mr.doob 已提交
588
			} else {
589

M
Mr.doob 已提交
590
				material = meshMaterial;
591
				if ( material && material.blending == blending && ( material.opacity < 1.0 == transparent ) ) {
M
Mr.doob 已提交
592

M
Mr.doob 已提交
593
					this.setBlending( material.blending );
M
Mr.doob 已提交
594 595
					this.renderBuffer( camera, material, materialFaceGroup );
					
596 597 598
				}

			}
599 600

		}
M
Mr.doob 已提交
601

602
	};
M
Mr.doob 已提交
603
	
M
Mr.doob 已提交
604
	this.render = function( scene, camera ) {
M
Mr.doob 已提交
605

M
Mr.doob 已提交
606
		var o, ol;
M
Mr.doob 已提交
607

M
Mr.doob 已提交
608
		this.initWebGLObjects( scene );
M
Mr.doob 已提交
609

610 611 612 613 614 615
		if ( this.autoClear ) {

			this.clear();

		}

616
		camera.autoUpdateMatrix && camera.updateMatrix();
M
Mr.doob 已提交
617
		this.loadCamera( _program, camera );
618

M
Mr.doob 已提交
619
		this.setupLights( _program, scene );
620

M
Mr.doob 已提交
621
		// opaque pass
M
Mr.doob 已提交
622

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

M
Mr.doob 已提交
625
			webGLObject = scene.__webGLObjects[ o ];
626 627
			
			if ( webGLObject.__object.visible ) {
M
Mr.doob 已提交
628

629
				this.setupMatrices( webGLObject.__object, camera );
M
Mr.doob 已提交
630 631
				this.loadMatrices( _program );
				this.renderPass( camera, webGLObject.__object, webGLObject, THREE.NormalBlending, false );
632 633
				
			}
M
Mr.doob 已提交
634

M
Mr.doob 已提交
635
		}
M
Mr.doob 已提交
636

M
Mr.doob 已提交
637
		// transparent pass
M
Mr.doob 已提交
638

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

M
Mr.doob 已提交
641
			webGLObject = scene.__webGLObjects[ o ];
M
Mr.doob 已提交
642

643 644 645
			if ( webGLObject.__object.visible ) {
				
				this.setupMatrices( webGLObject.__object, camera );
M
Mr.doob 已提交
646
				this.loadMatrices( _program );
647

648 649
				// opaque blended materials
				
M
Mr.doob 已提交
650 651
				this.renderPass( camera, webGLObject.__object, webGLObject, THREE.AdditiveBlending, false );
				this.renderPass( camera, webGLObject.__object, webGLObject, THREE.SubtractiveBlending, false );
652 653 654
				
				// transparent blended materials
				
M
Mr.doob 已提交
655 656
				this.renderPass( camera, webGLObject.__object, webGLObject, THREE.AdditiveBlending, true );
				this.renderPass( camera, webGLObject.__object, webGLObject, THREE.SubtractiveBlending, true );
657

658 659
				// transparent normal materials
				
M
Mr.doob 已提交
660
				this.renderPass( camera, webGLObject.__object, webGLObject, THREE.NormalBlending, true );
661 662
				
			}
M
Mr.doob 已提交
663

M
Mr.doob 已提交
664
		}
M
Mr.doob 已提交
665

M
Mr.doob 已提交
666
	};
M
Mr.doob 已提交
667

M
Mr.doob 已提交
668
	this.initWebGLObjects = function( scene ) {
M
Mr.doob 已提交
669

M
Mr.doob 已提交
670
		var o, ol, object, mf, materialFaceGroup;
M
Mr.doob 已提交
671

M
Mr.doob 已提交
672
		if ( !scene.__webGLObjects ) {
M
Mr.doob 已提交
673

M
Mr.doob 已提交
674
			scene.__webGLObjects = [];
M
Mr.doob 已提交
675

M
Mr.doob 已提交
676
		}
M
Mr.doob 已提交
677

678 679 680 681 682 683
		for ( o = 0, ol = scene.objects.length; o < ol; o++ ) {

			object = scene.objects[ o ];

			if ( object instanceof THREE.Mesh ) {

M
Mr.doob 已提交
684
				// create separate VBOs per material
M
Mr.doob 已提交
685

M
Mr.doob 已提交
686 687 688 689 690
				for ( mf in object.materialFaceGroup ) {

					materialFaceGroup = object.materialFaceGroup[ mf ];

					// initialise buffers on the first access
M
Mr.doob 已提交
691

M
Mr.doob 已提交
692 693 694 695 696 697 698
					if( ! materialFaceGroup.__webGLVertexBuffer ) {

						this.createBuffers( object, mf );
						materialFaceGroup.__object = object;
						scene.__webGLObjects.push( materialFaceGroup );

					}
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-- ) {
			
718 719 720
			zobject = scene.__webGLObjects[ o ].__object;
			
			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

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

M
Mr.doob 已提交
1082 1083


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

1087
			"uniform bool enableLighting;",
1088
			"uniform bool useRefract;",
M
Mr.doob 已提交
1089

1090 1091
			"uniform int pointLightNumber;",
			"uniform int directionalLightNumber;",
M
Mr.doob 已提交
1092

1093
			"uniform vec3 ambientLightColor;",
M
Mr.doob 已提交
1094

1095 1096
			maxDirLights ? "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];"     : "",
			maxDirLights ? "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];" : "",
1097

1098 1099
			maxPointLights ? "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];"    : "",
			maxPointLights ? "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];" : "",
1100

1101
			"uniform mat4 viewMatrix;",
1102
			"uniform mat3 normalMatrix;",
1103 1104

			"varying vec3 vNormal;",
1105
			"varying vec2 vUv;",
M
Mr.doob 已提交
1106

1107
			"varying vec3 vLightWeighting;",
1108

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

1111
			"varying vec3 vViewPosition;",
M
Mr.doob 已提交
1112

1113
			"varying vec3 vReflect;",
1114
			"uniform float mRefractionRatio;",
1115

1116
			"void main(void) {",
1117

1118
				// world space
M
Mr.doob 已提交
1119

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

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

1127
				// eye space
M
Mr.doob 已提交
1128

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

1132
				"if ( !enableLighting ) {",
1133

1134
					"vLightWeighting = vec3( 1.0, 1.0, 1.0 );",
1135 1136 1137

				"} else {",

1138
					"vLightWeighting = ambientLightColor;",
M
Mr.doob 已提交
1139

1140
					// directional lights
M
Mr.doob 已提交
1141

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

1148
					// point lights
M
Mr.doob 已提交
1149

1150
					maxPointLights ? "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {" : "",
1151 1152 1153 1154 1155
					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 已提交
1156

1157
				"}",
1158

1159
				"vNormal = transformedNormal;",
1160
				"vUv = uv;",
1161

1162
				"if ( useRefract ) {",
M
Mr.doob 已提交
1163

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

1166
				"} else {",
M
Mr.doob 已提交
1167

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

1170
				"}",
M
Mr.doob 已提交
1171

1172
				"gl_Position = projectionMatrix * mvPosition;",
1173

1174
			"}" ];
M
Mr.doob 已提交
1175

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

1178
	};
M
Mr.doob 已提交
1179

M
Mr.doob 已提交
1180 1181 1182 1183
	function buildProgram( fragment_shader, vertex_shader ) {
		
		var program = _gl.createProgram(),
		
M
Mr.doob 已提交
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
		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 已提交
1196 1197 1198
			"attribute vec3 position;",
			"attribute vec3 normal;",
			"attribute vec2 uv;",
M
Mr.doob 已提交
1199 1200 1201 1202 1203
			""
		].join("\n");
		
		_gl.attachShader( program, getShader( "fragment", prefix_fragment + fragment_shader ) );
		_gl.attachShader( program, getShader( "vertex", prefix_vertex + vertex_shader ) );
M
Mr.doob 已提交
1204 1205
		
		_gl.linkProgram( program );
N
Nicolas Garcia Belmonte 已提交
1206

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

M
Mr.doob 已提交
1209 1210
			alert( "Could not initialise shaders\n"+
					"VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" );
1211
			
N
Nicolas Garcia Belmonte 已提交
1212
		}
M
Mr.doob 已提交
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
		
		program.uniforms = {};
		
		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;
				
				if ( texture instanceof THREE.TextureCube &&
					 texture.image.length == 6 ) {
M
Mr.doob 已提交
1246

M
Mr.doob 已提交
1247 1248
					if ( !texture.image.__webGLTextureCube &&
						 !texture.image.__cubeMapInitialized && texture.image.loadCount == 6 ) {
N
Nicolas Garcia Belmonte 已提交
1249

M
Mr.doob 已提交
1250
						texture.image.__webGLTextureCube = _gl.createTexture();
M
Mr.doob 已提交
1251

M
Mr.doob 已提交
1252
						_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webGLTextureCube );
N
Nicolas Garcia Belmonte 已提交
1253

M
Mr.doob 已提交
1254 1255
						_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 );
1256

M
Mr.doob 已提交
1257 1258
						_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 已提交
1259

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

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

M
Mr.doob 已提交
1264
						}
M
Mr.doob 已提交
1265

M
Mr.doob 已提交
1266
						_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
M
Mr.doob 已提交
1267

M
Mr.doob 已提交
1268
						_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
1269

M
Mr.doob 已提交
1270
						texture.image.__cubeMapInitialized = true;
M
Mr.doob 已提交
1271

M
Mr.doob 已提交
1272
					}
M
Mr.doob 已提交
1273

M
Mr.doob 已提交
1274 1275 1276 1277 1278 1279 1280
					_gl.activeTexture( _gl.TEXTURE1 );
					_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webGLTextureCube );
				
				}
			
			}
			
1281
		}
M
Mr.doob 已提交
1282 1283
		
	};
U
unknown 已提交
1284

M
Mr.doob 已提交
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
	function cacheUniformLocations( program, identifiers ) {
		
		var i, l, id;
		
		for( i = 0, l = identifiers.length; i < l; i++ ) {
			
			id = identifiers[i];
			program.uniforms[id] = _gl.getUniformLocation( program, id );
			
		}
		
	};
	
	function cacheAttributeLocations( program ) {
		
		program.position = _gl.getAttribLocation( program, "position" );
		_gl.enableVertexAttribArray( program.position );
M
Mr.doob 已提交
1302

M
Mr.doob 已提交
1303 1304
		program.normal = _gl.getAttribLocation( program, "normal" );
		_gl.enableVertexAttribArray( program.normal );
M
Mr.doob 已提交
1305

M
Mr.doob 已提交
1306 1307
		program.uv = _gl.getAttribLocation( program, "uv" );
		_gl.enableVertexAttribArray( program.uv );
1308

M
Mr.doob 已提交
1309 1310 1311
	};
	
	function initUbershader( maxDirLights, maxPointLights ) {
M
Mr.doob 已提交
1312

M
Mr.doob 已提交
1313 1314
		var vertex_shader = generateVertexShader( maxDirLights, maxPointLights ),
		    fragment_shader = generateFragmentShader( maxDirLights, maxPointLights );
1315

M
Mr.doob 已提交
1316 1317 1318 1319 1320 1321
		//log ( vertex_shader );
		//log ( fragment_shader );
		
		_program = buildProgram( fragment_shader, vertex_shader );
		
		_gl.useProgram( _program );
M
Mr.doob 已提交
1322

M
Mr.doob 已提交
1323 1324 1325 1326
		// matrices
		// lights
		// material properties (Basic / Lambert / Blinn-Phong shader)
		// material properties (Depth)
M
Mr.doob 已提交
1327

M
Mr.doob 已提交
1328
		cacheUniformLocations( _program, [ 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition',
M
Mr.doob 已提交
1329 1330 1331 1332 1333 1334 1335
										   'enableLighting', 'ambientLightColor',
										   'material', 'mColor', 'mAmbient', 'mSpecular', 'mShininess', 'mOpacity',
										   'enableMap', 'tMap',
										   'enableCubeMap', 'tCube', 'mixEnvMap', 'mReflectivity',
										   'mRefractionRatio', 'useRefract',
										   'm2Near', 'mFarPlusNear', 'mFarMinusNear'
		] );		
1336

M
Mr.doob 已提交
1337

M
Mr.doob 已提交
1338 1339 1340
		if ( maxDirLights ) {
			
			cacheUniformLocations( _program, [ 'directionalLightNumber', 'directionalLightColor', 'directionalLightDirection' ] );			
M
Mr.doob 已提交
1341

M
Mr.doob 已提交
1342
		}
1343

M
Mr.doob 已提交
1344
		if ( maxPointLights ) {
M
Mr.doob 已提交
1345

M
Mr.doob 已提交
1346
			cacheUniformLocations( _program, [ 'pointLightNumber', 'pointLightColor', 'pointLightPosition' ] );			
M
Mr.doob 已提交
1347

M
Mr.doob 已提交
1348
		}
M
Mr.doob 已提交
1349

M
Mr.doob 已提交
1350 1351 1352 1353
		// texture (diffuse map)
		
		_gl.uniform1i( _program.uniforms.enableMap, 0 );
		_gl.uniform1i( _program.uniforms.tMap, 0 );
M
Mr.doob 已提交
1354

M
Mr.doob 已提交
1355
		// cube texture
M
Mr.doob 已提交
1356

M
Mr.doob 已提交
1357 1358 1359
		_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 已提交
1360

M
Mr.doob 已提交
1361 1362 1363 1364
		// refraction
		
		_gl.uniform1i( _program.uniforms.useRefract, 0 );
		
1365
		// vertex arrays
M
Mr.doob 已提交
1366

M
Mr.doob 已提交
1367
		cacheAttributeLocations( _program );	
N
Nicolas Garcia Belmonte 已提交
1368

1369
	};
N
Nicolas Garcia Belmonte 已提交
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395

	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 已提交
1396

1397
	};
N
Nicolas Garcia Belmonte 已提交
1398

1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409
	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;
1410 1411 1412 1413 1414 1415 1416
		
	};

	function materialNeedsSmoothNormals( material ) {

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

1417
	};
1418
	
M
Mr.doob 已提交
1419
	function bufferNeedsSmoothNormals( materialFaceGroup, object ) {
1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431
		
		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 ) {

				for ( i = 0, l = materialFaceGroup.material.length; i < l; i++ ) {

					if ( materialNeedsSmoothNormals( materialFaceGroup.material[ i ] ) ) {
1432

1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 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 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
						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 已提交
1494
	/* DEBUG
1495
	function getGLParams() {
M
Mr.doob 已提交
1496

1497
		var params  = {
M
Mr.doob 已提交
1498

1499 1500
			'MAX_VARYING_VECTORS': _gl.getParameter( _gl.MAX_VARYING_VECTORS ),
			'MAX_VERTEX_ATTRIBS': _gl.getParameter( _gl.MAX_VERTEX_ATTRIBS ),
M
Mr.doob 已提交
1501

1502 1503 1504
			'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 已提交
1505

1506 1507 1508
			'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 已提交
1509

1510 1511
		return params;
	};
M
Mr.doob 已提交
1512

1513
	function dumpObject( obj ) {
M
Mr.doob 已提交
1514

1515 1516
		var p, str = "";
		for ( p in obj ) {
M
Mr.doob 已提交
1517

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

1520
		}
M
Mr.doob 已提交
1521

1522 1523
		return str;
	}
A
alteredq 已提交
1524 1525
	*/

N
Nicolas Garcia Belmonte 已提交
1526
};