carloabelli
carloabelli

Reputation: 4349

OpenGL Does Not Render Triangle

I am following this tutorial with a few modifications and have got this code:

#define GLSL(src) "#version 330 core\n" #src

void MainWindow::initializeGL() {

    glClearColor(0, 0, 0, 1);

    // Generate buffers

    GLfloat verticies[] = {
        +0.0f, +1.0f, +0.0f,

        -1.0f, -1.0f, +0.0f,

        +1.0f, -1.0f, +0.0f,
    };

    GLuint vertexBufferID;
    glGenBuffers(1, &vertexBufferID);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verticies), verticies, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);

    // Generate shaders

    const char *vertexShaderSrc = GLSL(
        layout(location = 0) in vec3 pos;

        void main() {
            gl_Position.xyz = pos;
            gl_Position.w = 1.0;
        }
    );


    GLuint vertexShaderID = createGLShader(GL_VERTEX_SHADER, vertexShaderSrc);

    const GLchar *fragmentShaderSrc = GLSL(
        out vec4 color;

        void main() {
            color = vec4(0.0, 1.0, 0.0, 1.0);
        }
    );

    GLuint fragmentShaderID = createGLShader(GL_FRAGMENT_SHADER, fragmentShaderSrc);

    GLuint programID = glCreateProgram();
    glAttachShader(programID, vertexShaderID);
    glAttachShader(programID, fragmentShaderID);
    glLinkProgram(programID);
    glUseProgram(programID);
}

void MainWindow::paintGL() {
    //glViewport(0, 0, width(), height());
    glClear(GL_COLOR_BUFFER_BIT);

    glDrawArrays(GL_TRIANGLES, 0, 3);
    //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
}

GLuint MainWindow::createGLShader(GLenum type, const GLchar* src) {
    GLuint shaderID = glCreateShader(type);
    glShaderSource(shaderID, 1, &src, 0);
    glCompileShader(shaderID);
    GLint vertexCompileStatus;
    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &vertexCompileStatus);
    if (vertexCompileStatus != GL_TRUE) {
        GLint infoLogLength;
        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
        GLchar buffer[infoLogLength];
        glGetShaderInfoLog(shaderID, infoLogLength, 0, buffer);
        qDebug(buffer);
    }
    return shaderID;
}

This is all contained in a QGLWidget. However when I run this code I just get a black screen. What is going wrong? I don't get an error message so the shaders are compiling.

I set up the QGLWidget:

#include "mainwindow.h"
#include <QApplication>
#include <QGLFormat>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    QGLFormat glFormat;
    glFormat.setVersion(3, 3);
    glFormat.setProfile(QGLFormat::CoreProfile);

    MainWindow w(glFormat);
    w.show();

    return a.exec();
}

Upvotes: 1

Views: 922

Answers (1)

peppe
peppe

Reputation: 22734

Staying with "pure" OpenGL code, you need (at least) a Vertex Array Object. That object needs to be bound when you configure the vertex arrays, and everytime you draw from the aforementioned arrays.

So, before the calls to gl*VertexAttribArray, create and bind the VAO. Add a

GLuint m_vao;

member to your class. Then in initializeGL:

glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);

// now configure the arrays:
glEnableVertexAttribArray...
glVertexAttribArray...

// now release the VAO and move on
glBindVertexArray(0);

Then in paintGL we need the VAO again:

glBindVertexArray(m_vao);
glDrawArrays(...);
glBindVertexArray(0);

And now your code with Qt 5 OpenGL enablers (didn't try to compile it, but you can get the idea). You tell me which one is more readable and less error prone.

#define GLSL(src) "#version 330 core\n" #src

void MainWindow::initializeGL() {

    glClearColor(0, 0, 0, 1);

    // Generate buffers

    GLfloat verticies[] = {
        +0.0f, +1.0f, +0.0f,

        -1.0f, -1.0f, +0.0f,

        +1.0f, -1.0f, +0.0f,
    };

    m_vertexBuffer = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    m_vertexBuffer->create();
    m_vertexBuffer->setusagePatter(QOpenGLBuffer::StaticDraw);
    m_vertexBuffer->bind();
    m_vertexBuffer->allocate(verticies, sizeof(verticies);
    m_vertexBuffer->release();

    // Generate shaders

    const char *vertexShaderSrc = GLSL(
        layout(location = 0) in vec3 pos;

        void main() {
            gl_Position.xyz = pos;
            gl_Position.w = 1.0;
        }
    );

    const GLchar *fragmentShaderSrc = GLSL(
        out vec4 color;

        void main() {
            color = vec4(0.0, 1.0, 0.0, 1.0);
        }
    );

    m_program = new QOpenGLShaderProgram;
    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSrc);     
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSrc);
    m_program->link();
    // error checking missing from the last three calls. if they return false, check log()

    m_vao = new QOpenGLVertexArrayObject;
    m_vao->bind();
    m_program->bind();

    m_vertexBuffer->bind();
    m_program->enableAttributeArray("pos");
    m_program->setAttributeBuffer("pos", GL_FLOAT, 0, 3);
    m_vertexBuffer->release();

    m_program->release();
    m_vao->release();
}

void MainWindow::paintGL() {       
    glClear(GL_COLOR_BUFFER_BIT);

    m_vao->bind();
    m_program->bind();

    glDrawArrays(GL_TRIANGLES, 0, 3);

    m_program->release();
    m_vao->release();
}

Upvotes: 1

Related Questions