/
d.vision
/
division_engine_cpp
Обзор
Документация
Войти
/
d.vision
/
division_engine_cpp
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/core/context.cpp
279 строк
8 KB
den163
Improved SDF fonts visuals
05 дек 2024, 01:56
05 дек 2024, 01:56
8dec6fc
Код
Авторство
О чём код?
#include <cassert> #include <cstdint> #include <exception> #include <glm/ext/vector_int2.hpp> #include <glm/vec4.hpp> #include <sstream> #include <stb_image.h> #include <string> #include <tuple> #include <division_engine_core/input.h> #include <division_engine_core/render_pass_instance.h> #include <division_engine_core/renderer.h> #include <division_engine_core/shader.h> #include <division_engine_core/texture.h> #include <division_engine_core/types/color.h> #include <division_engine_core/uniform_buffer.h> #include <division_engine_core/vertex_buffer.h> #include "core/context.hpp" #include "core/exception.hpp" #include "core/input.hpp" #include "core/texture_settings.hpp" #include "division_engine_core/font.h" #include "division_engine_core/types/font.h" #include "division_engine_core/types/id.h" #include "division_engine_core/types/keycode.h" #include "division_engine_core/types/texture.h" #include "utility/file.hpp" namespace division_engine::core { Context::Context(DivisionContext* context) : _ctx(context) { stbi_set_flip_vertically_on_load(true); } DivisionId Context::create_bundled_shader(const std::filesystem::path& path_without_extension) { using path = std::filesystem::path; auto [vertex_entry_point, vertex_path, fragment_entry_point, fragment_path] = #if __APPLE__ std::make_tuple( "vert", path { path_without_extension }.concat(".vert.gen.metal"), "frag", path { path_without_extension }.concat(".frag.gen.metal") ); #else std::make_tuple( "main", path { path_without_extension }.concat(".vert"), "main", path { path_without_extension }.concat(".frag") ); #endif auto vertex_source = division_engine::utility::file::read_text(vertex_path); auto fragment_source = division_engine::utility::file::read_text(fragment_path); auto shader_descs = std::array { DivisionShaderSourceDescriptor { .type = DivisionShaderType::DIVISION_SHADER_VERTEX, .entry_point_name = vertex_entry_point, .source = vertex_source.c_str(), .source_size = static_cast<uint32_t>(vertex_source.length()), }, DivisionShaderSourceDescriptor { .type = DivisionShaderType::DIVISION_SHADER_FRAGMENT, .entry_point_name = fragment_entry_point, .source = fragment_source.c_str(), .source_size = static_cast<uint32_t>(fragment_source.length()), } }; DivisionId shader_program = 0; if (!division_engine_shader_program_alloc( _ctx, shader_descs.data(), shader_descs.size(), &shader_program )) { throw Exception { std::string { "Failed to create a shader" } }; } return shader_program; } void Context::delete_shader(DivisionId shader_id) { division_engine_shader_program_free(_ctx, shader_id); } DivisionId Context::create_vertex_buffer( std::span<const DivisionVertexAttributeSettings> per_vertex_attributes, std::span<const DivisionVertexAttributeSettings> per_instance_attributes, VertexBufferSize buffer_size, Topology topology ) { const DivisionVertexBufferConstSettings settings { .size = buffer_size, .per_vertex_attributes = per_vertex_attributes.data(), .per_instance_attributes = per_instance_attributes.data(), .per_vertex_attribute_count = static_cast<int32_t>(per_vertex_attributes.size()), .per_instance_attribute_count = static_cast<int32_t>(per_instance_attributes.size()), .topology = topology }; DivisionId vertex_buffer_id = 0; if (!division_engine_vertex_buffer_alloc(_ctx, &settings, &vertex_buffer_id)) { throw Exception { "Failed to create vertex buffer" }; } return vertex_buffer_id; } void Context::resize_vertex_buffer(DivisionId vertex_buffer_id, DivisionVertexBufferSize new_size) { if (!division_engine_vertex_buffer_resize(_ctx, vertex_buffer_id, new_size)) { throw Exception { "Failed to resize vertex buffer" }; } } void Context::delete_vertex_buffer(DivisionId vertex_buffer_id) { division_engine_vertex_buffer_free(_ctx, vertex_buffer_id); } void Context::delete_uniform(DivisionId buffer_id) { division_engine_uniform_buffer_free(_ctx, buffer_id); } DivisionId Context::create_uniform(DivisionUniformBufferDescriptor descriptor) { DivisionId buffer_id = 0; if (!division_engine_uniform_buffer_alloc(_ctx, descriptor, &buffer_id)) { throw Exception { "Failed to create uniform buffer" }; } return buffer_id; } void Context::draw_render_passes( std::span<const DivisionRenderPassInstance> render_pass_instances, glm::vec4 clear_color ) { division_engine_render_pass_instance_draw( _ctx, reinterpret_cast<DivisionColor*>(&clear_color), // NOLINT render_pass_instances.data(), render_pass_instances.size() ); } DivisionId Context::create_texture(const std::string& image_file_path) { int width, height, src_channels; // NOLINT if (!stbi_info(image_file_path.c_str(), &width, &height, &src_channels)) { throw new Exception { std::string("Failed to get info about the image by path ") + image_file_path }; } const int NOT_SUPPORTED_CHANNELS = 3; const int RGB_CHANNELS = 4; int dst_channels = src_channels == NOT_SUPPORTED_CHANNELS ? RGB_CHANNELS : src_channels; DivisionTextureFormat texture_fmt; // NOLINT switch (dst_channels) { case 1: texture_fmt = DIVISION_TEXTURE_FORMAT_R8Uint; break; case 4: texture_fmt = DIVISION_TEXTURE_FORMAT_RGBA32Uint; break; default: throw new Exception { std::string("Unsupported number of image channels") }; } auto* image_ptr = stbi_load(image_file_path.c_str(), &width, &height, &src_channels, dst_channels); if (!image_ptr) { throw new Exception { std::string("Failed to load image by path ") + image_file_path }; } const auto texture_id = create_texture(TextureSettings(glm::ivec2 { width, height }, texture_fmt)); set_texture_data(texture_id, image_ptr); stbi_image_free(image_ptr); return texture_id; } DivisionId Context::create_texture(const TextureSettings& texture_settings) { DivisionTexture texture { .channels_swizzle = texture_settings.channels_swizzle.value_or(TextureSettings::DEFAULT_CHANNELS_SWIZZLE), .texture_format = texture_settings.format, .min_filter = texture_settings.min_filter, .mag_filter = texture_settings.mag_filter, .width = static_cast<uint32_t>(texture_settings.size.x), .height = static_cast<uint32_t>(texture_settings.size.y), .has_channels_swizzle = texture_settings.channels_swizzle.has_value(), }; DivisionId id = 0; if (!division_engine_texture_alloc(_ctx, &texture, &id)) { throw Exception { "Failed to create a texture" }; } return id; } void Context::set_texture_data(DivisionId texture_id, const uint8_t* data) { division_engine_texture_set_data(_ctx, texture_id, data); } void Context::delete_texture(DivisionId texture_id) { division_engine_texture_free(_ctx, texture_id); } glm::vec2 Context::get_screen_size() const { return { _ctx->renderer_context->frame_buffer_width, _ctx->renderer_context->frame_buffer_height, }; } glm::vec2 Context::get_mouse_position() const { const auto input_ctx = _ctx->input_context->input.mouse; return { input_ctx.pos_x, input_ctx.pos_y }; } bool Context::is_mouse_button_pressed(int32_t mouse_button) const { return DIVISION_INPUT_GET_MOUSE_KEY_STATE( _ctx->input_context->input.mouse.mouse_button_state_mask, mouse_button ); } bool Context::is_key_pressed(DivisionKeycode key) const { return DIVISION_INPUT_GET_KEYBOARD_KEY_STATE( _ctx->input_context->input.keyboard.key_state_mask, key //NOLINT ); } DivisionId Context::create_font(const std::filesystem::path& font_path, uint32_t font_height) { DivisionId font_id; // NOLINT if (!division_engine_font_alloc(_ctx, font_path.c_str(), font_height, &font_id)) { throw Exception { std::string { "Failed to open font by path: " } + font_path.c_str(), }; } return font_id; } void Context::delete_font(DivisionId font_id) { division_engine_font_free(_ctx, font_id); } }