3
votes

I'm using freeglut. I've successfully rendered a triangle in single VBO using a shader program before.

The shader program compilation, linking and verification throws no errors. I believe the problem lies in the way I store and call VBOs (2 of them), because before I worked with 1 VBO only.

EDIT: deleted all unnecessary code

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <string.h>
#include <stdio.h>

#define countof(x) sizeof(x) / sizeof(x[0])

#define NUM_BUFFERS 2
#define INFOLOG_SIZE 1024

GLuint VBO_ids[NUM_BUFFERS];
GLfloat VBO0[] = {-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f};
GLfloat VBO1[] = {-1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,-1.0f, 0.0f};
GLfloat *VBOs[NUM_BUFFERS] = { VBO0, VBO1 };
GLuint shader_prog_id;

const GLchar *vert_src =
"#version 330\n"
"layout (location = 0) in vec3 Pos;\n"
"void main() {\n"
"   gl_Position = vec4(Pos.x, Pos.y, Pos.z, 1.0); }\n";

const GLchar *frag_src =
"#version 330\n"
"out vec4 FragColor;\n"
"void main() {\n"
"   FragColor = vec4(1.0, 1.0, 1.0, 1.0); }\n";

void vbo_init(void) {
    glGenBuffers(NUM_BUFFERS, VBO_ids);
    glBindBuffer(GL_ARRAY_BUFFER, VBO_ids[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VBO0), VBOs[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, VBO_ids[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VBO1), VBOs[1], GL_STATIC_DRAW); }

int shader_init(const GLchar **v_src, const GLchar **f_src, GLint *v_size, GLint *f_size) {
    GLint success;
    shader_prog_id = glCreateProgram();
    GLuint v_shader = glCreateShader(GL_VERTEX_SHADER);
    GLuint f_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(v_shader, 1, v_src, v_size);
    glShaderSource(f_shader, 1, f_src, f_size);
    glCompileShader(v_shader);
    glCompileShader(f_shader);
    glAttachShader(shader_prog_id, v_shader);
    glAttachShader(shader_prog_id, f_shader);
    glLinkProgram(shader_prog_id);
    glValidateProgram(shader_prog_id);
    return 1; }

int draw_initialize(void) {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    vbo_init();
    GLint vsrcsize = strlen(vert_src);
    GLint fsrcsize = strlen(frag_src);
    shader_init(&vert_src, &frag_src, &vsrcsize, &fsrcsize);
    return 1; }

void draw_callback(void) {
    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(shader_prog_id);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, VBO_ids[0]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glDrawArrays(GL_TRIANGLES, 0, countof(VBO0)/3);
    puts((char*)gluErrorString(glGetError()));
    glBindBuffer(GL_ARRAY_BUFFER, VBO_ids[1]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glDrawArrays(GL_TRIANGLES, 0, countof(VBO1)/3);

    glDisableVertexAttribArray(0);
    glutSwapBuffers(); }

int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
    glutInitContextProfile(GLUT_CORE_PROFILE);
    glutInitContextVersion(3, 3);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize(600, 600);
    glutCreateWindow("title");

    glewInit();
    draw_initialize();

    glutIdleFunc(draw_callback);
    glutMainLoop();
    return 0; }
1
If anyone would like to try to reproduce the bug the linker flags are -lglut -lGLEWuser2933244

1 Answers

1
votes

You need to supply a Vertex Array Object (VAO) in a Core context:

int draw_initialize(void)
{
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    vbo_init();
    GLint vsrcsize = strlen(vert_src);
    GLint fsrcsize = strlen(frag_src);
    shader_init(&vert_src, &frag_src, &vsrcsize, &fsrcsize);

    GLuint vao = 0;
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );

    return 1;
}

They encapsulate vertex attrib enable (glEnableVertexAttribArray()) and pointer (glVertexAttribPointer()) state.

Also:

  • glewExperimental = GL_TRUE before glewInit()
  • Set an actual glutDisplayFunc() instead of hoping GLUT will figure out what you meant by only registering an idle callback