索引表达式必须是常量 - WebGL/GLSL错误

Joe*_*ani 15 arrays glsl webgl glsles

我在使用非常量int作为索引访问片段着色器中的数组时遇到问题.我删除了公式,因为它无论如何都没有多大意义,但我的代码是基于当前像素计算tileID并使用它来确定颜色.

这是我的代码:

int tileID = <Insert formula here>;

vec3 colorTest;

int arrayTest[1024];
for (int x = 0; x < 1024; x++) {
    if (x == 1) arrayTest[x] = 1;
    else arrayTest[x] = 2;
}

if (arrayTest[tileID] == 1) colorTest = vec3(0.0, 1.0, 0.0);
else if (arrayTest[tileID] == 2) colorTest = vec3(1.0, 0.0, 0.0);
else colorTest = vec3(0.0, 0.0, 0.0);
Run Code Online (Sandbox Code Playgroud)

显然GLSL不喜欢这个,我得到错误:

'[]':索引表达式必须是常量

有谁知道我会如何解决这个问题?谢谢.

dav*_*ink 11

作为背景 - GLSL看起来很像C,但编译有点不同.事情是非常展开的,并且条件可以并行执行并在最后切换,这样的事情.取决于硬件......

您可以使用循环索引或常量来索引数组.循环中的赋值是可以的,但tileID的访问不是.

WebGL Shader语言来自GLES,记录在案

http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf

附录第5节讨论:

Indexing of Arrays, Vectors and Matrices
Definition:
constant-index-expressions are a superset of constant-expressions. Constant-index-expressions can include loop indices as defined in Appendix A section 4.
The following are constant-index-expressions:
• Constant expressions
• Loop indices as defined in section 4
• Expressions composed of both of the above
When used as an index, a constant-index-expression must have integral type.
Run Code Online (Sandbox Code Playgroud)

希望有所帮助!


哦,至于修复它,在上面的确切示例中...看起来你可以从tileID而不是预计算和索引计算.

或者,预先计算您喜欢的任何数组,并将其作为纹理传递.当然,纹理可以被索引,无论你喜欢什么.

这是我使用的javascript辅助方法,将浮点数传递给着色器:

function glSetupStuff() { ...
...
if(!gl.getExtension("OES_texture_float"))   // <<-- enables RGBA float values, handy!
    alert("cant pass in floats, use 8-bit values instead.");
... }

/*
 * Pass in an array of rgba floats,
 * for example: var data = new Float32Array([0.1,0.2,0.3,1,  .5,.5,1.0,1]);
 */
function textureFromFloats(gl,width,height,float32Array) 
{
var oldActive = gl.getParameter(gl.ACTIVE_TEXTURE);
gl.activeTexture(gl.TEXTURE15); // working register 31, thanks.

var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 
                width, height, 0, 
                gl.RGBA, gl.FLOAT, float32Array);

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.bindTexture(gl.TEXTURE_2D, null);

gl.activeTexture(oldActive);

return texture;
}
Run Code Online (Sandbox Code Playgroud)

注意gl.NEAREST的使用,所以它不会"模糊"你的值!然后你可以在gl.drawXxx调用之前设置它,例如

textureUnit = 3;  // from 0 to 15 is ok
gl.activeTexture(gl.TEXTURE0 + textureUnit);
gl.bindTexture(gl.TEXTURE_2D, texture);

var z = gl.getUniformLocation(prog, "uSampler");
gl.uniform1i(z, textureUnit);
Run Code Online (Sandbox Code Playgroud)

在着色器中(我相信片段或顶点;一些早期的webgl不支持顶点纹理......)

uniform sampler2D uSampler;
...
vec4 value = texture2D(uSampler, vec2(xValueBetween0And1,yValueBetween0And1));
Run Code Online (Sandbox Code Playgroud)

因此,您必须为数组作为纹理大小进行适当索引,范围为0到1.尝试从每个值/像素的中间进行采样.比如,如果数组宽度为2,则索引为0.25和0.75.

这就是它的要点!

  • @ Joey.Morani:另请注意,允许的数组索引类型因资源类型和着色器阶段而异.例如,在OpenGL ES 2.0中的顶点着色器中,您可以使用非const整数表达式索引统一数组.在片段着色器中,它必须是const-index(相反,它必须支持这一点 - 然而,实现可以自由地超出此要求).官方[GLSL规范](http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf)<pp.109-110 - A.5>,可能值得一读...... (4认同)

asd*_*sdf 5

在OS X 10.11.6上的Safari 9.1.2中测试过

uniform float data[32];

float getData(int id) {
    for (int i=0; i<32; i++) {
        if (i == id) return data[i];
    }
}

void main(void) {
    float f = getData(yourVariable);
}
Run Code Online (Sandbox Code Playgroud)