Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9d58c8c
rework text instance and type setting
Tehsapper Jun 7, 2025
fb68f8a
implement font stack support
Tehsapper Jun 9, 2025
d0501be
fix text selection
Tehsapper Jun 9, 2025
995a7e7
add support for CJK variant selection in text format
Tehsapper Jun 11, 2025
68f5b78
implement line spacing modifier
Tehsapper Jun 11, 2025
33094d6
fix LightContainer::add
Tehsapper Jun 12, 2025
6e7dffc
add pixel size override for type setter
Tehsapper Jun 16, 2025
1476595
add links support to text instance
Tehsapper Jun 16, 2025
4fcf065
fix includes
Tehsapper Jun 21, 2025
e990091
split composite pass into bloom enabled version
Tehsapper Jul 8, 2025
dd853bc
fix effect shader
Tehsapper Jul 8, 2025
caedf18
fix light removal
Tehsapper Jul 10, 2025
38b4104
fix glb loading
Tehsapper Jul 12, 2025
2541f56
add CPU profiler
Tehsapper Jul 15, 2025
a79c8f1
fix text selection driver crash
Tehsapper Aug 19, 2025
d3f50d2
profile cursor pos retrieval
Tehsapper Aug 25, 2025
2e3e712
support monospace digits
Tehsapper Aug 26, 2025
87de460
expire emitter once particles are dead
Tehsapper Aug 26, 2025
8b0ae1f
simplify camera
Tehsapper Sep 2, 2025
1c33bc1
meme snow
Tehsapper Sep 7, 2025
abee503
fix mutable texture image loading
Tehsapper Sep 8, 2025
a2a5cbf
more profiling
Tehsapper Sep 24, 2025
cff36a7
pass tex loader flags to gltf loader
Tehsapper Oct 12, 2025
58fa0e1
add ASTC compression support
Tehsapper Oct 13, 2025
dcae8e8
remove ASTC compression support as it cannot be used online
Tehsapper Oct 13, 2025
c89a964
improve skeletal rendering
Tehsapper Oct 14, 2025
7c21d04
implement GLTF saver via cgltf plus extension support
Tehsapper Oct 18, 2025
d6b3554
implement fog
Tehsapper Oct 19, 2025
add9b94
try ACES mapping
Tehsapper Oct 20, 2025
371c19e
fix failure on 0x0 framebuffer
Tehsapper Nov 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ set(ENGINE_CORE
src/limitless/core/context_observer.cpp
src/limitless/core/state_query.cpp
src/limitless/core/profiler.cpp
src/limitless/core/cpu_profiler.cpp
src/limitless/core/time_query.cpp

src/limitless/core/texture/texture.cpp
Expand Down Expand Up @@ -96,11 +97,14 @@ set(ENGINE_LOADERS
src/limitless/loaders/dds_loader.cpp
src/limitless/loaders/cgltf.c
src/limitless/loaders/gltf_model_loader.cpp
src/limitless/loaders/cgltf_write.c
src/limitless/loaders/gltf_model_saver.cpp
)

set(ENGINE_MODELS
src/limitless/models/elementary_model.cpp
src/limitless/models/text_model.cpp
src/limitless/models/text_selection_model.cpp
src/limitless/models/skeletal_model.cpp
src/limitless/models/abstract_model.cpp
src/limitless/models/cube.cpp
Expand Down Expand Up @@ -141,6 +145,7 @@ set(ENGINE_MS
set(ENGINE_TEXT
src/limitless/text/text_instance.cpp
src/limitless/text/font_atlas.cpp
src/limitless/text/type_setter.cpp
)

set(ENGINE_FX
Expand Down Expand Up @@ -173,6 +178,7 @@ set(ENGINE_RENDERER
src/limitless/renderer/deferred_lighting_pass.cpp
src/limitless/renderer/depth_pass.cpp
src/limitless/renderer/translucent_pass.cpp
src/limitless/renderer/fog_pass.cpp
src/limitless/renderer/bloom_pass.cpp
src/limitless/renderer/composite_pass.cpp
src/limitless/renderer/ssao_pass.cpp
Expand Down
37 changes: 14 additions & 23 deletions include/limitless/camera.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,27 @@
#include <glm/gtx/quaternion.hpp>

namespace Limitless {
enum class CameraMovement { Forward, Backward, Left, Right, Up, Down };
enum class CameraMode { Free, Panning };

class Camera {
private:
glm::vec3 position;
glm::vec3 front, up, right, world_up;
glm::vec3 front;
glm::vec3 up;
glm::vec3 right;
glm::vec3 world_up;

glm::mat4 projection;
glm::mat4 view;
glm::mat4 view_to_screen;

CameraMode mode {};

float pitch;
float pitch; // degrees
float yaw;

float fov {90}; // degrees
float near_distance {0.01f};
float far_distance {100.0f};

float move_speed {2.0f};
float mouse_sence {0.5f};
public:
explicit Camera(glm::uvec2 window_size) noexcept;
explicit Camera(glm::uvec2 screen_size) noexcept;

[[nodiscard]] const auto& getViewToScreen() const noexcept { return view_to_screen; }
[[nodiscard]] const auto& getProjection() const noexcept { return projection; }
Expand All @@ -42,21 +38,16 @@ namespace Limitless {
[[nodiscard]] const auto& getNear() const noexcept { return near_distance; }
[[nodiscard]] const auto& getFar() const noexcept { return far_distance; }
[[nodiscard]] const auto& getFov() const noexcept { return fov; }

[[nodiscard]] auto& getMoveSpeed() noexcept { return move_speed; }
[[nodiscard]] auto& getMouseSence() noexcept { return mouse_sence; }
[[nodiscard]] auto& getMode() noexcept { return mode; }
[[nodiscard]] const auto& getPitch() const noexcept { return pitch; }
[[nodiscard]] const auto& getYaw() const noexcept { return yaw; }

void setPosition(const glm::vec3& position) noexcept;
void setFront(const glm::vec3& front) noexcept;
void setFov(glm::uvec2 size, float fov) noexcept;
void setMode(CameraMode mode) noexcept;

void mouseMove(glm::dvec2 offset) noexcept;
void mouseScroll(float yoffset) noexcept;
void movement(CameraMovement move, float delta) noexcept;
void setFov(glm::uvec2 screen_size, float fov) noexcept;
void setPitch(float pitch) noexcept;
void setYaw(float yaw) noexcept;
void setRotation(float pitch, float yaw) noexcept;

void updateView() noexcept;
void updateProjection(glm::uvec2 size) noexcept;
void updateProjection(glm::uvec2 screen_size) noexcept;
};
}
}
5 changes: 4 additions & 1 deletion include/limitless/core/context_initializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace Limitless {

static void initializeGLEW();
static void initializeGLFW();
static void getExtensions() noexcept;
static void discoverExtensions() noexcept;
static void getLimits() noexcept;

ContextInitializer();
Expand All @@ -41,6 +41,9 @@ namespace Limitless {
static void printExtensions() noexcept;
static bool isExtensionSupported(std::string_view name) noexcept;
static bool checkMinimumRequirements() noexcept;
static const auto& getExtensions() noexcept {
return extensions;
}

static bool isProgramInterfaceQuerySupported() noexcept;
static bool isBindlessTextureSupported() noexcept;
Expand Down
57 changes: 57 additions & 0 deletions include/limitless/core/cpu_profiler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#pragma once

#include <chrono>
#include <unordered_map>

namespace Limitless {
struct CpuProfiler {
using MonotonicTime = std::chrono::steady_clock::time_point;
using Duration = std::chrono::steady_clock::duration;

struct Frame {
void record(Duration period);

Duration getMinDuration() const noexcept;
Duration getMaxDuration() const noexcept;
Duration getAverageDuration() const noexcept;
Duration getLastDuration() const noexcept;
size_t getCount() const noexcept;

Duration getTotalPerFrame() const noexcept;
size_t getCountPerFrame() const noexcept;

void startFrame();

private:
Duration min {Duration::max()};
Duration max {Duration::min()};
Duration avg {Duration::zero()};
Duration last {Duration::zero()};
Duration total_per_frame {Duration::zero()};
size_t n_per_frame {0};
size_t n {0};
};

std::unordered_map<const char*, Frame> frames;

void startFrame();
};

extern CpuProfiler global_profiler;

struct CpuProfileScope {
CpuProfiler::Frame& frame;
// Is a const char* to avoid dynamically allocating a std::sting for
// every profile frame.
const char* identifier;
CpuProfiler::MonotonicTime start;

CpuProfileScope(CpuProfiler& profiler, const char* id) noexcept;

~CpuProfileScope();

private:
// TODO: consider taking a clock instance.
static CpuProfiler::MonotonicTime now() noexcept;
};
}
9 changes: 8 additions & 1 deletion include/limitless/core/texture/texture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ namespace Limitless {

// GL_ARB_texture_compression_rgtc
R_RGTC = GL_COMPRESSED_RED_RGTC1,
RG_RGTC = GL_COMPRESSED_RG_RGTC2
RG_RGTC = GL_COMPRESSED_RG_RGTC2,

// GL_KHR_texture_compression_astc_ldr
RGBA_ASTC_4x4 = GL_COMPRESSED_RGBA_ASTC_4x4_KHR,
sRGBA8_ASTC_4x4 = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
};

enum class Format {
Expand Down Expand Up @@ -131,6 +135,8 @@ namespace Limitless {
bool mipmap {false};
bool compressed {false};
bool immutable {false};

size_t getBytesPerPixel() const noexcept;
protected:
Texture() = default;
public:
Expand Down Expand Up @@ -164,6 +170,7 @@ namespace Limitless {
[[nodiscard]] auto isCubemapArray() const noexcept { return target == Type::TexCubeMapArray; }
[[nodiscard]] uint32_t getId() const noexcept;
[[nodiscard]] auto& getExtensionTexture() noexcept { return *texture; }
[[nodiscard]] std::vector<std::byte> getPixels() const noexcept;

Texture& setMinFilter(Filter filter);
Texture& setMagFilter(Filter filter);
Expand Down
8 changes: 4 additions & 4 deletions include/limitless/core/texture/texture_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ namespace Limitless {
Builder& wrap_t(Texture::Wrap wrap);
Builder& wrap_r(Texture::Wrap wrap);

void useStateExtensionTexture();
void useNamedExtensionTexture();
void useBindlessExtensionTexture();
void useBestSupportedExtensionTexture();
Builder& useStateExtensionTexture();
Builder& useNamedExtensionTexture();
Builder& useBindlessExtensionTexture();
Builder& useBestSupportedExtensionTexture();

std::shared_ptr<Texture> buildMutable();
std::shared_ptr<Texture> buildImmutable();
Expand Down
17 changes: 15 additions & 2 deletions include/limitless/core/vertex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,27 @@ namespace Limitless {
struct TextVertex {
glm::vec2 position;
glm::vec2 uv;
glm::vec4 color;

TextVertex(glm::vec2 _position, glm::vec2 _uv) noexcept
TextVertex(glm::vec2 _position, glm::vec2 _uv, glm::vec4 _color) noexcept
: position{_position}
, uv{_uv} {}
, uv{_uv}
, color{_color}
{}

TextVertex() = default;
};

struct TextSelectionVertex {
glm::vec2 position;

TextSelectionVertex(glm::vec2 _position) noexcept
: position{_position}
{}

TextSelectionVertex() = default;
};

struct VertexNormal {
glm::vec3 position;
glm::vec3 normal;
Expand Down
1 change: 1 addition & 0 deletions include/limitless/core/vertex_array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ namespace Limitless {
VertexArray& operator<<(const std::pair<TextVertex, const std::shared_ptr<Buffer>&>& attribute) noexcept;
VertexArray& operator<<(const std::pair<VertexNormalTangent, const std::shared_ptr<Buffer>&>& attribute) noexcept;
VertexArray& operator<<(const std::pair<VertexTerrain, const std::shared_ptr<Buffer>&>& attribute) noexcept;
VertexArray& operator<<(const std::pair<TextSelectionVertex, const std::shared_ptr<Buffer>&>& attribute) noexcept;
};

void swap(VertexArray& lhs, VertexArray& rhs);
Expand Down
1 change: 1 addition & 0 deletions include/limitless/instances/instanced_instance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace Limitless {
void update(const Camera &camera) override;

auto& getInstances() noexcept { return instances; }
const auto& getInstances() const noexcept { return instances; }
auto& getVisibleInstances() noexcept { return visible_instances; }
auto& getBuffer() noexcept { return buffer ; }

Expand Down
13 changes: 11 additions & 2 deletions include/limitless/loaders/gltf_model_loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace Limitless {
class AbstractModel;
class TextureLoaderFlags;

enum class ModelLoaderOption {
FlipUV,
Expand All @@ -27,6 +28,7 @@ namespace Limitless {
std::set<ModelLoaderOption> options;
float scale_factor {1.0f};
InstanceTypes additional_instance_types;
TextureLoaderFlags base_tex_flags;

auto isPresent(ModelLoaderOption option) const { return options.count(option) != 0; }

Expand All @@ -39,17 +41,24 @@ namespace Limitless {
additional_instance_types.emplace(InstanceType::Instanced);
return *this;
}

ModelLoaderFlags& baseTextureLoaderFlags(TextureLoaderFlags tex_flags) {
base_tex_flags = std::move(tex_flags);
return *this;
}
};

class GltfModelLoader {
public:
// Load a 3D model from given file.
// Load a GLTF 3D model from given file.
// Will also attempt to load materials referenced in model definition.
// Returns a shared pointer to resulting model on success.
// Provided assets are modified.
// On failure, a ModelLoadError exception is thrown.
static std::shared_ptr<AbstractModel> loadModel(
Assets& assets, const fs::path& path, const ModelLoaderFlags& flags
Assets& assets,
const fs::path& path,
const ModelLoaderFlags& flags
);
};
}
17 changes: 17 additions & 0 deletions include/limitless/loaders/gltf_model_saver.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <filesystem>
#include <limitless/assets.hpp>
#include <limitless/models/model.hpp>

namespace Limitless {
struct ModelSaveError : public std::runtime_error {
explicit ModelSaveError(const std::string& msg) noexcept
: std::runtime_error(msg) {}
};

class GltfModelSaver {
public:
static void saveModel(const std::filesystem::path& output_path, const Model& model);
};
}
Loading