Переглянути джерело

WebGPURenderer: Int/Uint Support to StorageBufferNode in WebGLBackend (#28606)

* add uint/int support to pbo storageObject

* add uint/int support to pbo storageObject

* revert storage buffer node for another PR

* envmaps are uint16 but consumed as float?

* add rgbintegerformat to const
Renaud Rohlinger 1 рік тому
батько
коміт
276fa8ecae

+ 69 - 13
examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js

@@ -5,7 +5,7 @@ import NodeUniformsGroup from '../../common/nodes/NodeUniformsGroup.js';
 
 import { NodeSampledTexture, NodeSampledCubeTexture, NodeSampledTexture3D } from '../../common/nodes/NodeSampledTexture.js';
 
-import { RedFormat, RGFormat, IntType, DataTexture, RGBFormat, RGBAFormat, FloatType } from 'three';
+import { ByteType, ShortType, RGBAIntegerFormat, RGBIntegerFormat, RedIntegerFormat, RGIntegerFormat, UnsignedByteType, UnsignedIntType, UnsignedShortType, RedFormat, RGFormat, IntType, DataTexture, RGBFormat, RGBAFormat, FloatType } from 'three';
 
 const glslMethods = {
 	[ MathNode.ATAN2 ]: 'atan',
@@ -26,8 +26,21 @@ const supports = {
 const defaultPrecisions = `
 precision highp float;
 precision highp int;
+precision highp sampler2D;
 precision highp sampler3D;
-precision mediump sampler2DArray;
+precision highp samplerCube;
+precision highp sampler2DArray;
+
+precision highp usampler2D;
+precision highp usampler3D;
+precision highp usamplerCube;
+precision highp usampler2DArray;
+
+precision highp isampler2D;
+precision highp isampler3D;
+precision highp isamplerCube;
+precision highp isampler2DArray;
+
 precision lowp sampler2DShadow;
 `;
 
@@ -100,35 +113,50 @@ ${ flowData.code }
 			const numElements = attribute.count * attribute.itemSize;
 
 			const { itemSize } = attribute;
-			let format = RedFormat;
+
+			const isInteger = attribute.array.constructor.name.toLowerCase().includes( 'int' );
+
+			let format = isInteger ? RedIntegerFormat : RedFormat;
+
 
 			if ( itemSize === 2 ) {
 
-				format = RGFormat;
+				format = isInteger ? RGIntegerFormat : RGFormat;
 
 			} else if ( itemSize === 3 ) {
 
-				format = RGBFormat;
+				format = isInteger ? RGBIntegerFormat : RGBFormat;
 
 			} else if ( itemSize === 4 ) {
 
-				format = RGBAFormat;
+				format = isInteger ? RGBAIntegerFormat : RGBAFormat;
 
 			}
 
+			const typeMap = {
+				Float32Array: FloatType,
+				Uint8Array: UnsignedByteType,
+				Uint16Array: UnsignedShortType,
+				Uint32Array: UnsignedIntType,
+				Int8Array: ByteType,
+				Int16Array: ShortType,
+				Int32Array: IntType,
+				Uint8ClampedArray: UnsignedByteType,
+			};
+
 			const width = Math.pow( 2, Math.ceil( Math.log2( Math.sqrt( numElements / itemSize ) ) ) );
 			let height = Math.ceil( ( numElements / itemSize ) / width );
 			if ( width * height * itemSize < numElements ) height ++; // Ensure enough space
 
 			const newSize = width * height * itemSize;
 
-			const newArray = new Float32Array( newSize );
+			const newArray = new originalArray.constructor( newSize );
 
 			newArray.set( originalArray, 0 );
 
 			attribute.array = newArray;
 
-			const pboTexture = new DataTexture( attribute.array, width, height, format, FloatType );
+			const pboTexture = new DataTexture( attribute.array, width, height, format, typeMap[ attribute.array.constructor.name ] || FloatType );
 			pboTexture.needsUpdate = true;
 			pboTexture.isPBOTexture = true;
 
@@ -204,7 +232,20 @@ ${ flowData.code }
 
 			//
 
-			this.addLineFlowCode( `${ propertyName } = ${ snippet + channel }` );
+			const typePrefix = attribute.array.constructor.name.toLowerCase().charAt( 0 );
+
+			let prefix = 'vec4';
+			if ( typePrefix === 'u' ) {
+
+				prefix = 'uvec4';
+
+			} else if ( typePrefix === 'i' ) {
+
+				prefix = 'ivec4';
+
+			}
+
+			this.addLineFlowCode( `${ propertyName } = ${prefix}(${ snippet })${channel}` );
 
 			elementNodeData.propertyName = propertyName;
 
@@ -302,21 +343,36 @@ ${ flowData.code }
 			let snippet = null;
 			let group = false;
 
+
 			if ( uniform.type === 'texture' ) {
 
 				const texture = uniform.node.value;
 
+				let typePrefix = '';
+
+				if ( texture.isPBOTexture === true ) {
+
+					const prefix = texture.source.data.data.constructor.name.toLowerCase().charAt( 0 );
+
+					if ( prefix === 'u' || prefix === 'i' ) {
+
+						typePrefix = prefix;
+
+					}
+
+				}
+
 				if ( texture.compareFunction ) {
 
 					snippet = `sampler2DShadow ${ uniform.name };`;
 
 				} else if ( texture.isDataArrayTexture === true ) {
 
-					snippet = `sampler2DArray ${ uniform.name };`;
+					snippet = `${typePrefix}sampler2DArray ${ uniform.name };`;
 
 				} else {
 
-					snippet = `sampler2D ${ uniform.name };`;
+					snippet = `${typePrefix}sampler2D ${ uniform.name };`;
 
 				}
 
@@ -491,7 +547,7 @@ ${ flowData.code }
 
 				if ( shaderStage === 'compute' ) varying.needsInterpolation = true;
 				const type = varying.type;
-				const flat = type === 'int' || type === 'uint' ? 'flat ' : '';
+				const flat = type.includes( 'int' ) || type.includes( 'uv' ) || type.includes( 'iv' ) ? 'flat ' : '';
 
 				snippet += `${flat}${varying.needsInterpolation ? 'out' : '/*out*/'} ${type} ${varying.name};\n`;
 
@@ -504,7 +560,7 @@ ${ flowData.code }
 				if ( varying.needsInterpolation ) {
 
 					const type = varying.type;
-					const flat = type === 'int' || type === 'uint' ? 'flat ' : '';
+					const flat = type.includes( 'int' ) || type.includes( 'uv' ) || type.includes( 'iv' ) ? 'flat ' : '';
 
 					snippet += `${flat}in ${type} ${varying.name};\n`;
 

+ 32 - 0
examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js

@@ -147,6 +147,16 @@ class WebGLTextureUtils {
 			if ( glType === gl.SHORT ) internalFormat = gl.RG16I;
 			if ( glType === gl.INT ) internalFormat = gl.RG32I;
 
+		}
+
+		if ( glFormat === gl.RG_INTEGER ) {
+
+			if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.RG8UI;
+			if ( glType === gl.UNSIGNED_SHORT ) internalFormat = gl.RG16UI;
+			if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.RG32UI;
+			if ( glType === gl.BYTE ) internalFormat = gl.RG8I;
+			if ( glType === gl.SHORT ) internalFormat = gl.RG16I;
+			if ( glType === gl.INT ) internalFormat = gl.RG32I;
 
 		}
 
@@ -168,6 +178,17 @@ class WebGLTextureUtils {
 
 		}
 
+		if ( glFormat === gl.RGB_INTEGER ) {
+
+			if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.RGB8UI;
+			if ( glType === gl.UNSIGNED_SHORT ) internalFormat = gl.RGB16UI;
+			if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.RGB32UI;
+			if ( glType === gl.BYTE ) internalFormat = gl.RGB8I;
+			if ( glType === gl.SHORT ) internalFormat = gl.RGB16I;
+			if ( glType === gl.INT ) internalFormat = gl.RGB32I;
+
+		}
+
 		if ( glFormat === gl.RGBA ) {
 
 			if ( glType === gl.FLOAT ) internalFormat = gl.RGBA32F;
@@ -184,6 +205,17 @@ class WebGLTextureUtils {
 
 		}
 
+		if ( glFormat === gl.RGBA_INTEGER ) {
+
+			if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.RGBA8UI;
+			if ( glType === gl.UNSIGNED_SHORT ) internalFormat = gl.RGBA16UI;
+			if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.RGBA32UI;
+			if ( glType === gl.BYTE ) internalFormat = gl.RGBA8I;
+			if ( glType === gl.SHORT ) internalFormat = gl.RGBA16I;
+			if ( glType === gl.INT ) internalFormat = gl.RGBA32I;
+
+		}
+
 		if ( glFormat === gl.DEPTH_COMPONENT ) {
 
 			if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.DEPTH24_STENCIL8;

+ 1 - 0
src/constants.js

@@ -103,6 +103,7 @@ export const RedFormat = 1028;
 export const RedIntegerFormat = 1029;
 export const RGFormat = 1030;
 export const RGIntegerFormat = 1031;
+export const RGBIntegerFormat = 1032;
 export const RGBAIntegerFormat = 1033;
 
 export const RGB_S3TC_DXT1_Format = 33776;