From ed5d6dfa2ed08c5a9185f3eb4ffb4deb898ed2af Mon Sep 17 00:00:00 2001 From: quou Date: Sat, 22 Feb 2025 23:11:15 +1100 Subject: move shadows to a fullscreen buffer --- renderer.cpp | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 179 insertions(+), 1 deletion(-) (limited to 'renderer.cpp') diff --git a/renderer.cpp b/renderer.cpp index d8c4895..ffc0a3c 100644 --- a/renderer.cpp +++ b/renderer.cpp @@ -5,10 +5,23 @@ extern "C" { #include "memory.h" } +#include + struct VP_Cbuffer { m4f view_projection; }; +struct TS_Cbuffer { + m4f inv_view; + m4f inv_proj; + m4f prev_vp; +}; + +struct TS_Caster_Config { + int index; + char pad[60]; +}; + struct Global_Cbuffer { v3f camera_pos; int light_count; @@ -36,7 +49,22 @@ void init_drawlist( ); } -void Renderer::init(Arena* arena, Device* d) { +void Renderer::make_ts_sampler(Device* d) { + Sampler_State s{}; + s.min = Filter_Mode::point; + s.mag = Filter_Mode::point; + s.mip = Filter_Mode::point; + s.address_u = Address_Mode::border; + s.address_v = Address_Mode::border; + s.border[0] = 0.0f; + ts_sampler = d->create_sampler("temporal shadow sampler", s); +} + +void Renderer::init( + Arena* arena, + Device* d, + Asset_Arena& assets +) { int i; auto id = [&](int did, int cap) { init_drawlist(&drawlists[did], d, arena, cap); @@ -52,6 +80,37 @@ void Renderer::init(Arena* arena, Device* d) { sizeof(Global_Cbuffer), Buffer_Flags::constant_buffer ); + ts_config.init( + d, + "Temporal shadow cbuffer", + sizeof(TS_Cbuffer), + Buffer_Flags::constant_buffer + ); + ts_config2.init( + d, + "Temporal shadow casters", + sizeof(TS_Caster_Config) * Lighting::max_shadows, + Buffer_Flags::constant_buffer + ); + quad.init(d); + ts_shader = (Shader*)assets.load("ts.csh"); + ts_shadowmap_binding = ts_shader->descriptor_binding("shadowmaps"); + ts_depthmap_binding = ts_shader->descriptor_binding("depthmap"); + ts_prev_binding = ts_shader->descriptor_binding("previous"); + ts_vert_binding = ts_shader->binding_index("verts"); + ts_config_binding = ts_shader->descriptor_binding("config"); + ts_caster_config_binding = ts_shader->descriptor_binding("caster_config"); + ts_casters_binding = ts_shader->descriptor_binding("casters"); + ts_globals_binding = ts_shader->descriptor_binding("globals"); + assert(ts_shadowmap_binding >= 0); + assert(ts_depthmap_binding >= 0); + assert(ts_prev_binding >= 0); + assert(ts_vert_binding >= 0); + assert(ts_config_binding >= 0); + assert(ts_caster_config_binding >= 0); + assert(ts_casters_binding >= 0); + assert(ts_globals_binding >= 0); + make_ts_sampler(d); frame = 0; } @@ -60,6 +119,10 @@ void Renderer::destroy(Device* d) { for (i = 0; i < drawlist_count; i++) drawlists[i].vp.destroy(d); globals.destroy(d); + ts_config.destroy(d); + ts_config2.destroy(d); + quad.destroy(d); + d->destroy_sampler(ts_sampler); } void Renderer::set_camera(Camera_Id cam, int drawlist) { @@ -81,6 +144,7 @@ void Drawlist::render( vpc->view_projection = cam.get_proj() * cam.get_view(); vp.unmap(dev); vp.update(dev->get_ctx()); + res.shadows = l->ss_shadows[r.frame & 1]; res.sampler = r.clamped_linear; res.env_cubemap = r.env_cubemap; res.vp = vp.gpuonly; @@ -106,6 +170,67 @@ void Renderer::update_globals( globals.update(ctx); } +void Renderer::temporal_shadows( + Device* dev, + Context& ctx, + const Lighting* l, + Pipeline_Builder& pb +) { + int i, c = l->caster_count; + Camera& cam = get_camera(drawlists[FORWARD].camera); + TS_Cbuffer* cbuf = (TS_Cbuffer*)ts_config.map(dev); + TS_Caster_Config* casters = (TS_Caster_Config*)ts_config.map(dev); + for (i = 0; i < c; i++) { + casters[i].index = i; + } + cbuf->inv_view = cam.get_view().inverse(); + cbuf->inv_proj = cam.get_proj().inverse(); + ts_config.unmap(dev); + ts_config2.unmap(dev); + ctx.debug_push("temporal shadows"); + ts_config.update(ctx); + ts_config2.update(ctx); + for (i = 0; i < c; i++) { + int ind = frame & 1; + auto& pass = pb + .begin_rp() + .rp_target(l->ss_shadow_slices[ind][i], Clear_Mode::discard) + .build_rp(); + auto& pip = pb + .begin() + .shader(ts_shader->id) + .vertex_format(ts_shader->vf) + .texture( + ts_shadowmap_binding, + l->shadows, + l->shadow_sampler) + .texture( + ts_prev_binding, + l->ss_shadow_slices[!ind][i], + ts_sampler) + .texture( + ts_depthmap_binding, + dev->get_depth_target(), + ts_sampler) + .cbuffer(ts_config_binding, ts_config.gpuonly) + .cbuffer( + ts_caster_config_binding, + ts_config2.gpuonly, + i * sizeof(TS_Caster_Config), + sizeof(TS_Caster_Config)) + .cbuffer(ts_globals_binding, globals.gpuonly) + .sbuffer(ts_casters_binding, l->casters.gpuonly) + .build(); + quad.render( + ctx, + pip, + pass, + ts_vert_binding + ); + } + ctx.debug_pop(); +} + void Renderer::render( Device* dev, Arena* a, Texture_Id hdr_target, @@ -154,6 +279,8 @@ void Renderer::render( } ctx.debug_pop(); + temporal_shadows(dev, ctx, l, pb); + ctx.debug_push("forward"); drawlists[FORWARD].render(*this, dev, a, l, forward_pass, 0); ctx.debug_pop(); @@ -210,3 +337,54 @@ void Renderer::setcam(int did, Camera_Id cam) { assert(cam.index); drawlists[did].camera = cam; } + +void Fullscreen_Quad::init(Device* d) { + float verts[] = { + -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 3.0f, 0.0f, 2.0f, + 3.0f, -1.0f, 2.0f, 0.0f + }; + Buffer_Id stage; + void* mem; + stage = d->create_buffer( + "sky vb stage", + sizeof verts, + Buffer_Flags::cpu_readwrite | + Buffer_Flags::copy_src + ); + mem = d->map_buffer(stage, 0, sizeof verts); + memcpy(mem, verts, sizeof verts); + d->unmap_buffer(stage); + vb = d->create_buffer( + "fullscreen quad", + sizeof verts, + Buffer_Flags::copy_dst | + Buffer_Flags::vertex_buffer + ); + Context& ctx = d->acquire(); + ctx.copy(vb, stage); + d->submit(ctx); + d->destroy_bufferi(stage); +} + +void Fullscreen_Quad::destroy(Device* d) { + d->destroy_buffer(vb); +} + +void Fullscreen_Quad::render( + Context& ctx, + Pipeline& pip, + Render_Pass& pass, + int bind +) { + Vertex_Buffer_Binding vbb[] = {{ + .id = vb, + .offset = 0, + .target = bind + }, {}}; + Draw draw{}; + draw.verts = vbb; + draw.vertex_count = 3; + draw.instance_count = 1; + ctx.submit(draw, pip, pass); +} -- cgit v1.2.3-54-g00ecf