Kpure1000
Kpure1000

Reputation: 21

QOpenGLWidgets do not draw anything in application but draw normally in RenderDoc Frame Capture

I made a Qt Application to preview 3D model. I use QOpenGLWidget to draw the triangles, with the core profile OpenGL v3.3. The shader compiler does not output any errors, and application run successfully, and everything seems like work.

Here are the general steps:

auto format = QSurfaceFormat::defaultFormat();
format.setRenderableType(QSurfaceFormat::OpenGL);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setVersion(3, 3);
QSurfaceFormat::setDefaultFormat(format);
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
//////////////////
// Vertex Shader
//////////////////

#version 330 core
layout (location = 0) in vec3 aPos;

out vec3 fragPos;

void main()
{
    fragPos = aPos;
    gl_Position = vec4(aPos, 1.0);
}

////////////////////
// Fragment Shader
////////////////////

#version 330 core
in vec3 fragPos;
out vec4 fragCol;

uniform float _fov_rad;
uniform float _pitch;
uniform vec3 _sky;
uniform vec3 _ground;

void main()
{
    vec3 down   = (_pitch - _fov_rad * 0.5) * (_sky - _ground) + _ground;
    vec3 up     = (_pitch + _fov_rad * 0.5) * (_sky - _ground) + _ground;
    float pitch = (fragPos.y + 1.0) * 0.5;
    fragCol = vec4( pitch * (up - down) + down, 1.0) ;
}
///////////////////////////
//// in 'initializeGL' ////
///////////////////////////

//... some other initializations

makeCurrent();
// prepare data
QVector4 vertices = {
    {-1.f, -1.f, .0f},
    { 1.f, -1.f, .0f},
    {-1.f,  1.f, .0f},
    { 1.f,  1.f, .0f},
};
unsigned int indices[6] = {
    0, 1, 2,
    2, 1, 3
};
// creating buffers
auto vbo_v = std::make_shared<QOpenGLBuffer>(QOpenGLBuffer::Type::VertexBuffer);
if (!vbo_v->create()) {
    qDebug() << "TriangleData::TriangleData>> vbo_v create failed";
}
vbo_v->bind();
vbo_v->setUsagePattern(QOpenGLBuffer::UsagePattern::StaticDraw);
vbo_v->allocate(mesh->vertices.data(), mesh->verticesNum() * sizeof(QVector3D));

auto vbo_n = std::make_shared<QOpenGLBuffer>(QOpenGLBuffer::Type::VertexBuffer);
if (!vbo_n->create()) {
    qDebug() << "TriangleData::TriangleData>> vbo_n create failed";
}
vbo_n->bind();
vbo_n->setUsagePattern(QOpenGLBuffer::UsagePattern::StaticDraw);
vbo_n->allocate(mesh->normals.data(), mesh->verticesNum() * sizeof(QVector3D));

auto ibo = std::make_shared<QOpenGLBuffer>(QOpenGLBuffer::Type::IndexBuffer);
if (!ibo->create()) {
    qDebug() << "TriangleData::TriangleData>> ibo create failed";
}
ibo->bind();
ibo->setUsagePattern(QOpenGLBuffer::UsagePattern::StaticDraw);
ibo->allocate(mesh->indices.data(), mesh->facesNum() * 3 * sizeof(unsigned int));

... 

doneCurrent();

//////////////////////
//// in 'paintGL' ////
//////////////////////

QOpenGLFunctions f(QOpenGLContext::currentContext());
f.glClearColor(178.f/255.f, 168.f/255.f, 70.f/255.f, 1.0f);
f.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

QOpenGLShaderProgram* sprog = m_skyShader->sprog;
sprog->bind();
sprog->setUniformValue("_fov_rad", 70.f * 3.1415926f / 180.f);
sprog->setUniformValue("_sky", {.7f,.8f,.9f});
sprog->setUniformValue("_ground", {.1f,.2f,.3f});
sprog->setUniformValue("_pitch", .0f);

// binding attribute
vbo_v->bind();
sprog->enableAttributeArray(0);
sprog->setAttributeBuffer(0, GL_FLOAT, 0, 3, 0);

vbo_n->bind();
sprog->enableAttributeArray(1);
sprog->setAttributeBuffer(1, GL_FLOAT, 0, 3, 0);

ibo->bind();

// drawing
f.glDrawElements(GL_TRIANGLES, 2 * 3, GL_UNSIGNED_INT, 0);

If it worked, the result should look like this (the nice gradient background):

Expected Result

But it looks like this (only the clear color):

Actual Result

The same cpp code, and the similar shader (but in compatible profile) worked well.

For some reason it should run in core profile. Anyway, I still want to figure out why this weird problem occurred.

So I compiled RenderDoc from source to get Mac RenderDoc, and capture this application to point out the problem.

When I used RenderDoc (MAC) to launch this and capture the frames, it did render normally as below:

RenderDoc Capture

Here is the capture, saved as an .rdc file:

RDC file

Environment:

Upvotes: 1

Views: 217

Answers (1)

Kpure1000
Kpure1000

Reputation: 21

Possible Reason

In RenderDoc, I found that after all render pass, a VAO (Vertex Array Object) called defaultVAO was bound in CGLFLushDrawable().

But in my render pass, there was no VAO bound, because I follow along the old code with Compatible Profile OpenGL.

This might cause no actual buffers being flushed to draw in real application environment; but in renderDoc environment, it might be rendered by renderDoc's flushed normally.


Solution

I use QOpenGLFunctions_3_3_Core to create a vao when initialized for every render pass:

// 'RenderAPI' is my own redundant API
...
struct RenderAPI {
...
    QOpenGLFunctions_3_3_Core f_330C;
...
};
...
// in initialization QOpenGLWidget
auto &f = RenderAPI::getInstance()->f_330C;
f.glGenVertexArrays(1, &vao);

And bind the specific VAO before setting vertex attribute:

auto &f = RenderAPI::getInstance()->f_330C;
f.glBindVertexArray(vao);

enter image description here

Upvotes: 1

Related Questions