【发布时间】:2019-12-08 10:00:50
【问题描述】:
虽然 OpenGL 的作用很简单,但我仍然感到困惑,但我开始了解它是如何工作的。
我正在寻找一个最小的离屏渲染示例来帮助我入门。
我的应用程序将获取一堆三角形以及有关如何相对于相机定位它们并将渲染结果保存到图像文件的信息。暂时没有灯光、材质或后期处理。
我观看了有关创建屏幕外上下文、创建 FBO、渲染到纹理等的教程。我不介意使用 QT,因为它方便地提供了 OpenGL 工具、窗口和 QImage。据我了解,为了能够对渲染图像进行图像处理,您需要将渲染目标设置为纹理,然后使用着色器,最后将纹理读取到数组中。
试图把事情放在一起从来没有让我找到一个好的起点。我要么被设置依赖项卡住,出现黑屏,要么盯着那些除了我需要的东西做太多事情的项目。
更新 1: 搞定了。
#include <QtGui/QGuiApplication>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QOffscreenSurface>
#include <QtGui/QOpenGLFunctions_4_3_Core>
#include <QtGui/QOpenGLFramebufferObject>
#include <QtGui/QOpenGLShaderProgram>
#include <QDebug>
#include <QImage>
#include <QOpenGLBuffer>
int main(int argc, char* argv[])
{
QGuiApplication a(argc, argv);
QSurfaceFormat surfaceFormat;
surfaceFormat.setMajorVersion(4);
surfaceFormat.setMinorVersion(3);
QOpenGLContext openGLContext;
openGLContext.setFormat(surfaceFormat);
openGLContext.create();
if(!openGLContext.isValid()) return -1;
QOffscreenSurface surface;
surface.setFormat(surfaceFormat);
surface.create();
if(!surface.isValid()) return -2;
openGLContext.makeCurrent(&surface);
QOpenGLFunctions_4_3_Core f;
if(!f.initializeOpenGLFunctions()) return -3;
qDebug() << QString::fromLatin1((const char*)f.glGetString(GL_VERSION));
QSize vpSize = QSize(100, 200);
qDebug("Hi");
QOpenGLFramebufferObjectFormat fboFormat;
fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
QOpenGLFramebufferObject fbo(vpSize, fboFormat);
fbo.bind();
// //////////
static const float vertexPositions[] = {
-0.8f, -0.8f, 0.0f,
0.8f, -0.8f, 0.0f,
0.0f, 0.8f, 0.0f
};
static const float vertexColors[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
QOpenGLBuffer vertexPositionBuffer(QOpenGLBuffer::VertexBuffer);
vertexPositionBuffer.create();
vertexPositionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
vertexPositionBuffer.bind();
vertexPositionBuffer.allocate(vertexPositions, 9 * sizeof(float));
QOpenGLBuffer vertexColorBuffer(QOpenGLBuffer::VertexBuffer);
vertexColorBuffer.create();
vertexColorBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
vertexColorBuffer.bind();
vertexColorBuffer.allocate(vertexColors, 9 * sizeof(float));
QOpenGLShaderProgram program;
program.addShaderFromSourceCode(QOpenGLShader::Vertex,
"#version 330\n"
"in vec3 position;\n"
"in vec3 color;\n"
"out vec3 fragColor;\n"
"void main() {\n"
" fragColor = color;\n"
" gl_Position = vec4(position, 1.0);\n"
"}\n"
);
program.addShaderFromSourceCode(QOpenGLShader::Fragment,
"#version 330\n"
"in vec3 fragColor;\n"
"out vec4 color;\n"
"void main() {\n"
" color = vec4(fragColor, 1.0);\n"
"}\n"
);
program.link();
program.bind();
vertexPositionBuffer.bind();
program.enableAttributeArray("position");
program.setAttributeBuffer("position", GL_FLOAT, 0, 3);
vertexColorBuffer.bind();
program.enableAttributeArray("color");
program.setAttributeBuffer("color", GL_FLOAT, 0, 3);
f.glClearColor(0.3f, 0.0f, 0.7f, 1.0f);
f.glClear(GL_COLOR_BUFFER_BIT);
f.glDrawArrays(GL_TRIANGLES, 0, 3);
program.disableAttributeArray("position");
program.disableAttributeArray("color");
program.release();
// ///////////////
fbo.release();
qDebug("FBO released");
QImage im = fbo.toImage();
if (im.save("asd.png")){
qDebug("Image saved!!");
}
return 0;
}
保存的图片和FBO一样大小,颜色对应glClearColor中设置的那个,但是三角形没有渲染。我错过了什么?
【问题讨论】:
-
请参阅OpenGL Scale Single Pixel Line 它可以满足您 90% 的需求。但是它在屏幕上下文中使用...(在交换缓冲区之前您看不到渲染,因此不需要屏幕外的东西...)...它使用旧的 api 作为新的(渲染到纹理)不是由于驱动程序错误,在某些 Intel gfx 卡上可靠...
glReadPixels只需从那里将屏幕内容读入 CPU 端内存,您需要将其编码为图像...对于新 api,您可以加载纹理类似于它的方式存储... -
另请参阅simple complete GL+VAO/VBO+GLSL+shaders example in C++,以防您需要开始使用 GL 上下文和东西(新旧 api)
-
感谢您的回复。硬件兼容性不是问题。渲染到纹理的例子真的很有帮助。
-
那将是FBO and render to texture,但这是很多代码,在
glReadPixels上没有任何速度奖励,因为无论如何您都需要将图像复制回 CPU 端... -
我需要在 GPU 上进行图像处理。
标签: c++ qt opengl fbo render-to-texture