Reorganise irenderer and resource management
This commit is contained in:
parent
92417c492e
commit
c99a721ff0
|
@ -161,7 +161,7 @@ PenaltyIndentedWhitespace: 0
|
|||
PenaltyReturnTypeOnItsOwnLine: 1000
|
||||
PointerAlignment: Left
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Leave
|
||||
QualifierAlignment: Left
|
||||
ReferenceAlignment: Right
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
|
|
|
@ -109,13 +109,20 @@ FetchContent_MakeAvailable(assimp)
|
|||
|
||||
set(IRIDIUM_SOURCES
|
||||
src/module.cpp
|
||||
src/renderer/i_renderer.cpp
|
||||
src/renderer/r_bgfx.cpp
|
||||
src/renderer/models.cpp
|
||||
|
||||
src/renderer/interface.cpp
|
||||
src/renderer/bgfx.cpp
|
||||
|
||||
src/resource_management/handle_type.cpp
|
||||
src/resource_management/mesh_resource.cpp
|
||||
src/resource_management/shader_resource.cpp
|
||||
|
||||
src/input/key.cpp
|
||||
src/window/i_window.cpp
|
||||
src/window/w_glfw.cpp
|
||||
src/util/u_math.cpp
|
||||
|
||||
src/window/interface.cpp
|
||||
src/window/glfw.cpp
|
||||
|
||||
src/util/math.cpp
|
||||
)
|
||||
|
||||
add_library(iridium)
|
||||
|
@ -125,7 +132,7 @@ target_compile_options(iridium PUBLIC -Wall -Wextra)
|
|||
|
||||
if( ipo_supported )
|
||||
message(STATUS "IPO / LTO enabled")
|
||||
# set_property(TARGET iridium PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
set_property(TARGET iridium PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
else()
|
||||
message(STATUS "IPO / LTO not supported: <${error}>")
|
||||
endif()
|
||||
|
|
|
@ -12,7 +12,7 @@ endif()
|
|||
|
||||
if( ipo_supported )
|
||||
message(STATUS "IPO / LTO enabled")
|
||||
# set_property(TARGET iridium-example PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
set_property(TARGET iridium-example PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
else()
|
||||
message(STATUS "IPO / LTO not supported: <${error}>")
|
||||
endif()
|
||||
|
|
|
@ -47,7 +47,7 @@ std::unique_ptr<T> spawn_renderer(IWindow* window)
|
|||
template <typename T, typename ValueType>
|
||||
concept RangeOf = std::ranges::range<T> && std::same_as<std::ranges::range_value_t<T>, ValueType>;
|
||||
|
||||
auto reload_meshes(IRenderer &renderer, RangeOf<std::shared_ptr<MeshResource>> auto const &meshes)
|
||||
auto reload_meshes(IRenderer &renderer, const RangeOf<std::shared_ptr<MeshResource>> auto &meshes)
|
||||
{
|
||||
for(auto &mesh : meshes)
|
||||
{
|
||||
|
@ -118,7 +118,72 @@ auto load_models(IRenderer &renderer, std::string scene_filename = "assets/model
|
|||
return std::tuple{std::move(meshes), std::move(models)};
|
||||
}
|
||||
|
||||
void key_callback(GLFWWindow* window, std::unique_ptr<IRenderer> &renderer, RangeOf<std::shared_ptr<MeshResource>> auto const &meshes, IRenderer::handle_t &shader, Key key, int /*scancode*/, int action, int /*mods*/)
|
||||
std::vector<char> get_shader(std::string_view file_name, RendererType renderer_type)
|
||||
{
|
||||
using namespace fast_io::io;
|
||||
std::string_view shader_type_name = "???";
|
||||
|
||||
switch(renderer_type)
|
||||
{
|
||||
case RendererType::D3D11:
|
||||
case RendererType::D3D12:
|
||||
shader_type_name = "dx11";
|
||||
break;
|
||||
case RendererType::Gnm:
|
||||
shader_type_name = "pssl";
|
||||
break;
|
||||
case RendererType::Metal:
|
||||
shader_type_name = "metal";
|
||||
break;
|
||||
case RendererType::OpenGL:
|
||||
shader_type_name = "glsl";
|
||||
break;
|
||||
case RendererType::OpenGLES:
|
||||
shader_type_name = "essl";
|
||||
break;
|
||||
case RendererType::Vulkan:
|
||||
shader_type_name = "spirv";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
std::string filePath = std::format("assets/shaders/{}/{}", shader_type_name, file_name);
|
||||
|
||||
println("File path: ", filePath);
|
||||
try
|
||||
{
|
||||
fast_io::ibuf_file file{filePath};
|
||||
std::string fileContentStr;
|
||||
fast_io::ostring_ref ref(&fileContentStr);
|
||||
transmit(ref, file);
|
||||
std::vector<char> fileContent(fileContentStr.data(),
|
||||
fileContentStr.data() + fileContentStr.size() + 1);
|
||||
fileContentStr.clear();
|
||||
|
||||
return fileContent;
|
||||
}
|
||||
catch(const fast_io::error &e)
|
||||
{
|
||||
println("Failed to open file: ", filePath);
|
||||
println("Error: ", e);
|
||||
// TODO
|
||||
throw std::runtime_error("Failed to open file");
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ShaderResource> load_shader_resource(IRenderer &renderer, std::string_view vsh_name, std::string_view fsh_name)
|
||||
{
|
||||
auto renderer_type = renderer.get_renderer_type();
|
||||
auto vsh = get_shader(vsh_name, renderer_type);
|
||||
auto fsh = get_shader(fsh_name, renderer_type);
|
||||
auto cpu_shader = Shader{std::string{vsh_name}, std::string{fsh_name}, renderer_type, std::move(vsh), std::move(fsh)};
|
||||
auto gpu_shader = renderer.load_shader_program(cpu_shader);
|
||||
|
||||
return std::make_shared<ShaderResource>(std::move(cpu_shader), std::move(gpu_shader));
|
||||
}
|
||||
|
||||
void key_callback(GlfwWindow* window, std::unique_ptr<IRenderer> &renderer, const RangeOf<std::shared_ptr<MeshResource>> auto &meshes, std::shared_ptr<ShaderResource> &shader, Key key, int /*scancode*/, int action, int /*mods*/)
|
||||
{
|
||||
if(key == GLFW_KEY_F11 && action == GLFW_PRESS)
|
||||
{
|
||||
|
@ -137,9 +202,9 @@ void key_callback(GLFWWindow* window, std::unique_ptr<IRenderer> &renderer, Rang
|
|||
{
|
||||
// Ensure renderer is destroyed before creating a new one.
|
||||
renderer.reset();
|
||||
renderer = spawn_renderer<BGFXRenderer>(window);
|
||||
renderer = spawn_renderer<BgfxRenderer>(window);
|
||||
reload_meshes(*renderer, meshes);
|
||||
shader = renderer->load_shader("vs_cubes.bin", "fs_cubes.bin");
|
||||
shader = load_shader_resource(*renderer, "vs_cubes.bin", "fs_cubes.bin");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +216,7 @@ static void resize_callback(std::unique_ptr<IRenderer> &renderer, glm::vec2 size
|
|||
}
|
||||
}
|
||||
|
||||
void render_shit(IRenderer &renderer, int64_t timeOffset, MeshResource const &theModelInQuestion, IRenderer::handle_t shader_handle)
|
||||
void render_shit(IRenderer &renderer, int64_t timeOffset, const MeshResource &theModelInQuestion, const ShaderResource &shader)
|
||||
{
|
||||
float time = (float)((bx::getHPCounter() - timeOffset) / double(bx::getHPFrequency()));
|
||||
|
||||
|
@ -164,7 +229,7 @@ void render_shit(IRenderer &renderer, int64_t timeOffset, MeshResource const &th
|
|||
mtx = glm::translate(mtx, glm::vec3{offset + i * distance, 0.0f, 0.0f});
|
||||
mtx = glm::rotate(mtx, time * (i + 1) * 2.0f, glm::vec3{0.0f, -1.0f, 0.0f});
|
||||
mtx = glm::rotate(mtx, time * (2 - i) * 2.0f, glm::vec3{-1.0f, 0.0f, 0.0f});
|
||||
renderer.render_mesh(theModelInQuestion.gpu_mesh, shader_handle, mtx);
|
||||
renderer.render_mesh(theModelInQuestion.gpu_mesh, shader.gpu_shader.program_handle, mtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,7 +243,7 @@ int main()
|
|||
|
||||
{
|
||||
std::unique_ptr<IRenderer> renderer;
|
||||
auto window = std::make_unique<GLFWWindow>(IWindow::WindowConfig{.geometry = {{0, 0}, {800, 600}},
|
||||
auto window = std::make_unique<GlfwWindow>(IWindow::WindowConfig{.geometry = {{0, 0}, {800, 600}},
|
||||
.monitor = -1,
|
||||
.title = "Iridium Example"});
|
||||
|
||||
|
@ -190,13 +255,9 @@ int main()
|
|||
|
||||
// Initialize renderer
|
||||
// TODO: Currently just BGFX
|
||||
renderer = spawn_renderer<BGFXRenderer>(window.get());
|
||||
renderer = spawn_renderer<BgfxRenderer>(window.get());
|
||||
auto [meshes, models] = load_models(*renderer, "assets/models/suzanne.fbx");
|
||||
auto shader = renderer->load_shader("vs_cubes.bin", "fs_cubes.bin");
|
||||
renderer.reset();
|
||||
renderer = spawn_renderer<BGFXRenderer>(window.get());
|
||||
reload_meshes(*renderer, std::views::values(meshes));
|
||||
shader = renderer->load_shader("vs_cubes.bin", "fs_cubes.bin");
|
||||
auto shader = load_shader_resource(*renderer, "vs_cubes.bin", "fs_cubes.bin");
|
||||
|
||||
window->set_key_callback([&window, &renderer, &meshes, &shader](auto &&... args) {
|
||||
key_callback(window.get(), renderer, std::views::values(meshes), shader, std::forward<decltype(args)>(args)...);
|
||||
|
@ -211,7 +272,7 @@ int main()
|
|||
{
|
||||
if(renderer)
|
||||
{
|
||||
render_shit(*renderer, timeOffset, *meshes.at(0), shader);
|
||||
render_shit(*renderer, timeOffset, *meshes.at(0), *shader);
|
||||
renderer->update();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,15 +2,20 @@
|
|||
export module iridium;
|
||||
|
||||
// Renderer
|
||||
export import :i_renderer;
|
||||
export import :r_bgfx;
|
||||
export import :renderer.interface;
|
||||
export import :renderer.bgfx;
|
||||
|
||||
// Resources
|
||||
export import :handle_type;
|
||||
export import :resource.mesh;
|
||||
export import :resource.shader;
|
||||
|
||||
// Windowing
|
||||
export import :i_window;
|
||||
export import :w_glfw;
|
||||
export import :window.interface;
|
||||
export import :window.glfw;
|
||||
|
||||
// Utils
|
||||
export import :u_math;
|
||||
export import :util.math;
|
||||
|
||||
// Input
|
||||
export import :key;
|
||||
|
|
|
@ -16,13 +16,16 @@ module;
|
|||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/predef.h>
|
||||
|
||||
export module iridium:r_bgfx;
|
||||
import :i_renderer;
|
||||
import :i_window;
|
||||
import :w_glfw;
|
||||
export module iridium:renderer.bgfx;
|
||||
import :renderer.interface;
|
||||
import :window.interface;
|
||||
import :handle_type;
|
||||
import :resource.mesh;
|
||||
import :resource.shader;
|
||||
|
||||
import fast_io;
|
||||
import glm;
|
||||
|
@ -42,7 +45,7 @@ export namespace iridium
|
|||
*/
|
||||
|
||||
// Bgfx Renderer
|
||||
class BGFXRenderer : public IRenderer
|
||||
class BgfxRenderer : public IRenderer
|
||||
{
|
||||
public:
|
||||
bool init_renderer(IWindow* iwin) override
|
||||
|
@ -94,6 +97,30 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
RendererType get_renderer_type() override
|
||||
{
|
||||
switch(bgfx::getRendererType())
|
||||
{
|
||||
case bgfx::RendererType::Noop:
|
||||
case bgfx::RendererType::Direct3D11:
|
||||
return RendererType::D3D11;
|
||||
case bgfx::RendererType::Direct3D12:
|
||||
return RendererType::D3D12;
|
||||
case bgfx::RendererType::Gnm:
|
||||
return RendererType::Gnm;
|
||||
case bgfx::RendererType::Metal:
|
||||
return RendererType::Metal;
|
||||
case bgfx::RendererType::OpenGL:
|
||||
return RendererType::OpenGL;
|
||||
case bgfx::RendererType::OpenGLES:
|
||||
return RendererType::OpenGLES;
|
||||
case bgfx::RendererType::Vulkan:
|
||||
return RendererType::Vulkan;
|
||||
default:
|
||||
return RendererType::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
handle_t load_vertex_buffer(const void* vertices, uint32_t size) override
|
||||
{
|
||||
// Define the vertex layout
|
||||
|
@ -105,7 +132,7 @@ public:
|
|||
|
||||
auto vbh = bgfx::createVertexBuffer(
|
||||
// Static data can be passed with bgfx::makeRef, but this is not static.
|
||||
bgfx::copy(vertices, size),
|
||||
bgfx::makeRef(vertices, size),
|
||||
layout);
|
||||
m_vertex_buffers.insert(vbh.idx);
|
||||
return vbh.idx;
|
||||
|
@ -121,7 +148,7 @@ public:
|
|||
{
|
||||
auto ibh = bgfx::createIndexBuffer(
|
||||
// Static data can be passed with bgfx::makeRef
|
||||
bgfx::copy(indices, size));
|
||||
bgfx::makeRef(indices, size));
|
||||
m_index_buffers.insert(ibh.idx);
|
||||
return ibh.idx;
|
||||
}
|
||||
|
@ -132,13 +159,26 @@ public:
|
|||
m_index_buffers.erase(handle);
|
||||
}
|
||||
|
||||
handle_t load_shader(const char* vsh_name, const char* fsh_name) override
|
||||
GpuShader load_shader_program(handle_t vsh, handle_t fsh) override
|
||||
{
|
||||
auto vsh = get_shader(vsh_name);
|
||||
auto fsh = get_shader(fsh_name);
|
||||
auto program = bgfx::createProgram(vsh, fsh, true);
|
||||
m_shader_programs[program.idx] = {vsh.idx, fsh.idx, program.idx};
|
||||
return program.idx;
|
||||
auto program = bgfx::createProgram(static_cast<bgfx::ShaderHandle>(vsh), static_cast<bgfx::ShaderHandle>(fsh), false);
|
||||
m_shader_programs[program.idx] = {vsh, fsh, program.idx};
|
||||
return {vsh, fsh, program.idx};
|
||||
}
|
||||
|
||||
void unload_shader_program(const GpuShader &shader_program) override
|
||||
{
|
||||
bgfx::destroy(static_cast<bgfx::ShaderHandle>(shader_program.vertex_shader_handle));
|
||||
bgfx::destroy(static_cast<bgfx::ShaderHandle>(shader_program.fragment_shader_handle));
|
||||
bgfx::destroy(static_cast<bgfx::ProgramHandle>(shader_program.program_handle));
|
||||
m_shader_programs.erase(shader_program.program_handle);
|
||||
}
|
||||
|
||||
handle_t load_shader(const void* buffer, uint32_t size) override
|
||||
{
|
||||
const bgfx::Memory* mem_sh = bgfx::makeRef(buffer, size);
|
||||
bgfx::ShaderHandle sh = bgfx::createShader(mem_sh);
|
||||
return sh.idx;
|
||||
}
|
||||
|
||||
void unload_shader(handle_t handle) override
|
||||
|
@ -150,7 +190,7 @@ public:
|
|||
m_shader_programs.erase(handle);
|
||||
}
|
||||
|
||||
void render_mesh(GpuMesh const &mesh, handle_t shader_program, glm::mat4 const &transform) override
|
||||
void render_mesh(const GpuMesh &mesh, handle_t shader_program, const glm::mat4 &transform) override
|
||||
{
|
||||
bgfx::setTransform(value_ptr(transform));
|
||||
bgfx::setVertexBuffer(0, static_cast<bgfx::VertexBufferHandle>(mesh.vertices_handle));
|
||||
|
@ -170,7 +210,7 @@ public:
|
|||
bgfx::frame();
|
||||
}
|
||||
|
||||
~BGFXRenderer()
|
||||
~BgfxRenderer()
|
||||
{
|
||||
for(auto &vbh : m_vertex_buffers)
|
||||
{
|
||||
|
@ -204,58 +244,5 @@ private:
|
|||
bgfx::setViewRect(0, 0, 0, width, height);
|
||||
bgfx::frame();
|
||||
}
|
||||
|
||||
bgfx::ShaderHandle get_shader(std::string_view fileName)
|
||||
{
|
||||
using namespace fast_io::io;
|
||||
std::string_view shaderTypeName = "???";
|
||||
|
||||
switch(bgfx::getRendererType())
|
||||
{
|
||||
case bgfx::RendererType::Noop:
|
||||
case bgfx::RendererType::Direct3D11:
|
||||
case bgfx::RendererType::Direct3D12:
|
||||
shaderTypeName = "dx11";
|
||||
break;
|
||||
case bgfx::RendererType::Gnm:
|
||||
shaderTypeName = "pssl";
|
||||
break;
|
||||
case bgfx::RendererType::Metal:
|
||||
shaderTypeName = "metal";
|
||||
break;
|
||||
case bgfx::RendererType::OpenGL:
|
||||
shaderTypeName = "glsl";
|
||||
break;
|
||||
case bgfx::RendererType::OpenGLES:
|
||||
shaderTypeName = "essl";
|
||||
break;
|
||||
case bgfx::RendererType::Vulkan:
|
||||
shaderTypeName = "spirv";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
std::string filePath = std::format("assets/shaders/{}/{}", shaderTypeName, fileName);
|
||||
|
||||
println("File path: ", filePath);
|
||||
try
|
||||
{
|
||||
fast_io::native_file_loader file{filePath};
|
||||
|
||||
const bgfx::Memory* mem = bgfx::alloc(file.size() + 1);
|
||||
// fread(mem->data, 1, fileSize, file);
|
||||
std::ranges::copy(file, mem->data);
|
||||
mem->data[mem->size - 1] = '\0';
|
||||
|
||||
return bgfx::createShader(mem);
|
||||
}
|
||||
catch(const fast_io::error &e)
|
||||
{
|
||||
println("Failed to open file: ", filePath);
|
||||
println("Error: ", e);
|
||||
return BGFX_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace iridium
|
|
@ -1,138 +0,0 @@
|
|||
module;
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <ranges>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
#include <assimp/mesh.h>
|
||||
export module iridium:i_renderer;
|
||||
import :i_window;
|
||||
|
||||
import glm;
|
||||
|
||||
namespace
|
||||
{
|
||||
using handle_t = std::uint32_t;
|
||||
};
|
||||
|
||||
export namespace iridium
|
||||
{
|
||||
struct PosColorVertex
|
||||
{
|
||||
float x, y, z;
|
||||
uint32_t abgr;
|
||||
};
|
||||
struct Mesh
|
||||
{
|
||||
std::vector<PosColorVertex> vertices;
|
||||
std::vector<std::uint16_t> indices;
|
||||
|
||||
// Construct from an assimp mesh
|
||||
static Mesh from_assimp(aiMesh const &assimp_mesh)
|
||||
{
|
||||
Mesh mesh;
|
||||
auto fill_vertex_buffer = [&vertex_buffer = mesh.vertices, &assimp_mesh](auto &&colors) {
|
||||
// need to use an iterator because for some reason std::views::zip doesn't work
|
||||
auto it_colors = std::begin(colors);
|
||||
auto it_vertices = assimp_mesh.mVertices;
|
||||
for(; it_colors != std::end(colors) && it_vertices != assimp_mesh.mVertices + assimp_mesh.mNumVertices; ++it_colors, ++it_vertices)
|
||||
{
|
||||
auto const &vertex = *it_vertices;
|
||||
auto const &color = *it_colors;
|
||||
auto abgr = static_cast<std::uint32_t>(color.a * 255) << 24 | static_cast<std::uint32_t>(color.b * 255) << 16 | static_cast<std::uint32_t>(color.g * 255) << 8 | static_cast<std::uint32_t>(color.r * 255);
|
||||
vertex_buffer.emplace_back(vertex.x, vertex.y, vertex.z, abgr);
|
||||
}
|
||||
};
|
||||
|
||||
if(assimp_mesh.mColors[0])
|
||||
{
|
||||
fill_vertex_buffer(std::span{assimp_mesh.mColors[0], assimp_mesh.mNumVertices});
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_vertex_buffer(std::views::repeat(aiColor4D{1.0, 1.0, 1.0, 1.0}));
|
||||
}
|
||||
aiFace* faces;
|
||||
for(auto const index : std::span{assimp_mesh.mFaces, assimp_mesh.mNumFaces} | std::views::transform([](aiFace const &x) { return std::span{x.mIndices, x.mNumIndices}; }) | std::views::join)
|
||||
{
|
||||
mesh.indices.push_back(index);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
};
|
||||
struct GpuMesh
|
||||
{
|
||||
handle_t vertices_handle{};
|
||||
handle_t indices_handle{};
|
||||
GpuMesh(handle_t vertices_handle, handle_t indices_handle)
|
||||
: vertices_handle(vertices_handle), indices_handle(indices_handle)
|
||||
{
|
||||
}
|
||||
GpuMesh(GpuMesh const &) = delete;
|
||||
GpuMesh(GpuMesh &&) = default;
|
||||
GpuMesh &operator=(GpuMesh const &) = delete;
|
||||
GpuMesh &operator=(GpuMesh &&) = default;
|
||||
};
|
||||
struct MeshResource
|
||||
{
|
||||
Mesh cpu_mesh;
|
||||
GpuMesh gpu_mesh = {0, 0};
|
||||
};
|
||||
struct GpuShader
|
||||
{
|
||||
handle_t vertex_shader_handle;
|
||||
handle_t fragment_shader_handle;
|
||||
handle_t program_handle;
|
||||
};
|
||||
struct shaderResource
|
||||
{
|
||||
std::string vertex_shader;
|
||||
std::string fragment_shader;
|
||||
GpuShader gpu_shader;
|
||||
};
|
||||
class IRenderer
|
||||
{
|
||||
public:
|
||||
using handle_t = ::handle_t;
|
||||
virtual bool init_renderer(IWindow* window) = 0;
|
||||
GpuMesh load_mesh(Mesh const &mesh);
|
||||
// Shortcut for loading from assimp, calls load_mesh(Mesh const &)
|
||||
GpuMesh load_mesh(aiMesh const &mesh);
|
||||
void unload_mesh(GpuMesh const &mesh)
|
||||
{
|
||||
unload_vertex_buffer(mesh.vertices_handle);
|
||||
unload_index_buffer(mesh.indices_handle);
|
||||
}
|
||||
void unload_mesh(MeshResource const &mesh)
|
||||
{
|
||||
unload_mesh(mesh.gpu_mesh);
|
||||
}
|
||||
virtual handle_t load_vertex_buffer(const void* vertices, uint32_t size) = 0;
|
||||
virtual void unload_vertex_buffer(handle_t handle) = 0;
|
||||
virtual handle_t load_index_buffer(const void* indices, uint32_t size) = 0;
|
||||
virtual void unload_index_buffer(handle_t handle) = 0;
|
||||
virtual handle_t load_shader(const char* vsh, const char* fsh) = 0;
|
||||
virtual void unload_shader(handle_t handle) = 0;
|
||||
virtual void resize_frame_buffer(int width, int height) = 0;
|
||||
virtual void render_mesh(GpuMesh const &mesh, handle_t ShaderProgram, glm::mat4 const &transform) = 0;
|
||||
virtual void update() = 0;
|
||||
virtual ~IRenderer() = default;
|
||||
};
|
||||
|
||||
} // namespace iridium
|
||||
|
||||
// FIXME: module :private
|
||||
namespace iridium
|
||||
{
|
||||
GpuMesh IRenderer::load_mesh(aiMesh const &mesh)
|
||||
{
|
||||
return load_mesh(Mesh::from_assimp(mesh));
|
||||
}
|
||||
GpuMesh IRenderer::load_mesh(Mesh const &mesh)
|
||||
{
|
||||
return GpuMesh{
|
||||
load_vertex_buffer(mesh.vertices.data(), mesh.vertices.size() * sizeof(PosColorVertex)),
|
||||
load_index_buffer(mesh.indices.data(), mesh.indices.size() * sizeof(std::uint16_t))};
|
||||
}
|
||||
} // namespace iridium
|
|
@ -0,0 +1,76 @@
|
|||
module;
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <assimp/mesh.h>
|
||||
export module iridium:renderer.interface;
|
||||
import :handle_type;
|
||||
import :resource.mesh;
|
||||
import :resource.shader;
|
||||
import :window.interface;
|
||||
|
||||
import glm;
|
||||
|
||||
export namespace iridium
|
||||
{
|
||||
class IRenderer
|
||||
{
|
||||
public:
|
||||
virtual bool init_renderer(IWindow* window) = 0;
|
||||
virtual RendererType get_renderer_type() = 0;
|
||||
|
||||
GpuMesh load_mesh(const Mesh &mesh);
|
||||
// Shortcut for loading from assimp, calls load_mesh(Mesh const &)
|
||||
GpuMesh load_mesh(const aiMesh &mesh);
|
||||
void unload_mesh(const GpuMesh &mesh)
|
||||
{
|
||||
unload_vertex_buffer(mesh.vertices_handle);
|
||||
unload_index_buffer(mesh.indices_handle);
|
||||
}
|
||||
void unload_mesh(const MeshResource &mesh)
|
||||
{
|
||||
unload_mesh(mesh.gpu_mesh);
|
||||
}
|
||||
|
||||
GpuShader load_shader_program(const Shader &shader)
|
||||
{
|
||||
handle_t vsh = load_shader(shader.vertex_shader.data(), shader.vertex_shader.size());
|
||||
handle_t fsh = load_shader(shader.fragment_shader.data(), shader.fragment_shader.size());
|
||||
|
||||
return load_shader_program(vsh, fsh);
|
||||
}
|
||||
virtual GpuShader load_shader_program(handle_t vsh, handle_t fsh) = 0;
|
||||
virtual void unload_shader_program(const GpuShader &shader_program) = 0;
|
||||
|
||||
virtual handle_t load_vertex_buffer(const void* vertices, uint32_t size) = 0;
|
||||
virtual void unload_vertex_buffer(handle_t handle) = 0;
|
||||
|
||||
virtual handle_t load_index_buffer(const void* indices, uint32_t size) = 0;
|
||||
virtual void unload_index_buffer(handle_t handle) = 0;
|
||||
|
||||
virtual handle_t load_shader(const void* sh, uint32_t size) = 0;
|
||||
virtual void unload_shader(handle_t handle) = 0;
|
||||
|
||||
virtual void resize_frame_buffer(int width, int height) = 0;
|
||||
virtual void render_mesh(const GpuMesh &mesh, handle_t ShaderProgram, const glm::mat4 &transform) = 0;
|
||||
virtual void update() = 0;
|
||||
virtual ~IRenderer() = default;
|
||||
};
|
||||
|
||||
} // namespace iridium
|
||||
|
||||
// FIXME: Not required to be part of the module interface.
|
||||
namespace iridium
|
||||
{
|
||||
GpuMesh IRenderer::load_mesh(const aiMesh &mesh)
|
||||
{
|
||||
return load_mesh(Mesh::from_assimp(mesh));
|
||||
}
|
||||
GpuMesh IRenderer::load_mesh(const Mesh &mesh)
|
||||
{
|
||||
return GpuMesh{
|
||||
load_vertex_buffer(mesh.vertices.data(), mesh.vertices.size() * sizeof(PosColorVertex)),
|
||||
load_index_buffer(mesh.indices.data(), mesh.indices.size() * sizeof(std::uint16_t))};
|
||||
}
|
||||
} // namespace iridium
|
|
@ -1,2 +0,0 @@
|
|||
module;
|
||||
export module iridium:models;
|
|
@ -0,0 +1,8 @@
|
|||
module;
|
||||
#include <cstdint>
|
||||
export module iridium:handle_type;
|
||||
|
||||
export namespace iridium
|
||||
{
|
||||
using handle_t = std::uint32_t;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
module;
|
||||
#include <cstdint>
|
||||
#include <ranges>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
#include <assimp/mesh.h>
|
||||
export module iridium:resource.mesh;
|
||||
import :handle_type;
|
||||
|
||||
export namespace iridium
|
||||
{
|
||||
struct PosColorVertex
|
||||
{
|
||||
float x, y, z;
|
||||
std::uint32_t abgr;
|
||||
};
|
||||
|
||||
struct Mesh
|
||||
{
|
||||
std::vector<PosColorVertex> vertices;
|
||||
std::vector<std::uint16_t> indices;
|
||||
|
||||
// Construct from an assimp mesh
|
||||
static Mesh from_assimp(const aiMesh &assimp_mesh)
|
||||
{
|
||||
Mesh mesh;
|
||||
auto fill_vertex_buffer = [&vertex_buffer = mesh.vertices, &assimp_mesh](auto &&colors) {
|
||||
// need to use an iterator because for some reason std::views::zip doesn't work
|
||||
auto it_colors = std::begin(colors);
|
||||
auto it_vertices = assimp_mesh.mVertices;
|
||||
for(; it_colors != std::end(colors) && it_vertices != assimp_mesh.mVertices + assimp_mesh.mNumVertices; ++it_colors, ++it_vertices)
|
||||
{
|
||||
const auto &vertex = *it_vertices;
|
||||
const auto &color = *it_colors;
|
||||
auto abgr = static_cast<std::uint32_t>(color.a * 255) << 24 | static_cast<std::uint32_t>(color.b * 255) << 16 | static_cast<std::uint32_t>(color.g * 255) << 8 | static_cast<std::uint32_t>(color.r * 255);
|
||||
vertex_buffer.emplace_back(vertex.x, vertex.y, vertex.z, abgr);
|
||||
}
|
||||
};
|
||||
|
||||
if(assimp_mesh.mColors[0])
|
||||
{
|
||||
fill_vertex_buffer(std::span{assimp_mesh.mColors[0], assimp_mesh.mNumVertices});
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_vertex_buffer(std::views::repeat(aiColor4D{1.0, 1.0, 1.0, 1.0}));
|
||||
}
|
||||
aiFace* faces;
|
||||
for(const auto index : std::span{assimp_mesh.mFaces, assimp_mesh.mNumFaces} | std::views::transform([](const aiFace &x) { return std::span{x.mIndices, x.mNumIndices}; }) | std::views::join)
|
||||
{
|
||||
mesh.indices.push_back(index);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
};
|
||||
struct GpuMesh
|
||||
{
|
||||
handle_t vertices_handle{};
|
||||
handle_t indices_handle{};
|
||||
GpuMesh(handle_t vertices_handle, handle_t indices_handle)
|
||||
: vertices_handle(vertices_handle), indices_handle(indices_handle)
|
||||
{
|
||||
}
|
||||
GpuMesh(const GpuMesh &) = delete;
|
||||
GpuMesh(GpuMesh &&) = default;
|
||||
GpuMesh &operator=(const GpuMesh &) = delete;
|
||||
GpuMesh &operator=(GpuMesh &&) = default;
|
||||
};
|
||||
struct MeshResource
|
||||
{
|
||||
Mesh cpu_mesh;
|
||||
GpuMesh gpu_mesh = {0, 0};
|
||||
};
|
||||
} // namespace iridium
|
|
@ -0,0 +1,45 @@
|
|||
module;
|
||||
#include <string>
|
||||
#include <vector>
|
||||
export module iridium:resource.shader;
|
||||
import :handle_type;
|
||||
|
||||
export namespace iridium
|
||||
{
|
||||
enum class RendererType
|
||||
{
|
||||
D3D11,
|
||||
D3D12,
|
||||
Gnm,
|
||||
Metal,
|
||||
OpenGL,
|
||||
OpenGLES,
|
||||
Vulkan,
|
||||
Unknown
|
||||
};
|
||||
|
||||
struct Shader
|
||||
{
|
||||
std::string vertex_name;
|
||||
std::string fragment_name;
|
||||
|
||||
// Renderer Specific
|
||||
RendererType renderer_type;
|
||||
// DO NOT MAKE THESE STRINGS, OR ELSE MOVE CONSTRUCTION MAY INVALIDATE ITERATORS.
|
||||
std::vector<char> vertex_shader;
|
||||
std::vector<char> fragment_shader;
|
||||
};
|
||||
|
||||
struct GpuShader
|
||||
{
|
||||
handle_t vertex_shader_handle;
|
||||
handle_t fragment_shader_handle;
|
||||
handle_t program_handle;
|
||||
};
|
||||
|
||||
struct ShaderResource
|
||||
{
|
||||
Shader cpu_shader;
|
||||
GpuShader gpu_shader;
|
||||
};
|
||||
} // namespace iridium
|
|
@ -1,4 +1,4 @@
|
|||
export module iridium:u_math;
|
||||
export module iridium:util.math;
|
||||
import glm;
|
||||
|
||||
export namespace iridium::math
|
|
@ -1,10 +1,10 @@
|
|||
module;
|
||||
#include "native_windowing.h"
|
||||
#include <stdexcept>
|
||||
export module iridium:w_glfw;
|
||||
export module iridium:window.glfw;
|
||||
|
||||
import :i_window;
|
||||
import :u_math;
|
||||
import :window.interface;
|
||||
import :util.math;
|
||||
import :key;
|
||||
|
||||
import glm;
|
||||
|
@ -12,7 +12,7 @@ import glfw;
|
|||
|
||||
export namespace iridium
|
||||
{
|
||||
class GLFWWindow : public IWindow
|
||||
class GlfwWindow : public IWindow
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
@ -20,7 +20,7 @@ public:
|
|||
* @details Creates a
|
||||
* @param config
|
||||
*/
|
||||
GLFWWindow(WindowConfig config = WindowConfig())
|
||||
GlfwWindow(WindowConfig config = WindowConfig())
|
||||
: m_window{glfwCreateWindow(config.geometry.width(), config.geometry.height(), config.title.data(), get_monitor(config.monitor), nullptr)}
|
||||
{
|
||||
if(m_window == nullptr)
|
||||
|
@ -30,12 +30,12 @@ public:
|
|||
glfwSetWindowUserPointer(m_window, this);
|
||||
|
||||
glfwSetWindowSizeCallback(m_window, [](GLFWwindow* window, int width, int height) {
|
||||
auto win = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window));
|
||||
auto win = static_cast<GlfwWindow*>(glfwGetWindowUserPointer(window));
|
||||
win->m_resize_callback(glm::ivec2(width, height));
|
||||
});
|
||||
|
||||
glfwSetKeyCallback(m_window, [](GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
auto win = static_cast<GLFWWindow*>(glfwGetWindowUserPointer(window));
|
||||
auto win = static_cast<GlfwWindow*>(glfwGetWindowUserPointer(window));
|
||||
win->m_key_callback(static_cast<Key>(key), scancode, action, mods);
|
||||
});
|
||||
|
||||
|
@ -129,7 +129,7 @@ public:
|
|||
glfwPollEvents();
|
||||
}
|
||||
|
||||
~GLFWWindow()
|
||||
~GlfwWindow()
|
||||
{
|
||||
glfwDestroyWindow(m_window);
|
||||
}
|
|
@ -4,9 +4,9 @@ module;
|
|||
#include <string>
|
||||
|
||||
#include <boost/predef.h>
|
||||
export module iridium:i_window;
|
||||
export module iridium:window.interface;
|
||||
|
||||
import :u_math;
|
||||
import :util.math;
|
||||
import :key;
|
||||
|
||||
import glm;
|
Loading…
Reference in New Issue