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

5
import { BackSide, DoubleSide, FlatShading, CubeUVRefractionMapping, CubeUVReflectionMapping, GammaEncoding, LinearEncoding } from '../../constants';
R
Rich Harris 已提交
6 7
import { WebGLProgram } from './WebGLProgram';

M
Mr.doob 已提交
8
function WebGLPrograms( renderer, capabilities ) {
G
gero3 已提交
9

10
	var programs = [];
G
gero3 已提交
11

G
gero3 已提交
12 13 14 15 16 17
	var shaderIDs = {
		MeshDepthMaterial: 'depth',
		MeshNormalMaterial: 'normal',
		MeshBasicMaterial: 'basic',
		MeshLambertMaterial: 'lambert',
		MeshPhongMaterial: 'phong',
T
Takahiro 已提交
18
		MeshToonMaterial: 'phong',
19
		MeshStandardMaterial: 'physical',
W
WestLangley 已提交
20
		MeshPhysicalMaterial: 'physical',
G
gero3 已提交
21 22
		LineBasicMaterial: 'basic',
		LineDashedMaterial: 'dashed',
23
		PointsMaterial: 'points'
G
gero3 已提交
24
	};
G
gero3 已提交
25

M
Mr.doob 已提交
26
	var parameterNames = [
27 28
		"precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding",
		"lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap",
T
Takahiro 已提交
29
		"roughnessMap", "metalnessMap", "gradientMap",
M
Mr.doob 已提交
30 31 32
		"alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
		"flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
		"maxBones", "useVertexTexture", "morphTargets", "morphNormals",
33
		"maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
34
		"numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights",
35
		"shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
36
		"alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering"
M
Mr.doob 已提交
37
	];
G
gero3 已提交
38 39


M
Mr.doob 已提交
40
	function allocateBones( object ) {
G
gero3 已提交
41

42 43 44 45 46
		var skeleton = object.skeleton;
		var bones = skeleton.bones;

		if ( capabilities.floatVertexTextures ) {

G
gero3 已提交
47 48 49 50 51 52 53 54 55 56 57
			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)

G
gero3 已提交
58
			var nVertexUniforms = capabilities.maxVertexUniforms;
G
gero3 已提交
59 60
			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );

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

63
			if ( maxBones < bones.length ) {
G
gero3 已提交
64

65 66
				console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
				return 0;
G
gero3 已提交
67 68 69 70 71 72 73 74

			}

			return maxBones;

		}

	}
G
gero3 已提交
75

76
	function getTextureEncodingFromMap( map, gammaOverrideLinear ) {
77 78

		var encoding;
M
Mr.doob 已提交
79 80

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

R
Rich Harris 已提交
82
			encoding = LinearEncoding;
M
Mr.doob 已提交
83

84
		} else if ( map.isTexture ) {
M
Mr.doob 已提交
85

86
			encoding = map.encoding;
M
Mr.doob 已提交
87

88
		} else if ( map.isWebGLRenderTarget ) {
M
Mr.doob 已提交
89

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

93 94 95
		}

		// add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point.
R
Rich Harris 已提交
96
		if ( encoding === LinearEncoding && gammaOverrideLinear ) {
M
Mr.doob 已提交
97

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

100 101 102
		}

		return encoding;
M
Mr.doob 已提交
103

104 105
	}

106
	this.getParameters = function ( material, lights, fog, nClipPlanes, nClipIntersection, object ) {
M
Mr.doob 已提交
107

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

G
gero3 已提交
110
		// heuristics to create shader parameters according to lights in the scene
G
gero3 已提交
111 112
		// (not to blow over maxLights budget)

113
		var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
M
Mr.doob 已提交
114
		var precision = renderer.getPrecision();
G
gero3 已提交
115 116 117

		if ( material.precision !== null ) {

G
gero3 已提交
118
			precision = capabilities.getMaxPrecision( material.precision );
G
gero3 已提交
119 120 121

			if ( precision !== material.precision ) {

122
				console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
G
gero3 已提交
123 124 125 126

			}

		}
M
Mr.doob 已提交
127

128
		var currentRenderTarget = renderer.getRenderTarget();
129

G
gero3 已提交
130
		var parameters = {
G
gero3 已提交
131 132

			shaderID: shaderID,
G
gero3 已提交
133 134

			precision: precision,
G
gero3 已提交
135
			supportsVertexTextures: capabilities.vertexTextures,
136
			outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),
G
gero3 已提交
137
			map: !! material.map,
138
			mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),
G
gero3 已提交
139 140
			envMap: !! material.envMap,
			envMapMode: material.envMap && material.envMap.mapping,
141
			envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ),
R
Rich Harris 已提交
142
			envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ),
G
gero3 已提交
143 144 145
			lightMap: !! material.lightMap,
			aoMap: !! material.aoMap,
			emissiveMap: !! material.emissiveMap,
146
			emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ),
G
gero3 已提交
147 148
			bumpMap: !! material.bumpMap,
			normalMap: !! material.normalMap,
149
			displacementMap: !! material.displacementMap,
W
WestLangley 已提交
150 151
			roughnessMap: !! material.roughnessMap,
			metalnessMap: !! material.metalnessMap,
G
gero3 已提交
152 153 154
			specularMap: !! material.specularMap,
			alphaMap: !! material.alphaMap,

T
Takahiro 已提交
155
			gradientMap: !! material.gradientMap,
T
Takahiro 已提交
156

G
gero3 已提交
157 158 159 160
			combine: material.combine,

			vertexColors: material.vertexColors,

M
Mr.doob 已提交
161
			fog: !! fog,
G
gero3 已提交
162
			useFog: material.fog,
M
Mr.doob 已提交
163
			fogExp: ( fog && fog.isFogExp2 ),
G
gero3 已提交
164

R
Rich Harris 已提交
165
			flatShading: material.shading === FlatShading,
G
gero3 已提交
166 167

			sizeAttenuation: material.sizeAttenuation,
168
			logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
G
gero3 已提交
169

M
Mr.doob 已提交
170
			skinning: material.skinning && maxBones > 0,
G
gero3 已提交
171
			maxBones: maxBones,
172
			useVertexTexture: capabilities.floatVertexTextures,
G
gero3 已提交
173 174 175

			morphTargets: material.morphTargets,
			morphNormals: material.morphNormals,
M
Mr.doob 已提交
176 177
			maxMorphTargets: renderer.maxMorphTargets,
			maxMorphNormals: renderer.maxMorphNormals,
G
gero3 已提交
178

179 180 181
			numDirLights: lights.directional.length,
			numPointLights: lights.point.length,
			numSpotLights: lights.spot.length,
182
			numRectAreaLights: lights.rectArea.length,
183
			numHemiLights: lights.hemi.length,
184

T
tschw 已提交
185
			numClippingPlanes: nClipPlanes,
186
			numClipIntersection: nClipIntersection,
T
tschw 已提交
187

188
			dithering: material.dithering,
189

190
			shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && lights.shadows.length > 0,
M
Mr.doob 已提交
191
			shadowMapType: renderer.shadowMap.type,
G
gero3 已提交
192

B
Ben Houston 已提交
193
			toneMapping: renderer.toneMapping,
194
			physicallyCorrectLights: renderer.physicallyCorrectLights,
B
Ben Houston 已提交
195

196 197
			premultipliedAlpha: material.premultipliedAlpha,

G
gero3 已提交
198
			alphaTest: material.alphaTest,
R
Rich Harris 已提交
199 200
			doubleSided: material.side === DoubleSide,
			flipSided: material.side === BackSide,
201

202
			depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false
G
gero3 已提交
203 204

		};
205

G
gero3 已提交
206
		return parameters;
G
gero3 已提交
207

G
gero3 已提交
208
	};
G
gero3 已提交
209

M
Mr.doob 已提交
210
	this.getProgramCode = function ( material, parameters ) {
G
gero3 已提交
211

M
Mr.doob 已提交
212
		var array = [];
G
gero3 已提交
213 214 215

		if ( parameters.shaderID ) {

M
Mr.doob 已提交
216
			array.push( parameters.shaderID );
G
gero3 已提交
217 218 219

		} else {

M
Mr.doob 已提交
220 221
			array.push( material.fragmentShader );
			array.push( material.vertexShader );
G
gero3 已提交
222 223 224 225 226 227 228

		}

		if ( material.defines !== undefined ) {

			for ( var name in material.defines ) {

M
Mr.doob 已提交
229 230
				array.push( name );
				array.push( material.defines[ name ] );
G
gero3 已提交
231 232 233 234 235

			}

		}

G
gero3 已提交
236 237
		for ( var i = 0; i < parameterNames.length; i ++ ) {

M
Mr.doob 已提交
238
			array.push( parameters[ parameterNames[ i ] ] );
G
gero3 已提交
239 240 241

		}

M
Mr.doob 已提交
242 243
		array.push( material.onBeforeCompile.toString() );

244 245
		array.push( renderer.gammaOutput );

M
Mr.doob 已提交
246
		return array.join();
G
gero3 已提交
247 248 249

	};

250
	this.acquireProgram = function ( material, parameters, code ) {
G
gero3 已提交
251 252 253 254

		var program;

		// Check if code has been already compiled
G
gero3 已提交
255 256 257 258 259 260 261
		for ( var p = 0, pl = programs.length; p < pl; p ++ ) {

			var programInfo = programs[ p ];

			if ( programInfo.code === code ) {

				program = programInfo;
262
				++ program.usedTimes;
G
gero3 已提交
263 264 265 266 267 268 269 270

				break;

			}

		}

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

R
Rich Harris 已提交
272
			program = new WebGLProgram( renderer, code, material, parameters );
G
gero3 已提交
273
			programs.push( program );
G
gero3 已提交
274

G
gero3 已提交
275
		}
G
gero3 已提交
276

277
		return program;
G
gero3 已提交
278

279 280
	};

M
Mr.doob 已提交
281
	this.releaseProgram = function ( program ) {
282 283 284 285 286 287 288 289 290 291 292 293 294 295

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

297 298 299
	// Exposed for resource monitoring & error feedback via renderer.info:
	this.programs = programs;

M
Mr.doob 已提交
300
}
R
Rich Harris 已提交
301 302


303
export { WebGLPrograms };