索引表达式必须是常量 - WebGL/GLSL 错误 [英] Index expression must be constant - WebGL/GLSL error

查看:48
本文介绍了索引表达式必须是常量 - WebGL/GLSL 错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm having trouble accessing an array in a fragment shader using a non-constant int as the index. I've removed the formula as it wouldn't make much sense here anyway, but my code is meant to calculate the tileID based on the current pixel and use that to determine the color.

这是我的代码:

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);

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

Apparently GLSL doesn't like this and I get the error:

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

'[]' : Index expression must be constant

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

Does anyone know how I would fix this? Thanks.

推荐答案

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

As background -- GLSL looks a lot like C, but compiles a bit different. Things are very unrolled, and conditionals may be executed in parallel and switched at the end, that sort of thing. Depends on the hardware...

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

You can use loop indices or constants to index into arrays. The assignment in your loop is ok, but the access by tileID isn't.

WebGL 着色器语言来自 GLES,已记录

WebGL Shader language is from GLES, documented

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.

希望有帮助!

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

Oh, as for fixing it, in the exact example above... looks like you could compute from tileID rather than precompute and index.

或者,预先计算您喜欢的任何数组,并将其作为纹理传递.当然,纹理可以随意编入索引.

Or, precompute whatever array you like, and pass it in as a texture. A texture, of course, can be indexed however you like.

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

Here's a javascript helper method I use, to pass floats down to the shaders:

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;
}

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

Note the use of gl.NEAREST, so it doesn't "blur" your values! Then you can set it up before the gl.drawXxx call, with something like

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);

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

And in the shader (I believe fragment or vertex; some earlier webgl's didn't support vertex textures...)

uniform sampler2D uSampler;
...
vec4 value = texture2D(uSampler, vec2(xValueBetween0And1,yValueBetween0And1));

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

So, you have to index appropriately for the array-as-texture size, within range of 0 to 1. Try to sample from the middle of each value/pixel. Like, if the array is 2 values wide, index by 0.25 and 0.75.

这就是它的要点!

这篇关于索引表达式必须是常量 - WebGL/GLSL 错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆