Working prototype for entt based rendering

This commit is contained in:
2022-10-19 23:10:34 +02:00
parent 5b017d4725
commit 2cb49c1b9c
8 changed files with 264 additions and 150 deletions

View File

@@ -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);
}

View File

@@ -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<Camera>(perspective.yfov, perspective.aspectRatio);
} else {
m_camera = std::make_shared<Camera>(90., m_gameWindow->aspectRatio());
}
// m_camera = std::make_shared<Camera>(perspective.yfov, perspective.aspectRatio);
// } else {
m_camera = std::make_shared<Camera>(90., m_gameWindow->aspectRatio());
// }
std::vector<Model> models;
for (auto const &mesh : gltf.meshes) {
std::vector<Mesh_> 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<Model> models;
// for (auto const &mesh : gltf.meshes) {
// std::vector<Mesh_> 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<std::reference_wrapper<const Texture>> primitive_textures;
// std::vector<std::reference_wrapper<const Texture>> 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<ModelEntity> entities;
for (auto const &node : gltf.nodes) {
if (node.mesh == -1) {
continue;
}
// std::vector<ModelEntity> entities;
// for (auto const &node : gltf.nodes) {
// if (node.mesh == -1) {
// continue;
// }
ModelEntity entity(Entity::Prototype(node.name, {}, {}, 1.0F),
m_models[static_cast<unsigned>(node.mesh)],
defaultProgram);
// ModelEntity entity(Entity::Prototype(node.name, {}, {}, 1.0F),
// m_models[static_cast<unsigned>(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<unsigned>(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();

View File

@@ -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"

View File

@@ -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<Mesh>();
for (auto [entity, mesh] : mesh_view.each()) {
Log::logger().info("Convert mesh {}!");
auto mesh_view = m_registry.view<entt::resource<Mesh>>();
for (auto [entity, mesh] : mesh_view.each()) {
m_registry.emplace<GpuMesh>(entity, GpuMesh{mesh});
// Remove Mesh resource as it is no longer needed.
m_registry.erase<entt::resource<Mesh>>(entity);
}
}
void Scene::update(std::chrono::duration<float> delta)
void Scene::update(std::chrono::duration<float> delta,
ShaderProgram *shaderprogram,
glm::mat4 viewProjMatrix,
glm::vec3 viewPosition)
{
auto mesh_view = m_registry.view<GpuMesh, Transform>();
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();
}
}

View File

@@ -1,18 +1,23 @@
#pragma once
#include "mesh.h"
#include "material.h"
#include "gltf_loader.h"
#include "material.h"
#include "mesh.h"
#include <entt/entt.hpp>
#include <chrono>
#include <entt/entt.hpp>
class ShaderProgram;
class Scene
{
public:
Scene();
void update(std::chrono::duration<float> delta);
void update(std::chrono::duration<float> delta,
ShaderProgram *shaderprogram,
glm::mat4 viewProjMatrix,
glm::vec3 viewPosition);
private:
entt::registry m_registry;

View File

@@ -8,7 +8,7 @@ static auto create_vertex_attribute_data(std::span<uint8_t const> 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 <typename T>
static auto create_indices(std::span<uint8_t const> 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<VertexAttributeData>
fx::gltf::Document const &gltf) -> std::optional<std::pair<std::size_t,VertexAttributeData>>
{
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> &material_cache,
entt::resource_cache<Mesh> &mesh_cache) -> GltfPrimitive
{
@@ -188,13 +187,13 @@ auto load_gltf_primitive(fx::gltf::Primitive const &gltf_primitive,
std::map<Mesh::VertexAttributeId, VertexAttributeData> 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<uint8_t const> 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::UnsignedByte>(indices_data_span);
}
if (indices_accessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedShort) {
return create_indices<Indices::UnsignedShort>(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 =
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<entt::resource<GltfMesh>> {
auto mesh = [this, &node, &gltf_meshes]() -> std::optional<entt::resource<GltfMesh>> {
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<GltfMesh> mesh = gltf_mesh_cache[mesh_hash];
return {mesh};
auto const &gltf_mesh = gltf_meshes.at(node.mesh);
return {gltf_mesh};
}
return {};

View File

@@ -1,30 +1,81 @@
#include "mesh.h"
#include "util/Log.h"
#include <exception>
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<GLenum>(position_accessor.componentType),
position_accessor.normalized ? GL_TRUE : GL_FALSE,
position_buffer_view.byteStride,
reinterpret_cast<void *>(
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<decltype(arg)>;
if constexpr (std::is_same_v<T, VertexAttributeData::Scalar>) {
return 1;
}
if constexpr (std::is_same_v<T, VertexAttributeData::Vec2>) {
return 2;
}
if constexpr (std::is_same_v<T, VertexAttributeData::Vec3>) {
return 3;
}
if constexpr (std::is_same_v<T, VertexAttributeData::Vec4>) {
return 4;
}
std::terminate();
}();
glEnableVertexAttribArray(attr_id);
glVertexAttribPointer(
attr_id,
components,
GL_FLOAT, // static_cast<GLenum>(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<decltype(arg)>;
if constexpr (std::is_same_v<T, Indices::UnsignedByte>) {
return GL_UNSIGNED_BYTE;
}
if constexpr (std::is_same_v<T, Indices::UnsignedShort>) {
return GL_UNSIGNED_SHORT;
}
if constexpr (std::is_same_v<T, Indices::UnsignedInt>) {
return GL_UNSIGNED_INT;
}
std::terminate();
}();
},
mesh.indices.values);
glBindVertexArray(0);
}

View File

@@ -1,11 +1,11 @@
#pragma once
#include <array>
#include <cstdint>
#include <glad/gl.h>
#include <map>
#include <variant>
#include <vector>
#include <array>
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{};
};