summaryrefslogtreecommitdiff
path: root/renderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'renderer.cpp')
-rw-r--r--renderer.cpp169
1 files changed, 169 insertions, 0 deletions
diff --git a/renderer.cpp b/renderer.cpp
new file mode 100644
index 0000000..2d28ceb
--- /dev/null
+++ b/renderer.cpp
@@ -0,0 +1,169 @@
+#include "model.hpp"
+#include "renderer.hpp"
+
+extern "C" {
+#include "memory.h"
+}
+
+struct VP_Cbuffer {
+ m4f view_projection;
+};
+
+void init_drawlist(
+ Drawlist* l,
+ Device* d,
+ Arena* a,
+ int cap
+) {
+ l->count = 0;
+ l->cap = cap;
+ l->camera = 0;
+ l->vp.init(
+ d,
+ "Drawlist cbuffer",
+ sizeof(VP_Cbuffer),
+ Buffer_Flags::constant_buffer
+ );
+ l->models = (Model_Instance**)arena_alloc(
+ a,
+ cap * sizeof *l->models
+ );
+}
+
+void Renderer::init(Arena* arena, Device* d) {
+ int i;
+ auto id = [&](int did, int cap) {
+ init_drawlist(&drawlists[did], d, arena, cap);
+ };
+ id(FORWARD, 512);
+ for (i = SHADOW_MAP_START; i < SHADOW_MAP_END; i++)
+ id(i, 512);
+ camera_count = 1;
+ cameras.init();
+}
+
+void Renderer::destroy(Device* d) {
+ int i;
+ for (i = 0; i < drawlist_count; i++)
+ drawlists[i].vp.destroy(d);
+}
+
+void Renderer::set_camera(Camera_Id cam, int drawlist) {
+ drawlists[drawlist].camera = cam;
+}
+
+void Drawlist::render(
+ const Renderer& r,
+ Device* dev,
+ Arena* a,
+ const Lighting* l,
+ Render_Pass& pass
+) {
+ int i, c = count;
+ const Camera& cam = r.get_camera(camera);
+ Model_Resources res;
+ VP_Cbuffer* vpc = (VP_Cbuffer*)vp.map(dev);
+ vpc->view_projection = cam.get_proj() * cam.get_view();
+ vp.unmap(dev);
+ vp.update(dev->get_ctx());
+ res.sampler = r.clamped_linear;
+ res.env_cubemap = r.env_cubemap;
+ res.vp = vp.gpuonly;
+ for (i = 0; i < c; i++) {
+ models[i]->render(dev, a, pass, l, res);
+ }
+}
+
+void Renderer::render(
+ Device* dev,
+ Arena* a,
+ Texture_Id hdr_target,
+ const Lighting* l
+) {
+ int i, j;
+ Pipeline_Builder pb(a, dev);
+ Context& ctx = dev->get_ctx();
+
+ Render_Pass& depth_prepass = pb
+ .begin_rp()
+ .rp_depth_target(dev->get_depth_target(), 1.0f)
+ .build_rp();
+ Render_Pass& forward_pass = pb
+ .begin_rp()
+ .rp_target(hdr_target, Clear_Mode::restore)
+ .rp_depth_target(dev->get_depth_target(), Clear_Mode::restore)
+ .build_rp();
+ Render_Pass* shadow_passes[Lighting::max_shadows];
+ for (i = 0; i < Lighting::max_shadows; i++) {
+ shadow_passes[i] = &pb
+ .begin_rp()
+ .rp_depth_target(l->shadow_slices[i], 1.0f)
+ .build_rp();
+ }
+
+ ctx.debug_push("depth prepass");
+ drawlists[FORWARD].render(*this, dev, a, l, depth_prepass);
+ ctx.debug_pop();
+
+ ctx.debug_push("shadow maps");
+ for (
+ i = SHADOW_MAP_START, j = 0;
+ i < SHADOW_MAP_END && j < l->caster_count;
+ i++, j++
+ ) {
+ ctx.debug_push("shadow map");
+ drawlists[i].render(*this, dev, a, l, *shadow_passes[j]);
+ ctx.debug_pop();
+ }
+ ctx.debug_pop();
+
+ ctx.debug_push("forward");
+ drawlists[FORWARD].render(*this, dev, a, l, forward_pass);
+ ctx.debug_pop();
+}
+
+void Renderer::add_model(int drawlist, Model_Instance* m) {
+ Drawlist& d = drawlists[drawlist];
+ assert(d.count < d.cap);
+ if (d.count >= d.cap) {
+ print_war("Drawlist is full.\n");
+ return;
+ }
+ d.models[d.count++] = m;
+}
+
+void Renderer::rem_model(int drawlist, Model_Instance* m) {
+ int i;
+ Drawlist& d = drawlists[drawlist];
+ for (i = d.count - 1; i >= 0; i--)
+ if (d.models[i] == m)
+ d.models[i] = d.models[--d.count];
+ assert(0);
+}
+
+void Renderer::default_model(Model_Instance* m) {
+ int i;
+ for (i = 0; i < drawlist_count; i++)
+ add_model(i, m);
+}
+
+Camera_Id Renderer::create_camera() {
+ Camera_Id id(camera_count++);
+ Camera cam;
+ cameras.set(id, cam);
+ return id;
+}
+
+Camera& Renderer::get_camera(Camera_Id id) {
+ assert(id.index);
+ return cameras[id];
+}
+
+const Camera& Renderer::get_camera(Camera_Id id) const {
+ assert(id.index);
+ return cameras[id];
+}
+
+void Renderer::destroy_camera(Camera_Id cam) {
+ cameras.remove(cam);
+}