WebGLProgram.js 17.4 KB
Newer Older
1 2 3
THREE.WebGLProgram = ( function () {

	var programIdCount = 0;
4

B
Ben Houston 已提交
5
	// TODO: Combine the regex
6 7 8
	var structRe = /^([\w\d_]+)\.([\w\d_]+)$/;
	var arrayStructRe = /^([\w\d_]+)\[(\d+)\]\.([\w\d_]+)$/;
	var arrayRe = /^([\w\d_]+)\[0\]$/;
9

10
	function getEncodingComponents( encoding ) {
11 12 13

		switch ( encoding ) {

14
			case THREE.LinearEncoding:
15
				return ['Linear','( value )'];
16
			case THREE.sRGBEncoding:
17
				return ['sRGB','( value )'];
18
			case THREE.RGBEEncoding:
19
				return ['RGBE','( value )'];
20
			case THREE.RGBM7Encoding:
21
				return ['RGBM','( value, 7.0 )'];
22
			case THREE.RGBM16Encoding:
23
				return ['RGBM','( value, 16.0 )'];
24
			case THREE.RGBDEncoding:
25
				return ['RGBD','( value, 256.0 )'];
26
			case THREE.GammaEncoding:
27
				return ['Gamma','( value, float( GAMMA_FACTOR ) )'];
28
			default:
29 30
				throw new Error( 'unsupported encoding: ' + encoding );

31
		}
32

33 34 35 36 37 38 39 40 41 42 43 44 45
	}

	function getTexelDecodingFunction( functionName, encoding ) {

		var components = getEncodingComponents( encoding );
		return "vec4 " + functionName + "( vec4 value ) { return " + components[0] + "ToLinear" + components[1] + "; }";

	}

	function getTexelEncodingFunction( functionName, encoding ) {

		var components = getEncodingComponents( encoding );
		return "vec4 " + functionName + "( vec4 value ) { return LinearTo" + components[0] + components[1] + "; }";
46

47 48
	}

49 50 51 52 53
	function generateExtensions( extensions, parameters, rendererExtensions ) {

		extensions = extensions || {};

		var chunks = [
54 55
			( extensions.derivatives || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
			( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',
L
Liam Magee 已提交
56
			( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',
57
			( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : '',
58 59 60 61 62 63
		];

		return chunks.filter( filterEmptyLine ).join( '\n' );

	}

M
Mr.doob 已提交
64
	function generateDefines( defines ) {
65

66
		var chunks = [];
67

68 69 70
		for ( var name in defines ) {

			var value = defines[ name ];
71 72 73

			if ( value === false ) continue;

74
			chunks.push( '#define ' + name + ' ' + value );
75 76 77

		}

M
Mr.doob 已提交
78
		return chunks.join( '\n' );
79

M
Mr.doob 已提交
80
	}
81

82 83
	function fetchUniformLocations( gl, program, identifiers ) {

84 85
		var uniforms = {};

86
		var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
87

88 89
		for ( var i = 0; i < n; i ++ ) {

G
gero3 已提交
90
			var info = gl.getActiveUniform( program, i );
91 92 93
			var name = info.name;
			var location = gl.getUniformLocation( program, name );

B
Ben Houston 已提交
94
			//console.log("THREE.WebGLProgram: ACTIVE UNIFORM:", name);
95

M
Mr.doob 已提交
96 97
			var matches = structRe.exec( name );
			if ( matches ) {
98

M
Mr.doob 已提交
99 100
				var structName = matches[ 1 ];
				var structProperty = matches[ 2 ];
101 102

				var uniformsStruct = uniforms[ structName ];
M
Mr.doob 已提交
103 104 105

				if ( ! uniformsStruct ) {

106
					uniformsStruct = uniforms[ structName ] = {};
M
Mr.doob 已提交
107

108
				}
M
Mr.doob 已提交
109

110 111 112
				uniformsStruct[ structProperty ] = location;

				continue;
M
Mr.doob 已提交
113

114 115
			}

M
Mr.doob 已提交
116
			matches = arrayStructRe.exec( name );
117

M
Mr.doob 已提交
118 119 120 121 122
			if ( matches ) {

				var arrayName = matches[ 1 ];
				var arrayIndex = matches[ 2 ];
				var arrayProperty = matches[ 3 ];
123

124
				var uniformsArray = uniforms[ arrayName ];
M
Mr.doob 已提交
125 126 127

				if ( ! uniformsArray ) {

128
					uniformsArray = uniforms[ arrayName ] = [];
M
Mr.doob 已提交
129

130
				}
M
Mr.doob 已提交
131

132
				var uniformsArrayIndex = uniformsArray[ arrayIndex ];
M
Mr.doob 已提交
133 134 135

				if ( ! uniformsArrayIndex ) {

136
					uniformsArrayIndex = uniformsArray[ arrayIndex ] = {};
M
Mr.doob 已提交
137

138
				}
M
Mr.doob 已提交
139

140 141 142
				uniformsArrayIndex[ arrayProperty ] = location;

				continue;
M
Mr.doob 已提交
143

144 145
			}

M
Mr.doob 已提交
146
			matches = arrayRe.exec( name );
147

M
Mr.doob 已提交
148 149 150
			if ( matches ) {

				var arrayName = matches[ 1 ];
151 152 153 154

				uniforms[ arrayName ] = location;

				continue;
M
Mr.doob 已提交
155

156 157 158
			}

			uniforms[ name ] = location;
159 160 161 162 163

		}

		return uniforms;

M
Mr.doob 已提交
164
	}
165

166
	function fetchAttributeLocations( gl, program, identifiers ) {
167 168 169

		var attributes = {};

170
		var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
M
Mr.doob 已提交
171

172 173
		for ( var i = 0; i < n; i ++ ) {

G
gero3 已提交
174
			var info = gl.getActiveAttrib( program, i );
175 176
			var name = info.name;

177
			// console.log("THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:", name, i );
178

179
			attributes[ name ] = gl.getAttribLocation( program, name );
180 181 182 183 184

		}

		return attributes;

M
Mr.doob 已提交
185
	}
186

187
	function filterEmptyLine( string ) {
188

189
		return string !== '';
M
Mr.doob 已提交
190

B
Ben Adams 已提交
191
	}
192

193 194 195 196 197 198 199 200 201 202
	function replaceLightNums( string, parameters ) {

		return string
			.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
			.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
			.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
			.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights );

	}

M
Mr.doob 已提交
203 204 205 206 207 208
	function parseIncludes( string ) {

		var pattern = /#include +<([\w\d.]+)>/g;

		function replace( match, include ) {

209
			var replace = THREE.ShaderChunk[ include ];
210 211 212 213 214 215 216

			if ( replace === undefined ) {

				throw new Error( 'Can not resolve #include <' + include + '>' );

			}

217
			return parseIncludes( replace );
M
Mr.doob 已提交
218 219 220 221 222 223 224

		}

		return string.replace( pattern, replace );

	}

M
Mr.doob 已提交
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
	function unrollLoops( string ) {

		var pattern = /for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;

		function replace( match, start, end, snippet ) {

			var unroll = '';

			for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {

				unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' );

			}

			return unroll;

		}

		return string.replace( pattern, replace );

	}

247
	return function WebGLProgram( renderer, code, material, parameters ) {
248

M
Mr.doob 已提交
249
		var gl = renderer.context;
250

251
		var extensions = material.extensions;
252
		var defines = material.defines;
253 254 255 256

		var vertexShader = material.__webglShader.vertexShader;
		var fragmentShader = material.__webglShader.fragmentShader;

M
Mr.doob 已提交
257
		var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
258 259 260

		if ( parameters.shadowMapType === THREE.PCFShadowMap ) {

M
Mr.doob 已提交
261
			shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
262 263 264

		} else if ( parameters.shadowMapType === THREE.PCFSoftShadowMap ) {

M
Mr.doob 已提交
265
			shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
266 267 268

		}

M
Mr.doob 已提交
269 270 271
		var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
		var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
		var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
272

273
		if ( parameters.envMap ) {
274

275
			switch ( material.envMap.mapping ) {
276

277 278
				case THREE.CubeReflectionMapping:
				case THREE.CubeRefractionMapping:
M
Mr.doob 已提交
279
					envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
280
					break;
281

282 283
				case THREE.EquirectangularReflectionMapping:
				case THREE.EquirectangularRefractionMapping:
M
Mr.doob 已提交
284
					envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
285
					break;
286 287

				case THREE.SphericalReflectionMapping:
M
Mr.doob 已提交
288
					envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
289 290
					break;

291 292
			}

M
Mr.doob 已提交
293 294 295 296
			switch ( material.envMap.mapping ) {

				case THREE.CubeRefractionMapping:
				case THREE.EquirectangularRefractionMapping:
M
Mr.doob 已提交
297
					envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
M
Mr.doob 已提交
298 299 300 301
					break;

			}

302 303 304
			switch ( material.combine ) {

				case THREE.MultiplyOperation:
M
Mr.doob 已提交
305
					envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
306 307 308
					break;

				case THREE.MixOperation:
M
Mr.doob 已提交
309
					envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
310 311 312
					break;

				case THREE.AddOperation:
M
Mr.doob 已提交
313
					envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
314 315
					break;

316
			}
317

318 319
		}

320 321
		var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;

322
		// console.log( 'building new program ' );
323 324 325

		//

326 327
		var customExtensions = generateExtensions( extensions, parameters, renderer.extensions );

328 329 330 331
		var customDefines = generateDefines( defines );

		//

M
Mr.doob 已提交
332
		var program = gl.createProgram();
333

334
		var prefixVertex, prefixFragment;
335

336
		if ( material instanceof THREE.RawShaderMaterial ) {
337

338 339
			prefixVertex = '';
			prefixFragment = '';
340

341
		} else {
342

343
			prefixVertex = [
344

M
Mr.doob 已提交
345 346
				'precision ' + parameters.precision + ' float;',
				'precision ' + parameters.precision + ' int;',
347

348 349
				'#define SHADER_NAME ' + material.__webglShader.name,

350
				customDefines,
351

M
Mr.doob 已提交
352
				parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
353

M
Mr.doob 已提交
354 355
				renderer.gammaInput ? '#define GAMMA_INPUT' : '',
				renderer.gammaOutput ? '#define GAMMA_OUTPUT' : '',
356
				'#define GAMMA_FACTOR ' + gammaFactorDefine,
357

M
Mr.doob 已提交
358
				'#define MAX_BONES ' + parameters.maxBones,
359

M
Mr.doob 已提交
360 361
				parameters.map ? '#define USE_MAP' : '',
				parameters.envMap ? '#define USE_ENVMAP' : '',
362
				parameters.envMap ? '#define ' + envMapModeDefine : '',
M
Mr.doob 已提交
363
				parameters.lightMap ? '#define USE_LIGHTMAP' : '',
364
				parameters.aoMap ? '#define USE_AOMAP' : '',
365
				parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
M
Mr.doob 已提交
366 367
				parameters.bumpMap ? '#define USE_BUMPMAP' : '',
				parameters.normalMap ? '#define USE_NORMALMAP' : '',
368
				parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
M
Mr.doob 已提交
369
				parameters.specularMap ? '#define USE_SPECULARMAP' : '',
W
WestLangley 已提交
370 371
				parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
				parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
M
Mr.doob 已提交
372 373
				parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
				parameters.vertexColors ? '#define USE_COLOR' : '',
374

G
gero3 已提交
375
				parameters.flatShading ? '#define FLAT_SHADED' : '',
376

M
Mr.doob 已提交
377 378
				parameters.skinning ? '#define USE_SKINNING' : '',
				parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
379

M
Mr.doob 已提交
380
				parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
381
				parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
M
Mr.doob 已提交
382 383
				parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
				parameters.flipSided ? '#define FLIP_SIDED' : '',
384

M
Mr.doob 已提交
385 386
				parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
				parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
387
				parameters.pointLightShadows > 0 ? '#define POINT_LIGHT_SHADOWS' : '',
388

M
Mr.doob 已提交
389
				parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
390

M
Mr.doob 已提交
391
				parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
G
gero3 已提交
392
				parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
393 394


M
Mr.doob 已提交
395 396 397 398 399 400
				'uniform mat4 modelMatrix;',
				'uniform mat4 modelViewMatrix;',
				'uniform mat4 projectionMatrix;',
				'uniform mat4 viewMatrix;',
				'uniform mat3 normalMatrix;',
				'uniform vec3 cameraPosition;',
401

M
Mr.doob 已提交
402 403 404
				'attribute vec3 position;',
				'attribute vec3 normal;',
				'attribute vec2 uv;',
405

M
Mr.doob 已提交
406
				'#ifdef USE_COLOR',
407

M
Mr.doob 已提交
408
				'	attribute vec3 color;',
409

M
Mr.doob 已提交
410
				'#endif',
411

M
Mr.doob 已提交
412
				'#ifdef USE_MORPHTARGETS',
413

M
Mr.doob 已提交
414 415 416 417
				'	attribute vec3 morphTarget0;',
				'	attribute vec3 morphTarget1;',
				'	attribute vec3 morphTarget2;',
				'	attribute vec3 morphTarget3;',
418

M
Mr.doob 已提交
419
				'	#ifdef USE_MORPHNORMALS',
420

M
Mr.doob 已提交
421 422 423 424
				'		attribute vec3 morphNormal0;',
				'		attribute vec3 morphNormal1;',
				'		attribute vec3 morphNormal2;',
				'		attribute vec3 morphNormal3;',
425

M
Mr.doob 已提交
426
				'	#else',
427

M
Mr.doob 已提交
428 429 430 431
				'		attribute vec3 morphTarget4;',
				'		attribute vec3 morphTarget5;',
				'		attribute vec3 morphTarget6;',
				'		attribute vec3 morphTarget7;',
432

M
Mr.doob 已提交
433
				'	#endif',
434

M
Mr.doob 已提交
435
				'#endif',
436

M
Mr.doob 已提交
437
				'#ifdef USE_SKINNING',
438

M
Mr.doob 已提交
439 440
				'	attribute vec4 skinIndex;',
				'	attribute vec4 skinWeight;',
441

M
Mr.doob 已提交
442
				'#endif',
443

444
				'\n'
445

446
			].filter( filterEmptyLine ).join( '\n' );
447

448
			prefixFragment = [
449

450
				customExtensions,
W
WestLangley 已提交
451

M
Mr.doob 已提交
452 453
				'precision ' + parameters.precision + ' float;',
				'precision ' + parameters.precision + ' int;',
454

455 456
				'#define SHADER_NAME ' + material.__webglShader.name,

457
				customDefines,
458

G
gero3 已提交
459
				parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '',
460

M
Mr.doob 已提交
461 462
				renderer.gammaInput ? '#define GAMMA_INPUT' : '',
				renderer.gammaOutput ? '#define GAMMA_OUTPUT' : '',
463
				'#define GAMMA_FACTOR ' + gammaFactorDefine,
464

M
Mr.doob 已提交
465 466
				( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
				( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
467

M
Mr.doob 已提交
468 469 470 471 472 473
				parameters.map ? '#define USE_MAP' : '',
				parameters.envMap ? '#define USE_ENVMAP' : '',
				parameters.envMap ? '#define ' + envMapTypeDefine : '',
				parameters.envMap ? '#define ' + envMapModeDefine : '',
				parameters.envMap ? '#define ' + envMapBlendingDefine : '',
				parameters.lightMap ? '#define USE_LIGHTMAP' : '',
474
				parameters.aoMap ? '#define USE_AOMAP' : '',
475
				parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
M
Mr.doob 已提交
476 477 478
				parameters.bumpMap ? '#define USE_BUMPMAP' : '',
				parameters.normalMap ? '#define USE_NORMALMAP' : '',
				parameters.specularMap ? '#define USE_SPECULARMAP' : '',
W
WestLangley 已提交
479 480
				parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
				parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
M
Mr.doob 已提交
481 482
				parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
				parameters.vertexColors ? '#define USE_COLOR' : '',
483

G
gero3 已提交
484
				parameters.flatShading ? '#define FLAT_SHADED' : '',
485

M
Mr.doob 已提交
486 487
				parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
				parameters.flipSided ? '#define FLIP_SIDED' : '',
488

M
Mr.doob 已提交
489 490
				parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
				parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
491
				parameters.pointLightShadows > 0 ? '#define POINT_LIGHT_SHADOWS' : '',
492

M
Mr.doob 已提交
493
				parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
G
gero3 已提交
494
				parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
495

496
				parameters.envMap && renderer.extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '',
W
WestLangley 已提交
497

M
Mr.doob 已提交
498 499
				'uniform mat4 viewMatrix;',
				'uniform vec3 cameraPosition;',
500

501
				( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? THREE.ShaderChunk[ 'encodings' ] : '',
502

503 504 505
				parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
				parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
				parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
506
				parameters.outputEncoding ? getTexelEncodingFunction( "linearToOutputTexel", parameters.outputEncoding ) : '',
507

508 509 510
				'\n'

			].filter( filterEmptyLine ).join( '\n' );
511 512

		}
513

M
Mr.doob 已提交
514
		vertexShader = parseIncludes( vertexShader, parameters );
515
		vertexShader = replaceLightNums( vertexShader, parameters );
M
Mr.doob 已提交
516 517

		fragmentShader = parseIncludes( fragmentShader, parameters );
518 519
		fragmentShader = replaceLightNums( fragmentShader, parameters );

520
		if ( material instanceof THREE.ShaderMaterial === false ) {
M
Mr.doob 已提交
521

522 523 524 525
			vertexShader = unrollLoops( vertexShader );
			fragmentShader = unrollLoops( fragmentShader );

		}
526

527 528 529
		var vertexGlsl = prefixVertex + vertexShader;
		var fragmentGlsl = prefixFragment + fragmentShader;

M
Mr.doob 已提交
530 531 532
		// console.log( '*VERTEX*', vertexGlsl );
		// console.log( '*FRAGMENT*', fragmentGlsl );

533 534
		var glVertexShader = THREE.WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
		var glFragmentShader = THREE.WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
535

M
Mr.doob 已提交
536 537
		gl.attachShader( program, glVertexShader );
		gl.attachShader( program, glFragmentShader );
538

539 540 541
		// Force a particular attribute to index 0.

		if ( material.index0AttributeName !== undefined ) {
542

543
			gl.bindAttribLocation( program, 0, material.index0AttributeName );
544

545 546 547 548
		} else if ( parameters.morphTargets === true ) {

			// programs with morphTargets displace position out of attribute 0
			gl.bindAttribLocation( program, 0, 'position' );
549 550 551

		}

M
Mr.doob 已提交
552
		gl.linkProgram( program );
553

554 555 556 557 558 559
		var programLog = gl.getProgramInfoLog( program );
		var vertexLog = gl.getShaderInfoLog( glVertexShader );
		var fragmentLog = gl.getShaderInfoLog( glFragmentShader );

		var runnable = true;
		var haveDiagnostics = true;
560

M
Mr.doob 已提交
561 562 563
		// console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) );
		// console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) );

M
Mr.doob 已提交
564
		if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
565

566
			runnable = false;
567

568 569 570 571 572
			console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog );

		} else if ( programLog !== '' ) {

			console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
573

574
		} else if ( vertexLog === '' || fragmentLog === '' ) {
575

576
			haveDiagnostics = false;
577 578 579

		}

580
		if ( haveDiagnostics ) {
581

582
			this.diagnostics = {
583

584 585
				runnable: runnable,
				material: material,
586

587
				programLog: programLog,
588

589
				vertexShader: {
590

591 592
					log: vertexLog,
					prefix: prefixVertex
593

594
				},
595

596
				fragmentShader: {
597

598 599
					log: fragmentLog,
					prefix: prefixFragment
600

601 602 603
				}

			};
604

605
		}
606

M
Mr.doob 已提交
607 608
		// clean up

M
Mr.doob 已提交
609 610
		gl.deleteShader( glVertexShader );
		gl.deleteShader( glFragmentShader );
M
Mr.doob 已提交
611

612
		// set up caching for uniform locations
613

614
		var cachedUniforms;
615

616
		this.getUniforms = function() {
617

618 619 620 621 622 623 624
			if ( cachedUniforms === undefined ) {

				cachedUniforms = fetchUniformLocations( gl, program );

			}

			return cachedUniforms;
625

626
		};
627

628
		// set up caching for attribute locations
629

630
		var cachedAttributes;
631

632
		this.getAttributes = function() {
633

634 635 636 637 638 639 640
			if ( cachedAttributes === undefined ) {

				cachedAttributes = fetchAttributeLocations( gl, program );

			}

			return cachedAttributes;
641

642
		};
643

644 645 646 647 648 649 650 651 652
		// free resource

		this.destroy = function() {

			gl.deleteProgram( program );
			this.program = undefined;

		};

653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
		// DEPRECATED

		Object.defineProperties( this, {

			uniforms: {
				get: function() {

					console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' );
					return this.getUniforms();

				}
			},

			attributes: {
				get: function() {

					console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' );
					return this.getAttributes();

				}
			}
M
Mr.doob 已提交
674

G
gero3 已提交
675
		} );
676 677


678 679 680 681 682 683
		//

		this.id = programIdCount ++;
		this.code = code;
		this.usedTimes = 1;
		this.program = program;
M
Mr.doob 已提交
684 685
		this.vertexShader = glVertexShader;
		this.fragmentShader = glFragmentShader;
686 687 688 689 690

		return this;

	};

691
} )();