如何通过缓冲纹理将16位整数正确发送到GLSL着色器

时间:2016-08-24 19:30:07

标签: c++ opengl glsl buffer

我有3072个std::int16_t类型的值(16位整数),它对应于GLshort。我想把它们发送到我的GLSL着色器。我读了Buffer Textures并尝试实施这种方法。但是,一旦到达着色器,数据似乎不再完好无损。我还不确定,但看起来价值都是0或最大值。我做错了什么?

我的初始化代码看起来像这样(禁止一些与之无关的东西):

// 1: Get the data - array of GLshort:

GLshort tboData[3072];
for (size_t i = 0; i < 3072; ++i)
{
    // cdb.getSprite() returns std::int16_t
    tboData[i] = (GLshort) cbd.getSprite(i);
}

// 2: Make sure the Shader Program is being used:

sp->use(); // sp is a wrapper class for GL Shader Programs

// 3: Generate the GL_TEXTURE_BUFFER, bind it and send the data:

GLuint tbo;
glGenBuffers(1, &tbo);
glBindBuffer(GL_TEXTURE_BUFFER, tbo);
glBufferData(GL_TEXTURE_BUFFER, sizeof(tboData), tboData, GL_STATIC_DRAW);

// 4: Generate the Buffer Texture, activate and bind it:

GLuint tboTex;
glGenTextures(1, &tboTex);
glActiveTexture(GL_TEXTURE1); // GL_TEXTURE0 is a spritesheet
glBindTexture(GL_TEXTURE_BUFFER, tboTex);

// 5: Associate them using `GL_R16` to match the 16 bit integer array:

glTexBuffer(GL_TEXTURE_BUFFER, GL_R16, tbo);

// 6: Make the connection within the Shader:

glUniform1i(sp->getUniformLocation("tbo"), 1);
glBindBuffer(GL_TEXTURE_BUFFER, 0);

在渲染循环开始时,我确保所有内容都已绑定:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, spriteSheet);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER, tboTex);

在我的渲染循环中,我设置了一个将用于索引TBO的制服:

glUniform1i(sp->getUniformLocation("tboIndex"), tboIndex);

现在,顶点着色器重要部分:

#version 140

// other ins, outs, uniforms ...

uniform int tboIndex;
uniform isamplerBuffer tbo;
out float pass_Sprite; // Frag shader crashes when this is int, why?

void main()
{
    // gl_Position, matrices, etc ...
    pass_Sprite = texelFetch(tbo, tboIndex).r;
}

欢迎任何建议。

1 个答案:

答案 0 :(得分:6)

  

GL_R16

这是一种未签名的 normalized integer 格式。您的缓冲区采样器需要带符号的非规范化整数。

correct image formatGL_R16I

  

当这是int时,片段着色器崩溃,为什么

可能是因为你没有使用flat interpolation。插值对非浮点值不起作用。

它不会崩溃;它只是无法编译。您应始终检查着色器中的编译错误。