WebGLTextures.js 24.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, image );
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 67 68
			console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + _canvas.width + 'x' + _canvas.height, image );

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

		}

		return image;

	}

	function textureNeedsPowerOfTwo( texture ) {

T
Takahiro 已提交
78
		if ( _gl.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 );
97
		textureProperties.__maxMipLevel = Math.log2( Math.max( width, height ) );
98 99 100

	}

101 102
	function getInternalFormat( glFormat, glType ) {

T
Takahiro 已提交
103
		if ( ! _gl.isWebGL2 ) return glFormat;
T
Takahiro 已提交
104

105 106 107 108 109 110 111 112 113
		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 已提交
114 115 116

			if ( glType === _gl.FLOAT ) return _gl.RGBA32F;
			if ( glType === _gl.HALF_FLOAT ) return _gl.RGBA16F;
117
			if ( glType === _gl.UNSIGNED_BYTE ) return _gl.RGBA8;
T
Takahiro 已提交
118 119

		}
120 121 122 123 124

		return glFormat;

	}

125 126
	// Fallback filters for non-power-of-2 textures

M
Mr.doob 已提交
127
	function filterFallback( f ) {
128

R
Rich Harris 已提交
129
		if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) {
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148

			return _gl.NEAREST;

		}

		return _gl.LINEAR;

	}

	//

	function onTextureDispose( event ) {

		var texture = event.target;

		texture.removeEventListener( 'dispose', onTextureDispose );

		deallocateTexture( texture );

M
Mugen87 已提交
149 150 151 152 153
		if ( texture.isVideoTexture ) {

			delete _videoTextures[ texture.id ];

		}
154

M
Mugen87 已提交
155
		info.memory.textures --;
156 157 158 159 160 161 162 163 164 165 166

	}

	function onRenderTargetDispose( event ) {

		var renderTarget = event.target;

		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );

		deallocateRenderTarget( renderTarget );

M
Mugen87 已提交
167
		info.memory.textures --;
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193

	}

	//

	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
194
		properties.remove( texture );
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216

	}

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

		}

217
		if ( renderTarget.isWebGLRenderTargetCube ) {
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232

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

		}

233 234
		properties.remove( renderTarget.texture );
		properties.remove( renderTarget );
235 236 237 238 239 240 241 242 243 244 245

	}

	//



	function setTexture2D( texture, slot ) {

		var textureProperties = properties.get( texture );

246 247
		if ( texture.isVideoTexture ) updateVideoTexture( texture );

248 249 250 251 252 253 254 255
		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {

			var image = texture.image;

			if ( image === undefined ) {

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

256
			} else if ( image.complete === false ) {
257 258 259

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

260
			} else {
261

262 263
				uploadTexture( textureProperties, texture, slot );
				return;
264

265
			}
266 267 268 269 270 271 272 273

		}

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

	}

M
Mr.doob 已提交
274
	function setTextureCube( texture, slot ) {
275 276 277 278 279 280 281 282 283 284 285 286 287

		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 已提交
288
					info.memory.textures ++;
289 290 291 292 293 294 295 296

				}

				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 已提交
297 298
				var isCompressed = ( texture && texture.isCompressedTexture );
				var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316

				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 已提交
317 318
					isPowerOfTwoImage = isPowerOfTwo( image ),
					glFormat = utils.convert( texture.format ),
T
Takahiro 已提交
319 320
					glType = utils.convert( texture.type ),
					glInternalFormat = getInternalFormat( glFormat, glType );
321 322 323 324 325 326 327 328 329

				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );

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

					if ( ! isCompressed ) {

						if ( isDataTexture ) {

T
Takahiro 已提交
330
							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
331 332 333

						} else {

T
Takahiro 已提交
334
							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
335 336 337 338 339 340 341 342 343 344 345

						}

					} else {

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

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

							mipmap = mipmaps[ j ];

R
Rich Harris 已提交
346
							if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
347 348 349

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

T
Takahiro 已提交
350
									state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
351 352 353

								} else {

M
Mugen87 已提交
354
									console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
355 356 357 358 359

								}

							} else {

T
Takahiro 已提交
360
								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
361 362 363 364 365 366 367 368 369

							}

						}

					}

				}

370 371
				if ( ! isCompressed ) {

372
					textureProperties.__maxMipLevel = 0;
373 374 375

				} else {

376
					textureProperties.__maxMipLevel = mipmaps.length - 1;
377 378 379

				}

380
				if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {
381

382 383
					// We assume images for cube map have the same size.
					generateMipmap( _gl.TEXTURE_CUBE_MAP, texture, image.width, image.height );
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401

				}

				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 已提交
402
	function setTextureCubeDynamic( texture, slot ) {
403 404 405 406 407 408

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

	}

M
Mr.doob 已提交
409
	function setTextureParameters( textureType, texture, isPowerOfTwoImage ) {
410 411 412 413 414

		var extension;

		if ( isPowerOfTwoImage ) {

415 416
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) );
417

418 419
			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) );
420 421 422 423 424 425

		} 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 已提交
426
			if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
427 428 429 430 431 432 433 434

				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture );

			}

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

R
Rich Harris 已提交
435
			if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
436 437 438 439 440 441 442 443 444 445 446

				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture );

			}

		}

		extension = extensions.get( 'EXT_texture_filter_anisotropic' );

		if ( extension ) {

R
Rich Harris 已提交
447 448
			if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
			if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return;
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470

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

		if ( textureProperties.__webglInit === undefined ) {

			textureProperties.__webglInit = true;

			texture.addEventListener( 'dispose', onTextureDispose );

			textureProperties.__webglTexture = _gl.createTexture();

M
Mugen87 已提交
471
			info.memory.textures ++;
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490

		}

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

		_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 已提交
491
			glFormat = utils.convert( texture.format ),
T
Takahiro 已提交
492 493
			glType = utils.convert( texture.type ),
			glInternalFormat = getInternalFormat( glFormat, glType );
494

495 496 497 498
		setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage );

		var mipmap, mipmaps = texture.mipmaps;

499
		if ( texture.isDepthTexture ) {
500 501 502

			// populate depth texture with dummy data

T
Takahiro 已提交
503
			glInternalFormat = _gl.DEPTH_COMPONENT;
504

R
Rich Harris 已提交
505
			if ( texture.type === FloatType ) {
506

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

T
Takahiro 已提交
510
			} else if ( _gl.isWebGL2 ) {
511 512

				// WebGL 2.0 requires signed internalformat for glTexImage2D
T
Takahiro 已提交
513
				glInternalFormat = _gl.DEPTH_COMPONENT16;
514 515 516

			}

T
Takahiro 已提交
517
			if ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
T
Takahiro 已提交
518 519 520 521 522 523

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

					texture.type = UnsignedShortType;
527
					glType = utils.convert( texture.type );
T
Takahiro 已提交
528 529 530 531 532

				}

			}

533 534
			// Depth stencil textures need the DEPTH_STENCIL internal format
			// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
535
			if ( texture.format === DepthStencilFormat ) {
536

T
Takahiro 已提交
537
				glInternalFormat = _gl.DEPTH_STENCIL;
538

T
Takahiro 已提交
539 540 541 542 543
				// 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 已提交
544
					console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
T
Takahiro 已提交
545 546

					texture.type = UnsignedInt248Type;
547
					glType = utils.convert( texture.type );
T
Takahiro 已提交
548 549 550

				}

551 552
			}

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

555
		} else if ( texture.isDataTexture ) {
556 557 558 559 560 561 562 563 564 565

			// 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 已提交
566
					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
567 568 569 570

				}

				texture.generateMipmaps = false;
571
				textureProperties.__maxMipLevel = mipmaps.length - 1;
572 573 574

			} else {

T
Takahiro 已提交
575
				state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
576
				textureProperties.__maxMipLevel = 0;
577 578 579

			}

580
		} else if ( texture.isCompressedTexture ) {
581 582 583 584 585

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

				mipmap = mipmaps[ i ];

R
Rich Harris 已提交
586
				if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
587 588 589

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

T
Takahiro 已提交
590
						state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
591 592 593

					} else {

M
Mugen87 已提交
594
						console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
595 596 597 598 599

					}

				} else {

T
Takahiro 已提交
600
					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
601 602 603 604 605

				}

			}

606
			textureProperties.__maxMipLevel = mipmaps.length - 1;
607

608 609 610 611 612 613 614 615 616 617 618 619 620
		} 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 已提交
621
					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );
622 623 624 625

				}

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

			} else {

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

			}

		}

637 638
		if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) {

639
			generateMipmap( _gl.TEXTURE_2D, texture, image.width, image.height );
640 641

		}
642 643 644 645 646 647 648 649 650 651

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

654 655
		var glFormat = utils.convert( renderTarget.texture.format );
		var glType = utils.convert( renderTarget.texture.type );
T
Takahiro 已提交
656
		var glInternalFormat = getInternalFormat( glFormat, glType );
T
Takahiro 已提交
657
		var array = ( _gl.isWebGL2 ) ? new Uint8Array( renderTarget.width * renderTarget.height * 4 ) : null;
T
Takahiro 已提交
658
		state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, array );
659 660 661 662 663 664 665
		_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 已提交
666
	function setupRenderBufferStorage( renderbuffer, renderTarget ) {
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691

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

694
		var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube );
M
Mugen87 已提交
695
		if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
696 697 698

		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );

M
Mugen87 已提交
699
		if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
700

M
Mugen87 已提交
701
			throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
702 703 704 705

		}

		// upload an empty depth texture with framebuffer size
M
Mugen87 已提交
706
		if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
707 708
				renderTarget.depthTexture.image.width !== renderTarget.width ||
				renderTarget.depthTexture.image.height !== renderTarget.height ) {
M
Mugen87 已提交
709

710 711 712
			renderTarget.depthTexture.image.width = renderTarget.width;
			renderTarget.depthTexture.image.height = renderTarget.height;
			renderTarget.depthTexture.needsUpdate = true;
M
Mugen87 已提交
713

714 715 716 717 718
		}

		setTexture2D( renderTarget.depthTexture, 0 );

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

720
		if ( renderTarget.depthTexture.format === DepthFormat ) {
721 722 723

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

724
		} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
725 726 727 728 729

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

		} else {

M
Mugen87 已提交
730
			throw new Error( 'Unknown depthTexture format' );
731 732

		}
733 734 735 736 737 738 739 740

	}

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

		var renderTargetProperties = properties.get( renderTarget );

741
		var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
742 743 744

		if ( renderTarget.depthTexture ) {

M
Mugen87 已提交
745
			if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786

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

789
		var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
790 791 792 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
		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 );

			}

823 824
			if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) {

825
				generateMipmap( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, renderTarget.width, renderTarget.height );
826 827 828

			}

829 830 831 832 833 834 835 836
			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 );

837 838
			if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) {

839
				generateMipmap( _gl.TEXTURE_2D, renderTarget.texture, renderTarget.width, renderTarget.height );
840 841 842

			}

843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
			state.bindTexture( _gl.TEXTURE_2D, null );

		}

		// Setup depth and stencil buffers

		if ( renderTarget.depthBuffer ) {

			setupDepthRenderbuffer( renderTarget );

		}

	}

	function updateRenderTargetMipmap( renderTarget ) {

		var texture = renderTarget.texture;
860
		var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
861

862
		if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) {
863

864
			var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
865 866 867
			var webglTexture = properties.get( texture ).__webglTexture;

			state.bindTexture( target, webglTexture );
868
			generateMipmap( target, texture, renderTarget.width, renderTarget.height );
869 870 871 872 873 874
			state.bindTexture( target, null );

		}

	}

875 876 877
	function updateVideoTexture( texture ) {

		var id = texture.id;
M
Mugen87 已提交
878
		var frame = info.render.frame;
879 880

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

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

884 885
			_videoTextures[ id ] = frame;
			texture.update();
M
Mugen87 已提交
886 887 888 889 890

		}

	}

891 892 893 894 895 896
	this.setTexture2D = setTexture2D;
	this.setTextureCube = setTextureCube;
	this.setTextureCubeDynamic = setTextureCubeDynamic;
	this.setupRenderTarget = setupRenderTarget;
	this.updateRenderTargetMipmap = updateRenderTargetMipmap;

M
Mr.doob 已提交
897
}
R
Rich Harris 已提交
898 899


900
export { WebGLTextures };