Browse Source

Revise vertex buffer and vertex attribute classes, add text scene object class

master
C. J. Howard 2 years ago
parent
commit
8de74d2e1b
43 changed files with 1194 additions and 162 deletions
  1. +0
    -1
      CMakeLists.txt
  2. +1
    -1
      src/debug/performance-sampler.hpp
  3. +14
    -4
      src/entity/systems/painting.cpp
  4. +37
    -10
      src/entity/systems/subterrain.cpp
  5. +69
    -18
      src/entity/systems/terrain.cpp
  6. +1
    -1
      src/event/event-dispatcher.hpp
  7. +1
    -1
      src/event/event.hpp
  8. +37
    -6
      src/game/bootloader.cpp
  9. +97
    -18
      src/game/states/loading.cpp
  10. +1
    -1
      src/geom/convex-hull.hpp
  11. +1
    -1
      src/geom/morton.hpp
  12. +22
    -1
      src/gl/buffer-usage.hpp
  13. +1
    -1
      src/gl/gl.hpp
  14. +1
    -1
      src/gl/rasterizer.hpp
  15. +1
    -1
      src/gl/shader-object.hpp
  16. +42
    -9
      src/gl/vertex-array.cpp
  17. +46
    -10
      src/gl/vertex-array.hpp
  18. +69
    -0
      src/gl/vertex-attribute.hpp
  19. +30
    -9
      src/gl/vertex-buffer.cpp
  20. +60
    -9
      src/gl/vertex-buffer.hpp
  21. +1
    -1
      src/math/random.hpp
  22. +1
    -1
      src/renderer/material-property.hpp
  23. +1
    -1
      src/renderer/material.hpp
  24. +13
    -3
      src/renderer/passes/bloom-pass.cpp
  25. +13
    -3
      src/renderer/passes/final-pass.cpp
  26. +2
    -2
      src/renderer/passes/material-pass.cpp
  27. +2
    -2
      src/renderer/passes/outline-pass.cpp
  28. +2
    -2
      src/renderer/passes/sky-pass.cpp
  29. +2
    -2
      src/renderer/passes/ui-pass.cpp
  30. +1
    -1
      src/renderer/render-operation.hpp
  31. +28
    -0
      src/renderer/renderer.cpp
  32. +2
    -0
      src/renderer/renderer.hpp
  33. +13
    -3
      src/renderer/simple-render-pass.cpp
  34. +42
    -3
      src/renderer/vertex-attribute.hpp
  35. +1
    -1
      src/resources/image.hpp
  36. +24
    -15
      src/resources/model-loader.cpp
  37. +1
    -1
      src/resources/resource-handle.hpp
  38. +1
    -1
      src/scene/object.hpp
  39. +314
    -0
      src/scene/text.cpp
  40. +183
    -0
      src/scene/text.hpp
  41. +14
    -16
      src/type/text-direction.hpp
  42. +1
    -0
      src/type/type.hpp
  43. +1
    -1
      src/utility/paths.cpp

+ 0
- 1
CMakeLists.txt View File

@ -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)

+ 1
- 1
src/debug/performance-sampler.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_DEBUG_PERFORMANCE_SAMPLER_HPP
#define ANTKEEPER_DEBUG_PERFORMANCE_SAMPLER_HPP
#include <cstdlib>
#include <cstddef>
#include <vector>
namespace debug {

+ 14
- 4
src/entity/systems/painting.cpp View File

@ -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 <limits>
@ -46,6 +45,7 @@ painting::painting(entity::registry& registry, ::event_dispatcher* event_dispatc
scene_collection(nullptr),
is_painting(false)
{
/*
event_dispatcher->subscribe<tool_pressed_event>(this);
event_dispatcher->subscribe<tool_released_event>(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<float>::infinity();
midstroke = false;
*/
}
painting::~painting()
{
/*
event_dispatcher->unsubscribe<tool_pressed_event>(this);
event_dispatcher->unsubscribe<tool_released_event>(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<component::brush>(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<component::brush>(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<std::tuple<float3, float3>> painting::cast_ray(const float3& position) const
{
std::optional<std::tuple<float3, float3>> 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;
}

+ 37
- 10
src/entity/systems/subterrain.cpp View File

@ -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;

+ 69
- 18
src/entity/systems/terrain.cpp View File

@ -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 <functional>
#include <iostream>
@ -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");

+ 1
- 1
src/event/event-dispatcher.hpp View File

@ -22,7 +22,7 @@
#include "event.hpp"
#include "event-handler.hpp"
#include <cstdlib>
#include <cstddef>
#include <list>
#include <map>

+ 1
- 1
src/event/event.hpp View File

@ -21,7 +21,7 @@
#define ANTKEEPER_EVENT_HPP
#include <atomic>
#include <cstdlib>
#include <cstddef>
/**
* Abstract base class for events.

+ 37
- 6
src/game/bootloader.cpp View File

@ -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

+ 97
- 18
src/game/states/loading.cpp View File

@ -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 <stb/stb_image_write.h>
#include <unordered_set>
#include <codecvt>
#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<type::typeface>(it->second);
// Build character set
std::unordered_set<char32_t> 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<std::codecvt_utf8<char32_t>, 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<const gl::texture_2d*>("font_bitmap")->set_value(font_texture);
font_material->set_shader_program(ctx->resource_manager->load<gl::shader_program>("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<material>("fixed-star.mtl");

+ 1
- 1
src/geom/convex-hull.hpp View File

@ -24,7 +24,7 @@
#include "geom/plane.hpp"
#include "geom/sphere.hpp"
#include "geom/aabb.hpp"
#include <cstdlib>
#include <cstddef>
#include <vector>
namespace geom {

+ 1
- 1
src/geom/morton.hpp View File

@ -21,7 +21,7 @@
#define ANTKEEPER_GEOM_MORTON_HPP
#include <array>
#include <cstdlib>
#include <cstddef>
namespace geom {

+ 22
- 1
src/gl/buffer-usage.hpp View File

@ -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

+ 1
- 1
src/gl/gl.hpp View File

@ -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

+ 1
- 1
src/gl/rasterizer.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_GL_RASTERIZER_HPP
#define ANTKEEPER_GL_RASTERIZER_HPP
#include <cstdlib>
#include <cstddef>
namespace gl {

+ 1
- 1
src/gl/shader-object.hpp View File

@ -21,7 +21,7 @@
#define ANTKEEPER_GL_SHADER_OBJECT_HPP
#include "gl/shader-stage.hpp"
#include <cstdlib>
#include <cstddef>
#include <string>
namespace gl {

+ 42
- 9
src/gl/vertex-array.cpp View File

@ -20,6 +20,8 @@
#include "gl/vertex-array.hpp"
#include "gl/vertex-buffer.hpp"
#include <glad/glad.h>
#include <stdexcept>
#include <string>
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<std::size_t>(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<std::size_t>(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<GLuint>(location),
static_cast<GLint>(attribute.components),
gl_type,
GL_FALSE,
static_cast<GLsizei>(attribute.stride),
(const GLvoid*)attribute.offset);
glEnableVertexAttribArray(static_cast<GLuint>(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<GLuint>(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

+ 46
- 10
src/gl/vertex-array.hpp View File

@ -20,33 +20,69 @@
#ifndef ANTKEEPER_GL_VERTEX_ARRAY_HPP
#define ANTKEEPER_GL_VERTEX_ARRAY_HPP
#include <cstdlib>
#include <cstdint>
#include <unordered_map>
#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_location_type, vertex_attribute> 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

+ 69
- 0
src/gl/vertex-attribute.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GL_VERTEX_ATTRIBUTE_HPP
#define ANTKEEPER_GL_VERTEX_ATTRIBUTE_HPP
#include <cstddef>
#include <cstdint>
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

+ 30
- 9
src/gl/vertex-buffer.cpp View File

@ -18,6 +18,7 @@
*/
#include "gl/vertex-buffer.hpp"
#include <stdexcept>
#include <glad/glad.h>
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<std::size_t>(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<GLsizeiptr>(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<std::size_t>(usage)];
glBindBuffer(GL_ARRAY_BUFFER, gl_buffer_id);
glBufferData(GL_ARRAY_BUFFER, size, data, gl_usage);
glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizeiptr>(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<GLintptr>(offset), static_cast<GLsizeiptr>(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<GLintptr>(offset), static_cast<GLsizeiptr>(size), data);
}
} // namespace gl

+ 60
- 9
src/gl/vertex-buffer.hpp View File

@ -20,35 +20,87 @@
#ifndef ANTKEEPER_GL_VERTEX_BUFFER_HPP
#define ANTKEEPER_GL_VERTEX_BUFFER_HPP
#include <cstdlib>
#include <cstddef>
#include <cstdint>
#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

+ 1
- 1
src/math/random.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_MATH_RANDOM_HPP
#define ANTKEEPER_MATH_RANDOM_HPP
#include <cstdlib>
#include <cstddef>
#include <type_traits>
namespace math {

+ 1
- 1
src/renderer/material-property.hpp View File

@ -28,7 +28,7 @@
#include "gl/shader-program.hpp"
#include "gl/texture-2d.hpp"
#include "gl/texture-cube.hpp"
#include <cstdlib>
#include <cstddef>
class material;

+ 1
- 1
src/renderer/material.hpp View File

@ -23,7 +23,7 @@
#include "renderer/material-property.hpp"
#include "gl/shader-program.hpp"
#include <cstdint>
#include <cstdlib>
#include <cstddef>
#include <list>
#include <map>
#include <string>

+ 13
- 3
src/renderer/passes/bloom-pass.cpp View File

@ -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 <cmath>
@ -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()

+ 13
- 3
src/renderer/passes/final-pass.cpp View File

@ -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 <cmath>
@ -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()

+ 2
- 2
src/renderer/passes/material-pass.cpp View File

@ -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"

+ 2
- 2
src/renderer/passes/outline-pass.cpp View File

@ -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"

+ 2
- 2
src/renderer/passes/sky-pass.cpp View File

@ -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"

+ 2
- 2
src/renderer/passes/ui-pass.cpp View File

@ -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"

+ 1
- 1
src/renderer/render-operation.hpp View File

@ -23,7 +23,7 @@
#include "utility/fundamental-types.hpp"
#include "gl/vertex-array.hpp"
#include "gl/drawing-mode.hpp"
#include <cstdlib>
#include <cstddef>
class pose;
class material;

+ 28
- 0
src/renderer/renderer.cpp View File

@ -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<const scene::billboard*>(object));
else if (type == scene::lod_group::object_type_id)
process_lod_group(context, static_cast<const scene::lod_group*>(object));
else if (type == scene::text::object_type_id)
process_text(context, static_cast<const scene::text*>(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<float>* 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);
}

+ 2
- 0
src/renderer/renderer.hpp View File

@ -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;
};

+ 13
- 3
src/renderer/simple-render-pass.cpp View File

@ -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()

src/renderer/vertex-attributes.hpp → src/renderer/vertex-attribute.hpp View File

@ -17,8 +17,8 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#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

+ 1
- 1
src/resources/image.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_IMAGE_HPP
#define ANTKEEPER_IMAGE_HPP
#include <cstdlib>
#include <cstddef>
/**
* Stores basic image data.

+ 24
- 15
src/resources/model-loader.cpp View File

@ -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 <sstream>
@ -471,28 +471,37 @@ model* resource_loader::load(resource_manager* resource_manager, PHYSFS_F
// Map attribute names to locations
static const std::unordered_map<std::string, unsigned int> 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

+ 1
- 1
src/resources/resource-handle.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_RESOURCE_HANDLE_HPP
#define ANTKEEPER_RESOURCE_HANDLE_HPP
#include <cstdlib>
#include <cstddef>
/**
* Base class for resource handles.

+ 1
- 1
src/scene/object.hpp View File

@ -26,7 +26,7 @@
#include "math/quaternion-type.hpp"
#include "math/transform-type.hpp"
#include <atomic>
#include <cstdlib>
#include <cstddef>
namespace scene {

+ 314
- 0
src/scene/text.cpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "scene/text.hpp"
#include "renderer/material.hpp"
#include "renderer/vertex-attribute.hpp"
#include "math/vector-operators.hpp"
#include <cstddef>
#include <codecvt>
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<std::codecvt_utf8<char32_t>, 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<float*>(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<float>(glyph.position.x), static_cast<float>(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<float>(font_bitmap.get_width());
uvs[i].y = uvs[i].y / static_cast<float>(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<float>(local_bounds.min_point[j], position[j]);
local_bounds.max_point[j] = std::max<float>(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<char32_t>('\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<float*>(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

+ 183
- 0
src/scene/text.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<text>
{
public:
typedef geom::aabb<float> 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<std::byte> 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

src/gl/vertex-attribute-type.hpp → src/type/text-direction.hpp View File

@ -17,25 +17,23 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#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

+ 1
- 0
src/type/type.hpp View File

@ -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

+ 1
- 1
src/utility/paths.cpp View File

@ -18,7 +18,7 @@
*/
#include "paths.hpp"
#include <cstdlib>
#include <cstddef>
#include <limits.h>
#include <stdexcept>

Loading…
Cancel
Save