diff --git a/examples/jsm/loaders/KTX2Loader.js b/examples/jsm/loaders/KTX2Loader.js index b2ad541a296a31..1c6492a9e96044 100644 --- a/examples/jsm/loaders/KTX2Loader.js +++ b/examples/jsm/loaders/KTX2Loader.js @@ -42,7 +42,8 @@ import { SRGBColorSpace, UnsignedByteType, UnsignedInt5999Type, - UnsignedInt101111Type + UnsignedInt101111Type, + UnsignedShortType } from 'three'; import { WorkerPool } from '../utils/WorkerPool.js'; import { @@ -83,6 +84,7 @@ import { VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, VK_FORMAT_R16G16B16A16_SFLOAT, + VK_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_R16G16_SFLOAT, VK_FORMAT_R16_SFLOAT, VK_FORMAT_R32G32B32A32_SFLOAT, @@ -964,6 +966,8 @@ const FORMAT_MAP = { [ VK_FORMAT_R16G16_SFLOAT ]: RGFormat, [ VK_FORMAT_R16_SFLOAT ]: RedFormat, + [ VK_FORMAT_R16G16B16A16_UNORM ]: RGBAFormat, + [ VK_FORMAT_R8G8B8A8_SRGB ]: RGBAFormat, [ VK_FORMAT_R8G8B8A8_UNORM ]: RGBAFormat, [ VK_FORMAT_R8G8_SRGB ]: RGFormat, @@ -1022,6 +1026,8 @@ const TYPE_MAP = { [ VK_FORMAT_R16G16_SFLOAT ]: HalfFloatType, [ VK_FORMAT_R16_SFLOAT ]: HalfFloatType, + [ VK_FORMAT_R16G16B16A16_UNORM ]: UnsignedShortType, + [ VK_FORMAT_R8G8B8A8_SRGB ]: UnsignedByteType, [ VK_FORMAT_R8G8B8A8_UNORM ]: UnsignedByteType, [ VK_FORMAT_R8G8_SRGB ]: UnsignedByteType, @@ -1149,7 +1155,7 @@ async function createRawTexture( container ) { ); - } else if ( TYPE_MAP[ vkFormat ] === HalfFloatType ) { + } else if ( TYPE_MAP[ vkFormat ] === HalfFloatType || TYPE_MAP[ vkFormat ] === UnsignedShortType ) { data = new Uint16Array( diff --git a/examples/textures/ktx2/2d_rgba16unorm_linear.ktx2 b/examples/textures/ktx2/2d_rgba16unorm_linear.ktx2 new file mode 100644 index 00000000000000..fc86b4b3cbdece Binary files /dev/null and b/examples/textures/ktx2/2d_rgba16unorm_linear.ktx2 differ diff --git a/examples/webgl_loader_texture_ktx2.html b/examples/webgl_loader_texture_ktx2.html index 846c42e9ae865f..37155e494de56d 100644 --- a/examples/webgl_loader_texture_ktx2.html +++ b/examples/webgl_loader_texture_ktx2.html @@ -99,6 +99,7 @@ { path: '2d_rgba8.ktx2' }, { path: '2d_rgba8_linear.ktx2' }, { path: '2d_rgba16_linear.ktx2' }, + { path: '2d_rgba16unorm_linear.ktx2' }, { path: '2d_rgba32_linear.ktx2' }, { path: '2d_rgb9e5_linear.ktx2' }, { path: '2d_r11g11b10_linear.ktx2' }, diff --git a/src/loaders/ObjectLoader.js b/src/loaders/ObjectLoader.js index b29f8e6fa863cc..e88fe18262bd18 100644 --- a/src/loaders/ObjectLoader.js +++ b/src/loaders/ObjectLoader.js @@ -757,6 +757,7 @@ class ObjectLoader extends Loader { if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction; + if ( data.normalized !== undefined ) texture.normalized = data.normalized; if ( data.userData !== undefined ) texture.userData = data.userData; diff --git a/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js b/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js index 498114e1560ce7..6041181c8faa3d 100644 --- a/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +++ b/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js @@ -162,7 +162,7 @@ class WebGLTextureUtils { * @param {boolean} [forceLinearTransfer=false] - Whether to force a linear transfer or not. * @return {GLenum} The internal format. */ - getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { + getInternalFormat( internalFormatName, glFormat, glType, normalized, colorSpace, forceLinearTransfer = false ) { const { gl, extensions } = this; @@ -174,6 +174,20 @@ class WebGLTextureUtils { } + let extTextureNorm16 = null; + + if ( normalized ) { + + extTextureNorm16 = extensions.get( 'EXT_texture_norm16' ); + + if ( ! extTextureNorm16 ) { + + warn( 'WebGLRenderer: Unable to use normalized textures without EXT_texture_norm16 extension' ); + + } + + } + let internalFormat = glFormat; if ( glFormat === gl.RED ) { @@ -182,6 +196,8 @@ class WebGLTextureUtils { if ( glType === gl.HALF_FLOAT ) internalFormat = gl.R16F; if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.R8; if ( glType === gl.BYTE ) internalFormat = gl.R8_SNORM; + if ( glType === gl.UNSIGNED_SHORT && extTextureNorm16 ) internalFormat = extTextureNorm16.R16_EXT; + if ( glType === gl.SHORT && extTextureNorm16 ) internalFormat = extTextureNorm16.R16_SNORM_EXT; } @@ -202,6 +218,8 @@ class WebGLTextureUtils { if ( glType === gl.HALF_FLOAT ) internalFormat = gl.RG16F; if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.RG8; if ( glType === gl.BYTE ) internalFormat = gl.RG8_SNORM; + if ( glType === gl.UNSIGNED_SHORT && extTextureNorm16 ) internalFormat = extTextureNorm16.RG16_EXT; + if ( glType === gl.SHORT && extTextureNorm16 ) internalFormat = extTextureNorm16.RG16_SNORM_EXT; } @@ -224,6 +242,8 @@ class WebGLTextureUtils { if ( glType === gl.HALF_FLOAT ) internalFormat = gl.RGB16F; if ( glType === gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? gl.SRGB8 : gl.RGB8; if ( glType === gl.BYTE ) internalFormat = gl.RGB8_SNORM; + if ( glType === gl.UNSIGNED_SHORT && extTextureNorm16 ) internalFormat = extTextureNorm16.RGB16_EXT; + if ( glType === gl.SHORT && extTextureNorm16 ) internalFormat = extTextureNorm16.RGB16_SNORM_EXT; if ( glType === gl.UNSIGNED_SHORT_5_6_5 ) internalFormat = gl.RGB565; if ( glType === gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = gl.RGB5_A1; if ( glType === gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = gl.RGB4; @@ -251,6 +271,8 @@ class WebGLTextureUtils { if ( glType === gl.HALF_FLOAT ) internalFormat = gl.RGBA16F; if ( glType === gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? gl.SRGB8_ALPHA8 : gl.RGBA8; if ( glType === gl.BYTE ) internalFormat = gl.RGBA8_SNORM; + if ( glType === gl.UNSIGNED_SHORT && extTextureNorm16 ) internalFormat = extTextureNorm16.RGBA16_EXT; + if ( glType === gl.SHORT && extTextureNorm16 ) internalFormat = extTextureNorm16.RGBA16_SNORM_EXT; if ( glType === gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = gl.RGBA4; if ( glType === gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = gl.RGB5_A1; @@ -411,7 +433,7 @@ class WebGLTextureUtils { const glFormat = backend.utils.convert( texture.format, texture.colorSpace ); const glType = backend.utils.convert( texture.type ); - const glInternalFormat = this.getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture ); + const glInternalFormat = this.getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace, texture.isVideoTexture ); const textureGPU = gl.createTexture(); const glTextureType = this.getGLTextureType( texture ); diff --git a/src/renderers/webgl/WebGLTextures.js b/src/renderers/webgl/WebGLTextures.js index fe7975b0d920f9..2f9f03359e5705 100644 --- a/src/renderers/webgl/WebGLTextures.js +++ b/src/renderers/webgl/WebGLTextures.js @@ -125,7 +125,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { + function getInternalFormat( internalFormatName, glFormat, glType, normalized, colorSpace, forceLinearTransfer = false ) { if ( internalFormatName !== null ) { @@ -135,6 +135,20 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + let ext_texture_norm16; + + if ( normalized ) { + + ext_texture_norm16 = extensions.get( 'EXT_texture_norm16' ); + + if ( ! ext_texture_norm16 ) { + + warn( 'WebGLRenderer: Unable to use normalized textures without EXT_texture_norm16 extension' ); + + } + + } + let internalFormat = glFormat; if ( glFormat === _gl.RED ) { @@ -142,6 +156,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F; if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F; if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8; + if ( glType === _gl.UNSIGNED_SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.R16_EXT; + if ( glType === _gl.SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.R16_SNORM_EXT; } @@ -161,6 +177,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F; if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F; if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8; + if ( glType === _gl.UNSIGNED_SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RG16_EXT; + if ( glType === _gl.SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RG16_SNORM_EXT; } @@ -199,6 +217,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( glFormat === _gl.RGB ) { + if ( glType === _gl.UNSIGNED_SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RGB16_EXT; + if ( glType === _gl.SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RGB16_SNORM_EXT; if ( glType === _gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = _gl.RGB9_E5; if ( glType === _gl.UNSIGNED_INT_10F_11F_11F_REV ) internalFormat = _gl.R11F_G11F_B10F; @@ -211,6 +231,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; + if ( glType === _gl.UNSIGNED_SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RGBA16_EXT; + if ( glType === _gl.SHORT && ext_texture_norm16 ) internalFormat = ext_texture_norm16.RGBA16_SNORM_EXT; if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4; if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1; @@ -908,7 +930,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture ); + let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace, texture.isVideoTexture ); setTextureParameters( textureType, texture ); @@ -1357,7 +1379,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const image = cubeImage[ 0 ], glFormat = utils.convert( texture.format, texture.colorSpace ), glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace ); const useTexStorage = ( texture.isVideoTexture !== true ); const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); @@ -1553,7 +1575,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace ); const renderTargetProperties = properties.get( renderTarget ); const textureProperties = properties.get( texture ); @@ -1632,7 +1654,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace ); if ( useMultisampledRTT( renderTarget ) ) { @@ -2022,7 +2044,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glFormat = utils.convert( texture.format, texture.colorSpace ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.normalized, texture.colorSpace, renderTarget.isXRRenderTarget === true ); const samples = getRenderTargetSamples( renderTarget ); _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); diff --git a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js index 9aadc494186446..7a196ffe585b37 100644 --- a/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +++ b/src/renderers/webgpu/nodes/WGSLNodeBuilder.js @@ -1876,6 +1876,7 @@ ${ flowData.code } */ getUniforms( shaderStage ) { + const backend = this.renderer.backend; const uniforms = this.uniforms[ shaderStage ]; const bindingSnippets = []; @@ -1913,7 +1914,7 @@ ${ flowData.code } let multisampled = ''; - const { primarySamples } = this.renderer.backend.utils.getTextureSampleData( texture ); + const { primarySamples } = backend.utils.getTextureSampleData( texture ); if ( primarySamples > 1 ) { @@ -1931,7 +1932,7 @@ ${ flowData.code } } else if ( texture.isDepthTexture === true ) { - if ( this.renderer.backend.compatibilityMode && texture.compareFunction === null ) { + if ( backend.compatibilityMode && texture.compareFunction === null ) { textureType = `texture${ multisampled }_2d`; @@ -1943,7 +1944,7 @@ ${ flowData.code } } else if ( uniform.node.isStorageTextureNode === true ) { - const format = getFormat( texture ); + const format = getFormat( texture, backend.device ); const access = this.getStorageAccess( uniform.node, shaderStage ); const is3D = uniform.node.value.is3DTexture; diff --git a/src/renderers/webgpu/utils/WebGPUConstants.js b/src/renderers/webgpu/utils/WebGPUConstants.js index 3915848688978a..91b9934d022611 100644 --- a/src/renderers/webgpu/utils/WebGPUConstants.js +++ b/src/renderers/webgpu/utils/WebGPUConstants.js @@ -96,6 +96,8 @@ export const GPUTextureFormat = { RG8Snorm: 'rg8snorm', RG8Uint: 'rg8uint', RG8Sint: 'rg8sint', + R16Unorm: 'r16unorm', + R16Snorm: 'r16snorm', // 32-bit formats @@ -112,7 +114,11 @@ export const GPUTextureFormat = { RGBA8Sint: 'rgba8sint', BGRA8Unorm: 'bgra8unorm', BGRA8UnormSRGB: 'bgra8unorm-srgb', + RG16Unorm: 'rg16unorm', + RG16Snorm: 'rg16snorm', + // Packed 32-bit formats + RGB9E5UFloat: 'rgb9e5ufloat', RGB10A2Unorm: 'rgb10a2unorm', RG11B10UFloat: 'rg11b10ufloat', @@ -125,6 +131,8 @@ export const GPUTextureFormat = { RGBA16Uint: 'rgba16uint', RGBA16Sint: 'rgba16sint', RGBA16Float: 'rgba16float', + RGBA16Unorm: 'rgba16unorm', + RGBA16Snorm: 'rgba16snorm', // 128-bit formats diff --git a/src/renderers/webgpu/utils/WebGPUTextureUtils.js b/src/renderers/webgpu/utils/WebGPUTextureUtils.js index f12d5cf897b099..cc452d9fefc9b3 100644 --- a/src/renderers/webgpu/utils/WebGPUTextureUtils.js +++ b/src/renderers/webgpu/utils/WebGPUTextureUtils.js @@ -198,7 +198,7 @@ class WebGPUTextureUtils { let textureGPU; - const format = getFormat( texture ); + const format = getFormat( texture, this.backend.device ); if ( texture.isCubeTexture ) { @@ -1073,7 +1073,9 @@ class WebGPUTextureUtils { format === GPUTextureFormat.RG8Unorm || format === GPUTextureFormat.RG8Snorm || format === GPUTextureFormat.RG8Uint || - format === GPUTextureFormat.RG8Sint ) return 2; + format === GPUTextureFormat.RG8Sint || + format === GPUTextureFormat.R16Unorm || + format === GPUTextureFormat.R16Snorm ) return 2; // 32-bit formats if ( format === GPUTextureFormat.R32Uint || @@ -1089,6 +1091,8 @@ class WebGPUTextureUtils { format === GPUTextureFormat.RGBA8Sint || format === GPUTextureFormat.BGRA8Unorm || format === GPUTextureFormat.BGRA8UnormSRGB || + format === GPUTextureFormat.RG16Unorm || + format === GPUTextureFormat.RG16Snorm || // Packed 32-bit formats format === GPUTextureFormat.RGB9E5UFloat || format === GPUTextureFormat.RGB10A2Unorm || @@ -1104,7 +1108,9 @@ class WebGPUTextureUtils { format === GPUTextureFormat.RG32Float || format === GPUTextureFormat.RGBA16Uint || format === GPUTextureFormat.RGBA16Sint || - format === GPUTextureFormat.RGBA16Float ) return 8; + format === GPUTextureFormat.RGBA16Float || + format === GPUTextureFormat.RGBA16Unorm || + format === GPUTextureFormat.RGBA16Snorm ) return 8; // 128-bit formats if ( format === GPUTextureFormat.RGBA32Uint || @@ -1147,6 +1153,12 @@ class WebGPUTextureUtils { if ( format === GPUTextureFormat.RG16Float ) return Uint16Array; if ( format === GPUTextureFormat.RGBA16Float ) return Uint16Array; + if ( format === GPUTextureFormat.R16Unorm ) return Uint16Array; + if ( format === GPUTextureFormat.R16Snorm ) return Int16Array; + if ( format === GPUTextureFormat.RG16Unorm ) return Uint16Array; + if ( format === GPUTextureFormat.RG16Snorm ) return Int16Array; + if ( format === GPUTextureFormat.RGBA16Unorm ) return Uint16Array; + if ( format === GPUTextureFormat.RGBA16Snorm ) return Int16Array; if ( format === GPUTextureFormat.R32Uint ) return Uint32Array; if ( format === GPUTextureFormat.R32Sint ) return Int32Array; @@ -1201,19 +1213,33 @@ class WebGPUTextureUtils { * Returns the GPU format for the given texture. * * @param {Texture} texture - The texture. - * @param {?GPUDevice} [device=null] - The GPU device which is used for feature detection. - * It is not necessary to apply the device for most formats. + * @param {GPUDevice} [device] - The GPU device which is used for feature detection. * @return {string} The GPU format. */ -export function getFormat( texture, device = null ) { +export function getFormat( texture, device ) { const format = texture.format; const type = texture.type; + const normalized = texture.normalized; const colorSpace = texture.colorSpace; const transfer = ColorManagement.getTransfer( colorSpace ); let formatGPU; + let textureFormatsTier1 = false; + + if ( normalized ) { + + textureFormatsTier1 = device.features.has( GPUFeatureName.TextureFormatsTier1 ); + + if ( textureFormatsTier1 === false ) { + + warn( 'WebGPURenderer: Unable to use normalized textures without texture-formats-tier1 feature.' ); + + } + + } + if ( texture.isCompressedTexture === true || texture.isCompressedArrayTexture === true ) { switch ( format ) { @@ -1354,12 +1380,13 @@ export function getFormat( texture, device = null ) { break; case ShortType: - formatGPU = GPUTextureFormat.RGBA16Sint; + formatGPU = textureFormatsTier1 ? GPUTextureFormat.RGBA16Snorm : GPUTextureFormat.RGBA16Sint; break; case UnsignedShortType: - formatGPU = GPUTextureFormat.RGBA16Uint; + formatGPU = textureFormatsTier1 ? GPUTextureFormat.RGBA16Unorm : GPUTextureFormat.RGBA16Uint; break; + case UnsignedIntType: formatGPU = GPUTextureFormat.RGBA32Uint; break; @@ -1415,11 +1442,11 @@ export function getFormat( texture, device = null ) { break; case ShortType: - formatGPU = GPUTextureFormat.R16Sint; + formatGPU = textureFormatsTier1 ? GPUTextureFormat.R16Snorm : GPUTextureFormat.R16Sint; break; case UnsignedShortType: - formatGPU = GPUTextureFormat.R16Uint; + formatGPU = textureFormatsTier1 ? GPUTextureFormat.R16Unorm : GPUTextureFormat.R16Uint; break; case UnsignedIntType: @@ -1458,11 +1485,11 @@ export function getFormat( texture, device = null ) { break; case ShortType: - formatGPU = GPUTextureFormat.RG16Sint; + formatGPU = textureFormatsTier1 ? GPUTextureFormat.RG16Snorm : GPUTextureFormat.RG16Sint; break; case UnsignedShortType: - formatGPU = GPUTextureFormat.RG16Uint; + formatGPU = textureFormatsTier1 ? GPUTextureFormat.RG16Unorm : GPUTextureFormat.RG16Uint; break; case UnsignedIntType: diff --git a/src/textures/Texture.js b/src/textures/Texture.js index 42f0f2d0679438..695b1a32184b44 100644 --- a/src/textures/Texture.js +++ b/src/textures/Texture.js @@ -368,6 +368,15 @@ class Texture extends EventDispatcher { */ this.pmremVersion = 0; + /** + * Whether the texture should use one of the 16 bit integer formats which are normalized + * to [0, 1] or [-1, 1] (depending on signed/unsigned) when sampled. + * + * @type {boolean} + * @default false + */ + this.normalized = false; + } /** @@ -483,6 +492,7 @@ class Texture extends EventDispatcher { this.format = source.format; this.internalFormat = source.internalFormat; this.type = source.type; + this.normalized = source.normalized; this.offset.copy( source.offset ); this.repeat.copy( source.repeat ); @@ -601,6 +611,7 @@ class Texture extends EventDispatcher { format: this.format, internalFormat: this.internalFormat, type: this.type, + normalized: this.normalized, colorSpace: this.colorSpace, minFilter: this.minFilter,