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

B
bentok 已提交
5 6
import { LinearFilter, NearestFilter, RGBFormat, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, ClampToEdgeWrapping, NearestMipMapLinearFilter, NearestMipMapNearestFilter } from '../../constants.js';
import { _Math } from '../../math/Math.js';
R
Rich Harris 已提交
7

M
Mugen87 已提交
8
function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
9

M
Mugen87 已提交
10
	var _videoTextures = {};
11
	var _canvas;
12

M
Mr.doob 已提交
13
	//
14

M
Mr.doob 已提交
15
	function clampToMaxSize( image, maxSize ) {
16 17 18

		if ( image.width > maxSize || image.height > maxSize ) {

19
			if ( 'data' in image ) {
20

21 22
				console.warn( 'THREE.WebGLRenderer: image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
				return;
23

24
			}
25

26 27
			// Warning: Scaling through the canvas will only work with images that use
			// premultiplied alpha.
28

29
			var scale = maxSize / Math.max( image.width, image.height );
30

31 32 33
			var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
			canvas.width = Math.floor( image.width * scale );
			canvas.height = Math.floor( image.height * scale );
34

35 36
			var context = canvas.getContext( '2d' );
			context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
37

38
			console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height );
39

40
			return canvas;
41 42 43 44 45 46 47 48 49

		}

		return image;

	}

	function isPowerOfTwo( image ) {

R
Rich Harris 已提交
50
		return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height );
51 52 53 54 55

	}

	function makePowerOfTwo( image ) {

56
		if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof ImageBitmap ) {
57

58
			if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
59

60 61
			_canvas.width = _Math.floorPowerOfTwo( image.width );
			_canvas.height = _Math.floorPowerOfTwo( image.height );
62

63 64
			var context = _canvas.getContext( '2d' );
			context.drawImage( image, 0, 0, _canvas.width, _canvas.height );
65

66
			console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + _canvas.width + 'x' + _canvas.height );
67 68

			return _canvas;
69 70 71 72 73 74 75 76 77

		}

		return image;

	}

	function textureNeedsPowerOfTwo( texture ) {

T
Takahiro 已提交
78
		if ( capabilities.isWebGL2 ) return false;
T
Takahiro 已提交
79

M
Mr.doob 已提交
80 81 82
		return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
			( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );

83 84
	}

85
	function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) {
86 87 88

		return texture.generateMipmaps && isPowerOfTwo &&
			texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
89 90 91

	}

92
	function generateMipmap( target, texture, width, height ) {
93 94 95

		_gl.generateMipmap( target );

96
		var textureProperties = properties.get( texture );
A
aardgoose 已提交
97 98

		// Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11
99
		textureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;
100 101 102

	}

103 104
	function getInternalFormat( glFormat, glType ) {

T
Takahiro 已提交
105
		if ( ! capabilities.isWebGL2 ) return glFormat;
T
Takahiro 已提交
106

107 108
		var internalFormat = glFormat;

A
artur.trzesiok 已提交
109
		if ( glFormat === _gl.RED ) {
A
artur.trzesiok 已提交
110

111 112 113
			if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F;
			if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F;
			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8;
A
artur.trzesiok 已提交
114

A
artur.trzesiok 已提交
115
		}
A
artur.trzesiok 已提交
116

117 118
		if ( glFormat === _gl.RGB ) {

119 120 121
			if ( glType === _gl.FLOAT ) internalFormat = _gl.RGB32F;
			if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGB16F;
			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RGB8;
122 123 124 125

		}

		if ( glFormat === _gl.RGBA ) {
T
Takahiro 已提交
126

127 128 129 130 131 132 133 134 135 136 137 138 139 140
			if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F;
			if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F;
			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RGBA8;

		}

		if ( internalFormat === _gl.R16F || internalFormat === _gl.R32F ||
			internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) {

			extensions.get( 'EXT_color_buffer_float' );

		} else if ( internalFormat === _gl.RGB16F || internalFormat === _gl.RGB32F ) {

			console.warn( 'THREE.WebGLRenderer: Floating point textures with RGB format not supported. Please use RGBA instead.' );
T
Takahiro 已提交
141 142

		}
143

144
		return internalFormat;
145 146 147

	}

148 149
	// Fallback filters for non-power-of-2 textures

M
Mr.doob 已提交
150
	function filterFallback( f ) {
151

R
Rich Harris 已提交
152
		if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) {
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171

			return _gl.NEAREST;

		}

		return _gl.LINEAR;

	}

	//

	function onTextureDispose( event ) {

		var texture = event.target;

		texture.removeEventListener( 'dispose', onTextureDispose );

		deallocateTexture( texture );

M
Mugen87 已提交
172 173 174 175 176
		if ( texture.isVideoTexture ) {

			delete _videoTextures[ texture.id ];

		}
177

M
Mugen87 已提交
178
		info.memory.textures --;
179 180 181 182 183 184 185 186 187 188 189

	}

	function onRenderTargetDispose( event ) {

		var renderTarget = event.target;

		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );

		deallocateRenderTarget( renderTarget );

M
Mugen87 已提交
190
		info.memory.textures --;
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216

	}

	//

	function deallocateTexture( texture ) {

		var textureProperties = properties.get( texture );

		if ( texture.image && textureProperties.__image__webglTextureCube ) {

			// cube texture

			_gl.deleteTexture( textureProperties.__image__webglTextureCube );

		} else {

			// 2D texture

			if ( textureProperties.__webglInit === undefined ) return;

			_gl.deleteTexture( textureProperties.__webglTexture );

		}

		// remove all webgl properties
217
		properties.remove( texture );
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

	}

	function deallocateRenderTarget( renderTarget ) {

		var renderTargetProperties = properties.get( renderTarget );
		var textureProperties = properties.get( renderTarget.texture );

		if ( ! renderTarget ) return;

		if ( textureProperties.__webglTexture !== undefined ) {

			_gl.deleteTexture( textureProperties.__webglTexture );

		}

		if ( renderTarget.depthTexture ) {

			renderTarget.depthTexture.dispose();

		}

240
		if ( renderTarget.isWebGLRenderTargetCube ) {
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255

			for ( var i = 0; i < 6; i ++ ) {

				_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
				if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );

			}

		} else {

			_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
			if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );

		}

256 257
		properties.remove( renderTarget.texture );
		properties.remove( renderTarget );
258 259 260 261 262 263 264 265 266 267 268

	}

	//



	function setTexture2D( texture, slot ) {

		var textureProperties = properties.get( texture );

269 270
		if ( texture.isVideoTexture ) updateVideoTexture( texture );

271 272 273 274 275 276
		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {

			var image = texture.image;

			if ( image === undefined ) {

277
				console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );
278

279
			} else if ( image.complete === false ) {
280

281
				console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
282

283
			} else {
284

285 286
				uploadTexture( textureProperties, texture, slot );
				return;
287

288
			}
289 290 291 292 293 294 295 296

		}

		state.activeTexture( _gl.TEXTURE0 + slot );
		state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );

	}

A
artur.trzesiok 已提交
297
	function setTexture3D( texture, slot ) {
A
artur.trzesiok 已提交
298

A
artur.trzesiok 已提交
299 300 301
		var textureProperties = properties.get( texture );

		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
A
artur.trzesiok 已提交
302 303 304 305

			uploadTexture( textureProperties, texture, slot );
			return;

A
artur.trzesiok 已提交
306 307 308 309 310 311
		}

		state.activeTexture( _gl.TEXTURE0 + slot );
		state.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture );

	}
A
artur.trzesiok 已提交
312 313


M
Mr.doob 已提交
314
	function setTextureCube( texture, slot ) {
315 316 317 318 319 320 321 322 323 324 325 326 327

		var textureProperties = properties.get( texture );

		if ( texture.image.length === 6 ) {

			if ( texture.version > 0 && textureProperties.__version !== texture.version ) {

				if ( ! textureProperties.__image__webglTextureCube ) {

					texture.addEventListener( 'dispose', onTextureDispose );

					textureProperties.__image__webglTextureCube = _gl.createTexture();

M
Mugen87 已提交
328
					info.memory.textures ++;
329 330 331 332 333 334 335 336

				}

				state.activeTexture( _gl.TEXTURE0 + slot );
				state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );

				_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );

M
Mr.doob 已提交
337 338
				var isCompressed = ( texture && texture.isCompressedTexture );
				var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356

				var cubeImage = [];

				for ( var i = 0; i < 6; i ++ ) {

					if ( ! isCompressed && ! isDataTexture ) {

						cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize );

					} else {

						cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];

					}

				}

				var image = cubeImage[ 0 ],
M
Mugen87 已提交
357 358
					isPowerOfTwoImage = isPowerOfTwo( image ),
					glFormat = utils.convert( texture.format ),
T
Takahiro 已提交
359 360
					glType = utils.convert( texture.type ),
					glInternalFormat = getInternalFormat( glFormat, glType );
361 362 363 364 365 366 367 368 369

				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );

				for ( var i = 0; i < 6; i ++ ) {

					if ( ! isCompressed ) {

						if ( isDataTexture ) {

T
Takahiro 已提交
370
							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
371 372 373

						} else {

T
Takahiro 已提交
374
							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
375 376 377 378 379 380 381 382 383 384 385

						}

					} else {

						var mipmap, mipmaps = cubeImage[ i ].mipmaps;

						for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {

							mipmap = mipmaps[ j ];

R
Rich Harris 已提交
386
							if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
387 388 389

								if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {

T
Takahiro 已提交
390
									state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
391 392 393

								} else {

M
Mugen87 已提交
394
									console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
395 396 397 398 399

								}

							} else {

T
Takahiro 已提交
400
								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
401 402 403 404 405 406 407 408 409

							}

						}

					}

				}

410 411
				if ( ! isCompressed ) {

412
					textureProperties.__maxMipLevel = 0;
413 414 415

				} else {

416
					textureProperties.__maxMipLevel = mipmaps.length - 1;
417 418 419

				}

420
				if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {
421

422 423
					// We assume images for cube map have the same size.
					generateMipmap( _gl.TEXTURE_CUBE_MAP, texture, image.width, image.height );
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441

				}

				textureProperties.__version = texture.version;

				if ( texture.onUpdate ) texture.onUpdate( texture );

			} else {

				state.activeTexture( _gl.TEXTURE0 + slot );
				state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );

			}

		}

	}

M
Mr.doob 已提交
442
	function setTextureCubeDynamic( texture, slot ) {
443 444 445 446 447 448

		state.activeTexture( _gl.TEXTURE0 + slot );
		state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );

	}

M
Mr.doob 已提交
449
	function setTextureParameters( textureType, texture, isPowerOfTwoImage ) {
450 451 452 453 454

		var extension;

		if ( isPowerOfTwoImage ) {

455 456
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) );
457

458 459
			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) );
460 461 462 463 464 465

		} else {

			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );

R
Rich Harris 已提交
466
			if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
467

468
				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );
469 470 471 472 473 474

			}

			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );

R
Rich Harris 已提交
475
			if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
476

477
				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );
478 479 480 481 482 483 484 485 486

			}

		}

		extension = extensions.get( 'EXT_texture_filter_anisotropic' );

		if ( extension ) {

R
Rich Harris 已提交
487
			if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
T
Takahiro 已提交
488
			if ( texture.type === HalfFloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;
489 490 491 492 493 494 495 496 497 498 499 500 501 502

			if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {

				_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
				properties.get( texture ).__currentAnisotropy = texture.anisotropy;

			}

		}

	}

	function uploadTexture( textureProperties, texture, slot ) {

A
artur.trzesiok 已提交
503 504
		var textureType;

T
Takahiro 已提交
505
		if ( texture.isDataTexture3D ) {
A
artur.trzesiok 已提交
506 507 508 509 510 511 512

			textureType = _gl.TEXTURE_3D;

		} else {

			textureType = _gl.TEXTURE_2D;

A
artur.trzesiok 已提交
513 514
		}

515 516 517 518 519 520 521 522 523

		if ( textureProperties.__webglInit === undefined ) {

			textureProperties.__webglInit = true;

			texture.addEventListener( 'dispose', onTextureDispose );

			textureProperties.__webglTexture = _gl.createTexture();

M
Mugen87 已提交
524
			info.memory.textures ++;
525 526 527

		}
		state.activeTexture( _gl.TEXTURE0 + slot );
A
artur.trzesiok 已提交
528 529 530 531 532


		state.bindTexture( textureType, textureProperties.__webglTexture );


533 534 535 536 537 538 539 540 541 542 543 544 545 546

		_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
		_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
		_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );

		var image = clampToMaxSize( texture.image, capabilities.maxTextureSize );

		if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( image ) === false ) {

			image = makePowerOfTwo( image );

		}

		var isPowerOfTwoImage = isPowerOfTwo( image ),
M
Mugen87 已提交
547
			glFormat = utils.convert( texture.format ),
T
Takahiro 已提交
548 549
			glType = utils.convert( texture.type ),
			glInternalFormat = getInternalFormat( glFormat, glType );
550

A
artur.trzesiok 已提交
551
		setTextureParameters( textureType, texture, isPowerOfTwoImage );
552 553 554

		var mipmap, mipmaps = texture.mipmaps;

555
		if ( texture.isDepthTexture ) {
556 557 558

			// populate depth texture with dummy data

T
Takahiro 已提交
559
			glInternalFormat = _gl.DEPTH_COMPONENT;
560

R
Rich Harris 已提交
561
			if ( texture.type === FloatType ) {
562

T
Takahiro 已提交
563
				if ( ! capabilities.isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' );
T
Takahiro 已提交
564
				glInternalFormat = _gl.DEPTH_COMPONENT32F;
565

T
Takahiro 已提交
566
			} else if ( capabilities.isWebGL2 ) {
567 568

				// WebGL 2.0 requires signed internalformat for glTexImage2D
T
Takahiro 已提交
569
				glInternalFormat = _gl.DEPTH_COMPONENT16;
570 571 572

			}

T
Takahiro 已提交
573
			if ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
T
Takahiro 已提交
574 575 576 577 578 579

				// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
				// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
				// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
				if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {

M
Mugen87 已提交
580
					console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
T
Takahiro 已提交
581 582

					texture.type = UnsignedShortType;
583
					glType = utils.convert( texture.type );
T
Takahiro 已提交
584 585 586 587 588

				}

			}

589 590
			// Depth stencil textures need the DEPTH_STENCIL internal format
			// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
591
			if ( texture.format === DepthStencilFormat ) {
592

T
Takahiro 已提交
593
				glInternalFormat = _gl.DEPTH_STENCIL;
594

T
Takahiro 已提交
595 596 597 598 599
				// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
				// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
				// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
				if ( texture.type !== UnsignedInt248Type ) {

M
Mr.doob 已提交
600
					console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
T
Takahiro 已提交
601 602

					texture.type = UnsignedInt248Type;
603
					glType = utils.convert( texture.type );
T
Takahiro 已提交
604 605 606

				}

607 608
			}

T
Takahiro 已提交
609
			state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
610

611
		} else if ( texture.isDataTexture ) {
612 613 614 615 616 617 618 619 620 621

			// use manually created mipmaps if available
			// if there are no manual mipmaps
			// set 0 level mipmap and then use GL to generate other mipmap levels

			if ( mipmaps.length > 0 && isPowerOfTwoImage ) {

				for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {

					mipmap = mipmaps[ i ];
T
Takahiro 已提交
622
					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
623 624 625 626

				}

				texture.generateMipmaps = false;
627
				textureProperties.__maxMipLevel = mipmaps.length - 1;
628 629 630

			} else {

T
Takahiro 已提交
631
				state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
632
				textureProperties.__maxMipLevel = 0;
633 634 635

			}

636
		} else if ( texture.isCompressedTexture ) {
637 638 639 640 641

			for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {

				mipmap = mipmaps[ i ];

R
Rich Harris 已提交
642
				if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
643 644 645

					if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {

T
Takahiro 已提交
646
						state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
647 648 649

					} else {

M
Mugen87 已提交
650
						console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
651 652 653 654 655

					}

				} else {

T
Takahiro 已提交
656
					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
657 658 659 660 661

				}

			}

662
			textureProperties.__maxMipLevel = mipmaps.length - 1;
663

T
Takahiro 已提交
664
		} else if ( texture.isDataTexture3D ) {
A
artur.trzesiok 已提交
665

T
Takahiro 已提交
666
			state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
A
artur.trzesiok 已提交
667 668
			textureProperties.__maxMipLevel = 0;

669 670 671 672 673 674 675 676 677 678 679 680 681
		} else {

			// regular Texture (image, video, canvas)

			// use manually created mipmaps if available
			// if there are no manual mipmaps
			// set 0 level mipmap and then use GL to generate other mipmap levels

			if ( mipmaps.length > 0 && isPowerOfTwoImage ) {

				for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {

					mipmap = mipmaps[ i ];
T
Takahiro 已提交
682
					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );
683 684 685 686

				}

				texture.generateMipmaps = false;
687
				textureProperties.__maxMipLevel = mipmaps.length - 1;
688 689 690

			} else {

T
Takahiro 已提交
691
				state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
692
				textureProperties.__maxMipLevel = 0;
693 694 695 696 697

			}

		}

698 699
		if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {

700
			generateMipmap( _gl.TEXTURE_2D, texture, image.width, image.height );
701 702

		}
703 704 705 706 707 708 709 710 711 712

		textureProperties.__version = texture.version;

		if ( texture.onUpdate ) texture.onUpdate( texture );

	}

	// Render targets

	// Setup storage for target texture and bind it to correct framebuffer
M
Mr.doob 已提交
713
	function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
714

715 716
		var glFormat = utils.convert( renderTarget.texture.format );
		var glType = utils.convert( renderTarget.texture.type );
T
Takahiro 已提交
717
		var glInternalFormat = getInternalFormat( glFormat, glType );
718
		state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
719 720 721 722 723 724 725
		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
		_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );

	}

	// Setup storage for internal depth/stencil buffers and bind to correct framebuffer
M
Mr.doob 已提交
726
	function setupRenderBufferStorage( renderbuffer, renderTarget ) {
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751

		_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );

		if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {

			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );

		} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {

			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );

		} else {

			// FIXME: We don't support !depth !stencil
			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );

		}

		_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );

	}

	// Setup resources for a Depth Texture for a FBO (needs an extension)
M
Mr.doob 已提交
752
	function setupDepthTexture( framebuffer, renderTarget ) {
753

754
		var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube );
M
Mugen87 已提交
755
		if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
756 757 758

		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );

M
Mugen87 已提交
759
		if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
760

M
Mugen87 已提交
761
			throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
762 763 764 765

		}

		// upload an empty depth texture with framebuffer size
M
Mugen87 已提交
766
		if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
767 768
				renderTarget.depthTexture.image.width !== renderTarget.width ||
				renderTarget.depthTexture.image.height !== renderTarget.height ) {
M
Mugen87 已提交
769

770 771 772
			renderTarget.depthTexture.image.width = renderTarget.width;
			renderTarget.depthTexture.image.height = renderTarget.height;
			renderTarget.depthTexture.needsUpdate = true;
M
Mugen87 已提交
773

774 775 776 777 778
		}

		setTexture2D( renderTarget.depthTexture, 0 );

		var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
779

780
		if ( renderTarget.depthTexture.format === DepthFormat ) {
781 782 783

			_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );

784
		} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
785 786 787 788 789

			_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );

		} else {

M
Mugen87 已提交
790
			throw new Error( 'Unknown depthTexture format' );
791 792

		}
793 794 795 796 797 798 799 800

	}

	// Setup GL resources for a non-texture depth buffer
	function setupDepthRenderbuffer( renderTarget ) {

		var renderTargetProperties = properties.get( renderTarget );

801
		var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
802 803 804

		if ( renderTarget.depthTexture ) {

M
Mugen87 已提交
805
			if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846

			setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );

		} else {

			if ( isCube ) {

				renderTargetProperties.__webglDepthbuffer = [];

				for ( var i = 0; i < 6; i ++ ) {

					_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] );
					renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
					setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget );

				}

			} else {

				_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
				renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
				setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget );

			}

		}

		_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );

	}

	// Set up GL resources for the render target
	function setupRenderTarget( renderTarget ) {

		var renderTargetProperties = properties.get( renderTarget );
		var textureProperties = properties.get( renderTarget.texture );

		renderTarget.addEventListener( 'dispose', onRenderTargetDispose );

		textureProperties.__webglTexture = _gl.createTexture();

M
Mugen87 已提交
847
		info.memory.textures ++;
848

849
		var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882
		var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );

		// Setup framebuffer

		if ( isCube ) {

			renderTargetProperties.__webglFramebuffer = [];

			for ( var i = 0; i < 6; i ++ ) {

				renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();

			}

		} else {

			renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();

		}

		// Setup color buffer

		if ( isCube ) {

			state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
			setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo );

			for ( var i = 0; i < 6; i ++ ) {

				setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );

			}

883 884
			if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) {

885
				generateMipmap( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, renderTarget.width, renderTarget.height );
886 887 888

			}

889 890 891 892 893 894 895 896
			state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );

		} else {

			state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
			setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo );
			setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D );

897 898
			if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) {

899
				generateMipmap( _gl.TEXTURE_2D, renderTarget.texture, renderTarget.width, renderTarget.height );
900 901 902

			}

903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
			state.bindTexture( _gl.TEXTURE_2D, null );

		}

		// Setup depth and stencil buffers

		if ( renderTarget.depthBuffer ) {

			setupDepthRenderbuffer( renderTarget );

		}

	}

	function updateRenderTargetMipmap( renderTarget ) {

		var texture = renderTarget.texture;
920
		var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
921

922
		if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) {
923

924
			var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
925 926 927
			var webglTexture = properties.get( texture ).__webglTexture;

			state.bindTexture( target, webglTexture );
928
			generateMipmap( target, texture, renderTarget.width, renderTarget.height );
929 930 931 932 933 934
			state.bindTexture( target, null );

		}

	}

935 936 937
	function updateVideoTexture( texture ) {

		var id = texture.id;
M
Mugen87 已提交
938
		var frame = info.render.frame;
939 940

		// Check the last frame we updated the VideoTexture
M
Mugen87 已提交
941

942
		if ( _videoTextures[ id ] !== frame ) {
M
Mugen87 已提交
943

944 945
			_videoTextures[ id ] = frame;
			texture.update();
M
Mugen87 已提交
946 947 948 949 950

		}

	}

951
	this.setTexture2D = setTexture2D;
A
artur.trzesiok 已提交
952
	this.setTexture3D = setTexture3D;
953 954 955 956 957
	this.setTextureCube = setTextureCube;
	this.setTextureCubeDynamic = setTextureCubeDynamic;
	this.setupRenderTarget = setupRenderTarget;
	this.updateRenderTargetMipmap = updateRenderTargetMipmap;

M
Mr.doob 已提交
958
}
R
Rich Harris 已提交
959 960


961
export { WebGLTextures };