From 62e76e982b716d936b9899d10b69e5f9e9af15b6 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Mon, 27 Dec 2021 15:05:20 -0500 Subject: [PATCH] get dynamic vertex attribute parsing working --- src/main.cpp | 37 +++++++++++-------- src/shader.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++------- src/shader.h | 16 ++++---- 3 files changed, 117 insertions(+), 35 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 21a11cb..d5f1924 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -264,33 +264,36 @@ loadScene(RenderState* rs) // TODO: full lighting model model* tex_cube = getModel(rs, "../data/textured_cube.gltf"); assert(tex_cube != nullptr && tex_cube->num_meshes > 0); - GLmesh* texmesh = getFreeGLMesh(rs); - if (!texmesh) return false; - - *texmesh = loadGLMesh(s_debug, tex_cube->meshes[0], - GL_TRIANGLES, glm::vec3(0, 0, 0)); - if (texmesh->vao_id == 0) return false; + const mesh& texmesh = tex_cube->meshes[0]; // ======== // NOTE: testing new loadGLMesh interface - texmesh = getFreeGLMesh(rs); - if (!texmesh) return false; + GLmesh* gl_texmesh = getFreeGLMesh(rs); +#if 1 + if (!gl_texmesh) return false; GLVertexAttrib* pos_attrib = getVertexAttribByName(s_debug, "position"); GLVertexAttrib* normal_attrib = getVertexAttribByName(s_debug, "normal"); if (!pos_attrib || !normal_attrib) return false; GLBufferToAttribMapping attrib_mappings[2] = { - { "position", nullptr, pos_attrib }, - { "normal", nullptr, normal_attrib } + { "position", nullptr, pos_attrib, texmesh.vertices }, + { "normal", nullptr, normal_attrib, texmesh.normals } }; - *texmesh = loadGLMesh(s_debug, tex_cube->meshes[0], - GL_TRIANGLES, glm::vec3(10, 0, 0), - 2, attrib_mappings); - if (texmesh->vao_id == 0) return false; + *gl_texmesh = loadGLMesh(texmesh, GL_TRIANGLES, glm::vec3(-5, -5, 0), 2, + attrib_mappings); + if (gl_texmesh->vao_id == 0) return false; // // ======== + gl_texmesh = getFreeGLMesh(rs); +#endif + if (!gl_texmesh) return false; + + *gl_texmesh = loadGLMesh(s_debug, texmesh, + GL_TRIANGLES, glm::vec3(5, 5, 0)); + + if (gl_texmesh->vao_id == 0) return false; for (u32 i = 0; i < NUM_CUBES; i++) { GLmesh* gmesh = getFreeGLMesh(rs); if (!gmesh) return false; @@ -310,6 +313,9 @@ loop(RenderState* rs) bool running = true; SDL_Event e; + shader_program* s_default = getShaderByName("default", rs->gl_ctx); + shader_program* s_debug = getShaderByName("debug", rs->gl_ctx); + while (running) { frame_start = SDL_GetTicks(); @@ -329,7 +335,8 @@ loop(RenderState* rs) GLmesh& glm = rs->gl_meshes[i]; *glm.model_xform = glm::rotate( *glm.model_xform, (float) M_PI / 60, glm::vec3(0, 1, 0)); - renderVAO(&glm); + shader_program* s = (glm.shader) ? glm.shader : s_debug; + renderVAO(&glm, s); } SDL_GL_SwapWindow(rs->handles->window); diff --git a/src/shader.cpp b/src/shader.cpp index 2c8ab02..1bc035e 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -131,13 +131,19 @@ getShaderByID(GLContext* gl_ctx, GLuint prog_id) } void -renderVAO(GLmesh* glmesh) +renderVAO(GLmesh* glmesh, shader_program* shader) { - glUseProgram(glmesh->shader->prog_id); + glUseProgram(shader->prog_id); glBindVertexArray(glmesh->vao_id); - glUniformMatrix4fv(glmesh->shader->model_xform_id, 1, GL_FALSE, + glUniformMatrix4fv(shader->model_xform_id, 1, GL_FALSE, (float*) glmesh->model_xform); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glmesh->idx_buf_id); + + // FIXME: remove conditional when removing glmesh IDs + if (glmesh->element_buf) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glmesh->element_buf->id); + else + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glmesh->idx_buf_id); + glDrawElements( glmesh->draw_mode, glmesh->num_indices, GL_UNSIGNED_SHORT, 0); glBindVertexArray(0); @@ -241,25 +247,92 @@ getVertexAttribByName(shader_program* shader, const char* name) } GLmesh -loadGLMesh(shader_program* s, - const mesh& m, +initGLmesh(const mesh& m, u32 num_mappings, GLenum draw_mode, glm::vec3 pos) +{ + GLmesh glm = {0}; + glm.num_indices = m.num_indices; + glm.draw_mode = draw_mode; + glm.usage = GL_STATIC_DRAW; // TODO: logic for updating dynamic meshes + glm.num_vertex_attrib_buffers = num_mappings; + glm.vertex_attrib_buffers = UTIL_ALLOC(num_mappings, gl_buffer); + glm.model_xform = UTIL_ALLOC(1, glm::mat4); + glm.element_buf = UTIL_ALLOC(1, gl_buffer); + *glm.model_xform = glm::translate(glm::mat4(1), pos); + + return glm; +} + +void +initGLAttribBuffer(gl_buffer* buf, GLenum target, GLVertexAttrib* attrib) +{ + glGenBuffers(1, &buf->id); + buf->target = target; + buf->data_type = attrib->data_type; + buf->location = attrib->location; + buf->name = utilAllocateCStr(attrib->name); +} + +// FIXME: might as well pass in pointer to GLmesh, since that's how we're +// going to use this, can void copying GLmesh twich that way +GLmesh +loadGLMesh(const mesh& m, GLenum draw_mode, const glm::vec3& pos, u32 num_mappings, GLBufferToAttribMapping mappings[]) { - GLmesh glm = {0}; -#if 0 - // TODO: store gl_buffers on gl_ctx - // TODO: loop over mapping array to get buffer attrib info - WRONG! gl_ctx->num_vertex_buffers = num_mappings; - gl_ctx->vertex_buffers = ... + // NOTE: need to use freeGLMesh() when freeing because we're not storing + // the gl_buffers on a memory arean (yet) + GLmesh glm = initGLmesh(m, num_mappings, draw_mode, pos); + glGenVertexArrays(1, &glm.vao_id); + glBindVertexArray(glm.vao_id); + for (u32 i = 0; i < num_mappings; i++) { + // TODO: make a helper function here + gl_buffer& buf = glm.vertex_attrib_buffers[i]; + GLVertexAttrib* attrib = mappings[i].attrib; + u32 type_size = getGLTypeSize(attrib->data_type); + assert(type_size > 0); + + initGLAttribBuffer(&buf, GL_ARRAY_BUFFER, attrib); + glBindBuffer(buf.target, buf.id); + glBufferData(buf.target, + m.num_vertices * type_size, + mappings[i].mesh_buf, + glm.usage); + glVertexAttribPointer(attrib->location, attrib->num_components, + attrib->component_type, GL_FALSE, 0, 0); + glEnableVertexAttribArray(attrib->location); } -#endif + + glGenBuffers(1, &glm.element_buf->id); + glm.element_buf->target = GL_ELEMENT_ARRAY_BUFFER; + glm.element_buf->data_type = GL_UNSIGNED_SHORT; + glBindBuffer(glm.element_buf->target, glm.element_buf->id); + glBufferData(glm.element_buf->target, + m.num_indices * sizeof(u16), + m.indices, + glm.usage); + + glBindVertexArray(0); + return glm; } +void +freeGLMesh(GLmesh* glm) +{ + if (glm) { + for (u32 i = 0; i < glm->num_vertex_attrib_buffers; i++) + utilSafeFree(glm->vertex_attrib_buffers[i].name); + + utilSafeFree(glm->vertex_attrib_buffers); + utilSafeFree(glm->element_buf); + // NOTE: don't free the GLmesh because it is part of a memory arena + //utilSafeFree(glm); + } +} + // NOTE: internal bool diff --git a/src/shader.h b/src/shader.h index d18073a..a32d516 100644 --- a/src/shader.h +++ b/src/shader.h @@ -37,6 +37,7 @@ struct GLUniformBlock struct GLVertexAttrib { GLenum data_type; + GLenum component_type; u32 num_components; GLuint location; char* name; @@ -66,6 +67,7 @@ struct gl_buffer GLuint id; GLenum target; GLenum data_type; + GLuint location; // NOTE: if used as backing for vertex attribute GLuint binding_idx; // NOTE: if used as backing from uniform buffer object char* name; }; @@ -90,8 +92,9 @@ struct GLContext struct GLBufferToAttribMapping { const char* buf_name; - gl_buffer* buf; + gl_buffer* attrib_buf; GLVertexAttrib* attrib; + void* mesh_buf; }; struct GLmesh @@ -110,9 +113,9 @@ struct GLmesh glm::mat4* model_xform; // FIXME: WIP - u32 max_vertex_buffers; - u32 num_vertex_buffers; - gl_buffer* vertex_buffers; + u32 num_vertex_attrib_buffers; + gl_buffer* vertex_attrib_buffers; + gl_buffer* element_buf; // WIP // FIXME: replace IDs here with gl_buffer struct array? @@ -198,15 +201,14 @@ shader_program* getShaderByName(const char* name, GLContext* gl_ctx); shader_program* getShaderByID(GLContext* gl_ctx, GLuint prog_id); shader_program* getShaderByHash(GLContext* gl_ctx, u64 hash); shader_program* getFreeShader(GLContext* gl_ctx); -void renderVAO(GLmesh* glmesh); +void renderVAO(GLmesh* glmesh, shader_program* shader); GLmesh loadGLMesh(shader_program* s, const mesh& m, GLenum draw_mode, const glm::vec3& pos); // NOTE: testing new loadGLMesh interface GLVertexAttrib* getVertexAttribByName(shader_program* shader, const char* name); -GLmesh loadGLMesh(shader_program* s, - const mesh& m, +GLmesh loadGLMesh(const mesh& m, GLenum draw_mode, const glm::vec3& pos, u32 num_mappings,