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 52
		"alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering",
		"sheen"
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

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

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

272 273
			premultipliedAlpha: material.premultipliedAlpha,

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

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

			index0AttributeName: material.index0AttributeName,

			extensionDerivatives: material.extensions && material.extensions.derivatives,
			extensionFragDepth: material.extensions && material.extensions.frawbuffers,
			extensionDrawbuffers: material.extensions && material.extensions.drawbuffers,
			extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,

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

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

		};
294

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

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

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

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

		if ( parameters.shaderID ) {

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

		} else {

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

		}

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

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

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

			}

		}

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

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

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

			}
G
gero3 已提交
332

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

E
Emmett Lalish 已提交
336
		}
337

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

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

	};

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

		var program;

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

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

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

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

				break;

			}

		}

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

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

G
gero3 已提交
369
		}
G
gero3 已提交
370

371
		return program;
G
gero3 已提交
372

373 374
	};

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

		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 已提交
390

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

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


397
export { WebGLPrograms };