Compare commits

..

2 Commits

  1. 10
      src/inferno/application.cpp
  2. 55
      src/inferno/asset/asset-manager.cpp
  3. 94
      src/inferno/asset/asset-manager.h
  4. 80
      src/inferno/asset/font.cpp
  5. 52
      src/inferno/asset/font.h
  6. 125
      src/inferno/asset/shader.cpp
  7. 64
      src/inferno/asset/shader.h
  8. 72
      src/inferno/asset/texture.cpp
  9. 70
      src/inferno/asset/texture.h
  10. 4
      src/inferno/component/cubemap-component.cpp
  11. 2
      src/inferno/component/cubemap-component.h
  12. 5
      src/inferno/component/spritecomponent.cpp
  13. 2
      src/inferno/component/spritecomponent.h
  14. 11
      src/inferno/render/renderer.cpp
  15. 77
      src/inferno/render/shader.h
  16. 8
      src/inferno/system/textareasystem.cpp
  17. 4
      src/inferno/system/textareasystem.h
  18. 63
      vendor/glad/LICENSE
  19. 2
      vendor/ruc

10
src/inferno/application.cpp

@ -17,16 +17,16 @@
#include "inferno/event/keyevent.h" #include "inferno/event/keyevent.h"
#include "inferno/event/mouseevent.h" #include "inferno/event/mouseevent.h"
// #include "inferno/io/gltffile.h" // #include "inferno/io/gltffile.h"
#include "inferno/asset/font.h"
#include "inferno/io/input.h" #include "inferno/io/input.h"
#include "inferno/keycodes.h" #include "inferno/keycodes.h"
#include "inferno/render/buffer.h" #include "inferno/render/buffer.h"
#include "inferno/render/context.h" #include "inferno/render/context.h"
#include "inferno/render/font.h"
// #include "inferno/render/gltf.h" // #include "inferno/render/gltf.h"
#include "inferno/asset/shader.h"
#include "inferno/asset/texture.h"
#include "inferno/render/render-command.h" #include "inferno/render/render-command.h"
#include "inferno/render/renderer.h" #include "inferno/render/renderer.h"
#include "inferno/render/shader.h"
#include "inferno/render/texture.h"
#include "inferno/scene/scene.h" #include "inferno/scene/scene.h"
#include "inferno/settings.h" #include "inferno/settings.h"
#include "inferno/time.h" #include "inferno/time.h"
@ -78,13 +78,11 @@ Application::~Application()
{ {
m_scene->destroy(); m_scene->destroy();
FontManager::destroy();
RendererFont::destroy(); RendererFont::destroy();
Renderer2D::destroy(); Renderer2D::destroy();
RendererCubemap::destroy(); RendererCubemap::destroy();
RenderCommand::destroy(); RenderCommand::destroy();
TextureManager::destroy(); AssetManager::destroy();
ShaderManager::destroy();
// Input::destroy(); // Input::destroy();
Settings::destroy(); Settings::destroy();

55
src/inferno/asset/asset-manager.cpp

@ -0,0 +1,55 @@
/*
* Copyright (C) 2024 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#include <memory> // std::shared_ptr, std::static_pointer_cast
#include <string>
#include <string_view>
#include "ruc/format/log.h"
#include "inferno/asset/asset-manager.h"
#include "inferno/asset/shader.h"
namespace Inferno {
// -----------------------------------------
AssetManager::AssetManager(s)
{
ruc::info("AssetManager initialized");
}
AssetManager::~AssetManager()
{
}
void AssetManager::add(std::string_view path, std::shared_ptr<Asset> asset)
{
// Construct (key, value) pair and insert it into the unordered_map
auto stringPath = std::string(path.begin(), path.end());
m_assetList.emplace(std::move(stringPath), std::move(asset));
}
bool AssetManager::exists(std::string_view path)
{
return m_assetList.find(path.data()) != m_assetList.end();
}
void AssetManager::remove(std::string_view path)
{
if (exists(path)) {
m_assetList.erase(path.data());
}
}
void AssetManager::remove(std::shared_ptr<Asset> asset)
{
if (exists(asset->path())) {
m_assetList.erase(asset->path());
}
}
} // namespace Inferno

94
src/inferno/asset/asset-manager.h

@ -0,0 +1,94 @@
/*
* Copyright (C) 2024 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <memory> // std::shared_ptr
#include <string>
#include <string_view>
#include <unordered_map>
#include "ruc/meta/assert.h"
#include "ruc/meta/types.h"
#include "ruc/singleton.h"
namespace Inferno {
class Asset {
public:
virtual ~Asset() = default;
std::string path() const { return m_path; }
// -------------------------------------
std::string className() const { return typeid(*this).name(); }
template<typename T>
bool fastIs() const = delete;
virtual bool isFont() const { return false; }
virtual bool isShader() const { return false; }
virtual bool isTexture() const { return false; }
virtual bool isTexture2D() const { return false; }
virtual bool isTextureCubemap() const { return false; }
protected:
Asset(std::string_view path)
: m_path(std::string(path.begin(), path.end()))
{
}
protected:
std::string m_path;
};
// -----------------------------------------
template<typename T>
concept IsAsset = std::same_as<Asset, T> || std::derived_from<T, Asset>;
// -----------------------------------------
class AssetManager : public ruc::Singleton<AssetManager> {
public:
AssetManager(s);
virtual ~AssetManager();
void add(std::string_view path, std::shared_ptr<Asset> asset);
bool exists(std::string_view path);
void remove(std::string_view path);
void remove(std::shared_ptr<Asset> asset);
template<IsAsset T>
std::shared_ptr<T> get(std::string_view path)
{
if (!exists(path)) {
return nullptr;
}
auto asset = m_assetList.at(path.data());
VERIFY(is<T>(asset.get()), "expected asset {}, got {}", typeid(T).name(), asset->className());
return std::static_pointer_cast<T>(asset);
}
template<IsAsset T>
std::shared_ptr<T> load(std::string_view path)
{
if (exists(path)) {
return get<T>(path);
}
auto asset = T::create(path);
add(path, asset);
return asset;
}
private:
std::unordered_map<std::string, std::shared_ptr<Asset>> m_assetList;
};
} // namespace Inferno

80
src/inferno/render/font.cpp → src/inferno/asset/font.cpp

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2022 Riyyi * Copyright (C) 2022-2024 Riyyi
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
@ -7,32 +7,32 @@
#include <array> // std::array #include <array> // std::array
#include <charconv> // std;:from_chars #include <charconv> // std;:from_chars
#include <cstdint> // int32_t, uint32_t #include <cstdint> // int32_t, uint32_t
#include <limits> // std::numeric_limits
#include <ranges> // std::views::split #include <ranges> // std::views::split
#include <string> // std::getline #include <string> // std::getline
#include <utility> // std::move
#include "ruc/file.h" #include "ruc/file.h"
#include "ruc/format/log.h"
#include "ruc/meta/assert.h" #include "ruc/meta/assert.h"
#include "ruc/meta/concepts.h" #include "ruc/meta/concepts.h"
#include "inferno/render/font.h" #include "inferno/asset/font.h"
#include "inferno/render/texture.h" #include "inferno/asset/texture.h"
#include "inferno/util/integer.h"
namespace Inferno { namespace Inferno {
Font::Font(const std::string& name) std::shared_ptr<Font> Font::create(std::string_view path)
: m_name(std::move(name))
{ {
std::string path = name + ".fnt"; auto result = std::shared_ptr<Font>(new Font(path));
std::string image = name + ".png";
std::string font = ruc::File(path).data(); auto stringPath = std::string(path);
parseFont(font); std::string file = stringPath + ".fnt";
std::string image = stringPath + ".png";
m_texture = Texture2D::create(image); std::string font = ruc::File(file).data();
result->parseFont(font);
result->m_texture = Texture2D::create(image);
return result;
} }
// TODO: Move this to ruc // TODO: Move this to ruc
@ -167,58 +167,6 @@ std::string Font::findValue(const std::string& key, const std::vector<std::strin
return ""; return "";
} }
// -----------------------------------------
FontManager::FontManager(s)
{
ruc::info("FontManager initialized");
}
FontManager::~FontManager()
{
}
void FontManager::add(const std::string& name, std::shared_ptr<Font> font)
{
// Construct (key, value) pair and insert it into the unordered_map
m_fontList.emplace(std::move(name), std::move(font));
}
std::shared_ptr<Font> FontManager::load(const std::string& name)
{
if (exists(name)) {
return get(name);
}
std::shared_ptr<Font> font = std::make_shared<Font>(name);
add(name, font);
return get(name);
}
std::shared_ptr<Font> FontManager::get(const std::string& name)
{
return exists(name) ? m_fontList.at(name) : nullptr;
}
bool FontManager::exists(const std::string& name)
{
return m_fontList.find(name) != m_fontList.end();
}
void FontManager::remove(const std::string& name)
{
if (exists(name)) {
m_fontList.erase(name);
}
}
void FontManager::remove(std::shared_ptr<Font> font)
{
if (exists(font->name())) {
m_fontList.erase(font->name());
}
}
} // namespace Inferno } // namespace Inferno
void ruc::format::Formatter<glm::ivec2>::format(Builder& builder, glm::ivec2 value) const void ruc::format::Formatter<glm::ivec2>::format(Builder& builder, glm::ivec2 value) const

52
src/inferno/render/font.h → src/inferno/asset/font.h

@ -1,22 +1,24 @@
/* /*
* Copyright (C) 2022 Riyyi * Copyright (C) 2022-2024 Riyyi
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#pragma once #pragma once
#include <array> // std::array #include <array> // std::array
#include <cstdint> // int32_t, uint32_t #include <cstdint> // int32_t, uint32_t
#include <memory> // std::shared_ptr #include <memory> // std::shared_ptr
#include <string> // std::string #include <string> // std::string
#include <string_view>
#include <unordered_map> // std::unordered_map #include <unordered_map> // std::unordered_map
#include <vector> // std::vector #include <vector> // std::vector
#include "glm/ext/vector_int2.hpp" // glm::ivec2 #include "glm/ext/vector_int2.hpp" // glm::ivec2
#include "glm/ext/vector_uint2.hpp" // glm::uvec2 #include "glm/ext/vector_uint2.hpp" // glm::uvec2
#include "ruc/format/format.h" #include "ruc/format/format.h"
#include "ruc/singleton.h"
#include "inferno/asset/asset-manager.h"
#define PADDING 3 #define PADDING 3
@ -35,11 +37,13 @@ struct Symbol {
// ------------------------------------- // -------------------------------------
class Font { class Font final : public Asset {
public: public:
Font(const std::string& name);
virtual ~Font() {} virtual ~Font() {}
// Factory function
static std::shared_ptr<Font> create(std::string_view path);
enum Padding { enum Padding {
Top = 0, Top = 0,
Right, Right,
@ -47,7 +51,6 @@ public:
Left, Left,
}; };
inline std::string name() const { return m_name; }
inline uint32_t size() const { return m_size; } inline uint32_t size() const { return m_size; }
inline uint32_t lineSpacing() const { return m_lineSpacing; } inline uint32_t lineSpacing() const { return m_lineSpacing; }
inline std::shared_ptr<Texture> texture() const { return m_texture; } inline std::shared_ptr<Texture> texture() const { return m_texture; }
@ -56,12 +59,19 @@ public:
inline std::shared_ptr<Symbol> operator[](unsigned char c) const { return m_symbolList.at(c); } inline std::shared_ptr<Symbol> operator[](unsigned char c) const { return m_symbolList.at(c); }
private: private:
Font(std::string_view path)
: Asset(path)
{
}
void parseFont(const std::string& font); void parseFont(const std::string& font);
std::string findAction(const std::string& line) const; std::string findAction(const std::string& line) const;
std::vector<std::string> findColumns(const std::string& line) const; std::vector<std::string> findColumns(const std::string& line) const;
std::string findValue(const std::string& key, const std::vector<std::string>& columns) const; std::string findValue(const std::string& key, const std::vector<std::string>& columns) const;
std::string m_name; virtual bool isFont() const override { return true; }
private:
unsigned char m_size = { 0 }; unsigned char m_size = { 0 };
uint32_t m_lineSpacing = { 0 }; uint32_t m_lineSpacing = { 0 };
std::array<uint32_t, 4> m_padding = { 0 }; std::array<uint32_t, 4> m_padding = { 0 };
@ -69,24 +79,12 @@ private:
std::unordered_map<unsigned char, std::shared_ptr<Symbol>> m_symbolList; std::unordered_map<unsigned char, std::shared_ptr<Symbol>> m_symbolList;
}; };
// ------------------------------------- // -----------------------------------------
class FontManager final : public ruc::Singleton<FontManager> { // clang-format off
public: template<>
FontManager(s); inline bool Asset::fastIs<Font>() const { return isFont(); }
virtual ~FontManager(); // clang-format on
void add(const std::string& name, std::shared_ptr<Font> font);
std::shared_ptr<Font> load(const std::string& name);
std::shared_ptr<Font> get(const std::string& name);
bool exists(const std::string& name);
void remove(const std::string& name);
void remove(std::shared_ptr<Font> font);
private:
std::unordered_map<std::string, std::shared_ptr<Font>> m_fontList;
};
} // namespace Inferno } // namespace Inferno

125
src/inferno/render/shader.cpp → src/inferno/asset/shader.cpp

@ -1,11 +1,10 @@
/* /*
* Copyright (C) 2022 Riyyi * Copyright (C) 2022,2024 Riyyi
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#include <utility> // std::move #include <vector> // std::vector
#include <vector> // std::vector
#include "glad/glad.h" #include "glad/glad.h"
#include "glm/gtc/type_ptr.hpp" // glm::value_ptr #include "glm/gtc/type_ptr.hpp" // glm::value_ptr
@ -13,32 +12,34 @@
#include "ruc/format/log.h" #include "ruc/format/log.h"
#include "ruc/meta/assert.h" #include "ruc/meta/assert.h"
#include "inferno/core.h" #include "inferno/asset/shader.h"
#include "inferno/render/shader.h"
namespace Inferno { namespace Inferno {
Shader::Shader(const std::string& name) std::shared_ptr<Shader> Shader::create(std::string_view path)
: m_name(std::move(name))
, m_id(0)
{ {
auto result = std::shared_ptr<Shader>(new Shader(path));
// Get file contents // Get file contents
std::string vertexSrc = ruc::File(name + ".vert").data(); auto stringPath = std::string(path);
std::string fragmentSrc = ruc::File(name + ".frag").data(); std::string vertexSrc = ruc::File(stringPath + ".vert").data();
std::string fragmentSrc = ruc::File(stringPath + ".frag").data();
// Compile shaders // Compile shaders
uint32_t vertexID = compileShader(GL_VERTEX_SHADER, vertexSrc.c_str()); uint32_t vertexID = result->compileShader(GL_VERTEX_SHADER, vertexSrc.c_str());
uint32_t fragmentID = compileShader(GL_FRAGMENT_SHADER, fragmentSrc.c_str()); uint32_t fragmentID = result->compileShader(GL_FRAGMENT_SHADER, fragmentSrc.c_str());
// Link shaders // Link shaders
if (vertexID > 0 && fragmentID > 0) { if (vertexID > 0 && fragmentID > 0) {
m_id = linkShader(vertexID, fragmentID); result->m_id = result->linkShader(vertexID, fragmentID);
} }
// Clear resources // Clear resources
else if (vertexID > 0) else if (vertexID > 0)
glDeleteShader(vertexID); glDeleteShader(vertexID);
else if (fragmentID > 0) else if (fragmentID > 0)
glDeleteShader(fragmentID); glDeleteShader(fragmentID);
return result;
} }
Shader::~Shader() Shader::~Shader()
@ -49,62 +50,62 @@ Shader::~Shader()
} }
} }
int32_t Shader::findUniform(const std::string& name) const int32_t Shader::findUniform(std::string_view name) const
{ {
int32_t location = glGetUniformLocation(m_id, name.c_str()); int32_t location = glGetUniformLocation(m_id, name.data());
VERIFY(location != -1, "Shader could not find uniform '{}'", name); VERIFY(location != -1, "Shader could not find uniform '{}'", name);
return location; return location;
} }
void Shader::setInt(const std::string& name, int value) void Shader::setInt(std::string_view name, int value)
{ {
// Set uniform int // Set uniform int
glUniform1i(findUniform(name), value); glUniform1i(findUniform(name), value);
} }
void Shader::setInt(const std::string& name, int* values, uint32_t count) void Shader::setInt(std::string_view name, int* values, uint32_t count)
{ {
// Set uniform int array // Set uniform int array
glUniform1iv(findUniform(name), count, values); glUniform1iv(findUniform(name), count, values);
} }
void Shader::setFloat(const std::string& name, float value) const void Shader::setFloat(std::string_view name, float value) const
{ {
// Set uniform float // Set uniform float
glUniform1f(findUniform(name), value); glUniform1f(findUniform(name), value);
} }
void Shader::setFloat(const std::string& name, float v1, float v2, float v3, float v4) const void Shader::setFloat(std::string_view name, float v1, float v2, float v3, float v4) const
{ {
// Set uniform vec4 data // Set uniform vec4 data
glUniform4f(findUniform(name), v1, v2, v3, v4); glUniform4f(findUniform(name), v1, v2, v3, v4);
} }
void Shader::setFloat(const std::string& name, glm::vec2 value) const void Shader::setFloat(std::string_view name, glm::vec2 value) const
{ {
// Set uniform vec2 data // Set uniform vec2 data
glUniform2f(findUniform(name), value.x, value.y); glUniform2f(findUniform(name), value.x, value.y);
} }
void Shader::setFloat(const std::string& name, glm::vec3 value) const void Shader::setFloat(std::string_view name, glm::vec3 value) const
{ {
// Set uniform vec3 data // Set uniform vec3 data
glUniform3f(findUniform(name), value.x, value.y, value.z); glUniform3f(findUniform(name), value.x, value.y, value.z);
} }
void Shader::setFloat(const std::string& name, glm::vec4 value) const void Shader::setFloat(std::string_view name, glm::vec4 value) const
{ {
// Set uniform vec4 data // Set uniform vec4 data
glUniform4f(findUniform(name), value.x, value.y, value.z, value.w); glUniform4f(findUniform(name), value.x, value.y, value.z, value.w);
} }
void Shader::setFloat(const std::string& name, glm::mat3 matrix) const void Shader::setFloat(std::string_view name, glm::mat3 matrix) const
{ {
// Set uniform mat3 data // Set uniform mat3 data
glUniformMatrix3fv(findUniform(name), 1, GL_FALSE, glm::value_ptr(matrix)); glUniformMatrix3fv(findUniform(name), 1, GL_FALSE, glm::value_ptr(matrix));
} }
void Shader::setFloat(const std::string& name, glm::mat4 matrix) const void Shader::setFloat(std::string_view name, glm::mat4 matrix) const
{ {
// Set uniform mat4 data // Set uniform mat4 data
glUniformMatrix4fv(findUniform(name), 1, GL_FALSE, glm::value_ptr(matrix)); glUniformMatrix4fv(findUniform(name), 1, GL_FALSE, glm::value_ptr(matrix));
@ -199,80 +200,4 @@ int32_t Shader::checkStatus(uint32_t check, bool isProgram) const
return success; return success;
} }
// -----------------------------------------
ShaderManager::ShaderManager(s)
{
ruc::info("ShaderManager initialized");
}
ShaderManager::~ShaderManager()
{
}
void ShaderManager::add(const std::string& name, std::shared_ptr<Shader> shader)
{
// Construct (key, value) pair and insert it into the unordered_map
m_shaderList.emplace(std::move(name), std::move(shader));
}
std::shared_ptr<Shader> ShaderManager::load(const std::string& name)
{
if (exists(name)) {
return get(name);
}
std::shared_ptr<Shader> shader = std::make_shared<Shader>(name);
add(name, shader);
return get(name);
}
std::shared_ptr<Shader> ShaderManager::load(const std::string& vertexSource,
const std::string& fragmentSource)
{
std::string name = computeName(vertexSource, fragmentSource);
return load(name);
}
std::shared_ptr<Shader> ShaderManager::get(const std::string& name)
{
return exists(name) ? m_shaderList.at(name) : nullptr;
}
bool ShaderManager::exists(const std::string& name)
{
return m_shaderList.find(name) != m_shaderList.end();
}
void ShaderManager::remove(const std::string& name)
{
if (exists(name)) {
m_shaderList.erase(name);
}
}
void ShaderManager::remove(std::shared_ptr<Shader> shader)
{
if (exists(shader->name())) {
m_shaderList.erase(shader->name());
}
}
std::string ShaderManager::computeName(const std::string& vertexSource,
const std::string& fragmentSource)
{
auto vertexPos = vertexSource.find_last_of('.');
auto fragmentPos = fragmentSource.find_last_of('.');
VERIFY(vertexPos != std::string::npos, "Shader did not have file extension: '{}'", vertexSource);
VERIFY(fragmentPos != std::string::npos, "Shader did not have file extension: '{}'", fragmentSource);
auto vertexName = vertexSource.substr(0, vertexPos);
auto fragmentName = vertexSource.substr(0, fragmentPos);
VERIFY(vertexName == fragmentName, "Shader names did not match: {} {}", vertexSource, fragmentSource);
return vertexName;
}
} // namespace Inferno } // namespace Inferno

64
src/inferno/asset/shader.h

@ -0,0 +1,64 @@
/*
* Copyright (C) 2022,2024 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#include <cstdint> // int32_t, uint32_t
#include <string_view>
#include "glm/fwd.hpp" // glm::mat3, glm::mat4, glm::vec2, glm::vec3
#include "inferno/asset/asset-manager.h"
namespace Inferno {
class Shader : public Asset {
public:
virtual ~Shader();
// Factory function
static std::shared_ptr<Shader> create(std::string_view path);
int32_t findUniform(std::string_view name) const;
void setInt(std::string_view name, int value);
void setInt(std::string_view name, int* values, uint32_t count);
void setFloat(std::string_view name, float value) const;
void setFloat(std::string_view name, float v1, float v2, float v3, float v4) const;
void setFloat(std::string_view name, glm::vec2 value) const;
void setFloat(std::string_view name, glm::vec3 value) const;
void setFloat(std::string_view name, glm::vec4 value) const;
void setFloat(std::string_view name, glm::mat3 matrix) const;
void setFloat(std::string_view name, glm::mat4 matrix) const;
void bind() const;
void unbind() const;
uint32_t id() const { return m_id; }
protected:
uint32_t compileShader(int32_t type, const char* shaderSource) const;
uint32_t linkShader(uint32_t vertex, uint32_t fragment) const;
int32_t checkStatus(uint32_t check, bool isProgram = false) const;
private:
Shader(std::string_view path)
: Asset(path)
{
}
virtual bool isShader() const override { return true; }
private:
uint32_t m_id { 0 };
};
// -----------------------------------------
// clang-format off
template<>
inline bool Asset::fastIs<Shader>() const { return isShader(); }
// clang-format on
} // namespace Inferno

72
src/inferno/render/texture.cpp → src/inferno/asset/texture.cpp

@ -7,15 +7,13 @@
#include <climits> // UINT_MAX #include <climits> // UINT_MAX
#include <cstdint> // uint8_t, uint32_t #include <cstdint> // uint8_t, uint32_t
#include <memory> // std::shared_ptr #include <memory> // std::shared_ptr
#include <utility> // std::move
#include "glad/glad.h" #include "glad/glad.h"
#include "ruc/format/log.h"
#include "ruc/meta/assert.h" #include "ruc/meta/assert.h"
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "stb/stb_image.h" #include "stb/stb_image.h"
#include "inferno/render/texture.h" #include "inferno/asset/texture.h"
namespace Inferno { namespace Inferno {
@ -35,10 +33,9 @@ void Texture::init(uint32_t width, uint32_t height, uint8_t channels)
// ----------------------------------------- // -----------------------------------------
std::shared_ptr<Texture> Texture2D::create(const std::string& path) std::shared_ptr<Texture2D> Texture2D::create(std::string_view path)
{ {
auto result = std::shared_ptr<Texture2D>(new Texture2D); auto result = std::shared_ptr<Texture2D>(new Texture2D(path));
result->m_path = path;
int width = 0; int width = 0;
int height = 0; int height = 0;
@ -47,7 +44,7 @@ std::shared_ptr<Texture> Texture2D::create(const std::string& path)
// Load image data // Load image data
stbi_set_flip_vertically_on_load(1); stbi_set_flip_vertically_on_load(1);
data = stbi_load(path.c_str(), &width, &height, &channels, STBI_default); data = stbi_load(path.data(), &width, &height, &channels, STBI_default);
VERIFY(data, "failed to load image: '{}'", path); VERIFY(data, "failed to load image: '{}'", path);
result->init(width, height, channels); result->init(width, height, channels);
@ -115,10 +112,9 @@ void Texture2D::create(unsigned char* data)
// ----------------------------------------- // -----------------------------------------
std::shared_ptr<Texture> TextureCubemap::create(const std::string& path) std::shared_ptr<TextureCubemap> TextureCubemap::create(std::string_view path)
{ {
auto result = std::shared_ptr<TextureCubemap>(new TextureCubemap); auto result = std::shared_ptr<TextureCubemap>(new TextureCubemap(path));
result->m_path = path;
result->create(); result->create();
@ -201,57 +197,7 @@ void TextureCubemap::create()
glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
} }
// -----------------------------------------
TextureManager::TextureManager(s)
{
ruc::info("TextureManager initialized");
}
TextureManager::~TextureManager()
{
}
void TextureManager::add(const std::string& path, std::shared_ptr<Texture> texture)
{
// Construct (key, value) pair and insert it into the unordered_map
m_textureList.emplace(std::move(path), std::move(texture));
}
std::shared_ptr<Texture> TextureManager::load(const std::string& path, Texture::Type type)
{
if (exists(path)) {
return get(path);
}
auto texture = (type == Texture::TwoDimensional) ? Texture2D::create(path) : TextureCubemap::create(path);
add(path, texture);
return texture;
}
std::shared_ptr<Texture> TextureManager::get(const std::string& path)
{
return exists(path) ? m_textureList.at(path) : nullptr;
}
bool TextureManager::exists(const std::string& path)
{
return m_textureList.find(path) != m_textureList.end();
}
void TextureManager::remove(const std::string& path)
{
if (exists(path)) {
m_textureList.erase(path);
}
}
void TextureManager::remove(std::shared_ptr<Texture> texture)
{
if (exists(texture->path())) {
m_textureList.erase(texture->path());
}
}
} // namespace Inferno } // namespace Inferno
// FIXME
// auto texture = (type == Texture::TwoDimensional) ? Texture2D::create(path) : TextureCubemap::create(path);

70
src/inferno/render/texture.h → src/inferno/asset/texture.h

@ -6,33 +6,26 @@
#pragma once #pragma once
#include <cstdint> // uint8_t, uint32_t #include <cstdint> // uint8_t, uint32_t
#include <memory> // std::shared_ptr #include <memory> // std::shared_ptr
#include <string> // std::string #include <string_view>
#include <unordered_map> // std::unordered_map
#include "ruc/singleton.h" #include "inferno/asset/asset-manager.h"
namespace Inferno { namespace Inferno {
class Texture2D; class Texture2D;
class TextureCubemap; class TextureCubemap;
class Texture { class Texture : public Asset {
public: public:
virtual ~Texture(); virtual ~Texture();
enum Type : uint8_t {
TwoDimensional = 0,
Cubemap,
};
void init(uint32_t width, uint32_t height, uint8_t channels); void init(uint32_t width, uint32_t height, uint8_t channels);
virtual void bind(uint32_t unit = 0) const = 0; virtual void bind(uint32_t unit = 0) const = 0;
virtual void unbind() const = 0; virtual void unbind() const = 0;
std::string path() const { return m_path; }
uint32_t width() const { return m_width; } uint32_t width() const { return m_width; }
uint32_t height() const { return m_height; } uint32_t height() const { return m_height; }
uint32_t id() const { return m_id; } uint32_t id() const { return m_id; }
@ -40,21 +33,26 @@ public:
uint32_t dataFormat() const { return m_dataFormat; } uint32_t dataFormat() const { return m_dataFormat; }
virtual bool is2D() const { return false; } virtual bool is2D() const { return false; }
virtual bool isCubeMap() const { return false; } virtual bool isCubemap() const { return false; }
friend Texture2D; friend Texture2D;
friend TextureCubemap; friend TextureCubemap;
protected: protected:
Texture() {} Texture(std::string_view path)
: Asset(path)
{
}
protected: protected:
std::string m_path;
uint32_t m_width { 0 }; uint32_t m_width { 0 };
uint32_t m_height { 0 }; uint32_t m_height { 0 };
uint32_t m_id { 0 }; uint32_t m_id { 0 };
uint32_t m_internalFormat { 0 }; uint32_t m_internalFormat { 0 };
uint32_t m_dataFormat { 0 }; uint32_t m_dataFormat { 0 };
private:
virtual bool isTexture() const override { return true; }
}; };
// ------------------------------------- // -------------------------------------
@ -64,15 +62,18 @@ public:
virtual ~Texture2D() = default; virtual ~Texture2D() = default;
// Factory function // Factory function
static std::shared_ptr<Texture> create(const std::string& path); static std::shared_ptr<Texture2D> create(std::string_view path);
virtual void bind(uint32_t unit = 0) const override; virtual void bind(uint32_t unit = 0) const override;
virtual void unbind() const override; virtual void unbind() const override;
private: private:
Texture2D() {} Texture2D(std::string_view path)
: Texture(path)
{
}
virtual bool is2D() const override { return true; } virtual bool isTexture2D() const override { return true; }
private: private:
void create(unsigned char* data); void create(unsigned char* data);
@ -85,37 +86,34 @@ public:
virtual ~TextureCubemap() = default; virtual ~TextureCubemap() = default;
// Factory function // Factory function
static std::shared_ptr<Texture> create(const std::string& path); static std::shared_ptr<TextureCubemap> create(std::string_view path);
virtual void bind(uint32_t unit = 0) const override; virtual void bind(uint32_t unit = 0) const override;
virtual void unbind() const override; virtual void unbind() const override;
private: private:
TextureCubemap() {}; TextureCubemap(std::string_view path)
: Texture(path)
{
}
virtual bool isCubeMap() const override { return true; } virtual bool isTextureCubemap() const override { return true; }
private: private:
void create(); void create();
}; };
// ------------------------------------- // -----------------------------------------
class TextureManager final : public ruc::Singleton<TextureManager> {
public:
TextureManager(s);
~TextureManager();
void add(const std::string& path, std::shared_ptr<Texture> texture); // clang-format off
std::shared_ptr<Texture> load(const std::string& path, Texture::Type type = Texture::Type::TwoDimensional); template<>
std::shared_ptr<Texture> get(const std::string& path); inline bool Asset::fastIs<Texture>() const { return isTexture(); }
bool exists(const std::string& path);
void remove(const std::string& path); template<>
void remove(std::shared_ptr<Texture> texture); inline bool Asset::fastIs<Texture2D>() const { return isTexture2D(); }
private: template<>
std::unordered_map<std::string, std::shared_ptr<Texture>> m_textureList; inline bool Asset::fastIs<TextureCubemap>() const { return isTextureCubemap(); }
}; // clang-format on
} // namespace Inferno } // namespace Inferno

4
src/inferno/component/cubemap-component.cpp

@ -6,9 +6,9 @@
#include "ruc/json/json.h" #include "ruc/json/json.h"
#include "inferno/asset/texture.h"
#include "inferno/component/cubemap-component.h" #include "inferno/component/cubemap-component.h"
#include "inferno/component/spritecomponent.h" // TODO: Move glm::x toJson/fromJson to separate file #include "inferno/component/spritecomponent.h" // TODO: Move glm::x toJson/fromJson to separate file
#include "inferno/render/texture.h"
namespace Inferno { namespace Inferno {
@ -20,7 +20,7 @@ void fromJson(const ruc::Json& json, CubemapComponent& value)
json.at("color").getTo(value.color); json.at("color").getTo(value.color);
} }
if (json.exists("texture") && json.at("texture").type() == ruc::Json::Type::String) { if (json.exists("texture") && json.at("texture").type() == ruc::Json::Type::String) {
value.texture = TextureManager::the().load(json.at("texture").asString(), Texture::Type::Cubemap); value.texture = AssetManager::the().load<TextureCubemap>(json.at("texture").asString());
} }
} }

2
src/inferno/component/cubemap-component.h

@ -11,7 +11,7 @@
#include "glm/ext/vector_float4.hpp" // glm::vec4 #include "glm/ext/vector_float4.hpp" // glm::vec4
#include "ruc/json/json.h" #include "ruc/json/json.h"
#include "inferno/render/texture.h" #include "inferno/asset/texture.h"
namespace Inferno { namespace Inferno {

5
src/inferno/component/spritecomponent.cpp

@ -5,7 +5,8 @@
*/ */
#include "inferno/component/spritecomponent.h" #include "inferno/component/spritecomponent.h"
#include "inferno/render/texture.h" #include "inferno/asset/asset-manager.h"
#include "inferno/asset/texture.h"
namespace Inferno { namespace Inferno {
@ -17,7 +18,7 @@ void fromJson(const ruc::Json& json, SpriteComponent& value)
json.at("color").getTo(value.color); json.at("color").getTo(value.color);
} }
if (json.exists("texture") && json.at("texture").type() == ruc::Json::Type::String) { if (json.exists("texture") && json.at("texture").type() == ruc::Json::Type::String) {
value.texture = TextureManager::the().load(json.at("texture").asString()); value.texture = AssetManager::the().load<Texture2D>(json.at("texture").asString());
} }
} }

2
src/inferno/component/spritecomponent.h

@ -11,7 +11,7 @@
#include "glm/ext/vector_float4.hpp" // glm::vec4 #include "glm/ext/vector_float4.hpp" // glm::vec4
#include "ruc/json/json.h" #include "ruc/json/json.h"
#include "inferno/render/texture.h" #include "inferno/asset/texture.h"
namespace Inferno { namespace Inferno {

11
src/inferno/render/renderer.cpp

@ -10,12 +10,13 @@
#include "glad/glad.h" #include "glad/glad.h"
#include "ruc/format/log.h" #include "ruc/format/log.h"
#include "inferno/asset/asset-manager.h"
#include "inferno/asset/shader.h"
#include "inferno/asset/texture.h"
#include "inferno/component/transformcomponent.h" #include "inferno/component/transformcomponent.h"
#include "inferno/render/buffer.h" #include "inferno/render/buffer.h"
#include "inferno/render/render-command.h" #include "inferno/render/render-command.h"
#include "inferno/render/renderer.h" #include "inferno/render/renderer.h"
#include "inferno/render/shader.h"
#include "inferno/render/texture.h"
namespace Inferno { namespace Inferno {
@ -271,7 +272,7 @@ void Renderer2D::drawQuad(const TransformComponent& transform, glm::mat4 color,
void Renderer2D::loadShader() void Renderer2D::loadShader()
{ {
m_shader = ShaderManager::the().load("assets/glsl/batch-quad"); m_shader = AssetManager::the().load<Shader>("assets/glsl/batch-quad");
} }
// ----------------------------------------- // -----------------------------------------
@ -384,7 +385,7 @@ void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::mat4
void RendererCubemap::loadShader() void RendererCubemap::loadShader()
{ {
m_shader = ShaderManager::the().load("assets/glsl/batch-cubemap"); m_shader = AssetManager::the().load<Shader>("assets/glsl/batch-cubemap");
} }
// ----------------------------------------- // -----------------------------------------
@ -455,7 +456,7 @@ void RendererFont::drawSymbol(std::array<SymbolVertex, vertexPerQuad>& symbolQua
void RendererFont::loadShader() void RendererFont::loadShader()
{ {
m_shader = ShaderManager::the().load("assets/glsl/batch-font"); m_shader = AssetManager::the().load<Shader>("assets/glsl/batch-font");
} }
} // namespace Inferno } // namespace Inferno

77
src/inferno/render/shader.h

@ -1,77 +0,0 @@
/*
* Copyright (C) 2022 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <cstdint> // int32_t, uint32_t
#include <memory> // std::shared_ptr
#include <string> // std::string
#include <unordered_map> // std::unordered_map
#include "glm/glm.hpp"
#include "ruc/singleton.h"
namespace Inferno {
class Shader {
public:
Shader(const std::string& name);
virtual ~Shader();
int32_t findUniform(const std::string& name) const;
void setInt(const std::string& name, int value);
void setInt(const std::string& name, int* values, uint32_t count);
void setFloat(const std::string& name, float value) const;
void setFloat(const std::string& name, float v1, float v2, float v3, float v4) const;
void setFloat(const std::string& name, glm::vec2 value) const;
void setFloat(const std::string& name, glm::vec3 value) const;
void setFloat(const std::string& name, glm::vec4 value) const;
void setFloat(const std::string& name, glm::mat3 matrix) const;
void setFloat(const std::string& name, glm::mat4 matrix) const;
void bind() const;
void unbind() const;
inline std::string name() const { return m_name; }
inline uint32_t id() const { return m_id; }
protected:
uint32_t compileShader(int32_t type, const char* shaderSource) const;
uint32_t linkShader(uint32_t vertex, uint32_t fragment) const;
int32_t checkStatus(uint32_t check, bool isProgram = false) const;
private:
std::string m_name;
uint32_t m_id;
};
// -------------------------------------
class ShaderManager final : public ruc::Singleton<ShaderManager> {
public:
ShaderManager(s);
virtual ~ShaderManager();
void add(const std::string& name, std::shared_ptr<Shader> shader);
std::shared_ptr<Shader> load(const std::string& name);
std::shared_ptr<Shader> load(const std::string& vertexSource,
const std::string& fragmentSource);
std::shared_ptr<Shader> get(const std::string& name);
bool exists(const std::string& name);
void remove(const std::string& name);
void remove(std::shared_ptr<Shader> shader);
protected:
std::string computeName(const std::string& vertexSource,
const std::string& fragmentSource);
private:
std::unordered_map<std::string, std::shared_ptr<Shader>> m_shaderList;
};
} // namespace Inferno

8
src/inferno/system/textareasystem.cpp

@ -4,17 +4,15 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
#include <algorithm> // std::max
#include "ruc/format/log.h" #include "ruc/format/log.h"
#include "ruc/meta/assert.h" #include "ruc/meta/assert.h"
#include "inferno/application.h" #include "inferno/application.h"
#include "inferno/asset/font.h"
#include "inferno/asset/texture.h"
#include "inferno/component/textareacomponent.h" #include "inferno/component/textareacomponent.h"
#include "inferno/component/transformcomponent.h" #include "inferno/component/transformcomponent.h"
#include "inferno/render/font.h"
#include "inferno/render/renderer.h" #include "inferno/render/renderer.h"
#include "inferno/render/texture.h"
#include "inferno/scene/scene.h" #include "inferno/scene/scene.h"
#include "inferno/system/textareasystem.h" #include "inferno/system/textareasystem.h"
#include "inferno/window.h" #include "inferno/window.h"
@ -46,7 +44,7 @@ void TextAreaSystem::render()
// Calculate symbol quad // Calculate symbol quad
// Submit symbol quad for rendering // Submit symbol quad for rendering
std::shared_ptr<Font> font = FontManager::the().load(textarea.font); std::shared_ptr<Font> font = AssetManager::the().load<Font>(textarea.font);
// glm::mat4 translate = transform.translate; // glm::mat4 translate = transform.translate;
m_symbols.clear(); m_symbols.clear();

4
src/inferno/system/textareasystem.h

@ -6,15 +6,13 @@
#pragma once #pragma once
#include <cstdint> // std::uint32_t
#include <memory> // std::shared_ptr #include <memory> // std::shared_ptr
#include <optional> // std::optional #include <optional> // std::optional
#include <vector> // std::vector #include <vector> // std::vector
#include "glm/ext/vector_float3.hpp" // glm::vec3
#include "ruc/singleton.h" #include "ruc/singleton.h"
#include "inferno/render/font.h" #include "inferno/asset/font.h"
#include "inferno/render/renderer.h" #include "inferno/render/renderer.h"
namespace Inferno { namespace Inferno {

63
vendor/glad/LICENSE vendored

@ -0,0 +1,63 @@
The glad source code:
The MIT License (MIT)
Copyright (c) 2013-2022 David Herberth
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
The Khronos Specifications:
Copyright (c) 2013-2020 The Khronos Group Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
The EGL Specification and various headers:
Copyright (c) 2007-2016 The Khronos Group Inc.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and/or associated documentation files (the
"Materials"), to deal in the Materials without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Materials, and to
permit persons to whom the Materials are furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Materials.
THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.

2
vendor/ruc vendored

@ -1 +1 @@
Subproject commit 07c9f9959d3ce46da8bc7b0777d803524f9d1ec0 Subproject commit 85209522358c83dc28df2499b4d70c754121e74d
Loading…
Cancel
Save