Render TO and WITH texture using QOpenGLTexture and QOpenGLFramebufferObject

二次信任 提交于 2019-12-13 07:20:00

问题


According to the document of QOpenGLTexture in Qt5, one can render WITH texture, and can also render TO texture. Is there any simple example about these two usages? The scenario of such usages could be found at this link. The problematic codes about this are listed below:

In the offscreen part:

Initialization of offscreen rendering:

p_offscreen_context_ = std::make_unique<QOpenGLContext>();
p_offscreen_context_->setFormat(_p_onscreen_context->format()); // _p_onscreen_context is the context in the onscreen rendering part
p_offscreen_context_->setShareContext(_p_onscreen_context);
if (!p_offscreen_context_->create()) {
    std::cerr << "Failed to create OpenGL context!!" << std::endl;
    return;
}
p_offscreen_surface_ = std::make_unique<QOffscreenSurface>();
p_offscreen_surface_->setFormat(p_offscreen_context_->format());
p_offscreen_surface_->create();
if (!p_offscreen_surface_->isValid()) {
    std::cerr << "Failed to create Offscreen Surface!!" << std::endl;
    return;
}
make_current(); // p_offscreen_context_->makeCurrent(p_offscreen_surface_.get());
p_functions_ = std::make_unique<QOpenGLFunctions>();
p_functions_->initializeOpenGLFunctions();
create_frame_buffer_object(); // see below
done_current(); // p_offscreen_context_->doneCurrent();

In function create_frame_buffer_object():

make_current();
if (p_frame_buffer_object_) { p_frame_buffer_object_->release(); }
QOpenGLFramebufferObjectFormat format;
format.setSamples(0);
p_frame_buffer_object_ =
    std::make_shared<QOpenGLFramebufferObject>(width_, height_, format); // width_ and height_ represent the size of buffer
if (!p_frame_buffer_object_->isValid()) {
  std::cerr << "Failed to create Frame Buffer Object!!" << std::endl;
  return;
}
p_frame_buffer_object_->bind();
p_functions_->glClear(
    GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
p_frame_buffer_object_->release();
done_current();

Do the rendering:

std::lock_guard<std::mutex> lock_guard(mutex_);
make_current();
if (!initialized_.exchange(true)) { initiate_opengl(); } // do some initilization in the renderer part, see below
p_frame_buffer_object_->bind();
paint_opengl(); // do the rendering in the renderer part
texture_unit_ = p_frame_buffer_object_->texture(); // record the texture unit used in the FBO
p_frame_buffer_object_->release();
done_current();

The onscreen part:

This part simply involves the initialization and rendering of the renderer. Nothing else.

The renderer part (used by both onscreen and offscreen parts):

Initialization:

// creations of vertex array object, vertex index buffer and other resources are omitted

// creation of the QOpenGLTexture (might be wrong, but don't know how to fix)
p_texture_ = std::make_shared<QOpenGLTexture>(image.mirrored()); // image is a QImage which has the same width and height as FBO

Do the rendering:

// Render image via shader
p_program_->bind(); // shaders have been successfully compiled
{
    p_vertex_array_object_->bind();
    bind_texture(); // for offscreen part: p_texture_->bind();
                    // for onscreen part: p_texture_->bind(unit_);
                    // unit_ is the value of texture_unit_ from offscreen part
    ::glDrawElements(GL_TRIANGLE_FAN,
                     static_cast<GLsizei>(vertex_indices_.size()),
                     GL_UNSIGNED_SHORT,
                     static_cast<void *>(0)); // actually draw a quad 
    release_texture(); // for offscreen part: p_texture_->release();
                       // for onscreen part: p_texture_->release(unit_);
    p_vertex_array_object_->release();
}
p_program_->release();

I do not quite familiar with the mechanism of QOpenGLTexture and QOpenGLFramebufferObject, so anyone fixing my error and showing me the mechanism will be much appreciated.


回答1:


Textures themselves are just hunks of memory, a buffer. You can read and write to/from this memory as you wish. Most often, textures are being read from by pixel shader. That's what you described as rendering from a texture.

Rendering to a texture is a lot more interesting. The idea there is to create a texture that is dynamic: it's changing over time in a way you specify. So first, you do an initial render pass for each color in the frame buffer object, then you use an additional render pass to use the result of the first pass as the texture. This is rendering to a texture. This technique opens up a whole new world of interesting, dynamic effects.

For a simple example of this effect, the render-to-tex example from Chapter 4 of David Wolf's OpenGL Shading Language Cookbook is very good. I've pasted the image result of this example below. You can find this example's source code on Wolf's github repo for the book's examples.

The teapot is rendered to the FBO in the first pass, then applied to the cube in the second pass.

Sorry this isn't specific to QT, but from what I read it looks like the terminology between the two for this example seems very similar. I can't diagnose any specific issues you're having with that, but hopefully I helped give a good example of rendering to/from a texture.



来源:https://stackoverflow.com/questions/39295154/render-to-and-with-texture-using-qopengltexture-and-qopenglframebufferobject

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!