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

5 6 7
import { BackSide, DoubleSide, FlatShading, CubeUVRefractionMapping, CubeUVReflectionMapping, GammaEncoding, LinearEncoding, FloatType, RGBAFormat } from '../../constants';
import { _Math } from '../../math/Math';
import { DataTexture } from '../../textures/DataTexture';
R
Rich Harris 已提交
8 9
import { WebGLProgram } from './WebGLProgram';

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

12
	var programs = [];
G
gero3 已提交
13

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

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


M
Mr.doob 已提交
42
	function allocateBones( object ) {
G
gero3 已提交
43

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
		var skeleton = object.skeleton;
		var bones = skeleton.bones;

		if ( capabilities.floatVertexTextures ) {

			if ( skeleton.boneTexture === undefined ) {

				// layout (1 matrix = 4 pixels)
				//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
				//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
				//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
				//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
				//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)


				var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
				size = _Math.nextPowerOfTwo( Math.ceil( size ) );
				size = Math.max( size, 4 );

				var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
				boneMatrices.set( skeleton.boneMatrices ); // copy current values

				var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );

				skeleton.boneMatrices = boneMatrices;
				skeleton.boneTexture = boneTexture;
				skeleton.boneTextureSize = size;

			}
G
gero3 已提交
73 74 75 76 77 78 79 80 81 82 83 84

			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 已提交
85
			var nVertexUniforms = capabilities.maxVertexUniforms;
G
gero3 已提交
86 87
			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );

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

90
			if ( maxBones < bones.length ) {
G
gero3 已提交
91

92 93
				console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
				return 0;
G
gero3 已提交
94 95 96 97 98 99 100 101

			}

			return maxBones;

		}

	}
G
gero3 已提交
102

103
	function getTextureEncodingFromMap( map, gammaOverrideLinear ) {
104 105

		var encoding;
M
Mr.doob 已提交
106 107

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

R
Rich Harris 已提交
109
			encoding = LinearEncoding;
M
Mr.doob 已提交
110

111
		} else if ( map.isTexture ) {
M
Mr.doob 已提交
112

113
			encoding = map.encoding;
M
Mr.doob 已提交
114

115
		} else if ( map.isWebGLRenderTarget ) {
M
Mr.doob 已提交
116

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

120 121 122
		}

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

R
Rich Harris 已提交
125
			encoding = GammaEncoding;
M
Mr.doob 已提交
126

127 128 129
		}

		return encoding;
M
Mr.doob 已提交
130

131 132
	}

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

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

G
gero3 已提交
137
		// heuristics to create shader parameters according to lights in the scene
G
gero3 已提交
138 139
		// (not to blow over maxLights budget)

140
		var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
M
Mr.doob 已提交
141
		var precision = renderer.getPrecision();
G
gero3 已提交
142 143 144

		if ( material.precision !== null ) {

G
gero3 已提交
145
			precision = capabilities.getMaxPrecision( material.precision );
G
gero3 已提交
146 147 148

			if ( precision !== material.precision ) {

149
				console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
G
gero3 已提交
150 151 152 153

			}

		}
M
Mr.doob 已提交
154

155 156
		var currentRenderTarget = renderer.getCurrentRenderTarget();

G
gero3 已提交
157
		var parameters = {
G
gero3 已提交
158 159

			shaderID: shaderID,
G
gero3 已提交
160 161

			precision: precision,
G
gero3 已提交
162
			supportsVertexTextures: capabilities.vertexTextures,
163
			outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),
G
gero3 已提交
164
			map: !! material.map,
165
			mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),
G
gero3 已提交
166 167
			envMap: !! material.envMap,
			envMapMode: material.envMap && material.envMap.mapping,
168
			envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ),
R
Rich Harris 已提交
169
			envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ),
G
gero3 已提交
170 171 172
			lightMap: !! material.lightMap,
			aoMap: !! material.aoMap,
			emissiveMap: !! material.emissiveMap,
173
			emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ),
G
gero3 已提交
174 175
			bumpMap: !! material.bumpMap,
			normalMap: !! material.normalMap,
176
			displacementMap: !! material.displacementMap,
W
WestLangley 已提交
177 178
			roughnessMap: !! material.roughnessMap,
			metalnessMap: !! material.metalnessMap,
G
gero3 已提交
179 180 181
			specularMap: !! material.specularMap,
			alphaMap: !! material.alphaMap,

T
Takahiro 已提交
182
			gradientMap: !! material.gradientMap,
T
Takahiro 已提交
183

G
gero3 已提交
184 185 186 187
			combine: material.combine,

			vertexColors: material.vertexColors,

M
Mr.doob 已提交
188
			fog: !! fog,
G
gero3 已提交
189
			useFog: material.fog,
M
Mr.doob 已提交
190
			fogExp: ( fog && fog.isFogExp2 ),
G
gero3 已提交
191

R
Rich Harris 已提交
192
			flatShading: material.shading === FlatShading,
G
gero3 已提交
193 194

			sizeAttenuation: material.sizeAttenuation,
195
			logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
G
gero3 已提交
196

197
			skinning: material.skinning,
G
gero3 已提交
198
			maxBones: maxBones,
199
			useVertexTexture: capabilities.floatVertexTextures,
G
gero3 已提交
200 201 202

			morphTargets: material.morphTargets,
			morphNormals: material.morphNormals,
M
Mr.doob 已提交
203 204
			maxMorphTargets: renderer.maxMorphTargets,
			maxMorphNormals: renderer.maxMorphNormals,
G
gero3 已提交
205

206 207 208
			numDirLights: lights.directional.length,
			numPointLights: lights.point.length,
			numSpotLights: lights.spot.length,
209
			numRectAreaLights: lights.rectArea.length,
210
			numHemiLights: lights.hemi.length,
211

T
tschw 已提交
212
			numClippingPlanes: nClipPlanes,
213
			numClipIntersection: nClipIntersection,
T
tschw 已提交
214

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

B
Ben Houston 已提交
218
			toneMapping: renderer.toneMapping,
219
			physicallyCorrectLights: renderer.physicallyCorrectLights,
B
Ben Houston 已提交
220

221 222
			premultipliedAlpha: material.premultipliedAlpha,

G
gero3 已提交
223
			alphaTest: material.alphaTest,
R
Rich Harris 已提交
224 225
			doubleSided: material.side === DoubleSide,
			flipSided: material.side === BackSide,
226

227
			depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false
G
gero3 已提交
228 229

		};
230

G
gero3 已提交
231
		return parameters;
G
gero3 已提交
232

G
gero3 已提交
233
	};
G
gero3 已提交
234

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

M
Mr.doob 已提交
237
		var array = [];
G
gero3 已提交
238 239 240

		if ( parameters.shaderID ) {

M
Mr.doob 已提交
241
			array.push( parameters.shaderID );
G
gero3 已提交
242 243 244

		} else {

M
Mr.doob 已提交
245 246
			array.push( material.fragmentShader );
			array.push( material.vertexShader );
G
gero3 已提交
247 248 249 250 251 252 253

		}

		if ( material.defines !== undefined ) {

			for ( var name in material.defines ) {

M
Mr.doob 已提交
254 255
				array.push( name );
				array.push( material.defines[ name ] );
G
gero3 已提交
256 257 258 259 260

			}

		}

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

M
Mr.doob 已提交
263
			array.push( parameters[ parameterNames[ i ] ] );
G
gero3 已提交
264 265 266

		}

M
Mr.doob 已提交
267
		return array.join();
G
gero3 已提交
268 269 270

	};

271
	this.acquireProgram = function ( material, parameters, code ) {
G
gero3 已提交
272 273 274 275

		var program;

		// Check if code has been already compiled
G
gero3 已提交
276 277 278 279 280 281 282
		for ( var p = 0, pl = programs.length; p < pl; p ++ ) {

			var programInfo = programs[ p ];

			if ( programInfo.code === code ) {

				program = programInfo;
283
				++ program.usedTimes;
G
gero3 已提交
284 285 286 287 288 289 290 291

				break;

			}

		}

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

R
Rich Harris 已提交
293
			program = new WebGLProgram( renderer, code, material, parameters );
G
gero3 已提交
294
			programs.push( program );
G
gero3 已提交
295

G
gero3 已提交
296
		}
G
gero3 已提交
297

298
		return program;
G
gero3 已提交
299

300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
	};

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

318 319 320
	// Exposed for resource monitoring & error feedback via renderer.info:
	this.programs = programs;

M
Mr.doob 已提交
321
}
R
Rich Harris 已提交
322 323


324
export { WebGLPrograms };