具有自定义帧缓冲区和多个渲染目标的 QOpenGLWidget
QOpenGLWidget with custom framebuffer and multiple render targets
与 相关,我正在尝试渲染分割蒙版以启用对象拾取。但是我无法达到预期的效果。
选项 1 根本不起作用。我无法检索颜色附件 1 的内容,也无法检查它是否存在(我仅使用本机 OpenGL 调用创建了附件)。
使用 this post,我能够通过创建带有第二个颜色附件的自定义帧缓冲区来重现 green.png
和 red.png
图像,然后将其绑定并吸引到(全部在 paintGL()
中)。
不知何故我不得不使用这个人的帧缓冲区创建代码,因为当我自己创建帧缓冲区时总是有一个警告说 toImage called for missing color attachment
,尽管我附上了颜色附件并且 textures()
调用了帧缓冲区返回了两个对象。然后我尝试在
之后插入我的渲染代码
GLfloat red[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
f->glClearBufferfv(GL_COLOR, 0, red);
GLfloat green[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
f->glClearBufferfv(GL_COLOR, 1, green);
但这仍然导致了红色和绿色图像。但是当使用正常的默认帧缓冲区时,代码可以很好地渲染。我将着色器调整为(用于测试目的的简短版本):
void main() {
gl_FragData[0] = vec4(1.0, 1.0, 1.0, 1.0);
gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);
}
由于我能够生成红色和绿色图像,我假设一定有一种方法可以使用此自定义帧缓冲区检索片段数据。我现在拥有的解决方案是程序的完整(!)副本和另一个专用片段着色器,其唯一目的是渲染分段,并再次执行所有 OpenGL 绘制调用。正如您所猜到的,这是一个有点丑陋的解决方案,虽然场景不是那么大而且我的电脑能够轻松处理。有人拿到 idea/link 了吗?
如果要在 Fragment shader, then you have to declare multiple output 个变量中写入多个渲染目标:
#version 330
layout(location = 0) out vec4 fragData0;
layout(location = 1) out vec4 fragData1;
void main()
{
fragData0 = vec4(1.0, 1.0, 1.0, 1.0);
fragData1 = vec4(0.0, 0.0, 0.0, 1.0);
}
从 GLSL 1.1 版(#version 110
、OpenGL 2.0)到 GLSL 1.5 版(#version 150
、OpenGL 3.2),同样可以通过写入内置片段着色器输出变量 gl_FragData
.
void main()
{
gl_FragData[0] = vec4(1.0, 1.0, 1.0, 1.0);
gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);
}
另见 Fragment Shader Outputs - Through The Ages
要在 Qt 中使用多个渲染目标,必须将第二个颜色附件添加到帧缓冲区,并且颜色缓冲区列表必须由 glDrawBuffers
:
指定
QOpenGLShaderProgram *program;
QOpenGLFramebufferObject *fb;
int fb_width;
int fb_height,
fb = new QOpenGLFramebufferObject( fb_width, fb_height );
fb->addColorAttachment( fb_width, fb_height );
glViewport(0, 0, fb_width, fb_height);
fb->bind();
glClearColor(0, 0, 0, 1);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);
program->bind();
// ..... do the drawing
program->release();
fb->release();
可以访问附加到帧缓冲区的 OpenGL 纹理对象:
QVector<GLuint> fb_textrues = fb->textures();
与
选项 1 根本不起作用。我无法检索颜色附件 1 的内容,也无法检查它是否存在(我仅使用本机 OpenGL 调用创建了附件)。
使用 this post,我能够通过创建带有第二个颜色附件的自定义帧缓冲区来重现 green.png
和 red.png
图像,然后将其绑定并吸引到(全部在 paintGL()
中)。
不知何故我不得不使用这个人的帧缓冲区创建代码,因为当我自己创建帧缓冲区时总是有一个警告说 toImage called for missing color attachment
,尽管我附上了颜色附件并且 textures()
调用了帧缓冲区返回了两个对象。然后我尝试在
GLfloat red[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
f->glClearBufferfv(GL_COLOR, 0, red);
GLfloat green[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
f->glClearBufferfv(GL_COLOR, 1, green);
但这仍然导致了红色和绿色图像。但是当使用正常的默认帧缓冲区时,代码可以很好地渲染。我将着色器调整为(用于测试目的的简短版本):
void main() {
gl_FragData[0] = vec4(1.0, 1.0, 1.0, 1.0);
gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);
}
由于我能够生成红色和绿色图像,我假设一定有一种方法可以使用此自定义帧缓冲区检索片段数据。我现在拥有的解决方案是程序的完整(!)副本和另一个专用片段着色器,其唯一目的是渲染分段,并再次执行所有 OpenGL 绘制调用。正如您所猜到的,这是一个有点丑陋的解决方案,虽然场景不是那么大而且我的电脑能够轻松处理。有人拿到 idea/link 了吗?
如果要在 Fragment shader, then you have to declare multiple output 个变量中写入多个渲染目标:
#version 330
layout(location = 0) out vec4 fragData0;
layout(location = 1) out vec4 fragData1;
void main()
{
fragData0 = vec4(1.0, 1.0, 1.0, 1.0);
fragData1 = vec4(0.0, 0.0, 0.0, 1.0);
}
从 GLSL 1.1 版(#version 110
、OpenGL 2.0)到 GLSL 1.5 版(#version 150
、OpenGL 3.2),同样可以通过写入内置片段着色器输出变量 gl_FragData
.
void main()
{
gl_FragData[0] = vec4(1.0, 1.0, 1.0, 1.0);
gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);
}
另见 Fragment Shader Outputs - Through The Ages
要在 Qt 中使用多个渲染目标,必须将第二个颜色附件添加到帧缓冲区,并且颜色缓冲区列表必须由 glDrawBuffers
:
QOpenGLShaderProgram *program;
QOpenGLFramebufferObject *fb;
int fb_width;
int fb_height,
fb = new QOpenGLFramebufferObject( fb_width, fb_height );
fb->addColorAttachment( fb_width, fb_height );
glViewport(0, 0, fb_width, fb_height);
fb->bind();
glClearColor(0, 0, 0, 1);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);
program->bind();
// ..... do the drawing
program->release();
fb->release();
可以访问附加到帧缓冲区的 OpenGL 纹理对象:
QVector<GLuint> fb_textrues = fb->textures();