WebGLPrograms.js 12.0 KB
Newer Older
1
import { BackSide, DoubleSide, CubeUVRefractionMapping, CubeUVReflectionMapping, LinearEncoding, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping } from '../../constants.js';
B
bentok 已提交
2
import { WebGLProgram } from './WebGLProgram.js';
3 4
import { ShaderLib } from '../shaders/ShaderLib.js';
import { UniformsUtils } from '../shaders/UniformsUtils.js';
R
Rich Harris 已提交
5

M
Mugen87 已提交
6
function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingStates, clipping ) {
G
gero3 已提交
7

M
Mugen87 已提交
8
	const programs = [];
G
gero3 已提交
9

M
Mugen87 已提交
10 11 12 13 14
	const isWebGL2 = capabilities.isWebGL2;
	const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
	const floatVertexTextures = capabilities.floatVertexTextures;
	const maxVertexUniforms = capabilities.maxVertexUniforms;
	const vertexTextures = capabilities.vertexTextures;
15

M
Mugen87 已提交
16 17 18
	let precision = capabilities.precision;

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

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

M
Mugen87 已提交
51
	function getMaxBones( object ) {
G
gero3 已提交
52

M
Mugen87 已提交
53 54
		const skeleton = object.skeleton;
		const bones = skeleton.bones;
55

56
		if ( floatVertexTextures ) {
57

G
gero3 已提交
58 59 60 61 62 63 64 65 66 67 68
			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 已提交
69 70
			const nVertexUniforms = maxVertexUniforms;
			const nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
G
gero3 已提交
71

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

74
			if ( maxBones < bones.length ) {
G
gero3 已提交
75

76 77
				console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
				return 0;
G
gero3 已提交
78 79 80 81 82 83 84 85

			}

			return maxBones;

		}

	}
G
gero3 已提交
86

87
	function getTextureEncodingFromMap( map ) {
88

M
Mugen87 已提交
89
		let encoding;
M
Mr.doob 已提交
90

91
		if ( map && map.isTexture ) {
M
Mr.doob 已提交
92

93
			encoding = map.encoding;
M
Mr.doob 已提交
94

95
		} else if ( map && map.isWebGLRenderTarget ) {
M
Mr.doob 已提交
96

G
Garrett Johnson 已提交
97
			console.warn( 'THREE.WebGLPrograms.getTextureEncodingFromMap: don\'t use render targets as textures. Use their .texture property instead.' );
98
			encoding = map.texture.encoding;
M
Mr.doob 已提交
99

100 101 102 103
		} else {

			encoding = LinearEncoding;

104 105 106
		}

		return encoding;
M
Mr.doob 已提交
107

108 109
	}

M
Mugen87 已提交
110
	function getParameters( material, lights, shadows, scene, object ) {
M
Mr.doob 已提交
111

M
Mugen87 已提交
112 113
		const fog = scene.fog;
		const environment = material.isMeshStandardMaterial ? scene.environment : null;
M
Mr.doob 已提交
114

115
		const envMap = cubemaps.get( material.envMap || environment );
M
Mr.doob 已提交
116

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

G
gero3 已提交
119
		// heuristics to create shader parameters according to lights in the scene
G
gero3 已提交
120 121
		// (not to blow over maxLights budget)

M
Mugen87 已提交
122
		const maxBones = object.isSkinnedMesh ? getMaxBones( object ) : 0;
G
gero3 已提交
123 124 125

		if ( material.precision !== null ) {

G
gero3 已提交
126
			precision = capabilities.getMaxPrecision( material.precision );
G
gero3 已提交
127 128 129

			if ( precision !== material.precision ) {

130
				console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
G
gero3 已提交
131 132 133 134

			}

		}
M
Mr.doob 已提交
135

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
		let vertexShader, fragmentShader;

		if ( shaderID ) {

			const shader = ShaderLib[ shaderID ];

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

		} else {

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

		}
151

M
Mugen87 已提交
152
		const currentRenderTarget = renderer.getRenderTarget();
153

M
Mugen87 已提交
154
		const parameters = {
G
gero3 已提交
155

156
			isWebGL2: isWebGL2,
M
Mr.doob 已提交
157

G
gero3 已提交
158
			shaderID: shaderID,
159
			shaderName: material.type,
160

161 162
			vertexShader: vertexShader,
			fragmentShader: fragmentShader,
163 164
			defines: material.defines,

M
Mr.doob 已提交
165 166
			isRawShaderMaterial: material.isRawShaderMaterial === true,
			glslVersion: material.glslVersion,
G
gero3 已提交
167 168

			precision: precision,
M
Mr.doob 已提交
169 170

			instancing: object.isInstancedMesh === true,
171
			instancingColor: object.isInstancedMesh === true && object.instanceColor !== null,
M
Mr.doob 已提交
172

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

T
Takahiro 已提交
201
			gradientMap: !! material.gradientMap,
T
Takahiro 已提交
202

203
			sheen: !! material.sheen,
204

205 206
			transmissionMap: !! material.transmissionMap,

G
gero3 已提交
207 208
			combine: material.combine,

209
			vertexTangents: ( material.normalMap && material.vertexTangents ),
G
gero3 已提交
210
			vertexColors: material.vertexColors,
M
Mr.doob 已提交
211
			vertexAlphas: material.vertexColors === true && object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4,
212 213
			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 已提交
214

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

219
			flatShading: !! material.flatShading,
G
gero3 已提交
220 221

			sizeAttenuation: material.sizeAttenuation,
222
			logarithmicDepthBuffer: logarithmicDepthBuffer,
G
gero3 已提交
223

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

			morphTargets: material.morphTargets,
			morphNormals: material.morphNormals,

231 232 233
			numDirLights: lights.directional.length,
			numPointLights: lights.point.length,
			numSpotLights: lights.spot.length,
234
			numRectAreaLights: lights.rectArea.length,
235
			numHemiLights: lights.hemi.length,
236

237 238 239 240
			numDirLightShadows: lights.directionalShadowMap.length,
			numPointLightShadows: lights.pointShadowMap.length,
			numSpotLightShadows: lights.spotShadowMap.length,

M
Mugen87 已提交
241 242
			numClippingPlanes: clipping.numPlanes,
			numClipIntersection: clipping.numIntersection,
T
tschw 已提交
243

244
			dithering: material.dithering,
245

246
			shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
M
Mr.doob 已提交
247
			shadowMapType: renderer.shadowMap.type,
G
gero3 已提交
248

W
WestLangley 已提交
249
			toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
250
			physicallyCorrectLights: renderer.physicallyCorrectLights,
B
Ben Houston 已提交
251

252 253
			premultipliedAlpha: material.premultipliedAlpha,

G
gero3 已提交
254
			alphaTest: material.alphaTest,
R
Rich Harris 已提交
255 256
			doubleSided: material.side === DoubleSide,
			flipSided: material.side === BackSide,
257

258 259 260 261 262
			depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false,

			index0AttributeName: material.index0AttributeName,

			extensionDerivatives: material.extensions && material.extensions.derivatives,
263
			extensionFragDepth: material.extensions && material.extensions.fragDepth,
M
Michael Herzog 已提交
264
			extensionDrawBuffers: material.extensions && material.extensions.drawBuffers,
265 266
			extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,

267 268 269
			rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ),
			rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ),
			rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ),
270

M
Mr.doob 已提交
271
			customProgramCacheKey: material.customProgramCacheKey()
G
gero3 已提交
272 273

		};
274

G
gero3 已提交
275
		return parameters;
G
gero3 已提交
276

M
Mr.doob 已提交
277
	}
G
gero3 已提交
278

M
Mr.doob 已提交
279
	function getProgramCacheKey( parameters ) {
G
gero3 已提交
280

M
Mugen87 已提交
281
		const array = [];
G
gero3 已提交
282 283 284

		if ( parameters.shaderID ) {

M
Mr.doob 已提交
285
			array.push( parameters.shaderID );
G
gero3 已提交
286 287 288

		} else {

289 290
			array.push( parameters.fragmentShader );
			array.push( parameters.vertexShader );
G
gero3 已提交
291 292 293

		}

294
		if ( parameters.defines !== undefined ) {
G
gero3 已提交
295

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

M
Mr.doob 已提交
298
				array.push( name );
299
				array.push( parameters.defines[ name ] );
G
gero3 已提交
300 301 302 303 304

			}

		}

305
		if ( parameters.isRawShaderMaterial === false ) {
G
gero3 已提交
306

M
Mugen87 已提交
307
			for ( let i = 0; i < parameterNames.length; i ++ ) {
E
Emmett Lalish 已提交
308 309 310 311

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

			}
G
gero3 已提交
312

E
Emmett Lalish 已提交
313 314
			array.push( renderer.outputEncoding );
			array.push( renderer.gammaFactor );
M
Mr.doob 已提交
315

E
Emmett Lalish 已提交
316
		}
317

318
		array.push( parameters.customProgramCacheKey );
W
WestLangley 已提交
319

M
Mr.doob 已提交
320
		return array.join();
G
gero3 已提交
321

M
Mr.doob 已提交
322
	}
G
gero3 已提交
323

324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
	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 已提交
344
	function acquireProgram( parameters, cacheKey ) {
G
gero3 已提交
345

M
Mugen87 已提交
346
		let program;
G
gero3 已提交
347 348

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

M
Mugen87 已提交
351
			const 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, bindingStates );
G
gero3 已提交
367
			programs.push( program );
G
gero3 已提交
368

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

371
		return program;
G
gero3 已提交
372

M
Mr.doob 已提交
373
	}
374

M
Mr.doob 已提交
375
	function releaseProgram( program ) {
376 377 378 379

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

			// Remove from unordered set
M
Mugen87 已提交
380
			const i = programs.indexOf( program );
381 382 383 384 385 386 387 388
			programs[ i ] = programs[ programs.length - 1 ];
			programs.pop();

			// Free WebGL resources
			program.destroy();

		}

M
Mr.doob 已提交
389
	}
G
gero3 已提交
390

M
Mr.doob 已提交
391 392 393
	return {
		getParameters: getParameters,
		getProgramCacheKey: getProgramCacheKey,
394
		getUniforms: getUniforms,
M
Mr.doob 已提交
395 396 397 398 399
		acquireProgram: acquireProgram,
		releaseProgram: releaseProgram,
		// Exposed for resource monitoring & error feedback via renderer.info:
		programs: programs
	};
400

M
Mr.doob 已提交
401
}
R
Rich Harris 已提交
402 403


404
export { WebGLPrograms };