WebGLProgram.js 17.7 KB
Newer Older
1 2 3 4
/**
 * @author mrdoob / http://mrdoob.com/
 */

R
Rich Harris 已提交
5 6 7 8 9
import { WebGLUniforms } from './WebGLUniforms';
import { WebGLShader } from './WebGLShader';
import { ShaderChunk } from '../shaders/ShaderChunk';
import { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, EquirectangularRefractionMapping, CubeRefractionMapping, SphericalReflectionMapping, EquirectangularReflectionMapping, CubeUVRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, CineonToneMapping, Uncharted2ToneMapping, ReinhardToneMapping, LinearToneMapping, GammaEncoding, RGBDEncoding, RGBM16Encoding, RGBM7Encoding, RGBEEncoding, sRGBEncoding, LinearEncoding } from '../../constants';

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
var programIdCount = 0;

function getEncodingComponents( encoding ) {

	switch ( encoding ) {

		case LinearEncoding:
			return [ 'Linear','( value )' ];
		case sRGBEncoding:
			return [ 'sRGB','( value )' ];
		case RGBEEncoding:
			return [ 'RGBE','( value )' ];
		case RGBM7Encoding:
			return [ 'RGBM','( value, 7.0 )' ];
		case RGBM16Encoding:
			return [ 'RGBM','( value, 16.0 )' ];
		case RGBDEncoding:
			return [ 'RGBD','( value, 256.0 )' ];
		case GammaEncoding:
			return [ 'Gamma','( value, float( GAMMA_FACTOR ) )' ];
		default:
			throw new Error( 'unsupported encoding: ' + encoding );
32

33 34
	}

35
}
36

37
function getTexelDecodingFunction( functionName, encoding ) {
38

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

42
}
43

44
function getTexelEncodingFunction( functionName, encoding ) {
45

46 47
	var components = getEncodingComponents( encoding );
	return "vec4 " + functionName + "( vec4 value ) { return LinearTo" + components[ 0 ] + components[ 1 ] + "; }";
M
Mr.doob 已提交
48

49
}
B
Ben Houston 已提交
50

51
function getToneMappingFunction( functionName, toneMapping ) {
M
Mr.doob 已提交
52

53
	var toneMappingName;
M
Mr.doob 已提交
54

55
	switch ( toneMapping ) {
M
Mr.doob 已提交
56

57 58 59
		case LinearToneMapping:
			toneMappingName = "Linear";
			break;
M
Mr.doob 已提交
60

61 62 63
		case ReinhardToneMapping:
			toneMappingName = "Reinhard";
			break;
M
Mr.doob 已提交
64

65 66 67
		case Uncharted2ToneMapping:
			toneMappingName = "Uncharted2";
			break;
B
Ben Houston 已提交
68

69 70 71
		case CineonToneMapping:
			toneMappingName = "OptimizedCineon";
			break;
M
Mr.doob 已提交
72

73 74
		default:
			throw new Error( 'unsupported toneMapping: ' + toneMapping );
B
Ben Houston 已提交
75 76 77

	}

78
	return "vec3 " + functionName + "( vec3 color ) { return " + toneMappingName + "ToneMapping( color ); }";
79

80
}
81

82
function generateExtensions( extensions, parameters, rendererExtensions ) {
83

84
	extensions = extensions || {};
85

86 87 88 89
	var chunks = [
		( extensions.derivatives || parameters.envMapCubeUV || 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' : '',
		( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',
90
		( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''
91
	];
92

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

95
}
96

97
function generateDefines( defines ) {
98

99
	var chunks = [];
100

101
	for ( var name in defines ) {
102

103
		var value = defines[ name ];
104

105
		if ( value === false ) continue;
106

107
		chunks.push( '#define ' + name + ' ' + value );
108

M
Mr.doob 已提交
109
	}
110

111
	return chunks.join( '\n' );
112

113
}
114

115
function fetchAttributeLocations( gl, program, identifiers ) {
M
Mr.doob 已提交
116

117
	var attributes = {};
118

119
	var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
120

121
	for ( var i = 0; i < n; i ++ ) {
122

123 124
		var info = gl.getActiveAttrib( program, i );
		var name = info.name;
125

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

128
		attributes[ name ] = gl.getAttribLocation( program, name );
129

M
Mr.doob 已提交
130
	}
131

132
	return attributes;
133

134
}
M
Mr.doob 已提交
135

136
function filterEmptyLine( string ) {
137

138
	return string !== '';
139

140
}
141

142
function replaceLightNums( string, parameters ) {
143

144 145 146
	return string
		.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
		.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
147
		.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
148 149
		.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
		.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights );
M
Mr.doob 已提交
150

151
}
M
Mr.doob 已提交
152

153
function parseIncludes( string ) {
M
Mr.doob 已提交
154

155
	var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm;
156

157
	function replace( match, include ) {
158

159
		var replace = ShaderChunk[ include ];
160

161
		if ( replace === undefined ) {
162

163
			throw new Error( 'Can not resolve #include <' + include + '>' );
M
Mr.doob 已提交
164 165 166

		}

167
		return parseIncludes( replace );
M
Mr.doob 已提交
168 169 170

	}

171
	return string.replace( pattern, replace );
M
Mr.doob 已提交
172

173
}
M
Mr.doob 已提交
174

175
function unrollLoops( string ) {
M
Mr.doob 已提交
176

177
	var pattern = /for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
M
Mr.doob 已提交
178

179
	function replace( match, start, end, snippet ) {
M
Mr.doob 已提交
180

181
		var unroll = '';
M
Mr.doob 已提交
182

183
		for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {
M
Mr.doob 已提交
184

185
			unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' );
M
Mr.doob 已提交
186 187 188

		}

189
		return unroll;
M
Mr.doob 已提交
190 191 192

	}

193
	return string.replace( pattern, replace );
194

195
}
196

197
function WebGLProgram( renderer, code, material, shader, parameters ) {
198

199
	var gl = renderer.context;
200

201 202
	var extensions = material.extensions;
	var defines = material.defines;
203

204 205
	var vertexShader = shader.vertexShader;
	var fragmentShader = shader.fragmentShader;
206

207
	var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
208

209
	if ( parameters.shadowMapType === PCFShadowMap ) {
210

211
		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
212

213
	} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
214

215
		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
216

217
	}
218

219 220 221
	var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
	var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
	var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
222

223
	if ( parameters.envMap ) {
B
Ben Houston 已提交
224

225
		switch ( material.envMap.mapping ) {
226

227 228 229 230
			case CubeReflectionMapping:
			case CubeRefractionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
				break;
231

232 233 234 235
			case CubeUVReflectionMapping:
			case CubeUVRefractionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
				break;
236

237 238 239 240
			case EquirectangularReflectionMapping:
			case EquirectangularRefractionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
				break;
M
Mr.doob 已提交
241

242 243 244
			case SphericalReflectionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
				break;
M
Mr.doob 已提交
245

246
		}
M
Mr.doob 已提交
247

248
		switch ( material.envMap.mapping ) {
249

250 251 252 253
			case CubeRefractionMapping:
			case EquirectangularRefractionMapping:
				envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
				break;
254

255
		}
256

257
		switch ( material.combine ) {
258

259 260 261
			case MultiplyOperation:
				envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
				break;
262

263 264 265
			case MixOperation:
				envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
				break;
266

267 268 269
			case AddOperation:
				envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
				break;
270

271
		}
272

273
	}
274

275
	var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
276

277
	// console.log( 'building new program ' );
278

279
	//
280

281
	var customExtensions = generateExtensions( extensions, parameters, renderer.extensions );
282

283
	var customDefines = generateDefines( defines );
284

285
	//
286

287
	var program = gl.createProgram();
288

289
	var prefixVertex, prefixFragment;
290

M
Mr.doob 已提交
291
	if ( material.isRawShaderMaterial ) {
292

293
		prefixVertex = [
294

295 296 297
			customDefines,

			'\n'
298

299
		].filter( filterEmptyLine ).join( '\n' );
300

301
		prefixFragment = [
302

303 304 305 306
			customExtensions,
			customDefines,

			'\n'
307

308
		].filter( filterEmptyLine ).join( '\n' );
309

310
	} else {
311

312
		prefixVertex = [
313

314 315
			'precision ' + parameters.precision + ' float;',
			'precision ' + parameters.precision + ' int;',
316

317
			'#define SHADER_NAME ' + shader.name,
318

319
			customDefines,
320

321
			parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
322

323
			'#define GAMMA_FACTOR ' + gammaFactorDefine,
324

325
			'#define MAX_BONES ' + parameters.maxBones,
326 327 328
			( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
			( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',

329 330 331 332 333 334 335 336 337 338 339 340 341 342
			parameters.map ? '#define USE_MAP' : '',
			parameters.envMap ? '#define USE_ENVMAP' : '',
			parameters.envMap ? '#define ' + envMapModeDefine : '',
			parameters.lightMap ? '#define USE_LIGHTMAP' : '',
			parameters.aoMap ? '#define USE_AOMAP' : '',
			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
			parameters.normalMap ? '#define USE_NORMALMAP' : '',
			parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
			parameters.vertexColors ? '#define USE_COLOR' : '',
343

344
			parameters.flatShading ? '#define FLAT_SHADED' : '',
T
tschw 已提交
345

346 347
			parameters.skinning ? '#define USE_SKINNING' : '',
			parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
348

349 350 351 352
			parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
			parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
			parameters.flipSided ? '#define FLIP_SIDED' : '',
353

354
			'#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes,
355

356 357
			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
358

359
			parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
360

361 362
			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
			parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
363

364 365 366 367 368 369
			'uniform mat4 modelMatrix;',
			'uniform mat4 modelViewMatrix;',
			'uniform mat4 projectionMatrix;',
			'uniform mat4 viewMatrix;',
			'uniform mat3 normalMatrix;',
			'uniform vec3 cameraPosition;',
370

371 372 373
			'attribute vec3 position;',
			'attribute vec3 normal;',
			'attribute vec2 uv;',
374

375
			'#ifdef USE_COLOR',
376

377
			'	attribute vec3 color;',
378

379
			'#endif',
380

381
			'#ifdef USE_MORPHTARGETS',
382

383 384 385 386
			'	attribute vec3 morphTarget0;',
			'	attribute vec3 morphTarget1;',
			'	attribute vec3 morphTarget2;',
			'	attribute vec3 morphTarget3;',
387

388
			'	#ifdef USE_MORPHNORMALS',
389

390 391 392 393
			'		attribute vec3 morphNormal0;',
			'		attribute vec3 morphNormal1;',
			'		attribute vec3 morphNormal2;',
			'		attribute vec3 morphNormal3;',
394

395
			'	#else',
396

397 398 399 400
			'		attribute vec3 morphTarget4;',
			'		attribute vec3 morphTarget5;',
			'		attribute vec3 morphTarget6;',
			'		attribute vec3 morphTarget7;',
401

402
			'	#endif',
403

404
			'#endif',
405

406
			'#ifdef USE_SKINNING',
407

408 409
			'	attribute vec4 skinIndex;',
			'	attribute vec4 skinWeight;',
410

411
			'#endif',
412

413
			'\n'
W
WestLangley 已提交
414

415
		].filter( filterEmptyLine ).join( '\n' );
416

417
		prefixFragment = [
418

419
			customExtensions,
420

421 422
			'precision ' + parameters.precision + ' float;',
			'precision ' + parameters.precision + ' int;',
423

424
			'#define SHADER_NAME ' + shader.name,
425

426
			customDefines,
427

428
			parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '',
429

430
			'#define GAMMA_FACTOR ' + gammaFactorDefine,
431

432 433
			( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
			( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
434

435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
			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' : '',
			parameters.aoMap ? '#define USE_AOMAP' : '',
			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
			parameters.normalMap ? '#define USE_NORMALMAP' : '',
			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
			parameters.vertexColors ? '#define USE_COLOR' : '',
T
tschw 已提交
450

T
Takahiro 已提交
451
			parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
T
Takahiro 已提交
452

453
			parameters.flatShading ? '#define FLAT_SHADED' : '',
454

455 456
			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
			parameters.flipSided ? '#define FLIP_SIDED' : '',
457

458
			'#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes,
459
			'#define UNION_CLIPPING_PLANES ' + (parameters.numClippingPlanes - parameters.numClipIntersection),
460

461 462
			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
463

464
			parameters.premultipliedAlpha ? "#define PREMULTIPLIED_ALPHA" : '',
W
WestLangley 已提交
465

466
			parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : '',
467

468 469
			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
			parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
470

471
			parameters.envMap && renderer.extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '',
472

473 474
			'uniform mat4 viewMatrix;',
			'uniform vec3 cameraPosition;',
475

476 477 478
			( parameters.toneMapping !== NoToneMapping ) ? "#define TONE_MAPPING" : '',
			( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '',  // this code is required here because it is used by the toneMapping() function defined below
			( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( "toneMapping", parameters.toneMapping ) : '',
479

480
			parameters.dithering ? '#define DITHERING' : '',
481

482 483 484 485 486
			( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below
			parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
			parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
			parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
			parameters.outputEncoding ? getTexelEncodingFunction( "linearToOutputTexel", parameters.outputEncoding ) : '',
487

488
			parameters.depthPacking ? "#define DEPTH_PACKING " + material.depthPacking : '',
489

490
			'\n'
M
Mr.doob 已提交
491

492
		].filter( filterEmptyLine ).join( '\n' );
493

494
	}
M
Mr.doob 已提交
495

M
Mr.doob 已提交
496
	vertexShader = parseIncludes( vertexShader );
497
	vertexShader = replaceLightNums( vertexShader, parameters );
498

M
Mr.doob 已提交
499
	fragmentShader = parseIncludes( fragmentShader );
500
	fragmentShader = replaceLightNums( fragmentShader, parameters );
501

M
Mr.doob 已提交
502
	if ( ! material.isShaderMaterial ) {
503

504 505
		vertexShader = unrollLoops( vertexShader );
		fragmentShader = unrollLoops( fragmentShader );
M
Mr.doob 已提交
506

507
	}
508

509 510
	var vertexGlsl = prefixVertex + vertexShader;
	var fragmentGlsl = prefixFragment + fragmentShader;
511

512 513
	// console.log( '*VERTEX*', vertexGlsl );
	// console.log( '*FRAGMENT*', fragmentGlsl );
514

515 516
	var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
	var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
517

518 519
	gl.attachShader( program, glVertexShader );
	gl.attachShader( program, glFragmentShader );
520

521
	// Force a particular attribute to index 0.
522

523
	if ( material.index0AttributeName !== undefined ) {
524

525
		gl.bindAttribLocation( program, 0, material.index0AttributeName );
526

527
	} else if ( parameters.morphTargets === true ) {
528

529 530
		// programs with morphTargets displace position out of attribute 0
		gl.bindAttribLocation( program, 0, 'position' );
531

532
	}
533

534
	gl.linkProgram( program );
M
Mr.doob 已提交
535

536 537 538
	var programLog = gl.getProgramInfoLog( program );
	var vertexLog = gl.getShaderInfoLog( glVertexShader );
	var fragmentLog = gl.getShaderInfoLog( glFragmentShader );
539

540 541
	var runnable = true;
	var haveDiagnostics = true;
542

543 544
	// console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) );
	// console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) );
545

546
	if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
547

548
		runnable = false;
549

550
		console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog );
551

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

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

556
	} else if ( vertexLog === '' || fragmentLog === '' ) {
557

558
		haveDiagnostics = false;
559

560
	}
561

562
	if ( haveDiagnostics ) {
563

564
		this.diagnostics = {
565

566 567
			runnable: runnable,
			material: material,
568

569
			programLog: programLog,
570

571
			vertexShader: {
572

573 574
				log: vertexLog,
				prefix: prefixVertex
575

576
			},
577

578
			fragmentShader: {
579

580 581
				log: fragmentLog,
				prefix: prefixFragment
582

583
			}
M
Mr.doob 已提交
584

585
		};
M
Mr.doob 已提交
586

587
	}
588

589
	// clean up
590

591 592
	gl.deleteShader( glVertexShader );
	gl.deleteShader( glFragmentShader );
593

594
	// set up caching for uniform locations
595

596
	var cachedUniforms;
597

598
	this.getUniforms = function() {
599

600
		if ( cachedUniforms === undefined ) {
601

602
			cachedUniforms =
603
				new WebGLUniforms( gl, program, renderer );
604

605
		}
606

607
		return cachedUniforms;
608

609
	};
610

611
	// set up caching for attribute locations
612

613
	var cachedAttributes;
614

615
	this.getAttributes = function() {
616

617
		if ( cachedAttributes === undefined ) {
618

619
			cachedAttributes = fetchAttributeLocations( gl, program );
620

621
		}
622

623
		return cachedAttributes;
624

625
	};
626

627
	// free resource
628

629
	this.destroy = function() {
630

631 632
		gl.deleteProgram( program );
		this.program = undefined;
633

634
	};
635

636
	// DEPRECATED
637

638
	Object.defineProperties( this, {
639

640 641
		uniforms: {
			get: function() {
642

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

			}
647
		},
M
Mr.doob 已提交
648

649 650
		attributes: {
			get: function() {
651

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

655 656
			}
		}
657

658
	} );
659 660


661 662 663 664 665 666 667 668
	//

	this.id = programIdCount ++;
	this.code = code;
	this.usedTimes = 1;
	this.program = program;
	this.vertexShader = glVertexShader;
	this.fragmentShader = glFragmentShader;
669

670
	return this;
R
Rich Harris 已提交
671

672
}
R
Rich Harris 已提交
673

674
export { WebGLProgram };