diff options
-rw-r--r-- | c2.cpp | 53 | ||||
-rw-r--r-- | convmodel.c | 31 | ||||
-rw-r--r-- | intermediate/monkey.glb | bin | 69720 -> 80692 bytes | |||
-rw-r--r-- | intermediate/surface.glsl | 16 | ||||
-rw-r--r-- | model.cpp | 66 | ||||
-rw-r--r-- | model.hpp | 12 | ||||
-rw-r--r-- | src/monkey.blend | bin | 522496 -> 539788 bytes |
7 files changed, 135 insertions, 43 deletions
@@ -152,28 +152,6 @@ extern "C" int entrypoint() { dev->unmap_buffer(cbuf); } - { - Texture& bb = dev->get_texture(dev->get_backbuffer()); - void* mem; - mem = dev->map_buffer(cbuf2, 0, sizeof(Config_Buffer2)); - Config_Buffer2* c = (Config_Buffer2*)mem; - c->projection = m4f::pers( - 70.0f, - (float)bb.w / (float)bb.h, - 0.01f, - 100.0f - ); - c->transform = (m4f::translate( - m4f::identity(), - v3f(0.0f, 0.0f, -5.0f) - ) * m4f::rotate( - m4f::identity(), - rot, - raxis - )); - dev->unmap_buffer(cbuf2); - } - Pipeline_Builder pb(&frame_arena, dev); pb.begin_rp(); pb.rp_target(dev->get_backbuffer(), { r, 0x00, 0xff, 0xff }); @@ -207,10 +185,37 @@ extern "C" int entrypoint() { dev->get_ctx().submit(draw, pip, pass); pb.begin_rp(); - pb.rp_target(dev->get_backbuffer(), Clear_Mode::restore); pb.rp_depth_target(dev->get_depth_target(), 1.0f); + dev->get_ctx().submit(pb.build_rp()); + + pb.begin_rp(); + pb.rp_target(dev->get_backbuffer(), Clear_Mode::restore); + pb.rp_depth_target(dev->get_depth_target(), Clear_Mode::restore); Render_Pass& pass2 = pb.build_rp(); - monkey->render(dev, &frame_arena, pass2, cbuf2); + + Texture& bb = dev->get_texture(dev->get_backbuffer()); + m4f projection = m4f::pers( + 70.0f, + (float)bb.w / (float)bb.h, + 0.01f, + 100.0f + ); + m4f transform = (m4f::translate( + m4f::identity(), + v3f(0.0f, 0.0f, -5.0f) + ) * m4f::rotate( + m4f::identity(), + rot, + raxis + )); + monkey->update_transforms(); + monkey->render( + dev, + &frame_arena, + pass2, + transform, + projection + ); ui->render(&frame_arena, dev->get_backbuffer()); diff --git a/convmodel.c b/convmodel.c index 5e57fc9..1a09f99 100644 --- a/convmodel.c +++ b/convmodel.c @@ -75,6 +75,13 @@ void parse_node_cfg(const cgltf_node* n, Node_Config* cfg) { const jsmntok_t* t = &toks[i]; if (tcmp(json, "shader", t)) { cfg->shader = read_str(json, &t[1]); + if (string_len(cfg->shader) > 27) { + print_err( + "Shader name %s too long (max 27 chars).\n", + cfg->shader + ); + pbreak(3478); + } i++; } } @@ -216,20 +223,30 @@ void parse_prim( } void parse_node_mesh( + int parent_index, const cgltf_node* n, + const Node_Config* cfg, Shader_Attrib* desired, FILE* outfile ) { const cgltf_mesh* m = n->mesh; int i, c = m->primitives_count; + char buf[28]; + float matrix[16]; + zero(buf, sizeof buf); + string_copy(buf, cfg->shader); vertex_count = 0; index_count = 0; for (i = 0; i < c; i++) parse_prim(&m->primitives[i], desired); + cgltf_node_transform_local(n, matrix); fwrite("MESH", 4, 1, outfile); + fwrite(buf, 1, sizeof buf, outfile); fwrite(&vertex_size, 4, 1, outfile); fwrite(&index_count, 4, 1, outfile); fwrite(&vertex_count, 4, 1, outfile); + fwrite(&parent_index, 4, 1, outfile); + fwrite(matrix, sizeof matrix, 1, outfile); fwrite(vertex_buffer, 1, vertex_count * vertex_size, outfile); fwrite(index_buffer, 1, index_count * sizeof *index_buffer, outfile); } @@ -336,7 +353,11 @@ int calc_vertex_size(Shader_Attrib* attribs) { return s; } -void parse_node(const cgltf_node* n, FILE* outfile) { +void parse_node( + int parent_index, + const cgltf_node* n, + FILE* outfile +) { Node_Config cfg = { 0 }; if (n->extras.data) parse_node_cfg(n, &cfg); @@ -353,7 +374,7 @@ void parse_node(const cgltf_node* n, FILE* outfile) { vertex_size = calc_vertex_size(desired); current_vertex = arena_alloc(&arena, vertex_size); assert(desired != 0); - parse_node_mesh(n, desired, outfile); + parse_node_mesh(parent_index, n, &cfg, desired, outfile); } } @@ -376,8 +397,12 @@ int parse(const char* fname, FILE* outfile) { c = (int)d->nodes_count; fwrite(&c, 4, 1, outfile); for (i = 0; i < c; i++) { + const cgltf_node* n = &d->nodes[i]; + int parent_index = 0; + if (n->parent) + parent_index = n->parent - d->nodes; clear_arena(&arena); - parse_node(&d->nodes[i], outfile); + parse_node(parent_index, &d->nodes[i], outfile); } cgltf_free(d); return 0; diff --git a/intermediate/monkey.glb b/intermediate/monkey.glb Binary files differindex d7b3665..d199545 100644 --- a/intermediate/monkey.glb +++ b/intermediate/monkey.glb diff --git a/intermediate/surface.glsl b/intermediate/surface.glsl index 681ec3f..18c13a3 100644 --- a/intermediate/surface.glsl +++ b/intermediate/surface.glsl @@ -25,17 +25,17 @@ name: normal type: vec3 [struct] -name: Config +name: MVP [variable] -name: transform +name: model type: mat4 [variable] -name: projection +name: view_projection type: mat4 [cbuffer] -name: config_buffer -type: Config +name: c_mvp +type: MVP stage: vertex [target] @@ -48,10 +48,10 @@ type: vec4 void main() { interpolator.uv = uv; - interpolator.normal = mat3(config_buffer.transform) * normal; + interpolator.normal = mat3(c_mvp.model) * normal; gl_Position = - config_buffer.projection * - config_buffer.transform * + c_mvp.view_projection * + c_mvp.model * vec4(position, 1.0); } @@ -9,6 +9,11 @@ extern "C" { #include <string.h> +struct MVP_Cbuffer { + m4f model; + m4f view_projection; +}; + void Model_Loader::init(Device* device, Asset_Arena* shader_arena) { dev = device; shaders = shader_arena; @@ -55,6 +60,8 @@ Asset* Model_Loader::load(Arena* a, Arena* s, Pack_File* f) { for (i = 0, coff = 0, icoff = 0, vcoff = 0; i < node_count; i++) { Mesh& mesh = meshes[i]; int vertex_size, vertex_count; + char shader_name[28]; + Shader* shader; pack_read(f, magic, 4); if ( magic[0] != 'M' || @@ -65,12 +72,20 @@ Asset* Model_Loader::load(Arena* a, Arena* s, Pack_File* f) { print_err("Invalid mesh.\n"); return 0; } + pack_read(f, shader_name, sizeof shader_name); mesh.offset = icoff; - mesh.parent = 0; - mesh.shader = ((Shader*)shaders->load("surface.csh"))->id; + shader = (Shader*)shaders->load(shader_name); + assert(shader != 0); + mesh.shader = shader->id; + mesh.mvp_binding = shader->descriptor_binding("c_mvp"); + mesh.mesh_binding = shader->binding_index("mesh"); + assert(mesh.mvp_binding >= 0); + assert(mesh.mesh_binding >= 0); pack_read(f, &vertex_size, 4); pack_read(f, &mesh.count, 4); pack_read(f, &vertex_count, 4); + pack_read(f, &mesh.parent, 4); + pack_read(f, &mesh.local, 64); pack_read(f, &verts[coff], vertex_count * vertex_size); pack_read(f, &indices[icoff], mesh.count * sizeof *indices); mesh.vbo_offset = vcoff; @@ -90,6 +105,11 @@ Asset* Model_Loader::load(Arena* a, Arena* s, Pack_File* f) { Buffer_Flags::copy_dst | Buffer_Flags::index_buffer ); + r->mvp = dev->create_buffer( + sizeof(MVP_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); @@ -103,24 +123,56 @@ void Model_Loader::unload(Asset* a) { Model* m = (Model*)a; dev->destroy_buffer(m->vbo); dev->destroy_buffer(m->ibo); + dev->destroy_buffer(m->mvp); +} + +const m4f& Mesh::get_world(Model& m) { + if (world_dirty) { + if (parent) + world = m.get_meshes()[parent].get_world(m) * local; + else + world = local; + world_dirty = false; + } + return world; +} + +void Model::update_transforms() { + int i, c = mesh_count; + Mesh* meshes = get_meshes(); + for (i = 0; i < c; i++) + meshes[i].world_dirty = true; + for (i = 0; i < c; i++) + meshes[i].get_world(*this); } void Model::render( Device* dev, Arena* a, Render_Pass& pass, - Buffer_Id config + const m4f& transform, + const m4f& view_projection ) { int i, c = mesh_count; Mesh* meshes = get_meshes(); Context& ctx = dev->get_ctx(); + MVP_Cbuffer* cbuffers = (MVP_Cbuffer*)dev->map_buffer( + mvp, + 0, + c * sizeof *cbuffers + ); + for (i = 0; i < c; i++) { + cbuffers[i].view_projection = view_projection; + cbuffers[i].model = transform * meshes[i].world; + } + dev->unmap_buffer(mvp); for (i = 0; i < c; i++) { Mesh& mesh = meshes[i]; Shader& shader = dev->get_shader(mesh.shader); Vertex_Buffer_Binding vbb[] = {{ .id = vbo, .offset = 0, - .target = shader.binding_index("mesh") + .target = mesh.mesh_binding }, {}}; Index_Buffer_Binding ibb = { .id = ibo, @@ -138,8 +190,10 @@ void Model::render( pb.depth(true, true, Depth_Mode::less); pb.shader(mesh.shader); pb.cbuffer( - shader.descriptor_binding("config_buffer"), - config + mesh.mvp_binding, + mvp, + i * sizeof(MVP_Cbuffer), + sizeof(MVP_Cbuffer) ); pb.vertex_format(shader.vf); Pipeline& pip = pb.build(); @@ -2,17 +2,23 @@ #define model_hpp #include "asset.hpp" +#include "maths.hpp" #include "video.hpp" +struct Model; struct Mesh { int offset, vbo_offset, count; - int parent; + int parent, mesh_binding, mvp_binding; + bool world_dirty; + m4f local, world; Shader_Id shader; + const m4f& get_world(Model& m); }; struct Model : public Asset { Buffer_Id vbo; Buffer_Id ibo; + Buffer_Id mvp; int mesh_count; Mesh* get_meshes() { @@ -20,11 +26,13 @@ struct Model : public Asset { } void destroy(Device* dev); + void update_transforms(); void render( Device* dev, Arena* a, Render_Pass& pass, - Buffer_Id config + const m4f& transform, + const m4f& view_projection ); }; diff --git a/src/monkey.blend b/src/monkey.blend Binary files differindex 1c456dd..3f26c50 100644 --- a/src/monkey.blend +++ b/src/monkey.blend |