WebGLPrograms.js 11.9 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, bindingStates ) {
G
gero3 已提交
11

M
Mugen87 已提交
12
	const programs = [];
G
gero3 已提交
13

M
Mugen87 已提交
14 15 16 17 18
	const isWebGL2 = capabilities.isWebGL2;
	const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
	const floatVertexTextures = capabilities.floatVertexTextures;
	const maxVertexUniforms = capabilities.maxVertexUniforms;
	const vertexTextures = capabilities.vertexTextures;
19

M
Mugen87 已提交
20 21 22
	let precision = capabilities.precision;

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

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

M
Mr.doob 已提交
56
	function allocateBones( object ) {
G
gero3 已提交
57

M
Mugen87 已提交
58 59
		const skeleton = object.skeleton;
		const bones = skeleton.bones;
60

61
		if ( floatVertexTextures ) {
62

G
gero3 已提交
63 64 65 66 67 68 69 70 71 72 73
			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)

M
Mugen87 已提交
74 75
			const nVertexUniforms = maxVertexUniforms;
			const nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
G
gero3 已提交
76

M
Mugen87 已提交
77
			const maxBones = Math.min( nVertexMatrices, bones.length );
G
gero3 已提交
78

79
			if ( maxBones < bones.length ) {
G
gero3 已提交
80

81 82
				console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
				return 0;
G
gero3 已提交
83 84 85 86 87 88 89 90

			}

			return maxBones;

		}

	}
G
gero3 已提交
91

92
	function getTextureEncodingFromMap( map ) {
93

M
Mugen87 已提交
94
		let encoding;
M
Mr.doob 已提交
95 96

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

R
Rich Harris 已提交
98
			encoding = LinearEncoding;
M
Mr.doob 已提交
99

100
		} else if ( map.isTexture ) {
M
Mr.doob 已提交
101

102
			encoding = map.encoding;
M
Mr.doob 已提交
103

104
		} else if ( map.isWebGLRenderTarget ) {
M
Mr.doob 已提交
105

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

109 110 111
		}

		return encoding;
M
Mr.doob 已提交
112

113 114
	}

M
Mr.doob 已提交
115
	function getParameters( material, lights, shadows, scene, nClipPlanes, nClipIntersection, object ) {
M
Mr.doob 已提交
116

M
Mugen87 已提交
117 118
		const fog = scene.fog;
		const environment = material.isMeshStandardMaterial ? scene.environment : null;
M
Mr.doob 已提交
119

M
Mugen87 已提交
120
		const envMap = material.envMap || environment;
M
Mr.doob 已提交
121

M
Mugen87 已提交
122
		const shaderID = shaderIDs[ material.type ];
M
Mr.doob 已提交
123

G
gero3 已提交
124
		// heuristics to create shader parameters according to lights in the scene
G
gero3 已提交
125 126
		// (not to blow over maxLights budget)

M
Mugen87 已提交
127
		const maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
G
gero3 已提交
128 129 130

		if ( material.precision !== null ) {

G
gero3 已提交
131
			precision = capabilities.getMaxPrecision( material.precision );
G
gero3 已提交
132 133 134

			if ( precision !== material.precision ) {

135
				console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
G
gero3 已提交
136 137 138 139

			}

		}
M
Mr.doob 已提交
140

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
		let vertexShader, fragmentShader;

		if ( shaderID ) {

			const shader = ShaderLib[ shaderID ];

			vertexShader = shader.vertexShader;
			fragmentShader = shader.fragmentShader;

		} else {

			vertexShader = material.vertexShader;
			fragmentShader = material.fragmentShader;

		}
156

M
Mugen87 已提交
157
		const currentRenderTarget = renderer.getRenderTarget();
158

M
Mugen87 已提交
159
		const parameters = {
G
gero3 已提交
160

161
			isWebGL2: isWebGL2,
M
Mr.doob 已提交
162

G
gero3 已提交
163
			shaderID: shaderID,
164
			shaderName: material.name || material.type,
165

166 167
			vertexShader: vertexShader,
			fragmentShader: fragmentShader,
168 169 170 171
			defines: material.defines,

			isRawShaderMaterial: material.isRawShaderMaterial,
			isShaderMaterial: material.isShaderMaterial,
G
gero3 已提交
172 173

			precision: precision,
M
Mr.doob 已提交
174 175 176

			instancing: object.isInstancedMesh === true,

177
			supportsVertexTextures: vertexTextures,
178
			outputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding,
G
gero3 已提交
179
			map: !! material.map,
M
Mugen87 已提交
180
			mapEncoding: getTextureEncodingFromMap( material.map ),
W
WestLangley 已提交
181
			matcap: !! material.matcap,
M
Mugen87 已提交
182
			matcapEncoding: getTextureEncodingFromMap( material.matcap ),
M
Mr.doob 已提交
183 184 185 186
			envMap: !! envMap,
			envMapMode: envMap && envMap.mapping,
			envMapEncoding: getTextureEncodingFromMap( envMap ),
			envMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ),
G
gero3 已提交
187
			lightMap: !! material.lightMap,
M
Mugen87 已提交
188
			lightMapEncoding: getTextureEncodingFromMap( material.lightMap ),
G
gero3 已提交
189 190
			aoMap: !! material.aoMap,
			emissiveMap: !! material.emissiveMap,
M
Mugen87 已提交
191
			emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),
G
gero3 已提交
192 193
			bumpMap: !! material.bumpMap,
			normalMap: !! material.normalMap,
W
WestLangley 已提交
194
			objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
195
			tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,
196 197
			clearcoatMap: !! material.clearcoatMap,
			clearcoatRoughnessMap: !! material.clearcoatRoughnessMap,
198
			clearcoatNormalMap: !! material.clearcoatNormalMap,
199
			displacementMap: !! material.displacementMap,
W
WestLangley 已提交
200 201
			roughnessMap: !! material.roughnessMap,
			metalnessMap: !! material.metalnessMap,
G
gero3 已提交
202 203 204
			specularMap: !! material.specularMap,
			alphaMap: !! material.alphaMap,

T
Takahiro 已提交
205
			gradientMap: !! material.gradientMap,
T
Takahiro 已提交
206

207
			sheen: !! material.sheen,
208

209 210
			transmissionMap: !! material.transmissionMap,

G
gero3 已提交
211 212
			combine: material.combine,

213
			vertexTangents: ( material.normalMap && material.vertexTangents ),
G
gero3 已提交
214
			vertexColors: material.vertexColors,
215 216
			vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.displacementMap || !! material.transmissionMap,
			uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.transmissionMap ) && !! material.displacementMap,
G
gero3 已提交
217

M
Mr.doob 已提交
218
			fog: !! fog,
G
gero3 已提交
219
			useFog: material.fog,
E
Elias Hasle 已提交
220
			fogExp2: ( fog && fog.isFogExp2 ),
G
gero3 已提交
221

222
			flatShading: material.flatShading,
G
gero3 已提交
223 224

			sizeAttenuation: material.sizeAttenuation,
225
			logarithmicDepthBuffer: logarithmicDepthBuffer,
G
gero3 已提交
226

M
Mr.doob 已提交
227
			skinning: material.skinning && maxBones > 0,
G
gero3 已提交
228
			maxBones: maxBones,
229
			useVertexTexture: floatVertexTextures,
G
gero3 已提交
230 231 232

			morphTargets: material.morphTargets,
			morphNormals: material.morphNormals,
M
Mr.doob 已提交
233 234
			maxMorphTargets: renderer.maxMorphTargets,
			maxMorphNormals: renderer.maxMorphNormals,
G
gero3 已提交
235

236 237 238
			numDirLights: lights.directional.length,
			numPointLights: lights.point.length,
			numSpotLights: lights.spot.length,
239
			numRectAreaLights: lights.rectArea.length,
240
			numHemiLights: lights.hemi.length,
241

242 243 244 245
			numDirLightShadows: lights.directionalShadowMap.length,
			numPointLightShadows: lights.pointShadowMap.length,
			numSpotLightShadows: lights.spotShadowMap.length,

T
tschw 已提交
246
			numClippingPlanes: nClipPlanes,
247
			numClipIntersection: nClipIntersection,
T
tschw 已提交
248

249
			dithering: material.dithering,
250

251
			shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
M
Mr.doob 已提交
252
			shadowMapType: renderer.shadowMap.type,
G
gero3 已提交
253

W
WestLangley 已提交
254
			toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
255
			physicallyCorrectLights: renderer.physicallyCorrectLights,
B
Ben Houston 已提交
256

257 258
			premultipliedAlpha: material.premultipliedAlpha,

G
gero3 已提交
259
			alphaTest: material.alphaTest,
R
Rich Harris 已提交
260 261
			doubleSided: material.side === DoubleSide,
			flipSided: material.side === BackSide,
262

263 264 265 266 267
			depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false,

			index0AttributeName: material.index0AttributeName,

			extensionDerivatives: material.extensions && material.extensions.derivatives,
268
			extensionFragDepth: material.extensions && material.extensions.fragDepth,
M
Michael Herzog 已提交
269
			extensionDrawBuffers: material.extensions && material.extensions.drawBuffers,
270 271
			extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,

272 273 274
			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,
275

276
			customProgramCacheKey: material.customProgramCacheKey()
G
gero3 已提交
277 278

		};
279

G
gero3 已提交
280
		return parameters;
G
gero3 已提交
281

M
Mr.doob 已提交
282
	}
G
gero3 已提交
283

M
Mr.doob 已提交
284
	function getProgramCacheKey( parameters ) {
G
gero3 已提交
285

M
Mugen87 已提交
286
		const array = [];
G
gero3 已提交
287 288 289

		if ( parameters.shaderID ) {

M
Mr.doob 已提交
290
			array.push( parameters.shaderID );
G
gero3 已提交
291 292 293

		} else {

294 295
			array.push( parameters.fragmentShader );
			array.push( parameters.vertexShader );
G
gero3 已提交
296 297 298

		}

299
		if ( parameters.defines !== undefined ) {
G
gero3 已提交
300

M
Mugen87 已提交
301
			for ( const name in parameters.defines ) {
G
gero3 已提交
302

M
Mr.doob 已提交
303
				array.push( name );
304
				array.push( parameters.defines[ name ] );
G
gero3 已提交
305 306 307 308 309

			}

		}

310
		if ( parameters.isRawShaderMaterial === undefined ) {
G
gero3 已提交
311

M
Mugen87 已提交
312
			for ( let i = 0; i < parameterNames.length; i ++ ) {
E
Emmett Lalish 已提交
313 314 315 316

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

			}
G
gero3 已提交
317

E
Emmett Lalish 已提交
318 319
			array.push( renderer.outputEncoding );
			array.push( renderer.gammaFactor );
M
Mr.doob 已提交
320

E
Emmett Lalish 已提交
321
		}
322

323
		array.push( parameters.customProgramCacheKey );
W
WestLangley 已提交
324

M
Mr.doob 已提交
325
		return array.join();
G
gero3 已提交
326

M
Mr.doob 已提交
327
	}
G
gero3 已提交
328

329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
	function getUniforms( material ) {

		const shaderID = shaderIDs[ material.type ];
		let uniforms;

		if ( shaderID ) {

			const shader = ShaderLib[ shaderID ];
			uniforms = UniformsUtils.clone( shader.uniforms );

		} else {

			uniforms = material.uniforms;

		}

		return uniforms;

	}

M
Mr.doob 已提交
349
	function acquireProgram( parameters, cacheKey ) {
G
gero3 已提交
350

M
Mugen87 已提交
351
		let program;
G
gero3 已提交
352 353

		// Check if code has been already compiled
M
Mugen87 已提交
354
		for ( let p = 0, pl = programs.length; p < pl; p ++ ) {
G
gero3 已提交
355

M
Mugen87 已提交
356
			const preexistingProgram = programs[ p ];
G
gero3 已提交
357

358
			if ( preexistingProgram.cacheKey === cacheKey ) {
G
gero3 已提交
359

360
				program = preexistingProgram;
361
				++ program.usedTimes;
G
gero3 已提交
362 363 364 365 366 367 368 369

				break;

			}

		}

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

371
			program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates );
G
gero3 已提交
372
			programs.push( program );
G
gero3 已提交
373

G
gero3 已提交
374
		}
G
gero3 已提交
375

376
		return program;
G
gero3 已提交
377

M
Mr.doob 已提交
378
	}
379

M
Mr.doob 已提交
380
	function releaseProgram( program ) {
381 382 383 384

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

			// Remove from unordered set
M
Mugen87 已提交
385
			const i = programs.indexOf( program );
386 387 388 389 390 391 392 393
			programs[ i ] = programs[ programs.length - 1 ];
			programs.pop();

			// Free WebGL resources
			program.destroy();

		}

M
Mr.doob 已提交
394
	}
G
gero3 已提交
395

M
Mr.doob 已提交
396 397 398
	return {
		getParameters: getParameters,
		getProgramCacheKey: getProgramCacheKey,
399
		getUniforms: getUniforms,
M
Mr.doob 已提交
400 401 402 403 404
		acquireProgram: acquireProgram,
		releaseProgram: releaseProgram,
		// Exposed for resource monitoring & error feedback via renderer.info:
		programs: programs
	};
405

M
Mr.doob 已提交
406
}
R
Rich Harris 已提交
407 408


409
export { WebGLPrograms };