diff options
Diffstat (limited to 'lighting.cpp')
-rw-r--r-- | lighting.cpp | 78 |
1 files changed, 58 insertions, 20 deletions
diff --git a/lighting.cpp b/lighting.cpp index 1eb4298..9f154cb 100644 --- a/lighting.cpp +++ b/lighting.cpp @@ -8,6 +8,8 @@ extern "C" { #include "plat.h" } +#include <random> + /* needs to match surface shader */ struct GPU_Light { v3f dir; @@ -18,18 +20,19 @@ struct GPU_Light { struct GPU_Caster { m4f projection; + m4f jittered; }; void Lighting::init(Device* dev, int w, int h) { int i; Sampler_State ss{}; - lights.init( + gpu_lights.init( dev, "Light buffer", max_lights * sizeof(GPU_Light), Buffer_Flags::storage_buffer ); - casters.init( + gpu_casters.init( dev, "Caster buffer", max_shadows * sizeof(GPU_Caster), @@ -43,13 +46,14 @@ void Lighting::init(Device* dev, int w, int h) { shadow_res, 1, 1, - max_shadows, + shadowmap_count, 0 ); zero(ss_shadows, sizeof ss_shadows); zero(ss_shadow_slices, sizeof ss_shadow_slices); + zero(occlusion, sizeof occlusion); recreate(dev, w, h); - for (i = 0; i < max_shadows; i++) { + for (i = 0; i < shadowmap_count; i++) { cameras[i] = 0; shadow_slices[i] = dev->alias_texture( shadows, @@ -80,10 +84,10 @@ void Lighting::init(Device* dev, int w, int h) { void Lighting::destroy(Device* dev, Renderer& r) { int i; - lights.destroy(dev); - casters.destroy(dev); + gpu_lights.destroy(dev); + gpu_casters.destroy(dev); dev->destroy_sampler(shadow_sampler); - for (i = 0; i < max_shadows; i++) { + for (i = 0; i < shadowmap_count; i++) { dev->destroy_texture(shadow_slices[i]); r.destroy_camera(cameras[i]); } @@ -99,6 +103,8 @@ void Lighting::destroy_ss(Device* dev) { dev->destroy_texture(ss_shadow_slices[i][j]); if (ss_shadows[i]) dev->destroy_texture(ss_shadows[i]); + if (occlusion[i]) + dev->destroy_texture(occlusion[i]); } } @@ -131,7 +137,28 @@ void Lighting::recreate(Device* dev, int w, int h) { 0, j ); + occlusion[i] = dev->create_texture( + "Occlusion buffer", + texture_format_r32f, + Texture_Flags::sampleable | Texture_Flags::colour_target, + w, + h, + 1, + 1, + 1, + 0 + ); + } +} + +Camera_Id Lighting::gm_cam(Renderer& r) { + int id = cam_count++; + Camera_Id cid = cameras[id]; + if (!cid) { + cid = r.create_camera(); + cameras[id] = cid; } + return cid; } void Lighting::write_bufs( @@ -144,6 +171,10 @@ void Lighting::write_bufs( GPU_Light* ldst = (GPU_Light*)lptr; GPU_Caster* cdst = (GPU_Caster*)cptr; int count = 0, ccount = 0; + cam_count = 0; + std::random_device dev; + std::mt19937 rng(dev()); + std::uniform_real_distribution<float> dist6(-0.01f, 0.01f); for (auto v : w.view<Sun_Light>()) { GPU_Light gl; Sun_Light& l = v.get<Sun_Light>(); @@ -155,15 +186,22 @@ void Lighting::write_bufs( gl.colour = l.colour; gl.dir = l.dir; if (l.caster && ccount < max_shadows) { + Camera* cam[2]; int cid = ccount++; - GPU_Caster& c = cdst[cid]; - Camera_Id camid = cameras[cid]; - if (!camid) - camid = r.create_camera(); - Camera& cam = r.get_camera(camid); - cam.init_shadow(l.dir, s.bound.min, s.bound.max); - c.projection = cam.get_proj() * cam.get_view(); - cameras[cid] = camid; + Caster& caster = casters[cid]; + GPU_Caster& gc = cdst[cid]; + v3f jitter( + dist6(rng), + dist6(rng), + dist6(rng) + ); + caster = Caster { gm_cam(r), gm_cam(r) }; + cam[0] = &r.get_camera(caster.reality); + cam[1] = &r.get_camera(caster.jittered); + cam[0]->init_shadow(l.dir, s.bound.min, s.bound.max); + cam[1]->init_shadow(l.dir + jitter, s.bound.min, s.bound.max); + gc.projection = cam[0]->get_proj() * cam[0]->get_view(); + gc.jittered = cam[1]->get_proj() * cam[1]->get_view(); gl.caster_id = cid; } else gl.caster_id = -1; @@ -181,10 +219,10 @@ void Lighting::update( Model_Scene& s ) { light_count = 0; - write_bufs(lights.map(dev), casters.map(dev), w, r, s); - casters.unmap(dev); - lights.unmap(dev); - lights.update(ctx); - casters.update(ctx); + write_bufs(gpu_lights.map(dev), gpu_casters.map(dev), w, r, s); + gpu_casters.unmap(dev); + gpu_lights.unmap(dev); + gpu_lights.update(ctx); + gpu_casters.update(ctx); } |