#include "lighting.hpp" #include "model.hpp" #include "world.hpp" extern "C" { #include "memory.h" #include "plat.h" } /* needs to match surface shader */ struct GPU_Light { v3f dir; float brightness; v3f colour; float pad; }; void Lighting::init(Device* dev) { int i; lights.init( dev, "Light buffer", max_lights * sizeof(GPU_Light), Buffer_Flags::storage_buffer ); shadows = dev->create_texture( "Shadowmap Array", texture_format_d16, Texture_Flags::sampleable | Texture_Flags::depth_stencil_target, shadow_res, shadow_res, 1, 1, max_shadows, 0 ); for (i = 0; i < max_shadows; i++) { shadow_slices[i] = dev->alias_texture( shadows, "Shadowmap Slice", texture_format_d16, Texture_Flags::depth_stencil_target, shadow_res, shadow_res, 1, 1, 1, 0, i ); } } void Lighting::destroy(Device* dev) { int i; lights.destroy(dev); for (i = 0; i < max_shadows; i++) dev->destroy_texture(shadow_slices[i]); dev->destroy_texture(shadows); } void Lighting::write_buf(void* ptr, World& w) { GPU_Light* dst = (GPU_Light*)ptr; int count = 0, ccount = 0; for (auto v : w.view()) { GPU_Light gl; Sun_Light& l = v.get(); if (count >= max_lights) { print_war("Over light limit.\n"); return; } gl.brightness = l.brightness; gl.colour = l.colour; gl.dir = l.dir; dst[count++] = gl; if (l.caster) { Caster& c = casters[ccount++]; c.vp = m4f::identity(); } } light_count = count; caster_count = ccount; } void Lighting::update(Device* dev, Context& ctx, World& w) { light_count = 0; write_buf(lights.map(dev), w); lights.unmap(dev); lights.update(ctx); }