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

	var programIdCount = 0;

M
Mr.doob 已提交
5
	function generateDefines( defines ) {
6 7 8 9 10 11 12 13

		var value, chunk, chunks = [];

		for ( var d in defines ) {

			value = defines[ d ];
			if ( value === false ) continue;

M
Mr.doob 已提交
14
			chunk = '#define ' + d + ' ' + value;
15 16 17 18
			chunks.push( chunk );

		}

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

M
Mr.doob 已提交
21
	}
22

M
Mr.doob 已提交
23
	function cacheUniformLocations( gl, program, identifiers ) {
24 25 26 27 28 29 30 31 32 33 34 35

		var uniforms = {};

		for ( var i = 0, l = identifiers.length; i < l; i ++ ) {

			var id = identifiers[ i ];
			uniforms[ id ] = gl.getUniformLocation( program, id );

		}

		return uniforms;

M
Mr.doob 已提交
36
	}
37

M
Mr.doob 已提交
38
	function cacheAttributeLocations( gl, program, identifiers ) {
39 40 41 42 43 44 45 46 47 48 49 50

		var attributes = {};

		for ( var i = 0, l = identifiers.length; i < l; i ++ ) {

			var id = identifiers[ i ];
			attributes[ id ] = gl.getAttribLocation( program, id );

		}

		return attributes;

M
Mr.doob 已提交
51
	}
B
Ben Adams 已提交
52 53 54 55 56 57 58 59 60 61 62
	
	function programArrayToString ( previousValue, currentValue, index, array ) {
	
		if ( currentValue !== '' && currentValue !== undefined && currentValue !== null ) {
		
			return previousValue + currentValue + '\n';
			
		}
		
		return previousValue;
	}
63 64 65

	return function ( renderer, code, material, parameters ) {

M
Mr.doob 已提交
66
		var gl = renderer.context;
67 68

		var defines = material.defines;
69 70 71 72 73 74
		var uniforms = material.__webglShader.uniforms;
		var attributes = material.attributes;

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

75 76
		var index0AttributeName = material.index0AttributeName;

77 78 79 80 81 82 83 84
		if ( index0AttributeName === undefined && parameters.morphTargets === true ) {

			// programs with morphTargets displace position out of attribute 0

			index0AttributeName = 'position';

		}

M
Mr.doob 已提交
85
		var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
86 87 88

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

M
Mr.doob 已提交
89
			shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
90 91 92

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

M
Mr.doob 已提交
93
			shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
94 95 96

		}

M
Mr.doob 已提交
97 98 99
		var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
		var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
		var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
100

101
		if ( parameters.envMap ) {
102

103
			switch ( material.envMap.mapping ) {
104

105 106
				case THREE.CubeReflectionMapping:
				case THREE.CubeRefractionMapping:
M
Mr.doob 已提交
107
					envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
108
					break;
109

110 111
				case THREE.EquirectangularReflectionMapping:
				case THREE.EquirectangularRefractionMapping:
M
Mr.doob 已提交
112
					envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
113
					break;
114 115

				case THREE.SphericalReflectionMapping:
M
Mr.doob 已提交
116
					envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
117 118
					break;

119 120
			}

M
Mr.doob 已提交
121 122 123 124
			switch ( material.envMap.mapping ) {

				case THREE.CubeRefractionMapping:
				case THREE.EquirectangularRefractionMapping:
M
Mr.doob 已提交
125
					envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
M
Mr.doob 已提交
126 127 128 129
					break;

			}

130 131 132
			switch ( material.combine ) {

				case THREE.MultiplyOperation:
M
Mr.doob 已提交
133
					envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
134 135 136
					break;

				case THREE.MixOperation:
M
Mr.doob 已提交
137
					envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
138 139 140
					break;

				case THREE.AddOperation:
M
Mr.doob 已提交
141
					envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
142 143
					break;

144
			}
145

146 147
		}

148 149
		var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;

150
		// THREE.log( 'building new program ' );
151 152 153 154 155 156 157

		//

		var customDefines = generateDefines( defines );

		//

M
Mr.doob 已提交
158
		var program = gl.createProgram();
159

160
		var prefix_vertex, prefix_fragment;
161

162
		if ( material instanceof THREE.RawShaderMaterial ) {
163

164 165
			prefix_vertex = '';
			prefix_fragment = '';
166

167
		} else {
168

169
			prefix_vertex = [
170

M
Mr.doob 已提交
171 172
				'precision ' + parameters.precision + ' float;',
				'precision ' + parameters.precision + ' int;',
173

174
				customDefines,
175

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

M
Mr.doob 已提交
178 179
				renderer.gammaInput ? '#define GAMMA_INPUT' : '',
				renderer.gammaOutput ? '#define GAMMA_OUTPUT' : '',
180
				'#define GAMMA_FACTOR ' + gammaFactorDefine,
181

M
Mr.doob 已提交
182 183 184 185
				'#define MAX_DIR_LIGHTS ' + parameters.maxDirLights,
				'#define MAX_POINT_LIGHTS ' + parameters.maxPointLights,
				'#define MAX_SPOT_LIGHTS ' + parameters.maxSpotLights,
				'#define MAX_HEMI_LIGHTS ' + parameters.maxHemiLights,
186

M
Mr.doob 已提交
187
				'#define MAX_SHADOWS ' + parameters.maxShadows,
188

M
Mr.doob 已提交
189
				'#define MAX_BONES ' + parameters.maxBones,
190

M
Mr.doob 已提交
191 192 193 194
				parameters.map ? '#define USE_MAP' : '',
				parameters.envMap ? '#define USE_ENVMAP' : '',
				parameters.envMap ? '#define ' + envMapModeDefine : '',
				parameters.lightMap ? '#define USE_LIGHTMAP' : '',
195
				parameters.aoMap ? '#define USE_AOMAP' : '',
M
Mr.doob 已提交
196 197 198 199 200
				parameters.bumpMap ? '#define USE_BUMPMAP' : '',
				parameters.normalMap ? '#define USE_NORMALMAP' : '',
				parameters.specularMap ? '#define USE_SPECULARMAP' : '',
				parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
				parameters.vertexColors ? '#define USE_COLOR' : '',
201

202 203
				parameters.flatShading ? '#define FLAT_SHADED': '',

M
Mr.doob 已提交
204 205
				parameters.skinning ? '#define USE_SKINNING' : '',
				parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
206

M
Mr.doob 已提交
207 208 209 210
				parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
				parameters.morphNormals ? '#define USE_MORPHNORMALS' : '',
				parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
				parameters.flipSided ? '#define FLIP_SIDED' : '',
211

M
Mr.doob 已提交
212 213 214 215
				parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
				parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
				parameters.shadowMapDebug ? '#define SHADOWMAP_DEBUG' : '',
				parameters.shadowMapCascade ? '#define SHADOWMAP_CASCADE' : '',
216

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

M
Mr.doob 已提交
219
				parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
220
				parameters.logarithmicDepthBuffer && renderer.extensions.get('EXT_frag_depth') ? '#define USE_LOGDEPTHBUF_EXT' : '',
221 222


M
Mr.doob 已提交
223 224 225 226 227 228
				'uniform mat4 modelMatrix;',
				'uniform mat4 modelViewMatrix;',
				'uniform mat4 projectionMatrix;',
				'uniform mat4 viewMatrix;',
				'uniform mat3 normalMatrix;',
				'uniform vec3 cameraPosition;',
229

M
Mr.doob 已提交
230 231 232
				'attribute vec3 position;',
				'attribute vec3 normal;',
				'attribute vec2 uv;',
233

M
Mr.doob 已提交
234
				'#ifdef USE_COLOR',
235

M
Mr.doob 已提交
236
				'	attribute vec3 color;',
237

M
Mr.doob 已提交
238
				'#endif',
239

M
Mr.doob 已提交
240
				'#ifdef USE_MORPHTARGETS',
241

M
Mr.doob 已提交
242 243 244 245
				'	attribute vec3 morphTarget0;',
				'	attribute vec3 morphTarget1;',
				'	attribute vec3 morphTarget2;',
				'	attribute vec3 morphTarget3;',
246

M
Mr.doob 已提交
247
				'	#ifdef USE_MORPHNORMALS',
248

M
Mr.doob 已提交
249 250 251 252
				'		attribute vec3 morphNormal0;',
				'		attribute vec3 morphNormal1;',
				'		attribute vec3 morphNormal2;',
				'		attribute vec3 morphNormal3;',
253

M
Mr.doob 已提交
254
				'	#else',
255

M
Mr.doob 已提交
256 257 258 259
				'		attribute vec3 morphTarget4;',
				'		attribute vec3 morphTarget5;',
				'		attribute vec3 morphTarget6;',
				'		attribute vec3 morphTarget7;',
260

M
Mr.doob 已提交
261
				'	#endif',
262

M
Mr.doob 已提交
263
				'#endif',
264

M
Mr.doob 已提交
265
				'#ifdef USE_SKINNING',
266

M
Mr.doob 已提交
267 268
				'	attribute vec4 skinIndex;',
				'	attribute vec4 skinWeight;',
269

M
Mr.doob 已提交
270
				'#endif',
271

M
Mr.doob 已提交
272
				''
273

B
Ben Adams 已提交
274
			].reduce( programArrayToString, '' );
275

M
Mr.doob 已提交
276
			prefix_fragment = [
277

278 279
				( parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',

M
Mr.doob 已提交
280 281
				'precision ' + parameters.precision + ' float;',
				'precision ' + parameters.precision + ' int;',
282

283
				customDefines,
284

M
Mr.doob 已提交
285 286 287 288
				'#define MAX_DIR_LIGHTS ' + parameters.maxDirLights,
				'#define MAX_POINT_LIGHTS ' + parameters.maxPointLights,
				'#define MAX_SPOT_LIGHTS ' + parameters.maxSpotLights,
				'#define MAX_HEMI_LIGHTS ' + parameters.maxHemiLights,
289

M
Mr.doob 已提交
290
				'#define MAX_SHADOWS ' + parameters.maxShadows,
291

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

M
Mr.doob 已提交
294 295
				renderer.gammaInput ? '#define GAMMA_INPUT' : '',
				renderer.gammaOutput ? '#define GAMMA_OUTPUT' : '',
296
				'#define GAMMA_FACTOR ' + gammaFactorDefine,
297

M
Mr.doob 已提交
298 299
				( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
				( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
300

M
Mr.doob 已提交
301 302 303 304 305 306
				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' : '',
307
				parameters.aoMap ? '#define USE_AOMAP' : '',
M
Mr.doob 已提交
308 309 310 311 312
				parameters.bumpMap ? '#define USE_BUMPMAP' : '',
				parameters.normalMap ? '#define USE_NORMALMAP' : '',
				parameters.specularMap ? '#define USE_SPECULARMAP' : '',
				parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
				parameters.vertexColors ? '#define USE_COLOR' : '',
313

314 315
				parameters.flatShading ? '#define FLAT_SHADED': '',

M
Mr.doob 已提交
316 317 318
				parameters.metal ? '#define METAL' : '',
				parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
				parameters.flipSided ? '#define FLIP_SIDED' : '',
319

M
Mr.doob 已提交
320 321 322 323
				parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
				parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
				parameters.shadowMapDebug ? '#define SHADOWMAP_DEBUG' : '',
				parameters.shadowMapCascade ? '#define SHADOWMAP_CASCADE' : '',
324

M
Mr.doob 已提交
325
				parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
326
				parameters.logarithmicDepthBuffer && renderer.extensions.get('EXT_frag_depth') ? '#define USE_LOGDEPTHBUF_EXT' : '',
327

M
Mr.doob 已提交
328 329 330
				'uniform mat4 viewMatrix;',
				'uniform vec3 cameraPosition;',
				''
331

B
Ben Adams 已提交
332
			].reduce( programArrayToString, '' );
333 334

		}
335

M
Mr.doob 已提交
336 337
		var glVertexShader = new THREE.WebGLShader( gl, gl.VERTEX_SHADER, prefix_vertex + vertexShader );
		var glFragmentShader = new THREE.WebGLShader( gl, gl.FRAGMENT_SHADER, prefix_fragment + fragmentShader );
338

M
Mr.doob 已提交
339 340
		gl.attachShader( program, glVertexShader );
		gl.attachShader( program, glFragmentShader );
341 342 343

		if ( index0AttributeName !== undefined ) {

344 345 346 347
			// Force a particular attribute to index 0.
			// because potentially expensive emulation is done by browser if attribute 0 is disabled.
			// And, color, for example is often automatically bound to index 0 so disabling it

M
Mr.doob 已提交
348
			gl.bindAttribLocation( program, 0, index0AttributeName );
349 350 351

		}

M
Mr.doob 已提交
352
		gl.linkProgram( program );
353

M
Mr.doob 已提交
354 355 356
		var programLogInfo = gl.getProgramInfoLog( program );
		var vertexErrorLogInfo = gl.getShaderInfoLog( glVertexShader );
		var fragmentErrorLogInfo = gl.getShaderInfoLog( glFragmentShader );
357

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

M
Mr.doob 已提交
360
			THREE.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLogInfo, vertexErrorLogInfo, fragmentErrorLogInfo );
361 362

		}
363

364
		if ( programLogInfo !== '' ) {
365

366
			THREE.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLogInfo );
367 368 369

		}

M
Mr.doob 已提交
370 371
		// clean up

M
Mr.doob 已提交
372 373
		gl.deleteShader( glVertexShader );
		gl.deleteShader( glFragmentShader );
M
Mr.doob 已提交
374

375 376 377 378
		// cache uniform locations

		var identifiers = [

M
Mr.doob 已提交
379 380 381 382 383 384 385 386 387
			'viewMatrix',
			'modelViewMatrix',
			'projectionMatrix',
			'normalMatrix',
			'modelMatrix',
			'cameraPosition',
			'morphTargetInfluences',
			'bindMatrix',
			'bindMatrixInverse'
388 389 390 391 392

		];

		if ( parameters.useVertexTexture ) {

M
Mr.doob 已提交
393
			identifiers.push( 'boneTexture', 'boneTextureWidth', 'boneTextureHeight' );
394 395 396 397 398 399 400

		} else {

			identifiers.push( 'boneGlobalMatrices' );

		}

401 402
		if ( parameters.logarithmicDepthBuffer ) {

M
Mr.doob 已提交
403
			identifiers.push( 'logDepthBufFC' );
404 405 406

		}

407 408 409 410 411 412
		for ( var u in uniforms ) {

			identifiers.push( u );

		}

M
Mr.doob 已提交
413
		this.uniforms = cacheUniformLocations( gl, program, identifiers );
414 415 416

		// cache attributes locations

M
Mr.doob 已提交
417
		identifiers = [
418

M
Mr.doob 已提交
419 420 421 422 423 424 425 426 427
			'position',
			'normal',
			'uv',
			'uv2',
			'tangent',
			'color',
			'skinIndex',
			'skinWeight',
			'lineDistance'
428 429 430 431 432

		];

		for ( var i = 0; i < parameters.maxMorphTargets; i ++ ) {

M
Mr.doob 已提交
433
			identifiers.push( 'morphTarget' + i );
434 435 436 437 438

		}

		for ( var i = 0; i < parameters.maxMorphNormals; i ++ ) {

M
Mr.doob 已提交
439
			identifiers.push( 'morphNormal' + i );
440 441 442 443 444 445 446 447 448

		}

		for ( var a in attributes ) {

			identifiers.push( a );

		}

M
Mr.doob 已提交
449
		this.attributes = cacheAttributeLocations( gl, program, identifiers );
450
		this.attributesKeys = Object.keys( this.attributes );
451 452 453 454 455 456 457

		//

		this.id = programIdCount ++;
		this.code = code;
		this.usedTimes = 1;
		this.program = program;
M
Mr.doob 已提交
458 459
		this.vertexShader = glVertexShader;
		this.fragmentShader = glFragmentShader;
460 461 462 463 464

		return this;

	};

465
} )();