/
d.vision
/
division_engine_cpp
Обзор
Документация
Войти
/
d.vision
/
division_engine_cpp
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/canvas/rect_drawer.cpp
181 строка
6 KB
den163
Fixed bug found with sanitizer
02 дек 2024, 18:16
02 дек 2024, 18:16
a1c7179
Код
Авторство
О чём код?
#include "canvas/rect_drawer.hpp" #include "canvas/components/render_batch.hpp" #include "core/alpha_blend.hpp" #include "core/context.hpp" #include "core/render_pass_instance_builder.hpp" #include "canvas/components/render_texture.hpp" #include "glm/ext/vector_float4.hpp" #include "utility/algorithm.hpp" #include <division_engine_core/render_pass_descriptor.h> #include <division_engine_core/render_pass_instance.h> #include <division_engine_core/vertex_buffer.h> #include <algorithm> #include <filesystem> #include <iterator> #include <ranges> #include <vector> namespace division_engine::canvas { using namespace components; RectDrawer::RectDrawer(State& state, size_t rect_capacity) : _texture_bindings({ DivisionIdWithBinding { .id = state.white_texture_id, .shader_location = TEXTURE_LOCATION, } }) , _ctx(state.context) , _screen_size_uniform(DivisionIdWithBinding { .id = state.screen_size_uniform_id, .shader_location = SCREEN_SIZE_UNIFORM_LOCATION, }) , _vertex_buffer_id(make_vertex_buffer(_ctx, rect_capacity)) , _instance_capacity(rect_capacity) { using path = std::filesystem::path; _shader_id = _ctx.create_bundled_shader(path { "resources" } / "shaders" / "canvas" / "rect"); _render_pass_descriptor_id = _ctx.render_pass_descriptor_builder() .shader(_shader_id) .vertex_buffer(_vertex_buffer_id) .enable_aplha_blending( core::AlphaBlend { DIVISION_ALPHA_BLEND_SRC_ALPHA, DIVISION_ALPHA_BLEND_ONE_MINUS_SRC_ALPHA, }, DIVISION_ALPHA_BLEND_OP_ADD ) .build(); _query = state.world .query_builder< const RenderBounds, const RenderableRect, const RenderOrder, const RenderTexture>() .term<RenderBatch>() .up(flecs::IsA) .term<RenderTexture>() .up(flecs::IsA) .order_by<RenderOrder>([](auto, const RenderOrder* x, auto, const RenderOrder* y) { return x->compare(*y); }) .instanced() .build(); } RectDrawer::~RectDrawer() { _ctx.delete_shader(_shader_id); _ctx.delete_vertex_buffer(_vertex_buffer_id); } void RectDrawer::fill_render_queue(State& state) { auto overall_instance_count = 0; const auto needed_capacity = _query.count(); if (_instance_capacity < needed_capacity) { _ctx.resize_vertex_buffer( _vertex_buffer_id, DivisionVertexBufferSize { .vertex_count = RECT_VERTICES.size(), .index_count = RECT_INDICES.size(), .instance_count = static_cast<uint32_t>(needed_capacity) } ); _instance_capacity = needed_capacity; } auto data = _ctx.borrow_vertex_buffer_data<RectVertex, RectInstance>(_vertex_buffer_id); auto instances = data.per_instance_data(); _texture_bindings.clear(); _texture_bindings.reserve(_query.count()); _query.iter( [&](flecs::iter& it, const RenderBounds* render_bounds, const RenderableRect* rects, const RenderOrder* ord_ptr, const RenderTexture* tex_ptr) { _texture_bindings.emplace_back(DivisionIdWithBinding { .id = tex_ptr->texture_id, .shader_location = TEXTURE_LOCATION, }); const auto first_instance = overall_instance_count; const auto rect_count = it.count(); auto batch_instances = instances.subspan(first_instance, rect_count); for (auto i : it) { const auto& rect = rects[i]; const auto& bounds = render_bounds[i].value; batch_instances[i] = RectInstance { .size = bounds.size(), .position = glm::vec2 { bounds.left(), bounds.bottom() }, .color = rect.color, .tr_br_tl_bl_border_radius = rect.border_radius.tr_br_tl_bl, }; } overall_instance_count += static_cast<int>(rect_count); if (rect_count == 0) { return; } state.render_queue.enqueue_pass( make_render_pass_instance(&_texture_bindings.back(), first_instance, rect_count), ord_ptr[0] ); } ); } DivisionId RectDrawer::make_vertex_buffer(core::Context& context_helper, uint32_t instance_capacity) { auto id = context_helper.create_vertex_buffer<RectVertex, RectInstance>( core::VertexBufferSize { .vertex_count = RECT_VERTICES.size(), .index_count = RECT_INDICES.size(), .instance_count = instance_capacity, }, core::Topology::DIVISION_TOPOLOGY_TRIANGLES ); auto data = context_helper.borrow_vertex_buffer_data<RectVertex, RectInstance>(id); std::ranges::copy(RECT_VERTICES, data.per_vertex_data().data()); std::ranges::copy(RECT_INDICES, data.index_data().data()); return id; } DivisionRenderPassInstance RectDrawer::make_render_pass_instance( DivisionIdWithBinding* texture_ptr, size_t first_instance, size_t instance_count ) { return core::RenderPassInstanceBuilder { _render_pass_descriptor_id } .uniform_fragment_buffers({ &_screen_size_uniform, 1 }) .uniform_vertex_buffers({ &_screen_size_uniform, 1 }) .fragment_textures({ texture_ptr, 1 }) .vertices(RECT_VERTICES.size()) .indices(RECT_INDICES.size()) .instances(instance_count, first_instance) .build(); } }