Kub*_*lik 3 arrays glsl webgl three.js
我想为Three.js写一个片段着色器,它需要10000个整数的大数组。当我尝试在着色器的glsl代码中声明这样的数组时:
uniform int colorGrid[10000];
Run Code Online (Sandbox Code Playgroud)
然后着色器渲染器抛出
ERROR: too many uniform
Run Code Online (Sandbox Code Playgroud)
我还有其他选择-如何将这么大的数据传递给片段着色器?
纹理是大阵列。在纹理中传递整数会比较困难,但并非没有可能(对于WebGL2,请参见下文)。您需要在纹理的红色,绿色,蓝色和Alpha通道上拆分整数值,或者对纹理进行浮动,这将使整数值最大为2 ^ 24
要将整数打包到纹理中,您可以执行以下操作
// assumes unsigned ints
setPixelFromInt(pixels, width, x, y, intValue) {
var r = (intValue >> 24) & 0xFF;
var g = (intValue >> 16) & 0xFF;
var b = (intValue >> 8) & 0xFF;
var a = (intValue >> 0) & 0xFF;
var offset = (y * width + x) * 4;
pixels[offset + 0] = r;
pixels[offset + 1] = g;
pixels[offset + 2] = b;
pixels[offset + 3] = a;
}
var width = 100;
var height = 100;
var pixels = new Uint8Array(width * height * 4);
...
Run Code Online (Sandbox Code Playgroud)
要在着色器中恢复您的值,请执行以下操作?
uniform vec2 textureDimensions;
uniform sampler2D arrayTexture;
int getValueFromTexture(sampler2D arrayTexture, vec2 textureDimensions, int index) {
float x = mod(float(index), textureDimensions.x);
float y = floor(float(index) / textureDimensions.x);
vec2 uv = (vec2(x, y) + .5) / textureDimensions;
vec4 color = texture2D(arrayTexture, uv);
return int(color.r * 256.0 * 256.0 * 256.0 +
color.b * 256.0 * 256.0 +
color.g * 256.0 +
color.a);
}
Run Code Online (Sandbox Code Playgroud)
确保将过滤设置为gl.NEAREST
注意:我实际上并没有运行该代码,但是它说明了这个想法
在WebGL2中,您可以具有8、16或32位的整数纹理,并且在着色器中,该texelFetch函数无需过滤即可提取特定lod的特定纹理像素的值。还有一个textureSize功能,因此您不必手动统一传递纹理大小。
const int lod = 0
ivec2 textureDimensions = textureSize(arrayTexture, lod);
int x = index % textureDimensions.x;
int y = index / textureDimensions.x;
ivec4 color = texelFetch(arrayTexture, ivec2(x,y), lod);
Run Code Online (Sandbox Code Playgroud)