summaryrefslogtreecommitdiff
path: root/model.cpp
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2025-01-01 18:43:31 +1100
committerquou <quou@disroot.org>2025-01-01 18:43:31 +1100
commitd26100734623f37063206b9b144c2a29fd71d414 (patch)
tree11aefe54b4110109a841cb656b2f309ee69a1893 /model.cpp
parent568ba73c71b650f905bd1b3f60f10871316eefdc (diff)
material system
Diffstat (limited to 'model.cpp')
-rw-r--r--model.cpp124
1 files changed, 123 insertions, 1 deletions
diff --git a/model.cpp b/model.cpp
index 2b6f1f4..d911ac7 100644
--- a/model.cpp
+++ b/model.cpp
@@ -2,6 +2,7 @@
#include "model.hpp"
extern "C" {
+#include "material.h"
#include "memory.h"
#include "pack.h"
#include "plat.h"
@@ -14,6 +15,35 @@ struct MVP_Cbuffer {
m4f view_projection;
};
+struct Mat_Cbuffer {
+ float albedo[3];
+ float metalness;
+ float roughness;
+ float ao;
+ char pad[40];
+};
+
+void Material::use(
+ Pipeline_Builder& pb,
+ Sampler_Id sampler,
+ Shader& shader
+) {
+ auto bind = [&shader, &pb, sampler](
+ const char* name,
+ Texture_Id t
+ ) {
+ int loc = shader.descriptor_binding(name);
+ if (loc >= 0) {
+ pb.texture(loc, t, sampler);
+ }
+ };
+ bind("albedo", tex.albedo);
+ bind("ao", tex.ao);
+ bind("metal", tex.metal);
+ bind("rough", tex.rough);
+ bind("normal", tex.normal);
+}
+
void Model_Loader::init(Device* device, Asset_Arena* shader_arena) {
dev = device;
shaders = shader_arena;
@@ -68,6 +98,7 @@ Asset* Model_Loader::load(
Mesh& mesh = meshes[i];
int vertex_size, vertex_count;
char shader_name[28];
+ char material_name[28];
Shader* shader;
pack_read(f, magic, 4);
if (
@@ -80,13 +111,18 @@ Asset* Model_Loader::load(
return 0;
}
pack_read(f, shader_name, sizeof shader_name);
+ pack_read(f, material_name, sizeof material_name);
mesh.offset = icoff;
shader = (Shader*)shaders->load(shader_name);
+ mesh.material = (Material*)shaders->load(material_name);
assert(shader != 0);
+ assert(mesh.material != 0);
mesh.shader = shader->id;
mesh.mvp_binding = shader->descriptor_binding("c_mvp");
+ mesh.mat_binding = shader->descriptor_binding("material");
mesh.mesh_binding = shader->binding_index("mesh");
assert(mesh.mvp_binding >= 0);
+ assert(mesh.mat_binding >= 0);
assert(mesh.mesh_binding >= 0);
pack_read(f, &vertex_size, 4);
pack_read(f, &mesh.count, 4);
@@ -120,6 +156,12 @@ Asset* Model_Loader::load(
Buffer_Flags::constant_buffer |
Buffer_Flags::cpu_readwrite
);
+ r->mat = dev->create_buffer(
+ filename,
+ sizeof(Mat_Cbuffer) * node_count,
+ Buffer_Flags::constant_buffer |
+ Buffer_Flags::cpu_readwrite
+ );
ctx = &dev->acquire();
ctx->copy(r->vbo, stage_verts);
ctx->copy(r->ibo, stage_indices);
@@ -134,6 +176,7 @@ void Model_Loader::unload(Asset* a) {
dev->destroy_buffer(m->vbo);
dev->destroy_buffer(m->ibo);
dev->destroy_buffer(m->mvp);
+ dev->destroy_buffer(m->mat);
}
const m4f& Mesh::get_world(Model& m) {
@@ -168,17 +211,32 @@ void Model::update_cbuffers(
0,
c * sizeof *cbuffers
);
+ Mat_Cbuffer* mats = (Mat_Cbuffer*)dev->map_buffer(
+ mat,
+ 0,
+ c * sizeof *cbuffers
+ );
for (i = 0; i < c; i++) {
+ Mat_Cbuffer& mat = mats[i];
+ Material& sm = *meshes[i].material;
cbuffers[i].view_projection = view_projection;
cbuffers[i].model = transform * meshes[i].world;
+ mat.albedo[0] = sm.albedo.x;
+ mat.albedo[1] = sm.albedo.y;
+ mat.albedo[2] = sm.albedo.z;
+ mat.metalness = sm.metalness;
+ mat.roughness = sm.roughness;
+ mat.ao = sm.ao;
}
dev->unmap_buffer(mvp);
+ dev->unmap_buffer(mat);
}
void Model::render(
Device* dev,
Arena* a,
- Render_Pass& pass
+ Render_Pass& pass,
+ Sampler_Id sampler
) {
int i, c = mesh_count;
Mesh* meshes = get_meshes();
@@ -211,14 +269,78 @@ void Model::render(
pb.depth(true, false, Depth_Mode::equal);
pb.cull(Cull_Mode::back);
pb.shader(mesh.shader);
+ mesh.material->use(pb, sampler, dev->get_shader(mesh.shader));
pb.cbuffer(
mesh.mvp_binding,
mvp,
i * sizeof(MVP_Cbuffer),
sizeof(MVP_Cbuffer)
);
+ pb.cbuffer(
+ mesh.mat_binding,
+ mat,
+ i * sizeof(Mat_Cbuffer),
+ sizeof(Mat_Cbuffer)
+ );
pb.vertex_format(shader.vf);
Pipeline& pip = pb.build();
ctx.submit(draw, pip, pass);
}
}
+
+void Material_Loader::init(
+ Asset_Arena* texture_arena,
+ Texture_Id dt
+) {
+ default_tex = dt;
+ textures = texture_arena;
+}
+
+Asset* Material_Loader::load(
+ Arena* a,
+ Arena* s,
+ const char* filename,
+ Pack_File* f
+) {
+ Material_File mf;
+ Material* m = (Material*)arena_alloc(a, sizeof *m);
+ auto read_name = [&](int len) {
+ char* r = (char*)arena_alloc(s, len + 1);
+ r[pack_read(f, r, len)] = 0;
+ return r;
+ };
+ auto read_tex = [&](int len) {
+ if (!len) return default_tex;
+ const char* name = read_name(len);
+ auto t = (Texture*)textures->load(name);
+ if (!t)
+ return default_tex;
+ return t->id;
+ };
+ (void)filename;
+ pack_read(f, &mf, sizeof mf);
+ if (
+ mf.magic[0] != 'M' ||
+ mf.magic[1] != 'T' ||
+ mf.magic[2] != 'R' ||
+ mf.magic[3] != 'L'
+ ) return 0;
+ m->metalness = mf.metalness;
+ m->roughness = mf.roughness;
+ m->ao = mf.ao;
+ m->albedo = v3f(
+ (float)((mf.albedo >> 16) & 0xff) / 255.0f,
+ (float)((mf.albedo >> 8) & 0xff) / 255.0f,
+ (float)((mf.albedo) & 0xff) / 255.0f
+ );
+ m->tex.albedo = read_tex(mf.albedo_tex_len);
+ m->tex.ao = read_tex(mf.ao_tex_len);
+ m->tex.metal = read_tex(mf.metal_tex_len);
+ m->tex.rough = read_tex(mf.rough_tex_len);
+ m->tex.normal = read_tex(mf.normal_tex_len);
+ return m;
+}
+
+void Material_Loader::unload(Asset* a) {
+ (void)a;
+}