2
votes

I'll dump all the information. I am using c++. No matter what I try, glClear() works and rendering a mesh doesn't. There are no errors.

I have switched from freeglut to glfw. I had no problems before. I have the glfw3 dll and lib and the same for glew. I also have the OpenGL32 lib linked because of unresolved externals.

I am using Visual Studio 2017 and the libraries are up to date with the latest.

I got glfw from main glfw site and downloaded the 64 bit binaries. I got glew 32 and 64 bit binaries from http://glew.sourceforge.net/. I compile as 64 bit and run it on windows 10 64 bit.

It currently compiles and runs without code errors.

EDIT: I have taken some advice but still see no quad. Thanks for the input.

The new code:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
#include <fstream>
#include <string>
#include <iostream>
#include <vector>

GLFWwindow * window;
int width;
int height;

unsigned int vertex_array_buffer;
unsigned int vertex_buffer;
unsigned int index_buffer;

float vertex_model[24] = {
    -0.5f, -0.5f, 0.0f,
    0.0f, 0.0f, 1.0f,

    -0.5f, 0.5f, 0.0f,
    0.0f, 1.0f, 1.0f,

    0.5f, 0.5f, 0.0f,
    1.0f, 1.0f, 1.0f,

    0.5f, -0.5f, 0.0f,
    1.0f, 0.0f, 1.0f
};

unsigned int index_model[6] = {
    0, 1, 2,
    0, 2, 3
};

unsigned int program;

float ratio;

int main() {
    if (!glfwInit()) {
        exit(-1);
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    window = glfwCreateWindow(640, 480, "RenderEngine v0.0.0", NULL, NULL);
    if (!window)
    {
        exit(-1);
    }

    glfwMakeContextCurrent(window);

    if (glewInit()) {
        exit(-1);
    }

    glfwSwapInterval(1);

    unsigned int vert_shader;
    unsigned int frag_shader;

    const char * vert_shader_text;
    const char * frag_shader_text;

    std::ifstream file;
    std::string buffer;
    size_t f_size;

    file.open("shader.vert", std::ifstream::in | std::ifstream::binary);

    file.seekg(0, std::ios::end);
    f_size = file.tellg();
    buffer.resize(f_size);
    file.seekg(0);
    file.read(&buffer[0], f_size);
    file.close();

    vert_shader_text = buffer.c_str();

    buffer.clear();

    file.open("shader.frag", std::ifstream::in | std::ifstream::binary);

    file.seekg(0, std::ios::end);
    f_size = file.tellg();
    buffer.resize(f_size);
    file.seekg(0);
    file.read(&buffer[0], f_size);
    file.close();

    frag_shader_text = buffer.c_str();

    vert_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vert_shader, 1, &vert_shader_text, NULL);
    glCompileShader(vert_shader);

    int result = GL_FALSE;
    int log_length;

    glGetShaderiv(vert_shader, GL_COMPILE_STATUS, &result);
    glGetShaderiv(vert_shader, GL_INFO_LOG_LENGTH, &log_length);
    std::vector<char> vert_shader_error((log_length > 1) ? log_length : 1);
    glGetShaderInfoLog(vert_shader, log_length, NULL, &vert_shader_error[0]);
    std::cout << &vert_shader_error[0] << '\n';

    result = GL_FALSE;

    frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(frag_shader, 1, &frag_shader_text, NULL);
    glCompileShader(frag_shader);

    glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &result);
    glGetShaderiv(frag_shader, GL_INFO_LOG_LENGTH, &log_length);
    std::vector<char> frag_shader_error((log_length > 1) ? log_length : 1);
    glGetShaderInfoLog(frag_shader, log_length, NULL, &frag_shader_error[0]);
    std::cout << &frag_shader_error[0] << '\n';

    program = glCreateProgram();
    glAttachShader(program, vert_shader);
    glAttachShader(program, frag_shader);

    glBindAttribLocation(program, 0, "pos");
    glBindAttribLocation(program, 1, "color");

    glLinkProgram(program);

    glDeleteShader(vert_shader);
    glDeleteShader(frag_shader);

    glGetProgramiv(program, GL_LINK_STATUS, &result);
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
    std::vector<char> program_error((log_length > 1) ? log_length : 1);
    glGetProgramInfoLog(program, log_length, NULL, &program_error[0]);
    std::cout << &program_error[0] << '\n';

    glUseProgram(program);

    glGenVertexArrays(1, &vertex_array_buffer);
    glBindVertexArray(vertex_array_buffer);
    glGenBuffers(1, &vertex_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_model), vertex_model, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));
    glGenBuffers(1, &index_buffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index_model), index_model, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    if (glGetError()) {
        exit(-1);
    }

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    while (!glfwWindowShouldClose(window))
    {
        glfwGetFramebufferSize(window, &width, &height);
        ratio = width / (float)height;

        glViewport(0, 0, width, height);
        glClear(GL_COLOR_BUFFER_BIT);

        glBindVertexArray(vertex_array_buffer);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);

        glBindVertexArray(0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;
}

Also the shader files if you need them. The vertex shader:

#version 330

in layout(location = 0) vec3 pos;
in layout(location = 1) vec3 color;

out vec3 out_color;

void main() {
    gl_Position = vec4(pos, 1.0f);
    out_color = color;
}

The fragment shader:

#version 330

in vec3 out_color;

out vec4 final_color;

void main() {
    final_color = vec4(out_color, 1.0f);
}
3
I don't see any error checking in your code (like glGetError, GL_COMPILE_STATUS, GL_LINK_STATUS, ...) so how do you know that there are no errors? I can't verify it right now but imho GL_QUADS is not a valid mode for glDrawElements or was at least removed at around 3.2t.niese
I have changed to GL_TRIANGLES but haven't had good luck.Joe Cool
I don't see that you added any error checking to determine where the error occurs.t.niese
I have now but its already answered bellow.Joe Cool
@JoeCool: If you want to show the answer you used, you post an answer. You don't put the answer in your question.Nicol Bolas

3 Answers

2
votes

A few issues:

  • Even Intel supports OpenGL 3.3 Core contexts nowadays. Request one:

    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
  • Verify your shaders actually compile/link. On my system the vertex shader failed with:

    Vertex shader failed to compile with the following errors:
    ERROR: 0:3: error(#12) Unexpected qualifier
    ERROR: 0:4: error(#12) Unexpected qualifier
    ERROR: error(#273) 2 compilation errors.  No code generated
    

    layout() should be placed before in:

    layout(location = 0) in vec3 pos;
    layout(location = 1) in vec3 color;
    
  • Unbind your GL_ELEMENT_ARRAY_BUFFER after you unbind the VAO.

  • index_model is indexing right off the end of vertex_model. Don't do that unless you like access violations way down in the innards of your OpenGL driver :)

Screenshot:

screenshot

All together:

#include <GL/glew.h>
#include <glfw/glfw3.h>
#include <iostream>
#include <cstdarg>

struct Program
{
    static GLuint Load( const char* shader, ... )
    {
        GLuint prog = glCreateProgram();
        va_list args;
        va_start( args, shader );
        while( shader )
        {
            const GLenum type = va_arg( args, GLenum );
            AttachShader( prog, type, shader );
            shader = va_arg( args, const char* );
        }
        va_end( args );
        glLinkProgram( prog );
        CheckStatus( prog );
        return prog;
    }

private:
    static void CheckStatus( GLuint obj )
    {
        GLint status = GL_FALSE;
        if( glIsShader( obj ) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
        if( glIsProgram( obj ) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
        if( status == GL_TRUE ) return;
        GLchar log[ 1 << 15 ] = { 0 };
        if( glIsShader( obj ) ) glGetShaderInfoLog( obj, sizeof( log ), NULL, log );
        if( glIsProgram( obj ) ) glGetProgramInfoLog( obj, sizeof( log ), NULL, log );
        std::cerr << log << std::endl;
        std::exit( EXIT_FAILURE );
    }

    static void AttachShader( GLuint program, GLenum type, const char* src )
    {
        GLuint shader = glCreateShader( type );
        glShaderSource( shader, 1, &src, NULL );
        glCompileShader( shader );
        CheckStatus( shader );
        glAttachShader( program, shader );
        glDeleteShader( shader );
    }
};

const char* vert = 1 + R"GLSL(
#version 330 core

layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 color;

out vec3 out_color;

void main() {
    gl_Position = vec4(pos, 1.0f);
    out_color = color;
}
)GLSL";

const char* frag = 1 + R"GLSL(
#version 330 core

in vec3 out_color;

out vec4 final_color;

void main() {
    final_color = vec4(out_color, 1.0f);
}
)GLSL";

GLFWwindow * window;
int width;
int height;

unsigned int vertex_array_buffer;
unsigned int vertex_buffer;
unsigned int index_buffer;

float vertex_model[] =
{
    -0.5f, -0.5f, 0.0f,     0.0f, 0.0f, 1.0f,
    -0.5f,  0.5f, 0.0f,     0.0f, 1.0f, 1.0f,
     0.5f,  0.5f, 0.0f,     1.0f, 1.0f, 1.0f,
     0.5f, -0.5f, 0.0f,     1.0f, 0.0f, 1.0f,
};

unsigned int index_model[] =
{
    0, 1, 2,
};

unsigned int program;

float ratio;

int main()
{
    if( !glfwInit() )
    {
        exit( -1 );
    }

    glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
    glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
    glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
    window = glfwCreateWindow( 640, 480, "RenderEngine v0.0.0", NULL, NULL );
    if( !window )
    {
        exit( -1 );
    }

    glfwMakeContextCurrent( window );

    if( glewInit() )
    {
        exit( -1 );
    }

    glfwSwapInterval( 1 );

    GLuint program = Program::Load( vert, GL_VERTEX_SHADER, frag, GL_FRAGMENT_SHADER, NULL );
    glUseProgram( program );

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

    glGenBuffers( 1, &vertex_buffer );
    glBindBuffer( GL_ARRAY_BUFFER, vertex_buffer );
    glBufferData( GL_ARRAY_BUFFER, sizeof( vertex_model ), vertex_model, GL_STATIC_DRAW );
    glEnableVertexAttribArray( 0 );
    glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, (void*)0 );
    glEnableVertexAttribArray( 1 );
    glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, (void*)( sizeof( float ) * 3 ) );
    glBindBuffer( GL_ARRAY_BUFFER, 0 );

    glGenBuffers( 1, &index_buffer );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index_buffer );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( index_model ), index_model, GL_STATIC_DRAW );

    glBindVertexArray( 0 );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );

    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );

    while( !glfwWindowShouldClose( window ) )
    {
        glfwGetFramebufferSize( window, &width, &height );
        ratio = width / (float)height;

        glViewport( 0, 0, width, height );
        glClear( GL_COLOR_BUFFER_BIT );

        glBindVertexArray( vertex_array_buffer );
        glDrawElements( GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr );
        glBindVertexArray( 0 );

        glfwSwapBuffers( window );
        glfwPollEvents();
    }

    glfwDestroyWindow( window );
    glfwTerminate();

    return 0;
}
1
votes

glVertexAttribPointer takes passed arguments and currently bound VBO and saves that information inside the state of currently bound VAO.

glEnableVertexAttribArray enables an attribute also just in currently bound VAO. You enable them too early.

So, the correct order of doing things is:

  1. Bind VAO
  2. Bind VBO
  3. Call glVertexAttribPointer and glEnableVertexAttribArray
  4. Now you can unbind the VBO or repeat 2-3 because 3. saved the state into VAO.
  5. Unbind VAO

Index buffer should be placed anywhere between 1-5. Just take care to not accidentally unbind the index buffer too early - while VAO is still bound. Because VAO only remembers one index buffer.

Other than those early calls, I did not find any more mistakes.

This "hidden" capture of VBO has been "revealed" in OpenGL 4.5 by splitting the functionality of glVertexAttribPointer into glVertexArrayAttribBinding, glVertexArrayAttribFormat and glBindVertexBuffer.

1
votes

The named index buffer object is a state of the vertex array objects state vector. If you do glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0), when the vertex array object is bound, then the reference to the element buffer is broken.

Delete glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);, to solve the issue:

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

// [...]

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);

// [...]

//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // <---- skip this
glBindVertexArray(0);

In the array of vertices there are 4 coordinates and color attributes, so the indices have to be in the range [0, 3]. The coordinates are arranged in a quad and a quad can be drawn by 2 triangles as follows:

1         2
 +-------+
 |     / |
 |   /   |
 | /     |
 +-------+
0         3
unsigned int index_model[6] = {
    0, 1, 2,
    0, 2, 3
};