Compare commits
6
Commits
2793956be4
...
c06b06ed62
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c06b06ed62 | ||
|
|
5721b4249c | ||
|
|
95a64be4cd | ||
|
|
79b4f1c3d1 | ||
|
|
a266a27f88 | ||
|
|
08969e32d1 |
@@ -19,3 +19,6 @@
|
|||||||
[submodule "inferno/vendor/ruc"]
|
[submodule "inferno/vendor/ruc"]
|
||||||
path = vendor/ruc
|
path = vendor/ruc
|
||||||
url = https://github.com/Riyyi/ruc
|
url = https://github.com/Riyyi/ruc
|
||||||
|
[submodule "inferno/vendor/assimp"]
|
||||||
|
path = vendor/assimp
|
||||||
|
url = https://github.com/assimp/assimp
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ $ cmake .. && make
|
|||||||
|
|
||||||
* Libraries
|
* Libraries
|
||||||
|
|
||||||
|
- [[https://github.com/assimp/assimp][assimp]]
|
||||||
# - [[https://github.com/bulletphysics/bullet3][Bullet]]
|
# - [[https://github.com/bulletphysics/bullet3][Bullet]]
|
||||||
- [[https://github.com/skypjack/entt][EnTT]]
|
- [[https://github.com/skypjack/entt][EnTT]]
|
||||||
- [[https://github.com/Dav1dde/glad][glad]]
|
- [[https://github.com/Dav1dde/glad][glad]]
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 color;
|
||||||
|
|
||||||
|
in vec3 v_normal;
|
||||||
|
in vec2 v_textureCoordinates;
|
||||||
|
in flat float v_textureIndex;
|
||||||
|
|
||||||
|
uniform sampler2D u_textures[32];
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 textureColor = vec4(1.0f);
|
||||||
|
switch(int(v_textureIndex)) {
|
||||||
|
case 0: break; // Texture unit 0 is reserved for no texture
|
||||||
|
case 1: textureColor *= texture(u_textures[1], v_textureCoordinates); break;
|
||||||
|
case 2: textureColor *= texture(u_textures[2], v_textureCoordinates); break;
|
||||||
|
case 3: textureColor *= texture(u_textures[3], v_textureCoordinates); break;
|
||||||
|
case 4: textureColor *= texture(u_textures[4], v_textureCoordinates); break;
|
||||||
|
case 5: textureColor *= texture(u_textures[5], v_textureCoordinates); break;
|
||||||
|
case 6: textureColor *= texture(u_textures[6], v_textureCoordinates); break;
|
||||||
|
case 7: textureColor *= texture(u_textures[7], v_textureCoordinates); break;
|
||||||
|
case 8: textureColor *= texture(u_textures[8], v_textureCoordinates); break;
|
||||||
|
case 9: textureColor *= texture(u_textures[9], v_textureCoordinates); break;
|
||||||
|
case 10: textureColor *= texture(u_textures[10], v_textureCoordinates); break;
|
||||||
|
case 11: textureColor *= texture(u_textures[11], v_textureCoordinates); break;
|
||||||
|
case 12: textureColor *= texture(u_textures[12], v_textureCoordinates); break;
|
||||||
|
case 13: textureColor *= texture(u_textures[13], v_textureCoordinates); break;
|
||||||
|
case 14: textureColor *= texture(u_textures[14], v_textureCoordinates); break;
|
||||||
|
case 15: textureColor *= texture(u_textures[15], v_textureCoordinates); break;
|
||||||
|
case 16: textureColor *= texture(u_textures[16], v_textureCoordinates); break;
|
||||||
|
case 17: textureColor *= texture(u_textures[17], v_textureCoordinates); break;
|
||||||
|
case 18: textureColor *= texture(u_textures[18], v_textureCoordinates); break;
|
||||||
|
case 19: textureColor *= texture(u_textures[19], v_textureCoordinates); break;
|
||||||
|
case 20: textureColor *= texture(u_textures[20], v_textureCoordinates); break;
|
||||||
|
case 21: textureColor *= texture(u_textures[21], v_textureCoordinates); break;
|
||||||
|
case 22: textureColor *= texture(u_textures[22], v_textureCoordinates); break;
|
||||||
|
case 23: textureColor *= texture(u_textures[23], v_textureCoordinates); break;
|
||||||
|
case 24: textureColor *= texture(u_textures[24], v_textureCoordinates); break;
|
||||||
|
case 25: textureColor *= texture(u_textures[25], v_textureCoordinates); break;
|
||||||
|
case 26: textureColor *= texture(u_textures[26], v_textureCoordinates); break;
|
||||||
|
case 27: textureColor *= texture(u_textures[27], v_textureCoordinates); break;
|
||||||
|
case 28: textureColor *= texture(u_textures[28], v_textureCoordinates); break;
|
||||||
|
case 29: textureColor *= texture(u_textures[29], v_textureCoordinates); break;
|
||||||
|
case 30: textureColor *= texture(u_textures[30], v_textureCoordinates); break;
|
||||||
|
case 31: textureColor *= texture(u_textures[31], v_textureCoordinates); break;
|
||||||
|
}
|
||||||
|
color = textureColor;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 a_position;
|
||||||
|
layout(location = 1) in vec3 a_normal;
|
||||||
|
layout(location = 2) in vec2 a_textureCoordinates;
|
||||||
|
layout(location = 3) in float a_textureIndex;
|
||||||
|
|
||||||
|
out vec3 v_normal;
|
||||||
|
out vec2 v_textureCoordinates;
|
||||||
|
out flat float v_textureIndex;
|
||||||
|
|
||||||
|
uniform mat4 u_projectionView;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
v_normal = a_normal;
|
||||||
|
v_textureCoordinates = a_textureCoordinates;
|
||||||
|
v_textureIndex = a_textureIndex;
|
||||||
|
// Vclip = Camera projection * Camera view * Model transform * Vlocal
|
||||||
|
gl_Position = u_projectionView * vec4(a_position, 1.0f);
|
||||||
|
}
|
||||||
@@ -33,7 +33,4 @@ void main()
|
|||||||
v_borderColor = a_borderColor;
|
v_borderColor = a_borderColor;
|
||||||
v_offset = a_offset;
|
v_offset = a_offset;
|
||||||
gl_Position = vec4(a_position, 1.0f);
|
gl_Position = vec4(a_position, 1.0f);
|
||||||
|
|
||||||
// Vclip = Camera projection * Camera view * Model transform * Vlocal
|
|
||||||
// gl_Position = u_projectionView * vec4(a_position, 1.0f);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ Application::~Application()
|
|||||||
|
|
||||||
RendererFont::destroy();
|
RendererFont::destroy();
|
||||||
Renderer2D::destroy();
|
Renderer2D::destroy();
|
||||||
|
Renderer3D::destroy();
|
||||||
RendererCubemap::destroy();
|
RendererCubemap::destroy();
|
||||||
RenderCommand::destroy();
|
RenderCommand::destroy();
|
||||||
AssetManager::destroy();
|
AssetManager::destroy();
|
||||||
@@ -168,6 +169,7 @@ int Application::run()
|
|||||||
|
|
||||||
std::pair<glm::mat4, glm::mat4> projectionView = m_scene->cameraProjectionView();
|
std::pair<glm::mat4, glm::mat4> projectionView = m_scene->cameraProjectionView();
|
||||||
RendererCubemap::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
RendererCubemap::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||||
|
Renderer3D::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||||
Renderer2D::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
Renderer2D::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||||
RendererFont::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
RendererFont::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||||
|
|
||||||
@@ -175,6 +177,7 @@ int Application::run()
|
|||||||
// RendererCharacter::the().drawCharacter(character, f->texture());
|
// RendererCharacter::the().drawCharacter(character, f->texture());
|
||||||
|
|
||||||
RendererCubemap::the().endScene();
|
RendererCubemap::the().endScene();
|
||||||
|
Renderer3D::the().endScene();
|
||||||
Renderer2D::the().endScene();
|
Renderer2D::the().endScene();
|
||||||
RendererFont::the().endScene();
|
RendererFont::the().endScene();
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public:
|
|||||||
bool fastIs() const = delete;
|
bool fastIs() const = delete;
|
||||||
|
|
||||||
virtual bool isFont() const { return false; }
|
virtual bool isFont() const { return false; }
|
||||||
|
virtual bool isModel() const { return false; }
|
||||||
virtual bool isShader() const { return false; }
|
virtual bool isShader() const { return false; }
|
||||||
virtual bool isTexture() const { return false; }
|
virtual bool isTexture() const { return false; }
|
||||||
virtual bool isTexture2D() const { return false; }
|
virtual bool isTexture2D() const { return false; }
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint> // uint32_t
|
||||||
|
#include <memory> // std::shared_ptr
|
||||||
|
|
||||||
|
#include "assimp/Importer.hpp"
|
||||||
|
#include "assimp/postprocess.h"
|
||||||
|
#include "assimp/scene.h"
|
||||||
|
#include "assimp/texture.h"
|
||||||
|
#include "ruc/format/log.h"
|
||||||
|
|
||||||
|
#include "inferno/asset/model.h"
|
||||||
|
#include "inferno/asset/texture.h"
|
||||||
|
|
||||||
|
namespace Inferno {
|
||||||
|
|
||||||
|
std::shared_ptr<Model> Model::create(std::string_view path)
|
||||||
|
{
|
||||||
|
auto result = std::shared_ptr<Model>(new Model(path));
|
||||||
|
|
||||||
|
Assimp::Importer importer; // importer destructor uses RAII cleanup
|
||||||
|
const aiScene* scene = importer.ReadFile(
|
||||||
|
path.data(),
|
||||||
|
aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType);
|
||||||
|
|
||||||
|
VERIFY(scene != nullptr && (scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) == 0 && scene->mRootNode != nullptr,
|
||||||
|
"assimp loading file failed: {}", importer.GetErrorString());
|
||||||
|
|
||||||
|
processScene(result, scene);
|
||||||
|
processNode(result, scene->mRootNode, scene);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::processScene(std::shared_ptr<Model> model, const aiScene* scene)
|
||||||
|
{
|
||||||
|
VERIFY(scene->HasMeshes(), "malformed model");
|
||||||
|
VERIFY(scene->mNumTextures < 2, "unsupported model type");
|
||||||
|
|
||||||
|
if (scene->mNumTextures == 1) {
|
||||||
|
aiTexture* texture = scene->mTextures[0];
|
||||||
|
model->m_texture = Texture2D::create(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::processNode(std::shared_ptr<Model> model, aiNode* node, const aiScene* scene)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < node->mNumMeshes; ++i) {
|
||||||
|
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||||
|
processMesh(model, mesh, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < node->mNumChildren; ++i) {
|
||||||
|
processNode(model, node->mChildren[i], scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::processMesh(std::shared_ptr<Model> model, aiMesh* mesh, const aiScene* scene)
|
||||||
|
{
|
||||||
|
VERIFY(mesh->HasPositions(), "malformed model");
|
||||||
|
VERIFY(mesh->HasNormals(), "malformed model");
|
||||||
|
|
||||||
|
// Pre-allocate memory
|
||||||
|
model->m_vertices = std::vector<Vertex>(mesh->mNumVertices);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < mesh->mNumVertices; ++i) {
|
||||||
|
aiVector3D v = mesh->mVertices[i];
|
||||||
|
model->m_vertices[i].position = { v.x, v.y, v.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size of vertices == size of normals
|
||||||
|
for (uint32_t i = 0; i < mesh->mNumVertices; ++i) {
|
||||||
|
aiVector3D normal = mesh->mNormals[i];
|
||||||
|
model->m_vertices[i].normal = { normal.x, normal.y, normal.x };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh->HasTextureCoords(0)) {
|
||||||
|
// Size of vertices == size of texture coordinates
|
||||||
|
for (uint32_t i = 0; i < mesh->mNumVertices; ++i) {
|
||||||
|
aiVector3D tc = mesh->mTextureCoords[0][i];
|
||||||
|
model->m_vertices[i].textureCoordinates = { tc.x, tc.y };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: position in the texture atlas
|
||||||
|
|
||||||
|
if (mesh->HasFaces()) {
|
||||||
|
for (uint32_t i = 0; i < mesh->mNumFaces; ++i) {
|
||||||
|
aiFace face = mesh->mFaces[i];
|
||||||
|
for (uint32_t j = 0; j < face.mNumIndices; ++j) {
|
||||||
|
model->m_elements.push_back(face.mIndices[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ruc::debug("mesh: {:p}", mesh->mTextureCoordsNames);
|
||||||
|
// for (size_t i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||||||
|
// ruc::debug("mesh: {}", mesh->mTextureCoordsNames[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
ruc::debug("has texture: {}", scene->HasTextures());
|
||||||
|
|
||||||
|
ruc::error("asset::model vert {}", model->m_vertices.size());
|
||||||
|
ruc::error("asset::model elem {}", model->m_elements.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Inferno
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint> // uint32_t
|
||||||
|
#include <memory>
|
||||||
|
#include <span>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "assimp/scene.h"
|
||||||
|
|
||||||
|
#include "inferno/asset/asset-manager.h"
|
||||||
|
#include "inferno/render/renderer.h"
|
||||||
|
|
||||||
|
namespace Inferno {
|
||||||
|
|
||||||
|
class Texture2D;
|
||||||
|
|
||||||
|
class Model final : public Asset {
|
||||||
|
public:
|
||||||
|
virtual ~Model() {}
|
||||||
|
|
||||||
|
// Factory function
|
||||||
|
static std::shared_ptr<Model> create(std::string_view path);
|
||||||
|
|
||||||
|
std::span<const Vertex> vertices() const { return m_vertices; }
|
||||||
|
std::span<const uint32_t> elements() const { return m_elements; }
|
||||||
|
std::shared_ptr<Texture2D> texture() const { return m_texture; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Model(std::string_view path)
|
||||||
|
: Asset(path)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void processScene(std::shared_ptr<Model> model, const aiScene* scene);
|
||||||
|
static void processNode(std::shared_ptr<Model> model, aiNode* node, const aiScene* scene);
|
||||||
|
static void processMesh(std::shared_ptr<Model> model, aiMesh* mesh, const aiScene* scene);
|
||||||
|
|
||||||
|
virtual bool isModel() const override { return true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Vertex> m_vertices;
|
||||||
|
std::vector<uint32_t> m_elements;
|
||||||
|
// Some file formats embed their texture
|
||||||
|
std::shared_ptr<Texture2D> m_texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Inferno
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <cstdint> // uint8_t, uint32_t
|
#include <cstdint> // uint8_t, uint32_t
|
||||||
#include <memory> // std::shared_ptr
|
#include <memory> // std::shared_ptr
|
||||||
|
|
||||||
|
#include "assimp/texture.h"
|
||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
#include "ruc/meta/assert.h"
|
#include "ruc/meta/assert.h"
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
@@ -56,6 +57,32 @@ std::shared_ptr<Texture2D> Texture2D::create(std::string_view path)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Texture2D> Texture2D::create(aiTexture* texture)
|
||||||
|
{
|
||||||
|
auto result = std::shared_ptr<Texture2D>(new Texture2D(texture->mFilename.C_Str()));
|
||||||
|
|
||||||
|
int width = static_cast<int>(texture->mWidth);
|
||||||
|
int height = static_cast<int>(texture->mHeight);
|
||||||
|
int channels = 0;
|
||||||
|
unsigned char* data = reinterpret_cast<unsigned char*>(texture->pcData);
|
||||||
|
bool isCompressed = height == 0; // height 0 is compression, byte length stored in width variable
|
||||||
|
|
||||||
|
if (isCompressed) {
|
||||||
|
stbi_set_flip_vertically_on_load(0);
|
||||||
|
data = stbi_load_from_memory(data, width, &width, &height, &channels, STBI_default);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
channels = 4; // ARGB888
|
||||||
|
// TODO: imprement format hints? `archFormatHint'
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
result->init(width, height, channels);
|
||||||
|
result->create(data);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void Texture2D::bind(uint32_t unit) const
|
void Texture2D::bind(uint32_t unit) const
|
||||||
{
|
{
|
||||||
// Set active unit
|
// Set active unit
|
||||||
@@ -198,6 +225,3 @@ void TextureCubemap::create()
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Inferno
|
} // namespace Inferno
|
||||||
|
|
||||||
// FIXME
|
|
||||||
// auto texture = (type == Texture::TwoDimensional) ? Texture2D::create(path) : TextureCubemap::create(path);
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
#include "inferno/asset/asset-manager.h"
|
#include "inferno/asset/asset-manager.h"
|
||||||
|
|
||||||
|
struct aiTexture;
|
||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
class Texture2D;
|
class Texture2D;
|
||||||
@@ -63,6 +65,7 @@ public:
|
|||||||
|
|
||||||
// Factory function
|
// Factory function
|
||||||
static std::shared_ptr<Texture2D> create(std::string_view path);
|
static std::shared_ptr<Texture2D> create(std::string_view path);
|
||||||
|
static std::shared_ptr<Texture2D> create(aiTexture* texture);
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "inferno/component/model-component.h"
|
||||||
|
#include "inferno/asset/asset-manager.h"
|
||||||
|
#include "inferno/asset/model.h"
|
||||||
|
#include "inferno/asset/texture.h"
|
||||||
|
|
||||||
|
namespace Inferno {
|
||||||
|
|
||||||
|
void fromJson(const ruc::Json& json, ModelComponent& value)
|
||||||
|
{
|
||||||
|
VERIFY(json.type() == ruc::Json::Type::Object);
|
||||||
|
|
||||||
|
if (json.exists("model") && json.at("model").type() == ruc::Json::Type::String) {
|
||||||
|
value.model = AssetManager::the().load<Model>(json.at("model").asString());
|
||||||
|
}
|
||||||
|
if (json.exists("texture") && json.at("texture").type() == ruc::Json::Type::String) {
|
||||||
|
value.texture = AssetManager::the().load<Texture2D>(json.at("texture").asString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Inferno
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory> // std::shared_ptr
|
||||||
|
|
||||||
|
#include "ruc/json/json.h"
|
||||||
|
|
||||||
|
#include "inferno/asset/model.h"
|
||||||
|
#include "inferno/asset/texture.h"
|
||||||
|
|
||||||
|
namespace Inferno {
|
||||||
|
|
||||||
|
struct ModelComponent {
|
||||||
|
std::shared_ptr<Model> model;
|
||||||
|
std::shared_ptr<Texture2D> texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
void fromJson(const ruc::Json& json, ModelComponent& value);
|
||||||
|
|
||||||
|
} // namespace Inferno
|
||||||
@@ -321,6 +321,16 @@ void IndexBuffer::unbind() const
|
|||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IndexBuffer::uploadData(const void* data, uint32_t size)
|
||||||
|
{
|
||||||
|
bind();
|
||||||
|
|
||||||
|
// Upload data to the GPU
|
||||||
|
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, size, data);
|
||||||
|
|
||||||
|
unbind();
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
VertexArray::VertexArray()
|
VertexArray::VertexArray()
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ private:
|
|||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
// GPU memory which holds raw vertex data
|
// GPU memory which holds raw vertex data
|
||||||
class VertexBuffer {
|
class VertexBuffer { // Vertex Buffer Object, VBO
|
||||||
public:
|
public:
|
||||||
VertexBuffer(size_t size);
|
VertexBuffer(size_t size);
|
||||||
VertexBuffer(float* vertices, size_t size);
|
VertexBuffer(float* vertices, size_t size);
|
||||||
@@ -113,7 +113,7 @@ private:
|
|||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
// Vertices order of rendering
|
// Vertices order of rendering
|
||||||
class IndexBuffer {
|
class IndexBuffer { // Element Buffer Object, EBO
|
||||||
public:
|
public:
|
||||||
IndexBuffer(uint32_t* indices, size_t size);
|
IndexBuffer(uint32_t* indices, size_t size);
|
||||||
~IndexBuffer();
|
~IndexBuffer();
|
||||||
@@ -121,6 +121,8 @@ public:
|
|||||||
void bind() const;
|
void bind() const;
|
||||||
void unbind() const;
|
void unbind() const;
|
||||||
|
|
||||||
|
void uploadData(const void* data, uint32_t size);
|
||||||
|
|
||||||
uint32_t getCount() const { return m_count; }
|
uint32_t getCount() const { return m_count; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -131,7 +133,7 @@ private:
|
|||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
// Array that holds the vertex attributes configuration
|
// Array that holds the vertex attributes configuration
|
||||||
class VertexArray {
|
class VertexArray { // Vertex Array Object, VAO
|
||||||
public:
|
public:
|
||||||
VertexArray();
|
VertexArray();
|
||||||
~VertexArray();
|
~VertexArray();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#include <memory> // std::shadred_ptr
|
||||||
|
|
||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
#include "ruc/format/log.h"
|
#include "ruc/format/log.h"
|
||||||
@@ -39,9 +39,9 @@ void RenderCommand::clearColor(const glm::vec4& color)
|
|||||||
glClearColor(color.r, color.g, color.b, color.a);
|
glClearColor(color.r, color.g, color.b, color.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderCommand::drawIndexed(const VertexArray& vertexArray, uint32_t indexCount)
|
void RenderCommand::drawIndexed(std::shared_ptr<VertexArray> vertexArray, uint32_t indexCount)
|
||||||
{
|
{
|
||||||
uint32_t count = indexCount ? indexCount : vertexArray.getIndexBuffer()->getCount();
|
uint32_t count = indexCount ? indexCount : vertexArray->getIndexBuffer()->getCount();
|
||||||
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr);
|
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "glm/ext/matrix_float4x4.hpp" // glm::mat4
|
#include <memory> // std::shadred_ptr
|
||||||
|
|
||||||
|
#include "glm/ext/vector_float4.hpp" // glm::vec4
|
||||||
|
|
||||||
namespace Inferno {
|
namespace Inferno {
|
||||||
|
|
||||||
@@ -19,7 +21,7 @@ public:
|
|||||||
|
|
||||||
static void clear();
|
static void clear();
|
||||||
static void clearColor(const glm::vec4& color);
|
static void clearColor(const glm::vec4& color);
|
||||||
static void drawIndexed(const VertexArray& vertexArray, uint32_t indexCount = 0);
|
static void drawIndexed(std::shared_ptr<VertexArray> vertexArray, uint32_t indexCount = 0);
|
||||||
|
|
||||||
static void setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height);
|
static void setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height);
|
||||||
static void setDepthTest(bool enabled);
|
static void setDepthTest(bool enabled);
|
||||||
|
|||||||
+151
-40
@@ -4,8 +4,8 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm> // std::min
|
#include <algorithm> // std::copy, std::min
|
||||||
#include <utility> // std::move
|
#include <span>
|
||||||
|
|
||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
#include "ruc/format/log.h"
|
#include "ruc/format/log.h"
|
||||||
@@ -61,32 +61,7 @@ void Renderer<T>::initialize()
|
|||||||
// Create vertex array
|
// Create vertex array
|
||||||
m_vertexArray = std::make_shared<VertexArray>();
|
m_vertexArray = std::make_shared<VertexArray>();
|
||||||
|
|
||||||
// CPU
|
createElementBuffer();
|
||||||
// ---------------------------------
|
|
||||||
|
|
||||||
// Generate indices
|
|
||||||
|
|
||||||
uint32_t* indices = new uint32_t[maxIndices];
|
|
||||||
|
|
||||||
uint32_t offset = 0;
|
|
||||||
for (uint32_t i = 0; i < maxIndices; i += indexPerQuad) {
|
|
||||||
indices[i + 0] = offset + 0;
|
|
||||||
indices[i + 1] = offset + 1;
|
|
||||||
indices[i + 2] = offset + 2;
|
|
||||||
indices[i + 3] = offset + 2;
|
|
||||||
indices[i + 4] = offset + 3;
|
|
||||||
indices[i + 5] = offset + 0;
|
|
||||||
|
|
||||||
offset += vertexPerQuad;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GPU
|
|
||||||
// ---------------------------------
|
|
||||||
|
|
||||||
// Create index buffer
|
|
||||||
auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * maxIndices);
|
|
||||||
m_vertexArray->setIndexBuffer(indexBuffer);
|
|
||||||
delete[] indices;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -146,24 +121,56 @@ void Renderer<T>::unbind()
|
|||||||
m_shader->unbind();
|
m_shader->unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void Renderer<T>::createElementBuffer()
|
||||||
|
{
|
||||||
|
// CPU
|
||||||
|
// ---------------------------------
|
||||||
|
|
||||||
|
// Generate indices
|
||||||
|
|
||||||
|
uint32_t* indices = new uint32_t[maxElements];
|
||||||
|
|
||||||
|
uint32_t offset = 0;
|
||||||
|
for (uint32_t i = 0; i < maxElements; i += elementPerQuad) {
|
||||||
|
indices[i + 0] = offset + 0;
|
||||||
|
indices[i + 1] = offset + 1;
|
||||||
|
indices[i + 2] = offset + 2;
|
||||||
|
indices[i + 3] = offset + 2;
|
||||||
|
indices[i + 4] = offset + 3;
|
||||||
|
indices[i + 5] = offset + 0;
|
||||||
|
|
||||||
|
offset += vertexPerQuad;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GPU
|
||||||
|
// ---------------------------------
|
||||||
|
|
||||||
|
// Create index buffer
|
||||||
|
auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * maxElements);
|
||||||
|
m_vertexArray->setIndexBuffer(indexBuffer);
|
||||||
|
delete[] indices;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Renderer<T>::flush()
|
void Renderer<T>::flush()
|
||||||
{
|
{
|
||||||
if (m_quadIndex == 0) {
|
if (m_vertexIndex == 0 || m_elementIndex == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Upload index data to GPU
|
||||||
|
uploadElementBuffer();
|
||||||
|
|
||||||
// Upload vertex data to GPU
|
// Upload vertex data to GPU
|
||||||
m_vertexArray->at(0)->uploadData(
|
m_vertexArray->at(0)->uploadData(m_vertexBufferBase, m_vertexIndex * sizeof(T));
|
||||||
m_vertexBufferBase,
|
|
||||||
m_quadIndex * vertexPerQuad * sizeof(T));
|
|
||||||
|
|
||||||
bind();
|
bind();
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
bool depthTest = RenderCommand::depthTest();
|
bool depthTest = RenderCommand::depthTest();
|
||||||
RenderCommand::setDepthTest(m_enableDepthBuffer);
|
RenderCommand::setDepthTest(m_enableDepthBuffer);
|
||||||
RenderCommand::drawIndexed(*m_vertexArray, m_quadIndex * indexPerQuad);
|
RenderCommand::drawIndexed(m_vertexArray, m_elementIndex);
|
||||||
RenderCommand::setDepthTest(depthTest);
|
RenderCommand::setDepthTest(depthTest);
|
||||||
|
|
||||||
unbind();
|
unbind();
|
||||||
@@ -172,7 +179,8 @@ void Renderer<T>::flush()
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
void Renderer<T>::startBatch()
|
void Renderer<T>::startBatch()
|
||||||
{
|
{
|
||||||
m_quadIndex = 0;
|
m_vertexIndex = 0;
|
||||||
|
m_elementIndex = 0;
|
||||||
m_vertexBufferPtr = m_vertexBufferBase;
|
m_vertexBufferPtr = m_vertexBufferBase;
|
||||||
|
|
||||||
m_textureSlotIndex = 1;
|
m_textureSlotIndex = 1;
|
||||||
@@ -245,7 +253,7 @@ void Renderer2D::drawQuad(const TransformComponent& transform, glm::vec4 color,
|
|||||||
void Renderer2D::drawQuad(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture)
|
void Renderer2D::drawQuad(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture)
|
||||||
{
|
{
|
||||||
// Create a new batch if the quad limit has been reached
|
// Create a new batch if the quad limit has been reached
|
||||||
if (m_quadIndex >= maxQuads) {
|
if (m_vertexIndex + vertexPerQuad > maxVertices || m_elementIndex + elementPerQuad > maxElements) {
|
||||||
nextBatch();
|
nextBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,7 +275,8 @@ void Renderer2D::drawQuad(const TransformComponent& transform, glm::mat4 color,
|
|||||||
m_vertexBufferPtr++;
|
m_vertexBufferPtr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_quadIndex++;
|
m_vertexIndex += vertexPerQuad;
|
||||||
|
m_elementIndex += elementPerQuad;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer2D::loadShader()
|
void Renderer2D::loadShader()
|
||||||
@@ -366,7 +375,8 @@ void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::vec4
|
|||||||
void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture)
|
void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture)
|
||||||
{
|
{
|
||||||
// Create a new batch if the quad limit has been reached
|
// Create a new batch if the quad limit has been reached
|
||||||
if (m_quadIndex >= maxQuads) {
|
if (m_vertexIndex + (vertexPerQuad * quadPerCube) > maxVertices
|
||||||
|
|| m_elementIndex + (elementPerQuad * quadPerCube) > maxElements) {
|
||||||
nextBatch();
|
nextBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +390,8 @@ void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::mat4
|
|||||||
m_vertexBufferPtr++;
|
m_vertexBufferPtr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_quadIndex += quadPerCube;
|
m_vertexIndex += vertexPerQuad * quadPerCube;
|
||||||
|
m_elementIndex += elementPerQuad * quadPerCube;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererCubemap::loadShader()
|
void RendererCubemap::loadShader()
|
||||||
@@ -428,7 +439,7 @@ RendererFont::RendererFont(s)
|
|||||||
void RendererFont::drawSymbol(std::array<SymbolVertex, vertexPerQuad>& symbolQuad, std::shared_ptr<Texture> texture)
|
void RendererFont::drawSymbol(std::array<SymbolVertex, vertexPerQuad>& symbolQuad, std::shared_ptr<Texture> texture)
|
||||||
{
|
{
|
||||||
// Create a new batch if the quad limit has been reached
|
// Create a new batch if the quad limit has been reached
|
||||||
if (m_quadIndex >= maxQuads) {
|
if (m_vertexIndex + vertexPerQuad > maxVertices || m_elementIndex + elementPerQuad > maxElements) {
|
||||||
nextBatch();
|
nextBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +462,8 @@ void RendererFont::drawSymbol(std::array<SymbolVertex, vertexPerQuad>& symbolQua
|
|||||||
m_vertexBufferPtr++;
|
m_vertexBufferPtr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_quadIndex++;
|
m_vertexIndex += vertexPerQuad;
|
||||||
|
m_elementIndex += elementPerQuad;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererFont::loadShader()
|
void RendererFont::loadShader()
|
||||||
@@ -459,4 +471,103 @@ void RendererFont::loadShader()
|
|||||||
m_shader = AssetManager::the().load<Shader>("assets/glsl/batch-font");
|
m_shader = AssetManager::the().load<Shader>("assets/glsl/batch-font");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
Renderer3D::Renderer3D(s)
|
||||||
|
{
|
||||||
|
Renderer::initialize();
|
||||||
|
|
||||||
|
// CPU
|
||||||
|
// ---------------------------------
|
||||||
|
|
||||||
|
// Create array for storing quads vertices
|
||||||
|
m_vertexBufferBase = new Vertex[maxVertices];
|
||||||
|
m_vertexBufferPtr = m_vertexBufferBase;
|
||||||
|
|
||||||
|
// GPU
|
||||||
|
// ---------------------------------
|
||||||
|
|
||||||
|
m_enableDepthBuffer = true;
|
||||||
|
|
||||||
|
// Create vertex buffer
|
||||||
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(Vertex) * maxVertices);
|
||||||
|
vertexBuffer->setLayout({
|
||||||
|
{ BufferElementType::Vec3, "a_position" },
|
||||||
|
{ BufferElementType::Vec3, "a_normal" },
|
||||||
|
{ BufferElementType::Vec2, "a_textureCoordinates" },
|
||||||
|
{ BufferElementType::Float, "a_textureIndex" },
|
||||||
|
});
|
||||||
|
m_vertexArray->addVertexBuffer(vertexBuffer);
|
||||||
|
|
||||||
|
ruc::info("Renderer3D initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer3D::drawModel(std::span<const Vertex> vertices, std::span<const uint32_t> indices, const TransformComponent& transform, std::shared_ptr<Texture> texture)
|
||||||
|
{
|
||||||
|
VERIFY(vertices.size() <= maxVertices, "model vertices too big for buffer");
|
||||||
|
VERIFY(indices.size() <= maxElements, "model elements too big for buffer");
|
||||||
|
|
||||||
|
// Create a new batch if the quad limit has been reached
|
||||||
|
if (m_vertexIndex + vertices.size() > maxVertices || m_elementIndex + indices.size() > maxElements) {
|
||||||
|
nextBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t textureUnitIndex = addTextureUnit(texture);
|
||||||
|
|
||||||
|
// Add the vertices
|
||||||
|
for (auto vertex : vertices) {
|
||||||
|
m_vertexBufferPtr->position = transform.transform * glm::vec4(vertex.position, 1.0f);
|
||||||
|
m_vertexBufferPtr->normal = vertex.normal;
|
||||||
|
m_vertexBufferPtr->textureCoordinates = vertex.textureCoordinates;
|
||||||
|
m_vertexBufferPtr->textureIndex = (float)textureUnitIndex;
|
||||||
|
m_vertexBufferPtr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::copy(indices.begin(), indices.end(), m_elementBufferPtr);
|
||||||
|
m_elementBufferPtr += indices.size();
|
||||||
|
|
||||||
|
m_vertexIndex += vertices.size();
|
||||||
|
m_elementIndex += indices.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer3D::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView)
|
||||||
|
{
|
||||||
|
m_shader->bind();
|
||||||
|
m_shader->setFloat("u_projectionView", cameraProjection * cameraView);
|
||||||
|
m_shader->unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer3D::createElementBuffer()
|
||||||
|
{
|
||||||
|
// CPU
|
||||||
|
// ---------------------------------
|
||||||
|
|
||||||
|
// Create array for storing quads vertices
|
||||||
|
m_elementBufferBase = new uint32_t[maxElements];
|
||||||
|
m_elementBufferPtr = m_elementBufferBase;
|
||||||
|
|
||||||
|
// GPU
|
||||||
|
// ---------------------------------
|
||||||
|
|
||||||
|
// Create index buffer
|
||||||
|
auto indexBuffer = std::make_shared<IndexBuffer>(m_elementBufferBase, sizeof(uint32_t) * maxElements);
|
||||||
|
m_vertexArray->setIndexBuffer(indexBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer3D::uploadElementBuffer()
|
||||||
|
{
|
||||||
|
m_vertexArray->getIndexBuffer()->uploadData(m_elementBufferBase, m_elementIndex * sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer3D::loadShader()
|
||||||
|
{
|
||||||
|
m_shader = AssetManager::the().load<Shader>("assets/glsl/batch-3d");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer3D::startBatch()
|
||||||
|
{
|
||||||
|
Renderer<Vertex>::startBatch();
|
||||||
|
m_elementBufferPtr = m_elementBufferBase;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Inferno
|
} // namespace Inferno
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <cstdint> // int32_t, uint32_t
|
#include <cstdint> // int32_t, uint32_t
|
||||||
#include <memory> // std::shared_ptr, std::unique_ptr, std::make_shared, std::make_unique
|
#include <memory> // std::shared_ptr, std::unique_ptr, std::make_shared, std::make_unique
|
||||||
|
#include <span>
|
||||||
|
|
||||||
#include "glm/ext/matrix_float4x4.hpp" // glm::mat4
|
#include "glm/ext/matrix_float4x4.hpp" // glm::mat4
|
||||||
#include "glm/ext/vector_float2.hpp" // glm::vec2
|
#include "glm/ext/vector_float2.hpp" // glm::vec2
|
||||||
@@ -49,21 +50,27 @@ struct SymbolVertex {
|
|||||||
float offset = 0.0f;
|
float offset = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Vertex {
|
||||||
|
glm::vec3 position { 0.0f, 0.0f, 0.0f };
|
||||||
|
glm::vec3 normal { 1.0f, 1.0f, 1.0f };
|
||||||
|
glm::vec2 textureCoordinates { 0.0f, 0.0f };
|
||||||
|
float textureIndex = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Renderer {
|
class Renderer {
|
||||||
public:
|
public:
|
||||||
static constexpr const uint32_t vertexPerQuad = 4;
|
static constexpr const uint32_t vertexPerQuad = 4;
|
||||||
static constexpr const uint32_t indexPerQuad = 6;
|
static constexpr const uint32_t elementPerQuad = 6;
|
||||||
static constexpr const uint32_t quadPerCube = 6;
|
|
||||||
|
|
||||||
// When to start a new batch
|
// When to start a new batch
|
||||||
static constexpr const uint32_t maxQuads = 20000;
|
static constexpr const uint32_t maxVertices = 60000;
|
||||||
static constexpr const uint32_t maxVertices = maxQuads * vertexPerQuad;
|
static constexpr const uint32_t maxElements = 60000;
|
||||||
static constexpr const uint32_t maxIndices = maxQuads * indexPerQuad;
|
|
||||||
static constexpr const uint32_t maxTextureSlots = 32;
|
static constexpr const uint32_t maxTextureSlots = 32;
|
||||||
|
|
||||||
|
public:
|
||||||
virtual void beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView);
|
virtual void beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView);
|
||||||
virtual void endScene();
|
virtual void endScene();
|
||||||
|
|
||||||
@@ -79,6 +86,8 @@ protected:
|
|||||||
void bind();
|
void bind();
|
||||||
void unbind();
|
void unbind();
|
||||||
|
|
||||||
|
virtual void createElementBuffer();
|
||||||
|
virtual void uploadElementBuffer() {}
|
||||||
virtual void loadShader() = 0;
|
virtual void loadShader() = 0;
|
||||||
virtual void flush();
|
virtual void flush();
|
||||||
virtual void startBatch();
|
virtual void startBatch();
|
||||||
@@ -86,7 +95,8 @@ protected:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
// CPU quad vertices
|
// CPU quad vertices
|
||||||
uint32_t m_quadIndex { 0 };
|
uint32_t m_vertexIndex { 0 };
|
||||||
|
uint32_t m_elementIndex { 0 };
|
||||||
T* m_vertexBufferBase { nullptr };
|
T* m_vertexBufferBase { nullptr };
|
||||||
T* m_vertexBufferPtr { nullptr };
|
T* m_vertexBufferPtr { nullptr };
|
||||||
|
|
||||||
@@ -102,7 +112,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TOOD:
|
// TOOD:
|
||||||
// - Deduplicate flush()
|
// v Deduplicate flush()
|
||||||
// v Add bool for disabling depth buffer
|
// v Add bool for disabling depth buffer
|
||||||
// - Add Size for uploadData (this is prob not needed, we got T already)
|
// - Add Size for uploadData (this is prob not needed, we got T already)
|
||||||
// - Decide if its worth to remove template<T> from Renderer, just cast vertexBufferPtr before usage
|
// - Decide if its worth to remove template<T> from Renderer, just cast vertexBufferPtr before usage
|
||||||
@@ -114,7 +124,7 @@ class Renderer2D final
|
|||||||
, public ruc::Singleton<Renderer2D> {
|
, public ruc::Singleton<Renderer2D> {
|
||||||
public:
|
public:
|
||||||
Renderer2D(s);
|
Renderer2D(s);
|
||||||
virtual ~Renderer2D() {};
|
virtual ~Renderer2D() = default;
|
||||||
|
|
||||||
using Singleton<Renderer2D>::destroy;
|
using Singleton<Renderer2D>::destroy;
|
||||||
|
|
||||||
@@ -136,9 +146,12 @@ private:
|
|||||||
class RendererCubemap final
|
class RendererCubemap final
|
||||||
: public Renderer<CubemapVertex>
|
: public Renderer<CubemapVertex>
|
||||||
, public ruc::Singleton<RendererCubemap> {
|
, public ruc::Singleton<RendererCubemap> {
|
||||||
|
public:
|
||||||
|
static constexpr const uint32_t quadPerCube = 6;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RendererCubemap(s);
|
RendererCubemap(s);
|
||||||
virtual ~RendererCubemap() {};
|
virtual ~RendererCubemap() = default;
|
||||||
|
|
||||||
using Singleton<RendererCubemap>::destroy;
|
using Singleton<RendererCubemap>::destroy;
|
||||||
|
|
||||||
@@ -161,7 +174,7 @@ class RendererFont final
|
|||||||
, public ruc::Singleton<RendererFont> {
|
, public ruc::Singleton<RendererFont> {
|
||||||
public:
|
public:
|
||||||
RendererFont(s);
|
RendererFont(s);
|
||||||
virtual ~RendererFont() {};
|
virtual ~RendererFont() = default;
|
||||||
|
|
||||||
using Singleton<RendererFont>::destroy;
|
using Singleton<RendererFont>::destroy;
|
||||||
|
|
||||||
@@ -171,4 +184,31 @@ private:
|
|||||||
void loadShader() override;
|
void loadShader() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
class Renderer3D final
|
||||||
|
: public Renderer<Vertex>
|
||||||
|
, public ruc::Singleton<Renderer3D> {
|
||||||
|
public:
|
||||||
|
Renderer3D(s);
|
||||||
|
virtual ~Renderer3D() = default;
|
||||||
|
|
||||||
|
using Singleton<Renderer3D>::destroy;
|
||||||
|
|
||||||
|
virtual void beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView) override;
|
||||||
|
|
||||||
|
void drawModel(std::span<const Vertex> vertices, std::span<const uint32_t> indices, const TransformComponent& transform, std::shared_ptr<Texture> texture);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createElementBuffer() override;
|
||||||
|
void uploadElementBuffer() override;
|
||||||
|
void loadShader() override;
|
||||||
|
void startBatch() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// CPU element vertices
|
||||||
|
uint32_t* m_elementBufferBase { nullptr };
|
||||||
|
uint32_t* m_elementBufferPtr { nullptr };
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Inferno
|
} // namespace Inferno
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "inferno/component/cubemap-component.h"
|
#include "inferno/component/cubemap-component.h"
|
||||||
#include "inferno/component/id-component.h"
|
#include "inferno/component/id-component.h"
|
||||||
#include "inferno/component/luascriptcomponent.h"
|
#include "inferno/component/luascriptcomponent.h"
|
||||||
|
#include "inferno/component/model-component.h"
|
||||||
#include "inferno/component/nativescriptcomponent.h"
|
#include "inferno/component/nativescriptcomponent.h"
|
||||||
#include "inferno/component/spritecomponent.h"
|
#include "inferno/component/spritecomponent.h"
|
||||||
#include "inferno/component/tagcomponent.h"
|
#include "inferno/component/tagcomponent.h"
|
||||||
@@ -166,6 +167,10 @@ uint32_t Scene::loadEntity(ruc::Json components, uint32_t parentEntity)
|
|||||||
auto& text = addComponent<TextAreaComponent>(entity);
|
auto& text = addComponent<TextAreaComponent>(entity);
|
||||||
components.at("text").getTo(text);
|
components.at("text").getTo(text);
|
||||||
}
|
}
|
||||||
|
if (components.exists("model")) {
|
||||||
|
auto& text = addComponent<ModelComponent>(entity);
|
||||||
|
components.at("model").getTo(text);
|
||||||
|
}
|
||||||
if (components.exists("children")) {
|
if (components.exists("children")) {
|
||||||
VERIFY(components.at("children").type() == ruc::Json::Type::Array);
|
VERIFY(components.at("children").type() == ruc::Json::Type::Array);
|
||||||
const auto& children = components.at("children").asArray();
|
const auto& children = components.at("children").asArray();
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "glm/ext/matrix_transform.hpp" // glm::translate, glm::rotate, glm::scale, glm::radians
|
#include "glm/ext/matrix_transform.hpp" // glm::translate, glm::rotate, glm::scale, glm::radians
|
||||||
|
#include "inferno/component/model-component.h"
|
||||||
#include "ruc/format/log.h"
|
#include "ruc/format/log.h"
|
||||||
|
|
||||||
#include "inferno/component/cubemap-component.h"
|
#include "inferno/component/cubemap-component.h"
|
||||||
|
#include "inferno/component/model-component.h"
|
||||||
#include "inferno/component/spritecomponent.h"
|
#include "inferno/component/spritecomponent.h"
|
||||||
#include "inferno/component/transformcomponent.h"
|
#include "inferno/component/transformcomponent.h"
|
||||||
#include "inferno/render/renderer.h"
|
#include "inferno/render/renderer.h"
|
||||||
@@ -37,6 +39,15 @@ void RenderSystem::render()
|
|||||||
for (auto [entity, transform, cubemap] : cubemapView.each()) {
|
for (auto [entity, transform, cubemap] : cubemapView.each()) {
|
||||||
RendererCubemap::the().drawCubemap(transform, cubemap.color, cubemap.texture);
|
RendererCubemap::the().drawCubemap(transform, cubemap.color, cubemap.texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto modelView = m_registry->view<TransformComponent, ModelComponent>();
|
||||||
|
|
||||||
|
for (auto [entity, transform, model] : modelView.each()) {
|
||||||
|
Renderer3D::the().drawModel(model.model->vertices(),
|
||||||
|
model.model->elements(),
|
||||||
|
transform,
|
||||||
|
model.model->texture() ? model.model->texture() : model.texture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Inferno
|
} // namespace Inferno
|
||||||
|
|||||||
Vendored
+12
-1
@@ -9,6 +9,16 @@ add_subdirectory(glfw)
|
|||||||
# Add RUC target to project
|
# Add RUC target to project
|
||||||
add_subdirectory(ruc)
|
add_subdirectory(ruc)
|
||||||
|
|
||||||
|
# assimp options
|
||||||
|
option(ASSIMP_BUILD_ASSIMP_VIEW OFF)
|
||||||
|
option(ASSIMP_BUILD_TESTS OFF)
|
||||||
|
option(ASSIMP_INSTALL OFF)
|
||||||
|
option(ASSIMP_INSTALL_PDB OFF)
|
||||||
|
option(ASSIMP_WARNINGS_AS_ERRORS OFF)
|
||||||
|
|
||||||
|
# Add assimp target to project
|
||||||
|
add_subdirectory(assimp)
|
||||||
|
|
||||||
# Define engine source files
|
# Define engine source files
|
||||||
file(GLOB_RECURSE GLAD "glad/*.c")
|
file(GLOB_RECURSE GLAD "glad/*.c")
|
||||||
file(GLOB LUA "lua/lua/*.c")
|
file(GLOB LUA "lua/lua/*.c")
|
||||||
@@ -19,6 +29,7 @@ set(ENGINE_SOURCES ${GLAD} ${LUA})
|
|||||||
|
|
||||||
add_library(${ENGINE}-dependencies ${ENGINE_SOURCES})
|
add_library(${ENGINE}-dependencies ${ENGINE_SOURCES})
|
||||||
target_include_directories(${ENGINE}-dependencies PUBLIC
|
target_include_directories(${ENGINE}-dependencies PUBLIC
|
||||||
|
"assimp/include"
|
||||||
"glad/include"
|
"glad/include"
|
||||||
"lua")
|
"lua")
|
||||||
target_link_libraries(${ENGINE}-dependencies glfw ruc ruc-test)
|
target_link_libraries(${ENGINE}-dependencies glfw ruc ruc-test assimp)
|
||||||
|
|||||||
+1
Submodule vendor/assimp added at 762ad8e9b7
Reference in New Issue
Block a user