From 2cb49c1b9c7ee11229c0ff167ac4bbfd667e81f5 Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Wed, 19 Oct 2022 23:10:34 +0200 Subject: [PATCH] Working prototype for entt based rendering --- data/shaders/basic.frag | 1 + src/Controller.cpp | 206 +++++++++++++++++++++------------------- src/Helper.cpp | 2 +- src/Scene.cpp | 49 +++++++++- src/Scene.h | 13 ++- src/gltf_loader.cpp | 42 ++++---- src/mesh.cpp | 85 +++++++++++++---- src/mesh.h | 16 +++- 8 files changed, 264 insertions(+), 150 deletions(-) diff --git a/data/shaders/basic.frag b/data/shaders/basic.frag index 25921d7..518e535 100644 --- a/data/shaders/basic.frag +++ b/data/shaders/basic.frag @@ -69,6 +69,7 @@ void main() fragmentColor += pointLightContribution(u_pointLight[i], normal, v_fragmentPosition, viewDir); } + fragmentColor = vec3(1.,1.,1.); f_color = vec4(fragmentColor, 1.0f); } diff --git a/src/Controller.cpp b/src/Controller.cpp index 86b62e1..c4b0509 100644 --- a/src/Controller.cpp +++ b/src/Controller.cpp @@ -31,123 +31,124 @@ Controller::Controller() m_gameWindow->dimensions().second, postProcessingProgram) { - fx::gltf::ReadQuotas read_quotas{.MaxFileSize = 512 * 1024 * 1024, - .MaxBufferByteLength = 512 * 1024 * 1024}; + // fx::gltf::ReadQuotas read_quotas{.MaxFileSize = 512 * 1024 * 1024, + // .MaxBufferByteLength = 512 * 1024 * 1024}; - // auto gltf_path = std::filesystem::path("Lantern/glTF/Lantern.gltf"); - // auto gltf_path = std::filesystem::path("WaterBottle/glTF/WaterBottle.gltf"); - auto gltf_path = std::filesystem::path("ABeautifulGame.glb"); - auto gltf = [&]() { - if (gltf_path.extension() == ".gltf") { - return fx::gltf::LoadFromText(gltf_path, read_quotas); - } + // // auto gltf_path = std::filesystem::path("Lantern/glTF/Lantern.gltf"); + // // auto gltf_path = std::filesystem::path("WaterBottle/glTF/WaterBottle.gltf"); + // auto gltf_path = std::filesystem::path("ABeautifulGame.glb"); + // auto gltf = [&]() { + // if (gltf_path.extension() == ".gltf") { + // return fx::gltf::LoadFromText(gltf_path, read_quotas); + // } - return fx::gltf::LoadFromBinary(gltf_path, read_quotas); - }(); + // return fx::gltf::LoadFromBinary(gltf_path, read_quotas); + // }(); - defaultProgram.bind(); - AttributeLocations locations{}; + // defaultProgram.bind(); + // AttributeLocations locations{}; - locations.position = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_position"); - locations.normal = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_normal"); - locations.uv = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_texCoord"); - locations.tangent = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_tangent"); + // locations.position = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_position"); + // locations.normal = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_normal"); + // locations.uv = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_texCoord"); + // locations.tangent = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_tangent"); - ShaderProgram::unbind(); + // ShaderProgram::unbind(); - if (!gltf.cameras.empty()) { - auto const &gltf_camera = gltf.cameras.at(0); + // if (!gltf.cameras.empty()) { + // auto const &gltf_camera = gltf.cameras.at(0); - assert(gltf_camera.type == fx::gltf::Camera::Type::Perspective); - auto const &perspective = gltf_camera.perspective; + // assert(gltf_camera.type == fx::gltf::Camera::Type::Perspective); + // auto const &perspective = gltf_camera.perspective; - m_camera = std::make_shared(perspective.yfov, perspective.aspectRatio); - } else { - m_camera = std::make_shared(90., m_gameWindow->aspectRatio()); - } + // m_camera = std::make_shared(perspective.yfov, perspective.aspectRatio); + // } else { + m_camera = std::make_shared(90., m_gameWindow->aspectRatio()); + // } - std::vector models; - for (auto const &mesh : gltf.meshes) { - std::vector meshes; - for (auto const &primitive : mesh.primitives) { - auto const &material = gltf.materials.at(primitive.material); - auto baseColorTexture = material.pbrMetallicRoughness.baseColorTexture.index; - auto normalTexture = material.normalTexture.index; + // std::vector models; + // for (auto const &mesh : gltf.meshes) { + // std::vector meshes; + // for (auto const &primitive : mesh.primitives) { + // auto const &material = gltf.materials.at(primitive.material); + // auto baseColorTexture = material.pbrMetallicRoughness.baseColorTexture.index; + // auto normalTexture = material.normalTexture.index; - std::vector> primitive_textures; + // std::vector> primitive_textures; - // Check if texture already exists, if not load it. - if (baseColorTexture != -1 && !m_textures.contains(baseColorTexture)) { - auto const &gltf_texture = gltf.textures.at(baseColorTexture); - m_textures.emplace(baseColorTexture, - Texture(gltf_texture, - gltf_path.parent_path(), - gltf.images, - gltf.bufferViews, - gltf.buffers, - gltf.samplers, - TextureType::Diffuse)); + // // Check if texture already exists, if not load it. + // if (baseColorTexture != -1 && !m_textures.contains(baseColorTexture)) { + // auto const &gltf_texture = gltf.textures.at(baseColorTexture); + // m_textures.emplace(baseColorTexture, + // Texture(gltf_texture, + // gltf_path.parent_path(), + // gltf.images, + // gltf.bufferViews, + // gltf.buffers, + // gltf.samplers, + // TextureType::Diffuse)); - primitive_textures.emplace_back(m_textures.at(baseColorTexture)); - } + // primitive_textures.emplace_back(m_textures.at(baseColorTexture)); + // } - if (normalTexture != -1 && !m_textures.contains(normalTexture)) { - auto const &gltf_texture = gltf.textures.at(normalTexture); - m_textures.emplace(normalTexture, - Texture(gltf_texture, - gltf_path.parent_path(), - gltf.images, - gltf.bufferViews, - gltf.buffers, - gltf.samplers, - TextureType::Normal)); + // if (normalTexture != -1 && !m_textures.contains(normalTexture)) { + // auto const &gltf_texture = gltf.textures.at(normalTexture); + // m_textures.emplace(normalTexture, + // Texture(gltf_texture, + // gltf_path.parent_path(), + // gltf.images, + // gltf.bufferViews, + // gltf.buffers, + // gltf.samplers, + // TextureType::Normal)); - primitive_textures.emplace_back(m_textures.at(normalTexture)); - } + // primitive_textures.emplace_back(m_textures.at(normalTexture)); + // } - meshes.emplace_back(Mesh_({primitive, gltf, locations}, primitive_textures)); - } - models.emplace_back(Model(mesh.name, std::move(meshes))); - } - m_models = std::move(models); + // meshes.emplace_back(Mesh_({primitive, gltf, locations}, primitive_textures)); + // } + // models.emplace_back(Model(mesh.name, std::move(meshes))); + // } + // m_models = std::move(models); - std::vector entities; - for (auto const &node : gltf.nodes) { - if (node.mesh == -1) { - continue; - } + // std::vector entities; + // for (auto const &node : gltf.nodes) { + // if (node.mesh == -1) { + // continue; + // } - ModelEntity entity(Entity::Prototype(node.name, {}, {}, 1.0F), - m_models[static_cast(node.mesh)], - defaultProgram); + // ModelEntity entity(Entity::Prototype(node.name, {}, {}, 1.0F), + // m_models[static_cast(node.mesh)], + // defaultProgram); - if (!node.translation.empty()) { - entity.setPosition( - glm::vec3(node.translation[0], node.translation[1], node.translation[2])); - } + // if (!node.translation.empty()) { + // entity.setPosition( + // glm::vec3(node.translation[0], node.translation[1], node.translation[2])); + // } - if (!node.rotation.empty()) { - entity.setRotation(glm::eulerAngles( - glm::quat(node.rotation[3], node.rotation[0], node.rotation[1], node.rotation[2]))); - } + // if (!node.rotation.empty()) { + // entity.setRotation(glm::eulerAngles( + // glm::quat(node.rotation[3], node.rotation[0], node.rotation[1], + // node.rotation[2]))); + // } - if (!node.scale.empty()) { - entity.setScale(node.scale[0]); - } + // if (!node.scale.empty()) { + // entity.setScale(node.scale[0]); + // } - entities.push_back(std::move(entity)); - } + // entities.push_back(std::move(entity)); + // } - for (auto const &node : gltf.nodes) { - for (auto const &child : node.children) { - if (!node.translation.empty()) { - entities[child].translate( - glm::vec3(node.translation[0], node.translation[1], node.translation[2])); - } - } - } + // for (auto const &node : gltf.nodes) { + // for (auto const &child : node.children) { + // if (!node.translation.empty()) { + // entities[child].translate( + // glm::vec3(node.translation[0], node.translation[1], node.translation[2])); + // } + // } + // } - m_entities = std::move(entities); + // m_entities = std::move(entities); } void Controller::run() @@ -183,12 +184,19 @@ void Controller::run() m_camera->lookForward(); m_camera->updateVPM(); + static constexpr auto MICROSECONDS_PER_SECOND = 1'000'000; + m_scene.update( + std::chrono::microseconds(static_cast(m_deltaTime * MICROSECONDS_PER_SECOND)), + &defaultProgram, + m_camera->getViewProj(), + m_camera->getPosition()); + // Draw scene - defaultProgram.bind(); - for (auto const &entity : m_entities) { - entity.draw(m_camera->getViewProj(), m_camera->getPosition()); - } - ShaderProgram::unbind(); + // defaultProgram.bind(); + // for (auto const &entity : m_entities) { + // entity.draw(m_camera->getViewProj(), m_camera->getPosition()); + // } + // ShaderProgram::unbind(); m_postProcessFrameBuffer.unbind(); m_postProcessFrameBuffer.drawOnEntireScreen(); diff --git a/src/Helper.cpp b/src/Helper.cpp index 2543616..b78e722 100644 --- a/src/Helper.cpp +++ b/src/Helper.cpp @@ -109,7 +109,7 @@ void Helper::gl_debug_callback(GLenum source, } if (severity == GL_DEBUG_SEVERITY_HIGH || severity == GL_DEBUG_SEVERITY_MEDIUM) - Log::logger().debug("\n[OpenGL Debug Message]\n" + Log::logger().debug("[OpenGL Debug Message]\n" "Message: {}\n" "Source: {}\n" "Type: {}\n" diff --git a/src/Scene.cpp b/src/Scene.cpp index 725c234..31f851e 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -1,4 +1,6 @@ #include "Scene.h" +#include "ShaderProgram.h" +#include "mesh.h" #include "name.h" #include "transform.h" #include "util/Log.h" @@ -48,13 +50,50 @@ Scene::Scene() Log::logger().info("Hello entity {}!", name); } - auto mesh_view = m_registry.view(); - for (auto [entity, mesh] : mesh_view.each()) { - Log::logger().info("Convert mesh {}!"); - + auto mesh_view = m_registry.view>(); + for (auto [entity, mesh] : mesh_view.each()) { + m_registry.emplace(entity, GpuMesh{mesh}); + + // Remove Mesh resource as it is no longer needed. + m_registry.erase>(entity); } } -void Scene::update(std::chrono::duration delta) +void Scene::update(std::chrono::duration delta, + ShaderProgram *shaderprogram, + glm::mat4 viewProjMatrix, + glm::vec3 viewPosition) { + auto mesh_view = m_registry.view(); + for (auto [entity, mesh, transform] : mesh_view.each()) { + shaderprogram->bind(); + + // Bind modelview matrix uniform + { + // Translate * Rotate * Scale * vertex_vec; + // First scaling, then rotation, then translation + + // Translate + glm::mat4 translationMatrix = glm::translate(glm::mat4(1.0f), transform.translation); + + // Rotate + glm::mat4 rotationMatrix = glm::toMat4(transform.rotation); + + // Scale + glm::mat4 scaleMatrix = glm::scale(glm::mat4(1.0f), transform.scale); + + glm::mat4 modelMatrix = translationMatrix * rotationMatrix * scaleMatrix; + + glm::mat4 modelViewProj = viewProjMatrix * modelMatrix; + shaderprogram->setUniform("u_modelViewProjMatrix", modelViewProj); + // shaderprogram->setUniform("u_modelMatrix", modelMatrix); + // shaderprogram->setUniform("u_viewPosition", viewPosition); + } + + glBindVertexArray(mesh.vao); + glDrawElements(GL_TRIANGLES, mesh.indices_count, mesh.indices_type, nullptr); + glBindVertexArray(0); + + ShaderProgram::unbind(); + } } diff --git a/src/Scene.h b/src/Scene.h index 740f8d7..6686fd2 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -1,18 +1,23 @@ #pragma once -#include "mesh.h" -#include "material.h" #include "gltf_loader.h" +#include "material.h" +#include "mesh.h" -#include #include +#include + +class ShaderProgram; class Scene { public: Scene(); - void update(std::chrono::duration delta); + void update(std::chrono::duration delta, + ShaderProgram *shaderprogram, + glm::mat4 viewProjMatrix, + glm::vec3 viewPosition); private: entt::registry m_registry; diff --git a/src/gltf_loader.cpp b/src/gltf_loader.cpp index 05d9eda..eca6f77 100644 --- a/src/gltf_loader.cpp +++ b/src/gltf_loader.cpp @@ -8,7 +8,7 @@ static auto create_vertex_attribute_data(std::span vertex_attribu -> VertexAttributeData { T attribute_data; - attribute_data.reserve(vertex_attribute_data.size_bytes()); + attribute_data.resize(vertex_attribute_data.size_bytes()); std::memcpy( attribute_data.data(), vertex_attribute_data.data(), vertex_attribute_data.size_bytes()); @@ -20,7 +20,7 @@ template static auto create_indices(std::span gltf_index_data) -> Indices { T index_data; - index_data.reserve(gltf_index_data.size_bytes()); + index_data.resize(gltf_index_data.size_bytes()); std::memcpy(index_data.data(), gltf_index_data.data(), gltf_index_data.size_bytes()); @@ -105,7 +105,7 @@ static auto load_material(fx::gltf::Material const &material, static auto load_attribute(std::string_view attribute_name, uint32_t attribute_id, - fx::gltf::Document const &gltf) -> std::optional + fx::gltf::Document const &gltf) -> std::optional> { auto const &attribute_accessor = gltf.accessors.at(attribute_id); @@ -165,13 +165,12 @@ static auto load_attribute(std::string_view attribute_name, std::terminate(); }(); - return std::move(vertex_attribute_data); + return std::make_pair(vertex_attribute_id.value(), std::move(vertex_attribute_data)); } auto load_gltf_primitive(fx::gltf::Primitive const &gltf_primitive, fx::gltf::Document const &gltf, - std::filesystem::path const &document_path, - unsigned primitive_id, + std::string_view primitive_identifier, entt::resource_cache &material_cache, entt::resource_cache &mesh_cache) -> GltfPrimitive { @@ -188,13 +187,13 @@ auto load_gltf_primitive(fx::gltf::Primitive const &gltf_primitive, std::map attributes; for (auto const &attribute : gltf_primitive.attributes) { - auto vertex_attribute_data = load_attribute(attribute.first, attribute.second, gltf); + auto vertex_attribute = load_attribute(attribute.first, attribute.second, gltf); - if (!vertex_attribute_data.has_value()) { + if (!vertex_attribute.has_value()) { continue; } - attributes.emplace(attribute.second, std::move(vertex_attribute_data.value())); + attributes.emplace(vertex_attribute.value().first, std::move(vertex_attribute.value().second)); } // Load indices @@ -206,11 +205,10 @@ auto load_gltf_primitive(fx::gltf::Primitive const &gltf_primitive, std::span indices_data_span = indices_buffer_span.subspan(indices_buffer_view.byteOffset, indices_buffer_view.byteLength); - auto indices = [indices_data_span, &indices_accessor]() { + Indices indices = [indices_data_span, &indices_accessor]() { if (indices_accessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedByte) { return create_indices(indices_data_span); } - if (indices_accessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedShort) { return create_indices(indices_data_span); } @@ -222,12 +220,10 @@ auto load_gltf_primitive(fx::gltf::Primitive const &gltf_primitive, std::terminate(); }(); - std::string const mesh_name = - document_path.string() + ".primitive." + std::to_string(primitive_id); - entt::hashed_string const mesh_hash(mesh_name.c_str()); + entt::hashed_string const mesh_hash(primitive_identifier.data()); entt::resource mesh = - mesh_cache.load(mesh_hash, Mesh{.attributes = attributes, .indices = indices}) + mesh_cache.load(mesh_hash, Mesh{.attributes = attributes, .indices = std::move(indices)}) .first->second; // Get material by hash @@ -274,8 +270,13 @@ auto GltfLoader::operator()(std::filesystem::path const &document_path) -> resul primitives.reserve(gltf_mesh.primitives.size()); for (auto const &gltf_primitive : gltf_mesh.primitives) { + std::string const primitive_identifier = document_path.string() + "." + gltf_mesh.name + + "." + ".primitive." + + std::to_string(primitive_count); + primitives.push_back(load_gltf_primitive( - gltf_primitive, gltf, document_path, primitive_count, material_cache, mesh_cache)); + gltf_primitive, gltf, primitive_identifier, material_cache, mesh_cache)); + ++primitive_count; } if (gltf_mesh.name.empty()) { @@ -296,13 +297,10 @@ auto GltfLoader::operator()(std::filesystem::path const &document_path) -> resul for (std::size_t i = 0; i < gltf.nodes.size(); ++i) { auto const &node = gltf.nodes.at(i); - auto mesh = [this, &node, &gltf]() -> std::optional> { + auto mesh = [this, &node, &gltf_meshes]() -> std::optional> { if (node.mesh != -1) { - // Get mesh by hash - auto const &gltf_mesh = gltf.meshes.at(node.mesh); - entt::hashed_string mesh_hash(gltf_mesh.name.c_str()); - entt::resource mesh = gltf_mesh_cache[mesh_hash]; - return {mesh}; + auto const &gltf_mesh = gltf_meshes.at(node.mesh); + return {gltf_mesh}; } return {}; diff --git a/src/mesh.cpp b/src/mesh.cpp index 6dbe52e..d39323c 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -1,30 +1,81 @@ #include "mesh.h" +#include "util/Log.h" + +#include GpuMesh::GpuMesh(Mesh const &mesh) { glGenVertexArrays(1, &vao); glBindVertexArray(vao); + // Vertex attributes for (auto const &[attribute_id, attribute_data] : mesh.attributes) { // BUG: https://github.com/llvm/llvm-project/issues/48582 auto attr_id = attribute_id; - std::visit([=](auto&& arg) { - GLuint vbo{}; - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, arg.size(), arg.data(), GL_STATIC_DRAW); + GLuint vbo{}; + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); - glEnableVertexAttribArray(attr_id); - glVertexAttribPointer( - attr_id, - accessor_byte_size(position_accessor.type), - static_cast(position_accessor.componentType), - position_accessor.normalized ? GL_TRUE : GL_FALSE, - position_buffer_view.byteStride, - reinterpret_cast( - position_accessor - .byteOffset)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast, - // performance-no-int-to-ptr) - } + std::visit( + [attr_id](auto &&arg) { + glBufferData(GL_ARRAY_BUFFER, arg.size(), arg.data(), GL_STATIC_DRAW); + + int const components = [arg]() -> int { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return 1; + } + if constexpr (std::is_same_v) { + return 2; + } + if constexpr (std::is_same_v) { + return 3; + } + if constexpr (std::is_same_v) { + return 4; + } + + std::terminate(); + }(); + + glEnableVertexAttribArray(attr_id); + glVertexAttribPointer( + attr_id, + components, + GL_FLOAT, // static_cast(position_accessor.componentType), + false, // position_accessor.normalized ? GL_TRUE : GL_FALSE, + 0, + nullptr); + }, + attribute_data.values); } + + // Indices + GLuint ebo{}; + glGenBuffers(1, &ebo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + std::visit( + [this](auto &&arg) { + glBufferData(GL_ELEMENT_ARRAY_BUFFER, arg.size(), arg.data(), GL_STATIC_DRAW); + + indices_count = arg.size(); + indices_type = [arg]() -> GLenum { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return GL_UNSIGNED_BYTE; + } + if constexpr (std::is_same_v) { + return GL_UNSIGNED_SHORT; + } + if constexpr (std::is_same_v) { + return GL_UNSIGNED_INT; + } + + std::terminate(); + }(); + }, + mesh.indices.values); + + glBindVertexArray(0); +} diff --git a/src/mesh.h b/src/mesh.h index 1ea816b..a88dabd 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -1,11 +1,11 @@ #pragma once +#include #include #include #include #include #include -#include struct VertexAttributeData { @@ -45,11 +45,20 @@ struct GpuMesh GpuMesh(GpuMesh const &) = delete; auto operator=(GpuMesh const &) -> GpuMesh & = delete; - GpuMesh(GpuMesh &&other) noexcept : vao(other.vao) { other.vao = 0; } + GpuMesh(GpuMesh &&other) noexcept + : vao(other.vao), indices_count(other.indices_count), indices_type(other.indices_type) + { + other.vao = 0; + } auto operator=(GpuMesh &&other) noexcept -> GpuMesh & { vao = other.vao; + indices_count = other.indices_count; + indices_type = other.indices_type; + + // Deinitialize other other.vao = 0; + return *this; }; @@ -57,4 +66,7 @@ struct GpuMesh // TODO: also store vertex buffers. GLuint vao{}; + + GLsizei indices_count{}; + GLenum indices_type{}; };