models now rendering

This commit is contained in:
matthew 2025-06-18 15:24:40 +10:00
parent 874b5de482
commit 25292c0347
6 changed files with 284 additions and 111 deletions

Binary file not shown.

View File

@ -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,6 +538,12 @@ 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].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;
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;
@ -550,6 +552,7 @@ apParseModel(u8 *data)
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;

View File

@ -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;

View File

@ -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;
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");
}
return success;
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;
} break;
case 2:
{
format = GL_RG8;
copy_format = GL_RG;
} break;
case 3:
{
format = GL_RGB8;
copy_format = GL_RGB;
} break;
case 4:
{
format = GL_RGBA8;
copy_format = GL_RGBA;
} break;
default:
{
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::

View File

@ -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);

View File

@ -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);
}