WebGLPrograms.js 11.7 KB
Newer Older
M
Mr.doob 已提交
1 2 3 4
/**
 * @author mrdoob / http://mrdoob.com/
 */

5
import { BackSide, DoubleSide, CubeUVRefractionMapping, CubeUVReflectionMapping, LinearEncoding, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping } from '../../constants.js';
B
bentok 已提交
6
import { WebGLProgram } from './WebGLProgram.js';
7 8
import { ShaderLib } from '../shaders/ShaderLib.js';
import { UniformsUtils } from '../shaders/UniformsUtils.js';
R
Rich Harris 已提交
9

10
function WebGLPrograms( renderer, extensions, capabilities ) {
G
gero3 已提交
11

12
	var programs = [];
G
gero3 已提交
13

14 15 16 17 18 19 20
	var isWebGL2 = capabilities.isWebGL2;
	var logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
	var floatVertexTextures = capabilities.floatVertexTextures;
	var precision = capabilities.precision;
	var maxVertexUniforms = capabilities.maxVertexUniforms;
	var vertexTextures = capabilities.vertexTextures;

G
gero3 已提交
21 22
	var shaderIDs = {
		MeshDepthMaterial: 'depth',
W
WestLangley 已提交
23
		MeshDistanceMaterial: 'distanceRGBA',
G
gero3 已提交
24 25 26 27
		MeshNormalMaterial: 'normal',
		MeshBasicMaterial: 'basic',
		MeshLambertMaterial: 'lambert',
		MeshPhongMaterial: 'phong',
28
		MeshToonMaterial: 'toon',
29
		MeshStandardMaterial: 'physical',
W
WestLangley 已提交
30
		MeshPhysicalMaterial: 'physical',
W
WestLangley 已提交
31
		MeshMatcapMaterial: 'matcap',
G
gero3 已提交
32 33
		LineBasicMaterial: 'basic',
		LineDashedMaterial: 'dashed',
34
		PointsMaterial: 'points',
35 36
		ShadowMaterial: 'shadow',
		SpriteMaterial: 'sprite'
G
gero3 已提交
37
	};
G
gero3 已提交
38

M
Mr.doob 已提交
39
	var parameterNames = [
G
gero3 已提交
40
		"precision", "isWebGL2", "supportsVertexTextures", "outputEncoding", "instancing", "numMultiviewViews",
G
gero3 已提交
41
		"map", "mapEncoding", "matcap", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding", "envMapCubeUV",
42
		"lightMap", "lightMapEncoding", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "tangentSpaceNormalMap", "clearcoatNormalMap", "displacementMap", "specularMap",
T
Takahiro 已提交
43
		"roughnessMap", "metalnessMap", "gradientMap",
44
		"alphaMap", "combine", "vertexColors", "vertexTangents", "vertexUvs", "uvsVertexOnly", "fog", "useFog", "fogExp2",
M
Mr.doob 已提交
45 46
		"flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
		"maxBones", "useVertexTexture", "morphTargets", "morphNormals",
47
		"maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
48
		"numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights",
G
gero3 已提交
49
		"numDirLightShadows", "numPointLightShadows", "numSpotLightShadows",
50
		"shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
51
		"alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering",
52
		"sheen", "transparent"
M
Mr.doob 已提交
53
	];
G
gero3 已提交
54

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
	function getShaderObject( material, shaderID ) {

		var shaderobject;

		if ( shaderID ) {

			var shader = ShaderLib[ shaderID ];

			shaderobject = {
				name: material.type,
				uniforms: UniformsUtils.clone( shader.uniforms ),
				vertexShader: shader.vertexShader,
				fragmentShader: shader.fragmentShader
			};

		} else {

			shaderobject = {
				name: material.type,
				uniforms: material.uniforms,
				vertexShader: material.vertexShader,
				fragmentShader: material.fragmentShader
			};

		}

		return shaderobject;

	}
G
gero3 已提交
84

M
Mr.doob 已提交
85
	function allocateBones( object ) {
G
gero3 已提交
86

87 88 89
		var skeleton = object.skeleton;
		var bones = skeleton.bones;

90
		if ( floatVertexTextures ) {
91

G
gero3 已提交
92 93 94 95 96 97 98 99 100 101 102
			return 1024;

		} else {

			// default for when object is not specified
			// ( for example when prebuilding shader to be used with multiple objects )
			//
			//  - leave some extra space for other uniforms
			//  - limit here is ANGLE's 254 max uniform vectors
			//    (up to 54 should be safe)

103
			var nVertexUniforms = maxVertexUniforms;
G
gero3 已提交
104 105
			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );

106
			var maxBones = Math.min( nVertexMatrices, bones.length );
G
gero3 已提交
107

108
			if ( maxBones < bones.length ) {
G
gero3 已提交
109

110 111
				console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
				return 0;
G
gero3 已提交
112 113 114 115 116 117 118 119

			}

			return maxBones;

		}

	}
G
gero3 已提交
120

121
	function getTextureEncodingFromMap( map ) {
122 123

		var encoding;
M
Mr.doob 已提交
124 125

		if ( ! map ) {
M
Mr.doob 已提交
126

R
Rich Harris 已提交
127
			encoding = LinearEncoding;
M
Mr.doob 已提交
128

129
		} else if ( map.isTexture ) {
M
Mr.doob 已提交
130

131
			encoding = map.encoding;
M
Mr.doob 已提交
132

133
		} else if ( map.isWebGLRenderTarget ) {
M
Mr.doob 已提交
134

135
			console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." );
136
			encoding = map.texture.encoding;
M
Mr.doob 已提交
137

138 139 140
		}

		return encoding;
M
Mr.doob 已提交
141

142 143
	}

M
Mr.doob 已提交
144 145 146 147 148 149
	this.getParameters = function ( material, lights, shadows, scene, nClipPlanes, nClipIntersection, object ) {

		var fog = scene.fog;
		var environment = material.isMeshStandardMaterial ? scene.environment : null;

		var envMap = material.envMap || environment;
M
Mr.doob 已提交
150

G
gero3 已提交
151
		var shaderID = shaderIDs[ material.type ];
M
Mr.doob 已提交
152

G
gero3 已提交
153
		// heuristics to create shader parameters according to lights in the scene
G
gero3 已提交
154 155
		// (not to blow over maxLights budget)

156
		var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
G
gero3 已提交
157 158 159

		if ( material.precision !== null ) {

G
gero3 已提交
160
			precision = capabilities.getMaxPrecision( material.precision );
G
gero3 已提交
161 162 163

			if ( precision !== material.precision ) {

164
				console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
G
gero3 已提交
165 166 167 168

			}

		}
M
Mr.doob 已提交
169

170 171 172
		var shaderobject = getShaderObject( material, shaderID );
		material.onBeforeCompile( shaderobject, renderer );

173
		var currentRenderTarget = renderer.getRenderTarget();
G
gero3 已提交
174
		var numMultiviewViews = currentRenderTarget && currentRenderTarget.isWebGLMultiviewRenderTarget ? currentRenderTarget.numViews : 0;
175

G
gero3 已提交
176
		var parameters = {
G
gero3 已提交
177

178
			isWebGL2: isWebGL2,
M
Mr.doob 已提交
179

G
gero3 已提交
180
			shaderID: shaderID,
181 182 183 184 185 186 187 188 189
			shaderName: shaderobject.name,

			uniforms: shaderobject.uniforms,
			vertexShader: shaderobject.vertexShader,
			fragmentShader: shaderobject.fragmentShader,
			defines: material.defines,

			isRawShaderMaterial: material.isRawShaderMaterial,
			isShaderMaterial: material.isShaderMaterial,
G
gero3 已提交
190 191

			precision: precision,
M
Mr.doob 已提交
192 193 194

			instancing: object.isInstancedMesh === true,

195
			supportsVertexTextures: vertexTextures,
G
gero3 已提交
196
			numMultiviewViews: numMultiviewViews,
197
			outputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding,
G
gero3 已提交
198
			map: !! material.map,
M
Mugen87 已提交
199
			mapEncoding: getTextureEncodingFromMap( material.map ),
W
WestLangley 已提交
200
			matcap: !! material.matcap,
M
Mugen87 已提交
201
			matcapEncoding: getTextureEncodingFromMap( material.matcap ),
M
Mr.doob 已提交
202 203 204 205
			envMap: !! envMap,
			envMapMode: envMap && envMap.mapping,
			envMapEncoding: getTextureEncodingFromMap( envMap ),
			envMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ),
G
gero3 已提交
206
			lightMap: !! material.lightMap,
M
Mugen87 已提交
207
			lightMapEncoding: getTextureEncodingFromMap( material.lightMap ),
G
gero3 已提交
208 209
			aoMap: !! material.aoMap,
			emissiveMap: !! material.emissiveMap,
M
Mugen87 已提交
210
			emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),
G
gero3 已提交
211 212
			bumpMap: !! material.bumpMap,
			normalMap: !! material.normalMap,
W
WestLangley 已提交
213
			objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
214
			tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,
215
			clearcoatNormalMap: !! material.clearcoatNormalMap,
216
			displacementMap: !! material.displacementMap,
W
WestLangley 已提交
217 218
			roughnessMap: !! material.roughnessMap,
			metalnessMap: !! material.metalnessMap,
G
gero3 已提交
219 220 221
			specularMap: !! material.specularMap,
			alphaMap: !! material.alphaMap,

T
Takahiro 已提交
222
			gradientMap: !! material.gradientMap,
T
Takahiro 已提交
223

224
			sheen: !! material.sheen,
225

G
gero3 已提交
226 227
			combine: material.combine,

228
			vertexTangents: ( material.normalMap && material.vertexTangents ),
G
gero3 已提交
229
			vertexColors: material.vertexColors,
230
			vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.displacementMap,
231
			uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap ) && !! material.displacementMap,
G
gero3 已提交
232

M
Mr.doob 已提交
233
			fog: !! fog,
G
gero3 已提交
234
			useFog: material.fog,
E
Elias Hasle 已提交
235
			fogExp2: ( fog && fog.isFogExp2 ),
G
gero3 已提交
236

237
			flatShading: material.flatShading,
G
gero3 已提交
238 239

			sizeAttenuation: material.sizeAttenuation,
240
			logarithmicDepthBuffer: logarithmicDepthBuffer,
G
gero3 已提交
241

M
Mr.doob 已提交
242
			skinning: material.skinning && maxBones > 0,
G
gero3 已提交
243
			maxBones: maxBones,
244
			useVertexTexture: floatVertexTextures,
G
gero3 已提交
245 246 247

			morphTargets: material.morphTargets,
			morphNormals: material.morphNormals,
M
Mr.doob 已提交
248 249
			maxMorphTargets: renderer.maxMorphTargets,
			maxMorphNormals: renderer.maxMorphNormals,
G
gero3 已提交
250

251 252 253
			numDirLights: lights.directional.length,
			numPointLights: lights.point.length,
			numSpotLights: lights.spot.length,
254
			numRectAreaLights: lights.rectArea.length,
255
			numHemiLights: lights.hemi.length,
256

257 258 259 260
			numDirLightShadows: lights.directionalShadowMap.length,
			numPointLightShadows: lights.pointShadowMap.length,
			numSpotLightShadows: lights.spotShadowMap.length,

T
tschw 已提交
261
			numClippingPlanes: nClipPlanes,
262
			numClipIntersection: nClipIntersection,
T
tschw 已提交
263

264
			dithering: material.dithering,
265
			transparent: material.transparent,
266

267
			shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
M
Mr.doob 已提交
268
			shadowMapType: renderer.shadowMap.type,
G
gero3 已提交
269

W
WestLangley 已提交
270
			toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
271
			physicallyCorrectLights: renderer.physicallyCorrectLights,
B
Ben Houston 已提交
272

273 274
			premultipliedAlpha: material.premultipliedAlpha,

G
gero3 已提交
275
			alphaTest: material.alphaTest,
R
Rich Harris 已提交
276 277
			doubleSided: material.side === DoubleSide,
			flipSided: material.side === BackSide,
278

279 280 281 282 283
			depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false,

			index0AttributeName: material.index0AttributeName,

			extensionDerivatives: material.extensions && material.extensions.derivatives,
284
			extensionFragDepth: material.extensions && material.extensions.fragDepth,
285
			extensionDrawbuffers: material.extensions && material.extensions.drawBuffers,
286 287
			extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,

288 289 290
			rendererExtensionFragDepth: isWebGL2 || extensions.get( 'EXT_frag_depth' ) !== null,
			rendererExtensionDrawBuffers: isWebGL2 || extensions.get( 'WEBGL_draw_buffers' ) !== null,
			rendererExtensionShaderTextureLod: isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) !== null,
291 292

			onBeforeCompile: material.onBeforeCompile
G
gero3 已提交
293 294

		};
295

G
gero3 已提交
296
		return parameters;
G
gero3 已提交
297

G
gero3 已提交
298
	};
G
gero3 已提交
299

300
	this.getProgramCacheKey = function ( parameters ) {
G
gero3 已提交
301

M
Mr.doob 已提交
302
		var array = [];
G
gero3 已提交
303 304 305

		if ( parameters.shaderID ) {

M
Mr.doob 已提交
306
			array.push( parameters.shaderID );
G
gero3 已提交
307 308 309

		} else {

310 311
			array.push( parameters.fragmentShader );
			array.push( parameters.vertexShader );
G
gero3 已提交
312 313 314

		}

315
		if ( parameters.defines !== undefined ) {
G
gero3 已提交
316

317
			for ( var name in parameters.defines ) {
G
gero3 已提交
318

M
Mr.doob 已提交
319
				array.push( name );
320
				array.push( parameters.defines[ name ] );
G
gero3 已提交
321 322 323 324 325

			}

		}

326
		if ( parameters.isRawShaderMaterial === undefined ) {
G
gero3 已提交
327

E
Emmett Lalish 已提交
328 329 330 331 332
			for ( var i = 0; i < parameterNames.length; i ++ ) {

				array.push( parameters[ parameterNames[ i ] ] );

			}
G
gero3 已提交
333

E
Emmett Lalish 已提交
334 335
			array.push( renderer.outputEncoding );
			array.push( renderer.gammaFactor );
M
Mr.doob 已提交
336

E
Emmett Lalish 已提交
337
		}
338

339
		array.push( parameters.onBeforeCompile.toString() );
W
WestLangley 已提交
340

M
Mr.doob 已提交
341
		return array.join();
G
gero3 已提交
342 343 344

	};

345
	this.acquireProgram = function ( parameters, cacheKey ) {
G
gero3 已提交
346 347 348 349

		var program;

		// Check if code has been already compiled
G
gero3 已提交
350 351
		for ( var p = 0, pl = programs.length; p < pl; p ++ ) {

352
			var preexistingProgram = programs[ p ];
G
gero3 已提交
353

354
			if ( preexistingProgram.cacheKey === cacheKey ) {
G
gero3 已提交
355

356
				program = preexistingProgram;
357
				++ program.usedTimes;
G
gero3 已提交
358 359 360 361 362 363 364 365

				break;

			}

		}

		if ( program === undefined ) {
G
gero3 已提交
366

367
			program = new WebGLProgram( renderer, cacheKey, parameters );
G
gero3 已提交
368
			programs.push( program );
G
gero3 已提交
369

G
gero3 已提交
370
		}
G
gero3 已提交
371

372
		return program;
G
gero3 已提交
373

374 375
	};

M
Mr.doob 已提交
376
	this.releaseProgram = function ( program ) {
377 378 379 380 381 382 383 384 385 386 387 388 389 390

		if ( -- program.usedTimes === 0 ) {

			// Remove from unordered set
			var i = programs.indexOf( program );
			programs[ i ] = programs[ programs.length - 1 ];
			programs.pop();

			// Free WebGL resources
			program.destroy();

		}

	};
G
gero3 已提交
391

392 393 394
	// Exposed for resource monitoring & error feedback via renderer.info:
	this.programs = programs;

M
Mr.doob 已提交
395
}
R
Rich Harris 已提交
396 397


398
export { WebGLPrograms };