summaryrefslogtreecommitdiff
path: root/renderer.cpp
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2025-02-22 23:11:15 +1100
committerquou <quou@disroot.org>2025-02-22 23:25:45 +1100
commited5d6dfa2ed08c5a9185f3eb4ffb4deb898ed2af (patch)
tree29a6dc82b3ccd528c80978dbc5bd6ef8c925f231 /renderer.cpp
parentab9ed1ccadbd2c1b971bfbfb5ee651aa03a4a63e (diff)
move shadows to a fullscreen buffer
Diffstat (limited to 'renderer.cpp')
-rw-r--r--renderer.cpp180
1 files changed, 179 insertions, 1 deletions
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 <string.h>
+
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);
+}