diff --git a/assets/shaders/pbr.vert.spv b/assets/shaders/pbr.vert.spv index fefbd27..835bd5b 100644 Binary files a/assets/shaders/pbr.vert.spv and b/assets/shaders/pbr.vert.spv differ diff --git a/src/assets.cpp b/src/assets.cpp index f890d48..cd2f17f 100644 --- a/src/assets.cpp +++ b/src/assets.cpp @@ -435,10 +435,6 @@ apParseModel(u8 *data) { switch (m3d->material[i].prop[j].type) { - case m3dp_Kd: - { - U32ColToVec4(&model->materials.data[i].props.albedo, m3d->material[i].prop[j].value.color); - } break; case m3dp_Ka: { U32ColToVec4(&model->materials.data[i].props.ambient, m3d->material[i].prop[j].value.color); @@ -474,7 +470,7 @@ apParseModel(u8 *data) } u32 num_meshes = 0; - u32 last = UINT32_MAX; + u64 last = UINT64_MAX; for (u64 i = 0; i < m3d->numface; i += 1) { if (m3d->face[i].materialid != last) @@ -487,11 +483,11 @@ apParseModel(u8 *data) model->meshes.length = u64(num_meshes); model->meshes.data = (apMesh *)malloc(sizeof(apMesh) * num_meshes); - last = UINT32_MAX; + last = UINT64_MAX; u32 current_index = 0; for (u64 i = 0, j = 0; i < m3d->numface; i += 1, j += 3) { - if (last == UINT32_MAX) + if (last == UINT64_MAX) { model->meshes.data[current_index].mat_idx = m3d->face[i].materialid; model->meshes.data[current_index].start_idx = 0; @@ -542,14 +538,21 @@ apParseModel(u8 *data) model->vertices.data[j+2].normal.y = m3d->vertex[m3d->face[i].normal[2]].y; model->vertices.data[j+2].normal.z = m3d->vertex[m3d->face[i].normal[2]].z; - model->vertices.data[j+0].uv.x = m3d->tmap[m3d->face[i].texcoord[0]].u; - model->vertices.data[j+0].uv.y = m3d->tmap[m3d->face[i].texcoord[0]].v; + model->vertices.data[j+0].color = m3d->vertex[m3d->face[i].vertex[0]].color; + model->vertices.data[j+1].color = m3d->vertex[m3d->face[i].vertex[1]].color; + model->vertices.data[j+2].color = m3d->vertex[m3d->face[i].vertex[2]].color; - model->vertices.data[j+1].uv.x = m3d->tmap[m3d->face[i].texcoord[1]].u; - model->vertices.data[j+1].uv.y = m3d->tmap[m3d->face[i].texcoord[1]].v; + if (m3d->numtmap) + { + model->vertices.data[j+0].uv.x = m3d->tmap[m3d->face[i].texcoord[0]].u; + model->vertices.data[j+0].uv.y = m3d->tmap[m3d->face[i].texcoord[0]].v; - model->vertices.data[j+2].uv.x = m3d->tmap[m3d->face[i].texcoord[2]].u; - model->vertices.data[j+2].uv.y = m3d->tmap[m3d->face[i].texcoord[2]].v; + model->vertices.data[j+1].uv.x = m3d->tmap[m3d->face[i].texcoord[1]].u; + model->vertices.data[j+1].uv.y = m3d->tmap[m3d->face[i].texcoord[1]].v; + + model->vertices.data[j+2].uv.x = m3d->tmap[m3d->face[i].texcoord[2]].u; + model->vertices.data[j+2].uv.y = m3d->tmap[m3d->face[i].texcoord[2]].v; + } model->indices.data[j+0] = j+0; model->indices.data[j+1] = j+1; @@ -561,12 +564,6 @@ apParseModel(u8 *data) #endif } - for (u64 i = 0; i < model->meshes.length; i += 1) - { - apMesh *mesh = model->meshes.data + i; - Printfln("mat_idx: %llu start_idx: %llu length: %llu", mesh->mat_idx, mesh->start_idx, mesh->length); - } - model->m3d = m3d; return model; diff --git a/src/assets.h b/src/assets.h index cb2c39f..27561cd 100644 --- a/src/assets.h +++ b/src/assets.h @@ -16,6 +16,7 @@ typedef struct apVertex Vec3 pos; Vec3 normal; Vec2 uv; + u32 color; } apVertex; ArrayType(apVertex); @@ -30,7 +31,6 @@ typedef struct Image typedef struct apMatProps { - Vec4 albedo; Vec4 ambient; Vec4 specular; f32 shininess; diff --git a/src/renderer.cpp b/src/renderer.cpp index 585afe3..c82af8e 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -18,6 +18,13 @@ Init(Renderer *renderer) { b32 success = true; + renderer->perm_arena = ArenaCreate(MB(32)); + + for (u64 i = 0; i < FRAME_OVERLAP; i += 1) + { + renderer->frame_arenas[i] = ArenaCreate(MB(16)); + } + RGFW_setGLHint(RGFW_glMajor, 4); RGFW_setGLHint(RGFW_glMinor, 6); RGFW_setGLHint(RGFW_glProfile, RGFW_glCore); @@ -41,20 +48,29 @@ Init(Renderer *renderer) } } +#ifdef BUILD_DEBUG + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(DebugCallback, NULL); +#endif + for (u32 i = 0; i < PIPELINE_MAX; i += 1) { renderer->pipelines[i] = BuildPipeline(g_Pipeline_Create_Info + i); } - yoder = rLoadModel("models/yoda"); + glCreateBuffers(1, &renderer->mat_buf); + apMatProps props = {0}; + glNamedBufferData(renderer->mat_buf, sizeof(apMatProps), &props, GL_STATIC_DRAW); + + InitModels(renderer); return success; } -static b32 +static void InitModels(Renderer *renderer) { - b32 success = true; + Arena *arena = renderer->perm_arena; for (u64 i = 0; i < MODEL_ASSET_MAX; i += 1) { @@ -62,9 +78,49 @@ InitModels(Renderer *renderer) Asset asset = apLoadWithHash(hash); Assert(asset.model != NULL, "InitModels failure: Model loaded is NULL"); - } + apModel *a_model = asset.model; + rModel *model = renderer->models + i; - return success; + model->textures.length = a_model->textures.length; + model->textures.data = (u32 *)ArenaAlloc(arena, sizeof(u32) * model->textures.length); + + for (u64 j = 0; j < model->textures.length; j += 1) + { + apTexData *t_data = a_model->textures.data + j; + model->textures.data[j] = CreateTexture(t_data->bytes, t_data->w, t_data->h, t_data->ch); + Assert(model->textures.data[j] != GL_NONE, "InitModels failure: texture data is GL_NONE"); + } + + apVertexArray v_arr = a_model->vertices; + u32Array i_arr = a_model->indices; + model->buffer = CreateIndexedBuffer(v_arr.data, v_arr.length, i_arr.data, i_arr.length); + + + // TODO: placeholder/error material + model->meshes.length = a_model->meshes.length; + model->meshes.data = (rMesh *)ArenaAlloc(arena, sizeof(rMesh) * a_model->meshes.length); + for (u64 i = 0; i < model->meshes.length; i += 1) + { + apMesh *a_mesh = a_model->meshes.data + i; + rMesh *mesh = model->meshes.data + i; + + mesh->length = a_mesh->length; + mesh->idx_offset = uintptr(a_mesh->start_idx * sizeof(u32)); + + mesh->type = PPT_NONE; + if (a_mesh->mat_idx != UINT32_MAX) + { + apMaterial *mat = a_model->materials.data + a_mesh->mat_idx; + + mesh->type |= mat->tex.albedo != UINT32_MAX ? PPT_ALBEDO_TEX : PPT_ALBEDO_VALUE; + mesh->type |= mat->tex.ambient != UINT32_MAX ? PPT_AMBIENT_TEX : PPT_AMBIENT_VALUE; + mesh->type |= mat->tex.specular != UINT32_MAX ? PPT_SPECULAR_TEX : PPT_SPECULAR_VALUE; + + mesh->values = mat->props; + mesh->textures = mat->tex; + } + } + } } static PipelineHandle @@ -157,62 +213,38 @@ CreateShader(int type) return (ShaderHandle)glCreateShader(type); } -static rIndexedBuffer -rLoadModel(char *asset) -{ - rIndexedBuffer mesh = {0}; - - /* - mesh.array = CreateVertexArray(); - mesh.vertex = CreateVertexBuffer(); - mesh.index = CreateIndexBuffer(); - - glBindVertexArray(mesh.array); - glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex); - - Asset data = apLoad(asset); - Assert(data.model != NULL, "CreateMeshBuffer failed to load asset"); - - mesh.draw_count = data.model_meta.i_count; - - Printfln("v_count: %llu", data.model->v_count); - - glBufferData( - GL_ARRAY_BUFFER, - data.model->v_count * sizeof(apVertex), - data.model->vertices, - GL_STATIC_DRAW - ); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index); - glBufferData( - GL_ELEMENT_ARRAY_BUFFER, - data.model->i_count * sizeof(u32), - data.model->indices, - GL_STATIC_DRAW - ); - - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(apVertex), 0); - - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(apVertex), (void *)offsetof(apVertex, col)); - - apUnload(asset); - - glBindVertexArray(0); - - */ - - return mesh; -} - - // ::Init::Impl::End:: // ::Draw::Impl::Start:: +static void +rDrawModel(Renderer *renderer, rModel *model) +{ + glUseProgram(renderer->pipelines[PIPELINE_PBR]); + + for (u64 i = 0; i < model->meshes.length; i += 1) + { + rMesh *mesh = model->meshes.data + i; + + u32 albedo = mesh->textures.albedo != UINT32_MAX ? mesh->textures.albedo : 0; + glBindTextureUnit(0, albedo); + + u32 ambient = mesh->textures.ambient != UINT32_MAX ? mesh->textures.ambient : 0; + glBindTextureUnit(1, ambient); + + u32 specular = mesh->textures.specular != UINT32_MAX ? mesh->textures.ambient : 0; + glBindTextureUnit(2, specular); + + glNamedBufferSubData(renderer->mat_buf, 0, sizeof(apMatProps), &mesh->values); + + glBindBufferBase(GL_UNIFORM_BUFFER, 0, renderer->mat_buf); + + glBindVertexArray(model->buffer.vao); + glDrawElements(GL_TRIANGLES, mesh->length, GL_UNSIGNED_INT, (void *)(model->buffer.ioffset + mesh->idx_offset)); + } +} + static void DrawIndexedBuffer(rIndexedBuffer *buffer) { @@ -220,7 +252,6 @@ DrawIndexedBuffer(rIndexedBuffer *buffer) glDrawElements(GL_TRIANGLES, buffer->icount, GL_UNSIGNED_INT, (void *)buffer->ioffset); } - // ::Draw::Impl::End:: @@ -242,8 +273,8 @@ CreateIndexedBuffer(rawptr vert_data, u32 vcount, rawptr idx_data, u32 icount) isize idx_len_aligned = Align(idx_len, alignment); #if BUILD_DEBUG - Assert((vert_len_aligned / alignment) == 0, "Buffers are not aligned"); - Assert((idx_len_aligned / alignment) == 0, "Buffers are not aligned"); + Assert((vert_len_aligned % alignment) == 0, "Buffers are not aligned"); + Assert((idx_len_aligned % alignment) == 0, "Buffers are not aligned"); #endif isize vert_offset = 0; @@ -258,19 +289,16 @@ CreateIndexedBuffer(rawptr vert_data, u32 vcount, rawptr idx_data, u32 icount) glCreateVertexArrays(1, &vao); constexpr u32 pos_size = SizeOfMember(apVertex, pos) / sizeof(f32); - glEnableVertexArrayAttrib(vao, 0); - glVertexArrayAttribBinding(vao, 0, 0); - glVertexArrayAttribFormat(vao, 0, pos_size, GL_FLOAT, GL_FALSE, 0); + SetVertexAttrib(vao, 0, pos_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, pos)); constexpr u32 normal_size = SizeOfMember(apVertex, normal) / sizeof(f32); - glEnableVertexArrayAttrib(vao, 1); - glVertexArrayAttribBinding(vao, 1, 0); - glVertexArrayAttribFormat(vao, 1, normal_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, normal)); + SetVertexAttrib(vao, 1, normal_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, normal)); + + constexpr u32 col_size = SizeOfMember(apVertex, color) / sizeof(u8); + SetVertexAttrib(vao, 2, col_size, GL_UNSIGNED_BYTE, GL_FALSE, offsetof(apVertex, color)); constexpr u32 uv_size = SizeOfMember(apVertex, uv) / sizeof(f32); - glEnableVertexArrayAttrib(vao, 2); - glVertexArrayAttribBinding(vao, 2, 0); - glVertexArrayAttribFormat(vao, 2, uv_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, uv)); + SetVertexAttrib(vao, 3, uv_size, GL_FLOAT, GL_FALSE, offsetof(apVertex, uv)); glVertexArrayVertexBuffer(vao, 0, buffer, vert_offset, sizeof(apVertex)); glVertexArrayElementBuffer(vao, buffer); @@ -284,6 +312,14 @@ CreateIndexedBuffer(rawptr vert_data, u32 vcount, rawptr idx_data, u32 icount) return indexed_buffer; } +static void +SetVertexAttrib(u32 vao, u32 idx, u32 count, i32 type, b32 normalized, u32 offset) +{ + glEnableVertexArrayAttrib(vao, idx); + glVertexArrayAttribBinding(vao, idx, 0); + glVertexArrayAttribFormat(vao, idx, count, type, normalized, offset); +} + // ::Buffers::Impl::End:: @@ -302,20 +338,29 @@ CreateTexture(rawptr data, u32 width, u32 height, u32 channels) switch (channels) { case 1: - format = GL_R8; - copy_format = GL_RED; - break; + { + format = GL_R8; + copy_format = GL_RED; + } break; case 2: - format = GL_RG8; - copy_format = GL_RG; + { + format = GL_RG8; + copy_format = GL_RG; + } break; case 3: - format = GL_RGB8; - copy_format = GL_RGB; + { + format = GL_RGB8; + copy_format = GL_RGB; + } break; case 4: - format = GL_RGBA8; - copy_format = GL_RGBA; + { + format = GL_RGBA8; + copy_format = GL_RGBA; + } break; default: - Assert(false, "CreateTexture failure: unsupported channel number passed in"); + { + Assert(false, "CreateTexture failure: unsupported channel number passed in"); + } break; } glTextureStorage2D(tex, mipmap, format, width, height); @@ -339,16 +384,121 @@ RunCycle(Renderer *renderer) { while (RGFW_window_checkEvent(renderer->window)); - Asset yoder = apLoad("models/yoda"); - glUseProgram(renderer->pipelines[PIPELINE_PBR]); glClearColor(0.1f, 0.8f, 0.4f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); - //DrawMeshBuffer(&yoder); + rDrawModel(renderer, renderer->models + 2); RGFW_window_swapBuffers(renderer->window); return !RGFW_window_shouldClose(renderer->window); } + + + +// ::Debug::Impl::Start:: + +void DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message, void const* user_param) +{ + if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) return; + + const char *source_str, *type_str, *severity_str; + + switch (source) + { + case GL_DEBUG_SOURCE_API: + { + source_str = "API"; + } break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: + { + source_str = "WINDOW SYSTEM"; + } break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: + { + source_str = "SHADER COMPILER"; + } break; + case GL_DEBUG_SOURCE_THIRD_PARTY: + { + source_str = "THIRD PARTY"; + } break; + case GL_DEBUG_SOURCE_APPLICATION: + { + source_str = "APPLICATION"; + } break; + case GL_DEBUG_SOURCE_OTHER: + { + source_str = "OTHER"; + } break; + default: + { + source_str = "UNKNOWN"; + } break; + } + + switch (type) + { + case GL_DEBUG_TYPE_ERROR: + { + type_str = "ERROR"; + } break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + { + type_str = "DEPRECATED BEHAVIOR"; + } break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + { + type_str = "UNDEFINED BEHAVIOR"; + } break; + case GL_DEBUG_TYPE_PORTABILITY: + { + type_str = "PORTABILITY"; + } break; + case GL_DEBUG_TYPE_PERFORMANCE: + { + type_str = "PERFORMANCE"; + } break; + case GL_DEBUG_TYPE_MARKER: + { + type_str = "MARKER"; + } break; + case GL_DEBUG_TYPE_OTHER: + { + type_str = "OTHER"; + } break; + default: + { + type_str = "UNKNOWN"; + } break; + } + + switch (severity) + { + case GL_DEBUG_SEVERITY_NOTIFICATION: + { + severity_str = "NOTIFICATION"; + } break; + case GL_DEBUG_SEVERITY_LOW: + { + severity_str = "LOW"; + } break; + case GL_DEBUG_SEVERITY_MEDIUM: + { + severity_str = "MEDIUM"; + } break; + case GL_DEBUG_SEVERITY_HIGH: + { + severity_str = "HIGH"; + } break; + default: + { + severity_str = "UNKNOWN"; + } break; + } + + Printfln("Source: [%s] \nType: [%s] \nSeverity: [%s] \n%s", source_str, type_str, severity_str, message); +} + +// ::Debug::Impl::End:: diff --git a/src/renderer.h b/src/renderer.h index fbdeb9e..9388be4 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -5,6 +5,8 @@ #include "assets.h" +constexpr u64 FRAME_OVERLAP = 2; + typedef enum Pipeline_e { PIPELINE_PBR, @@ -12,6 +14,17 @@ typedef enum Pipeline_e PIPELINE_MAX, } Pipeline; +typedef enum PBRPropType_e +{ + PPT_NONE = 0x0000, + PPT_ALBEDO_VALUE = 0x0001, + PPT_AMBIENT_VALUE = 0x0002, + PPT_SPECULAR_VALUE = 0x0004, + PPT_ALBEDO_TEX = 0x0008, + PPT_AMBIENT_TEX = 0x0010, + PPT_SPECULAR_TEX = 0x0020, +} PBRPropType; + typedef struct PipelineCreateInfo { char *vertex_shader; @@ -33,29 +46,36 @@ typedef struct rIndexedBuffer typedef struct rMesh { - rIndexedBuffer buffer; - apMatProps material; - u32 texture; + apMatProps values; + apMatTextures textures; + uintptr idx_offset; + u64 length; + u32 type; } rMesh; ArrayType(rMesh); typedef struct rModel { + rIndexedBuffer buffer; rMeshArray meshes; + u32Array textures; } rModel; typedef struct Renderer { RGFW_window *window; PipelineHandle pipelines[PIPELINE_MAX]; - rIndexedBuffer models[MODEL_ASSET_MAX]; + rModel models[MODEL_ASSET_MAX]; + u32 mat_buf; + Arena *perm_arena; + Arena *frame_arenas[FRAME_OVERLAP]; } Renderer; // ::Init::Decl:: static b32 Init(Renderer *renderer); -static b32 InitModels(Renderer *renderer); +static void InitModels(Renderer *renderer); static PipelineHandle CreatePipeline(); static VertexBuffer CreateVertexBuffer(); static IndexBuffer CreateIndexBuffer(); @@ -68,11 +88,14 @@ static b32 BuildShader(ShaderHandle *handle, char *asset); // ::Draw::Decl:: static void DrawIndexedBuffer(rIndexedBuffer *buffer); +static void rDrawModel(Renderer *renderer, rModel *model); // ::Buffers::Decl:: static rIndexedBuffer rLoadModel(char *asset); static rIndexedBuffer CreateIndexedBuffer(rawptr vert_data, u32 vcount, rawptr idx_data, u32 icount); +static void SetVertexAttrib(u32 vao, u32 idx, u32 count, i32 type, b32 normalized, u32 offset); +static u32 rCreateBuffer(rawptr data, u32 size); // ::Textures::Decl:: @@ -82,3 +105,7 @@ static u32 CreateTexture(rawptr data, u32 width, u32 height, u32 channels); static void DrawMeshBuffer(rIndexedBuffer *mesh); +// ::Debug::Decl:: + +void DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, GLchar const* message, void const* user_param); + diff --git a/src/shaders/pbr.vert.glsl b/src/shaders/pbr.vert.glsl index 8bb64e7..b2fcf04 100644 --- a/src/shaders/pbr.vert.glsl +++ b/src/shaders/pbr.vert.glsl @@ -2,14 +2,14 @@ layout (location = 0) in vec3 in_pos; layout (location = 1) in vec3 in_normal; -layout (location = 2) in vec2 in_uv; +layout (location = 2) in vec4 in_color; +layout (location = 3) in vec2 in_uv; layout (location = 0) out vec4 out_color; layout (location = 1) out vec2 out_uv; -layout (std140, location = 0) uniform Properties +layout (std140, binding = 0) uniform Properties { - vec4 color; vec4 ambient; vec4 diffuse; vec4 specular; @@ -19,10 +19,9 @@ layout (std140, location = 0) uniform Properties layout (binding = 0) uniform sampler2D albedo_texture; layout (binding = 1) uniform sampler2D ambient_texture; layout (binding = 2) uniform sampler2D specular_texture; -layout (binding = 3) uniform sampler2D emission_texture; void main() { gl_Position = vec4(in_pos, 1.0); - out_color = in_color; + out_color = texture(albedo_texture, in_uv); }