如何使用 QOpenGLBuffer::PixelUnpackBuffer
How to use QOpenGLBuffer:: PixelUnpackBuffer
我不知道如何正确地写入和读取 QOpenGLBuffer:: PixelUnpackBuffer
。
- 写入 PBO 之前的正确设置是什么?
QOpenGLBuffer::write
将无法使用简单的 QImage.bits()
或 glReadPixels()
将 FBO 渲染传递到 PBO。它必须是特定类型的数据?
- 如何将书面 PBO 与
Texture::setData()
一起使用?
一个简单的 Texture.setData(*format*, *pixel_type*, pubo, nullptr)
就够了吗?
这里有一些代码来举例说明我在做什么:
QImage ScribbleArea::proImg(const QImage& image,
const QImage& tip,
const QString& vertexPosVar,
const QString& textureCoordVar){
QOpenGLContext context;
QOffscreenSurface offSurface;
offSurface.setFormat(context.format());
offSurface.create();
// I'm sharing the context to show the offscreen Render into a
// QOpenGLTextureBlitter under PaintGL()
context.setShareContext(ScribbleArea::context());
context.create();
context.makeCurrent(&offSurface);
m_fbo = new QOpenGLFramebufferObject(image.size());
m_fbo->bind();
context.functions()->glViewport(0, 0, image.width(), image.height());
QOpenGLShaderProgram program(&context);
program.addShaderFromSourceFile(QOpenGLShader::Vertex, "path to vertex shader");
program.addShaderFromSourceFile(QOpenGLShader::Fragment, "path to fragment shader");
program.link();
program.bind();
// The next block is basically what I understood how to setup a PBO using
// Qt's OpenGL wrapper.
QOpenGLBuffer *pubo = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer);
pubo->setUsagePattern(QOpenGLBuffer::DynamicCopy);
pubo->create();
pubo->bind();
pubo->map(QOpenGLBuffer::ReadWrite);
pubo->allocate(image.bits(),image.sizeInBytes());
pubo->write(0,image.bits(),image.sizeInBytes());
pubo->unmap();
pubo->release();
// Testing how to use texture::setData() using straight bytes instead of the
// baked method of setData(QImage).
// I believe this is how to use the PBO's content to set the texture using QOpenGL.
QOpenGLTexture textu(QOpenGLTexture::Target2D);
textu.setSize(image.width(),image.height());
textu.setFormat(QOpenGLTexture::RGBA8_UNorm);
textu.allocateStorage();
textu.setData(QOpenGLTexture::BGRA,QOpenGLTexture::UInt8,image.bits(),nullptr);
// The texture bellow is a test to see if I was able to set up two textures and
// change which one the shader should use.
QOpenGLTexture brush(QOpenGLTexture::Target2D);
brush.setData(tip);
// Using native OpenGL snippets never work. The texture remain black.
// GLuint tex;
// glGenTextures(1, &tex);
// glBindTexture(GL_TEXTURE_2D, tex);
// glTexImage2D(GL_TEXTURE_2D, 0, 3, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glBindTexture( GL_TEXTURE_2D, 0);
GLint brTip = 1;
brush.bind(brTip);
GLint oriTxt = 0;
textu.bind(oriTxt);
//Rest of the code. Following Amin Ahmadi tutorial.
你有一些误解,其中大部分与 Qt 的抽象无关 类,但与这些对象在 GL 本身中的工作方式有关:
// The next block is basically what I understood how to setup a PBO using
// Qt's OpenGL wrapper.
QOpenGLBuffer *pubo = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer);
pubo->setUsagePattern(QOpenGLBuffer::DynamicCopy);
pubo->create();
pubo->bind();
到目前为止,还不错...
pubo->map(QOpenGLBuffer::ReadWrite);
现在您尝试将缓冲区映射到内存。这是行不通的,因为缓冲区对象 没有 分配给它的任何存储,所以这个调用应该失败并出现 GL 错误。此外,map
会将内存地址 return 映射到内存将被映射的位置,您在这里从不关心,因此即使映射有效,您也无法使用它。更糟糕的是,在映射缓冲区时,您不能对其进行任何 GL 操作(除非您创建持久映射)。
pubo->allocate(image.bits(),image.sizeInBytes());
好的,现在您创建一些存储空间。但只是因为映射操作较早失败。
pubo->write(0,image.bits(),image.sizeInBytes());
这也应该有效。也只是因为你没有在这里激活内存映射。
pubo->unmap();
这将失败,因为未映射缓冲区。不过没关系。无论如何,您从来不需要也不打算使用缓冲区映射。
- What is the proper setup before writing into a PBO?
创建缓冲区对象,并为其分配(足够的)存储空间。
QOpenGLBuffer::write
will not work using with a simple QImage.bits()
, or glReadPixels()
to pass the FBO render into the PBO. It has to be a specific type of data?
不知道你在说什么。将 QImage
中的数据写入其中即可。 glReadPixels
这里的意思不清楚。如果要将像素读入缓冲区对象,则需要将其绑定为 GL_PIXEL_PACK_BUFFER
,而不是 _UNPACK_BUFFER
.
为什么说“不行”?
- How do you use a written PBO with
Texture::setData()
? A simple Texture.setData(*format*, *pixel_type*, pubo, nullptr)
据我所知(即可以在文档中找到)QOpenGLTexture::setData()
没有重载,它会采用任何 QtOpenGLBuffer
参数。
在 OpenGL 中,当绑定 GL_PIXEL_UNPACK_BUFFER
时,glTexImage...()
函数的 data
指针将被视为该缓冲区对象的 字节偏移量.因此,你只需要绑定你的 pobo
,并用正确的值调用 setData
,但显然你永远不会将 pobo
作为参数传递给 setData
。
顺便说一句,那些 Qt OpenGL 抽象产生的问题多于它们解决的问题(例如,QtOpenGLBuffer
抽象使 GL 缓冲对象看起来像是类型化的,这是完全错误的——同一个缓冲对象可以同时绑定到多个绑定目标)。然而,无论您对这些抽象有何看法,它们绝不会阻止您了解实际的底层 GL 对象是如何工作的——实际上,与它们一起您必须同时学习 GL 和 Qt 的抽象语义有时非常随意。
我不知道如何正确地写入和读取 QOpenGLBuffer:: PixelUnpackBuffer
。
- 写入 PBO 之前的正确设置是什么?
QOpenGLBuffer::write
将无法使用简单的QImage.bits()
或glReadPixels()
将 FBO 渲染传递到 PBO。它必须是特定类型的数据?- 如何将书面 PBO 与
Texture::setData()
一起使用? 一个简单的Texture.setData(*format*, *pixel_type*, pubo, nullptr)
就够了吗?
这里有一些代码来举例说明我在做什么:
QImage ScribbleArea::proImg(const QImage& image,
const QImage& tip,
const QString& vertexPosVar,
const QString& textureCoordVar){
QOpenGLContext context;
QOffscreenSurface offSurface;
offSurface.setFormat(context.format());
offSurface.create();
// I'm sharing the context to show the offscreen Render into a
// QOpenGLTextureBlitter under PaintGL()
context.setShareContext(ScribbleArea::context());
context.create();
context.makeCurrent(&offSurface);
m_fbo = new QOpenGLFramebufferObject(image.size());
m_fbo->bind();
context.functions()->glViewport(0, 0, image.width(), image.height());
QOpenGLShaderProgram program(&context);
program.addShaderFromSourceFile(QOpenGLShader::Vertex, "path to vertex shader");
program.addShaderFromSourceFile(QOpenGLShader::Fragment, "path to fragment shader");
program.link();
program.bind();
// The next block is basically what I understood how to setup a PBO using
// Qt's OpenGL wrapper.
QOpenGLBuffer *pubo = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer);
pubo->setUsagePattern(QOpenGLBuffer::DynamicCopy);
pubo->create();
pubo->bind();
pubo->map(QOpenGLBuffer::ReadWrite);
pubo->allocate(image.bits(),image.sizeInBytes());
pubo->write(0,image.bits(),image.sizeInBytes());
pubo->unmap();
pubo->release();
// Testing how to use texture::setData() using straight bytes instead of the
// baked method of setData(QImage).
// I believe this is how to use the PBO's content to set the texture using QOpenGL.
QOpenGLTexture textu(QOpenGLTexture::Target2D);
textu.setSize(image.width(),image.height());
textu.setFormat(QOpenGLTexture::RGBA8_UNorm);
textu.allocateStorage();
textu.setData(QOpenGLTexture::BGRA,QOpenGLTexture::UInt8,image.bits(),nullptr);
// The texture bellow is a test to see if I was able to set up two textures and
// change which one the shader should use.
QOpenGLTexture brush(QOpenGLTexture::Target2D);
brush.setData(tip);
// Using native OpenGL snippets never work. The texture remain black.
// GLuint tex;
// glGenTextures(1, &tex);
// glBindTexture(GL_TEXTURE_2D, tex);
// glTexImage2D(GL_TEXTURE_2D, 0, 3, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glBindTexture( GL_TEXTURE_2D, 0);
GLint brTip = 1;
brush.bind(brTip);
GLint oriTxt = 0;
textu.bind(oriTxt);
//Rest of the code. Following Amin Ahmadi tutorial.
你有一些误解,其中大部分与 Qt 的抽象无关 类,但与这些对象在 GL 本身中的工作方式有关:
// The next block is basically what I understood how to setup a PBO using // Qt's OpenGL wrapper. QOpenGLBuffer *pubo = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer); pubo->setUsagePattern(QOpenGLBuffer::DynamicCopy); pubo->create(); pubo->bind();
到目前为止,还不错...
pubo->map(QOpenGLBuffer::ReadWrite);
现在您尝试将缓冲区映射到内存。这是行不通的,因为缓冲区对象 没有 分配给它的任何存储,所以这个调用应该失败并出现 GL 错误。此外,map
会将内存地址 return 映射到内存将被映射的位置,您在这里从不关心,因此即使映射有效,您也无法使用它。更糟糕的是,在映射缓冲区时,您不能对其进行任何 GL 操作(除非您创建持久映射)。
pubo->allocate(image.bits(),image.sizeInBytes());
好的,现在您创建一些存储空间。但只是因为映射操作较早失败。
pubo->write(0,image.bits(),image.sizeInBytes());
这也应该有效。也只是因为你没有在这里激活内存映射。
pubo->unmap();
这将失败,因为未映射缓冲区。不过没关系。无论如何,您从来不需要也不打算使用缓冲区映射。
- What is the proper setup before writing into a PBO?
创建缓冲区对象,并为其分配(足够的)存储空间。
QOpenGLBuffer::write
will not work using with a simpleQImage.bits()
, orglReadPixels()
to pass the FBO render into the PBO. It has to be a specific type of data?
不知道你在说什么。将 QImage
中的数据写入其中即可。 glReadPixels
这里的意思不清楚。如果要将像素读入缓冲区对象,则需要将其绑定为 GL_PIXEL_PACK_BUFFER
,而不是 _UNPACK_BUFFER
.
为什么说“不行”?
- How do you use a written PBO with
Texture::setData()
? A simpleTexture.setData(*format*, *pixel_type*, pubo, nullptr)
据我所知(即可以在文档中找到)QOpenGLTexture::setData()
没有重载,它会采用任何 QtOpenGLBuffer
参数。
在 OpenGL 中,当绑定 GL_PIXEL_UNPACK_BUFFER
时,glTexImage...()
函数的 data
指针将被视为该缓冲区对象的 字节偏移量.因此,你只需要绑定你的 pobo
,并用正确的值调用 setData
,但显然你永远不会将 pobo
作为参数传递给 setData
。
顺便说一句,那些 Qt OpenGL 抽象产生的问题多于它们解决的问题(例如,QtOpenGLBuffer
抽象使 GL 缓冲对象看起来像是类型化的,这是完全错误的——同一个缓冲对象可以同时绑定到多个绑定目标)。然而,无论您对这些抽象有何看法,它们绝不会阻止您了解实际的底层 GL 对象是如何工作的——实际上,与它们一起您必须同时学习 GL 和 Qt 的抽象语义有时非常随意。