diff options
Diffstat (limited to 'renderer.cpp')
-rw-r--r-- | renderer.cpp | 169 |
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); +} |