From d26100734623f37063206b9b144c2a29fd71d414 Mon Sep 17 00:00:00 2001 From: quou Date: Wed, 1 Jan 2025 18:43:31 +1100 Subject: material system --- model.cpp | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) (limited to 'model.cpp') 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; +} -- cgit v1.2.3-54-g00ecf