ソースを参照

texture: add WebGL internal format support

* Adds `internalFormat` attribute to Texture.js and Texture.d.ts
* Adds `internalFormat` string mapping to GL constant in WebGLTextures.js
* Adds `internalFormat` in Texture documentation
* Adds internal format string constants to constants documentation
David Peicho 6 年 前
コミット
d97151ba0f

+ 275 - 0
docs/api/en/constants/Textures.html

@@ -147,8 +147,12 @@
 		<h2>Formats</h2>
 		<code>
 		THREE.AlphaFormat
+		THREE.RGFormat
+		THREE.RGIntegerFormat
 		THREE.RGBFormat
+		THREE.RGBIntegerFormat
 		THREE.RGBAFormat
+		THREE.RGBAIntegerFormat
 		THREE.LuminanceFormat
 		THREE.LuminanceAlphaFormat
 		THREE.RGBEFormat
@@ -161,10 +165,28 @@
 
 		[page:constant AlphaFormat] discards the red, green and blue components and reads just the alpha component.<br /><br />
 
+		[page:constant RGFormat] discards the alpha, and blue components and reads the red, and green components.
+		(can only be used with a WebGL 2 rendering context).
+		<br /><br />
+
+		[page:constant RGIntegerFormat] discards the alpha, and blue components and reads the red, and green components.
+		The texels are read as integers instead of floating point.
+		(can only be used with a WebGL 2 rendering context).
+		<br /><br />
+
 		[page:constant RGBFormat] discards the alpha components and reads the red, green and blue components.<br /><br />
 
+		[page:constant RGBIntegerFormat] discards the alpha components and reads the red, green and blue components.
+		(can only be used with a WebGL 2 rendering context).
+		<br /><br />
+
 		[page:constant RGBAFormat] is the default and reads the red, green, blue and alpha components.<br /><br />
 
+		[page:constant RGBAIntegerFormat] is the default and reads the red, green, blue and alpha components.
+		The texels are read as integers instead of floating point.
+		(can only be used with a WebGL 2 rendering context).
+		<br /><br />
+
 		[page:constant LuminanceFormat] reads each element as a single luminance component.
 		 This is then converted to a floating point, clamped to the range [0,1], and then assembled
 		 into an RGBA element by placing the luminance value in the red, green and blue channels,
@@ -238,6 +260,259 @@
 		extension. <br /><br />
 		</p>
 
+		<h2>Internal Formats</h2>
+		<code>
+		'ALPHA'
+		'RGB'
+		'RGBA'
+		'LUMINANCE'
+		'LUMINANCE_ALPHA'
+		'RED_INTEGER'
+		'R8'
+		'R8_SNORM'
+		'R8I'
+		'R8UI'
+		'R16I'
+		'R16UI'
+		'R16F'
+		'R32I'
+		'R32UI'
+		'R32F'
+		'RG8'
+		'RG8_SNORM'
+		'RG8I'
+		'RG8UI'
+		'RG16I'
+		'RG16UI'
+		'RG16F'
+		'RG32I'
+		'RG32UI'
+		'RG32F'
+		'RGB565'
+		'RGB8'
+		'RGB8_SNORM'
+		'RGB8I'
+		'RGB8UI'
+		'RGB16I'
+		'RGB16UI'
+		'RGB16F'
+		'RGB32I'
+		'RGB32UI'
+		'RGB32F'
+		'RGB9_E5'
+		'SRGB8'
+		'R11F_G11F_B10F'
+		'RGBA4'
+		'RGBA8'
+		'RGBA8_SNORM'
+		'RGBA8I'
+		'RGBA8UI'
+		'RGBA16I'
+		'RGBA16UI'
+		'RGBA16F'
+		'RGBA32I'
+		'RGBA32UI'
+		'RGBA32F'
+		'RGB5_A1'
+		'RGB10_A2'
+		'RGB10_A2UI'
+		'SRGB8_ALPHA8'
+		'DEPTH_COMPONENT16'
+		'DEPTH_COMPONENT24'
+		'DEPTH_COMPONENT32F'
+		'DEPTH24_STENCIL8'
+		'DEPTH32F_STENCIL8'
+		</code>
+
+		<p>
+
+		Heads up: changing the internal format of a texture will only affect the
+		texture when using a WebGL 2 rendering context.<br /><br />
+
+		For use with a texture's [page:Texture.internalFormat internalFormat]	property,
+		these define how elements of a texture, or *texels*, are stored on the GPU.<br /><br />
+
+		[page:constant R8] stores the red component on 8 bits.<br /><br />
+
+		[page:constant R8_SNORM] stores the red component on 8 bits. The component is stored as normalized. <br /><br />
+
+		[page:constant R8I] stores the red component on 8 bits. The component is stored as an integer. <br /><br />
+
+		[page:constant R8UI] stores the red component on 8 bits. The component is stored as an unsigned integer. <br /><br />
+
+		[page:constant R16I] stores the red component on 16 bits. The component is stored as an integer. <br /><br />
+
+		[page:constant R16UI] stores the red component on 16 bits. The component is stored as an unsigned integer. <br /><br />
+
+		[page:constant R16F] stores the red component on 16 bits. The component is stored as floating point. <br /><br />
+
+		[page:constant R32I] stores the red component on 32 bits. The component is stored as an integer. <br /><br />
+
+		[page:constant R32UI] stores the red component on 32 bits. The component is stored as an unsigned integer. <br /><br />
+
+		[page:constant R32F] stores the red component on 32 bits. The component is stored as floating point. <br /><br />
+
+		[page:constant RG8] stores the red and green components on 8 bits each.<br /><br />
+
+		[page:constant RG8_SNORM] stores the red and green components on 8 bits each.
+		Every component is stored as normalized.
+		<br /><br />
+
+		[page:constant RG8I] stores the red and green components on 8 bits each.
+		Every component is stored as an integer.
+		<br /><br />
+
+		[page:constant RG8UI] stores the red and green components on 8 bits each.
+		Every component is stored as an unsigned integer.
+		<br /><br />
+
+		[page:constant RG16I] stores the red and green components on 16 bits each.
+		Every component is stored as an integer.
+		<br /><br />
+
+		[page:constant RG16UI] stores the red and green components on 16 bits each.
+		Every component is stored as an unsigned integer.
+		<br /><br />
+
+		[page:constant RG16F] stores the red and green components on 16 bits each.
+		Every component is stored as floating point.
+		<br /><br />
+
+		[page:constant RG32I] stores the red and green components on 32 bits each.
+		Every component is stored as an integer.
+		<br /><br />
+
+		[page:constant RG32UI] stores the red and green components on 32 bits.
+		Every component is stored as an unsigned integer.
+		<br /><br />
+
+		[page:constant RG32F] stores the red and green components on 32 bits.
+		Every component is stored as floating point.
+		<br /><br />
+
+		[page:constant RGB8] stores the red, green, and blue components on 8 bits each.
+
+		[page:constant RGB8_SNORM] stores the red, green, and blue components on 8 bits each.
+		Every component is stored as normalized.
+		<br /><br />
+
+		[page:constant RGB8I] stores the red, green, and blue components on 8 bits each.
+		Every component is stored as an integer.
+		<br /><br />
+
+		[page:constant RGB8UI] stores the red, green, and blue components on 8 bits each.
+		Every component is stored as an unsigned integer.
+		<br /><br />
+
+		[page:constant RGB16I] stores the red, green, and blue components on 16 bits each.
+		Every component is stored as an integer.
+		<br /><br />
+
+		[page:constant RGB16UI] stores the red, green, and blue components on 16 bits each.
+		Every component is stored as an unsigned integer.
+		<br /><br />
+
+		[page:constant RGB16F] stores the red, green, and blue components on 16 bits each.
+		Every component is stored as floating point
+		<br /><br />
+
+		[page:constant RGB32I] stores the red, green, and blue components on 32 bits each.
+		Every component is stored as an integer.
+		<br /><br />
+
+		[page:constant RGB32UI] stores the red, green, and blue components on 32 bits each.
+		Every component is stored as an unsigned integer.
+		<br /><br />
+
+		[page:constant RGB32F] stores the red, green, and blue components on 32 bits each.
+		Every component is stored as floating point
+		<br /><br />
+
+		[page:constant R11F_G11F_B10F] stores the red, green, and blue components respectively on 11 bits, 11 bits, and 10bits.
+		Every component is stored as floating point.
+		<br /><br />
+
+		[page:constant RGB565] stores the red, green, and blue components respectively on 5 bits, 6 bits, and 5 bits.<br /><br />
+
+		[page:constant RGB9_E5] stores the red, green, and blue components on 9 bits each.<br /><br />
+
+		[page:constant RGBA8] stores the red, green, blue, and alpha components on 8 bits each.<br /><br />
+
+		[page:constant RGBA8_SNORM] stores the red, green, blue, and alpha components on 8 bits.
+		Every component is stored as normalized.
+		<br /><br />
+
+		[page:constant RGBA8I] stores the red, green, blue, and alpha components on 8 bits each.
+		Every component is stored as an integer.
+		<br /><br />
+
+		[page:constant RGBA8UI] stores the red, green, blue, and alpha components on 8 bits.
+		Every component is stored as an unsigned integer.
+		<br /><br />
+
+		[page:constant RGBA16I] stores the red, green, blue, and alpha components on 16 bits.
+		Every component is stored as an integer.
+		<br /><br />
+
+		[page:constant RGBA16UI] stores the red, green, blue, and alpha components on 16 bits.
+		Every component is stored as an unsigned integer.
+		<br /><br />
+
+		[page:constant RGBA16F] stores the red, green, blue, and alpha components on 16 bits.
+		Every component is stored as floating point.
+		<br /><br />
+
+		[page:constant RGBA32I] stores the red, green, blue, and alpha components on 32 bits.
+		Every component is stored as an integer.
+		<br /><br />
+
+		[page:constant RGBA32UI] stores the red, green, blue, and alpha components on 32 bits.
+		Every component is stored as an unsigned integer.
+		<br /><br />
+
+		[page:constant RGBA32F] stores the red, green, blue, and alpha components on 32 bits.
+		Every component is stored as floating point.
+		<br /><br />
+
+		[page:constant RGB5_A1] stores the red, green, blue, and alpha components respectively on 5 bits, 5 bits, 5 bits, and 1 bit.<br /><br />
+
+		[page:constant RGB10_A2] stores the red, green, blue, and alpha components respectively on 10 bits, 10 bits, 10 bits and 2 bits.<br /><br />
+
+		[page:constant RGB10_A2UI] stores the red, green, blue, and alpha components respectively on 10 bits, 10 bits, 10 bits and 2 bits.
+		Every component is stored as an unsigned integer.
+		<br /><br />
+
+		[page:constant SRGB8] stores the red, green, and blue components on 8 bits each.<br /><br />
+
+		[page:constant SRGB8_ALPHA8] stores the red, green, blue, and alpha components on 8 bits each.<br /><br />
+
+		[page:constant DEPTH_COMPONENT16] stores the depth component on 16bits.<br /><br />
+
+		[page:constant DEPTH_COMPONENT24] stores the depth component on 24bits.<br /><br />
+
+		[page:constant DEPTH_COMPONENT32F] stores the depth component on 32bits. The component is stored as floating point.<br /><br />
+
+		[page:constant DEPTH24_STENCIL8] stores the depth, and stencil components respectively on 24 bits and 8 bits.
+		The stencil component is stored as an unsigned integer.
+		<br /><br />
+
+		[page:constant DEPTH32F_STENCIL8] stores the depth, and stencil components respectively on 32 bits and 8 bits.
+		The depth component is stored as floating point, and the stencil component as an unsigned integer.
+		<br /><br />
+
+		Note that the texture must have the correct [page:Texture.type type] set,
+		as well as the correct [page:Texture.format format].
+
+		See [link:https://developer.mozilla.org/en/docs/Web/API/WebGLRenderingContext/texImage2D WebGLRenderingContext.texImage2D], and
+		[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texImage3D WebGL2RenderingContext.texImage3D],
+		for more details regarding the possible combination of [page:Texture.format format], [page:Texture.internalFormat internalFormat],
+		and [page:Texture.type type].<br /><br />
+
+		For more in-depth information regarding internal formats, you can also refer directly
+		to the [link:https://www.khronos.org/registry/webgl/specs/latest/2.0/ WebGL2 Specification] and
+		to the [link:https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf OpenGL ES 3.0 Specification].
+		</p>
+
 		<h2>Encoding</h2>
 		<code>
 		THREE.LinearEncoding

+ 11 - 0
docs/api/en/textures/Texture.html

@@ -126,6 +126,17 @@
 		See the [page:Textures texture constants] page for details of other formats.
 		</p>
 
+		<h3>[property:String internalFormat]</h3>
+		<p>
+		The default value is obtained using a combination of [page:Texture.format .format] and
+		[page:Texture.type .type].<br />
+
+		The GPU format allows the developer to specify how the data is going to be
+		stored on the GPU.<br /><br />
+
+		See the [page:Textures texture constants] page for details regarding all supported internal formats.
+		</p>
+
 		<h3>[property:number type]</h3>
 		<p>
 		This must correspond to the [page:Texture.format .format]. The default is [page:Textures THREE.UnsignedByteType],

+ 63 - 0
src/constants.d.ts

@@ -177,6 +177,69 @@ export const DepthFormat: PixelFormat;
 export const DepthStencilFormat: PixelFormat;
 export const RedFormat: PixelFormat;
 
+// Internal Pixel Formats
+export type PixelFormatGPU =
+	'ALPHA'
+	| 'RGB'
+	| 'RGBA'
+	| 'LUMINANCE'
+	| 'LUMINANCE_ALPHA'
+	| 'RED_INTEGER'
+	| 'R8'
+	| 'R8_SNORM'
+	| 'R8I'
+	| 'R8UI'
+	| 'R16I'
+	| 'R16UI'
+	| 'R16F'
+	| 'R32I'
+	| 'R32UI'
+	| 'R32F'
+	| 'RG8'
+	| 'RG8_SNORM'
+	| 'RG8I'
+	| 'RG8UI'
+	| 'RG16I'
+	| 'RG16UI'
+	| 'RG16F'
+	| 'RG32I'
+	| 'RG32UI'
+	| 'RG32F'
+	| 'RGB565'
+	| 'RGB8'
+	| 'RGB8_SNORM'
+	| 'RGB8I'
+	| 'RGB8UI'
+	| 'RGB16I'
+	| 'RGB16UI'
+	| 'RGB16F'
+	| 'RGB32I'
+	| 'RGB32UI'
+	| 'RGB32F'
+	| 'RGB9_E5'
+	| 'SRGB8'
+	| 'R11F_G11F_B10F'
+	| 'RGBA4'
+	| 'RGBA8'
+	| 'RGBA8_SNORM'
+	| 'RGBA8I'
+	| 'RGBA8UI'
+	| 'RGBA16I'
+	| 'RGBA16UI'
+	| 'RGBA16F'
+	| 'RGBA32I'
+	| 'RGBA32UI'
+	| 'RGBA32F'
+	| 'RGB5_A1'
+	| 'RGB10_A2'
+	| 'RGB10_A2UI'
+	| 'SRGB8_ALPHA8'
+	| 'DEPTH_COMPONENT16'
+	| 'DEPTH_COMPONENT24'
+	| 'DEPTH_COMPONENT32F'
+	| 'DEPTH24_STENCIL8'
+	| 'DEPTH32F_STENCIL8';
+
 // Compressed texture formats
 // DDS / ST3C Compressed texture formats
 export enum CompressedPixelFormat {}

+ 1 - 0
src/constants.js

@@ -101,6 +101,7 @@ export var RGBEFormat = RGBAFormat;
 export var DepthFormat = 1026;
 export var DepthStencilFormat = 1027;
 export var RedFormat = 1028;
+
 export var RGB_S3TC_DXT1_Format = 33776;
 export var RGBA_S3TC_DXT1_Format = 33777;
 export var RGBA_S3TC_DXT3_Format = 33778;

+ 16 - 6
src/renderers/webgl/WebGLTextures.js

@@ -137,10 +137,20 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 	}
 
-	function getInternalFormat( glFormat, glType ) {
+	function getInternalFormat( texture, glFormat, glType ) {
 
 		if ( isWebGL2 === false ) return glFormat;
 
+		var internalFormatName = texture.internalFormat; // User specified internal format.
+
+		if ( internalFormatName !== null ) {
+
+			if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];
+
+			console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' );
+
+		}
+
 		var internalFormat = glFormat;
 
 		if ( glFormat === _gl.RED ) {
@@ -427,7 +437,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 				supportsMips = isPowerOfTwo( image ) || isWebGL2,
 				glFormat = utils.convert( texture.format ),
 				glType = utils.convert( texture.type ),
-				glInternalFormat = getInternalFormat( glFormat, glType );
+				glInternalFormat = getInternalFormat( texture, glFormat, glType );
 
 			setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips );
 
@@ -649,7 +659,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 		var supportsMips = isPowerOfTwo( image ) || isWebGL2,
 			glFormat = utils.convert( texture.format ),
 			glType = utils.convert( texture.type ),
-			glInternalFormat = getInternalFormat( glFormat, glType );
+			glInternalFormat = getInternalFormat( texture, glFormat, glType );
 
 		setTextureParameters( textureType, texture, supportsMips );
 
@@ -822,7 +832,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 		var glFormat = utils.convert( renderTarget.texture.format );
 		var glType = utils.convert( renderTarget.texture.type );
-		var glInternalFormat = getInternalFormat( glFormat, glType );
+		var glInternalFormat = getInternalFormat( renderTarget.texture, glFormat, glType );
 		state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
 		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
@@ -872,7 +882,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 			var glFormat = utils.convert( renderTarget.texture.format );
 			var glType = utils.convert( renderTarget.texture.type );
-			var glInternalFormat = getInternalFormat( glFormat, glType );
+			var glInternalFormat = getInternalFormat( renderTarget.texture, glFormat, glType );
 
 			if ( isMultisample ) {
 
@@ -1021,7 +1031,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 					_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer );
 					var glFormat = utils.convert( renderTarget.texture.format );
 					var glType = utils.convert( renderTarget.texture.type );
-					var glInternalFormat = getInternalFormat( glFormat, glType );
+					var glInternalFormat = getInternalFormat( renderTarget.texture, glFormat, glType );
 					var samples = getRenderTargetSamples( renderTarget );
 					_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
 

+ 10 - 2
src/renderers/webgl/WebGLUniforms.js

@@ -628,8 +628,16 @@ function getPureArraySetter( type ) {
 		case 0x8b5b: return setValueM3Array; // _MAT3
 		case 0x8b5c: return setValueM4Array; // _MAT4
 
-		case 0x8b5e: return setValueT1Array; // SAMPLER_2D
-		case 0x8b60: return setValueT6Array; // SAMPLER_CUBE
+		case 0x8b5e: // SAMPLER_2D
+		case 0x8d66: // SAMPLER_EXTERNAL_OES
+		case 0x8dca: // INT_SAMPLER_2D
+		case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
+			return setValueT1Array;
+
+		case 0x8b60: // SAMPLER_CUBE
+		case 0x8dcc: // INT_SAMPLER_CUBE
+		case 0x8dd4: // UNSIGNED_SAMPLER_CUBE
+			return setValueT6Array;
 
 		case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL
 		case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2

+ 3 - 1
src/textures/Texture.d.ts

@@ -5,8 +5,9 @@ import {
 	Wrapping,
 	TextureFilter,
 	PixelFormat,
+	PixelFormatGPU,
 	TextureDataType,
-	TextureEncoding,
+	TextureEncoding
 } from '../constants';
 
 // Textures /////////////////////////////////////////////////////////////////////
@@ -40,6 +41,7 @@ export class Texture extends EventDispatcher {
 	minFilter: TextureFilter;
 	anisotropy: number;
 	format: PixelFormat;
+	internalFormat: PixelFormatGPU | null;
 	type: TextureDataType;
 	offset: Vector2;
 	repeat: Vector2;

+ 2 - 0
src/textures/Texture.js

@@ -45,6 +45,7 @@ function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, ty
 	this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
 
 	this.format = format !== undefined ? format : RGBAFormat;
+	this.internalFormat = null;
 	this.type = type !== undefined ? type : UnsignedByteType;
 
 	this.offset = new Vector2( 0, 0 );
@@ -110,6 +111,7 @@ Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
 		this.anisotropy = source.anisotropy;
 
 		this.format = source.format;
+		this.internalFormat = source.internalFormat;
 		this.type = source.type;
 
 		this.offset.copy( source.offset );