diff --git a/src/main.cpp b/src/main.cpp index 6b7ee11..8a6d39c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,17 +55,6 @@ loadScene(RenderState* rs) shader_program* s_default = getShaderByName("default", rs->gl_ctx); assert(s_default); - // NOTE: set up mapping between shader attributes, and vertex buffers - GLVertexAttrib* df_pos_attrib = - getVertexAttribByName(s_default, "position"); - GLVertexAttrib* df_uv_attrib = getVertexAttribByName(s_default, "uv"); - assert(df_pos_attrib && df_uv_attrib); - - GLBufferToAttribMapping default_mappings[2] = { - { "position", df_pos_attrib, VERTEX}, - { "uvs", df_uv_attrib, UV } - }; - // NOTE: init new render group RenderGroup* debug_cube_group = getFreeRenderGroup(rs); assert(debug_cube_group); @@ -76,8 +65,13 @@ loadScene(RenderState* rs) Entity* e = getFreeEntity(debug_cube_group); assert(e); - initEntity(e, rs->gl_ctx, rs->rg_arena, tex_cube, - 2, default_mappings, "textured_box"); + initEntity(e, + rs->gl_ctx, + rs->rg_arena, + tex_cube, + s_default->num_vertex_attribs, + s_default->attrib_mappings, + "textured_box"); scaleEntity(e, 5); #if 0 diff --git a/src/shader.cpp b/src/shader.cpp index d12ceba..b124e54 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -604,6 +604,8 @@ parseAttributes(MemoryArena* arena, shader_program* s, GLContext* gl_ctx) glGetProgramiv(s->prog_id, GL_ACTIVE_ATTRIBUTES, &num_attribs); s->num_vertex_attribs = num_attribs; s->vertex_attribs = ARENA_ALLOC(arena, GLVertexAttrib, num_attribs); + s->attrib_mappings = + ARENA_ALLOC(arena, GLBufferToAttribMapping, num_attribs); GLchar attrib_name[256] = {0}; GLsizei length; diff --git a/src/shader.h b/src/shader.h index 50fb860..486a004 100644 --- a/src/shader.h +++ b/src/shader.h @@ -33,11 +33,21 @@ struct GLUniformBlock char* name; }; +enum MeshBufferType +{ + VERTEX, + NORMAL, + UV, + COLOR, + MESH_BUFFER_TYPE_COUNT +}; + // NOTE: we need another struct for vertex attributes that mirrors gl_buffer // because an attribute is associated with a shader_program while a buffer is // associated with the vertex data passed to glBufferData() struct GLVertexAttrib { + MeshBufferType buf_type; GLenum data_type; GLenum component_type; u32 num_components; @@ -45,6 +55,12 @@ struct GLVertexAttrib char* name; }; +struct GLBufferToAttribMapping +{ + GLVertexAttrib* attrib; + MeshBufferType buf_type; +}; + struct shader_program { GLuint prog_id; @@ -60,6 +76,7 @@ struct shader_program u32 num_vertex_attribs; GLVertexAttrib* vertex_attribs; + GLBufferToAttribMapping* attrib_mappings; char* name; u64 hash; // NOTE: hash of vs filpath + fs filepath concat @@ -106,21 +123,6 @@ struct GLContext GLTexture* textures; }; -enum MeshBufferType -{ - VERTEX, - NORMAL, - UV, - COLOR -}; - -struct GLBufferToAttribMapping -{ - const char* buf_name; - GLVertexAttrib* attrib; - MeshBufferType buf_type; -}; - // TODO: rename to GLMesh struct GLmesh { diff --git a/src/tangerine.cpp b/src/tangerine.cpp index 8a52461..98dba40 100644 --- a/src/tangerine.cpp +++ b/src/tangerine.cpp @@ -19,7 +19,6 @@ GLContext* initGLContext(MemoryArena* arena, // interface - RenderState* initRenderState(u32 max_models, u32 max_textures, @@ -54,6 +53,9 @@ initRenderState(u32 max_models, // FIXME: need to test this with another shader that has another UBO gl_buffer& ubo = rs->gl_ctx->uniform_buffers[rs->gl_ctx->num_ubos++]; initTransforms(rs->assets.arena, rs->xforms, &ubo, rs->gl_ctx); + + bool ret = loadDefaultShaders(rs); + assert(ret); } return rs; @@ -179,6 +181,56 @@ renderFrame(RenderState* rs, const GLClearColor& clear_col) } } +bool +loadDefaultShaders(RenderState* rs, + u32 num_shaders, + const ShaderInit shaders[]) +{ + for (u32 i = 0; i < num_shaders; i++) { + const ShaderInit& si = shaders[i]; + bool ret = addShaderProgram(rs->assets.arena, + rs->gl_ctx, + si.vert_path, + si.frag_path, + si.name); + + if (!ret) { + LOG(Error) << "failed to load shader " << si.name << "\n"; + return false; + } + + // TODO: need to set the mappings here + shader_program* shader = getShaderByName(si.name, rs->gl_ctx); + assert(shader); + + // NOTE: not every buffer will be available for every shader, so we + // enumerate them all, and store the ones that are present + u32 attrib_idx = 0; + + for (u32 i = 0; i < MESH_BUFFER_TYPE_COUNT; i++) { + MeshBufferType buf_type = (MeshBufferType) i; + GLVertexAttrib* attrib = getVertexAttribByType(shader, buf_type); + + if (attrib) + shader->attrib_mappings[attrib_idx++] = { attrib, buf_type }; + } + } + + return true; +} + +GLVertexAttrib* +getVertexAttribByType(shader_program* shader, MeshBufferType buf_type) +{ + switch (buf_type) { + case VERTEX: return getVertexAttribByName(shader, "position"); + case NORMAL: return getVertexAttribByName(shader, "normal"); + case UV: return getVertexAttribByName(shader, "uv"); + case COLOR: return getVertexAttribByName(shader, "color"); + default: return nullptr; + } +} + // internal diff --git a/src/tangerine.h b/src/tangerine.h index e30d8a4..6837b48 100644 --- a/src/tangerine.h +++ b/src/tangerine.h @@ -135,3 +135,39 @@ void doRenderLoop(RenderState* rs, void renderFrame(RenderState* rs, const GLClearColor& clear_col); + +// NOTE: automatic loading of default shaders + +struct ShaderInit +{ + const char* name; + const char* vert_path; + const char* frag_path; +}; + +#define DEFAULT_SHADER_INIT { "default", \ + "../data/shader.vert", \ + "../data/shader.frag" } +#define DEBUG_SHADER_INIT { "debug", \ + "../data/debug.vert", \ + "../data/debug.frag", } +#define COLORED_VERT_SHADER_INIT { "colored_vertices", \ + "../data/colored_vertices.vert", \ + "../data/colored_vertices.frag", } +#define SHADER_INIT_COUNT 3 +const ShaderInit SHADER_INIT_LIST[SHADER_INIT_COUNT] +{ + DEFAULT_SHADER_INIT, + DEBUG_SHADER_INIT, + COLORED_VERT_SHADER_INIT +}; + +bool loadDefaultShaders(RenderState* rs, + u32 num_shaders = SHADER_INIT_COUNT, + const ShaderInit shaders[] = SHADER_INIT_LIST); + +// NOTE: only useful if the shader attribute names match the names in the +// default shaders. If loading a custom shader, this may not work as expected, +// and you should use getVertexAttribByName instead +GLVertexAttrib* getVertexAttribByType(shader_program* shader, + MeshBufferType buf_type);