summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c2.cpp62
-rw-r--r--model.cpp240
-rw-r--r--model.hpp54
3 files changed, 239 insertions, 117 deletions
diff --git a/c2.cpp b/c2.cpp
index 73bbbb6..39a57c4 100644
--- a/c2.cpp
+++ b/c2.cpp
@@ -110,7 +110,9 @@ extern "C" int entrypoint() {
Texture* texture;
Texture* texture2;
Texture_Id default_texture;
- Model* monkey;
+ Model_Instance* monkey, * monkey2;
+ Model_Scene scene;
+ Camera camera;
Buffer_Id vbo, cbuf;
Sampler_Id clamped_linear;
C2* app = App::create<C2>("c2");
@@ -140,7 +142,6 @@ extern "C" int entrypoint() {
mat_loader.init(&assets, default_texture);
register_asset_loader("MODL", &model_loader);
register_asset_loader("MTRL", &mat_loader);
- monkey = (Model*)assets.load("monkey.mdl");
app->dev = dev;
shader = (Shader*)assets.load("triangle.csh");
ui_shader = (Shader*)assets.load("ui.csh");
@@ -166,6 +167,20 @@ extern "C" int entrypoint() {
vbo = upload_verts(dev);
ui->layout(app->w, app->h);
auto fps_label = ui->create_element<UI::Label>(ui->root, "");
+ scene.init(app->arena, 32, clamped_linear);
+ monkey = scene.instantiate(
+ dev,
+ (Model*)assets.load("monkey.mdl")
+ );
+ monkey2 = scene.instantiate(
+ dev,
+ (Model*)assets.load("monkey.mdl")
+ );
+ camera.init(
+ 90.0f,
+ v3f(0.0f, 0.0f, 1.0f),
+ v3f(0.0f, 0.0f, 0.0f)
+ );
while (app->running) {
Arena frame_arena;
init_arena(&frame_arena, per_frame, per_frame_memory_size);
@@ -239,13 +254,7 @@ extern "C" int entrypoint() {
Render_Pass& pass2 = pb.build_rp();
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(
+ monkey->transform = (m4f::translate(
m4f::identity(),
v3f(0.0f, 0.0f, -5.0f)
) * m4f::rotate(
@@ -253,27 +262,19 @@ extern "C" int entrypoint() {
rot,
raxis
));
- monkey->update_transforms();
- monkey->update_cbuffers(
- dev,
- transform,
- projection
- );
- ctx.debug_push("depth prepass");
- monkey->render(
- dev,
- &frame_arena,
- depth_prepass,
- clamped_linear
- );
- ctx.debug_pop();
- ctx.debug_push("forward");
- monkey->render(
- dev,
- &frame_arena,
- pass2,
- clamped_linear
- );
+ monkey2->transform = (m4f::translate(
+ m4f::identity(),
+ v3f(2.0f, 0.0f, -7.0f)
+ ) * m4f::rotate(
+ m4f::identity(),
+ rot * 2.0f,
+ v3f(1.0f, 0.0f, 0.0f)
+ ));
+ camera.asp = (float)bb.w / (float)bb.h;
+ scene.update(camera, dev);
+ ctx.debug_push("scene");
+ scene.render(dev, &frame_arena, depth_prepass, clamped_linear);
+ scene.render(dev, &frame_arena, pass2, clamped_linear);
ctx.debug_pop();
ctx.debug_push("ui");
@@ -286,6 +287,7 @@ extern "C" int entrypoint() {
dev->present();
app->end();
}
+ scene.destroy(dev);
ui->destroy();
assets.destroy();
dev->destroy_texture(default_texture);
diff --git a/model.cpp b/model.cpp
index d911ac7..6aa6510 100644
--- a/model.cpp
+++ b/model.cpp
@@ -150,24 +150,13 @@ Asset* Model_Loader::load(
Buffer_Flags::copy_dst |
Buffer_Flags::index_buffer
);
- r->mvp = dev->create_buffer(
- filename,
- sizeof(MVP_Cbuffer) * node_count,
- 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);
dev->submit(*ctx);
dev->destroy_bufferi(stage_verts);
dev->destroy_bufferi(stage_indices);
+ r->update_transforms();
return r;
}
@@ -175,8 +164,6 @@ 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);
- dev->destroy_buffer(m->mat);
}
const m4f& Mesh::get_world(Model& m) {
@@ -199,28 +186,124 @@ void Model::update_transforms() {
meshes[i].get_world(*this);
}
-void Model::update_cbuffers(
+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;
+}
+
+void Camera::init(float vfov, const v3f& f, const v3f& p) {
+ fov = vfov;
+ forward = f;
+ position = p;
+ near = 0.1f;
+ far = 1000.0f;
+ asp = 1.0f;
+}
+
+m4f Camera::get_view() const {
+ v3f up(0.0f, 1.0f, 0.0f);
+ return m4f::lookat(position, position + forward, up);
+}
+
+m4f Camera::get_proj() const {
+ return m4f::pers(fov, asp, near, far);
+}
+
+void Model_Instance::init(Device* dev, Model* model) {
+ m = model;
+ mvp = dev->create_buffer(
+ "Model instance MVP",
+ sizeof(MVP_Cbuffer) * m->mesh_count,
+ Buffer_Flags::constant_buffer |
+ Buffer_Flags::cpu_readwrite
+ );
+ mat = dev->create_buffer(
+ "Model instance material",
+ sizeof(Mat_Cbuffer) * m->mesh_count,
+ Buffer_Flags::constant_buffer |
+ Buffer_Flags::cpu_readwrite
+ );
+}
+
+void Model_Instance::destroy(Device* dev) {
+ dev->destroy_buffer(mat);
+ dev->destroy_buffer(mvp);
+}
+
+void Model_Instance::update_cbuffers(
Device* dev,
- const m4f& transform,
- const m4f& view_projection
+ const Camera& cam
) {
- int i, c = mesh_count;
- Mesh* meshes = get_meshes();
- MVP_Cbuffer* cbuffers = (MVP_Cbuffer*)dev->map_buffer(
+ int i, c = m->mesh_count;
+ Mesh* meshes = m->get_meshes();
+ MVP_Cbuffer* mvps = (MVP_Cbuffer*)dev->map_buffer(
mvp,
0,
- c * sizeof *cbuffers
+ c * sizeof *mvps
);
Mat_Cbuffer* mats = (Mat_Cbuffer*)dev->map_buffer(
mat,
0,
- c * sizeof *cbuffers
+ c * sizeof *mats
);
+ m4f view_projection = cam.get_proj();
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;
+ mvps[i].view_projection = view_projection;
+ mvps[i].model = transform * meshes[i].world;
mat.albedo[0] = sm.albedo.x;
mat.albedo[1] = sm.albedo.y;
mat.albedo[2] = sm.albedo.z;
@@ -232,26 +315,26 @@ void Model::update_cbuffers(
dev->unmap_buffer(mat);
}
-void Model::render(
+void Model_Instance::render(
Device* dev,
Arena* a,
Render_Pass& pass,
Sampler_Id sampler
) {
- int i, c = mesh_count;
- Mesh* meshes = get_meshes();
+ int i, c = m->mesh_count;
+ Mesh* meshes = m->get_meshes();
Context& ctx = dev->get_ctx();
bool depth_only = !pass.colour_count;
for (i = 0; i < c; i++) {
Mesh& mesh = meshes[i];
Shader& shader = dev->get_shader(mesh.shader);
Vertex_Buffer_Binding vbb[] = {{
- .id = vbo,
+ .id = m->vbo,
.offset = 0,
.target = mesh.mesh_binding
}, {}};
Index_Buffer_Binding ibb = {
- .id = ibo,
+ .id = m->ibo,
.offset = 0
};
Draw draw{};
@@ -288,59 +371,60 @@ void Model::render(
}
}
-void Material_Loader::init(
- Asset_Arena* texture_arena,
- Texture_Id dt
+void Model_Scene::init(
+ Arena* arena,
+ int max_instances,
+ Sampler_Id s
) {
- default_tex = dt;
- textures = texture_arena;
+ instances = (Model_Instance*)arena_alloc(arena, max_instances);
+ count = 0;
+ max = max_instances;
+ sampler = s;
}
-Asset* Material_Loader::load(
- Arena* a,
- Arena* s,
- const char* filename,
- Pack_File* f
+Model_Instance* Model_Scene::instantiate(
+ Device* dev,
+ Model* model
) {
- 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;
+ Model_Instance* instance = &instances[count++];
+ assert(count <= max);
+ instance->init(dev, model);
+ return instance;
}
-void Material_Loader::unload(Asset* a) {
- (void)a;
+void Model_Scene::uninstantiate(
+ Device* dev,
+ Model_Instance* model
+) {
+ int idx = model - instances;
+ int last = count - 1;
+ model->destroy(dev);
+ instances[idx] = instances[last];
+ count = last;
+}
+
+void Model_Scene::update(const Camera& cam, Device* dev) {
+ int i;
+ Model_Instance* instance = instances;
+ for (i = 0; i < count; i++, instance++)
+ instance->update_cbuffers(dev, cam);
+}
+
+void Model_Scene::render(
+ Device* dev,
+ Arena* a,
+ Render_Pass& pass,
+ Sampler_Id sampler
+) {
+ int i;
+ Model_Instance* instance = instances;
+ for (i = 0; i < count; i++, instance++)
+ instance->render(dev, a, pass, sampler);
+}
+
+void Model_Scene::destroy(Device* dev) {
+ int i;
+ Model_Instance* instance = instances;
+ for (i = 0; i < count; i++, instance++)
+ instance->destroy(dev);
}
diff --git a/model.hpp b/model.hpp
index 0dd8c43..53fb0fb 100644
--- a/model.hpp
+++ b/model.hpp
@@ -27,7 +27,7 @@ struct Mesh {
int offset, vbo_offset, count;
int parent, mesh_binding, mvp_binding, mat_binding;
bool world_dirty;
- m4f local, world;
+ m4f world, local;
Shader_Id shader;
Material* material;
const m4f& get_world(Model& m);
@@ -36,8 +36,6 @@ struct Mesh {
struct Model : public Asset {
Buffer_Id vbo;
Buffer_Id ibo;
- Buffer_Id mvp;
- Buffer_Id mat;
int mesh_count;
Mesh* get_meshes() {
@@ -51,12 +49,6 @@ struct Model : public Asset {
const m4f& transform,
const m4f& view_projection
);
- void render(
- Device* dev,
- Arena* a,
- Render_Pass& pass,
- Sampler_Id sampler
- );
};
struct Model_Loader : public Asset_Loader {
@@ -85,4 +77,48 @@ struct Material_Loader : public Asset_Loader {
void unload(Asset* a) override;
};
+struct Camera {
+ float fov, near, far, asp;
+ v3f forward, position;
+ void init(float vfov, const v3f& f, const v3f& p);
+ m4f get_view() const;
+ m4f get_proj() const;
+};
+
+struct Model_Instance {
+ Buffer_Id mvp;
+ Buffer_Id mat;
+ m4f transform;
+ Model* m;
+
+ void init(Device* dev, Model* model);
+ void destroy(Device* dev);
+ void update_cbuffers(Device* dev, const Camera& cam);
+ void render(
+ Device* dev,
+ Arena* a,
+ Render_Pass& pass,
+ Sampler_Id sampler
+ );
+};
+
+struct Model_Scene {
+ Model_Instance* instances;
+ int count, max;
+ Sampler_Id sampler;
+
+ Model_Instance* instantiate(Device* dev, Model* model);
+ void uninstantiate(Device* dev, Model_Instance* model);
+ void destroy(Device* dev);
+
+ void init(Arena* arena, int max_instances, Sampler_Id s);
+ void update(const Camera& cam, Device* dev);
+ void render(
+ Device* dev,
+ Arena* a,
+ Render_Pass& pass,
+ Sampler_Id sampler
+ );
+};
+
#endif