Skip to content

Commit

Permalink
ui: Add shadow rendering around windows
Browse files Browse the repository at this point in the history
  • Loading branch information
yeetari committed May 16, 2024
1 parent 43f4b4b commit 2ae524b
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 4 deletions.
8 changes: 6 additions & 2 deletions engine/include/vull/ui/painter.hh
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,18 @@ private:
FontAtlas *m_atlas{nullptr};

void compile(vk::Context &context, vk::CommandBuffer &cmd_buf, Vec2u viewport_extent,
const vk::SampledImage &null_image);
const vk::SampledImage &null_image, const vk::SampledImage &shadow_image);
uint32_t get_texture_index(const vk::SampledImage &image);

public:
Painter() { m_bound_textures.push({}); }
Painter() {
m_bound_textures.push({});
m_bound_textures.push({});
}

void bind_atlas(FontAtlas &atlas);
void paint_rect(LayoutPoint position, LayoutSize size, const Colour &colour);
void paint_shadow(LayoutPoint p, LayoutSize s);
void paint_image(LayoutPoint position, LayoutSize size, const vk::SampledImage &image);
void paint_text(Font &font, LayoutPoint position, const Colour &colour, StringView text);
void set_scissor(LayoutPoint position, LayoutSize size);
Expand Down
1 change: 1 addition & 0 deletions engine/include/vull/ui/renderer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Renderer {
vkb::DescriptorSetLayout m_descriptor_set_layout{nullptr};
vk::Pipeline m_pipeline;
vk::Image m_null_image;
vk::Image m_shadow_image;

public:
explicit Renderer(vk::Context &context);
Expand Down
35 changes: 34 additions & 1 deletion engine/sources/ui/painter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,38 @@ void Painter::paint_rect(LayoutPoint position, LayoutSize size, const Colour &co
});
}

void Painter::paint_shadow(LayoutPoint p, LayoutSize s) {
auto push_cmd = [this](LayoutPoint start, LayoutPoint end, Vec2f uv_a, Vec2f uv_c) {
m_commands.push(PaintCommand{
.position = start.round(),
.size = (end - start).round(),
.variant{TextCommand{
.colour = Colour::from_rgb(0.0f, 0.0f, 0.0f, 2.1f),
.uv_a = uv_a,
.uv_c = uv_c,
.texture_index = 1,
}},
});
};

float uv_0 = 0.0f;
float uv_1 = 0.333333f;
float uv_2 = 0.666666f;
float uv_3 = 1.0f;

auto m = p + s;
auto size = LayoutUnit::from_int_pixels(30);

push_cmd(LayoutPoint(p.x() - size, p.y() - size), p, {uv_0, uv_0}, {uv_1, uv_1});
push_cmd(LayoutPoint(p.x(), p.y() - size), LayoutPoint(m.x(), p.y()), {uv_1, uv_0}, {uv_2, uv_1});
push_cmd(LayoutPoint(m.x(), p.y() - size), LayoutPoint(m.x() + size, p.y()), {uv_2, uv_0}, {uv_3, uv_1});
push_cmd(LayoutPoint(p.x() - size, p.y()), LayoutPoint(p.x(), m.y()), {uv_0, uv_1}, {uv_1, uv_2});
push_cmd(LayoutPoint(m.x(), p.y()), LayoutPoint(m.x() + size, m.y()), {uv_2, uv_1}, {uv_3, uv_2});
push_cmd(LayoutPoint(p.x() - size, m.y()), LayoutPoint(p.x(), m.y() + size), {uv_0, uv_2}, {uv_1, uv_3});
push_cmd(LayoutPoint(p.x(), m.y()), LayoutPoint(m.x(), m.y() + size), {uv_1, uv_2}, {uv_2, uv_3});
push_cmd(LayoutPoint(m.x(), m.y()), LayoutPoint(m.x() + size, m.y() + size), {uv_2, uv_2}, {uv_3, uv_3});
}

void Painter::paint_image(LayoutPoint position, LayoutSize size, const vk::SampledImage &image) {
m_commands.push(PaintCommand{
.position = position.floor(),
Expand Down Expand Up @@ -101,13 +133,14 @@ void Painter::unset_scissor() {
}

void Painter::compile(vk::Context &context, vk::CommandBuffer &cmd_buf, Vec2u viewport_extent,
const vk::SampledImage &null_image) {
const vk::SampledImage &null_image, const vk::SampledImage &shadow_image) {
const auto descriptor_size = context.descriptor_size(vkb::DescriptorType::CombinedImageSampler);
auto descriptor_buffer =
context.create_buffer(m_bound_textures.size() * descriptor_size, vkb::BufferUsage::SamplerDescriptorBufferEXT,
vk::MemoryUsage::HostToDevice);

m_bound_textures[0] = BoundTexture{*null_image.view(), null_image.sampler()};
m_bound_textures[1] = BoundTexture{*shadow_image.view(), shadow_image.sampler()};

auto *descriptor_data = descriptor_buffer.mapped<uint8_t>();
for (const auto &texture : m_bound_textures) {
Expand Down
67 changes: 66 additions & 1 deletion engine/sources/ui/renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
#include <vull/support/assert.hh>
#include <vull/support/function.hh>
#include <vull/support/result.hh>
#include <vull/support/unique_ptr.hh>
#include <vull/support/utility.hh>
#include <vull/ui/painter.hh>
#include <vull/vpak/file_system.hh>
#include <vull/vpak/reader.hh>
#include <vull/vulkan/buffer.hh>
#include <vull/vulkan/command_buffer.hh>
#include <vull/vulkan/context.hh>
#include <vull/vulkan/image.hh>
Expand Down Expand Up @@ -103,6 +107,59 @@ Renderer::Renderer(vk::Context &context) : m_context(context) {
.subresourceRange = m_null_image.full_view().range(),
});
});

vkb::ImageCreateInfo shadow_image_ci{
.sType = vkb::StructureType::ImageCreateInfo,
.imageType = vkb::ImageType::_2D,
.format = vkb::Format::R8G8B8A8Srgb,
.extent = {384, 384, 1},
.mipLevels = 1,
.arrayLayers = 1,
.samples = vkb::SampleCount::_1,
.tiling = vkb::ImageTiling::Optimal,
.usage = vkb::ImageUsage::Sampled | vkb::ImageUsage::TransferDst,
.sharingMode = vkb::SharingMode::Exclusive,
.initialLayout = vkb::ImageLayout::Undefined,
};
m_shadow_image = m_context.create_image(shadow_image_ci, vk::MemoryUsage::DeviceOnly);

auto staging_buffer =
m_context.create_buffer(384 * 384 * 4, vkb::BufferUsage::TransferSrc, vk::MemoryUsage::HostOnly);
auto stream = vpak::open("/9slice");
VULL_EXPECT(stream->read({staging_buffer.mapped_raw(), staging_buffer.size()}));

queue->immediate_submit([&](const vk::CommandBuffer &cmd_buf) {
vkb::ImageMemoryBarrier2 transfer_write_barrier{
.sType = vkb::StructureType::ImageMemoryBarrier2,
.dstStageMask = vkb::PipelineStage2::Copy,
.dstAccessMask = vkb::Access2::TransferWrite,
.oldLayout = vkb::ImageLayout::Undefined,
.newLayout = vkb::ImageLayout::TransferDstOptimal,
.image = *m_shadow_image,
.subresourceRange = m_shadow_image.full_view().range(),
};
vkb::BufferImageCopy copy{
.imageSubresource{
.aspectMask = vkb::ImageAspect::Color,
.layerCount = 1,
},
.imageExtent = {384, 384, 1},
};
vkb::ImageMemoryBarrier2 image_read_barrier{
.sType = vkb::StructureType::ImageMemoryBarrier2,
.srcStageMask = vkb::PipelineStage2::Copy,
.srcAccessMask = vkb::Access2::TransferWrite,
.dstStageMask = vkb::PipelineStage2::AllCommands,
.dstAccessMask = vkb::Access2::ShaderRead,
.oldLayout = vkb::ImageLayout::TransferDstOptimal,
.newLayout = vkb::ImageLayout::ReadOnlyOptimal,
.image = *m_shadow_image,
.subresourceRange = m_shadow_image.full_view().range(),
};
cmd_buf.image_barrier(transfer_write_barrier);
cmd_buf.copy_buffer_to_image(staging_buffer, m_shadow_image, vkb::ImageLayout::TransferDstOptimal, copy);
cmd_buf.image_barrier(image_read_barrier);
});
}

Renderer::~Renderer() {
Expand All @@ -122,7 +179,15 @@ void Renderer::build_pass(vk::RenderGraph &graph, vk::ResourceId &target, Painte
.b = vkb::ComponentSwizzle::One,
.a = vkb::ComponentSwizzle::One,
})
.sampled(vk::Sampler::Nearest));
.sampled(vk::Sampler::Nearest),
m_shadow_image
.swizzle_view({
.r = vkb::ComponentSwizzle::One,
.g = vkb::ComponentSwizzle::One,
.b = vkb::ComponentSwizzle::One,
.a = vkb::ComponentSwizzle::Identity,
})
.sampled(vk::Sampler::Linear));
});
}

Expand Down
2 changes: 2 additions & 0 deletions engine/sources/ui/window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ void Window::paint(Painter &painter, LayoutPoint position) const {
painter.paint_rect(position + m_content_pane->offset_in_parent(),
{computed_width(), computed_height() - m_title_pane->computed_height()}, colour);

painter.paint_shadow(position, computed_size());

// Paint children.
Pane::paint(painter, position);
}
Expand Down

0 comments on commit 2ae524b

Please sign in to comment.