WebGLTextures.js 25.9 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

A
artur.trzesiok 已提交
107
		if ( glFormat === _gl.RED ) {
A
artur.trzesiok 已提交
108

A
artur.trzesiok 已提交
109 110 111
			if ( glType === _gl.FLOAT ) return _gl.R32F;
			if ( glType === _gl.HALF_FLOAT ) return _gl.R16F;
			if ( glType === _gl.UNSIGNED_BYTE ) return _gl.R8;
A
artur.trzesiok 已提交
112

A
artur.trzesiok 已提交
113
		}
A
artur.trzesiok 已提交
114

115 116 117 118 119 120 121 122 123
		if ( glFormat === _gl.RGB ) {

			if ( glType === _gl.FLOAT ) return _gl.RGB32F;
			if ( glType === _gl.HALF_FLOAT ) return _gl.RGB16F;
			if ( glType === _gl.UNSIGNED_BYTE ) return _gl.RGB8;

		}

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

			if ( glType === _gl.FLOAT ) return _gl.RGBA32F;
			if ( glType === _gl.HALF_FLOAT ) return _gl.RGBA16F;
127
			if ( glType === _gl.UNSIGNED_BYTE ) return _gl.RGBA8;
T
Takahiro 已提交
128 129

		}
130 131 132 133 134

		return glFormat;

	}

135 136
	// Fallback filters for non-power-of-2 textures

M
Mr.doob 已提交
137
	function filterFallback( f ) {
138

R
Rich Harris 已提交
139
		if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) {
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158

			return _gl.NEAREST;

		}

		return _gl.LINEAR;

	}

	//

	function onTextureDispose( event ) {

		var texture = event.target;

		texture.removeEventListener( 'dispose', onTextureDispose );

		deallocateTexture( texture );

M
Mugen87 已提交
159 160 161 162 163
		if ( texture.isVideoTexture ) {

			delete _videoTextures[ texture.id ];

		}
164

M
Mugen87 已提交
165
		info.memory.textures --;
166 167 168 169 170 171 172 173 174 175 176

	}

	function onRenderTargetDispose( event ) {

		var renderTarget = event.target;

		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );

		deallocateRenderTarget( renderTarget );

M
Mugen87 已提交
177
		info.memory.textures --;
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203

	}

	//

	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
204
		properties.remove( texture );
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226

	}

	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();

		}

227
		if ( renderTarget.isWebGLRenderTargetCube ) {
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242

			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 );

		}

243 244
		properties.remove( renderTarget.texture );
		properties.remove( renderTarget );
245 246 247 248 249 250 251 252 253 254 255

	}

	//



	function setTexture2D( texture, slot ) {

		var textureProperties = properties.get( texture );

256 257
		if ( texture.isVideoTexture ) updateVideoTexture( texture );

258 259 260 261 262 263
		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {

			var image = texture.image;

			if ( image === undefined ) {

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

266
			} else if ( image.complete === false ) {
267

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

270
			} else {
271

272 273
				uploadTexture( textureProperties, texture, slot );
				return;
274

275
			}
276 277 278 279 280 281 282 283

		}

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

	}

A
artur.trzesiok 已提交
284
	function setTexture3D( texture, slot ) {
A
artur.trzesiok 已提交
285

A
artur.trzesiok 已提交
286 287 288
		var textureProperties = properties.get( texture );

		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
A
artur.trzesiok 已提交
289 290 291 292

			uploadTexture( textureProperties, texture, slot );
			return;

A
artur.trzesiok 已提交
293 294 295 296 297 298
		}

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

	}
A
artur.trzesiok 已提交
299 300


M
Mr.doob 已提交
301
	function setTextureCube( texture, slot ) {
302 303 304 305 306 307 308 309 310 311 312 313 314

		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 已提交
315
					info.memory.textures ++;
316 317 318 319 320 321 322 323

				}

				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 已提交
324 325
				var isCompressed = ( texture && texture.isCompressedTexture );
				var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343

				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 已提交
344 345
					isPowerOfTwoImage = isPowerOfTwo( image ),
					glFormat = utils.convert( texture.format ),
T
Takahiro 已提交
346 347
					glType = utils.convert( texture.type ),
					glInternalFormat = getInternalFormat( glFormat, glType );
348 349 350 351 352 353 354 355 356

				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );

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

					if ( ! isCompressed ) {

						if ( isDataTexture ) {

T
Takahiro 已提交
357
							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
358 359 360

						} else {

T
Takahiro 已提交
361
							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
362 363 364 365 366 367 368 369 370 371 372

						}

					} else {

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

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

							mipmap = mipmaps[ j ];

R
Rich Harris 已提交
373
							if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
374 375 376

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

T
Takahiro 已提交
377
									state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
378 379 380

								} else {

M
Mugen87 已提交
381
									console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
382 383 384 385 386

								}

							} else {

T
Takahiro 已提交
387
								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
388 389 390 391 392 393 394 395 396

							}

						}

					}

				}

397 398
				if ( ! isCompressed ) {

399
					textureProperties.__maxMipLevel = 0;
400 401 402

				} else {

403
					textureProperties.__maxMipLevel = mipmaps.length - 1;
404 405 406

				}

407
				if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {
408

409 410
					// We assume images for cube map have the same size.
					generateMipmap( _gl.TEXTURE_CUBE_MAP, texture, image.width, image.height );
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428

				}

				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 已提交
429
	function setTextureCubeDynamic( texture, slot ) {
430 431 432 433 434 435

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

	}

M
Mr.doob 已提交
436
	function setTextureParameters( textureType, texture, isPowerOfTwoImage ) {
437 438 439 440 441

		var extension;

		if ( isPowerOfTwoImage ) {

442 443
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) );
444

445 446
			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) );
447 448 449 450 451 452

		} 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 已提交
453
			if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
454

455
				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );
456 457 458 459 460 461

			}

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

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

464
				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );
465 466 467 468 469 470 471 472 473

			}

		}

		extension = extensions.get( 'EXT_texture_filter_anisotropic' );

		if ( extension ) {

R
Rich Harris 已提交
474
			if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
T
Takahiro 已提交
475
			if ( texture.type === HalfFloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;
476 477 478 479 480 481 482 483 484 485 486 487 488 489

			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 已提交
490 491
		var textureType;

T
Takahiro 已提交
492
		if ( texture.isDataTexture3D ) {
A
artur.trzesiok 已提交
493 494 495 496 497 498 499

			textureType = _gl.TEXTURE_3D;

		} else {

			textureType = _gl.TEXTURE_2D;

A
artur.trzesiok 已提交
500 501
		}

502 503 504 505 506 507 508 509 510

		if ( textureProperties.__webglInit === undefined ) {

			textureProperties.__webglInit = true;

			texture.addEventListener( 'dispose', onTextureDispose );

			textureProperties.__webglTexture = _gl.createTexture();

M
Mugen87 已提交
511
			info.memory.textures ++;
512 513 514

		}
		state.activeTexture( _gl.TEXTURE0 + slot );
A
artur.trzesiok 已提交
515 516 517 518 519


		state.bindTexture( textureType, textureProperties.__webglTexture );


520 521 522 523 524 525 526 527 528 529 530 531 532 533

		_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 已提交
534
			glFormat = utils.convert( texture.format ),
T
Takahiro 已提交
535 536
			glType = utils.convert( texture.type ),
			glInternalFormat = getInternalFormat( glFormat, glType );
537

A
artur.trzesiok 已提交
538
		setTextureParameters( textureType, texture, isPowerOfTwoImage );
539 540 541

		var mipmap, mipmaps = texture.mipmaps;

542
		if ( texture.isDepthTexture ) {
543 544 545

			// populate depth texture with dummy data

T
Takahiro 已提交
546
			glInternalFormat = _gl.DEPTH_COMPONENT;
547

R
Rich Harris 已提交
548
			if ( texture.type === FloatType ) {
549

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

T
Takahiro 已提交
553
			} else if ( capabilities.isWebGL2 ) {
554 555

				// WebGL 2.0 requires signed internalformat for glTexImage2D
T
Takahiro 已提交
556
				glInternalFormat = _gl.DEPTH_COMPONENT16;
557 558 559

			}

T
Takahiro 已提交
560
			if ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
T
Takahiro 已提交
561 562 563 564 565 566

				// 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 已提交
567
					console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
T
Takahiro 已提交
568 569

					texture.type = UnsignedShortType;
570
					glType = utils.convert( texture.type );
T
Takahiro 已提交
571 572 573 574 575

				}

			}

576 577
			// Depth stencil textures need the DEPTH_STENCIL internal format
			// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
578
			if ( texture.format === DepthStencilFormat ) {
579

T
Takahiro 已提交
580
				glInternalFormat = _gl.DEPTH_STENCIL;
581

T
Takahiro 已提交
582 583 584 585 586
				// 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 已提交
587
					console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
T
Takahiro 已提交
588 589

					texture.type = UnsignedInt248Type;
590
					glType = utils.convert( texture.type );
T
Takahiro 已提交
591 592 593

				}

594 595
			}

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

598
		} else if ( texture.isDataTexture ) {
599 600 601 602 603 604 605 606 607 608

			// 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 已提交
609
					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
610 611 612 613

				}

				texture.generateMipmaps = false;
614
				textureProperties.__maxMipLevel = mipmaps.length - 1;
615 616 617

			} else {

T
Takahiro 已提交
618
				state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
619
				textureProperties.__maxMipLevel = 0;
620 621 622

			}

623
		} else if ( texture.isCompressedTexture ) {
624 625 626 627 628

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

				mipmap = mipmaps[ i ];

R
Rich Harris 已提交
629
				if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
630 631 632

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

T
Takahiro 已提交
633
						state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
634 635 636

					} else {

M
Mugen87 已提交
637
						console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
638 639 640 641 642

					}

				} else {

T
Takahiro 已提交
643
					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
644 645 646 647 648

				}

			}

649
			textureProperties.__maxMipLevel = mipmaps.length - 1;
650

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

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

656 657 658 659 660 661 662 663 664 665 666 667 668
		} 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 已提交
669
					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );
670 671 672 673

				}

				texture.generateMipmaps = false;
674
				textureProperties.__maxMipLevel = mipmaps.length - 1;
675 676 677

			} else {

T
Takahiro 已提交
678
				state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
679
				textureProperties.__maxMipLevel = 0;
680 681 682 683 684

			}

		}

685 686
		if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {

687
			generateMipmap( _gl.TEXTURE_2D, texture, image.width, image.height );
688 689

		}
690 691 692 693 694 695 696 697 698 699

		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 已提交
700
	function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
701

702 703
		var glFormat = utils.convert( renderTarget.texture.format );
		var glType = utils.convert( renderTarget.texture.type );
T
Takahiro 已提交
704
		var glInternalFormat = getInternalFormat( glFormat, glType );
705
		state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
706 707 708 709 710 711 712
		_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 已提交
713
	function setupRenderBufferStorage( renderbuffer, renderTarget ) {
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738

		_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 已提交
739
	function setupDepthTexture( framebuffer, renderTarget ) {
740

741
		var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube );
M
Mugen87 已提交
742
		if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
743 744 745

		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );

M
Mugen87 已提交
746
		if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
747

M
Mugen87 已提交
748
			throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
749 750 751 752

		}

		// upload an empty depth texture with framebuffer size
M
Mugen87 已提交
753
		if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
754 755
				renderTarget.depthTexture.image.width !== renderTarget.width ||
				renderTarget.depthTexture.image.height !== renderTarget.height ) {
M
Mugen87 已提交
756

757 758 759
			renderTarget.depthTexture.image.width = renderTarget.width;
			renderTarget.depthTexture.image.height = renderTarget.height;
			renderTarget.depthTexture.needsUpdate = true;
M
Mugen87 已提交
760

761 762 763 764 765
		}

		setTexture2D( renderTarget.depthTexture, 0 );

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

767
		if ( renderTarget.depthTexture.format === DepthFormat ) {
768 769 770

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

771
		} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
772 773 774 775 776

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

		} else {

M
Mugen87 已提交
777
			throw new Error( 'Unknown depthTexture format' );
778 779

		}
780 781 782 783 784 785 786 787

	}

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

		var renderTargetProperties = properties.get( renderTarget );

788
		var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
789 790 791

		if ( renderTarget.depthTexture ) {

M
Mugen87 已提交
792
			if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
793 794 795 796 797 798 799 800 801 802 803 804 805 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

			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 已提交
834
		info.memory.textures ++;
835

836
		var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869
		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 );

			}

870 871
			if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) {

872
				generateMipmap( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, renderTarget.width, renderTarget.height );
873 874 875

			}

876 877 878 879 880 881 882 883
			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 );

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

886
				generateMipmap( _gl.TEXTURE_2D, renderTarget.texture, renderTarget.width, renderTarget.height );
887 888 889

			}

890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
			state.bindTexture( _gl.TEXTURE_2D, null );

		}

		// Setup depth and stencil buffers

		if ( renderTarget.depthBuffer ) {

			setupDepthRenderbuffer( renderTarget );

		}

	}

	function updateRenderTargetMipmap( renderTarget ) {

		var texture = renderTarget.texture;
907
		var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
908

909
		if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) {
910

911
			var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
912 913 914
			var webglTexture = properties.get( texture ).__webglTexture;

			state.bindTexture( target, webglTexture );
915
			generateMipmap( target, texture, renderTarget.width, renderTarget.height );
916 917 918 919 920 921
			state.bindTexture( target, null );

		}

	}

922 923 924
	function updateVideoTexture( texture ) {

		var id = texture.id;
M
Mugen87 已提交
925
		var frame = info.render.frame;
926 927

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

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

931 932
			_videoTextures[ id ] = frame;
			texture.update();
M
Mugen87 已提交
933 934 935 936 937

		}

	}

938
	this.setTexture2D = setTexture2D;
A
artur.trzesiok 已提交
939
	this.setTexture3D = setTexture3D;
940 941 942 943 944
	this.setTextureCube = setTextureCube;
	this.setTextureCubeDynamic = setTextureCubeDynamic;
	this.setupRenderTarget = setupRenderTarget;
	this.updateRenderTargetMipmap = updateRenderTargetMipmap;

M
Mr.doob 已提交
945
}
R
Rich Harris 已提交
946 947


948
export { WebGLTextures };