【问题标题】:Pass 1d texture into fragment shader - all zeroes?将 1d 纹理传递到片段着色器 - 全为零?
【发布时间】:2013-12-19 00:14:31
【问题描述】:

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

这是我学习了许多教程后的 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 读取似乎会弄乱其他纹理..

【问题讨论】:

  • 我认为对于 int 格式的纹理提取,结果被标准化为 [0,1] 浮点数。试试isampler1D 采样器
  • @AndonM.Coleman - isampler1D 不会编译,GL_R16IGL_R32I 不会改变任何东西。
  • @AndonM.Coleman - 它似乎也不适用于浮点数 - 我已将代码添加到问题中。再次感谢您的宝贵时间!
  • 看我的回答,不要使用浮点纹理。使用常规定点(无符号归一化是技术术语)纹理。所以像glTexImage1D (GL_TEXTURE_1D, 0, GL_R8, myVec.size (), GL_RED, GL_UNSIGNED_BYTE, &amp;myVec [0]);。如果您需要存储超过 256 个值,则需要调整大小和类型以及 GLSL 着色器。

标签: c++ opengl textures fragment-shader


【解决方案1】:

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

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


你不能在 OpenGL 2.1 中使用整数纹理,如果我们回到你昨天在 UBO 上遇到的同样的问题。如果您无法在 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 并转换为 @ 987654334@。它远非完美,但多年来我们在没有整数纹理的情况下相处得很好。

这是对着色器的修改,正是这样做的:

#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.0GL_R16

【讨论】:

  • texelFetch 不会编译,float dat = texture1D(myTexture, 0.0).r * 65535.0; 也总是给出零:(
  • @Nathaniel 你使用的是哪个version 指令?
  • @Nathaniel:是的,我忘记了texelFetch (...) 在一分钟内不在 GLSL 1.20 中。我很快就会有一个更新的答案,你将不得不做一些数学来从你的整数索引计算浮点纹理坐标。这个数学将要求您知道着色器中纹理的尺寸。请参阅我对纹理过滤器的评论 - 它必须是 GL_NEAREST 才能使这种事情起作用。
  • 结果始终为零 - 我正在扯掉我的头发:(
  • @Nathaniel:你能展示一下你用来向一维纹理提供数据的调用吗?我认为您使用的是无效枚举,无论如何您都在最后一次编辑您的问题(format 在这种情况下应该是 GL_RED - 像 GL_R32F 这样的大小格式仅适用于internalFormat).
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-17
  • 2019-09-14
  • 2018-08-29
  • 1970-01-01
  • 2016-05-08
  • 1970-01-01
相关资源
最近更新 更多