根据Qt5中QOpenGLTexture
的文档,可以渲染 WITH 纹理,还可以渲染 TO 纹理。有关这两种用法的简单例子吗?
这种用法的情景可以在this link找到。有关这方面的问题代码如下:
屏幕外渲染的初始化:
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();
这部分只涉及渲染器的初始化和渲染。没别了。
初始化:
// 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();
我对QOpenGLTexture
和QOpenGLFramebufferObject
的机制不是很熟悉,所以任何修复错误并向我展示机制的人都会非常感激。
答案 0 :(得分:1)
纹理本身只是一堆记忆,一种缓冲。您可以根据需要读取和写入此内存。通常,像素着色器正在读取纹理。这就是你所描述的从>>纹理中渲染。
渲染到纹理更有趣。我们的想法是创建一个动态的纹理:它以您指定的方式随时间变化。首先,为帧缓冲区对象中的每种颜色执行初始渲染过程,然后使用其他渲染过程将第一遍的结果用作纹理。这会将渲染为纹理。这种技术开辟了一个有趣,动态效果的全新世界。
对于这种效果的简单示例,David Wolf的OpenGL着色语言手册第4章中的render-to-tex示例非常好。我已经粘贴了下面这个例子的图像结果。您可以在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.
对不起,这不是QT特有的,但从我看来,看起来这两个例子之间的术语看起来非常相似。我无法诊断您遇到的任何具体问题,但希望我帮助提供了一个很好的渲染纹理的例子。