WebGLProgram.js 21.0 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';
A
angus 已提交
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, LogLuvEncoding } from '../../constants.js';
R
Rich Harris 已提交
9

10 11
var programIdCount = 0;

A
aardgoose 已提交
12 13 14 15 16 17 18 19 20 21 22 23 24 25
function addLineNumbers( string ) {

	var lines = string.split( '\n' );

	for ( var i = 0; i < lines.length; i ++ ) {

		lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];

	}

	return lines.join( '\n' );

}

26 27 28 29 30
function getEncodingComponents( encoding ) {

	switch ( encoding ) {

		case LinearEncoding:
M
Mugen87 已提交
31
			return [ 'Linear', '( value )' ];
32
		case sRGBEncoding:
M
Mugen87 已提交
33
			return [ 'sRGB', '( value )' ];
34
		case RGBEEncoding:
M
Mugen87 已提交
35
			return [ 'RGBE', '( value )' ];
36
		case RGBM7Encoding:
M
Mugen87 已提交
37
			return [ 'RGBM', '( value, 7.0 )' ];
38
		case RGBM16Encoding:
M
Mugen87 已提交
39
			return [ 'RGBM', '( value, 16.0 )' ];
40
		case RGBDEncoding:
M
Mugen87 已提交
41
			return [ 'RGBD', '( value, 256.0 )' ];
42
		case GammaEncoding:
M
Mugen87 已提交
43
			return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
A
angus 已提交
44
		case LogLuvEncoding:
A
angus 已提交
45
			return [ 'LogLuv', '( value )' ];
46 47
		default:
			throw new Error( 'unsupported encoding: ' + encoding );
48

49 50
	}

51
}
52

A
aardgoose 已提交
53
function getShaderErrors( gl, shader, type ) {
A
aardgoose 已提交
54 55 56 57 58 59 60 61 62

	var status = gl.getShaderParameter( shader, gl.COMPILE_STATUS );
	var log = gl.getShaderInfoLog( shader ).trim();

	if ( status && log === '' ) return '';

	// --enable-privileged-webgl-extension
	// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );

A
aardgoose 已提交
63 64 65
	var source = gl.getShaderSource( shader );

	return 'THREE.WebGLShader: gl.getShaderInfoLog() ' + type + '\n' + log + addLineNumbers( source );
A
aardgoose 已提交
66 67 68

}

69
function getTexelDecodingFunction( functionName, encoding ) {
70

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

74
}
75

76
function getTexelEncodingFunction( functionName, encoding ) {
77

78
	var components = getEncodingComponents( encoding );
M
Mr.doob 已提交
79
	return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
M
Mr.doob 已提交
80

81
}
B
Ben Houston 已提交
82

83
function getToneMappingFunction( functionName, toneMapping ) {
M
Mr.doob 已提交
84

85
	var toneMappingName;
M
Mr.doob 已提交
86

87
	switch ( toneMapping ) {
M
Mr.doob 已提交
88

89
		case LinearToneMapping:
M
Mr.doob 已提交
90
			toneMappingName = 'Linear';
91
			break;
M
Mr.doob 已提交
92

93
		case ReinhardToneMapping:
M
Mr.doob 已提交
94
			toneMappingName = 'Reinhard';
95
			break;
M
Mr.doob 已提交
96

97
		case Uncharted2ToneMapping:
M
Mr.doob 已提交
98
			toneMappingName = 'Uncharted2';
99
			break;
B
Ben Houston 已提交
100

101
		case CineonToneMapping:
M
Mr.doob 已提交
102
			toneMappingName = 'OptimizedCineon';
103
			break;
M
Mr.doob 已提交
104

C
ChenX 已提交
105 106
		case ACESFilmicToneMapping:
			toneMappingName = 'ACESFilmic';
C
ChenX 已提交
107 108
			break;

109 110
		default:
			throw new Error( 'unsupported toneMapping: ' + toneMapping );
B
Ben Houston 已提交
111 112 113

	}

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

116
}
117

118
function generateExtensions( extensions, parameters, rendererExtensions ) {
119

120
	extensions = extensions || {};
121

122
	var chunks = [
A
arobertson0 已提交
123
		( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || ( parameters.normalMap && ! parameters.objectSpaceNormalMap ) || parameters.clearCoatNormalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
124 125
		( 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' : '',
126
		( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''
127
	];
128

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

131
}
132

133
function generateDefines( defines ) {
134

135
	var chunks = [];
136

137
	for ( var name in defines ) {
138

139
		var value = defines[ name ];
140

141
		if ( value === false ) continue;
142

143
		chunks.push( '#define ' + name + ' ' + value );
144

M
Mr.doob 已提交
145
	}
146

147
	return chunks.join( '\n' );
148

149
}
150

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

153
	var attributes = {};
154

155
	var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
156

157
	for ( var i = 0; i < n; i ++ ) {
158

159 160
		var info = gl.getActiveAttrib( program, i );
		var name = info.name;
161

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

164
		attributes[ name ] = gl.getAttribLocation( program, name );
165

M
Mr.doob 已提交
166
	}
167

168
	return attributes;
169

170
}
M
Mr.doob 已提交
171

172
function filterEmptyLine( string ) {
173

174
	return string !== '';
175

176
}
177

178
function replaceLightNums( string, parameters ) {
179

180 181 182
	return string
		.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
		.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
183
		.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
184
		.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
185 186 187 188
		.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )
		.replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )
		.replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )
		.replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );
M
Mr.doob 已提交
189

190
}
M
Mr.doob 已提交
191

192 193 194 195 196 197 198 199
function replaceClippingPlaneNums( string, parameters ) {

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

}

200
function parseIncludes( string ) {
M
Mr.doob 已提交
201

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

204
	function replace( match, include ) {
205

206
		var replace = ShaderChunk[ include ];
207

208
		if ( replace === undefined ) {
209

210
			throw new Error( 'Can not resolve #include <' + include + '>' );
M
Mr.doob 已提交
211 212 213

		}

214
		return parseIncludes( replace );
M
Mr.doob 已提交
215 216 217

	}

218
	return string.replace( pattern, replace );
M
Mr.doob 已提交
219

220
}
M
Mr.doob 已提交
221

222
function unrollLoops( string ) {
M
Mr.doob 已提交
223

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

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

228
		var unroll = '';
M
Mr.doob 已提交
229

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

232 233 234
			unroll += snippet
				.replace( /\[ i \]/g, '[ ' + i + ' ]' )
				.replace( /UNROLLED_LOOP_INDEX/g, i );
M
Mr.doob 已提交
235 236 237

		}

238
		return unroll;
M
Mr.doob 已提交
239 240 241

	}

242
	return string.replace( pattern, replace );
243

244
}
245

246
function WebGLProgram( renderer, extensions, code, material, shader, parameters, capabilities ) {
247

248
	var gl = renderer.getContext();
249

250
	var defines = material.defines;
251

252 253
	var vertexShader = shader.vertexShader;
	var fragmentShader = shader.fragmentShader;
254

255
	var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
256

257
	if ( parameters.shadowMapType === PCFShadowMap ) {
258

259
		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
260

261
	} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
262

263
		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
264

265
	}
266

267 268 269
	var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
	var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
	var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
270

271
	if ( parameters.envMap ) {
B
Ben Houston 已提交
272

273
		switch ( material.envMap.mapping ) {
274

275 276 277 278
			case CubeReflectionMapping:
			case CubeRefractionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
				break;
279

280 281 282 283
			case CubeUVReflectionMapping:
			case CubeUVRefractionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
				break;
284

285 286 287 288
			case EquirectangularReflectionMapping:
			case EquirectangularRefractionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
				break;
M
Mr.doob 已提交
289

290 291 292
			case SphericalReflectionMapping:
				envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
				break;
M
Mr.doob 已提交
293

294
		}
M
Mr.doob 已提交
295

296
		switch ( material.envMap.mapping ) {
297

298 299 300 301
			case CubeRefractionMapping:
			case EquirectangularRefractionMapping:
				envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
				break;
302

303
		}
304

305
		switch ( material.combine ) {
306

307 308 309
			case MultiplyOperation:
				envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
				break;
310

311 312 313
			case MixOperation:
				envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
				break;
314

315 316 317
			case AddOperation:
				envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
				break;
318

319
		}
320

321
	}
322

323
	var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
324

325
	// console.log( 'building new program ' );
326

327
	//
328

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

331
	var customDefines = generateDefines( defines );
332

333
	//
334

335
	var program = gl.createProgram();
336

337
	var prefixVertex, prefixFragment;
338

M
Mr.doob 已提交
339
	if ( material.isRawShaderMaterial ) {
340

341
		prefixVertex = [
342

343
			customDefines
344

345
		].filter( filterEmptyLine ).join( '\n' );
346

347 348 349 350 351 352
		if ( prefixVertex.length > 0 ) {

			prefixVertex += '\n';

		}

353
		prefixFragment = [
354

355
			customExtensions,
356
			customDefines
357

358
		].filter( filterEmptyLine ).join( '\n' );
359

360 361 362 363 364 365
		if ( prefixFragment.length > 0 ) {

			prefixFragment += '\n';

		}

366
	} else {
367

368
		prefixVertex = [
369

370 371
			'precision ' + parameters.precision + ' float;',
			'precision ' + parameters.precision + ' int;',
372

373
			'#define SHADER_NAME ' + shader.name,
374

375
			customDefines,
376

377
			parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
378

379
			'#define GAMMA_FACTOR ' + gammaFactorDefine,
380

381
			'#define MAX_BONES ' + parameters.maxBones,
382 383 384
			( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
			( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',

385 386 387 388 389 390 391 392
			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 已提交
393
			( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
A
arobertson0 已提交
394
			parameters.clearCoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
395 396 397 398 399
			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 已提交
400 401

			parameters.vertexTangents ? '#define USE_TANGENT' : '',
402
			parameters.vertexColors ? '#define USE_COLOR' : '',
403

404
			parameters.flatShading ? '#define FLAT_SHADED' : '',
T
tschw 已提交
405

406 407
			parameters.skinning ? '#define USE_SKINNING' : '',
			parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
408

409 410 411 412
			parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
			parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
			parameters.flipSided ? '#define FLIP_SIDED' : '',
413

414 415
			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
416

417
			parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
418

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

422 423 424 425 426 427
			'uniform mat4 modelMatrix;',
			'uniform mat4 modelViewMatrix;',
			'uniform mat4 projectionMatrix;',
			'uniform mat4 viewMatrix;',
			'uniform mat3 normalMatrix;',
			'uniform vec3 cameraPosition;',
428

429 430 431
			'attribute vec3 position;',
			'attribute vec3 normal;',
			'attribute vec2 uv;',
432

D
Don McCurdy 已提交
433 434 435 436 437 438
			'#ifdef USE_TANGENT',

			'	attribute vec4 tangent;',

			'#endif',

439
			'#ifdef USE_COLOR',
440

441
			'	attribute vec3 color;',
442

443
			'#endif',
444

445
			'#ifdef USE_MORPHTARGETS',
446

447 448 449 450
			'	attribute vec3 morphTarget0;',
			'	attribute vec3 morphTarget1;',
			'	attribute vec3 morphTarget2;',
			'	attribute vec3 morphTarget3;',
451

452
			'	#ifdef USE_MORPHNORMALS',
453

454 455 456 457
			'		attribute vec3 morphNormal0;',
			'		attribute vec3 morphNormal1;',
			'		attribute vec3 morphNormal2;',
			'		attribute vec3 morphNormal3;',
458

459
			'	#else',
460

461 462 463 464
			'		attribute vec3 morphTarget4;',
			'		attribute vec3 morphTarget5;',
			'		attribute vec3 morphTarget6;',
			'		attribute vec3 morphTarget7;',
465

466
			'	#endif',
467

468
			'#endif',
469

470
			'#ifdef USE_SKINNING',
471

472 473
			'	attribute vec4 skinIndex;',
			'	attribute vec4 skinWeight;',
474

475
			'#endif',
476

477
			'\n'
W
WestLangley 已提交
478

479
		].filter( filterEmptyLine ).join( '\n' );
480

481
		prefixFragment = [
482

483
			customExtensions,
484

485 486
			'precision ' + parameters.precision + ' float;',
			'precision ' + parameters.precision + ' int;',
487

488
			'#define SHADER_NAME ' + shader.name,
489

490
			customDefines,
491

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

494
			'#define GAMMA_FACTOR ' + gammaFactorDefine,
495

496 497
			( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
			( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
498

499
			parameters.map ? '#define USE_MAP' : '',
500
			parameters.matcap ? '#define USE_MATCAP' : '',
501 502 503 504 505 506 507 508 509
			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 已提交
510
			( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
A
arobertson0 已提交
511
			parameters.clearCoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
512 513 514 515
			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
D
Don McCurdy 已提交
516 517

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

T
Takahiro 已提交
520
			parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
T
Takahiro 已提交
521

522
			parameters.flatShading ? '#define FLAT_SHADED' : '',
523

524 525
			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
			parameters.flipSided ? '#define FLIP_SIDED' : '',
526

527 528
			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
529

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

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

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

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

539 540
			'uniform mat4 viewMatrix;',
			'uniform vec3 cameraPosition;',
541

M
Mr.doob 已提交
542
			( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
M
Mugen87 已提交
543
			( 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 已提交
544
			( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
545

546
			parameters.dithering ? '#define DITHERING' : '',
547

W
WestLangley 已提交
548 549
			( 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
550
			parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
W
WestLangley 已提交
551
			parameters.matcapEncoding ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',
552 553
			parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
			parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
M
Mr.doob 已提交
554
			parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',
555

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

558
			'\n'
M
Mr.doob 已提交
559

560
		].filter( filterEmptyLine ).join( '\n' );
561

562
	}
M
Mr.doob 已提交
563

M
Mr.doob 已提交
564
	vertexShader = parseIncludes( vertexShader );
565
	vertexShader = replaceLightNums( vertexShader, parameters );
566
	vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
567

M
Mr.doob 已提交
568
	fragmentShader = parseIncludes( fragmentShader );
569
	fragmentShader = replaceLightNums( fragmentShader, parameters );
570
	fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
571

572 573
	vertexShader = unrollLoops( vertexShader );
	fragmentShader = unrollLoops( fragmentShader );
574

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

577 578 579 580 581 582 583 584 585 586 587 588 589 590
		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 已提交
591

T
Takahiro 已提交
592
		// GLSL 3.0 conversion
T
Takahiro 已提交
593 594
		prefixVertex = [
			'#version 300 es\n',
T
Takahiro 已提交
595 596 597
			'#define attribute in',
			'#define varying out',
			'#define texture2D texture'
T
Takahiro 已提交
598
		].join( '\n' ) + '\n' + prefixVertex;
T
Takahiro 已提交
599

T
Takahiro 已提交
600 601
		prefixFragment = [
			'#version 300 es\n',
T
Takahiro 已提交
602
			'#define varying in',
T
Takahiro 已提交
603 604
			isGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',
			isGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',
T
Takahiro 已提交
605
			'#define gl_FragDepthEXT gl_FragDepth',
T
Takahiro 已提交
606 607 608 609 610 611 612 613 614
			'#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 已提交
615
		].join( '\n' ) + '\n' + prefixFragment;
T
Takahiro 已提交
616 617 618

	}

619 620
	var vertexGlsl = prefixVertex + vertexShader;
	var fragmentGlsl = prefixFragment + fragmentShader;
621

622 623
	// console.log( '*VERTEX*', vertexGlsl );
	// console.log( '*FRAGMENT*', fragmentGlsl );
624

A
aardgoose 已提交
625 626
	var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
	var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
627

628 629
	gl.attachShader( program, glVertexShader );
	gl.attachShader( program, glFragmentShader );
630

631
	// Force a particular attribute to index 0.
632

633
	if ( material.index0AttributeName !== undefined ) {
634

635
		gl.bindAttribLocation( program, 0, material.index0AttributeName );
636

637
	} else if ( parameters.morphTargets === true ) {
638

639 640
		// programs with morphTargets displace position out of attribute 0
		gl.bindAttribLocation( program, 0, 'position' );
641

642
	}
643

644
	gl.linkProgram( program );
M
Mr.doob 已提交
645

646 647
	// check for link errors
	if ( renderer.debug.checkShaderErrors ) {
648

649 650 651
		var programLog = gl.getProgramInfoLog( program ).trim();
		var vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
		var fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
652

653 654
		var runnable = true;
		var haveDiagnostics = true;
655

656
		if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
657

658
			runnable = false;
659

A
aardgoose 已提交
660 661
			var vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
			var fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
A
aardgoose 已提交
662

A
aardgoose 已提交
663
			console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors );
664

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

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

669
		} else if ( vertexLog === '' || fragmentLog === '' ) {
670

671 672 673
			haveDiagnostics = false;

		}
674

675
		if ( haveDiagnostics ) {
676

677
			this.diagnostics = {
678

679 680
				runnable: runnable,
				material: material,
681

682
				programLog: programLog,
683

684
				vertexShader: {
685

686 687
					log: vertexLog,
					prefix: prefixVertex
688

689
				},
690

691
				fragmentShader: {
692

693 694
					log: fragmentLog,
					prefix: prefixFragment
695

696
				}
M
Mr.doob 已提交
697

698 699 700
			};

		}
M
Mr.doob 已提交
701

702
	}
703

704
	// clean up
705

706 707
	gl.deleteShader( glVertexShader );
	gl.deleteShader( glFragmentShader );
708

709
	// set up caching for uniform locations
710

711
	var cachedUniforms;
712

713
	this.getUniforms = function () {
714

715
		if ( cachedUniforms === undefined ) {
716

717
			cachedUniforms = new WebGLUniforms( gl, program );
718

719
		}
720

721
		return cachedUniforms;
722

723
	};
724

725
	// set up caching for attribute locations
726

727
	var cachedAttributes;
728

729
	this.getAttributes = function () {
730

731
		if ( cachedAttributes === undefined ) {
732

733
			cachedAttributes = fetchAttributeLocations( gl, program );
734

735
		}
736

737
		return cachedAttributes;
738

739
	};
740

741
	// free resource
742

M
Mugen87 已提交
743
	this.destroy = function () {
744

745 746
		gl.deleteProgram( program );
		this.program = undefined;
747

748
	};
749

750 751
	//

W
WestLangley 已提交
752
	this.name = shader.name;
753 754 755 756 757 758
	this.id = programIdCount ++;
	this.code = code;
	this.usedTimes = 1;
	this.program = program;
	this.vertexShader = glVertexShader;
	this.fragmentShader = glFragmentShader;
759

760
	return this;
R
Rich Harris 已提交
761

762
}
R
Rich Harris 已提交
763

764
export { WebGLProgram };