c++ - Shape not being drawn in OpenGL when unbinding vertex array -
i'm learning opengl , set mesh class render shapes. drawing works without
glbindvertexarray(0);
at end i'm guessing messed can't figure out.
here code: main.cpp
#include <gl/glew.h> #include <sdl2/sdl.h> #include <iostream> #include "mesh.h" #define width 1280 #define height 720 // vertex shader const char* vs = "\n\ #version 330 \n\ layout (location = 0) in vec2 position; \n\ layout (location = 1) in vec3 color; \n\ out vec3 color; \n\ \n\ void main() { \n\ color = color; \n\ gl_position = vec4(position, 0.0, 1.0); \n\ } \n\ \n\ "; // fragment shader const char* fs = "\n\ #version 330 \n\ in vec3 color; \n\ out vec4 fragcolor; \n\ \n\ void main() { \n\ fragcolor = vec4(color, 1.0); \n\ } \n\ "; bool checkshader(gluint shader) { glint status; glgetshaderiv(shader, gl_compile_status, &status); if (status != gl_true) { char buffer[512]; glgetshaderinfolog(shader, 512, null, buffer); std::cout << "error compiling shader:" << buffer << std::endl; return false; } return true; } bool compileshaders() { // compile vertex shader gluint vertexshader = glcreateshader(gl_vertex_shader); glshadersource(vertexshader, 1, &vs, null); glcompileshader(vertexshader); if (!checkshader(vertexshader)) return false; // compile fragment shader gluint fragmentshader = glcreateshader(gl_fragment_shader); glshadersource(fragmentshader, 1, &fs, null); glcompileshader(fragmentshader); if (!checkshader(fragmentshader)) return false; gluint shaderprogram = glcreateprogram(); glattachshader(shaderprogram, vertexshader); glattachshader(shaderprogram, fragmentshader); glbindfragdatalocation(shaderprogram, 0, "outcolor"); gllinkprogram(shaderprogram); gluseprogram(shaderprogram); return true; } int main() { bool success = true; bool running = true; sdl_window* window; sdl_glcontext context; // initialize sdl/glew if (sdl_init(sdl_init_video) < 0) { std::cerr << "video initialization failed:" << sdl_geterror() << std::endl; success = false; } sdl_gl_setattribute(sdl_gl_context_major_version, 3); sdl_gl_setattribute(sdl_gl_context_minor_version, 3); sdl_gl_setattribute(sdl_gl_doublebuffer, 1); sdl_gl_setattribute(sdl_gl_depth_size, 24); window = sdl_createwindow("game title", sdl_windowpos_centered, sdl_windowpos_centered, width, height, sdl_window_shown | sdl_window_opengl | sdl_window_borderless); context = sdl_gl_createcontext(window); glewexperimental = gl_true; if (glewinit() != glew_ok) { std::cerr << "problem initializing glew." << std::endl; success = false; } sdl_event e; // mesh setup float vertices[] = { 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.5f,-0.5f, 0.0f, 1.0f, 0.0f, -0.5f,-0.5f, 0.0f, 0.0f, 1.0f }; float vertices2[] = { -1.0f,-1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, -0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; gluint elements[] = { 0, 1, 2 }; mesh triangle(vertices, elements, sizeof(vertices), sizeof(elements)); mesh triangle2(vertices2, elements, sizeof(vertices2), sizeof(elements)); if (!compileshaders()) success = false; if (!success) { std::cerr << "a problem ocurred during initialization, exit." << std::endl; exit(1); } while (running) { while (sdl_pollevent(&e)) { if (e.type == sdl_quit) running = false; if (e.type == sdl_keydown) if (e.key.keysym.sym == sdlk_escape) running = false; } glclearcolor(0.0f, 1.0f, 0.5f, 0.0f); glclear(gl_color_buffer_bit); triangle.draw(); triangle2.draw(); sdl_gl_swapwindow(window); sdl_delay(1); } sdl_gl_deletecontext(context); sdl_quit(); return 0; }
mesh.h
#ifndef mesh_h #define mesh_h #include <gl/glew.h> class mesh { private: gluint ibo; gluint vbo; gluint vao; float* vertices; gluint* indices; int sizevertices; int sizeindices; public: mesh(float* vertices, gluint* indices, int sizevertices, int sizeindices); void draw(); }; #endif //mesh_h
mesh.cpp
#include "mesh.h" #define position 0 #define color 1 mesh::mesh(float* vertices, gluint* indices, int sizevertices, int sizeindices) { this->vertices = vertices; this->indices = indices; this->sizevertices = sizevertices; this->sizeindices = sizeindices; glgenvertexarrays(1, &vao); glgenbuffers(1, &vbo); glgenbuffers(1, &ibo); } void mesh::draw() { glenablevertexattribarray(position); glvertexattribpointer(position, 2, gl_float, gl_false,5*sizeof(float), 0); glenablevertexattribarray(color); glvertexattribpointer(color, 3, gl_float, gl_false, 5*sizeof(float), (void*)(2*sizeof(float))); glbindvertexarray(vao); glbindbuffer(gl_array_buffer, vbo); glbufferdata(gl_array_buffer, sizevertices, vertices, gl_static_draw); glbindbuffer(gl_element_array_buffer, ibo); glbufferdata(gl_element_array_buffer, sizeindices, indices, gl_static_draw); gldrawelements(gl_triangles, 3, gl_unsigned_int, 0); //glbindvertexarray(0); if uncomment this, mesh not displayed }
the calls glvertexattribpointer pointer refer vao , vbo bound @ time of calling. in code you're calling glvertexattribpointer before vao , vbo bound. first iteration round calls fail. without unbinding vao/vbo next iteration vao/vbo state happen (by circumstance) more or less right; you've swapped vao/vbo between 2 triangle instances.
update – fixed code
mesh::mesh(float* vertices, gluint* indices, int sizevertices, int sizeindices) { this->vertices = vertices; this->indices = indices; this->sizevertices = sizevertices; this->sizeindices = sizeindices; glgenvertexarrays(1, &vao); glgenbuffers(1, &vbo); glgenbuffers(1, &ibo); /* vaos contain array_buffers */ glbindvertexarray(vao); glbindbuffer(gl_array_buffer, vbo); glbufferdata(gl_array_buffer, sizevertices, vertices, gl_static_draw); glenablevertexattribarray(position); glvertexattribpointer(position, 2, gl_float, gl_false,5*sizeof(float), 0); glenablevertexattribarray(color); glvertexattribpointer(color, 3, gl_float, gl_false, 5*sizeof(float), (void*)(2*sizeof(float))); glbindbuffer(gl_array_buffer, 0); glbindvertexarray(vao); /* element_array_buffers not contained in vaos */ glbindbuffer(gl_element_array_buffer, ibo); glbufferdata(gl_element_array_buffer, sizeindices, indices, gl_static_draw); glbindbuffer(gl_element_array_buffer, 0); } void mesh::draw() { /* vaos keep glvertexattribpointer bindings, * it's sufficient bind vao; * no need binding vbos (as long don't want change pointers). */ glbindvertexarray(vao); glbindbuffer(gl_element_array_buffer, ibo); /* need bind element_array_buffer though */ gldrawelements(gl_triangles, 3, gl_unsigned_int, 0); glbindbuffer(gl_element_array_buffer, 0); glbindvertexarray(0); }
Comments
Post a Comment