将1d纹理传递到片段着色器 - 全部为零?

时间:2013-12-19 00:14:31

标签: c++ opengl textures fragment-shader

我正在尝试使用1D纹理将一组int数组传递到片段着色器中。虽然代码编译并运行,但当我查看着色器中的纹理值时,它们都是零!

这是我遵循了许多教程之后的C ++代码:

GLuint texture;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0 + 5); // use the 5th since first 4 may be taken
glBindTexture  (GL_TEXTURE_1D, texture);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RED_INTEGER, myVec.size(), 0, 
                               GL_RED_INTEGER, GL_INT, &myVec[0]);

GLint textureLoc =  glGetUniformLocation( program, "myTexture" );
glUniform1i(textureLoc, 5); 

这就是我如何尝试访问着色器中的纹理:

uniform sampler1D myTexture; 
int dat = int(texture1D(myTexture, 0.0).r); // 0.0 is just an example 
if (dat == 0) { // always true!

我确信这对我来说是一些微不足道的错误,但我无法理解。遗憾的是我不得不使用GLSL 1.20,所以这种语法似乎已经过时了。

那么为什么着色器中的纹理值始终为零?

修改

如果我用浮点数替换int,我仍然有问题:

std::vector <float> temp; 
// fill temp...
glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, GL_R32F, temp.size(), 0, GL_R32F, GL_FLOAT, &temp[0]);
// ...
glUniform1f(textureLoc, 5);

这一次,只是从sampler读取似乎搞乱了其他纹理..

1 个答案:

答案 0 :(得分:2)

首先,GL_RED_INTEGER对于内部格式是错误的。我会使用GL_R32I(32位有符号整数),您也可以使用GL_R8IGL_R16I,具体取决于您的实际存储要求 - 较小的类型通常更好。另外,不要使用sampler1D作为整数纹理,请使用isampler1D

由于OpenGL ES在您使用像素传输函数(例如glTexture2D (...))时不支持数据类型转换,因此如果查看表格,通常可以在表格中找到格式,内部格式和类型的最佳组合OpenGL ES docs

<小时/> 如果我们回到你昨天使用UBO的同样问题,你不能在OpenGL 2.1中使用整数纹理。如果您无法在OS X上获得核心配置文件上下文,则仅限于GLSL 1.2(OpenGL 2.1)。将定义GL_R32IGL_RED_INTEGER等的常量,但它们应该在OS X的OpenGL 2.1实现中在运行时创建GL_INVALID_ENUM错误。

这并不是说您无法将整数值打包到标准定点纹理中并在着色器中返回整数值。如果您使用每组件8位格式(例如GL_R8),则可以存储 0 - 255 范围内的值。在着色器中,在进行纹理查找后(我会将GL_NEAREST用于纹理过滤器,过滤会使事情变得混乱)您可以将浮点结果乘以 255.0 并进行投射到int。它远非完美,但我们相处很好,没有整数纹理多年。

以下是对着色器的修改:

#version 120

uniform sampler1D myTexture;
int dat = (int)(texture1D (myTexture, (idx + 0.5)/(float)textureWidth).r * 255.0);
if (dat == 0) { // not always true!

假设GL_R8为内部格式,65535.0使用GL_R16