diff --git a/src/asset.cpp b/src/asset.cpp index 99b986d..202f8ea 100644 --- a/src/asset.cpp +++ b/src/asset.cpp @@ -21,7 +21,6 @@ bool parseMeshNode(mesh* m, model* getCachedModel(Assets* assets, u64 path_hash); model* loadModelFile(Assets* assets, const char* filename); util_image* getCachedTexture(Assets* assets, u64 path_hash); -util_image* loadTextureFile(Assets* assets, const char* filename); // interface @@ -43,8 +42,12 @@ getTextureByPath(Assets* assets, const char* filepath) util_image* texture = getCachedTexture(assets, utilFNV64a_str(filepath)); - if (!texture) - texture = loadTextureFile(assets, filepath); + // NOTE: the texture should be loaded when the model is loaded, so it's an + // error if we don't find it in cache + if (!texture) { + LOG(Error) << "texture file, " << filepath << " not loaded\n"; + return nullptr; + } return texture; } @@ -90,9 +93,13 @@ copyDiffuseTexture(Assets* assets, const tinygltf::Model& t_mdl) && t_mdl.images.size() == 1 && t_mdl.images[0].image.size() > 0); tinygltf::Image t_img = t_mdl.images[0]; - util_image* dtex = getFreeTexture(assets); - if (!dtex) return nullptr; + + if (!dtex) { + LOG(Error) << "Error Loading diffuse texture\n"; + // TODO: reclaim arena memory + return nullptr; + } dtex->w = t_img.width; dtex->h = t_img.height; @@ -122,19 +129,16 @@ loadModelFile(Assets* assets, const char* filename) << " , msg: " << err << "\n"; return nullptr; } + #if 0 dumpNodes(t_mdl); #endif + // NOTE: assume we're working with a single buffer assert(t_mdl.buffers.size() == 1); model* mdl = initModel(assets, t_mdl, filename); mdl->diffuse_texture = copyDiffuseTexture(assets, t_mdl); - - if (mdl->diffuse_texture == nullptr) { - LOG(Error) << "Error Loading diffuse texture\n"; - // TODO: reclaim arena memory - return nullptr; - } + if (mdl->diffuse_texture == nullptr) return nullptr; uint mesh_idx = 0; @@ -166,12 +170,6 @@ getCachedModel(Assets* assets, u64 path_hash) return nullptr; } -util_image* -loadTextureFile(Assets* assets, const char* filename) -{ - return nullptr; -} - util_image* getCachedTexture(Assets* assets, u64 path_hash) { diff --git a/src/entity.cpp b/src/entity.cpp index 1bece4d..0f57166 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -6,6 +6,7 @@ bool initEntity(Entity* e, + GLContext* gl_ctx, MemoryArena* arena, model* mdl, u32 num_attrib_mappings, @@ -17,11 +18,19 @@ initEntity(Entity* e, e->xform = ARENA_ALLOC(arena, glm::mat4, 1); *e->xform = glm::mat4(1.f); e->name = arenaCopyCStr(arena, name); + e->diffuse_texture = getGLTexture(gl_ctx, mdl->diffuse_texture); + + if (!e->diffuse_texture) + return false; 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); + *glm = loadGLMesh(mdl->meshes[i], + GL_TRIANGLES, + e->diffuse_texture->id, + glm::vec3(0, 0, 0), + num_attrib_mappings, + attrib_mappings); if (glm->vao_id == 0) { printf("%s(), error initializing entity\n", __FUNCTION__); diff --git a/src/entity.h b/src/entity.h index e7a1bf0..a13793b 100644 --- a/src/entity.h +++ b/src/entity.h @@ -18,6 +18,7 @@ struct Entity bool initEntity(Entity* e, + GLContext* gl_ctx, MemoryArena* arena, model* mdl, u32 num_attrib_mappings, diff --git a/src/main.cpp b/src/main.cpp index 3a6ae8b..1cc5680 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -279,9 +279,8 @@ loadScene(RenderState* rs) Entity* e = getFreeEntity(orange_cubes); assert(e != nullptr); - // FIXME: check if mesh texture is cached here? - if (!initEntity(e, rs->rg_arena, tex_cube, 2, attrib_mappings, - "debug_box")) + if (!initEntity(e, rs->gl_ctx, rs->rg_arena, tex_cube, + 2, attrib_mappings, "debug_box")) { // FIXME: this doesn't actually do anything freeRenderGroup(orange_cubes, rs->rg_arena); @@ -299,7 +298,8 @@ loadScene(RenderState* rs) assert(e != nullptr); // FIXME: this a bug, we're reusing the attrib_mappings from the debug // shader for the default shader, which could have different attributes - initEntity(e, rs->rg_arena, tex_cube, 2, attrib_mappings, "orange_box"); + initEntity(e, rs->gl_ctx, rs->rg_arena, tex_cube, + 2, attrib_mappings, "orange_box"); return true; } diff --git a/src/shader.cpp b/src/shader.cpp index 0660be7..3c39fd0 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -27,33 +27,12 @@ bool compileAndLinkShader(shader_program* shader, GLuint& vs_id, GLuint& fs_id); u32 getGLTypeSize(GLenum e); +GLTexture* getFreeGLTexture(GLContext* gl_ctx); +bool loadGLTexture(util_image* image, GLuint& tex_id); // NOTE: interface -shader_program* -getFreeShader(GLContext* gl_ctx) -{ - if (gl_ctx->num_shaders >= gl_ctx->max_shaders) { - printf("%s(), GLContext->shaders full\n", __FUNCTION__); - return nullptr; - } - - shader_program* s = &gl_ctx->shaders[gl_ctx->num_shaders++]; - return s; -} - -shader_program* -getShaderByHash(GLContext* gl_ctx, u64 hash) -{ - for (u32 i; i < gl_ctx->num_shaders; i++) { - if (gl_ctx->shaders[i].hash == hash) - return &gl_ctx->shaders[i]; - } - - return nullptr; -} - bool addShaderProgram(MemoryArena* arena, GLContext* gl_ctx, @@ -103,6 +82,29 @@ addShaderProgram(MemoryArena* arena, return false; } +shader_program* +getFreeShader(GLContext* gl_ctx) +{ + if (gl_ctx->num_shaders >= gl_ctx->max_shaders) { + printf("%s(), GLContext->shaders full\n", __FUNCTION__); + return nullptr; + } + + shader_program* s = &gl_ctx->shaders[gl_ctx->num_shaders++]; + return s; +} + +shader_program* +getShaderByHash(GLContext* gl_ctx, u64 hash) +{ + for (u32 i; i < gl_ctx->num_shaders; i++) { + if (gl_ctx->shaders[i].hash == hash) + return &gl_ctx->shaders[i]; + } + + return nullptr; +} + shader_program* getShaderByName(const char* name, GLContext* gl_ctx) { @@ -130,6 +132,33 @@ getShaderByID(GLContext* gl_ctx, GLuint prog_id) return nullptr; } +GLTexture* +getGLTexture(GLContext* gl_ctx, util_image* diffuse_img) +{ + u64 fp_hash = utilFNV64a_str(diffuse_img->file_path); + + for (u32 i = 0; i < gl_ctx->num_textures; i++) { + GLTexture* glt = &gl_ctx->textures[i]; + + if (glt->filepath_hash == fp_hash) + return glt; + } + + GLTexture* glt = getFreeGLTexture(gl_ctx); + if (!glt) return nullptr; + + glt->pixel_format = (diffuse_img->num_channels == 3) ? GL_RGB : GL_RGBA; + glt->width = diffuse_img->w; + glt->height = diffuse_img->h; + glt->filepath_hash = diffuse_img->filepath_hash; + + if (loadGLTexture(diffuse_img, glt->id)) + return glt; + + printf("%s(), Error, unable to load texture\n", __FUNCTION__); + return nullptr; +} + void renderVAO(GLmesh* glmesh, glm::mat4* model_xform, shader_program* shader) { @@ -211,28 +240,12 @@ initGLAttribBuffer(gl_buffer* buf, GLenum target, GLVertexAttrib* attrib) buf->name = utilAllocateCStr(attrib->name); } -// FIXME: WIP -bool -initGLTexture(const util_image image, GLuint& tex_id) -{ - glGenTextures(1, &tex_id); - glBindTexture(GL_TEXTURE_2D, tex_id); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - GLenum pixel_format = (image.num_channels == 3) ? GL_RGB : GL_RGBA; - glTexImage2D(GL_TEXTURE_2D, 0, pixel_format, image.w, image.h, 0, - pixel_format, GL_UNSIGNED_BYTE, image.pixels); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - return (glGetError() == GL_NO_ERROR); -} -// FIXME: WIP - // FIXME: might as well pass in pointer to GLmesh, since that's how we're // going to use this, can void copying GLmesh twice that way GLmesh loadGLMesh(const mesh& m, GLenum draw_mode, + GLuint diffuse_texture_id, const glm::vec3& pos, u32 num_mappings, GLBufferToAttribMapping mappings[]) @@ -240,6 +253,7 @@ loadGLMesh(const mesh& m, // 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); + glm.tex_id = diffuse_texture_id; glGenVertexArrays(1, &glm.vao_id); glBindVertexArray(glm.vao_id); @@ -293,6 +307,31 @@ freeGLMesh(GLmesh* glm) // NOTE: internal +GLTexture* +getFreeGLTexture(GLContext* gl_ctx) +{ + if (gl_ctx->num_textures < gl_ctx->max_textures) + return &gl_ctx->textures[gl_ctx->num_textures++]; + + printf("%s(), no free textures\n", __FUNCTION__); + return nullptr; +} + +bool +loadGLTexture(util_image* image, GLuint& tex_id) +{ + glGenTextures(1, &tex_id); + glBindTexture(GL_TEXTURE_2D, tex_id); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + GLenum pixel_format = (image->num_channels == 3) ? GL_RGB : GL_RGBA; + glTexImage2D(GL_TEXTURE_2D, 0, pixel_format, image->w, image->h, 0, + pixel_format, GL_UNSIGNED_BYTE, image->pixels); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + return (glGetError() == GL_NO_ERROR); +} + bool compileAndLinkShader(shader_program* shader, const char* vert_src, diff --git a/src/shader.h b/src/shader.h index ce8daee..d9d19fd 100644 --- a/src/shader.h +++ b/src/shader.h @@ -164,10 +164,12 @@ 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); +GLTexture* getGLTexture(GLContext* gl_ctx, util_image* diffuse_img); 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, + GLuint diffuse_texture_id, const glm::vec3& pos, u32 num_mappings, GLBufferToAttribMapping mappings[]);