Browse Source

Render+Asset: De-duplicate different manager classes into one for assets

master
Riyyi 7 months ago
parent
commit
2793956be4
  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. 44
      src/inferno/asset/font.h
  6. 123
      src/inferno/asset/shader.cpp
  7. 64
      src/inferno/asset/shader.h
  8. 72
      src/inferno/asset/texture.cpp
  9. 66
      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. 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

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

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2022 Riyyi * Copyright (C) 2022-2024 Riyyi
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
@ -10,13 +10,15 @@
#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

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

@ -1,10 +1,9 @@
/* /*
* 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"
@ -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);

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

@ -8,31 +8,24 @@
#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> { // clang-format off
public: template<>
TextureManager(s); inline bool Asset::fastIs<Texture>() const { return isTexture(); }
~TextureManager();
void add(const std::string& path, std::shared_ptr<Texture> texture);
std::shared_ptr<Texture> load(const std::string& path, Texture::Type type = Texture::Type::TwoDimensional);
std::shared_ptr<Texture> get(const std::string& path);
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 {

2
vendor/ruc vendored

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