From 8de74d2e1b3f4d65709a86808f24a63b08380432 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Wed, 20 Oct 2021 14:20:03 +0800 Subject: [PATCH] Revise vertex buffer and vertex attribute classes, add text scene object class --- CMakeLists.txt | 1 - src/debug/performance-sampler.hpp | 2 +- src/entity/systems/painting.cpp | 18 +- src/entity/systems/subterrain.cpp | 47 ++- src/entity/systems/terrain.cpp | 87 ++++- src/event/event-dispatcher.hpp | 2 +- src/event/event.hpp | 2 +- src/game/bootloader.cpp | 43 ++- src/game/states/loading.cpp | 115 ++++++- src/geom/convex-hull.hpp | 2 +- src/geom/morton.hpp | 2 +- src/gl/buffer-usage.hpp | 23 +- src/gl/gl.hpp | 2 +- src/gl/rasterizer.hpp | 2 +- src/gl/shader-object.hpp | 2 +- src/gl/vertex-array.cpp | 51 ++- src/gl/vertex-array.hpp | 56 +++- src/gl/vertex-attribute.hpp | 69 ++++ src/gl/vertex-buffer.cpp | 39 ++- src/gl/vertex-buffer.hpp | 69 +++- src/math/random.hpp | 2 +- src/renderer/material-property.hpp | 2 +- src/renderer/material.hpp | 2 +- src/renderer/passes/bloom-pass.cpp | 16 +- src/renderer/passes/final-pass.cpp | 16 +- src/renderer/passes/material-pass.cpp | 4 +- src/renderer/passes/outline-pass.cpp | 4 +- src/renderer/passes/sky-pass.cpp | 4 +- src/renderer/passes/ui-pass.cpp | 4 +- src/renderer/render-operation.hpp | 2 +- src/renderer/renderer.cpp | 28 ++ src/renderer/renderer.hpp | 2 + src/renderer/simple-render-pass.cpp | 16 +- ...ex-attributes.hpp => vertex-attribute.hpp} | 45 ++- src/resources/image.hpp | 2 +- src/resources/model-loader.cpp | 39 ++- src/resources/resource-handle.hpp | 2 +- src/scene/object.hpp | 2 +- src/scene/text.cpp | 314 ++++++++++++++++++ src/scene/text.hpp | 183 ++++++++++ .../text-direction.hpp} | 30 +- src/type/type.hpp | 1 + src/utility/paths.cpp | 2 +- 43 files changed, 1194 insertions(+), 162 deletions(-) create mode 100644 src/gl/vertex-attribute.hpp rename src/renderer/{vertex-attributes.hpp => vertex-attribute.hpp} (66%) create mode 100644 src/scene/text.cpp create mode 100644 src/scene/text.hpp rename src/{gl/vertex-attribute-type.hpp => type/text-direction.hpp} (71%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bc5ed2..00b9acf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.7) - option(VERSION_STRING "Project version string" "0.0.0") project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) diff --git a/src/debug/performance-sampler.hpp b/src/debug/performance-sampler.hpp index 8d50708..ad9ef4b 100644 --- a/src/debug/performance-sampler.hpp +++ b/src/debug/performance-sampler.hpp @@ -20,7 +20,7 @@ #ifndef ANTKEEPER_DEBUG_PERFORMANCE_SAMPLER_HPP #define ANTKEEPER_DEBUG_PERFORMANCE_SAMPLER_HPP -#include +#include #include namespace debug { diff --git a/src/entity/systems/painting.cpp b/src/entity/systems/painting.cpp index 607abdb..9c6807b 100644 --- a/src/entity/systems/painting.cpp +++ b/src/entity/systems/painting.cpp @@ -31,8 +31,7 @@ #include "entity/components/collision.hpp" #include "entity/components/transform.hpp" #include "gl/vertex-buffer.hpp" -#include "gl/vertex-attribute-type.hpp" -#include "renderer/vertex-attributes.hpp" +#include "renderer/vertex-attribute.hpp" #include "geom/mesh-functions.hpp" #include @@ -46,6 +45,7 @@ painting::painting(entity::registry& registry, ::event_dispatcher* event_dispatc scene_collection(nullptr), is_painting(false) { + /* event_dispatcher->subscribe(this); event_dispatcher->subscribe(this); @@ -67,7 +67,7 @@ painting::painting(entity::registry& registry, ::event_dispatcher* event_dispatc // Setup stroke vbo and vao stroke_vbo = stroke_model->get_vertex_buffer(); - stroke_vbo->repurpose(sizeof(float) * vertex_size * vertex_count, nullptr, gl::buffer_usage::dynamic_draw); + stroke_vbo->repurpose(gl::buffer_usage::dynamic_draw, sizeof(float) * vertex_size * vertex_count, nullptr); stroke_model->get_vertex_array()->bind_attribute(VERTEX_POSITION_LOCATION, *stroke_vbo, 4, gl::vertex_attribute_type::float_32, vertex_stride, 0); stroke_model->get_vertex_array()->bind_attribute(VERTEX_NORMAL_LOCATION, *stroke_vbo, 3, gl::vertex_attribute_type::float_32, vertex_stride, sizeof(float) * 4); stroke_model->get_vertex_array()->bind_attribute(VERTEX_TEXCOORD_LOCATION, *stroke_vbo, 2, gl::vertex_attribute_type::float_32, vertex_stride, sizeof(float) * 7); @@ -86,12 +86,15 @@ painting::painting(entity::registry& registry, ::event_dispatcher* event_dispatc stroke_bounds_max.z = -std::numeric_limits::infinity(); midstroke = false; + */ } painting::~painting() { + /* event_dispatcher->unsubscribe(this); event_dispatcher->unsubscribe(this); + */ } void painting::update(double t, double dt) @@ -270,12 +273,15 @@ void painting::update(double t, double dt) void painting::set_scene(scene::collection* collection) { + /* this->scene_collection = collection; scene_collection->add_object(stroke_model_instance); + */ } void painting::handle_event(const tool_pressed_event& event) { + /* if (registry.has(event.entity_id)) { auto cast_result = cast_ray(event.position); @@ -292,10 +298,12 @@ void painting::handle_event(const tool_pressed_event& event) midstroke = false; } } + */ } void painting::handle_event(const tool_released_event& event) { + /* if (registry.has(event.entity_id)) { auto cast_result = cast_ray(command::get_world_transform(registry, event.entity_id).translation); @@ -308,11 +316,13 @@ void painting::handle_event(const tool_released_event& event) brush_entity = entt::null; is_painting = false; } + */ } std::optional> painting::cast_ray(const float3& position) const { std::optional> result; + /* float3 intersection; float3 surface_normal; @@ -355,7 +365,7 @@ std::optional> painting::cast_ray(const float3& posit surface_normal = calculate_face_normal(*face); result = std::make_tuple(intersection, surface_normal); } - + */ return result; } diff --git a/src/entity/systems/subterrain.cpp b/src/entity/systems/subterrain.cpp index 3def03c..b931f08 100644 --- a/src/entity/systems/subterrain.cpp +++ b/src/entity/systems/subterrain.cpp @@ -24,8 +24,8 @@ #include "renderer/model.hpp" #include "renderer/material.hpp" #include "geom/mesh-functions.hpp" -#include "renderer/vertex-attributes.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "renderer/vertex-attribute.hpp" +#include "gl/vertex-attribute.hpp" #include "gl/drawing-mode.hpp" #include "gl/vertex-buffer.hpp" #include "resources/resource-manager.hpp" @@ -219,16 +219,43 @@ subterrain::subterrain(entity::registry& registry, ::resource_manager* resource_ subterrain_model_vertex_size = 3 + 3 + 3; subterrain_model_vertex_stride = subterrain_model_vertex_size * sizeof(float); - // Bind vertex attributes + // Get model VBO and VAO gl::vertex_buffer* vbo = subterrain_model->get_vertex_buffer(); gl::vertex_array* vao = subterrain_model->get_vertex_array(); - std::size_t offset = 0; - vao->bind_attribute(VERTEX_POSITION_LOCATION, *vbo, 3, gl::vertex_attribute_type::float_32, subterrain_model_vertex_stride, 0); - offset += 3; - vao->bind_attribute(VERTEX_NORMAL_LOCATION, *vbo, 3, gl::vertex_attribute_type::float_32, subterrain_model_vertex_stride, sizeof(float) * offset); - offset += 3; - vao->bind_attribute(VERTEX_BARYCENTRIC_LOCATION, *vbo, 3, gl::vertex_attribute_type::float_32, subterrain_model_vertex_stride, sizeof(float) * offset); - offset += 3; + + std::size_t attribute_offset = 0; + + // Define position vertex attribute + gl::vertex_attribute position_attribute; + position_attribute.buffer = vbo; + position_attribute.offset = attribute_offset; + position_attribute.stride = subterrain_model_vertex_stride; + position_attribute.type = gl::vertex_attribute_type::float_32; + position_attribute.components = 3; + attribute_offset += position_attribute.components * sizeof(float); + + // Define normal vertex attribute + gl::vertex_attribute normal_attribute; + normal_attribute.buffer = vbo; + normal_attribute.offset = attribute_offset; + normal_attribute.stride = subterrain_model_vertex_stride; + normal_attribute.type = gl::vertex_attribute_type::float_32; + normal_attribute.components = 3; + attribute_offset += normal_attribute.components * sizeof(float); + + // Define barycentric vertex attribute + gl::vertex_attribute barycentric_attribute; + barycentric_attribute.buffer = vbo; + barycentric_attribute.offset = attribute_offset; + barycentric_attribute.stride = subterrain_model_vertex_stride; + barycentric_attribute.type = gl::vertex_attribute_type::float_32; + barycentric_attribute.components = 3; + attribute_offset += barycentric_attribute.components * sizeof(float); + + // Bind vertex attributes to VAO + vao->bind(render::vertex_attribute::position, position_attribute); + vao->bind(render::vertex_attribute::normal, normal_attribute); + vao->bind(render::vertex_attribute::barycentric, barycentric_attribute); // Calculate adjusted bounds to fit isosurface resolution //isosurface_resolution = 0.325f; diff --git a/src/entity/systems/terrain.cpp b/src/entity/systems/terrain.cpp index c85bfd3..03faad6 100644 --- a/src/entity/systems/terrain.cpp +++ b/src/entity/systems/terrain.cpp @@ -26,10 +26,10 @@ #include "geom/morton.hpp" #include "geom/quadtree.hpp" #include "geom/spherical.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "gl/vertex-attribute.hpp" #include "math/constants.hpp" #include "math/quaternion-operators.hpp" -#include "renderer/vertex-attributes.hpp" +#include "renderer/vertex-attribute.hpp" #include "utility/fundamental-types.hpp" #include #include @@ -471,26 +471,77 @@ model* terrain::generate_patch_model(const geom::mesh& patch_mesh, material* pat // Allocate patch model model* patch_model = new model(); + + // Get model VBO and VAO + gl::vertex_buffer* vbo = patch_model->get_vertex_buffer(); + gl::vertex_array* vao = patch_model->get_vertex_array(); // Resize model VBO and upload vertex data - gl::vertex_buffer* vbo = patch_model->get_vertex_buffer(); vbo->resize(patch_triangle_count * 3 * patch_vertex_stride, patch_vertex_data); - // Bind vertex attributes to model VAO - gl::vertex_array* vao = patch_model->get_vertex_array(); - std::size_t offset = 0; - vao->bind_attribute(VERTEX_POSITION_LOCATION, *vbo, 3, gl::vertex_attribute_type::float_32, patch_vertex_stride, 0); - offset += 3; - vao->bind_attribute(VERTEX_TEXCOORD_LOCATION, *vbo, 2, gl::vertex_attribute_type::float_32, patch_vertex_stride, sizeof(float) * offset); - offset += 2; - vao->bind_attribute(VERTEX_NORMAL_LOCATION, *vbo, 3, gl::vertex_attribute_type::float_32, patch_vertex_stride, sizeof(float) * offset); - offset += 3; - vao->bind_attribute(VERTEX_TANGENT_LOCATION, *vbo, 4, gl::vertex_attribute_type::float_32, patch_vertex_stride, sizeof(float) * offset); - offset += 4; - vao->bind_attribute(VERTEX_BARYCENTRIC_LOCATION, *vbo, 3, gl::vertex_attribute_type::float_32, patch_vertex_stride, sizeof(float) * offset); - offset += 3; - vao->bind_attribute(VERTEX_TARGET_LOCATION, *vbo, 3, gl::vertex_attribute_type::float_32, patch_vertex_stride, sizeof(float) * offset); - offset += 3; + std::size_t attribute_offset = 0; + + // Define position vertex attribute + gl::vertex_attribute position_attribute; + position_attribute.buffer = vbo; + position_attribute.offset = attribute_offset; + position_attribute.stride = patch_vertex_stride; + position_attribute.type = gl::vertex_attribute_type::float_32; + position_attribute.components = 3; + attribute_offset += position_attribute.components * sizeof(float); + + // Define UV vertex attribute + gl::vertex_attribute uv_attribute; + uv_attribute.buffer = vbo; + uv_attribute.offset = attribute_offset; + uv_attribute.stride = patch_vertex_stride; + uv_attribute.type = gl::vertex_attribute_type::float_32; + uv_attribute.components = 2; + attribute_offset += uv_attribute.components * sizeof(float); + + // Define normal vertex attribute + gl::vertex_attribute normal_attribute; + normal_attribute.buffer = vbo; + normal_attribute.offset = attribute_offset; + normal_attribute.stride = patch_vertex_stride; + normal_attribute.type = gl::vertex_attribute_type::float_32; + normal_attribute.components = 3; + attribute_offset += normal_attribute.components * sizeof(float); + + // Define tangent vertex attribute + gl::vertex_attribute tangent_attribute; + tangent_attribute.buffer = vbo; + tangent_attribute.offset = attribute_offset; + tangent_attribute.stride = patch_vertex_stride; + tangent_attribute.type = gl::vertex_attribute_type::float_32; + tangent_attribute.components = 4; + attribute_offset += tangent_attribute.components * sizeof(float); + + // Define barycentric vertex attribute + gl::vertex_attribute barycentric_attribute; + barycentric_attribute.buffer = vbo; + barycentric_attribute.offset = attribute_offset; + barycentric_attribute.stride = patch_vertex_stride; + barycentric_attribute.type = gl::vertex_attribute_type::float_32; + barycentric_attribute.components = 3; + attribute_offset += barycentric_attribute.components * sizeof(float); + + // Define target vertex attribute + gl::vertex_attribute target_attribute; + target_attribute.buffer = vbo; + target_attribute.offset = attribute_offset; + target_attribute.stride = patch_vertex_stride; + target_attribute.type = gl::vertex_attribute_type::float_32; + target_attribute.components = 3; + attribute_offset += target_attribute.components * sizeof(float); + + // Bind vertex attributes to VAO + vao->bind(render::vertex_attribute::position, position_attribute); + vao->bind(render::vertex_attribute::uv, uv_attribute); + vao->bind(render::vertex_attribute::normal, normal_attribute); + vao->bind(render::vertex_attribute::tangent, tangent_attribute); + vao->bind(render::vertex_attribute::barycentric, barycentric_attribute); + vao->bind(render::vertex_attribute::target, target_attribute); // Create model group model_group* patch_model_group = patch_model->add_group("terrain"); diff --git a/src/event/event-dispatcher.hpp b/src/event/event-dispatcher.hpp index 7f5fecd..516bf42 100644 --- a/src/event/event-dispatcher.hpp +++ b/src/event/event-dispatcher.hpp @@ -22,7 +22,7 @@ #include "event.hpp" #include "event-handler.hpp" -#include +#include #include #include diff --git a/src/event/event.hpp b/src/event/event.hpp index 7f94039..478a326 100644 --- a/src/event/event.hpp +++ b/src/event/event.hpp @@ -21,7 +21,7 @@ #define ANTKEEPER_EVENT_HPP #include -#include +#include /** * Abstract base class for events. diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index abf2fcc..4e9c8e1 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -35,7 +35,7 @@ #include "gl/texture-filter.hpp" #include "gl/texture-wrapping.hpp" #include "gl/vertex-array.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "gl/vertex-attribute.hpp" #include "gl/vertex-buffer.hpp" #include "renderer/material-flags.hpp" #include "renderer/material-property.hpp" @@ -47,7 +47,7 @@ #include "renderer/passes/shadow-map-pass.hpp" #include "renderer/passes/sky-pass.hpp" #include "renderer/simple-render-pass.hpp" -#include "renderer/vertex-attributes.hpp" +#include "renderer/vertex-attribute.hpp" #include "renderer/compositor.hpp" #include "renderer/renderer.hpp" #include "resources/resource-manager.hpp" @@ -600,9 +600,40 @@ void setup_rendering(game::context* ctx) ctx->billboard_vbo = new gl::vertex_buffer(sizeof(float) * billboard_vertex_size * billboard_vertex_count, billboard_vertex_data); ctx->billboard_vao = new gl::vertex_array(); - ctx->billboard_vao->bind_attribute(VERTEX_POSITION_LOCATION, *ctx->billboard_vbo, 3, gl::vertex_attribute_type::float_32, billboard_vertex_stride, 0); - ctx->billboard_vao->bind_attribute(VERTEX_TEXCOORD_LOCATION, *ctx->billboard_vbo, 2, gl::vertex_attribute_type::float_32, billboard_vertex_stride, sizeof(float) * 3); - ctx->billboard_vao->bind_attribute(VERTEX_BARYCENTRIC_LOCATION, *ctx->billboard_vbo, 3, gl::vertex_attribute_type::float_32, billboard_vertex_stride, sizeof(float) * 5); + + std::size_t attribute_offset = 0; + + // Define position vertex attribute + gl::vertex_attribute position_attribute; + position_attribute.buffer = ctx->billboard_vbo; + position_attribute.offset = attribute_offset; + position_attribute.stride = billboard_vertex_stride; + position_attribute.type = gl::vertex_attribute_type::float_32; + position_attribute.components = 3; + attribute_offset += position_attribute.components * sizeof(float); + + // Define UV vertex attribute + gl::vertex_attribute uv_attribute; + uv_attribute.buffer = ctx->billboard_vbo; + uv_attribute.offset = attribute_offset; + uv_attribute.stride = billboard_vertex_stride; + uv_attribute.type = gl::vertex_attribute_type::float_32; + uv_attribute.components = 2; + attribute_offset += uv_attribute.components * sizeof(float); + + // Define barycentric vertex attribute + gl::vertex_attribute barycentric_attribute; + barycentric_attribute.buffer = ctx->billboard_vbo; + barycentric_attribute.offset = attribute_offset; + barycentric_attribute.stride = billboard_vertex_stride; + barycentric_attribute.type = gl::vertex_attribute_type::float_32; + barycentric_attribute.components = 3; + attribute_offset += barycentric_attribute.components * sizeof(float); + + // Bind vertex attributes to VAO + ctx->billboard_vao->bind(render::vertex_attribute::position, position_attribute); + ctx->billboard_vao->bind(render::vertex_attribute::uv, uv_attribute); + ctx->billboard_vao->bind(render::vertex_attribute::barycentric, barycentric_attribute); } // Create renderer @@ -841,7 +872,7 @@ void setup_systems(game::context* ctx) ctx->painting_system = new entity::system::painting(*ctx->entity_registry, event_dispatcher, ctx->resource_manager); ctx->painting_system->set_scene(ctx->surface_scene); - // Setup solar system + // Setup orbit system ctx->orbit_system = new entity::system::orbit(*ctx->entity_registry); // Setup blackbody system diff --git a/src/game/states/loading.cpp b/src/game/states/loading.cpp index b79f1cd..7180e1c 100644 --- a/src/game/states/loading.cpp +++ b/src/game/states/loading.cpp @@ -38,20 +38,27 @@ #include "geom/spherical.hpp" #include "gl/drawing-mode.hpp" #include "gl/vertex-array.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "gl/vertex-attribute.hpp" #include "gl/vertex-buffer.hpp" #include "physics/light/photometry.hpp" #include "physics/orbit/orbit.hpp" #include "renderer/material.hpp" #include "renderer/model.hpp" #include "renderer/passes/shadow-map-pass.hpp" -#include "renderer/vertex-attributes.hpp" +#include "renderer/vertex-attribute.hpp" #include "resources/resource-manager.hpp" #include "scene/ambient-light.hpp" #include "scene/directional-light.hpp" #include "utility/timestamp.hpp" #include "type/type.hpp" #include +#include +#include + +#include "gl/texture-wrapping.hpp" +#include "gl/texture-filter.hpp" +#include "scene/text.hpp" +#include "renderer/material-flags.hpp" namespace game { namespace state { @@ -60,6 +67,7 @@ namespace loading { /// Loads control profile and calibrates gamepads static void load_controls(game::context* ctx); +/// Loads typefaces and builds fonts static void load_fonts(game::context* ctx); /// Creates the universe and solar system. @@ -237,35 +245,86 @@ void load_fonts(game::context* ctx) if (auto it = ctx->strings->find("font_monospace"); it != ctx->strings->end()) ctx->typefaces["monospace"] = ctx->resource_manager->load(it->second); + // Build character set + std::unordered_set charset; + { + // Add all character codes from the basic Latin unicode block + for (char32_t code = type::unicode::block::basic_latin.first; code <= type::unicode::block::basic_latin.last; ++code) + charset.insert(code); + + // Add all character codes from game strings + for (auto it = ctx->strings->begin(); it != ctx->strings->end(); ++it) + { + // Convert UTF-8 string to UTF-32 + std::wstring_convert, char32_t> convert; + std::u32string u32 = convert.from_bytes(it->second); + + /// Insert each character code from the UTF-32 string into the character set + for (char32_t code: u32) + charset.insert(code); + } + } + // Build bitmap fonts - if (auto it = ctx->typefaces.find("serif"); it != ctx->typefaces.end()) + if (auto it = ctx->typefaces.find("sans_serif"); it != ctx->typefaces.end()) { type::typeface* typeface = it->second; - type::bitmap_font font; + type::bitmap_font* font = new type::bitmap_font(); - const float size = 48.0f; + // Get font metrics + const float size = 28.0f; if (type::font_metrics metrics; typeface->get_metrics(size, metrics)) - font.set_font_metrics(metrics); + font->set_font_metrics(metrics); - image& font_bitmap = font.get_bitmap(); + // Format font bitmap + image& font_bitmap = font->get_bitmap(); font_bitmap.format(sizeof(unsigned char), 1); - type::unicode::block block = type::unicode::block::basic_latin; - for (char32_t code = block.first; code <= block.last; ++code) + // For each UTF-32 character code in the character set + for (char32_t code: charset) { if (!typeface->has_glyph(code)) continue; - type::bitmap_glyph& glyph = font[code]; + type::bitmap_glyph& glyph = (*font)[code]; typeface->get_metrics(size, code, glyph.metrics); typeface->get_bitmap(size, code, glyph.bitmap); } - font.pack(); + // Pack glyph bitmaps into the font bitmap + font->pack(); + + // Create font texture from bitmap + gl::texture_2d* font_texture = new gl::texture_2d(font_bitmap.get_width(), font_bitmap.get_height(), gl::pixel_type::uint_8, gl::pixel_format::r, gl::color_space::linear, font_bitmap.get_pixels()); + font_texture->set_wrapping(gl::texture_wrapping::extend, gl::texture_wrapping::extend); + font_texture->set_filters(gl::texture_min_filter::linear, gl::texture_mag_filter::linear); + + // Create font material + material* font_material = new material(); + font_material->set_flags(MATERIAL_FLAG_TRANSLUCENT); + font_material->add_property("font_bitmap")->set_value(font_texture); + font_material->set_shader_program(ctx->resource_manager->load("bitmap-font.glsl")); + // Create text scene object + scene::text* text_object = new scene::text(); + text_object->set_material(font_material); + text_object->set_font(font); + text_object->set_color({1.0f, 1.0f, 1.0f, 1.0f}); + //text_object->set_content("Hello, World!"); + + if (auto it = ctx->strings->find("continue"); it != ctx->strings->end()) + text_object->set_content(it->second); + + // Add text object to UI scene + ctx->ui_scene->add_object(text_object); + + + /* + // Output font bitmap std::string bitmap_path = ctx->config_path + "bitmap-font-serif.png"; stbi_flip_vertically_on_write(0); stbi_write_png(bitmap_path.c_str(), font_bitmap.get_width(), font_bitmap.get_height(), font_bitmap.get_channel_count(), font_bitmap.get_pixels(), font_bitmap.get_width() * font_bitmap.get_channel_count()); + */ } } @@ -484,19 +543,39 @@ void extrasolar_heliogenesis(game::context* ctx) // Allocate stars model model* stars_model = new model(); - // Resize model VBO and upload vertex data + // Get model VBO and VAO gl::vertex_buffer* vbo = stars_model->get_vertex_buffer(); + gl::vertex_array* vao = stars_model->get_vertex_array(); + + // Resize model VBO and upload vertex data vbo->resize(star_count * star_vertex_stride, star_vertex_data); // Free star catalog vertex data delete[] star_vertex_data; - // Bind vertex attributes to model VAO - gl::vertex_array* vao = stars_model->get_vertex_array(); - std::size_t vao_offset = 0; - vao->bind_attribute(VERTEX_POSITION_LOCATION, *vbo, 3, gl::vertex_attribute_type::float_32, star_vertex_stride, 0); - vao_offset += 3; - vao->bind_attribute(VERTEX_COLOR_LOCATION, *vbo, 4, gl::vertex_attribute_type::float_32, star_vertex_stride, sizeof(float) * vao_offset); + std::size_t attribute_offset = 0; + + // Define position vertex attribute + gl::vertex_attribute position_attribute; + position_attribute.buffer = vbo; + position_attribute.offset = attribute_offset; + position_attribute.stride = star_vertex_stride; + position_attribute.type = gl::vertex_attribute_type::float_32; + position_attribute.components = 3; + attribute_offset += position_attribute.components * sizeof(float); + + // Define color vertex attribute + gl::vertex_attribute color_attribute; + color_attribute.buffer = vbo; + color_attribute.offset = attribute_offset; + color_attribute.stride = star_vertex_stride; + color_attribute.type = gl::vertex_attribute_type::float_32; + color_attribute.components = 4; + attribute_offset += color_attribute.components * sizeof(float); + + // Bind vertex attributes to VAO + vao->bind(render::vertex_attribute::position, position_attribute); + vao->bind(render::vertex_attribute::color, color_attribute); // Load star material material* star_material = ctx->resource_manager->load("fixed-star.mtl"); diff --git a/src/geom/convex-hull.hpp b/src/geom/convex-hull.hpp index addd7c1..a847c40 100644 --- a/src/geom/convex-hull.hpp +++ b/src/geom/convex-hull.hpp @@ -24,7 +24,7 @@ #include "geom/plane.hpp" #include "geom/sphere.hpp" #include "geom/aabb.hpp" -#include +#include #include namespace geom { diff --git a/src/geom/morton.hpp b/src/geom/morton.hpp index 02f5f6d..3006130 100644 --- a/src/geom/morton.hpp +++ b/src/geom/morton.hpp @@ -21,7 +21,7 @@ #define ANTKEEPER_GEOM_MORTON_HPP #include -#include +#include namespace geom { diff --git a/src/gl/buffer-usage.hpp b/src/gl/buffer-usage.hpp index 9b0a266..577f81e 100644 --- a/src/gl/buffer-usage.hpp +++ b/src/gl/buffer-usage.hpp @@ -22,20 +22,41 @@ namespace gl { +/** + * Usage hints for vertex buffers. + * + * @see gl::vertex_buffer + */ enum class buffer_usage { + /// Data will be modified once, by the application, and used at most a few times, for drawing commands. stream_draw, + + /// Data will be modified once, by reading data from the GL, and used at most a few times, to return that data to the application. stream_read, + + /// Data will be modified once, by reading data from the GL, and used at most a few times, for drawing commands. stream_copy, + + /// Data will be modified once, by the application, and used many times, for drawing commands. static_draw, + + /// Data will be modified once, by reading data from the GL, and used many times, to return that data to the application. static_read, + + /// Data will be modified once, by reading data from the GL, and many times, for drawing commands. static_copy, + + /// Data will be modified repeatedly, by the application, and used many times, for drawing commands. dynamic_draw, + + /// Data will be modified repeatedly, by reading data from the GL, and used many times, to return that data to the application. dynamic_read, + + /// Data will be modified repeatedly, by reading data from the GL, and used many times, for drawing commands. dynamic_copy }; } // namespace gl #endif // ANTKEEPER_GL_BUFFER_USAGE_HPP - diff --git a/src/gl/gl.hpp b/src/gl/gl.hpp index dada098..88db4e8 100644 --- a/src/gl/gl.hpp +++ b/src/gl/gl.hpp @@ -41,7 +41,7 @@ namespace gl {} #include "texture-filter.hpp" #include "texture-wrapping.hpp" #include "vertex-array.hpp" -#include "vertex-attribute-type.hpp" +#include "vertex-attribute.hpp" #include "vertex-buffer.hpp" #endif // ANTKEEPER_GL_HPP diff --git a/src/gl/rasterizer.hpp b/src/gl/rasterizer.hpp index b5a7206..63d5525 100644 --- a/src/gl/rasterizer.hpp +++ b/src/gl/rasterizer.hpp @@ -20,7 +20,7 @@ #ifndef ANTKEEPER_GL_RASTERIZER_HPP #define ANTKEEPER_GL_RASTERIZER_HPP -#include +#include namespace gl { diff --git a/src/gl/shader-object.hpp b/src/gl/shader-object.hpp index 19c8333..b99c5e7 100644 --- a/src/gl/shader-object.hpp +++ b/src/gl/shader-object.hpp @@ -21,7 +21,7 @@ #define ANTKEEPER_GL_SHADER_OBJECT_HPP #include "gl/shader-stage.hpp" -#include +#include #include namespace gl { diff --git a/src/gl/vertex-array.cpp b/src/gl/vertex-array.cpp index 2960591..15b31e6 100644 --- a/src/gl/vertex-array.cpp +++ b/src/gl/vertex-array.cpp @@ -20,6 +20,8 @@ #include "gl/vertex-array.hpp" #include "gl/vertex-buffer.hpp" #include +#include +#include namespace gl { @@ -47,20 +49,51 @@ vertex_array::~vertex_array() glDeleteVertexArrays(1, &gl_array_id); } -void vertex_array::bind_attribute(unsigned int index, const vertex_buffer& buffer, int size, vertex_attribute_type type, int stride, std::size_t offset) +void vertex_array::bind(attribute_location_type location, const vertex_attribute& attribute) { - GLenum gl_type = vertex_attribute_type_lut[static_cast(type)]; - + if (attribute.buffer == nullptr) + { + throw std::invalid_argument("Cannot bind vertex attribute that has a null vertex buffer."); + } + + if (attribute.components < 1 || attribute.components > 4) + { + throw std::invalid_argument("Cannot bind vertex attribute that has an unsupported number of components (" + std::to_string(attribute.components) + ")"); + } + + attributes[location] = attribute; + + GLenum gl_type = vertex_attribute_type_lut[static_cast(attribute.type)]; glBindVertexArray(gl_array_id); - glBindBuffer(GL_ARRAY_BUFFER, buffer.gl_buffer_id); - glVertexAttribPointer(index, size, gl_type, GL_FALSE, stride, (const GLvoid*)offset); - glEnableVertexAttribArray(index); + glBindBuffer(GL_ARRAY_BUFFER, attribute.buffer->gl_buffer_id); + glVertexAttribPointer( + static_cast(location), + static_cast(attribute.components), + gl_type, + GL_FALSE, + static_cast(attribute.stride), + (const GLvoid*)attribute.offset); + glEnableVertexAttribArray(static_cast(location)); } -void vertex_array::bind_elements(const vertex_buffer& buffer) +void vertex_array::unbind(attribute_location_type location) { - glBindVertexArray(gl_array_id); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.gl_buffer_id); + if (auto it = attributes.find(location); it != attributes.end()) + { + glBindVertexArray(gl_array_id); + glDisableVertexAttribArray(static_cast(location)); + + attributes.erase(it); + } + else + { + throw std::invalid_argument("Non-existent vertex attribute cannot be unbound."); + } +} + +const typename vertex_array::attribute_map_type& vertex_array::get_attributes() const +{ + return attributes; } } // namespace gl diff --git a/src/gl/vertex-array.hpp b/src/gl/vertex-array.hpp index c886ae1..aab69a2 100644 --- a/src/gl/vertex-array.hpp +++ b/src/gl/vertex-array.hpp @@ -20,33 +20,69 @@ #ifndef ANTKEEPER_GL_VERTEX_ARRAY_HPP #define ANTKEEPER_GL_VERTEX_ARRAY_HPP -#include +#include +#include +#include "gl/vertex-attribute.hpp" namespace gl { class rasterizer; class vertex_buffer; -enum class vertex_attribute_type; +/** + * Vertex array object (VAO), which describes how vertex attributes are stored in vertex buffer objects (VBOs). + * + * @see gl::vertex_attribute + * @see gl::vertex_buffer + */ class vertex_array { public: - explicit vertex_array(); + /// Vertex attribute binding location type. + typedef std::uint_fast32_t attribute_location_type; + + /// Maps vertex attribute to binding locations. + typedef std::unordered_map attribute_map_type; + + /// Constructs a vertex array. + vertex_array(); + + /// Destructs a vertex array. ~vertex_array(); vertex_array(const vertex_array&) = delete; vertex_array& operator=(const vertex_array&) = delete; - - void bind_attribute(unsigned int index, const vertex_buffer& buffer, int size, vertex_attribute_type type, int stride, std::size_t offset); - void bind_elements(const vertex_buffer& buffer); - + + /** + * Binds a vertex attribute to the vertex array. + * + * @param location Location to which the vertex attribute should be bound. + * @param attribute Vertex attribute to bind. + * + * @except std::invalid_argument Cannot bind vertex attribute that has a null vertex buffer. + * @except std::invalid_argument Cannot bind vertex attribute that has an unsupported number of components. + */ + void bind(attribute_location_type location, const vertex_attribute& attribute); + + /** + * Unbinds a vertex attribute from the vertex array. + * + * @param location Location of the vertex attribute to unbind. + * + * @except std::invalid_argument Non-existent vertex attribute cannot be unbound. + */ + void unbind(attribute_location_type location); + + /// Returns a const reference to the map of vertex attributes bound to this vertex array. + const attribute_map_type& get_attributes() const; + private: friend class rasterizer; - - unsigned int gl_array_id; + + attribute_map_type attributes; + std::uint_fast32_t gl_array_id; }; } // namespace gl #endif // ANTKEEPER_GL_VERTEX_ARRAY_HPP - diff --git a/src/gl/vertex-attribute.hpp b/src/gl/vertex-attribute.hpp new file mode 100644 index 0000000..356f823 --- /dev/null +++ b/src/gl/vertex-attribute.hpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2021 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_GL_VERTEX_ATTRIBUTE_HPP +#define ANTKEEPER_GL_VERTEX_ATTRIBUTE_HPP + +#include +#include + +namespace gl { + +class vertex_buffer; + +enum class vertex_attribute_type +{ + int_8, + uint_8, + int_16, + uint_16, + int_32, + uint_32, + float_16, + float_32, + float_64 +}; + +/** + * Describes a vertex attribute within a vertex buffer. + * + * @see gl::vertex_buffer + * @see gl::vertex_array + */ +struct vertex_attribute +{ + /// Pointer to the vertex buffer containing vertex attribute data. + const vertex_buffer* buffer; + + /// Offset to the first component of the first instance of this attribute in the vertex buffer, in bytes. + std::size_t offset; + + /// Number of bytes between consecutive instances of this attribute in the vertex buffer. A value of `0` indicates attribute instances are tightly packed. + std::size_t stride; + + /// Data type of each component in the attribute. + vertex_attribute_type type; + + /// Number of components per attribute instance. Supported values are `1`, `2`, `3`, and `4`. + std::uint8_t components; +}; + +} // namespace gl + +#endif // ANTKEEPER_GL_VERTEX_ATTRIBUTE_HPP diff --git a/src/gl/vertex-buffer.cpp b/src/gl/vertex-buffer.cpp index b397b98..1c5f31e 100644 --- a/src/gl/vertex-buffer.cpp +++ b/src/gl/vertex-buffer.cpp @@ -18,6 +18,7 @@ */ #include "gl/vertex-buffer.hpp" +#include #include namespace gl { @@ -41,10 +42,9 @@ vertex_buffer::vertex_buffer(std::size_t size, const void* data, buffer_usage us usage(usage) { GLenum gl_usage = buffer_usage_lut[static_cast(usage)]; - glGenBuffers(1, &gl_buffer_id); glBindBuffer(GL_ARRAY_BUFFER, gl_buffer_id); - glBufferData(GL_ARRAY_BUFFER, size, data, gl_usage); + glBufferData(GL_ARRAY_BUFFER, static_cast(size), data, gl_usage); } vertex_buffer::vertex_buffer(): @@ -56,26 +56,47 @@ vertex_buffer::~vertex_buffer() glDeleteBuffers(1, &gl_buffer_id); } -void vertex_buffer::repurpose(std::size_t size, const void* data, buffer_usage usage) +void vertex_buffer::repurpose(buffer_usage usage, std::size_t size, const void* data) { this->size = size; this->usage = usage; - + GLenum gl_usage = buffer_usage_lut[static_cast(usage)]; - glBindBuffer(GL_ARRAY_BUFFER, gl_buffer_id); - glBufferData(GL_ARRAY_BUFFER, size, data, gl_usage); + glBufferData(GL_ARRAY_BUFFER, static_cast(size), data, gl_usage); } void vertex_buffer::resize(std::size_t size, const void* data) { - repurpose(size, data, usage); + repurpose(usage, size, data); +} + +void vertex_buffer::write(std::size_t offset, std::size_t size, const void* data) +{ + // Abort empty write operations + if (!size) + return; + + // Bounds check + if (offset + size > this->size) + throw std::out_of_range("Vertex buffer write operation exceeded buffer bounds."); + + glBindBuffer(GL_ARRAY_BUFFER, gl_buffer_id); + glBufferSubData(GL_ARRAY_BUFFER, static_cast(offset), static_cast(size), data); } -void vertex_buffer::update(int offset, std::size_t size, const void* data) +void vertex_buffer::read(std::size_t offset, std::size_t size, void* data) const { + // Abort empty read operations + if (!size) + return; + + // Bounds check + if (offset + size > this->size) + throw std::out_of_range("Vertex buffer read operation exceeded buffer bounds."); + glBindBuffer(GL_ARRAY_BUFFER, gl_buffer_id); - glBufferSubData(GL_ARRAY_BUFFER, offset, size, data); + glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(offset), static_cast(size), data); } } // namespace gl diff --git a/src/gl/vertex-buffer.hpp b/src/gl/vertex-buffer.hpp index c2113c5..4598fd7 100644 --- a/src/gl/vertex-buffer.hpp +++ b/src/gl/vertex-buffer.hpp @@ -20,35 +20,87 @@ #ifndef ANTKEEPER_GL_VERTEX_BUFFER_HPP #define ANTKEEPER_GL_VERTEX_BUFFER_HPP -#include +#include +#include #include "gl/buffer-usage.hpp" namespace gl { class vertex_array; +/** + * Vertex buffer object (VBO). + */ class vertex_buffer { public: + /** + * Creates a vertex buffer, settings its size, uploading its data, and setting its usage hint. + * + * @param size Size of the buffer's data, in bytes. + * @param data Pointer to data that will be copied into the buffer, or `nullptr` if no data is to be copied. + * @param usage Buffer usage hint. + */ explicit vertex_buffer(std::size_t size, const void* data = nullptr, buffer_usage usage = buffer_usage::static_draw); + + /// Creates an empty vertex buffer. vertex_buffer(); + + /// Destroys a vertex buffer. ~vertex_buffer(); vertex_buffer(const vertex_buffer&) = delete; vertex_buffer& operator=(const vertex_buffer&) = delete; - - void repurpose(std::size_t size, const void* data = nullptr, buffer_usage usage = buffer_usage::static_draw); + + /** + * Repurposes a vertex buffer, changing its usage hint, its size, and replacing its data. + * + * @param usage New usage hint for the buffer. + * @param size New size of the buffer's data, in bytes. + * @param data Pointer to data that will be copied into the buffer, or `nullptr` if no data is to be copied. + */ + void repurpose(buffer_usage usage, std::size_t size, const void* data = nullptr); + + /** + * Resizes the vertex buffer. + * + * @param size New size of the buffer's data, in bytes. + * @param data Pointer to data that will be copied into the buffer, or `nullptr` if no data is to be copied. + */ void resize(std::size_t size, const void* data = nullptr); - - void update(int offset, std::size_t size, const void* data); - + + /** + * Writes data into the vertex buffer. + * + * @param offset Offset into the buffer's data, in bytes, where writing will begin. + * @param size Size of the write operation, in bytes. + * @param data Pointer to the data that will be written. + * + * @except std::out_of_range Vertex buffer write operation exceeded buffer bounds. + */ + void write(std::size_t offset, std::size_t size, const void* data); + + /** + * Reads a subset of the buffer's data from the GL and returns it to the application. + * + * @param offset Offset into the buffer's data, in bytes, where reading will begin. + * @param size Size of the data to read, in bytes. + * @param data Pointer to where the read bytes will be stored. + * + * @except std::out_of_range Vertex buffer read operation exceeded buffer bounds. + */ + void read(std::size_t offset, std::size_t size, void* data) const; + + /// Returns the size of the buffer's data, in bytes. std::size_t get_size() const; + + /// Return's the buffer's usage hint. buffer_usage get_usage() const; private: friend class vertex_array; - - unsigned int gl_buffer_id; + + std::uint_fast32_t gl_buffer_id; std::size_t size; buffer_usage usage; }; @@ -66,4 +118,3 @@ inline buffer_usage vertex_buffer::get_usage() const } // namespace gl #endif // ANTKEEPER_GL_VERTEX_BUFFER_HPP - diff --git a/src/math/random.hpp b/src/math/random.hpp index 8d4c3c9..de9acdf 100644 --- a/src/math/random.hpp +++ b/src/math/random.hpp @@ -20,7 +20,7 @@ #ifndef ANTKEEPER_MATH_RANDOM_HPP #define ANTKEEPER_MATH_RANDOM_HPP -#include +#include #include namespace math { diff --git a/src/renderer/material-property.hpp b/src/renderer/material-property.hpp index 5677778..64ffdbf 100644 --- a/src/renderer/material-property.hpp +++ b/src/renderer/material-property.hpp @@ -28,7 +28,7 @@ #include "gl/shader-program.hpp" #include "gl/texture-2d.hpp" #include "gl/texture-cube.hpp" -#include +#include class material; diff --git a/src/renderer/material.hpp b/src/renderer/material.hpp index 2d4d33e..6816202 100644 --- a/src/renderer/material.hpp +++ b/src/renderer/material.hpp @@ -23,7 +23,7 @@ #include "renderer/material-property.hpp" #include "gl/shader-program.hpp" #include -#include +#include #include #include #include diff --git a/src/renderer/passes/bloom-pass.cpp b/src/renderer/passes/bloom-pass.cpp index 2504574..484eb46 100644 --- a/src/renderer/passes/bloom-pass.cpp +++ b/src/renderer/passes/bloom-pass.cpp @@ -25,12 +25,12 @@ #include "gl/shader-input.hpp" #include "gl/vertex-buffer.hpp" #include "gl/vertex-array.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "gl/vertex-attribute.hpp" #include "gl/drawing-mode.hpp" #include "gl/texture-2d.hpp" #include "gl/texture-wrapping.hpp" #include "gl/texture-filter.hpp" -#include "renderer/vertex-attributes.hpp" +#include "renderer/vertex-attribute.hpp" #include "renderer/render-context.hpp" #include "math/math.hpp" #include @@ -93,7 +93,17 @@ bloom_pass::bloom_pass(gl::rasterizer* rasterizer, const gl::framebuffer* frameb quad_vbo = new gl::vertex_buffer(sizeof(float) * vertex_size * vertex_count, vertex_data); quad_vao = new gl::vertex_array(); - quad_vao->bind_attribute(VERTEX_POSITION_LOCATION, *quad_vbo, 3, gl::vertex_attribute_type::float_32, vertex_stride, 0); + + // Define position vertex attribute + gl::vertex_attribute position_attribute; + position_attribute.buffer = quad_vbo; + position_attribute.offset = 0; + position_attribute.stride = vertex_stride; + position_attribute.type = gl::vertex_attribute_type::float_32; + position_attribute.components = 3; + + // Bind vertex attributes to VAO + quad_vao->bind(render::vertex_attribute::position, position_attribute); } bloom_pass::~bloom_pass() diff --git a/src/renderer/passes/final-pass.cpp b/src/renderer/passes/final-pass.cpp index 43c89e3..4fb34ef 100644 --- a/src/renderer/passes/final-pass.cpp +++ b/src/renderer/passes/final-pass.cpp @@ -25,12 +25,12 @@ #include "gl/shader-input.hpp" #include "gl/vertex-buffer.hpp" #include "gl/vertex-array.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "gl/vertex-attribute.hpp" #include "gl/drawing-mode.hpp" #include "gl/texture-2d.hpp" #include "gl/texture-wrapping.hpp" #include "gl/texture-filter.hpp" -#include "renderer/vertex-attributes.hpp" +#include "renderer/vertex-attribute.hpp" #include "renderer/render-context.hpp" #include "math/math.hpp" #include @@ -68,7 +68,17 @@ final_pass::final_pass(gl::rasterizer* rasterizer, const gl::framebuffer* frameb quad_vbo = new gl::vertex_buffer(sizeof(float) * vertex_size * vertex_count, vertex_data); quad_vao = new gl::vertex_array(); - quad_vao->bind_attribute(VERTEX_POSITION_LOCATION, *quad_vbo, 3, gl::vertex_attribute_type::float_32, vertex_stride, 0); + + // Define position vertex attribute + gl::vertex_attribute position_attribute; + position_attribute.buffer = quad_vbo; + position_attribute.offset = 0; + position_attribute.stride = vertex_stride; + position_attribute.type = gl::vertex_attribute_type::float_32; + position_attribute.components = 3; + + // Bind vertex attributes to VAO + quad_vao->bind(render::vertex_attribute::position, position_attribute); } final_pass::~final_pass() diff --git a/src/renderer/passes/material-pass.cpp b/src/renderer/passes/material-pass.cpp index d2a5d3e..5526a93 100644 --- a/src/renderer/passes/material-pass.cpp +++ b/src/renderer/passes/material-pass.cpp @@ -26,12 +26,12 @@ #include "gl/shader-input.hpp" #include "gl/vertex-buffer.hpp" #include "gl/vertex-array.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "gl/vertex-attribute.hpp" #include "gl/drawing-mode.hpp" #include "gl/texture-2d.hpp" #include "gl/texture-wrapping.hpp" #include "gl/texture-filter.hpp" -#include "renderer/vertex-attributes.hpp" +#include "renderer/vertex-attribute.hpp" #include "renderer/material-flags.hpp" #include "renderer/model.hpp" #include "renderer/render-context.hpp" diff --git a/src/renderer/passes/outline-pass.cpp b/src/renderer/passes/outline-pass.cpp index 1edd48d..99be641 100644 --- a/src/renderer/passes/outline-pass.cpp +++ b/src/renderer/passes/outline-pass.cpp @@ -25,9 +25,9 @@ #include "gl/shader-input.hpp" #include "gl/vertex-buffer.hpp" #include "gl/vertex-array.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "gl/vertex-attribute.hpp" #include "gl/drawing-mode.hpp" -#include "renderer/vertex-attributes.hpp" +#include "renderer/vertex-attribute.hpp" #include "renderer/render-context.hpp" #include "renderer/material.hpp" #include "renderer/material-flags.hpp" diff --git a/src/renderer/passes/sky-pass.cpp b/src/renderer/passes/sky-pass.cpp index d52baa7..f386518 100644 --- a/src/renderer/passes/sky-pass.cpp +++ b/src/renderer/passes/sky-pass.cpp @@ -26,12 +26,12 @@ #include "gl/shader-input.hpp" #include "gl/vertex-buffer.hpp" #include "gl/vertex-array.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "gl/vertex-attribute.hpp" #include "gl/drawing-mode.hpp" #include "gl/texture-2d.hpp" #include "gl/texture-wrapping.hpp" #include "gl/texture-filter.hpp" -#include "renderer/vertex-attributes.hpp" +#include "renderer/vertex-attribute.hpp" #include "renderer/render-context.hpp" #include "renderer/model.hpp" #include "renderer/material.hpp" diff --git a/src/renderer/passes/ui-pass.cpp b/src/renderer/passes/ui-pass.cpp index c92735d..3427b5e 100644 --- a/src/renderer/passes/ui-pass.cpp +++ b/src/renderer/passes/ui-pass.cpp @@ -25,12 +25,12 @@ #include "gl/shader-input.hpp" #include "gl/vertex-buffer.hpp" #include "gl/vertex-array.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "gl/vertex-attribute.hpp" #include "gl/drawing-mode.hpp" #include "gl/texture-2d.hpp" #include "gl/texture-wrapping.hpp" #include "gl/texture-filter.hpp" -#include "renderer/vertex-attributes.hpp" +#include "renderer/vertex-attribute.hpp" #include "renderer/material-flags.hpp" #include "renderer/render-context.hpp" #include "scene/camera.hpp" diff --git a/src/renderer/render-operation.hpp b/src/renderer/render-operation.hpp index 4cd07ba..3f04032 100644 --- a/src/renderer/render-operation.hpp +++ b/src/renderer/render-operation.hpp @@ -23,7 +23,7 @@ #include "utility/fundamental-types.hpp" #include "gl/vertex-array.hpp" #include "gl/drawing-mode.hpp" -#include +#include class pose; class material; diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index 87f87be..6749428 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -25,6 +25,7 @@ #include "scene/model-instance.hpp" #include "scene/billboard.hpp" #include "scene/lod-group.hpp" +#include "scene/text.hpp" #include "renderer/model.hpp" #include "gl/drawing-mode.hpp" #include "math/math.hpp" @@ -128,6 +129,8 @@ void renderer::process_object(render_context& context, const scene::object_base* process_billboard(context, static_cast(object)); else if (type == scene::lod_group::object_type_id) process_lod_group(context, static_cast(object)); + else if (type == scene::text::object_type_id) + process_text(context, static_cast(object)); } void renderer::process_model_instance(render_context& context, const scene::model_instance* model_instance) const @@ -220,3 +223,28 @@ void renderer::process_lod_group(render_context& context, const scene::lod_group process_object(context, object); } } + +void renderer::process_text(render_context& context, const scene::text* text) const +{ + // Get object culling volume + const geom::bounding_volume* object_culling_volume = text->get_culling_mask(); + if (!object_culling_volume) + object_culling_volume = &text->get_bounds(); + + // Perform view-frustum culling + if (!context.camera_culling_volume->intersects(*object_culling_volume)) + return; + + render_operation operation; + operation.material = text->get_material(); + operation.pose = nullptr; + operation.vertex_array = text->get_vertex_array(); + operation.drawing_mode = gl::drawing_mode::triangles; + operation.start_index = 0; + operation.index_count = text->get_vertex_count(); + operation.transform = math::matrix_cast(text->get_transform_tween().interpolate(context.alpha)); + operation.depth = context.clip_near.signed_distance(math::resize<3>(operation.transform[3])); + operation.instance_count = 0; + + context.operations.push_back(operation); +} diff --git a/src/renderer/renderer.hpp b/src/renderer/renderer.hpp index 0d7536b..e50bcaf 100644 --- a/src/renderer/renderer.hpp +++ b/src/renderer/renderer.hpp @@ -32,6 +32,7 @@ namespace scene class model_instance; class billboard; class lod_group; + class text; } /* @@ -71,6 +72,7 @@ private: void process_model_instance(render_context& context, const scene::model_instance* model_instance) const; void process_billboard(render_context& context, const scene::billboard* billboard) const; void process_lod_group(render_context& context, const scene::lod_group* lod_group) const; + void process_text(render_context& context, const scene::text* text) const; mutable render_operation billboard_op; }; diff --git a/src/renderer/simple-render-pass.cpp b/src/renderer/simple-render-pass.cpp index 4ee257b..57d53d8 100644 --- a/src/renderer/simple-render-pass.cpp +++ b/src/renderer/simple-render-pass.cpp @@ -24,12 +24,12 @@ #include "gl/shader-input.hpp" #include "gl/vertex-buffer.hpp" #include "gl/vertex-array.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "gl/vertex-attribute.hpp" #include "gl/drawing-mode.hpp" #include "gl/texture-2d.hpp" #include "gl/texture-wrapping.hpp" #include "gl/texture-filter.hpp" -#include "renderer/vertex-attributes.hpp" +#include "renderer/vertex-attribute.hpp" #include "renderer/render-context.hpp" #include "renderer/material.hpp" #include "renderer/material-property.hpp" @@ -64,7 +64,17 @@ simple_render_pass::simple_render_pass(gl::rasterizer* rasterizer, const gl::fra quad_vbo = new gl::vertex_buffer(sizeof(float) * vertex_size * vertex_count, vertex_data); quad_vao = new gl::vertex_array(); - quad_vao->bind_attribute(VERTEX_POSITION_LOCATION, *quad_vbo, 3, gl::vertex_attribute_type::float_32, vertex_stride, 0); + + // Define position vertex attribute + gl::vertex_attribute position_attribute; + position_attribute.buffer = quad_vbo; + position_attribute.offset = 0; + position_attribute.stride = vertex_stride; + position_attribute.type = gl::vertex_attribute_type::float_32; + position_attribute.components = 3; + + // Bind vertex attributes to VAO + quad_vao->bind(render::vertex_attribute::position, position_attribute); } simple_render_pass::~simple_render_pass() diff --git a/src/renderer/vertex-attributes.hpp b/src/renderer/vertex-attribute.hpp similarity index 66% rename from src/renderer/vertex-attributes.hpp rename to src/renderer/vertex-attribute.hpp index 942af70..b986355 100644 --- a/src/renderer/vertex-attributes.hpp +++ b/src/renderer/vertex-attribute.hpp @@ -17,8 +17,8 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_VERTEX_ATTRIBUTES_HPP -#define ANTKEEPER_VERTEX_ATTRIBUTES_HPP +#ifndef ANTKEEPER_VERTEX_ATTRIBUTE_HPP +#define ANTKEEPER_VERTEX_ATTRIBUTE_HPP /// Vertex position (vec3) #define VERTEX_POSITION_LOCATION 0 @@ -47,5 +47,44 @@ /// Vertex morph target (vec3) #define VERTEX_TARGET_LOCATION 8 -#endif // ANTKEEPER_VERTEX_ATTRIBUTES_HPP +namespace render { +/** + * Contains enumerated vertex attribute locations. + */ +namespace vertex_attribute +{ + enum + { + /// Vertex position (vec3) + position, + + /// Vertex UV texture coordinates (vec2) + uv, + + /// Vertex normal (vec3) + normal, + + /// Vertex tangent (vec4) + tangent, + + /// Vertex color (vec4) + color, + + /// Vertex bone indices (vec4) + bone_index, + + /// Vertex bone weights (vec4) + bone_weight, + + /// Vertex barycentric coordinates (vec3) + barycentric, + + /// Vertex morph target (vec3) + target + }; +} + +} // namespace render + +#endif // ANTKEEPER_VERTEX_ATTRIBUTE_HPP diff --git a/src/resources/image.hpp b/src/resources/image.hpp index e0c6824..33be9d2 100644 --- a/src/resources/image.hpp +++ b/src/resources/image.hpp @@ -20,7 +20,7 @@ #ifndef ANTKEEPER_IMAGE_HPP #define ANTKEEPER_IMAGE_HPP -#include +#include /** * Stores basic image data. diff --git a/src/resources/model-loader.cpp b/src/resources/model-loader.cpp index aff36ad..db665e5 100644 --- a/src/resources/model-loader.cpp +++ b/src/resources/model-loader.cpp @@ -20,8 +20,8 @@ #include "resources/resource-loader.hpp" #include "resources/resource-manager.hpp" #include "renderer/model.hpp" -#include "renderer/vertex-attributes.hpp" -#include "gl/vertex-attribute-type.hpp" +#include "renderer/vertex-attribute.hpp" +#include "gl/vertex-attribute.hpp" #include "gl/drawing-mode.hpp" #include "utility/fundamental-types.hpp" #include @@ -471,28 +471,37 @@ model* resource_loader::load(resource_manager* resource_manager, PHYSFS_F // Map attribute names to locations static const std::unordered_map attribute_location_map = { - {"position", VERTEX_POSITION_LOCATION}, - {"texcoord", VERTEX_TEXCOORD_LOCATION}, - {"normal", VERTEX_NORMAL_LOCATION}, - {"tangent", VERTEX_TANGENT_LOCATION}, - {"color", VERTEX_COLOR_LOCATION}, - {"bone_index", VERTEX_BONE_INDEX_LOCATION}, - {"bone_weight", VERTEX_BONE_WEIGHT_LOCATION}, - {"barycentric", VERTEX_BARYCENTRIC_LOCATION} + {"position", render::vertex_attribute::position}, + {"texcoord", render::vertex_attribute::uv}, + {"normal", render::vertex_attribute::normal}, + {"tangent", render::vertex_attribute::tangent}, + {"color", render::vertex_attribute::color}, + {"bone_index", render::vertex_attribute::bone_index}, + {"bone_weight", render::vertex_attribute::bone_weight}, + {"barycentric", render::vertex_attribute::barycentric}, + {"target", render::vertex_attribute::target} }; // Bind attributes to VAO gl::vertex_array* vao = model->get_vertex_array(); - std::size_t offset = 0; + std::size_t attribute_offset = 0; for (auto attribute_it = attributes.begin(); attribute_it != attributes.end(); ++attribute_it) { std::string attribute_name = attribute_it->first; - std::size_t attribute_size = std::get<0>(attribute_it->second); if (auto location_it = attribute_location_map.find(attribute_name); location_it != attribute_location_map.end()) - vao->bind_attribute(location_it->second, *vbo, attribute_size, gl::vertex_attribute_type::float_32, vertex_stride, offset); - - offset += attribute_size * sizeof(float); + { + gl::vertex_attribute attribute; + attribute.buffer = vbo; + attribute.offset = attribute_offset; + attribute.stride = vertex_stride; + attribute.type = gl::vertex_attribute_type::float_32; + attribute.components = std::get<0>(attribute_it->second); + + vao->bind(location_it->second, attribute); + + attribute_offset += attribute.components * sizeof(float); + } } // Load materials diff --git a/src/resources/resource-handle.hpp b/src/resources/resource-handle.hpp index a0eb0ed..238a3e3 100644 --- a/src/resources/resource-handle.hpp +++ b/src/resources/resource-handle.hpp @@ -20,7 +20,7 @@ #ifndef ANTKEEPER_RESOURCE_HANDLE_HPP #define ANTKEEPER_RESOURCE_HANDLE_HPP -#include +#include /** * Base class for resource handles. diff --git a/src/scene/object.hpp b/src/scene/object.hpp index e176919..3e82f47 100644 --- a/src/scene/object.hpp +++ b/src/scene/object.hpp @@ -26,7 +26,7 @@ #include "math/quaternion-type.hpp" #include "math/transform-type.hpp" #include -#include +#include namespace scene { diff --git a/src/scene/text.cpp b/src/scene/text.cpp new file mode 100644 index 0000000..50d8efa --- /dev/null +++ b/src/scene/text.cpp @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2021 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#include "scene/text.hpp" +#include "renderer/material.hpp" +#include "renderer/vertex-attribute.hpp" +#include "math/vector-operators.hpp" +#include +#include + +namespace scene { + +text::text(): + local_bounds{{0, 0, 0}, {0, 0, 0}}, + world_bounds{{0, 0, 0}, {0, 0, 0}}, + material(nullptr), + font(nullptr), + direction(type::text_direction::ltr), + content_u8(std::string()), + content_u32(std::u32string()), + color({0.0f, 0.0f, 0.0f, 1.0f}), + vertex_stride(0), + vertex_count(0), + vao(nullptr), + vbo(nullptr) +{ + // Allocate VBO and VAO + vbo = new gl::vertex_buffer(0, nullptr, gl::buffer_usage::static_draw); + vao = new gl::vertex_array(); + + // Calculate vertex stride + vertex_stride = (3 + 2 + 4) * sizeof(float); + + // Init vertex attribute offset + std::size_t attribute_offset = 0; + + // Define vertex position attribute + gl::vertex_attribute position_attribute; + position_attribute.buffer = vbo; + position_attribute.offset = attribute_offset; + position_attribute.stride = vertex_stride; + position_attribute.type = gl::vertex_attribute_type::float_32; + position_attribute.components = 3; + attribute_offset += position_attribute.components * sizeof(float); + + // Define vertex UV attribute + gl::vertex_attribute uv_attribute; + uv_attribute.buffer = vbo; + uv_attribute.offset = attribute_offset; + uv_attribute.stride = vertex_stride; + uv_attribute.type = gl::vertex_attribute_type::float_32; + uv_attribute.components = 2; + attribute_offset += uv_attribute.components * sizeof(float); + + // Define vertex color attribute + gl::vertex_attribute color_attribute; + color_attribute.buffer = vbo; + color_attribute.offset = attribute_offset; + color_attribute.stride = vertex_stride; + color_attribute.type = gl::vertex_attribute_type::float_32; + color_attribute.components = 4; + attribute_offset += color_attribute.components * sizeof(float); + + // Bind vertex attributes to VAO + vao->bind(render::vertex_attribute::position, position_attribute); + vao->bind(render::vertex_attribute::uv, uv_attribute); + vao->bind(render::vertex_attribute::color, color_attribute); +} + +text::~text() +{ + // Free VAO and VBO + delete vao; + delete vbo; +} + +void text::set_material(::material* material) +{ + this->material = material; +} + +void text::set_font(const type::bitmap_font* font) +{ + if (this->font != font) + { + this->font = font; + + // Update text in VBO + update_content(); + } +} + +void text::set_direction(type::text_direction direction) +{ + if (this->direction != direction) + { + this->direction = direction; + + // Update text in VBO + update_content(); + } +} + +void text::set_content(const std::string& content) +{ + // If content has changed + if (content_u8 != content) + { + // Update UTF-8 content + content_u8 = content; + + // Convert UTF-8 content to UTF-32 + std::wstring_convert, char32_t> convert; + content_u32 = convert.from_bytes(content_u8.c_str()); + + // Update text in VBO + update_content(); + } +} + +void text::set_color(const float4& color) +{ + this->color = color; + + // Update color in VBO + update_color(); +} + +void text::transformed() +{ + world_bounds = aabb_type::transform(local_bounds, get_transform()); +} + +void text::update_tweens() +{ + object_base::update_tweens(); + if (material) + { + material->update_tweens(); + } +} + +void text::update_content() +{ + // If no valid font or no text, clear vertex count + if (!font || content_u32.empty()) + { + vertex_count = 0; + return; + } + + // Calculate new vertex count and minimum vertex buffer size + std::size_t vertex_count = content_u32.length() * 6; + std::size_t min_vertex_buffer_size = vertex_count * vertex_stride; + + // Expand vertex data buffer to accommodate vertices + if (vertex_data.size() < min_vertex_buffer_size) + vertex_data.resize(min_vertex_buffer_size); + + // Get font metrics and bitmap + const type::font_metrics& font_metrics = font->get_font_metrics(); + const image& font_bitmap = font->get_bitmap(); + + // Init pen position + float2 pen_position = {0.0f, 0.0f}; + + // Reset local-space bounds + local_bounds = {{0, 0, 0}, {0, 0, 0}}; + + // Generate vertex data + char32_t previous_code = 0; + float* v = reinterpret_cast(vertex_data.data()); + for (char32_t code: content_u32) + { + // Apply kerning + if (previous_code) + { + pen_position.x += font->get_kerning(previous_code, code).x; + } + + if (font->contains(code)) + { + // Get glyph + const type::bitmap_glyph& glyph = font->get_glyph(code); + + // Calculate vertex positions + float2 positions[6]; + positions[0] = pen_position + glyph.metrics.horizontal_bearing; + positions[1] = {positions[0].x, positions[0].y - glyph.metrics.height}; + positions[2] = {positions[0].x + glyph.metrics.width, positions[1].y}; + positions[3] = {positions[2].x, positions[0].y}; + positions[4] = positions[0]; + positions[5] = positions[2]; + + // Calculate vertex UVs + float2 uvs[6]; + uvs[0] = {static_cast(glyph.position.x), static_cast(glyph.position.y)}; + uvs[1] = {uvs[0].x, uvs[0].y + glyph.metrics.height}; + uvs[2] = {uvs[0].x + glyph.metrics.width, uvs[1].y}; + uvs[3] = {uvs[2].x, uvs[0].y}; + uvs[4] = uvs[0]; + uvs[5] = uvs[2]; + + for (int i = 0; i < 6; ++i) + { + // Round positions + positions[i].x = std::round(positions[i].x); + positions[i].y = std::round(positions[i].y); + + // Normalize UVs + uvs[i].x = uvs[i].x / static_cast(font_bitmap.get_width()); + uvs[i].y = uvs[i].y / static_cast(font_bitmap.get_height()); + } + + // Add vertex to vertex data buffer + for (int i = 0; i < 6; ++i) + { + *(v++) = positions[i].x; + *(v++) = positions[i].y; + *(v++) = 0.0f; + *(v++) = uvs[i].x; + *(v++) = uvs[i].y; + *(v++) = color.x; + *(v++) = color.y; + *(v++) = color.z; + *(v++) = color.w; + } + + // Advance pen position + pen_position.x += glyph.metrics.horizontal_advance; + + // Update local-space bounds + for (int i = 0; i < 4; ++i) + { + const float2& position = positions[i]; + for (int j = 0; j < 2; ++j) + { + local_bounds.min_point[j] = std::min(local_bounds.min_point[j], position[j]); + local_bounds.max_point[j] = std::max(local_bounds.max_point[j], position[j]); + } + } + } + else + { + // Glyph not in font, zero vertex data + for (std::size_t i = 0; i < (6 * 9); ++i) + *(v++) = 0.0f; + } + + // Handle newlines + if (code == static_cast('\n')) + { + pen_position.x = 0.0f; + pen_position.y -= font_metrics.linegap; + } + + // Update previous UTF-32 character code + previous_code = code; + } + + // Resize VBO, if necessary, and upload vertex data + if (vertex_count > this->vertex_count) + { + this->vertex_count = vertex_count; + vbo->resize(min_vertex_buffer_size, vertex_data.data()); + } + else + { + vbo->write(0, min_vertex_buffer_size, vertex_data.data()); + } + + // Update vertex count + this->vertex_count = vertex_count; + + // Update world-space bounds + transformed(); +} + +void text::update_color() +{ + float* v = reinterpret_cast(vertex_data.data()); + for (std::size_t i = 0; i < vertex_count; ++i) + { + // Skip vertex position (vec3) and vertex UV (vec2) + v += (3 + 2); + + // Update vertex color + *(v++) = color.x; + *(v++) = color.y; + *(v++) = color.z; + *(v++) = color.w; + } + + // Update VBO + vbo->write(0, vertex_count * vertex_stride, vertex_data.data()); +} + +} // namespace scene diff --git a/src/scene/text.hpp b/src/scene/text.hpp new file mode 100644 index 0000000..047fe5b --- /dev/null +++ b/src/scene/text.hpp @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2021 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_SCENE_TEXT_HPP +#define ANTKEEPER_SCENE_TEXT_HPP + +#include "scene/object.hpp" +#include "geom/aabb.hpp" +#include "utility/fundamental-types.hpp" +#include "gl/vertex-array.hpp" +#include "gl/vertex-buffer.hpp" +#include "renderer/material.hpp" +#include "type/bitmap-font.hpp" +#include "type/text-direction.hpp" + +namespace scene { + +/** + * Text scene object. + */ +class text: public object +{ +public: + typedef geom::aabb aabb_type; + + /// Constructs a text object. + text(); + + /// Destructs a text object. + ~text(); + + /** + * Sets the text material. + * + * @param material Text material. + */ + void set_material(material* material); + + /** + * Sets the text font. + * + * @param font Pointer to a font. + */ + void set_font(const type::bitmap_font* font); + + /** + * Sets the direction of the text. + * + * @param direction Text direction. + */ + void set_direction(type::text_direction direction); + + /** + * Sets the text content. + * + * @param content UTF-8 string of text. + */ + void set_content(const std::string& content); + + /** + * Sets the text color. + * + * Text color is passed to the text's material shader as a vertex color. + * + * @param color RGBA color. + */ + void set_color(const float4& color); + + /// Returns the text material. + material* get_material() const; + + /// Returns the text font. + const type::bitmap_font* get_font() const; + + /// Returns the text direction. + const type::text_direction& get_direction() const; + + /// Returns the text content. + const std::string& get_content() const; + + /// Returns the text color. + const float4& get_color() const; + + /// Returns the text vertex array. + const gl::vertex_array* get_vertex_array() const; + + /// Returns the text vertex buffer. + const gl::vertex_buffer* get_vertex_buffer() const; + + /// Returns the number of vertices. + std::size_t get_vertex_count() const; + + /// @copydoc scene::object::get_bounds() const + virtual const bounding_volume_type& get_bounds() const; + + /// @copydoc scene::object::update_tweens() + virtual void update_tweens(); + +private: + void update_content(); + void update_color(); + + virtual void transformed(); + + aabb_type local_bounds; + aabb_type world_bounds; + material* material; + const type::bitmap_font* font; + type::text_direction direction; + std::string content_u8; + std::u32string content_u32; + float4 color; + std::size_t vertex_stride; + std::size_t vertex_count; + std::vector vertex_data; + gl::vertex_array* vao; + gl::vertex_buffer* vbo; +}; + +inline material* text::get_material() const +{ + return material; +} + +inline const type::bitmap_font* text::get_font() const +{ + return font; +} + +inline const type::text_direction& text::get_direction() const +{ + return direction; +} + +inline const std::string& text::get_content() const +{ + return content_u8; +} + +inline const float4& text::get_color() const +{ + return color; +} + +inline const gl::vertex_array* text::get_vertex_array() const +{ + return vao; +} + +inline const gl::vertex_buffer* text::get_vertex_buffer() const +{ + return vbo; +} + +inline std::size_t text::get_vertex_count() const +{ + return vertex_count; +} + +inline const typename object_base::bounding_volume_type& text::get_bounds() const +{ + return world_bounds; +} + +} // namespace scene + +#endif // ANTKEEPER_SCENE_TEXT_HPP diff --git a/src/gl/vertex-attribute-type.hpp b/src/type/text-direction.hpp similarity index 71% rename from src/gl/vertex-attribute-type.hpp rename to src/type/text-direction.hpp index 4e934f7..19c7733 100644 --- a/src/gl/vertex-attribute-type.hpp +++ b/src/type/text-direction.hpp @@ -17,25 +17,23 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_GL_VERTEX_ATTRIBUTE_TYPE_HPP -#define ANTKEEPER_GL_VERTEX_ATTRIBUTE_TYPE_HPP +#ifndef ANTKEEPER_TYPE_TEXT_DIRECTION_HPP +#define ANTKEEPER_TYPE_TEXT_DIRECTION_HPP -namespace gl { +namespace type { -enum class vertex_attribute_type +/** + * Text writing direction. + */ +enum class text_direction { - int_8, - uint_8, - int_16, - uint_16, - int_32, - uint_32, - float_16, - float_32, - float_64 + /// Text is written from left to right. + ltr, + + /// Text is written from right to left. + rtl }; -} // namespace gl - -#endif // ANTKEEPER_GL_VERTEX_ATTRIBUTE_TYPE_HPP +} // namespace type +#endif // ANTKEEPER_TYPE_TEXT_DIRECTION_HPP diff --git a/src/type/type.hpp b/src/type/type.hpp index feeb910..42995da 100644 --- a/src/type/type.hpp +++ b/src/type/type.hpp @@ -29,6 +29,7 @@ namespace type {} #include "type/font-metrics.hpp" #include "type/glyph-metrics.hpp" #include "type/kerning-table.hpp" +#include "type/text-direction.hpp" #include "type/unicode/unicode.hpp" #endif // ANTKEEPER_TYPE_HPP diff --git a/src/utility/paths.cpp b/src/utility/paths.cpp index 0e005ba..0ea96c6 100644 --- a/src/utility/paths.cpp +++ b/src/utility/paths.cpp @@ -18,7 +18,7 @@ */ #include "paths.hpp" -#include +#include #include #include