From 62539c777f0b6a5728ad3d8a3f6b711e046ad7d1 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Wed, 29 Dec 2021 10:33:36 -0500 Subject: [PATCH] use RenderGroups and Entities to store groups of meshes --- src/main.cpp | 216 ++++++++++++++++++++++++++++++++++--------------- src/shader.cpp | 7 +- src/shader.h | 25 +----- 3 files changed, 154 insertions(+), 94 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4d35750..ca81bfd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,42 +22,121 @@ struct SDLHandles SDL_DisplayMode display_mode; }; +// TODO: node/tree structure for entities +struct Node; + +struct Entity +{ + u32 num_meshes; + GLmesh* meshes; + glm::mat4* xform; + char* name; +}; + +struct RenderGroup +{ + shader_program* shader; + u32 num_entites; + u32 max_entities; + Entity* entities; + char* name; +}; + struct RenderState { - memory_arena* asset_arena; transforms* xforms; // NOTE: would be part of camera in libTangerine SDLHandles* handles; GLContext* gl_ctx; + memory_arena* asset_arena; Assets* assets; - // FIXME: WIP - // TODO: need to initialize groups memory_arena* rg_arena; u32 num_render_groups; u32 max_render_groups; RenderGroup* render_groups; - // TODO: need to initialize mappings - u32 num_mappings; - u32 max_mappings; - ShaderToRenderGroupMapping* mappings; - /// - - // TODO: can remove these after implementing render groups - u32 num_gl_meshes; - u32 max_gl_meshes; - GLmesh* gl_meshes; - u32 num_lights; u32 max_lights; PointLight* lights; }; +#define DEFAULT_ENTITY_COUNT 256 +void +initRenderGroup(RenderGroup* rg, + memory_arena* arena, + shader_program* shader, + u32 num_entities = DEFAULT_ENTITY_COUNT, + const char* name = "") +{ + rg->max_entities = num_entities; + rg->shader = shader; + rg->name = arenaCopyCStr(arena, name); + rg->entities = ARENA_ALLOC(arena, Entity, num_entities); +} + +void +freeRenderGroup(RenderGroup* rg, memory_arena* arena) +{ + printf("%s(), should probably look into freeing arena memory?\n", + __FUNCTION__); + assert(0); +} + +Entity* +getFreeEntity(RenderGroup* rg) +{ + if (rg->num_entites < rg->max_entities) + return &rg->entities[rg->num_entites++]; + + printf("%s(), render group full\n", __FUNCTION__); + return nullptr; +} + +bool +initEntity(Entity* e, + memory_arena* arena, + model* mdl, + u32 num_attrib_mappings, + GLBufferToAttribMapping* attrib_mappings, + const char* name = "") +{ + e->num_meshes = mdl->num_meshes; + e->meshes = ARENA_ALLOC(arena, GLmesh, e->num_meshes); + e->xform = ARENA_ALLOC(arena, glm::mat4, 1); + *e->xform = glm::mat4(1.f); + e->name = arenaCopyCStr(arena, name); + + for (u32 i = 0; i< e->num_meshes; i++) { + GLmesh* glm = &e->meshes[i]; + *glm = loadGLMesh(mdl->meshes[i], GL_TRIANGLES, glm::vec3(0, 0, 0), + num_attrib_mappings, attrib_mappings); + + if (glm->vao_id == 0) { + printf("%s(), error initializing entity\n", __FUNCTION__); + return false; + } + } + + return true; +} + +void +setEntityPosition(Entity* e, glm::vec3 pos) +{ + *e->xform = glm::translate(*e->xform, pos); +} + +void +rotateEntity(Entity* e, glm::vec3 axis, float radians) +{ + *e->xform = glm::rotate(*e->xform, radians, axis); +} + // NOTE: equivalent to rgAppend() in libTangerine model* -getModel(RenderState* rs, const char* filepath) +getModelByPath(RenderState* rs, const char* filepath) { model* mdl = assetGetCached(rs->assets, utilFNV64a_str(filepath)); @@ -67,13 +146,13 @@ getModel(RenderState* rs, const char* filepath) return mdl; } -GLmesh* -getFreeGLMesh(RenderState* rs) +RenderGroup* +getFreeRenderGroup(RenderState* rs) { - if (rs->num_gl_meshes < rs->max_gl_meshes) - return &rs->gl_meshes[rs->num_gl_meshes++]; + if (rs->num_render_groups < rs->max_render_groups) + return &rs->render_groups[rs->num_render_groups++]; - printf("%s(), Error, rs->gl_meshes is full\n", __FUNCTION__); + printf("%s(), no free render group\n", __FUNCTION__); return nullptr; } @@ -109,7 +188,7 @@ initAssets(memory_arena* arena, return assets; } -#define MAX_GL_MESHES 256 +#define DEFAULT_RENDER_GROUP_COUNT 256 RenderState* initRenderState() { @@ -117,13 +196,16 @@ initRenderState() if (rs) { rs->asset_arena = arenaInit(DEFAULT_ARENA_SIZE); - rs->rg_arena = arenaInit(DEFAULT_ARENA_SIZE); rs->assets = initAssets(rs->asset_arena); + + rs->rg_arena = arenaInit(DEFAULT_ARENA_SIZE); + rs->max_render_groups = DEFAULT_RENDER_GROUP_COUNT; + rs->render_groups = ARENA_ALLOC(rs->rg_arena, RenderGroup, + DEFAULT_RENDER_GROUP_COUNT); + rs->gl_ctx = initGLContext(rs->asset_arena); rs->xforms = ARENA_ALLOC(rs->asset_arena, transforms, 1); rs->handles = UTIL_ALLOC(1, SDLHandles); - rs->max_gl_meshes = MAX_GL_MESHES; - rs->gl_meshes = ARENA_ALLOC(rs->rg_arena, GLmesh, MAX_GL_MESHES); } return rs; @@ -233,20 +315,12 @@ addShaders(RenderState* rs) bool loadScene(RenderState* rs) { - const u32 NUM_CUBES = 4; - glm::vec3 cube_locs[NUM_CUBES] = { - glm::vec3(-10, 10, 0), - glm::vec3(-10, -10, 0), - glm::vec3( 10, 10, 0), - glm::vec3( 10, -10, 0), - }; - shader_program* s_default = getShaderByName("default", rs->gl_ctx); shader_program* s_debug = getShaderByName("debug", rs->gl_ctx); if (!s_default || !s_debug) return false; // TODO: full lighting model - model* tex_cube = getModel(rs, "../data/textured_cube.gltf"); + model* tex_cube = getModelByPath(rs, "../data/textured_cube.gltf"); assert(tex_cube != nullptr && tex_cube->num_meshes > 0); const mesh& texmesh = tex_cube->meshes[0]; @@ -259,30 +333,42 @@ loadScene(RenderState* rs) { "normal", nullptr, normal_attrib, texmesh.normals } }; - // NOTE: load meshes - GLmesh* gl_texmesh = getFreeGLMesh(rs); - if (!gl_texmesh) 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); - if (!gl_texmesh) return false; + const u32 NUM_CUBES = 4; + glm::vec3 cube_locs[NUM_CUBES] = { + glm::vec3(-10, 10, 0), + glm::vec3(-10, -10, 0), + glm::vec3( 10, 10, 0), + glm::vec3( 10, -10, 0), + }; - *gl_texmesh = loadGLMesh(texmesh, GL_TRIANGLES, glm::vec3(5, 5, 0), 2, - attrib_mappings); - if (gl_texmesh->vao_id == 0) return false; + RenderGroup* orange_cubes = getFreeRenderGroup(rs); + assert(orange_cubes != nullptr); + initRenderGroup(orange_cubes, rs->rg_arena, s_debug, NUM_CUBES, + "debug_cubes"); for (u32 i = 0; i < NUM_CUBES; i++) { - GLmesh* gmesh = getFreeGLMesh(rs); - if (!gmesh) return false; + Entity* e = getFreeEntity(orange_cubes); + assert(e != nullptr); + + if (!initEntity(e, rs->rg_arena, tex_cube, 2, attrib_mappings, + "debug_box")) + { + // FIXME: this doesn't actually do anything + freeRenderGroup(orange_cubes, rs->rg_arena); + return false; + } - *gmesh = loadGLMesh(texmesh, GL_TRIANGLES, cube_locs[i], 2, - attrib_mappings); - if (gmesh->vao_id == 0) return false; + setEntityPosition(e, cube_locs[i]); } + RenderGroup* debug_cube_group = getFreeRenderGroup(rs); + assert(debug_cube_group != nullptr); + initRenderGroup(debug_cube_group, rs->rg_arena, s_default, 1, + "orange_cubes"); + Entity* e = getFreeEntity(debug_cube_group); + assert(e != nullptr); + initEntity(e, rs->rg_arena, tex_cube, 2, attrib_mappings, "orange_box"); + return true; } @@ -294,9 +380,6 @@ 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(); @@ -312,14 +395,18 @@ loop(RenderState* rs) glClearColor(0.2, 0.2, 0.2, 1); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - for (u32 i = 0; i < rs->num_gl_meshes; i++) { - GLmesh& glm = rs->gl_meshes[i]; - *glm.model_xform = glm::rotate( - *glm.model_xform, (float) M_PI / 60, glm::vec3(0, 1, 0)); - // FIXME: need a shader to gl_mesh mapping - //shader_program* s = (glm.shader) ? glm.shader : s_debug; - shader_program* s = s_debug; - renderVAO(&glm, s); + for (u32 i = 0; i < rs->num_render_groups; i++) { + RenderGroup& rg = rs->render_groups[i]; + + for (u32 j = 0; j < rg.num_entites; j++) { + Entity& e = rg.entities[j]; + rotateEntity(&e, glm::vec3(0, 1, 0), (float) M_PI / 60); + + for (u32 k = 0; k < e.num_meshes; k++) { + GLmesh& glm = e.meshes[k]; + renderVAO(&glm, e.xform, rg.shader); + } + } } SDL_GL_SwapWindow(rs->handles->window); @@ -359,11 +446,6 @@ main() return 1; } -#if 0 - shader_program* s_debug = getShaderByName("debug", rs->gl_ctx); - dumpShader(s_debug->prog_id); -#endif - if (!loadScene(rs)) { LOG(Error) << "error loading scene\n"; return 1; diff --git a/src/shader.cpp b/src/shader.cpp index eb1e198..6aa8b5b 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -131,12 +131,12 @@ getShaderByID(GLContext* gl_ctx, GLuint prog_id) } void -renderVAO(GLmesh* glmesh, shader_program* shader) +renderVAO(GLmesh* glmesh, glm::mat4* model_xform, shader_program* shader) { glUseProgram(shader->prog_id); glBindVertexArray(glmesh->vao_id); glUniformMatrix4fv(shader->model_xform_id, 1, GL_FALSE, - (float*) glmesh->model_xform); + (float*) model_xform); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glmesh->element_buf->id); glDrawElements( glmesh->draw_mode, glmesh->num_indices, GL_UNSIGNED_SHORT, 0); @@ -212,7 +212,7 @@ initGLAttribBuffer(gl_buffer* buf, GLenum target, GLVertexAttrib* attrib) } // 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 +// going to use this, can void copying GLmesh twice that way GLmesh loadGLMesh(const mesh& m, GLenum draw_mode, @@ -273,6 +273,7 @@ freeGLMesh(GLmesh* glm) } } + // NOTE: internal bool diff --git a/src/shader.h b/src/shader.h index 84db88d..6d307cb 100644 --- a/src/shader.h +++ b/src/shader.h @@ -112,29 +112,6 @@ struct GLmesh gl_buffer* element_buf; }; -// TODO: node/tree structure for entities -struct Node; - -struct Entity -{ - u32 num_meshes; - GLmesh* meshes; -}; - -struct RenderGroup -{ - u32 num_entites; - u32 max_entities; - Entity* entities; - char* name; -}; - -struct ShaderToRenderGroupMapping -{ - shader_program* shader; - RenderGroup* render_group; -}; - struct Animation; struct PointLight @@ -171,7 +148,7 @@ 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, shader_program* shader); +void renderVAO(GLmesh* glmesh, glm::mat4* model_xform, shader_program* shader); GLVertexAttrib* getVertexAttribByName(shader_program* shader, const char* name); GLmesh loadGLMesh(const mesh& m, GLenum draw_mode,