diff --git a/CMakeLists.txt b/CMakeLists.txt
index 90c54cfa69095fc41300065ab26ab22d7215eef0..d68b269f36170faf92d5ba6d89b0eac9d060bbca 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -565,6 +565,28 @@ message("=======================================================================
         target_link_libraries(lava-spawn lava::demo)
 
         set_property(TARGET lava-spawn PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${PROJECT_BINARY_DIR}")
+
+        message("> lava-light")
+
+        set(LIGHT_SHADERS
+                res/light/gbuffer.frag
+                res/light/gbuffer.vert
+                res/light/lighting.frag
+                res/light/lighting.vert
+                res/light/data.inc
+                )
+
+        add_executable(lava-light 
+                ${LIBLAVA_DEMO_DIR}/light.cpp
+                ${LIGHT_SHADERS}
+                )
+
+        source_group("Shader Files" FILES ${LIGHT_SHADERS})
+
+        set_target_properties(lava-light PROPERTIES FOLDER "lava-demo")
+        target_link_libraries(lava-light lava::demo)
+
+        set_property(TARGET lava-light PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${PROJECT_BINARY_DIR}")
 endif()
 
 option(LIBLAVA_TEMPLATE "Enable Template" TRUE)
diff --git a/liblava-demo/light.cpp b/liblava-demo/light.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a1d4f27c2d6838d2b7569cb5853618adefe82217
--- /dev/null
+++ b/liblava-demo/light.cpp
@@ -0,0 +1,460 @@
+// file      : liblava-demo/light.cpp
+// copyright : Copyright (c) 2018-present, Lava Block OÜ and contributors
+// license   : MIT; see accompanying LICENSE file
+
+#include <imgui.h>
+#include <demo.hpp>
+
+using namespace lava;
+
+// structs for interfacing with shaders
+namespace glsl
+{
+    using namespace glm;
+    using uint = uint32_t;
+#include "res/light/data.inc"
+}
+
+glsl::UboData g_ubo;
+
+struct gbuffer_attachment {
+    enum type : uint32_t {
+        albedo = 0,
+        normal,
+        metallic_roughness,
+        depth,
+        count
+    };
+
+    VkFormats requested_formats;
+    VkImageUsageFlags usage;
+    image::ptr image_handle;
+    attachment::ptr renderpass_attachment;
+    VkAttachmentReference subpass_reference;
+
+    bool create(uint32_t index);
+};
+
+using attachment_array = std::array<gbuffer_attachment, gbuffer_attachment::count>;
+attachment_array g_attachments = {
+    gbuffer_attachment{ { VK_FORMAT_R8G8B8A8_UNORM }, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT },
+    gbuffer_attachment{ { VK_FORMAT_R16G16B16A16_SFLOAT }, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT },
+    gbuffer_attachment{ { VK_FORMAT_R16G16_SFLOAT }, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT },
+    gbuffer_attachment{ { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D16_UNORM }, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT },
+};
+
+using light_array = std::array<glsl::LightData, 3>;
+const light_array g_lights = {
+    glsl::LightData{ { 2.0f, 2.0f, 2.5f }, 10.0f, { 30.0f, 10.0f, 10.0f } },
+    glsl::LightData{ { -2.0f, -2.0f, -0.5f }, 10.0f, { 10.0f, 30.0f, 10.0f } },
+    glsl::LightData{ { 0.0f, 0.0f, -1.5f }, 10.0f, { 10.0f, 10.0f, 30.0f } }
+};
+
+app* g_app = nullptr;
+
+render_pass::ptr create_gbuffer_renderpass(attachment_array& attachments);
+
+int main(int argc, char* argv[]) {
+    app app("lava light", { argc, argv });
+    if (!app.setup())
+        return error::not_ready;
+
+    target_callback resize_callback;
+    app.target->add_callback(&resize_callback);
+
+    g_app = &app;
+
+    // create global immutable resources
+    // destroyed in app.add_run_end
+
+    mesh::ptr object = create_mesh(app.device, mesh_type::quad);
+    if (!object)
+        return error::create_failed;
+
+    using object_array = std::array<mat4, 2>;
+    object_array object_instances;
+
+    texture::ptr tex_normal = load_texture(app.device, "light/normal.png");
+    texture::ptr tex_roughness = load_texture(app.device, "light/roughness.png");
+    if (!tex_normal || !tex_roughness)
+        return error::create_failed;
+
+    app.staging.add(tex_normal);
+    app.staging.add(tex_roughness);
+
+    buffer ubo_buffer;
+    if (!ubo_buffer.create_mapped(app.device, nullptr, sizeof(g_ubo), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT))
+        return error::create_failed;
+
+    buffer light_buffer;
+    if (!light_buffer.create_mapped(app.device, g_lights.data(), sizeof(g_lights), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))
+        return error::create_failed;
+
+    const VkSamplerCreateInfo sampler_info = {
+        .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+        .magFilter = VK_FILTER_NEAREST,
+        .minFilter = VK_FILTER_NEAREST,
+        .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST
+    };
+    VkSampler sampler;
+    if (!app.device->vkCreateSampler(&sampler_info, &sampler))
+        return error::create_failed;
+
+    // pipeline-specific resources
+    // created in app.on_create, destroyed in app.on_destroy
+
+    descriptor::pool descriptor_pool;
+
+    render_pass::ptr gbuffer_renderpass = make_render_pass(app.device);
+    descriptor::ptr gbuffer_set_layout = make_descriptor();
+    pipeline_layout::ptr gbuffer_pipeline_layout = make_pipeline_layout();
+    graphics_pipeline::ptr gbuffer_pipeline = make_graphics_pipeline(app.device);
+    VkDescriptorSet gbuffer_set = VK_NULL_HANDLE;
+
+    descriptor::ptr lighting_set_layout = make_descriptor();
+    pipeline_layout::ptr lighting_pipeline_layout = make_pipeline_layout();
+    graphics_pipeline::ptr lighting_pipeline = make_graphics_pipeline(app.device);
+    VkDescriptorSet lighting_set = VK_NULL_HANDLE;
+
+    app.on_create = [&]() {
+        const VkDescriptorPoolSizes pool_sizes = {
+            { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1 * 2 }, // one uniform buffer for each pass (gbuffer + lighting)
+            { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1 }, // light buffer
+            { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 /* normal + roughness texture */ + g_attachments.size() },
+        };
+        constexpr ui32 max_sets = 2; // one for each pass
+        if (!descriptor_pool.create(app.device, pool_sizes, max_sets))
+            return false;
+
+        // gbuffer pass
+
+        gbuffer_set_layout->add_binding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
+        gbuffer_set_layout->add_binding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
+        gbuffer_set_layout->add_binding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
+        if (!gbuffer_set_layout->create(app.device))
+            return false;
+        gbuffer_set = gbuffer_set_layout->allocate(descriptor_pool.get());
+        if (!gbuffer_set)
+            return false;
+
+        std::vector<VkWriteDescriptorSet> gbuffer_write_sets;
+        for (const descriptor::binding::ptr& binding : gbuffer_set_layout->get_bindings()) {
+            const VkDescriptorSetLayoutBinding& info = binding->get();
+            gbuffer_write_sets.push_back({ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+                                           .dstSet = gbuffer_set,
+                                           .dstBinding = info.binding,
+                                           .descriptorCount = info.descriptorCount,
+                                           .descriptorType = info.descriptorType });
+        }
+
+        gbuffer_write_sets[0].pBufferInfo = ubo_buffer.get_descriptor_info();
+        gbuffer_write_sets[1].pImageInfo = tex_normal->get_descriptor_info();
+        gbuffer_write_sets[2].pImageInfo = tex_roughness->get_descriptor_info();
+
+        app.device->vkUpdateDescriptorSets(gbuffer_write_sets.size(), gbuffer_write_sets.data());
+
+        gbuffer_pipeline_layout->add(gbuffer_set_layout);
+        gbuffer_pipeline_layout->add_range({ VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(glsl::PushConstantData) });
+        if (!gbuffer_pipeline_layout->create(app.device))
+            return false;
+
+        const VkPipelineColorBlendAttachmentState gbuffer_blend_state = {
+            .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
+        };
+
+        if (!gbuffer_pipeline->add_shader(file_data("light/gbuffer.vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT))
+            return false;
+        if (!gbuffer_pipeline->add_shader(file_data("light/gbuffer.fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT))
+            return false;
+        for (size_t i = 0; i < g_attachments.size() - 1; i++) {
+            gbuffer_pipeline->add_color_blend_attachment(gbuffer_blend_state);
+        }
+        gbuffer_pipeline->set_depth_test_and_write(true, true);
+        gbuffer_pipeline->set_depth_compare_op(VK_COMPARE_OP_LESS);
+        gbuffer_pipeline->set_rasterization_cull_mode(VK_CULL_MODE_NONE);
+        gbuffer_pipeline->set_vertex_input_binding({ 0, sizeof(vertex), VK_VERTEX_INPUT_RATE_VERTEX });
+        gbuffer_pipeline->set_vertex_input_attributes({
+            { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, to_ui32(offsetof(vertex, position)) },
+            { 1, 0, VK_FORMAT_R32G32_SFLOAT, to_ui32(offsetof(vertex, uv)) },
+            { 2, 0, VK_FORMAT_R32G32B32_SFLOAT, to_ui32(offsetof(vertex, normal)) },
+        });
+        gbuffer_pipeline->set_layout(gbuffer_pipeline_layout);
+        gbuffer_pipeline->set_auto_size(true);
+
+        gbuffer_pipeline->on_process = [&](VkCommandBuffer cmd_buf) {
+            scoped_label label(cmd_buf, "gbuffer");
+
+            gbuffer_pipeline_layout->bind(cmd_buf, gbuffer_set);
+            object->bind(cmd_buf);
+
+            for (size_t i = 0; i < object_instances.size(); i++) {
+                const glsl::PushConstantData pc = {
+                    .model = object_instances[i],
+                    .color = v3(1.0f),
+                    .metallic = float(i % 2),
+                    .enableNormalMapping = 1 - (i % 2)
+                };
+                app.device->call().vkCmdPushConstants(cmd_buf, gbuffer_pipeline_layout->get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
+                                                      0, sizeof(pc), &pc);
+                object->draw(cmd_buf);
+            }
+        };
+
+        gbuffer_renderpass = create_gbuffer_renderpass(g_attachments);
+        gbuffer_renderpass->add_front(gbuffer_pipeline);
+
+        // lighting pass
+
+        for (size_t i = 0; i < g_attachments.size(); i++) {
+            lighting_set_layout->add_binding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
+        }
+        lighting_set_layout->add_binding(g_attachments.size() + 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
+        lighting_set_layout->add_binding(g_attachments.size() + 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
+        if (!lighting_set_layout->create(app.device))
+            return false;
+        lighting_set = lighting_set_layout->allocate(descriptor_pool.get());
+        if (!lighting_set)
+            return false;
+
+        lighting_pipeline_layout->add(lighting_set_layout);
+        if (!lighting_pipeline_layout->create(app.device))
+            return false;
+
+        const VkPipelineColorBlendAttachmentState lighting_blend_state = {
+            .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
+        };
+
+        if (!lighting_pipeline->add_shader(file_data("light/lighting.vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT))
+            return false;
+        if (!lighting_pipeline->add_shader(file_data("light/lighting.fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT))
+            return false;
+        lighting_pipeline->add_color_blend_attachment(lighting_blend_state);
+        lighting_pipeline->set_rasterization_cull_mode(VK_CULL_MODE_NONE);
+        lighting_pipeline->set_layout(lighting_pipeline_layout);
+        lighting_pipeline->set_auto_size(true);
+
+        lighting_pipeline->on_process = [&](VkCommandBuffer cmd_buf) {
+            scoped_label label(cmd_buf, "lighting");
+
+            // run a fullscreen pass to calculate lighting, the shader loops over all lights
+            // - this is NOT very performant, but simplifies the demo
+            // - in a proper deferred renderer you most likely want to:
+            //     - render light geometries (e.g. spheres) while depth testing against the gbuffer depth
+            //     - use some kind of spatial acceleration structure for lights
+
+            lighting_pipeline_layout->bind(cmd_buf, lighting_set);
+            app.device->call().vkCmdDraw(cmd_buf, 3, 1, 0, 0);
+        };
+
+        // use lava's default backbuffer renderpass
+        render_pass::ptr lighting_renderpass = app.shading.get_pass();
+        lighting_renderpass->add_front(lighting_pipeline);
+
+        // the resize callback creates the gbuffer images and renderpass, call it once manually
+        if (!resize_callback.on_created({}, { { 0, 0 }, app.target->get_size() }))
+            return false;
+
+        // renderpasses have been created at this point, actually create the pipelines
+        if (!gbuffer_pipeline->create(gbuffer_renderpass->get()))
+            return false;
+        if (!lighting_pipeline->create(lighting_renderpass->get()))
+            return false;
+
+        return true;
+    };
+
+    app.on_process = [&](VkCommandBuffer cmd_buf, index frame) {
+        scoped_label label(cmd_buf, "on_process");
+
+        // start custom renderpass, run on_process() for each pipeline added to the renderpass
+        gbuffer_renderpass->process(cmd_buf);
+    };
+
+    app.on_update = [&](delta dt) {
+        float seconds = to_delta(app.get_running_time());
+        constexpr float distance = 1.25f;
+        const float left = -distance * (object_instances.size() - 1) * 0.5f;
+        for (size_t i = 0; i < object_instances.size(); i++) {
+            float x = left + distance * i;
+            v3 axis = v3(0.0f);
+            axis[i % 3] = 1.0f;
+            mat4 model = mat4(1.0f);
+            model = glm::translate(model, { x, 0.0f, 0.0f });
+            model = glm::rotate(model, glm::radians(std::fmod(seconds * 45.0f, 360.0f)), axis);
+            model = glm::scale(model, { 0.5f, 0.5f, 0.5f });
+            object_instances[i] = model;
+        }
+
+        return true;
+    };
+
+    // handle backbuffer resize
+
+    resize_callback.on_created = [&](VkAttachmentsRef, rect area) {
+        // update uniform buffer
+        g_ubo.camPos = { 0.0f, 0.0f, -1.25f };
+        g_ubo.lightCount = g_lights.size();
+        g_ubo.view = glm::lookAtLH(g_ubo.camPos, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f });
+        g_ubo.projection = perspective_matrix(area.get_size(), 90.0f, 3.0f);
+        g_ubo.invProjection = glm::inverse(g_ubo.projection);
+        g_ubo.resolution = area.get_size();
+        *(decltype(g_ubo)*) ubo_buffer.get_mapped_data() = g_ubo;
+
+        // (re-)create gbuffer attachments and collect views for framebuffer creation
+        VkImageViews views;
+        for (gbuffer_attachment& att : g_attachments) {
+            if (!att.image_handle->create(app.device, area.get_size()))
+                return false;
+            views.push_back(att.image_handle->get_view());
+        }
+
+        // update lighting descriptor set with new gbuffer image handles
+        std::vector<VkWriteDescriptorSet> lighting_write_sets;
+        for (const descriptor::binding::ptr& binding : lighting_set_layout->get_bindings()) {
+            const VkDescriptorSetLayoutBinding& info = binding->get();
+            lighting_write_sets.push_back({ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+                                            .dstSet = lighting_set,
+                                            .dstBinding = info.binding,
+                                            .descriptorCount = info.descriptorCount,
+                                            .descriptorType = info.descriptorType });
+        }
+
+        std::array<VkDescriptorImageInfo, g_attachments.size()> lighting_images;
+        for (size_t i = 0; i < g_attachments.size(); i++) {
+            lighting_images[i] = {
+                .sampler = sampler,
+                .imageView = g_attachments[i].image_handle->get_view(),
+                .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+            };
+            lighting_write_sets[i].pImageInfo = &lighting_images[i];
+        }
+        lighting_write_sets[g_attachments.size() + 0].pBufferInfo = ubo_buffer.get_descriptor_info();
+        lighting_write_sets[g_attachments.size() + 1].pBufferInfo = light_buffer.get_descriptor_info();
+
+        app.device->vkUpdateDescriptorSets(lighting_write_sets.size(), lighting_write_sets.data());
+
+        // create framebuffer (and renderpass if necessary)
+        if (gbuffer_renderpass->get() == VK_NULL_HANDLE)
+            return gbuffer_renderpass->create({ views }, area);
+        else
+            return gbuffer_renderpass->on_created({ views }, area);
+    };
+
+    resize_callback.on_destroyed = [&]() {
+        app.device->wait_for_idle();
+        // destroy framebuffer
+        gbuffer_renderpass->on_destroyed();
+        // destroy gbuffer attachments
+        for (gbuffer_attachment& att : g_attachments) {
+            att.image_handle->destroy();
+        }
+    };
+
+    app.imgui.on_draw = [&]() {
+        ImGui::SetNextWindowPos(ImVec2(30, 30), ImGuiCond_FirstUseEver);
+        ImGui::SetNextWindowSize(ImVec2(262, 262), ImGuiCond_FirstUseEver);
+
+        ImGui::Begin(app.get_name());
+
+        app.draw_about();
+
+        ImGui::End();
+    };
+
+    app.on_destroy = [&]() {
+        app.target->remove_callback(&resize_callback);
+        resize_callback.on_destroyed();
+
+        lighting_pipeline->destroy();
+        lighting_pipeline_layout->destroy();
+        lighting_set_layout->destroy();
+
+        gbuffer_pipeline->destroy();
+        gbuffer_pipeline_layout->destroy();
+        gbuffer_set_layout->destroy();
+        gbuffer_renderpass->destroy();
+
+        descriptor_pool.destroy();
+    };
+
+    app.add_run_end([&]() {
+        app.device->vkDestroySampler(sampler);
+        sampler = VK_NULL_HANDLE;
+
+        light_buffer.destroy();
+        ubo_buffer.destroy();
+
+        tex_roughness->destroy();
+        tex_normal->destroy();
+
+        object->destroy();
+    });
+
+    return app.run();
+}
+
+bool gbuffer_attachment::create(uint32_t index) {
+    usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
+    std::optional<VkFormat> format = get_supported_format(g_app->device->get_vk_physical_device(), requested_formats, usage);
+    if (!format.has_value())
+        return false;
+
+    image_handle = make_image(*format);
+    image_handle->set_usage(usage);
+
+    renderpass_attachment = make_attachment(*format);
+    renderpass_attachment->set_op(VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE);
+    renderpass_attachment->set_stencil_op(VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE);
+    renderpass_attachment->set_layouts(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+
+    subpass_reference.attachment = index;
+    subpass_reference.layout = (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
+                                   ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+                                   : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+    return true;
+}
+
+render_pass::ptr create_gbuffer_renderpass(attachment_array& attachments) {
+    VkClearValues clear_values(attachments.size(), { .color = { 0.0f, 0.0f, 0.0f, 1.0f } });
+    clear_values[gbuffer_attachment::depth] = { .depthStencil = { 1.0f, 0 } };
+
+    render_pass::ptr pass = make_render_pass(g_app->device);
+    pass->set_clear_values(clear_values);
+
+    VkAttachmentReferences color_attachments;
+    for (uint32_t i = 0; i < gbuffer_attachment::count; i++) {
+        if (!attachments[i].create(i))
+            return nullptr;
+        pass->add(attachments[i].renderpass_attachment);
+        if (i != gbuffer_attachment::depth)
+            color_attachments.push_back(attachments[i].subpass_reference);
+    }
+
+    subpass::ptr sub = make_subpass();
+    sub->set_color_attachments(color_attachments);
+    sub->set_depth_stencil_attachment(attachments[gbuffer_attachment::depth].subpass_reference);
+    pass->add(sub);
+
+    subpass_dependency::ptr dependency = make_subpass_dependency(VK_SUBPASS_EXTERNAL, 0);
+    // wait for previous fragment shader to finish reading before clearing attachments
+    dependency->set_stage_mask(
+        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+        VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
+    // we need a memory barrier because this isn't a standard write-after-read hazard
+    // subpass deps have an implicit attachment layout transition, so the dst access mask must be correct
+    dependency->set_access_mask(0,
+                                VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
+    pass->add(dependency);
+
+    dependency = make_subpass_dependency(pass->get_subpass_count() - 1, VK_SUBPASS_EXTERNAL);
+    // don't run any fragment shader (sample attachments) before we're done writing to attachments
+    dependency->set_stage_mask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+                               VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+    // make attachment writes visible to subsequent reads
+    dependency->set_access_mask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+                                VK_ACCESS_SHADER_READ_BIT);
+    pass->add(dependency);
+
+    return pass;
+}
diff --git a/liblava/app/imgui.cpp b/liblava/app/imgui.cpp
index cd0663bda94836d7c79875d1f80044f2eda039c7..074544b8ef372ab2468d151ca0852a40ece48bc2 100644
--- a/liblava/app/imgui.cpp
+++ b/liblava/app/imgui.cpp
@@ -280,75 +280,11 @@ namespace lava {
 #undef MAP_ANALOG
 
     static ui32 imgui_vert_shader[] = {
-        0x07230203, 0x00010000, 0x0008000a, 0x0000002e, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
-        0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
-        0x000a000f, 0x00000000, 0x00000004, 0x6e69616d, 0x00000000, 0x0000000b, 0x0000000f, 0x00000015,
-        0x0000001b, 0x0000001c, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, 0x00000004, 0x6e69616d,
-        0x00000000, 0x00030005, 0x00000009, 0x00000000, 0x00050006, 0x00000009, 0x00000000, 0x6f6c6f43,
-        0x00000072, 0x00040006, 0x00000009, 0x00000001, 0x00005655, 0x00030005, 0x0000000b, 0x0074754f,
-        0x00040005, 0x0000000f, 0x6c6f4361, 0x0000726f, 0x00030005, 0x00000015, 0x00565561, 0x00060005,
-        0x00000019, 0x505f6c67, 0x65567265, 0x78657472, 0x00000000, 0x00060006, 0x00000019, 0x00000000,
-        0x505f6c67, 0x7469736f, 0x006e6f69, 0x00030005, 0x0000001b, 0x00000000, 0x00040005, 0x0000001c,
-        0x736f5061, 0x00000000, 0x00060005, 0x0000001e, 0x73755075, 0x6e6f4368, 0x6e617473, 0x00000074,
-        0x00050006, 0x0000001e, 0x00000000, 0x61635375, 0x0000656c, 0x00060006, 0x0000001e, 0x00000001,
-        0x61725475, 0x616c736e, 0x00006574, 0x00030005, 0x00000020, 0x00006370, 0x00040047, 0x0000000b,
-        0x0000001e, 0x00000000, 0x00040047, 0x0000000f, 0x0000001e, 0x00000002, 0x00040047, 0x00000015,
-        0x0000001e, 0x00000001, 0x00050048, 0x00000019, 0x00000000, 0x0000000b, 0x00000000, 0x00030047,
-        0x00000019, 0x00000002, 0x00040047, 0x0000001c, 0x0000001e, 0x00000000, 0x00050048, 0x0000001e,
-        0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x0000001e, 0x00000001, 0x00000023, 0x00000008,
-        0x00030047, 0x0000001e, 0x00000002, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002,
-        0x00030016, 0x00000006, 0x00000020, 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040017,
-        0x00000008, 0x00000006, 0x00000002, 0x0004001e, 0x00000009, 0x00000007, 0x00000008, 0x00040020,
-        0x0000000a, 0x00000003, 0x00000009, 0x0004003b, 0x0000000a, 0x0000000b, 0x00000003, 0x00040015,
-        0x0000000c, 0x00000020, 0x00000001, 0x0004002b, 0x0000000c, 0x0000000d, 0x00000000, 0x00040020,
-        0x0000000e, 0x00000001, 0x00000007, 0x0004003b, 0x0000000e, 0x0000000f, 0x00000001, 0x00040020,
-        0x00000011, 0x00000003, 0x00000007, 0x0004002b, 0x0000000c, 0x00000013, 0x00000001, 0x00040020,
-        0x00000014, 0x00000001, 0x00000008, 0x0004003b, 0x00000014, 0x00000015, 0x00000001, 0x00040020,
-        0x00000017, 0x00000003, 0x00000008, 0x0003001e, 0x00000019, 0x00000007, 0x00040020, 0x0000001a,
-        0x00000003, 0x00000019, 0x0004003b, 0x0000001a, 0x0000001b, 0x00000003, 0x0004003b, 0x00000014,
-        0x0000001c, 0x00000001, 0x0004001e, 0x0000001e, 0x00000008, 0x00000008, 0x00040020, 0x0000001f,
-        0x00000009, 0x0000001e, 0x0004003b, 0x0000001f, 0x00000020, 0x00000009, 0x00040020, 0x00000021,
-        0x00000009, 0x00000008, 0x0004002b, 0x00000006, 0x00000028, 0x00000000, 0x0004002b, 0x00000006,
-        0x00000029, 0x3f800000, 0x00050036, 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8,
-        0x00000005, 0x0004003d, 0x00000007, 0x00000010, 0x0000000f, 0x00050041, 0x00000011, 0x00000012,
-        0x0000000b, 0x0000000d, 0x0003003e, 0x00000012, 0x00000010, 0x0004003d, 0x00000008, 0x00000016,
-        0x00000015, 0x00050041, 0x00000017, 0x00000018, 0x0000000b, 0x00000013, 0x0003003e, 0x00000018,
-        0x00000016, 0x0004003d, 0x00000008, 0x0000001d, 0x0000001c, 0x00050041, 0x00000021, 0x00000022,
-        0x00000020, 0x0000000d, 0x0004003d, 0x00000008, 0x00000023, 0x00000022, 0x00050085, 0x00000008,
-        0x00000024, 0x0000001d, 0x00000023, 0x00050041, 0x00000021, 0x00000025, 0x00000020, 0x00000013,
-        0x0004003d, 0x00000008, 0x00000026, 0x00000025, 0x00050081, 0x00000008, 0x00000027, 0x00000024,
-        0x00000026, 0x00050051, 0x00000006, 0x0000002a, 0x00000027, 0x00000000, 0x00050051, 0x00000006,
-        0x0000002b, 0x00000027, 0x00000001, 0x00070050, 0x00000007, 0x0000002c, 0x0000002a, 0x0000002b,
-        0x00000028, 0x00000029, 0x00050041, 0x00000011, 0x0000002d, 0x0000001b, 0x0000000d, 0x0003003e,
-        0x0000002d, 0x0000002c, 0x000100fd, 0x00010038
+        #include "res/tool/imgui/imgui.vert.u32"
     };
 
     static ui32 imgui_frag_shader[] = {
-        0x07230203, 0x00010000, 0x0008000a, 0x0000001e, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
-        0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
-        0x0007000f, 0x00000004, 0x00000004, 0x6e69616d, 0x00000000, 0x00000009, 0x0000000d, 0x00030010,
-        0x00000004, 0x00000007, 0x00030003, 0x00000002, 0x000001c2, 0x00040005, 0x00000004, 0x6e69616d,
-        0x00000000, 0x00040005, 0x00000009, 0x6c6f4366, 0x0000726f, 0x00030005, 0x0000000b, 0x00000000,
-        0x00050006, 0x0000000b, 0x00000000, 0x6f6c6f43, 0x00000072, 0x00040006, 0x0000000b, 0x00000001,
-        0x00005655, 0x00030005, 0x0000000d, 0x00006e49, 0x00050005, 0x00000016, 0x78655473, 0x65727574,
-        0x00000000, 0x00040047, 0x00000009, 0x0000001e, 0x00000000, 0x00040047, 0x0000000d, 0x0000001e,
-        0x00000000, 0x00040047, 0x00000016, 0x00000022, 0x00000000, 0x00040047, 0x00000016, 0x00000021,
-        0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00030016, 0x00000006,
-        0x00000020, 0x00040017, 0x00000007, 0x00000006, 0x00000004, 0x00040020, 0x00000008, 0x00000003,
-        0x00000007, 0x0004003b, 0x00000008, 0x00000009, 0x00000003, 0x00040017, 0x0000000a, 0x00000006,
-        0x00000002, 0x0004001e, 0x0000000b, 0x00000007, 0x0000000a, 0x00040020, 0x0000000c, 0x00000001,
-        0x0000000b, 0x0004003b, 0x0000000c, 0x0000000d, 0x00000001, 0x00040015, 0x0000000e, 0x00000020,
-        0x00000001, 0x0004002b, 0x0000000e, 0x0000000f, 0x00000000, 0x00040020, 0x00000010, 0x00000001,
-        0x00000007, 0x00090019, 0x00000013, 0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
-        0x00000001, 0x00000000, 0x0003001b, 0x00000014, 0x00000013, 0x00040020, 0x00000015, 0x00000000,
-        0x00000014, 0x0004003b, 0x00000015, 0x00000016, 0x00000000, 0x0004002b, 0x0000000e, 0x00000018,
-        0x00000001, 0x00040020, 0x00000019, 0x00000001, 0x0000000a, 0x00050036, 0x00000002, 0x00000004,
-        0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x00050041, 0x00000010, 0x00000011, 0x0000000d,
-        0x0000000f, 0x0004003d, 0x00000007, 0x00000012, 0x00000011, 0x0004003d, 0x00000014, 0x00000017,
-        0x00000016, 0x00050041, 0x00000019, 0x0000001a, 0x0000000d, 0x00000018, 0x0004003d, 0x0000000a,
-        0x0000001b, 0x0000001a, 0x00050057, 0x00000007, 0x0000001c, 0x00000017, 0x0000001b, 0x00050085,
-        0x00000007, 0x0000001d, 0x00000012, 0x0000001c, 0x0003003e, 0x00000009, 0x0000001d, 0x000100fd,
-        0x00010038
+        #include "res/tool/imgui/imgui.frag.u32"
     };
 
     bool imgui::create(graphics_pipeline::ptr p, index mf) {
diff --git a/liblava/block/render_pass.hpp b/liblava/block/render_pass.hpp
index b7c825db40532df160301242632287087ec453cb..76e6cee01e8be2ff4aecf203cce70f0aff855987 100644
--- a/liblava/block/render_pass.hpp
+++ b/liblava/block/render_pass.hpp
@@ -19,7 +19,7 @@ namespace lava {
         bool create(VkAttachmentsRef target_attachments, rect area);
         void destroy();
 
-        void process(VkCommandBuffer cmd_buf, index frame);
+        void process(VkCommandBuffer cmd_buf, index frame = 0);
 
         device_ptr get_device() {
             return device;
diff --git a/liblava/block/subpass.cpp b/liblava/block/subpass.cpp
index a7434c8202ea3d2bb4142c097a450a75b7e34f1a..a5e4453cf87c15effc4d7504bbb2ff471190cd51 100644
--- a/liblava/block/subpass.cpp
+++ b/liblava/block/subpass.cpp
@@ -157,11 +157,11 @@ namespace lava {
     subpass_dependency::subpass_dependency() {
         dependency.srcSubpass = 0;
         dependency.dstSubpass = 0;
-        dependency.srcStageMask = VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM;
-        dependency.dstStageMask = VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM;
-        dependency.srcAccessMask = VK_ACCESS_FLAG_BITS_MAX_ENUM;
-        dependency.dstAccessMask = VK_ACCESS_FLAG_BITS_MAX_ENUM;
-        dependency.dependencyFlags = VK_DEPENDENCY_FLAG_BITS_MAX_ENUM;
+        dependency.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+        dependency.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+        dependency.srcAccessMask = 0;
+        dependency.dstAccessMask = 0;
+        dependency.dependencyFlags = 0;
     }
 
     subpass_dependency::ptr make_subpass_dependency(ui32 src_subpass, ui32 dst_subpass, VkDependencyFlags dependency_flags) {
diff --git a/liblava/resource/image.cpp b/liblava/resource/image.cpp
index 433a733897f6ccbc1a75cb802c97d272591f0770..36680b72204ee3809f00118efd27af159ca470f5 100644
--- a/liblava/resource/image.cpp
+++ b/liblava/resource/image.cpp
@@ -3,6 +3,7 @@
 // license   : MIT; see accompanying LICENSE file
 
 #include <liblava/resource/image.hpp>
+#include <liblava/resource/format.hpp>
 
 namespace lava {
 
@@ -27,7 +28,7 @@ namespace lava {
         };
 
         subresource_range = {
-            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+            .aspectMask = format_aspect_mask(format),
             .baseMipLevel = 0,
             .levelCount = 1,
             .baseArrayLayer = 0,
diff --git a/res/lamp/gen_spirv.bat b/res/lamp/gen_spirv.bat
index 0537ee0ff193d3b099765fbdae234c719c469177..8783e014d8fbac73b5b8ff3470a13a90fba99f0f 100644
--- a/res/lamp/gen_spirv.bat
+++ b/res/lamp/gen_spirv.bat
@@ -1,7 +1,4 @@
 @ECHO on
 
-glslangValidator -V -x -o lamp.frag.u32 lamp.frag
-glslangValidator -V -x -o lamp.vert.u32 lamp.vert
-
 glslangValidator -V -o fragment.spirv lamp.frag
 glslangValidator -V -o vertex.spirv lamp.vert
diff --git a/res/lamp/gen_spirv.sh b/res/lamp/gen_spirv.sh
index eafc01834fdca88815fc411660b3e9796fcd9f33..b5aef81682c35f787a98d5002ee6da918a1dc11c 100644
--- a/res/lamp/gen_spirv.sh
+++ b/res/lamp/gen_spirv.sh
@@ -1,7 +1,4 @@
 #!/bin/bash
 
-glslangValidator -V -x -o lamp.frag.u32 lamp.frag
-glslangValidator -V -x -o lamp.vert.u32 lamp.vert
-
 glslangValidator -V -o fragment.spirv lamp.frag
 glslangValidator -V -o vertex.spirv lamp.vert
diff --git a/res/lamp/lamp.frag.u32 b/res/lamp/lamp.frag.u32
deleted file mode 100644
index 2babd9459bfc186eb262e38103456ff79263a256..0000000000000000000000000000000000000000
--- a/res/lamp/lamp.frag.u32
+++ /dev/null
@@ -1,244 +0,0 @@
-	// 1011.0.0
-	0x07230203,0x00010000,0x0008000a,0x00000165,0x00000000,0x00020011,0x00000001,0x0006000b,
-	0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
-	0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000099,0x00000152,0x00030010,
-	0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
-	0x00000000,0x00040005,0x0000000b,0x66762868,0x00003b33,0x00030005,0x0000000a,0x00000071,
-	0x00030005,0x0000000e,0x00000066,0x00060005,0x00000013,0x73755075,0x6e6f4368,0x6e617473,
-	0x00000074,0x00060006,0x00000013,0x00000000,0x73655275,0x74756c6f,0x006e6f69,0x00060006,
-	0x00000013,0x00000001,0x6d695475,0x70654465,0x00006874,0x00050006,0x00000013,0x00000002,
-	0x6c6f4375,0x0000726f,0x00030005,0x00000015,0x00006370,0x00030005,0x00000095,0x00000070,
-	0x00060005,0x00000099,0x465f6c67,0x43676172,0x64726f6f,0x00000000,0x00030005,0x000000a4,
-	0x0000006f,0x00030005,0x000000ae,0x00000064,0x00030005,0x000000be,0x00000063,0x00030005,
-	0x000000c0,0x00000074,0x00030005,0x000000c2,0x00000069,0x00040005,0x000000d1,0x61726170,
-	0x0000006d,0x00030005,0x000000d9,0x0000006a,0x00040005,0x000000e7,0x61726170,0x0000006d,
-	0x00030005,0x000000f0,0x00000065,0x00030005,0x000000f3,0x0000006e,0x00040005,0x000000fa,
-	0x61726170,0x0000006d,0x00040005,0x00000108,0x61726170,0x0000006d,0x00040005,0x00000111,
-	0x61726170,0x0000006d,0x00040005,0x0000011f,0x61726170,0x0000006d,0x00040005,0x00000128,
-	0x61726170,0x0000006d,0x00040005,0x00000136,0x61726170,0x0000006d,0x00050005,0x00000152,
-	0x67617266,0x6f6c6f43,0x00000072,0x00050048,0x00000013,0x00000000,0x00000023,0x00000000,
-	0x00050048,0x00000013,0x00000001,0x00000023,0x00000008,0x00050048,0x00000013,0x00000002,
-	0x00000023,0x00000010,0x00030047,0x00000013,0x00000002,0x00040047,0x00000099,0x0000000b,
-	0x0000000f,0x00040047,0x00000152,0x0000001e,0x00000000,0x00020013,0x00000002,0x00030021,
-	0x00000003,0x00000002,0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,
-	0x00000003,0x00040020,0x00000008,0x00000007,0x00000007,0x00040021,0x00000009,0x00000006,
-	0x00000008,0x00040020,0x0000000d,0x00000007,0x00000006,0x0004002b,0x00000006,0x0000000f,
-	0x3f800000,0x00040017,0x00000011,0x00000006,0x00000002,0x00040017,0x00000012,0x00000006,
-	0x00000004,0x0005001e,0x00000013,0x00000011,0x00000011,0x00000012,0x00040020,0x00000014,
-	0x00000009,0x00000013,0x0004003b,0x00000014,0x00000015,0x00000009,0x00040015,0x00000016,
-	0x00000020,0x00000001,0x0004002b,0x00000016,0x00000017,0x00000001,0x00040015,0x00000018,
-	0x00000020,0x00000000,0x0004002b,0x00000018,0x00000019,0x00000000,0x00040020,0x0000001a,
-	0x00000009,0x00000006,0x0004002b,0x00000006,0x0000001d,0x3e395810,0x0004002b,0x00000006,
-	0x00000021,0x3f000000,0x0004002b,0x00000006,0x00000025,0x3e818937,0x0004002b,0x00000006,
-	0x0000002f,0x3e810625,0x0004002b,0x00000006,0x00000036,0x3e2f1aa0,0x0004002b,0x00000006,
-	0x00000040,0x3e083127,0x0004002b,0x00000006,0x00000047,0x3e90e560,0x0004002b,0x00000006,
-	0x00000051,0x3e872b02,0x0004002b,0x00000006,0x00000058,0x3e147ae1,0x0004002b,0x00000018,
-	0x0000005f,0x00000001,0x0004002b,0x00000018,0x00000063,0x00000002,0x0004002b,0x00000006,
-	0x0000006d,0x40400000,0x0004002b,0x00000006,0x00000074,0x3e570a3d,0x0004002b,0x00000006,
-	0x00000078,0x40c00000,0x0004002b,0x00000006,0x0000007c,0x41a00000,0x0004002b,0x00000006,
-	0x00000082,0x40a00000,0x0004002b,0x00000006,0x00000088,0x40900000,0x0004002b,0x00000006,
-	0x0000008c,0x3e99999a,0x00040020,0x00000094,0x00000007,0x00000011,0x0004002b,0x00000006,
-	0x00000096,0xbf800000,0x0004002b,0x00000006,0x00000097,0x40000000,0x00040020,0x00000098,
-	0x00000001,0x00000012,0x0004003b,0x00000098,0x00000099,0x00000001,0x0004002b,0x00000016,
-	0x0000009d,0x00000000,0x00040020,0x0000009e,0x00000009,0x00000011,0x0004002b,0x00000006,
-	0x000000a9,0x3fa00000,0x0004002b,0x00000006,0x000000ac,0x00000000,0x0004002b,0x00000006,
-	0x000000ba,0x42800000,0x00040020,0x000000bd,0x00000007,0x00000012,0x0007002c,0x00000012,
-	0x000000bf,0x000000ac,0x000000ac,0x000000ac,0x000000ac,0x00040020,0x000000c1,0x00000007,
-	0x00000016,0x0004002b,0x00000016,0x000000c9,0x00000019,0x00020014,0x000000ca,0x0004002b,
-	0x00000006,0x000000d3,0x3ecccccd,0x0004002b,0x00000016,0x000000e0,0x00000005,0x0004002b,
-	0x00000006,0x000000f1,0x3c23d70a,0x0006002c,0x00000007,0x000000f2,0x000000f1,0x000000ac,
-	0x000000ac,0x0006002c,0x00000007,0x000000f4,0x000000ac,0x000000ac,0x000000ac,0x0004002b,
-	0x00000006,0x0000013c,0xbe19999a,0x0006002c,0x00000007,0x0000013d,0x000000ac,0x000000ac,
-	0x0000013c,0x0004002b,0x00000006,0x00000141,0x3e19999a,0x0006002c,0x00000007,0x00000142,
-	0x000000ac,0x0000013c,0x00000141,0x0004002b,0x00000006,0x00000146,0x3e1eb852,0x00040020,
-	0x00000151,0x00000003,0x00000012,0x0004003b,0x00000151,0x00000152,0x00000003,0x0004002b,
-	0x00000016,0x00000154,0x00000002,0x0004002b,0x00000018,0x0000015b,0x00000003,0x00050036,
-	0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003b,0x00000094,
-	0x00000095,0x00000007,0x0004003b,0x00000008,0x000000a4,0x00000007,0x0004003b,0x00000008,
-	0x000000ae,0x00000007,0x0004003b,0x000000bd,0x000000be,0x00000007,0x0004003b,0x0000000d,
-	0x000000c0,0x00000007,0x0004003b,0x000000c1,0x000000c2,0x00000007,0x0004003b,0x00000008,
-	0x000000d1,0x00000007,0x0004003b,0x000000c1,0x000000d9,0x00000007,0x0004003b,0x00000008,
-	0x000000e7,0x00000007,0x0004003b,0x00000008,0x000000f0,0x00000007,0x0004003b,0x00000008,
-	0x000000f3,0x00000007,0x0004003b,0x00000008,0x000000fa,0x00000007,0x0004003b,0x00000008,
-	0x00000108,0x00000007,0x0004003b,0x00000008,0x00000111,0x00000007,0x0004003b,0x00000008,
-	0x0000011f,0x00000007,0x0004003b,0x00000008,0x00000128,0x00000007,0x0004003b,0x00000008,
-	0x00000136,0x00000007,0x0004003d,0x00000012,0x0000009a,0x00000099,0x0007004f,0x00000011,
-	0x0000009b,0x0000009a,0x0000009a,0x00000000,0x00000001,0x0005008e,0x00000011,0x0000009c,
-	0x0000009b,0x00000097,0x00050041,0x0000009e,0x0000009f,0x00000015,0x0000009d,0x0004003d,
-	0x00000011,0x000000a0,0x0000009f,0x00050088,0x00000011,0x000000a1,0x0000009c,0x000000a0,
-	0x00050050,0x00000011,0x000000a2,0x00000096,0x00000096,0x00050081,0x00000011,0x000000a3,
-	0x000000a2,0x000000a1,0x0003003e,0x00000095,0x000000a3,0x00050041,0x0000000d,0x000000a5,
-	0x00000095,0x00000019,0x0004003d,0x00000006,0x000000a6,0x000000a5,0x00050041,0x0000000d,
-	0x000000a7,0x00000095,0x0000005f,0x0004003d,0x00000006,0x000000a8,0x000000a7,0x00050085,
-	0x00000006,0x000000aa,0x000000a8,0x000000a9,0x00050083,0x00000006,0x000000ab,0x000000aa,
-	0x0000008c,0x00060050,0x00000007,0x000000ad,0x000000a6,0x000000ab,0x000000ac,0x0003003e,
-	0x000000a4,0x000000ad,0x00050041,0x0000000d,0x000000af,0x00000095,0x00000019,0x0004003d,
-	0x00000006,0x000000b0,0x000000af,0x00060041,0x0000001a,0x000000b1,0x00000015,0x00000017,
-	0x00000019,0x0004003d,0x00000006,0x000000b2,0x000000b1,0x00050088,0x00000006,0x000000b3,
-	0x000000b2,0x0000007c,0x0006000c,0x00000006,0x000000b4,0x00000001,0x0000000e,0x000000b3,
-	0x00050085,0x00000006,0x000000b5,0x000000b4,0x0000008c,0x00050081,0x00000006,0x000000b6,
-	0x000000b0,0x000000b5,0x00050041,0x0000000d,0x000000b7,0x00000095,0x0000005f,0x0004003d,
-	0x00000006,0x000000b8,0x000000b7,0x00060050,0x00000007,0x000000b9,0x000000b6,0x000000b8,
-	0x0000000f,0x00060050,0x00000007,0x000000bb,0x000000ba,0x000000ba,0x000000ba,0x00050088,
-	0x00000007,0x000000bc,0x000000b9,0x000000bb,0x0003003e,0x000000ae,0x000000bc,0x0003003e,
-	0x000000be,0x000000bf,0x0003003e,0x000000c0,0x000000ac,0x0003003e,0x000000c2,0x0000009d,
-	0x000200f9,0x000000c3,0x000200f8,0x000000c3,0x000400f6,0x000000c5,0x000000c6,0x00000000,
-	0x000200f9,0x000000c7,0x000200f8,0x000000c7,0x0004003d,0x00000016,0x000000c8,0x000000c2,
-	0x000500b1,0x000000ca,0x000000cb,0x000000c8,0x000000c9,0x000400fa,0x000000cb,0x000000c4,
-	0x000000c5,0x000200f8,0x000000c4,0x0004003d,0x00000007,0x000000cc,0x000000a4,0x0004003d,
-	0x00000007,0x000000cd,0x000000ae,0x0004003d,0x00000006,0x000000ce,0x000000c0,0x0005008e,
-	0x00000007,0x000000cf,0x000000cd,0x000000ce,0x00050081,0x00000007,0x000000d0,0x000000cc,
-	0x000000cf,0x0003003e,0x000000d1,0x000000d0,0x00050039,0x00000006,0x000000d2,0x0000000b,
-	0x000000d1,0x000500b8,0x000000ca,0x000000d4,0x000000d2,0x000000d3,0x000300f7,0x000000d6,
-	0x00000000,0x000400fa,0x000000d4,0x000000d5,0x000000d6,0x000200f8,0x000000d5,0x0004003d,
-	0x00000006,0x000000d7,0x000000c0,0x00050083,0x00000006,0x000000d8,0x000000d7,0x00000082,
-	0x0003003e,0x000000c0,0x000000d8,0x0003003e,0x000000d9,0x0000009d,0x000200f9,0x000000da,
-	0x000200f8,0x000000da,0x000400f6,0x000000dc,0x000000dd,0x00000000,0x000200f9,0x000000de,
-	0x000200f8,0x000000de,0x0004003d,0x00000016,0x000000df,0x000000d9,0x000500b1,0x000000ca,
-	0x000000e1,0x000000df,0x000000e0,0x000400fa,0x000000e1,0x000000db,0x000000dc,0x000200f8,
-	0x000000db,0x0004003d,0x00000007,0x000000e2,0x000000a4,0x0004003d,0x00000007,0x000000e3,
-	0x000000ae,0x0004003d,0x00000006,0x000000e4,0x000000c0,0x0005008e,0x00000007,0x000000e5,
-	0x000000e3,0x000000e4,0x00050081,0x00000007,0x000000e6,0x000000e2,0x000000e5,0x0003003e,
-	0x000000e7,0x000000e6,0x00050039,0x00000006,0x000000e8,0x0000000b,0x000000e7,0x000500ba,
-	0x000000ca,0x000000e9,0x000000e8,0x000000d3,0x000300f7,0x000000eb,0x00000000,0x000400fa,
-	0x000000e9,0x000000ea,0x000000eb,0x000200f8,0x000000ea,0x0004003d,0x00000006,0x000000ec,
-	0x000000c0,0x00050081,0x00000006,0x000000ed,0x000000ec,0x0000000f,0x0003003e,0x000000c0,
-	0x000000ed,0x000200f9,0x000000eb,0x000200f8,0x000000eb,0x000200f9,0x000000dd,0x000200f8,
-	0x000000dd,0x0004003d,0x00000016,0x000000ee,0x000000d9,0x00050080,0x00000016,0x000000ef,
-	0x000000ee,0x00000017,0x0003003e,0x000000d9,0x000000ef,0x000200f9,0x000000da,0x000200f8,
-	0x000000dc,0x0003003e,0x000000f0,0x000000f2,0x0003003e,0x000000f3,0x000000f4,0x0004003d,
-	0x00000007,0x000000f5,0x000000a4,0x0004003d,0x00000007,0x000000f6,0x000000ae,0x0004003d,
-	0x00000006,0x000000f7,0x000000c0,0x0005008e,0x00000007,0x000000f8,0x000000f6,0x000000f7,
-	0x00050081,0x00000007,0x000000f9,0x000000f5,0x000000f8,0x0003003e,0x000000fa,0x000000f9,
-	0x00050039,0x00000006,0x000000fb,0x0000000b,0x000000fa,0x0004003d,0x00000007,0x000000fc,
-	0x000000a4,0x0004003d,0x00000007,0x000000fd,0x000000ae,0x0004003d,0x00000006,0x000000fe,
-	0x000000c0,0x0005008e,0x00000007,0x000000ff,0x000000fd,0x000000fe,0x00050081,0x00000007,
-	0x00000100,0x000000fc,0x000000ff,0x0004003d,0x00000007,0x00000101,0x000000f0,0x0008004f,
-	0x00000007,0x00000102,0x00000101,0x00000101,0x00000000,0x00000001,0x00000001,0x00050081,
-	0x00000007,0x00000103,0x00000100,0x00000102,0x00050051,0x00000006,0x00000104,0x00000103,
-	0x00000000,0x00050051,0x00000006,0x00000105,0x00000103,0x00000001,0x00050051,0x00000006,
-	0x00000106,0x00000103,0x00000002,0x00060050,0x00000007,0x00000107,0x00000104,0x00000105,
-	0x00000106,0x0003003e,0x00000108,0x00000107,0x00050039,0x00000006,0x00000109,0x0000000b,
-	0x00000108,0x00050083,0x00000006,0x0000010a,0x000000fb,0x00000109,0x00050041,0x0000000d,
-	0x0000010b,0x000000f3,0x00000019,0x0003003e,0x0000010b,0x0000010a,0x0004003d,0x00000007,
-	0x0000010c,0x000000a4,0x0004003d,0x00000007,0x0000010d,0x000000ae,0x0004003d,0x00000006,
-	0x0000010e,0x000000c0,0x0005008e,0x00000007,0x0000010f,0x0000010d,0x0000010e,0x00050081,
-	0x00000007,0x00000110,0x0000010c,0x0000010f,0x0003003e,0x00000111,0x00000110,0x00050039,
-	0x00000006,0x00000112,0x0000000b,0x00000111,0x0004003d,0x00000007,0x00000113,0x000000a4,
-	0x0004003d,0x00000007,0x00000114,0x000000ae,0x0004003d,0x00000006,0x00000115,0x000000c0,
-	0x0005008e,0x00000007,0x00000116,0x00000114,0x00000115,0x00050081,0x00000007,0x00000117,
-	0x00000113,0x00000116,0x0004003d,0x00000007,0x00000118,0x000000f0,0x0008004f,0x00000007,
-	0x00000119,0x00000118,0x00000118,0x00000001,0x00000000,0x00000001,0x00050081,0x00000007,
-	0x0000011a,0x00000117,0x00000119,0x00050051,0x00000006,0x0000011b,0x0000011a,0x00000000,
-	0x00050051,0x00000006,0x0000011c,0x0000011a,0x00000001,0x00050051,0x00000006,0x0000011d,
-	0x0000011a,0x00000002,0x00060050,0x00000007,0x0000011e,0x0000011b,0x0000011c,0x0000011d,
-	0x0003003e,0x0000011f,0x0000011e,0x00050039,0x00000006,0x00000120,0x0000000b,0x0000011f,
-	0x00050083,0x00000006,0x00000121,0x00000112,0x00000120,0x00050041,0x0000000d,0x00000122,
-	0x000000f3,0x0000005f,0x0003003e,0x00000122,0x00000121,0x0004003d,0x00000007,0x00000123,
-	0x000000a4,0x0004003d,0x00000007,0x00000124,0x000000ae,0x0004003d,0x00000006,0x00000125,
-	0x000000c0,0x0005008e,0x00000007,0x00000126,0x00000124,0x00000125,0x00050081,0x00000007,
-	0x00000127,0x00000123,0x00000126,0x0003003e,0x00000128,0x00000127,0x00050039,0x00000006,
-	0x00000129,0x0000000b,0x00000128,0x0004003d,0x00000007,0x0000012a,0x000000a4,0x0004003d,
-	0x00000007,0x0000012b,0x000000ae,0x0004003d,0x00000006,0x0000012c,0x000000c0,0x0005008e,
-	0x00000007,0x0000012d,0x0000012b,0x0000012c,0x00050081,0x00000007,0x0000012e,0x0000012a,
-	0x0000012d,0x0004003d,0x00000007,0x0000012f,0x000000f0,0x0008004f,0x00000007,0x00000130,
-	0x0000012f,0x0000012f,0x00000001,0x00000001,0x00000000,0x00050081,0x00000007,0x00000131,
-	0x0000012e,0x00000130,0x00050051,0x00000006,0x00000132,0x00000131,0x00000000,0x00050051,
-	0x00000006,0x00000133,0x00000131,0x00000001,0x00050051,0x00000006,0x00000134,0x00000131,
-	0x00000002,0x00060050,0x00000007,0x00000135,0x00000132,0x00000133,0x00000134,0x0003003e,
-	0x00000136,0x00000135,0x00050039,0x00000006,0x00000137,0x0000000b,0x00000136,0x00050083,
-	0x00000006,0x00000138,0x00000129,0x00000137,0x00050041,0x0000000d,0x00000139,0x000000f3,
-	0x00000063,0x0003003e,0x00000139,0x00000138,0x0004003d,0x00000007,0x0000013a,0x000000f3,
-	0x0006000c,0x00000007,0x0000013b,0x00000001,0x00000045,0x0000013a,0x0003003e,0x000000f3,
-	0x0000013b,0x0004003d,0x00000007,0x0000013e,0x000000f3,0x00050094,0x00000006,0x0000013f,
-	0x0000013d,0x0000013e,0x0007000c,0x00000006,0x00000140,0x00000001,0x00000028,0x0000013f,
-	0x000000ac,0x0004003d,0x00000007,0x00000143,0x000000f3,0x00050094,0x00000006,0x00000144,
-	0x00000142,0x00000143,0x0007000c,0x00000006,0x00000145,0x00000001,0x00000028,0x00000144,
-	0x000000ac,0x00050085,0x00000006,0x00000147,0x00000145,0x00000146,0x00050081,0x00000006,
-	0x00000148,0x00000140,0x00000147,0x0004003d,0x00000012,0x00000149,0x000000be,0x00070050,
-	0x00000012,0x0000014a,0x00000148,0x00000148,0x00000148,0x00000148,0x00050081,0x00000012,
-	0x0000014b,0x00000149,0x0000014a,0x0003003e,0x000000be,0x0000014b,0x000200f9,0x000000c5,
-	0x000200f8,0x000000d6,0x0004003d,0x00000006,0x0000014d,0x000000c0,0x00050081,0x00000006,
-	0x0000014e,0x0000014d,0x00000082,0x0003003e,0x000000c0,0x0000014e,0x000200f9,0x000000c6,
-	0x000200f8,0x000000c6,0x0004003d,0x00000016,0x0000014f,0x000000c2,0x00050080,0x00000016,
-	0x00000150,0x0000014f,0x00000017,0x0003003e,0x000000c2,0x00000150,0x000200f9,0x000000c3,
-	0x000200f8,0x000000c5,0x0004003d,0x00000012,0x00000153,0x000000be,0x00060041,0x0000001a,
-	0x00000155,0x00000015,0x00000154,0x00000019,0x0004003d,0x00000006,0x00000156,0x00000155,
-	0x00060041,0x0000001a,0x00000157,0x00000015,0x00000154,0x0000005f,0x0004003d,0x00000006,
-	0x00000158,0x00000157,0x00060041,0x0000001a,0x00000159,0x00000015,0x00000154,0x00000063,
-	0x0004003d,0x00000006,0x0000015a,0x00000159,0x00060041,0x0000001a,0x0000015c,0x00000015,
-	0x00000154,0x0000015b,0x0004003d,0x00000006,0x0000015d,0x0000015c,0x00070050,0x00000012,
-	0x0000015e,0x00000156,0x00000158,0x0000015a,0x0000015d,0x0004003d,0x00000006,0x0000015f,
-	0x000000c0,0x00060041,0x0000001a,0x00000160,0x00000015,0x00000017,0x0000005f,0x0004003d,
-	0x00000006,0x00000161,0x00000160,0x00050085,0x00000006,0x00000162,0x0000015f,0x00000161,
-	0x0005008e,0x00000012,0x00000163,0x0000015e,0x00000162,0x00050081,0x00000012,0x00000164,
-	0x00000153,0x00000163,0x0003003e,0x00000152,0x00000164,0x000100fd,0x00010038,0x00050036,
-	0x00000006,0x0000000b,0x00000000,0x00000009,0x00030037,0x00000008,0x0000000a,0x000200f8,
-	0x0000000c,0x0004003b,0x0000000d,0x0000000e,0x00000007,0x0003003e,0x0000000e,0x0000000f,
-	0x0004003d,0x00000007,0x00000010,0x0000000a,0x00060041,0x0000001a,0x0000001b,0x00000015,
-	0x00000017,0x00000019,0x0004003d,0x00000006,0x0000001c,0x0000001b,0x00050085,0x00000006,
-	0x0000001e,0x0000001c,0x0000001d,0x0006000c,0x00000006,0x0000001f,0x00000001,0x0000000d,
-	0x0000001e,0x0004007f,0x00000006,0x00000020,0x0000001f,0x00050085,0x00000006,0x00000022,
-	0x00000020,0x00000021,0x00060041,0x0000001a,0x00000023,0x00000015,0x00000017,0x00000019,
-	0x0004003d,0x00000006,0x00000024,0x00000023,0x00050085,0x00000006,0x00000026,0x00000024,
-	0x00000025,0x0006000c,0x00000006,0x00000027,0x00000001,0x0000000d,0x00000026,0x00060050,
-	0x00000007,0x00000028,0x00000022,0x00000027,0x0000000f,0x0007000c,0x00000006,0x00000029,
-	0x00000001,0x00000043,0x00000010,0x00000028,0x0004003d,0x00000006,0x0000002a,0x0000000e,
-	0x00050085,0x00000006,0x0000002b,0x0000002a,0x00000029,0x0003003e,0x0000000e,0x0000002b,
-	0x0004003d,0x00000007,0x0000002c,0x0000000a,0x00060041,0x0000001a,0x0000002d,0x00000015,
-	0x00000017,0x00000019,0x0004003d,0x00000006,0x0000002e,0x0000002d,0x00050085,0x00000006,
-	0x00000030,0x0000002e,0x0000002f,0x0006000c,0x00000006,0x00000031,0x00000001,0x0000000d,
-	0x00000030,0x0004007f,0x00000006,0x00000032,0x00000031,0x00050085,0x00000006,0x00000033,
-	0x00000032,0x00000021,0x00060041,0x0000001a,0x00000034,0x00000015,0x00000017,0x00000019,
-	0x0004003d,0x00000006,0x00000035,0x00000034,0x00050085,0x00000006,0x00000037,0x00000035,
-	0x00000036,0x0006000c,0x00000006,0x00000038,0x00000001,0x0000000d,0x00000037,0x00060050,
-	0x00000007,0x00000039,0x00000033,0x00000038,0x0000000f,0x0007000c,0x00000006,0x0000003a,
-	0x00000001,0x00000043,0x0000002c,0x00000039,0x0004003d,0x00000006,0x0000003b,0x0000000e,
-	0x00050085,0x00000006,0x0000003c,0x0000003b,0x0000003a,0x0003003e,0x0000000e,0x0000003c,
-	0x0004003d,0x00000007,0x0000003d,0x0000000a,0x00060041,0x0000001a,0x0000003e,0x00000015,
-	0x00000017,0x00000019,0x0004003d,0x00000006,0x0000003f,0x0000003e,0x00050085,0x00000006,
-	0x00000041,0x0000003f,0x00000040,0x0006000c,0x00000006,0x00000042,0x00000001,0x0000000d,
-	0x00000041,0x0004007f,0x00000006,0x00000043,0x00000042,0x00050085,0x00000006,0x00000044,
-	0x00000043,0x00000021,0x00060041,0x0000001a,0x00000045,0x00000015,0x00000017,0x00000019,
-	0x0004003d,0x00000006,0x00000046,0x00000045,0x00050085,0x00000006,0x00000048,0x00000046,
-	0x00000047,0x0006000c,0x00000006,0x00000049,0x00000001,0x0000000d,0x00000048,0x00060050,
-	0x00000007,0x0000004a,0x00000044,0x00000049,0x0000000f,0x0007000c,0x00000006,0x0000004b,
-	0x00000001,0x00000043,0x0000003d,0x0000004a,0x0004003d,0x00000006,0x0000004c,0x0000000e,
-	0x00050085,0x00000006,0x0000004d,0x0000004c,0x0000004b,0x0003003e,0x0000000e,0x0000004d,
-	0x0004003d,0x00000007,0x0000004e,0x0000000a,0x00060041,0x0000001a,0x0000004f,0x00000015,
-	0x00000017,0x00000019,0x0004003d,0x00000006,0x00000050,0x0000004f,0x00050085,0x00000006,
-	0x00000052,0x00000050,0x00000051,0x0006000c,0x00000006,0x00000053,0x00000001,0x0000000d,
-	0x00000052,0x0004007f,0x00000006,0x00000054,0x00000053,0x00050085,0x00000006,0x00000055,
-	0x00000054,0x00000021,0x00060041,0x0000001a,0x00000056,0x00000015,0x00000017,0x00000019,
-	0x0004003d,0x00000006,0x00000057,0x00000056,0x00050085,0x00000006,0x00000059,0x00000057,
-	0x00000058,0x0006000c,0x00000006,0x0000005a,0x00000001,0x0000000d,0x00000059,0x00060050,
-	0x00000007,0x0000005b,0x00000055,0x0000005a,0x0000000f,0x0007000c,0x00000006,0x0000005c,
-	0x00000001,0x00000043,0x0000004e,0x0000005b,0x0004003d,0x00000006,0x0000005d,0x0000000e,
-	0x00050085,0x00000006,0x0000005e,0x0000005d,0x0000005c,0x0003003e,0x0000000e,0x0000005e,
-	0x00050041,0x0000000d,0x00000060,0x0000000a,0x0000005f,0x0004003d,0x00000006,0x00000061,
-	0x00000060,0x0006000c,0x00000006,0x00000062,0x00000001,0x0000000e,0x00000061,0x00050041,
-	0x0000000d,0x00000064,0x0000000a,0x00000063,0x0004003d,0x00000006,0x00000065,0x00000064,
-	0x0006000c,0x00000006,0x00000066,0x00000001,0x0000000e,0x00000065,0x00050081,0x00000006,
-	0x00000067,0x00000066,0x0000000f,0x00050085,0x00000006,0x00000068,0x00000062,0x00000067,
-	0x00050041,0x0000000d,0x00000069,0x0000000a,0x00000019,0x0004003d,0x00000006,0x0000006a,
-	0x00000069,0x00050041,0x0000000d,0x0000006b,0x0000000a,0x00000063,0x0004003d,0x00000006,
-	0x0000006c,0x0000006b,0x00050085,0x00000006,0x0000006e,0x0000006c,0x0000006d,0x0006000c,
-	0x00000006,0x0000006f,0x00000001,0x0000000e,0x0000006e,0x00050081,0x00000006,0x00000070,
-	0x0000006a,0x0000006f,0x0006000c,0x00000006,0x00000071,0x00000001,0x0000000e,0x00000070,
-	0x00050081,0x00000006,0x00000072,0x00000071,0x0000000f,0x00050085,0x00000006,0x00000073,
-	0x00000068,0x00000072,0x00050083,0x00000006,0x00000075,0x00000073,0x00000074,0x00050041,
-	0x0000000d,0x00000076,0x0000000a,0x00000063,0x0004003d,0x00000006,0x00000077,0x00000076,
-	0x00050085,0x00000006,0x00000079,0x00000077,0x00000078,0x00060041,0x0000001a,0x0000007a,
-	0x00000015,0x00000017,0x00000019,0x0004003d,0x00000006,0x0000007b,0x0000007a,0x00050088,
-	0x00000006,0x0000007d,0x0000007b,0x0000007c,0x00050081,0x00000006,0x0000007e,0x00000079,
-	0x0000007d,0x0006000c,0x00000006,0x0000007f,0x00000001,0x0000000e,0x0000007e,0x00050041,
-	0x0000000d,0x00000080,0x0000000a,0x00000019,0x0004003d,0x00000006,0x00000081,0x00000080,
-	0x00050085,0x00000006,0x00000083,0x00000081,0x00000082,0x0006000c,0x00000006,0x00000084,
-	0x00000001,0x0000000e,0x00000083,0x00050085,0x00000006,0x00000085,0x0000007f,0x00000084,
-	0x00050041,0x0000000d,0x00000086,0x0000000a,0x0000005f,0x0004003d,0x00000006,0x00000087,
-	0x00000086,0x00050085,0x00000006,0x00000089,0x00000087,0x00000088,0x0006000c,0x00000006,
-	0x0000008a,0x00000001,0x0000000e,0x00000089,0x00050085,0x00000006,0x0000008b,0x00000085,
-	0x0000008a,0x00050085,0x00000006,0x0000008d,0x0000008b,0x0000008c,0x00050081,0x00000006,
-	0x0000008e,0x00000075,0x0000008d,0x0004003d,0x00000006,0x0000008f,0x0000000e,0x00050085,
-	0x00000006,0x00000090,0x0000008f,0x0000008e,0x0003003e,0x0000000e,0x00000090,0x0004003d,
-	0x00000006,0x00000091,0x0000000e,0x000200fe,0x00000091,0x00010038
diff --git a/res/lamp/lamp.vert.u32 b/res/lamp/lamp.vert.u32
deleted file mode 100644
index 2bca18dee8401fd14d49b92debed284110d6d38a..0000000000000000000000000000000000000000
--- a/res/lamp/lamp.vert.u32
+++ /dev/null
@@ -1,31 +0,0 @@
-	// 1011.0.0
-	0x07230203,0x00010000,0x0008000a,0x00000029,0x00000000,0x00020011,0x00000001,0x0006000b,
-	0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
-	0x0007000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000c,0x0000001a,0x00030003,
-	0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,0x00000000,0x00040005,0x00000009,
-	0x5574756f,0x00000056,0x00060005,0x0000000c,0x565f6c67,0x65747265,0x646e4978,0x00007865,
-	0x00060005,0x00000018,0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x00000018,
-	0x00000000,0x505f6c67,0x7469736f,0x006e6f69,0x00030005,0x0000001a,0x00000000,0x00040047,
-	0x0000000c,0x0000000b,0x0000002a,0x00050048,0x00000018,0x00000000,0x0000000b,0x00000000,
-	0x00030047,0x00000018,0x00000002,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,
-	0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000002,0x00040020,
-	0x00000008,0x00000007,0x00000007,0x00040015,0x0000000a,0x00000020,0x00000001,0x00040020,
-	0x0000000b,0x00000001,0x0000000a,0x0004003b,0x0000000b,0x0000000c,0x00000001,0x0004002b,
-	0x0000000a,0x0000000e,0x00000001,0x0004002b,0x0000000a,0x00000010,0x00000002,0x00040017,
-	0x00000017,0x00000006,0x00000004,0x0003001e,0x00000018,0x00000017,0x00040020,0x00000019,
-	0x00000003,0x00000018,0x0004003b,0x00000019,0x0000001a,0x00000003,0x0004002b,0x0000000a,
-	0x0000001b,0x00000000,0x0004002b,0x00000006,0x0000001d,0x40000000,0x0004002b,0x00000006,
-	0x0000001f,0xbf800000,0x0004002b,0x00000006,0x00000022,0x00000000,0x0004002b,0x00000006,
-	0x00000023,0x3f800000,0x00040020,0x00000027,0x00000003,0x00000017,0x00050036,0x00000002,
-	0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003b,0x00000008,0x00000009,
-	0x00000007,0x0004003d,0x0000000a,0x0000000d,0x0000000c,0x000500c4,0x0000000a,0x0000000f,
-	0x0000000d,0x0000000e,0x000500c7,0x0000000a,0x00000011,0x0000000f,0x00000010,0x0004006f,
-	0x00000006,0x00000012,0x00000011,0x0004003d,0x0000000a,0x00000013,0x0000000c,0x000500c7,
-	0x0000000a,0x00000014,0x00000013,0x00000010,0x0004006f,0x00000006,0x00000015,0x00000014,
-	0x00050050,0x00000007,0x00000016,0x00000012,0x00000015,0x0003003e,0x00000009,0x00000016,
-	0x0004003d,0x00000007,0x0000001c,0x00000009,0x0005008e,0x00000007,0x0000001e,0x0000001c,
-	0x0000001d,0x00050050,0x00000007,0x00000020,0x0000001f,0x0000001f,0x00050081,0x00000007,
-	0x00000021,0x0000001e,0x00000020,0x00050051,0x00000006,0x00000024,0x00000021,0x00000000,
-	0x00050051,0x00000006,0x00000025,0x00000021,0x00000001,0x00070050,0x00000017,0x00000026,
-	0x00000024,0x00000025,0x00000022,0x00000023,0x00050041,0x00000027,0x00000028,0x0000001a,
-	0x0000001b,0x0003003e,0x00000028,0x00000026,0x000100fd,0x00010038
diff --git a/res/light/data.inc b/res/light/data.inc
new file mode 100644
index 0000000000000000000000000000000000000000..a61b8bbb65b9e057ceba48812180f3f40ee46976
--- /dev/null
+++ b/res/light/data.inc
@@ -0,0 +1,25 @@
+struct UboData
+{
+    vec3 camPos;
+    uint lightCount;
+    mat4 view;
+    mat4 projection;
+    mat4 invProjection;
+    uvec2 resolution;
+};
+
+struct PushConstantData
+{
+    mat4 model;
+    vec3 color;
+    float metallic;
+    uint enableNormalMapping;
+};
+
+struct LightData
+{
+    vec3 position;
+    float radius;
+    vec3 intensity;
+    float _padding;
+};
diff --git a/res/light/gbuffer.frag b/res/light/gbuffer.frag
new file mode 100644
index 0000000000000000000000000000000000000000..17904f116e9dbc913f7660a6b7d5ada43712ca45
--- /dev/null
+++ b/res/light/gbuffer.frag
@@ -0,0 +1,57 @@
+#version 450 core
+#extension GL_GOOGLE_include_directive : require
+
+#include "data.inc"
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inNormal;
+
+layout(push_constant) uniform PushConstants
+{
+    PushConstantData pc;
+};
+
+layout (binding = 1) uniform sampler2D samplerNormal;
+layout (binding = 2) uniform sampler2D samplerRoughness;
+
+layout (location = 0) out vec4 outAlbedo;
+layout (location = 1) out vec4 outNormal;
+layout (location = 2) out vec2 outMetallicRoughness;
+
+// Schlüter 2013. Normal Mapping Without Precomputed Tangents.
+// http://www.thetenthplanet.de/archives/1180
+mat3 cotangentFrame(vec3 N, vec3 pos, vec2 uv)
+{
+    vec3 dPx = dFdx(pos);
+    vec3 dPy = dFdy(pos);
+    vec2 dTx = dFdx(uv);
+    vec2 dTy = dFdy(uv);
+
+    vec3 dPxC = cross(N, dPx);
+    vec3 dPyC = cross(dPy, N);
+
+    vec3 T = dPyC * dTx.x + dPxC * dTy.x;
+    vec3 B = dPyC * dTx.y + dPxC * dTy.y;
+
+    float invmax = inversesqrt(max(dot(T, T), dot(B, B)));
+
+    return mat3(T * invmax, B * invmax, N);
+}
+
+void main()
+{
+    vec3 normal = normalize(inNormal);
+    if(pc.enableNormalMapping != 0)
+    {
+        mat3 TBN = cotangentFrame(normal, inPos, inUV);
+        vec3 tangentNormal = texture(samplerNormal, inUV).xyz * 2.0 - 1.0;
+        normal = normalize(TBN * tangentNormal);
+    }
+
+    float roughness = texture(samplerRoughness, inUV).x;
+
+    outAlbedo = vec4(pc.color, 1.0);
+    outNormal = vec4(normal, 1.0);
+    outMetallicRoughness = vec2(pc.metallic, roughness);
+}
diff --git a/res/light/gbuffer.fragment.spirv b/res/light/gbuffer.fragment.spirv
new file mode 100644
index 0000000000000000000000000000000000000000..fbfc7ec3054724cb7b79a07be0e24647c50ba383
Binary files /dev/null and b/res/light/gbuffer.fragment.spirv differ
diff --git a/res/light/gbuffer.vert b/res/light/gbuffer.vert
new file mode 100644
index 0000000000000000000000000000000000000000..c1a53258366d80e35fff16bf6805d922b6535974
--- /dev/null
+++ b/res/light/gbuffer.vert
@@ -0,0 +1,35 @@
+#version 450 core
+#extension GL_GOOGLE_include_directive : require
+
+#include "data.inc"
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec2 inUV;
+layout (location = 2) in vec3 inNormal;
+
+layout(push_constant) uniform PushConstants
+{
+    PushConstantData pc;
+};
+
+layout (binding = 0) uniform Ubo
+{
+    UboData ubo;
+};
+
+layout (location = 0) out vec3 outPos;
+layout (location = 1) out vec2 outUV;
+layout (location = 2) out vec3 outNormal;
+
+void main()
+{
+    outPos = vec3(pc.model * vec4(inPos, 1.0));
+    outUV = inUV;
+    outNormal = normalize(mat3(pc.model) * inNormal);
+    // correctly render double-sided materials
+    vec3 V = normalize(ubo.camPos - outPos);
+    if(dot(outNormal, V) < 0.0)
+        outNormal = -outNormal;
+
+    gl_Position = ubo.projection * ubo.view * vec4(outPos, 1.0);
+}
diff --git a/res/light/gbuffer.vertex.spirv b/res/light/gbuffer.vertex.spirv
new file mode 100644
index 0000000000000000000000000000000000000000..d0d60d68998c24b1a50067233c623ec923db9f19
Binary files /dev/null and b/res/light/gbuffer.vertex.spirv differ
diff --git a/res/light/gen_spirv.bat b/res/light/gen_spirv.bat
new file mode 100644
index 0000000000000000000000000000000000000000..dedef7221ba685ff03eb039a5429ebefff63a3ba
--- /dev/null
+++ b/res/light/gen_spirv.bat
@@ -0,0 +1,7 @@
+@ECHO on
+
+glslangValidator -V -o gbuffer.fragment.spirv gbuffer.frag
+glslangValidator -V -o gbuffer.vertex.spirv gbuffer.vert
+
+glslangValidator -V -o lighting.fragment.spirv lighting.frag
+glslangValidator -V -o lighting.vertex.spirv lighting.vert
diff --git a/res/light/gen_spirv.sh b/res/light/gen_spirv.sh
new file mode 100644
index 0000000000000000000000000000000000000000..3c4b2c65deb92de6f79e9b3b210f7f63d5f77305
--- /dev/null
+++ b/res/light/gen_spirv.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+glslangValidator -V -o gbuffer.fragment.spirv gbuffer.frag
+glslangValidator -V -o gbuffer.vertex.spirv gbuffer.vert
+
+glslangValidator -V -o lighting.fragment.spirv lighting.frag
+glslangValidator -V -o lighting.vertex.spirv lighting.vert
diff --git a/res/light/lighting.frag b/res/light/lighting.frag
new file mode 100644
index 0000000000000000000000000000000000000000..a6e800d074d8206d3cacd98e9994e561cd8e2a3c
--- /dev/null
+++ b/res/light/lighting.frag
@@ -0,0 +1,171 @@
+#version 450 core
+#extension GL_GOOGLE_include_directive : require
+
+#include "data.inc"
+
+layout (binding = 0) uniform sampler2D samplerGbufferAlbedo;
+layout (binding = 1) uniform sampler2D samplerGbufferNormal;
+layout (binding = 2) uniform sampler2D samplerGbufferMetallicRoughness;
+layout (binding = 3) uniform sampler2D samplerGbufferDepth;
+
+layout (binding = 4) uniform Ubo
+{
+    UboData ubo;
+};
+
+layout (binding = 5) restrict readonly buffer Sbo_Lights
+{
+    LightData lights[];
+};
+
+layout(location = 0) out vec4 outFragColor;
+
+// Physically based shading, metallic + roughness workflow (GLTF 2.0 core material spec)
+// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material
+// Some GLSL code adapted from
+// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#appendix-b-brdf-implementation
+// https://google.github.io/filament/Filament.md.html
+
+#define INV_PI 0.31831
+
+struct Material
+{
+    vec3 diffuse;
+    vec3 f0;
+    float a;
+};
+
+// Schlick approximation to Fresnel equation using F90 = 1
+// Schlick 1994. An Inexpensive BRDF Model for Physically based Rendering.
+vec3 F_Schlick(float VoH, vec3 F0)
+{
+    float f = pow(1.0 - VoH, 5.0);
+    return f + F0 * (1.0 - f);
+}
+
+// GGX Normal Distribution Function
+// Bruce Walter et al. 2007. Microfacet Models for Refraction through Rough Surfaces.
+float D_GGX(float NoH, float a)
+{
+    a = NoH * a;
+    float k = a / (1.0 - NoH * NoH + a * a);
+    return k * k * INV_PI;
+}
+
+// GGX Geometric Shadowing/Occlusion Function, based on Smith approach
+// height-correlated joint masking-shadowing function
+// Heitz 2014. Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs.
+float V_SmithGGXCorrelated(float NoV, float NoL, float a)
+{
+    float a2 = a * a;
+    float GGXV = NoL * sqrt(NoV * NoV * (1.0 - a2) + a2);
+    float GGXL = NoV * sqrt(NoL * NoL * (1.0 - a2) + a2);
+    return 0.5 / (GGXV + GGXL);
+}
+
+// Lambertian diffuse BRDF
+vec3 diffuseBrdf(Material mat, float VoH)
+{
+    vec3 F = F_Schlick(VoH, mat.f0);
+    return (1.0 - F) * mat.diffuse * INV_PI;
+}
+
+vec3 specularBrdf(Material mat, float NoH, float VoH, float NoV, float NoL)
+{
+    float D = D_GGX(NoH, mat.a);
+    vec3 F = F_Schlick(VoH, mat.f0);
+    float V = V_SmithGGXCorrelated(NoV, NoL, mat.a);
+
+    return (D * V) * F;
+}
+
+// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#appendix-b-brdf-implementation
+vec3 brdf(Material mat, vec3 v, vec3 l, vec3 n)
+{
+    vec3 h = normalize(l + v);
+
+    float NoV = abs(dot(n, v)) + 1e-5;
+    float NoL = clamp(dot(n, l), 0.0, 1.0);
+    float NoH = clamp(dot(n, h), 0.0, 1.0);
+    float VoH = clamp(dot(v, h), 0.0, 1.0);
+
+    return specularBrdf(mat, NoH, VoH, NoV, NoL) + diffuseBrdf(mat, VoH);
+}
+
+// inverse square falloff
+float distanceAttenuation(float distance)
+{
+    return 1.0 / max(distance * distance, 0.01 * 0.01);
+}
+
+// windowing function with smooth transition to 0
+// radius is arbitrary
+// Karis 2014. Real Shading in Unreal Engine 4.
+float distanceAttenuation(float distance, float radius)
+{
+    float nom = clamp(1.0 - pow(distance / radius, 4.0), 0.0, 1.0);
+    return nom * nom * distanceAttenuation(distance);
+}
+
+vec3 screenToEye(vec3 fragCoord, uvec2 resolution, mat4 invProjection)
+{
+    vec3 ndc = vec3(
+        2.0 * fragCoord.xy / vec2(resolution) - 1.0, // -> [-1;1]
+        fragCoord.z // [0;1]
+    );
+    vec4 eye = invProjection * vec4(ndc, 1.0);
+    return eye.xyz / eye.w;
+}
+
+// luminance-only fit of ACES LDR output transform
+// Narkowicz 2016. ACES Filmic Tone Mapping Curve.
+// https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
+vec3 tonemap(vec3 x)
+{
+    return clamp((x * (2.51 * x + 0.03)) / (x * (2.43 * x + 0.59) + 0.14), 0.0, 1.0);
+}
+
+void main()
+{
+    vec2 uv = gl_FragCoord.xy / vec2(ubo.resolution);
+    vec3 albedo = texture(samplerGbufferAlbedo, uv).rgb;
+    vec2 metallicRoughness = texture(samplerGbufferMetallicRoughness, uv).xy;
+    float metallic = metallicRoughness.x;
+    float roughness = metallicRoughness.y;
+    
+    // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-pbr_mat
+
+    const vec3 dielectricSpecular = vec3(0.04, 0.04, 0.04);
+    const vec3 black = vec3(0.0, 0.0, 0.0);
+
+    Material mat;
+    mat.diffuse = mix(albedo * (vec3(1.0) - dielectricSpecular), black, metallic);
+    mat.f0 = mix(dielectricSpecular, albedo, metallic);
+    mat.a = roughness * roughness;
+
+    // restore fragment coordinate from depth
+    float z = texture(samplerGbufferDepth, uv).x;
+    vec3 fragCoord = vec3(gl_FragCoord.xy, z);
+    vec3 pos = screenToEye(fragCoord, ubo.resolution, ubo.invProjection);
+
+    vec3 V = normalize(ubo.camPos - pos);
+    vec3 N = texture(samplerGbufferNormal, uv).xyz;
+
+    vec3 radiance = vec3(0.0);
+    for(uint i = 0; i < ubo.lightCount; i++)
+    {
+        LightData light = lights[i];
+        float dist = distance(light.position, pos);
+        float attenuation = distanceAttenuation(dist, light.radius);
+        if(attenuation > 0.0)
+        {
+            vec3 L = normalize(light.position - pos);
+            vec3 radiance_in = light.intensity * attenuation;
+            float NoL = clamp(dot(N, L), 0.0, 1.0);
+            if(NoL > 0.0)
+                radiance += brdf(mat, V, L, N) * radiance_in * NoL;
+        }
+    }
+    
+    outFragColor = vec4(tonemap(radiance), 1.0);
+}
diff --git a/res/light/lighting.fragment.spirv b/res/light/lighting.fragment.spirv
new file mode 100644
index 0000000000000000000000000000000000000000..6a262c170ff2ab9edfed0d2692ffc042a64f7869
Binary files /dev/null and b/res/light/lighting.fragment.spirv differ
diff --git a/res/light/lighting.vert b/res/light/lighting.vert
new file mode 100644
index 0000000000000000000000000000000000000000..7bec00d3a8b52e4969d858e386cc762085e244dc
--- /dev/null
+++ b/res/light/lighting.vert
@@ -0,0 +1,7 @@
+#version 450 core
+
+void main()
+{
+    vec2 uv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+    gl_Position = vec4(uv * 2.0f + -1.0f, 0.0f, 1.0f);
+}
diff --git a/res/light/lighting.vertex.spirv b/res/light/lighting.vertex.spirv
new file mode 100644
index 0000000000000000000000000000000000000000..d664c7747f5c955ac7ff3fcabafc00644bcb5f87
Binary files /dev/null and b/res/light/lighting.vertex.spirv differ
diff --git a/res/light/normal.png b/res/light/normal.png
new file mode 100644
index 0000000000000000000000000000000000000000..c73c2672b782f9c858189cbf2dad969734435af2
Binary files /dev/null and b/res/light/normal.png differ
diff --git a/res/light/roughness.png b/res/light/roughness.png
new file mode 100644
index 0000000000000000000000000000000000000000..075f9431c83d4c8caa664530f4d4afc3f5bff086
Binary files /dev/null and b/res/light/roughness.png differ
diff --git a/res/spawn/gen_spirv.bat b/res/spawn/gen_spirv.bat
index 076c334b6b8600efe403b9240dc16fee9146aefe..8eac113e715e92f459d0128d5c29eaea005a0c3f 100644
--- a/res/spawn/gen_spirv.bat
+++ b/res/spawn/gen_spirv.bat
@@ -1,7 +1,4 @@
 @ECHO on
 
-glslangValidator -V -x -o spawn.frag.u32 spawn.frag
-glslangValidator -V -x -o spawn.vert.u32 spawn.vert
-
 glslangValidator -V -o fragment.spirv spawn.frag
 glslangValidator -V -o vertex.spirv spawn.vert
diff --git a/res/spawn/gen_spirv.sh b/res/spawn/gen_spirv.sh
index b916c1e9c3cec07ba61f5d226a20c2e5c5d8afe7..6bb0f5872946f32565710d56de83a2706ec80fbd 100644
--- a/res/spawn/gen_spirv.sh
+++ b/res/spawn/gen_spirv.sh
@@ -1,7 +1,4 @@
 #!/bin/bash
 
-glslangValidator -V -x -o spawn.frag.u32 spawn.frag
-glslangValidator -V -x -o spawn.vert.u32 spawn.vert
-
 glslangValidator -V -o fragment.spirv spawn.frag
 glslangValidator -V -o vertex.spirv spawn.vert
diff --git a/res/spawn/spawn.frag.u32 b/res/spawn/spawn.frag.u32
deleted file mode 100644
index accac4cc19c7eeea1f71436ec8f43b3c349a722f..0000000000000000000000000000000000000000
--- a/res/spawn/spawn.frag.u32
+++ /dev/null
@@ -1,22 +0,0 @@
-	// 1011.0.0
-	0x07230203,0x00010000,0x0008000a,0x00000018,0x00000000,0x00020011,0x00000001,0x0006000b,
-	0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
-	0x0008000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000b,0x00000014,
-	0x00030010,0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,
-	0x6e69616d,0x00000000,0x00060005,0x00000009,0x4674756f,0x43676172,0x726f6c6f,0x00000000,
-	0x00040005,0x0000000b,0x6f436e69,0x00726f6c,0x00060005,0x00000010,0x706d6173,0x4372656c,
-	0x726f6c6f,0x00000000,0x00040005,0x00000014,0x56556e69,0x00000000,0x00040047,0x00000009,
-	0x0000001e,0x00000000,0x00040047,0x0000000b,0x0000001e,0x00000000,0x00040047,0x00000010,
-	0x00000022,0x00000000,0x00040047,0x00000010,0x00000021,0x00000002,0x00040047,0x00000014,
-	0x0000001e,0x00000001,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,
-	0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,
-	0x00000003,0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040020,0x0000000a,
-	0x00000001,0x00000007,0x0004003b,0x0000000a,0x0000000b,0x00000001,0x00090019,0x0000000d,
-	0x00000006,0x00000001,0x00000000,0x00000000,0x00000000,0x00000001,0x00000000,0x0003001b,
-	0x0000000e,0x0000000d,0x00040020,0x0000000f,0x00000000,0x0000000e,0x0004003b,0x0000000f,
-	0x00000010,0x00000000,0x00040017,0x00000012,0x00000006,0x00000002,0x00040020,0x00000013,
-	0x00000001,0x00000012,0x0004003b,0x00000013,0x00000014,0x00000001,0x00050036,0x00000002,
-	0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003d,0x00000007,0x0000000c,
-	0x0000000b,0x0004003d,0x0000000e,0x00000011,0x00000010,0x0004003d,0x00000012,0x00000015,
-	0x00000014,0x00050057,0x00000007,0x00000016,0x00000011,0x00000015,0x00050085,0x00000007,
-	0x00000017,0x0000000c,0x00000016,0x0003003e,0x00000009,0x00000017,0x000100fd,0x00010038
diff --git a/res/spawn/spawn.vert.u32 b/res/spawn/spawn.vert.u32
deleted file mode 100644
index fb56eb3207b4ce11fcab8a7d22f01b9d7b280df0..0000000000000000000000000000000000000000
--- a/res/spawn/spawn.vert.u32
+++ /dev/null
@@ -1,53 +0,0 @@
-	// 1011.0.0
-	0x07230203,0x00010000,0x0008000a,0x00000034,0x00000000,0x00020011,0x00000001,0x0006000b,
-	0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
-	0x000b000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000b,0x0000000f,
-	0x00000011,0x00000015,0x0000002b,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,
-	0x6e69616d,0x00000000,0x00050005,0x00000009,0x4374756f,0x726f6c6f,0x00000000,0x00040005,
-	0x0000000b,0x6f436e69,0x00726f6c,0x00040005,0x0000000f,0x5574756f,0x00000056,0x00040005,
-	0x00000011,0x56556e69,0x00000000,0x00060005,0x00000013,0x505f6c67,0x65567265,0x78657472,
-	0x00000000,0x00060006,0x00000013,0x00000000,0x505f6c67,0x7469736f,0x006e6f69,0x00030005,
-	0x00000015,0x00000000,0x00050005,0x00000019,0x5f6f6255,0x656d6143,0x00006172,0x00060006,
-	0x00000019,0x00000000,0x6a6f7270,0x69746365,0x00006e6f,0x00050006,0x00000019,0x00000001,
-	0x77656976,0x00000000,0x00050005,0x0000001b,0x5f6f6275,0x656d6163,0x00006172,0x00050005,
-	0x00000023,0x5f6f6255,0x77617053,0x0000006e,0x00050006,0x00000023,0x00000000,0x65646f6d,
-	0x0000006c,0x00050005,0x00000025,0x5f6f6275,0x77617073,0x0000006e,0x00040005,0x0000002b,
-	0x6f506e69,0x00000073,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000b,
-	0x0000001e,0x00000001,0x00040047,0x0000000f,0x0000001e,0x00000001,0x00040047,0x00000011,
-	0x0000001e,0x00000002,0x00050048,0x00000013,0x00000000,0x0000000b,0x00000000,0x00030047,
-	0x00000013,0x00000002,0x00040048,0x00000019,0x00000000,0x00000005,0x00050048,0x00000019,
-	0x00000000,0x00000023,0x00000000,0x00050048,0x00000019,0x00000000,0x00000007,0x00000010,
-	0x00040048,0x00000019,0x00000001,0x00000005,0x00050048,0x00000019,0x00000001,0x00000023,
-	0x00000040,0x00050048,0x00000019,0x00000001,0x00000007,0x00000010,0x00030047,0x00000019,
-	0x00000002,0x00040047,0x0000001b,0x00000022,0x00000000,0x00040047,0x0000001b,0x00000021,
-	0x00000000,0x00040048,0x00000023,0x00000000,0x00000005,0x00050048,0x00000023,0x00000000,
-	0x00000023,0x00000000,0x00050048,0x00000023,0x00000000,0x00000007,0x00000010,0x00030047,
-	0x00000023,0x00000002,0x00040047,0x00000025,0x00000022,0x00000000,0x00040047,0x00000025,
-	0x00000021,0x00000001,0x00040047,0x0000002b,0x0000001e,0x00000000,0x00020013,0x00000002,
-	0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,
-	0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,0x00000007,0x0004003b,0x00000008,
-	0x00000009,0x00000003,0x00040020,0x0000000a,0x00000001,0x00000007,0x0004003b,0x0000000a,
-	0x0000000b,0x00000001,0x00040017,0x0000000d,0x00000006,0x00000002,0x00040020,0x0000000e,
-	0x00000003,0x0000000d,0x0004003b,0x0000000e,0x0000000f,0x00000003,0x00040020,0x00000010,
-	0x00000001,0x0000000d,0x0004003b,0x00000010,0x00000011,0x00000001,0x0003001e,0x00000013,
-	0x00000007,0x00040020,0x00000014,0x00000003,0x00000013,0x0004003b,0x00000014,0x00000015,
-	0x00000003,0x00040015,0x00000016,0x00000020,0x00000001,0x0004002b,0x00000016,0x00000017,
-	0x00000000,0x00040018,0x00000018,0x00000007,0x00000004,0x0004001e,0x00000019,0x00000018,
-	0x00000018,0x00040020,0x0000001a,0x00000002,0x00000019,0x0004003b,0x0000001a,0x0000001b,
-	0x00000002,0x00040020,0x0000001c,0x00000002,0x00000018,0x0004002b,0x00000016,0x0000001f,
-	0x00000001,0x0003001e,0x00000023,0x00000018,0x00040020,0x00000024,0x00000002,0x00000023,
-	0x0004003b,0x00000024,0x00000025,0x00000002,0x00040017,0x00000029,0x00000006,0x00000003,
-	0x00040020,0x0000002a,0x00000001,0x00000029,0x0004003b,0x0000002a,0x0000002b,0x00000001,
-	0x0004002b,0x00000006,0x0000002d,0x3f800000,0x00050036,0x00000002,0x00000004,0x00000000,
-	0x00000003,0x000200f8,0x00000005,0x0004003d,0x00000007,0x0000000c,0x0000000b,0x0003003e,
-	0x00000009,0x0000000c,0x0004003d,0x0000000d,0x00000012,0x00000011,0x0003003e,0x0000000f,
-	0x00000012,0x00050041,0x0000001c,0x0000001d,0x0000001b,0x00000017,0x0004003d,0x00000018,
-	0x0000001e,0x0000001d,0x00050041,0x0000001c,0x00000020,0x0000001b,0x0000001f,0x0004003d,
-	0x00000018,0x00000021,0x00000020,0x00050092,0x00000018,0x00000022,0x0000001e,0x00000021,
-	0x00050041,0x0000001c,0x00000026,0x00000025,0x00000017,0x0004003d,0x00000018,0x00000027,
-	0x00000026,0x00050092,0x00000018,0x00000028,0x00000022,0x00000027,0x0004003d,0x00000029,
-	0x0000002c,0x0000002b,0x00050051,0x00000006,0x0000002e,0x0000002c,0x00000000,0x00050051,
-	0x00000006,0x0000002f,0x0000002c,0x00000001,0x00050051,0x00000006,0x00000030,0x0000002c,
-	0x00000002,0x00070050,0x00000007,0x00000031,0x0000002e,0x0000002f,0x00000030,0x0000002d,
-	0x00050091,0x00000007,0x00000032,0x00000028,0x00000031,0x00050041,0x00000008,0x00000033,
-	0x00000015,0x00000017,0x0003003e,0x00000033,0x00000032,0x000100fd,0x00010038
diff --git a/res/tool/imgui/fragment.spirv b/res/tool/imgui/fragment.spirv
deleted file mode 100644
index df76a7b54c236cbb5e4ca94161d8a25e15b3f87c..0000000000000000000000000000000000000000
Binary files a/res/tool/imgui/fragment.spirv and /dev/null differ
diff --git a/res/tool/imgui/gen_spirv.bat b/res/tool/imgui/gen_spirv.bat
index 1b488c1636d4c1574013b1a3a21f15773dbbcbb9..681c2b8f1ea6cfa18090cddb6f2f56eaebfac3e2 100644
--- a/res/tool/imgui/gen_spirv.bat
+++ b/res/tool/imgui/gen_spirv.bat
@@ -2,6 +2,3 @@
 
 glslangValidator -V -x -o imgui.frag.u32 imgui.frag
 glslangValidator -V -x -o imgui.vert.u32 imgui.vert
-
-glslangValidator -V -o fragment.spirv imgui.frag
-glslangValidator -V -o vertex.spirv imgui.vert
diff --git a/res/tool/imgui/gen_spirv.sh b/res/tool/imgui/gen_spirv.sh
index 145bcd988b08eb20e8cf551d20d6c2d72c4e36c6..1587b045a23a804f27cfbe6027643f6d5d1f185e 100644
--- a/res/tool/imgui/gen_spirv.sh
+++ b/res/tool/imgui/gen_spirv.sh
@@ -2,6 +2,3 @@
 
 glslangValidator -V -x -o imgui.frag.u32 imgui.frag
 glslangValidator -V -x -o imgui.vert.u32 imgui.vert
-
-glslangValidator -V -o fragment.spirv imgui.frag
-glslangValidator -V -o vertex.spirv imgui.vert
diff --git a/res/tool/imgui/imgui.frag.u32 b/res/tool/imgui/imgui.frag.u32
index 1b5de78e6a17ab140d9876936dbbc73f4332e0ef..d48648205d0a248ea37fb1efb0c8e27638f46482 100644
--- a/res/tool/imgui/imgui.frag.u32
+++ b/res/tool/imgui/imgui.frag.u32
@@ -1,4 +1,4 @@
-	// 1011.0.0
+	// 1011.4.0
 	0x07230203,0x00010000,0x0008000a,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006000b,
 	0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
 	0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x00030010,
diff --git a/res/tool/imgui/imgui.vert.u32 b/res/tool/imgui/imgui.vert.u32
index 797858398400d89872e827f75fdf61da1cb12966..3e72b5114184796bfd9d68eff7aa39c0860a3ecf 100644
--- a/res/tool/imgui/imgui.vert.u32
+++ b/res/tool/imgui/imgui.vert.u32
@@ -1,4 +1,4 @@
-	// 1011.0.0
+	// 1011.4.0
 	0x07230203,0x00010000,0x0008000a,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b,
 	0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
 	0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015,
diff --git a/res/tool/imgui/vertex.spirv b/res/tool/imgui/vertex.spirv
deleted file mode 100644
index 7e9aa0f2efddbf2bfb79e38f1e59f6ffdb41e9ec..0000000000000000000000000000000000000000
Binary files a/res/tool/imgui/vertex.spirv and /dev/null differ
diff --git a/res/triangle/gen_spirv.bat b/res/triangle/gen_spirv.bat
index 3e8dcf5de9bf6f4a55f211682e58e396ee85c7da..62ab62a900b383472868fb19711b9a449f78dc5d 100644
--- a/res/triangle/gen_spirv.bat
+++ b/res/triangle/gen_spirv.bat
@@ -1,7 +1,4 @@
 @ECHO on
 
-glslangValidator -V -x -o triangle.frag.u32 triangle.frag
-glslangValidator -V -x -o triangle.vert.u32 triangle.vert
-
 glslangValidator -V -o fragment.spirv triangle.frag
 glslangValidator -V -o vertex.spirv triangle.vert
diff --git a/res/triangle/gen_spirv.sh b/res/triangle/gen_spirv.sh
index f8e28dcbdb150e863abd8080c3910d63633eb8b5..7d60294b8643b8152a1fc05afc5bb4090b18499b 100644
--- a/res/triangle/gen_spirv.sh
+++ b/res/triangle/gen_spirv.sh
@@ -1,7 +1,4 @@
 #!/bin/bash
 
-glslangValidator -V -x -o triangle.frag.u32 triangle.frag
-glslangValidator -V -x -o triangle.vert.u32 triangle.vert
-
 glslangValidator -V -o fragment.spirv triangle.frag
 glslangValidator -V -o vertex.spirv triangle.vert
diff --git a/res/triangle/triangle.frag.u32 b/res/triangle/triangle.frag.u32
deleted file mode 100644
index 64387fc29388c3d2fa7f4069def3eb9efb4d5fc0..0000000000000000000000000000000000000000
--- a/res/triangle/triangle.frag.u32
+++ /dev/null
@@ -1,13 +0,0 @@
-	// 1011.0.0
-	0x07230203,0x00010000,0x0008000a,0x0000000d,0x00000000,0x00020011,0x00000001,0x0006000b,
-	0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
-	0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000b,0x00030010,
-	0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
-	0x00000000,0x00060005,0x00000009,0x4674756f,0x43676172,0x726f6c6f,0x00000000,0x00040005,
-	0x0000000b,0x6f436e69,0x00726f6c,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,
-	0x0000000b,0x0000001e,0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,
-	0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,
-	0x00000008,0x00000003,0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040020,
-	0x0000000a,0x00000001,0x00000007,0x0004003b,0x0000000a,0x0000000b,0x00000001,0x00050036,
-	0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003d,0x00000007,
-	0x0000000c,0x0000000b,0x0003003e,0x00000009,0x0000000c,0x000100fd,0x00010038
diff --git a/res/triangle/triangle.vert.u32 b/res/triangle/triangle.vert.u32
deleted file mode 100644
index c299f2421641c3666dc662cb881362f16f312717..0000000000000000000000000000000000000000
--- a/res/triangle/triangle.vert.u32
+++ /dev/null
@@ -1,26 +0,0 @@
-	// 1011.0.0
-	0x07230203,0x00010000,0x0008000a,0x0000001c,0x00000000,0x00020011,0x00000001,0x0006000b,
-	0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
-	0x0009000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000b,0x0000000f,
-	0x00000014,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,0x00000000,
-	0x00050005,0x00000009,0x4374756f,0x726f6c6f,0x00000000,0x00040005,0x0000000b,0x6f436e69,
-	0x00726f6c,0x00060005,0x0000000d,0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,
-	0x0000000d,0x00000000,0x505f6c67,0x7469736f,0x006e6f69,0x00030005,0x0000000f,0x00000000,
-	0x00040005,0x00000014,0x6f506e69,0x00000073,0x00040047,0x00000009,0x0000001e,0x00000000,
-	0x00040047,0x0000000b,0x0000001e,0x00000001,0x00050048,0x0000000d,0x00000000,0x0000000b,
-	0x00000000,0x00030047,0x0000000d,0x00000002,0x00040047,0x00000014,0x0000001e,0x00000000,
-	0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020,
-	0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,0x00000007,
-	0x0004003b,0x00000008,0x00000009,0x00000003,0x00040020,0x0000000a,0x00000001,0x00000007,
-	0x0004003b,0x0000000a,0x0000000b,0x00000001,0x0003001e,0x0000000d,0x00000007,0x00040020,
-	0x0000000e,0x00000003,0x0000000d,0x0004003b,0x0000000e,0x0000000f,0x00000003,0x00040015,
-	0x00000010,0x00000020,0x00000001,0x0004002b,0x00000010,0x00000011,0x00000000,0x00040017,
-	0x00000012,0x00000006,0x00000003,0x00040020,0x00000013,0x00000001,0x00000012,0x0004003b,
-	0x00000013,0x00000014,0x00000001,0x0004002b,0x00000006,0x00000016,0x3f800000,0x00050036,
-	0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003d,0x00000007,
-	0x0000000c,0x0000000b,0x0003003e,0x00000009,0x0000000c,0x0004003d,0x00000012,0x00000015,
-	0x00000014,0x00050051,0x00000006,0x00000017,0x00000015,0x00000000,0x00050051,0x00000006,
-	0x00000018,0x00000015,0x00000001,0x00050051,0x00000006,0x00000019,0x00000015,0x00000002,
-	0x00070050,0x00000007,0x0000001a,0x00000017,0x00000018,0x00000019,0x00000016,0x00050041,
-	0x00000008,0x0000001b,0x0000000f,0x00000011,0x0003003e,0x0000001b,0x0000001a,0x000100fd,
-	0x00010038