在片段着色器中访问 3D 数组
Access to 3D array in fragment shader
我正在尝试使用 PyOpenGL 从 Python 程序向片段着色器提供对 3 维标量数据数组的访问。
在片段着色器中,我声明了 3d 采样器统一
uniform sampler3D vol;
并且在 Python 程序中我有以下代码来设置标量 3d 纹理
vol = numpy.random.rand(3, 3, 3).astype(np.float32)
texture = glGenTextures(1)
glUniform1i(glGetUniformLocation(program, "vol"), 0)
glActiveTexture(GL_TEXTURE0 + 0)
glBindTexture(GL_TEXTURE_3D, texture)
glTexImage3D(GL_TEXTURE_3D, 0, GL_RED, 3, 3, 3, 0, GL_RED, GL_FLOAT, vol)
glEnable(GL_TEXTURE_3D)
但是,无论我从采样器的哪个位置取值,例如
color = texture(vol, vec3(0, 0, 0));
看来我总是得到黑色(0, 0, 0)。
我做错了什么?
我知道我的片段着色器的基本设置有效,即如果我写 color = vec3(1, 0, 0)
我得到红色像素。
我也知道没有OpenGL错误,因为我是运行由glutInit()
处理的带有选项-glerror
的程序,导致OpenGL错误被翻译成Python 个异常。
那是因为你的 GL_RED
纹理格式被 限制 到范围 <0,1>
!!!
要补救,您需要使用非钳位纹理格式或禁用钳位...这里是在我的 GL 实现上工作的示例:
- GLSL back raytrace through 3D volume
此处从两者中提取的格式:
glTexImage3D(GL_TEXTURE_3D, 0, GL_R16F, xs,ys,zs, 0, GL_RED, GL_FLOAT, dat);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, size, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
对于标量数据,我会使用第一个选项。还有更多的格式没有限制,试试看吧...
我从未使用过禁用钳位功能,但在研究类似问题时在某处看到这段代码(不确定是否有效):
glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE);
从理论上讲,您可以使用任何纹理格式...
要验证您可以使用这个:
我也没有看到纹理集的任何参数。我希望是这样的:
glBindTexture(GL_TEXTURE_3D,txrvol);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE);
避免因非精确纹理坐标的插值而弄乱您的数据...
我发现了问题:显然 GL_TEXTURE_3D 默认情况下是 mipmapped,我只提供了级别 0,并且(我不太清楚)选择了另一个级别。问题由glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0)
.
解决
我正在尝试使用 PyOpenGL 从 Python 程序向片段着色器提供对 3 维标量数据数组的访问。
在片段着色器中,我声明了 3d 采样器统一
uniform sampler3D vol;
并且在 Python 程序中我有以下代码来设置标量 3d 纹理
vol = numpy.random.rand(3, 3, 3).astype(np.float32)
texture = glGenTextures(1)
glUniform1i(glGetUniformLocation(program, "vol"), 0)
glActiveTexture(GL_TEXTURE0 + 0)
glBindTexture(GL_TEXTURE_3D, texture)
glTexImage3D(GL_TEXTURE_3D, 0, GL_RED, 3, 3, 3, 0, GL_RED, GL_FLOAT, vol)
glEnable(GL_TEXTURE_3D)
但是,无论我从采样器的哪个位置取值,例如
color = texture(vol, vec3(0, 0, 0));
看来我总是得到黑色(0, 0, 0)。
我做错了什么?
我知道我的片段着色器的基本设置有效,即如果我写 color = vec3(1, 0, 0)
我得到红色像素。
我也知道没有OpenGL错误,因为我是运行由glutInit()
处理的带有选项-glerror
的程序,导致OpenGL错误被翻译成Python 个异常。
那是因为你的 GL_RED
纹理格式被 限制 到范围 <0,1>
!!!
要补救,您需要使用非钳位纹理格式或禁用钳位...这里是在我的 GL 实现上工作的示例:
- GLSL back raytrace through 3D volume
此处从两者中提取的格式:
glTexImage3D(GL_TEXTURE_3D, 0, GL_R16F, xs,ys,zs, 0, GL_RED, GL_FLOAT, dat);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, size, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
对于标量数据,我会使用第一个选项。还有更多的格式没有限制,试试看吧...
我从未使用过禁用钳位功能,但在研究类似问题时在某处看到这段代码(不确定是否有效):
glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE);
从理论上讲,您可以使用任何纹理格式...
要验证您可以使用这个:
我也没有看到纹理集的任何参数。我希望是这样的:
glBindTexture(GL_TEXTURE_3D,txrvol);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE);
避免因非精确纹理坐标的插值而弄乱您的数据...
我发现了问题:显然 GL_TEXTURE_3D 默认情况下是 mipmapped,我只提供了级别 0,并且(我不太清楚)选择了另一个级别。问题由glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0)
.