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

	var programIdCount = 0;

M
Mr.doob 已提交
5
	function generateDefines( defines ) {
6

7
		var chunks = [];
8

9 10 11
		for ( var name in defines ) {

			var value = defines[ name ];
12 13 14

			if ( value === false ) continue;

15
			chunks.push( '#define ' + name + ' ' + value );
16 17 18

		}

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

M
Mr.doob 已提交
21
	}
22

23 24
	function fetchUniformLocations( gl, program, identifiers ) {

25 26 27

		var uniforms = {};

28
		var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
M
Mr.doob 已提交
29

30 31 32 33 34 35 36
		for ( var i = 0; i < n; i ++ ) {

			var info = gl.getActiveUniform( program , i );
			var name = info.name;
			var location = gl.getUniformLocation( program, name );

			//console.log("THREE.WebGLProgram: ACTIVE UNIFORM:", name);
37

38 39 40 41 42 43 44 45
			var suffixPos = name.lastIndexOf( '[0]' );
			if ( suffixPos !== -1 && suffixPos === name.length - 3 ) {

				uniforms[ name.substr( 0, suffixPos ) ] = location;

			}

			uniforms[ name ] = location;
46 47 48 49 50

		}

		return uniforms;

M
Mr.doob 已提交
51
	}
52

53
	function fetchAttributeLocations( gl, program, identifiers ) {
54 55 56

		var attributes = {};

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

59 60 61 62 63 64
		for ( var i = 0; i < n; i ++ ) {

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

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

66
			attributes[ name ] = gl.getAttribLocation( program, name );
67 68 69 70 71

		}

		return attributes;

M
Mr.doob 已提交
72
	}
73

74
	function filterEmptyLine( string ) {
75

76
		return string !== '';
M
Mr.doob 已提交
77

B
Ben Adams 已提交
78
	}
79 80 81

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

M
Mr.doob 已提交
82
		var gl = renderer.context;
83 84

		var defines = material.defines;
85 86 87 88 89 90
		var uniforms = material.__webglShader.uniforms;
		var attributes = material.attributes;

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

91 92
		var index0AttributeName = material.index0AttributeName;

93
		/*
94 95 96 97 98 99 100
		if ( index0AttributeName === undefined && parameters.morphTargets === true ) {

			// programs with morphTargets displace position out of attribute 0

			index0AttributeName = 'position';

		}
101
		*/
102

M
Mr.doob 已提交
103
		var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
104 105 106

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

M
Mr.doob 已提交
107
			shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
108 109 110

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

M
Mr.doob 已提交
111
			shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
112 113 114

		}

M
Mr.doob 已提交
115 116 117
		var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
		var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
		var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
118

119
		if ( parameters.envMap ) {
120

121
			switch ( material.envMap.mapping ) {
122

123 124
				case THREE.CubeReflectionMapping:
				case THREE.CubeRefractionMapping:
M
Mr.doob 已提交
125
					envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
126
					break;
127

128 129
				case THREE.EquirectangularReflectionMapping:
				case THREE.EquirectangularRefractionMapping:
M
Mr.doob 已提交
130
					envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
131
					break;
132 133

				case THREE.SphericalReflectionMapping:
M
Mr.doob 已提交
134
					envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
135 136
					break;

137 138
			}

M
Mr.doob 已提交
139 140 141 142
			switch ( material.envMap.mapping ) {

				case THREE.CubeRefractionMapping:
				case THREE.EquirectangularRefractionMapping:
M
Mr.doob 已提交
143
					envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
M
Mr.doob 已提交
144 145 146 147
					break;

			}

148 149 150
			switch ( material.combine ) {

				case THREE.MultiplyOperation:
M
Mr.doob 已提交
151
					envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
152 153 154
					break;

				case THREE.MixOperation:
M
Mr.doob 已提交
155
					envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
156 157 158
					break;

				case THREE.AddOperation:
M
Mr.doob 已提交
159
					envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
160 161
					break;

162
			}
163

164 165
		}

166 167
		var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;

168
		// console.log( 'building new program ' );
169 170 171 172 173 174 175

		//

		var customDefines = generateDefines( defines );

		//

M
Mr.doob 已提交
176
		var program = gl.createProgram();
177

178
		var prefixVertex, prefixFragment;
179

180
		if ( material instanceof THREE.RawShaderMaterial ) {
181

182 183
			prefixVertex = '';
			prefixFragment = '';
184

185
		} else {
186

187
			prefixVertex = [
188

M
Mr.doob 已提交
189 190
				'precision ' + parameters.precision + ' float;',
				'precision ' + parameters.precision + ' int;',
191

192 193
				'#define SHADER_NAME ' + material.__webglShader.name,

194
				customDefines,
195

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

M
Mr.doob 已提交
198 199
				renderer.gammaInput ? '#define GAMMA_INPUT' : '',
				renderer.gammaOutput ? '#define GAMMA_OUTPUT' : '',
200
				'#define GAMMA_FACTOR ' + gammaFactorDefine,
201

M
Mr.doob 已提交
202 203 204 205
				'#define MAX_DIR_LIGHTS ' + parameters.maxDirLights,
				'#define MAX_POINT_LIGHTS ' + parameters.maxPointLights,
				'#define MAX_SPOT_LIGHTS ' + parameters.maxSpotLights,
				'#define MAX_HEMI_LIGHTS ' + parameters.maxHemiLights,
206

M
Mr.doob 已提交
207
				'#define MAX_SHADOWS ' + parameters.maxShadows,
208

M
Mr.doob 已提交
209
				'#define MAX_BONES ' + parameters.maxBones,
210

M
Mr.doob 已提交
211 212 213 214
				parameters.map ? '#define USE_MAP' : '',
				parameters.envMap ? '#define USE_ENVMAP' : '',
				parameters.envMap ? '#define ' + envMapModeDefine : '',
				parameters.lightMap ? '#define USE_LIGHTMAP' : '',
215
				parameters.aoMap ? '#define USE_AOMAP' : '',
216
				parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
M
Mr.doob 已提交
217 218 219 220 221
				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' : '',
222

223 224
				parameters.flatShading ? '#define FLAT_SHADED': '',

M
Mr.doob 已提交
225 226
				parameters.skinning ? '#define USE_SKINNING' : '',
				parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
227

M
Mr.doob 已提交
228 229 230 231
				parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
				parameters.morphNormals ? '#define USE_MORPHNORMALS' : '',
				parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
				parameters.flipSided ? '#define FLIP_SIDED' : '',
232

M
Mr.doob 已提交
233 234 235 236
				parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
				parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
				parameters.shadowMapDebug ? '#define SHADOWMAP_DEBUG' : '',
				parameters.shadowMapCascade ? '#define SHADOWMAP_CASCADE' : '',
237

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

M
Mr.doob 已提交
240
				parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
241
				parameters.logarithmicDepthBuffer && renderer.extensions.get('EXT_frag_depth') ? '#define USE_LOGDEPTHBUF_EXT' : '',
242 243


M
Mr.doob 已提交
244 245 246 247 248 249
				'uniform mat4 modelMatrix;',
				'uniform mat4 modelViewMatrix;',
				'uniform mat4 projectionMatrix;',
				'uniform mat4 viewMatrix;',
				'uniform mat3 normalMatrix;',
				'uniform vec3 cameraPosition;',
250

M
Mr.doob 已提交
251 252 253
				'attribute vec3 position;',
				'attribute vec3 normal;',
				'attribute vec2 uv;',
254

M
Mr.doob 已提交
255
				'#ifdef USE_COLOR',
256

M
Mr.doob 已提交
257
				'	attribute vec3 color;',
258

M
Mr.doob 已提交
259
				'#endif',
260

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

M
Mr.doob 已提交
263 264 265 266
				'	attribute vec3 morphTarget0;',
				'	attribute vec3 morphTarget1;',
				'	attribute vec3 morphTarget2;',
				'	attribute vec3 morphTarget3;',
267

M
Mr.doob 已提交
268
				'	#ifdef USE_MORPHNORMALS',
269

M
Mr.doob 已提交
270 271 272 273
				'		attribute vec3 morphNormal0;',
				'		attribute vec3 morphNormal1;',
				'		attribute vec3 morphNormal2;',
				'		attribute vec3 morphNormal3;',
274

M
Mr.doob 已提交
275
				'	#else',
276

M
Mr.doob 已提交
277 278 279 280
				'		attribute vec3 morphTarget4;',
				'		attribute vec3 morphTarget5;',
				'		attribute vec3 morphTarget6;',
				'		attribute vec3 morphTarget7;',
281

M
Mr.doob 已提交
282
				'	#endif',
283

M
Mr.doob 已提交
284
				'#endif',
285

M
Mr.doob 已提交
286
				'#ifdef USE_SKINNING',
287

M
Mr.doob 已提交
288 289
				'	attribute vec4 skinIndex;',
				'	attribute vec4 skinWeight;',
290

M
Mr.doob 已提交
291
				'#endif',
292

293
				'\n'
294

295
			].filter( filterEmptyLine ).join( '\n' );
296

297
			prefixFragment = [
298

299
				( parameters.bumpMap || parameters.normalMap || parameters.flatShading || material.derivatives ) ? '#extension GL_OES_standard_derivatives : enable' : '',
300

M
Mr.doob 已提交
301 302
				'precision ' + parameters.precision + ' float;',
				'precision ' + parameters.precision + ' int;',
303

304 305
				'#define SHADER_NAME ' + material.__webglShader.name,

306
				customDefines,
307

M
Mr.doob 已提交
308 309 310 311
				'#define MAX_DIR_LIGHTS ' + parameters.maxDirLights,
				'#define MAX_POINT_LIGHTS ' + parameters.maxPointLights,
				'#define MAX_SPOT_LIGHTS ' + parameters.maxSpotLights,
				'#define MAX_HEMI_LIGHTS ' + parameters.maxHemiLights,
312

M
Mr.doob 已提交
313
				'#define MAX_SHADOWS ' + parameters.maxShadows,
314

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

M
Mr.doob 已提交
317 318
				renderer.gammaInput ? '#define GAMMA_INPUT' : '',
				renderer.gammaOutput ? '#define GAMMA_OUTPUT' : '',
319
				'#define GAMMA_FACTOR ' + gammaFactorDefine,
320

M
Mr.doob 已提交
321 322
				( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
				( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
323

M
Mr.doob 已提交
324 325 326 327 328 329
				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' : '',
330
				parameters.aoMap ? '#define USE_AOMAP' : '',
331
				parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
M
Mr.doob 已提交
332 333 334 335 336
				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' : '',
337

338 339
				parameters.flatShading ? '#define FLAT_SHADED': '',

M
Mr.doob 已提交
340 341 342
				parameters.metal ? '#define METAL' : '',
				parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
				parameters.flipSided ? '#define FLIP_SIDED' : '',
343

M
Mr.doob 已提交
344 345 346 347
				parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
				parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
				parameters.shadowMapDebug ? '#define SHADOWMAP_DEBUG' : '',
				parameters.shadowMapCascade ? '#define SHADOWMAP_CASCADE' : '',
348

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

M
Mr.doob 已提交
352 353
				'uniform mat4 viewMatrix;',
				'uniform vec3 cameraPosition;',
354

355 356 357
				'\n'

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

		}
360

361 362 363 364 365
		var vertexGlsl = prefixVertex + vertexShader;
		var fragmentGlsl = prefixFragment + fragmentShader;

		var glVertexShader = new THREE.WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
		var glFragmentShader = new THREE.WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
366

M
Mr.doob 已提交
367 368
		gl.attachShader( program, glVertexShader );
		gl.attachShader( program, glFragmentShader );
369 370 371

		if ( index0AttributeName !== undefined ) {

372 373 374 375
			// 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 已提交
376
			gl.bindAttribLocation( program, 0, index0AttributeName );
377 378 379

		}

M
Mr.doob 已提交
380
		gl.linkProgram( program );
381

M
Mr.doob 已提交
382 383 384
		var programLogInfo = gl.getProgramInfoLog( program );
		var vertexErrorLogInfo = gl.getShaderInfoLog( glVertexShader );
		var fragmentErrorLogInfo = gl.getShaderInfoLog( glFragmentShader );
385

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

388
			console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLogInfo, vertexErrorLogInfo, fragmentErrorLogInfo );
389 390

		}
391

392
		else if ( programLogInfo !== '' ) {
393

394
			console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLogInfo );
395 396 397

		}

M
Mr.doob 已提交
398 399
		// clean up

M
Mr.doob 已提交
400 401
		gl.deleteShader( glVertexShader );
		gl.deleteShader( glFragmentShader );
M
Mr.doob 已提交
402

403
		// set up caching for uniform locations
404

405
		var getUniforms = function() { return this._cachedUniforms; };
406

407
		this.getUniforms = function() {
408

409 410 411
			// fetch, cache, and next time just use a dumb accessor
			var uniforms = fetchUniformLocations( gl, program );
			this._cachedUniforms = uniforms;
412
			this.getUniforms = getUniforms;
413
			return uniforms;
414

415
		};
416

417
		// set up caching for attribute locations
418

419
		var getAttributes = function() { return this._cachedAttributes; };
420

421
		this.getAttributes = function() {
422

423 424
			var attributes = fetchAttributeLocations( gl, program );
			this._cachedAttributes = attributes;
425
			this.getAttributes = getAttributes;
426
			return attributes;
427

428
		};
429

430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
		// 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 已提交
451

452 453 454
		});


455 456 457 458 459 460
		//

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

		return this;

	};

468
} )();