使用QOpenGLTexture和QOpenGLFramebufferObject渲染到和WITH纹理 [英] Render TO and WITH texture using QOpenGLTexture and QOpenGLFramebufferObject

查看:1663
本文介绍了使用QOpenGLTexture和QOpenGLFramebufferObject渲染到和WITH纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据Qt5中的QOpenGLTexture文档,可以渲染 WITH 纹理,也可以渲染 TO 纹理.关于这两种用法,是否有任何简单的示例? 可以在

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:

屏幕外渲染的初始化:

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();

在功能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();

进行渲染:

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.

初始化:

// 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

进行渲染:

// 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();

我对QOpenGLTextureQOpenGLFramebufferObject的机制不太熟悉,因此任何修复我的错误并向我展示该机制的人都将不胜感激.

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.

推荐答案

纹理本身就是大量的内存,一个缓冲区.您可以根据需要在该内存中读写.大多数情况下,像素着色器从中读取纹理.这就是您描述为从纹理 渲染

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.

对于这种效果的简单示例,David Wolf的OpenGL着色语言食谱第4章中的render-to-tex示例非常好.我在下面粘贴了此示例的图像结果.您可以在 Wolf的github存储库中找到该示例的源代码.

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.

此茶壶在第一遍渲染到FBO,然后在第二遍渲染到多维数据集通过.

抱歉,这不是QT特有的,但从我的阅读看来,本例中两者之间的术语看起来非常相似.我无法诊断出与此有关的任何特定问题,但希望我能提供一个很好的示例,以从纹理渲染/从纹理渲染.

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.

这篇关于使用QOpenGLTexture和QOpenGLFramebufferObject渲染到和WITH纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆