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

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

10 11 12 13 14 15 16
var programIdCount = 0;

function getEncodingComponents( encoding ) {

	switch ( encoding ) {

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

33 34
	}

35
}
36

37
function getTexelDecodingFunction( functionName, encoding ) {
38

39
	var components = getEncodingComponents( encoding );
M
Mr.doob 已提交
40
	return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';
41

42
}
43

44
function getTexelEncodingFunction( functionName, encoding ) {
45

46
	var components = getEncodingComponents( encoding );
M
Mr.doob 已提交
47
	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
		case LinearToneMapping:
M
Mr.doob 已提交
58
			toneMappingName = 'Linear';
59
			break;
M
Mr.doob 已提交
60

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

65
		case Uncharted2ToneMapping:
M
Mr.doob 已提交
66
			toneMappingName = 'Uncharted2';
67
			break;
B
Ben Houston 已提交
68

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

C
ChenX 已提交
73 74
		case ACESFilmicToneMapping:
			toneMappingName = 'ACESFilmic';
C
ChenX 已提交
75 76
			break;

77 78
		default:
			throw new Error( 'unsupported toneMapping: ' + toneMapping );
B
Ben Houston 已提交
79 80 81

	}

M
Mr.doob 已提交
82
	return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
83

84
}
85

86
function generateExtensions( extensions, parameters, rendererExtensions ) {
87

88
	extensions = extensions || {};
89

90
	var chunks = [
W
WestLangley 已提交
91
		( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || ( parameters.normalMap && ! parameters.objectSpaceNormalMap ) || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
92 93
		( 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' : '',
94
		( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''
95
	];
96

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

99
}
100

101
function generateDefines( defines ) {
102

103
	var chunks = [];
104

105
	for ( var name in defines ) {
106

107
		var value = defines[ name ];
108

109
		if ( value === false ) continue;
110

111
		chunks.push( '#define ' + name + ' ' + value );
112

M
Mr.doob 已提交
113
	}
114

115
	return chunks.join( '\n' );
116

117
}
118

M
Mugen87 已提交
119
function fetchAttributeLocations( gl, program ) {
M
Mr.doob 已提交
120

121
	var attributes = {};
122

123
	var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
124

125
	for ( var i = 0; i < n; i ++ ) {
126

127 128
		var info = gl.getActiveAttrib( program, i );
		var name = info.name;
129

M
Mugen87 已提交
130
		// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
131

132
		attributes[ name ] = gl.getAttribLocation( program, name );
133

M
Mr.doob 已提交
134
	}
135

136
	return attributes;
137

138
}
M
Mr.doob 已提交
139

140
function filterEmptyLine( string ) {
141

142
	return string !== '';
143

144
}
145

146
function replaceLightNums( string, parameters ) {
147

148 149 150
	return string
		.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
		.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
151
		.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
152 153
		.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
		.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights );
M
Mr.doob 已提交
154

155
}
M
Mr.doob 已提交
156

157 158 159 160 161 162 163 164
function replaceClippingPlaneNums( string, parameters ) {

	return string
		.replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
		.replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );

}

165
function parseIncludes( string ) {
M
Mr.doob 已提交
166

M
Mathieu Brédif 已提交
167
	var pattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
168

169
	function replace( match, include ) {
170

171
		var replace = ShaderChunk[ include ];
172

173
		if ( replace === undefined ) {
174

175
			throw new Error( 'Can not resolve #include <' + include + '>' );
M
Mr.doob 已提交
176 177 178

		}

179
		return parseIncludes( replace );
M
Mr.doob 已提交
180 181 182

	}

183
	return string.replace( pattern, replace );
M
Mr.doob 已提交
184

185
}
M
Mr.doob 已提交
186

187
function unrollLoops( string ) {
M
Mr.doob 已提交
188

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

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

193
		var unroll = '';
M
Mr.doob 已提交
194

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

197
			unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' );
M
Mr.doob 已提交
198 199 200

		}

201
		return unroll;
M
Mr.doob 已提交
202 203 204

	}

205
	return string.replace( pattern, replace );
206

207
}
208

209
function WebGLProgram( renderer, extensions, code, material, shader, parameters, capabilities, textures ) {
210

211
	var gl = renderer.context;
212

213
	var defines = material.defines;
214

215 216
	var vertexShader = shader.vertexShader;
	var fragmentShader = shader.fragmentShader;
217

218
	var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
219

220
	if ( parameters.shadowMapType === PCFShadowMap ) {
221

222
		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
223

224
	} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
225

226
		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
227

228
	}
229

230 231 232
	var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
	var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
	var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
233

234
	if ( parameters.envMap ) {
B
Ben Houston 已提交
235

236
		switch ( material.envMap.mapping ) {
237

238 239 240 241
			case CubeReflectionMapping:
			case CubeRefractionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
				break;
242

243 244 245 246
			case CubeUVReflectionMapping:
			case CubeUVRefractionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
				break;
247

248 249 250 251
			case EquirectangularReflectionMapping:
			case EquirectangularRefractionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
				break;
M
Mr.doob 已提交
252

253 254 255
			case SphericalReflectionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
				break;
M
Mr.doob 已提交
256

257
		}
M
Mr.doob 已提交
258

259
		switch ( material.envMap.mapping ) {
260

261 262 263 264
			case CubeRefractionMapping:
			case EquirectangularRefractionMapping:
				envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
				break;
265

266
		}
267

268
		switch ( material.combine ) {
269

270 271 272
			case MultiplyOperation:
				envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
				break;
273

274 275 276
			case MixOperation:
				envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
				break;
277

278 279 280
			case AddOperation:
				envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
				break;
281

282
		}
283

284
	}
285

286
	var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
287

288
	// console.log( 'building new program ' );
289

290
	//
291

T
Takahiro 已提交
292
	var customExtensions = capabilities.isWebGL2 ? '' : generateExtensions( material.extensions, parameters, extensions );
293

294
	var customDefines = generateDefines( defines );
295

296
	//
297

298
	var program = gl.createProgram();
299

300
	var prefixVertex, prefixFragment;
301

M
Mr.doob 已提交
302
	if ( material.isRawShaderMaterial ) {
303

304
		prefixVertex = [
305

306
			customDefines
307

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

310 311 312 313 314 315
		if ( prefixVertex.length > 0 ) {

			prefixVertex += '\n';

		}

316
		prefixFragment = [
317

318
			customExtensions,
319
			customDefines
320

321
		].filter( filterEmptyLine ).join( '\n' );
322

323 324 325 326 327 328
		if ( prefixFragment.length > 0 ) {

			prefixFragment += '\n';

		}

329
	} else {
330

331
		prefixVertex = [
332

333 334
			'precision ' + parameters.precision + ' float;',
			'precision ' + parameters.precision + ' int;',
335

336
			'#define SHADER_NAME ' + shader.name,
337

338
			customDefines,
339

340
			parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
341

342
			'#define GAMMA_FACTOR ' + gammaFactorDefine,
343

344
			'#define MAX_BONES ' + parameters.maxBones,
345 346 347
			( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
			( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',

348 349 350 351 352 353 354 355
			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' : '',
W
WestLangley 已提交
356
			( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
357 358 359 360 361
			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' : '',
D
Don McCurdy 已提交
362 363

			parameters.vertexTangents ? '#define USE_TANGENT' : '',
364
			parameters.vertexColors ? '#define USE_COLOR' : '',
365

366
			parameters.flatShading ? '#define FLAT_SHADED' : '',
T
tschw 已提交
367

368 369
			parameters.skinning ? '#define USE_SKINNING' : '',
			parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
370

371 372 373 374
			parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
			parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
			parameters.flipSided ? '#define FLIP_SIDED' : '',
375

376 377
			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
378

379
			parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
380

381
			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
T
Takahiro 已提交
382
			parameters.logarithmicDepthBuffer && ( capabilities.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
383

384 385 386 387 388 389
			'uniform mat4 modelMatrix;',
			'uniform mat4 modelViewMatrix;',
			'uniform mat4 projectionMatrix;',
			'uniform mat4 viewMatrix;',
			'uniform mat3 normalMatrix;',
			'uniform vec3 cameraPosition;',
390

391 392 393
			'attribute vec3 position;',
			'attribute vec3 normal;',
			'attribute vec2 uv;',
394

D
Don McCurdy 已提交
395 396 397 398 399 400
			'#ifdef USE_TANGENT',

			'	attribute vec4 tangent;',

			'#endif',

401
			'#ifdef USE_COLOR',
402

403
			'	attribute vec3 color;',
404

405
			'#endif',
406

407
			'#ifdef USE_MORPHTARGETS',
408

409 410 411 412
			'	attribute vec3 morphTarget0;',
			'	attribute vec3 morphTarget1;',
			'	attribute vec3 morphTarget2;',
			'	attribute vec3 morphTarget3;',
413

414
			'	#ifdef USE_MORPHNORMALS',
415

416 417 418 419
			'		attribute vec3 morphNormal0;',
			'		attribute vec3 morphNormal1;',
			'		attribute vec3 morphNormal2;',
			'		attribute vec3 morphNormal3;',
420

421
			'	#else',
422

423 424 425 426
			'		attribute vec3 morphTarget4;',
			'		attribute vec3 morphTarget5;',
			'		attribute vec3 morphTarget6;',
			'		attribute vec3 morphTarget7;',
427

428
			'	#endif',
429

430
			'#endif',
431

432
			'#ifdef USE_SKINNING',
433

434 435
			'	attribute vec4 skinIndex;',
			'	attribute vec4 skinWeight;',
436

437
			'#endif',
438

439
			'\n'
W
WestLangley 已提交
440

441
		].filter( filterEmptyLine ).join( '\n' );
442

443
		prefixFragment = [
444

445
			customExtensions,
446

447 448
			'precision ' + parameters.precision + ' float;',
			'precision ' + parameters.precision + ' int;',
449

450
			'#define SHADER_NAME ' + shader.name,
451

452
			customDefines,
453

454
			parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer
455

456
			'#define GAMMA_FACTOR ' + gammaFactorDefine,
457

458 459
			( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
			( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
460

461
			parameters.map ? '#define USE_MAP' : '',
462
			parameters.matcap ? '#define USE_MATCAP' : '',
463 464 465 466 467 468 469 470 471
			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' : '',
W
WestLangley 已提交
472
			( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
473 474 475 476
			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
D
Don McCurdy 已提交
477 478

			parameters.vertexTangents ? '#define USE_TANGENT' : '',
479
			parameters.vertexColors ? '#define USE_COLOR' : '',
T
tschw 已提交
480

T
Takahiro 已提交
481
			parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
T
Takahiro 已提交
482

483
			parameters.flatShading ? '#define FLAT_SHADED' : '',
484

485 486
			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
			parameters.flipSided ? '#define FLIP_SIDED' : '',
487

488 489
			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
490

M
Mr.doob 已提交
491
			parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
W
WestLangley 已提交
492

M
Mr.doob 已提交
493
			parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
494

495
			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
T
Takahiro 已提交
496
			parameters.logarithmicDepthBuffer && ( capabilities.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
497

T
Takahiro 已提交
498
			parameters.envMap && ( capabilities.isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) ) ? '#define TEXTURE_LOD_EXT' : '',
499

500 501
			'uniform mat4 viewMatrix;',
			'uniform vec3 cameraPosition;',
502

M
Mr.doob 已提交
503
			( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
M
Mugen87 已提交
504
			( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
M
Mr.doob 已提交
505
			( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
506

507
			parameters.dithering ? '#define DITHERING' : '',
508

W
WestLangley 已提交
509 510
			( parameters.outputEncoding || parameters.mapEncoding || parameters.matcapEncoding || 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
511
			parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
W
WestLangley 已提交
512
			parameters.matcapEncoding ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',
513 514
			parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
			parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
M
Mr.doob 已提交
515
			parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',
516

M
Mr.doob 已提交
517
			parameters.depthPacking ? '#define DEPTH_PACKING ' + material.depthPacking : '',
518

519
			'\n'
M
Mr.doob 已提交
520

521
		].filter( filterEmptyLine ).join( '\n' );
522

523
	}
M
Mr.doob 已提交
524

M
Mr.doob 已提交
525
	vertexShader = parseIncludes( vertexShader );
526
	vertexShader = replaceLightNums( vertexShader, parameters );
527
	vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
528

M
Mr.doob 已提交
529
	fragmentShader = parseIncludes( fragmentShader );
530
	fragmentShader = replaceLightNums( fragmentShader, parameters );
531
	fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
532

533 534
	vertexShader = unrollLoops( vertexShader );
	fragmentShader = unrollLoops( fragmentShader );
535

T
Takahiro 已提交
536
	if ( capabilities.isWebGL2 && ! material.isRawShaderMaterial ) {
T
Takahiro 已提交
537

538 539 540 541 542 543 544 545 546 547 548 549 550 551
		var isGLSL3ShaderMaterial = false;

		var versionRegex = /^\s*#version\s+300\s+es\s*\n/;

		if ( material.isShaderMaterial &&
			vertexShader.match( versionRegex ) !== null &&
			fragmentShader.match( versionRegex ) !== null ) {

			isGLSL3ShaderMaterial = true;

			vertexShader = vertexShader.replace( versionRegex, '' );
			fragmentShader = fragmentShader.replace( versionRegex, '' );

		}
T
Takahiro 已提交
552

T
Takahiro 已提交
553
		// GLSL 3.0 conversion
T
Takahiro 已提交
554 555
		prefixVertex = [
			'#version 300 es\n',
T
Takahiro 已提交
556 557 558
			'#define attribute in',
			'#define varying out',
			'#define texture2D texture'
T
Takahiro 已提交
559
		].join( '\n' ) + '\n' + prefixVertex;
T
Takahiro 已提交
560

T
Takahiro 已提交
561 562
		prefixFragment = [
			'#version 300 es\n',
T
Takahiro 已提交
563
			'#define varying in',
T
Takahiro 已提交
564 565
			isGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',
			isGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',
T
Takahiro 已提交
566
			'#define gl_FragDepthEXT gl_FragDepth',
T
Takahiro 已提交
567 568 569 570 571 572 573 574 575
			'#define texture2D texture',
			'#define textureCube texture',
			'#define texture2DProj textureProj',
			'#define texture2DLodEXT textureLod',
			'#define texture2DProjLodEXT textureProjLod',
			'#define textureCubeLodEXT textureLod',
			'#define texture2DGradEXT textureGrad',
			'#define texture2DProjGradEXT textureProjGrad',
			'#define textureCubeGradEXT textureGrad'
T
Takahiro 已提交
576
		].join( '\n' ) + '\n' + prefixFragment;
T
Takahiro 已提交
577 578 579

	}

580 581
	var vertexGlsl = prefixVertex + vertexShader;
	var fragmentGlsl = prefixFragment + fragmentShader;
582

583 584
	// console.log( '*VERTEX*', vertexGlsl );
	// console.log( '*FRAGMENT*', fragmentGlsl );
585

586 587
	var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl, renderer.programCheckEnabled );
	var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl, renderer.programCheckEnabled );
588

589 590
	gl.attachShader( program, glVertexShader );
	gl.attachShader( program, glFragmentShader );
591

592
	// Force a particular attribute to index 0.
593

594
	if ( material.index0AttributeName !== undefined ) {
595

596
		gl.bindAttribLocation( program, 0, material.index0AttributeName );
597

598
	} else if ( parameters.morphTargets === true ) {
599

600 601
		// programs with morphTargets displace position out of attribute 0
		gl.bindAttribLocation( program, 0, 'position' );
602

603
	}
604

605
	gl.linkProgram( program );
M
Mr.doob 已提交
606

M
Mugen87 已提交
607 608 609
	var programLog = gl.getProgramInfoLog( program ).trim();
	var vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
	var fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
610

611 612
	var runnable = true;
	var haveDiagnostics = true;
613

614 615
	// console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) );
	// console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) );
616

617
	if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
618

619
		runnable = false;
620

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

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

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

627
	} else if ( vertexLog === '' || fragmentLog === '' ) {
628

629
		haveDiagnostics = false;
630

631
	}
632

633
	if ( haveDiagnostics ) {
634

635
		this.diagnostics = {
636

637 638
			runnable: runnable,
			material: material,
639

640
			programLog: programLog,
641

642
			vertexShader: {
643

644 645
				log: vertexLog,
				prefix: prefixVertex
646

647
			},
648

649
			fragmentShader: {
650

651 652
				log: fragmentLog,
				prefix: prefixFragment
653

654
			}
M
Mr.doob 已提交
655

656
		};
M
Mr.doob 已提交
657

658
	}
659

660
	// clean up
661

662 663
	gl.deleteShader( glVertexShader );
	gl.deleteShader( glFragmentShader );
664

665
	// set up caching for uniform locations
666

667
	var cachedUniforms;
668

669
	this.getUniforms = function () {
670

671
		if ( cachedUniforms === undefined ) {
672

673
			cachedUniforms = new WebGLUniforms( gl, program, textures );
674

675
		}
676

677
		return cachedUniforms;
678

679
	};
680

681
	// set up caching for attribute locations
682

683
	var cachedAttributes;
684

685
	this.getAttributes = function () {
686

687
		if ( cachedAttributes === undefined ) {
688

689
			cachedAttributes = fetchAttributeLocations( gl, program );
690

691
		}
692

693
		return cachedAttributes;
694

695
	};
696

697
	// free resource
698

M
Mugen87 已提交
699
	this.destroy = function () {
700

701 702
		gl.deleteProgram( program );
		this.program = undefined;
703

704
	};
705

706
	// DEPRECATED
707

708
	Object.defineProperties( this, {
709

710
		uniforms: {
M
Mugen87 已提交
711
			get: function () {
712

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

			}
717
		},
M
Mr.doob 已提交
718

719
		attributes: {
M
Mugen87 已提交
720
			get: function () {
721

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

725 726
			}
		}
727

728
	} );
729 730


731 732
	//

W
WestLangley 已提交
733
	this.name = shader.name;
734 735 736 737 738 739
	this.id = programIdCount ++;
	this.code = code;
	this.usedTimes = 1;
	this.program = program;
	this.vertexShader = glVertexShader;
	this.fragmentShader = glFragmentShader;
740

741
	return this;
R
Rich Harris 已提交
742

743
}
R
Rich Harris 已提交
744

745
export { WebGLProgram };