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

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

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',
18
		MeshStandardMaterial: 'physical',
W
WestLangley 已提交
19
		MeshPhysicalMaterial: 'physical',
G
gero3 已提交
20 21
		LineBasicMaterial: 'basic',
		LineDashedMaterial: 'dashed',
22
		PointsMaterial: 'points'
G
gero3 已提交
23
	};
G
gero3 已提交
24

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


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

G
gero3 已提交
41
		if ( capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture ) {
G
gero3 已提交
42 43 44 45 46 47 48 49 50 51 52 53

			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 已提交
54
			var nVertexUniforms = capabilities.maxVertexUniforms;
G
gero3 已提交
55 56 57 58
			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );

			var maxBones = nVertexMatrices;

R
Rich Harris 已提交
59
			if ( object !== undefined && (object && object.isSkinnedMesh) ) {
G
gero3 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

				maxBones = Math.min( object.skeleton.bones.length, maxBones );

				if ( maxBones < object.skeleton.bones.length ) {

					console.warn( 'WebGLRenderer: too many bones - ' + object.skeleton.bones.length + ', this GPU supports just ' + maxBones + ' (try OpenGL instead of ANGLE)' );

				}

			}

			return maxBones;

		}

	}
G
gero3 已提交
76

77
	function getTextureEncodingFromMap( map, gammaOverrideLinear ) {
78 79

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

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

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

R
Rich Harris 已提交
85
		} else if ( (map && map.isTexture) ) {
M
Mr.doob 已提交
86

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

R
Rich Harris 已提交
89
		} else if ( (map && map.isWebGLRenderTarget) ) {
M
Mr.doob 已提交
90

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

94 95 96
		}

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

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

101 102 103
		}

		return encoding;
M
Mr.doob 已提交
104

105 106
	}

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

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

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

		var maxBones = allocateBones( object );
M
Mr.doob 已提交
115
		var precision = renderer.getPrecision();
G
gero3 已提交
116 117 118

		if ( material.precision !== null ) {

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

			if ( precision !== material.precision ) {

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

			}

		}
M
Mr.doob 已提交
128

129 130
		var currentRenderTarget = renderer.getCurrentRenderTarget();

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

			shaderID: shaderID,
G
gero3 已提交
134 135

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

			combine: material.combine,

			vertexColors: material.vertexColors,

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

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

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

			skinning: material.skinning,
			maxBones: maxBones,
G
gero3 已提交
171
			useVertexTexture: capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture,
G
gero3 已提交
172 173 174

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

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

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

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

B
Ben Houston 已提交
190
			toneMapping: renderer.toneMapping,
191
			physicallyCorrectLights: renderer.physicallyCorrectLights,
B
Ben Houston 已提交
192

193 194
			premultipliedAlpha: material.premultipliedAlpha,

G
gero3 已提交
195
			alphaTest: material.alphaTest,
R
Rich Harris 已提交
196 197
			doubleSided: material.side === DoubleSide,
			flipSided: material.side === BackSide,
198

199
			depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false
G
gero3 已提交
200 201

		};
202

G
gero3 已提交
203
		return parameters;
G
gero3 已提交
204

G
gero3 已提交
205
	};
G
gero3 已提交
206

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

M
Mr.doob 已提交
209
		var array = [];
G
gero3 已提交
210 211 212

		if ( parameters.shaderID ) {

M
Mr.doob 已提交
213
			array.push( parameters.shaderID );
G
gero3 已提交
214 215 216

		} else {

M
Mr.doob 已提交
217 218
			array.push( material.fragmentShader );
			array.push( material.vertexShader );
G
gero3 已提交
219 220 221 222 223 224 225

		}

		if ( material.defines !== undefined ) {

			for ( var name in material.defines ) {

M
Mr.doob 已提交
226 227
				array.push( name );
				array.push( material.defines[ name ] );
G
gero3 已提交
228 229 230 231 232

			}

		}

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

M
Mr.doob 已提交
235
			array.push( parameters[ parameterNames[ i ] ] );
G
gero3 已提交
236 237 238

		}

M
Mr.doob 已提交
239
		return array.join();
G
gero3 已提交
240 241 242

	};

243
	this.acquireProgram = function ( material, parameters, code ) {
G
gero3 已提交
244 245 246 247

		var program;

		// Check if code has been already compiled
G
gero3 已提交
248 249 250 251 252 253 254
		for ( var p = 0, pl = programs.length; p < pl; p ++ ) {

			var programInfo = programs[ p ];

			if ( programInfo.code === code ) {

				program = programInfo;
255
				++ program.usedTimes;
G
gero3 已提交
256 257 258 259 260 261 262 263

				break;

			}

		}

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

R
Rich Harris 已提交
265
			program = new WebGLProgram( renderer, code, material, parameters );
G
gero3 已提交
266
			programs.push( program );
G
gero3 已提交
267

G
gero3 已提交
268
		}
G
gero3 已提交
269

270
		return program;
G
gero3 已提交
271

272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
	};

	this.releaseProgram = function( program ) {

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

290 291 292
	// Exposed for resource monitoring & error feedback via renderer.info:
	this.programs = programs;

M
Mr.doob 已提交
293
}
R
Rich Harris 已提交
294 295


296
export { WebGLPrograms };