在愉快地使用PyOpenGL一段时间后,我现在严重陷入困境。我正在开发一个Python包,它允许我使用GLSL着色器和OpenCL程序进行图像处理,使用纹理作为标准方式将数据输入和输出GLSL着色器和OpenCL程序。
一切正常,除了我无法成功将纹理复制到pbo(像素缓冲对象)。 我正在使用pbo来获取OpenCL中的纹理数据,并且在PyOpenCL中运行良好且快速:我可以从其复制我的OpenCL输出 pbo到纹理并显示它,我也可以将数据从cpu加载到pbo中。但我绝对没有试图用GPU上的纹理数据来填充我的pbo,这是我需要做的就是将GLSL着色器生成的图像加载到OpenCL中进行进一步处理。
我已经阅读了两种方法: 变体1绑定pbo,绑定纹理并使用glGetTexImage() 变量2将纹理附加到帧缓冲对象,绑定fbo和pbo并使用glReadPixels()
我还读到glReadPixels()和glGetTexImage()的PyOpenGL版本在使用绑定pbo时应该使用的'Null'指针有问题,因此我使用的是OpenGL.raw.GL变体。
但是在这两种情况下我都会收到“无效操作”错误,而我真的看不出我做错了什么。以下两个版本 我的pixelbuffer Python类的load_texture()方法,我希望我没有把它们剥离得太远......
变体1:
def _load_texture(self, texture):
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, self.id)
glEnable(texture.target)
glActiveTexture(GL_TEXTURE0_ARB)
glBindTexture(texture.target, texture.id)
OpenGL.raw.GL.glGetTexImage(texture.target, 0, texture.gl_imageformat,
texture.gl_dtype, ctypes.c_void_p(0))
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0)
glDisable(texture.target)
变体2:
def _load_texture(self, texture):
fbo = FrameBufferObject.from_textures([texture])
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
texture.target, texture.id, 0)
glReadBuffer(GL_COLOR_ATTACHMENT0)
glBindFramebuffer(GL_FRAMEBUFFER, fbo.id)
glBindBuffer(GL_PIXEL_PACK_BUFFER, self.id)
OpenGL.raw.GL.glReadPixels(0, 0, self.size[0], self.size[1],
texture.gl_imageformat, texture.gl_dtype,
ctypes.c_void_p(0))
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_RECTANGLE_ARB, 0, 0)
glBindFramebuffer(GL_FRAMEBUFFER, 0)
编辑(添加有关错误和初始化我的pbo的一些信息):
我得到的变量1的错误是:
OpenGL.error.GLError: GLError(
err = 1282,
description = 'invalid operation',
baseOperation = glGetTexImage,
cArguments = (
GL_TEXTURE_RECTANGLE_ARB,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
c_void_p(None),
)
我正在初次化我的pbo:
self.usage = usage
if isinstance(size, tuple):
size = size[0] * size[1] * self.imageformat.planecount
bytesize = self.imageformat.get_bytesize_per_plane() * size
glBindBuffer(self.arraytype, self.id)
glBufferData(self.arraytype, bytesize, None, self.usage)
glBindBuffer(self.arraytype, 0)
'self.arraytype'是GL_ARRAY_BUFFER,self.usage我已经尝试了所有可能性以防万一,但GL_STREAM_READ对我的使用类型来说似乎最合乎逻辑。 我通常使用的大小是1024乘1024,4个平面,每个平面1个字节,因为它是unisgned int。从主机传输像素数据时,这种方法很有效。
我也在使用Kubuntu 11.10,在GPU上使用带有3Gb内存的NVIDIA GeForce GTX 580,使用专有驱动程序,版本295.33
我错过了什么?
答案 0 :(得分:1)
自己找到了一个解决方案而没有真正理解为什么会产生巨大的差异。
我所拥有的代码(对于两种变体)基本上都是正确的,但需要调用glBufferData才能使用它。我在原始代码中初始化我的pbo时已经完成了相同的调用,但我的猜测是在初始化和我尝试加载纹理之间有足够的进行,因为pbo内存不知何故变成了在此期间解除了分配。
现在我只是将这个调用移到了我的glGetTexImage调用附近,它的工作原理没有改变。
奇怪,我不确定这是一个错误或功能,如果它与PyOpenGL,NVIDIA驱动程序或其他东西有关。如果它是预期的行为,那么在任何地方都很容易找到它。
下面的变体1代码可以工作并且速度也很快,变体2在以相同的方式处理时效果很好,但速度只有一半。
def _load_texture(self, texture):
bytesize = (self.size[0] * self.size[1] *
self.imageformat.planecount *
self.imageformat.get_bytesize_per_plane())
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, self.id)
glBufferData(GL_PIXEL_PACK_BUFFER_ARB,
bytesize,
None, self.usage)
glEnable(texture.target)
glActiveTexture(GL_TEXTURE0_ARB)
glBindTexture(texture.target, texture.id)
OpenGL.raw.GL.glGetTexImage(texture.target, 0, texture.gl_imageformat,
texture.gl_dtype, ctypes.c_void_p(0))
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0)
glDisable(texture.target)