Working prototype for entt based rendering
This commit is contained in:
@@ -69,6 +69,7 @@ void main()
|
|||||||
fragmentColor += pointLightContribution(u_pointLight[i], normal, v_fragmentPosition, viewDir);
|
fragmentColor += pointLightContribution(u_pointLight[i], normal, v_fragmentPosition, viewDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fragmentColor = vec3(1.,1.,1.);
|
||||||
f_color = vec4(fragmentColor, 1.0f);
|
f_color = vec4(fragmentColor, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,123 +31,124 @@ Controller::Controller()
|
|||||||
m_gameWindow->dimensions().second,
|
m_gameWindow->dimensions().second,
|
||||||
postProcessingProgram)
|
postProcessingProgram)
|
||||||
{
|
{
|
||||||
fx::gltf::ReadQuotas read_quotas{.MaxFileSize = 512 * 1024 * 1024,
|
// fx::gltf::ReadQuotas read_quotas{.MaxFileSize = 512 * 1024 * 1024,
|
||||||
.MaxBufferByteLength = 512 * 1024 * 1024};
|
// .MaxBufferByteLength = 512 * 1024 * 1024};
|
||||||
|
|
||||||
// auto gltf_path = std::filesystem::path("Lantern/glTF/Lantern.gltf");
|
// // 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("WaterBottle/glTF/WaterBottle.gltf");
|
||||||
auto gltf_path = std::filesystem::path("ABeautifulGame.glb");
|
// auto gltf_path = std::filesystem::path("ABeautifulGame.glb");
|
||||||
auto gltf = [&]() {
|
// auto gltf = [&]() {
|
||||||
if (gltf_path.extension() == ".gltf") {
|
// if (gltf_path.extension() == ".gltf") {
|
||||||
return fx::gltf::LoadFromText(gltf_path, read_quotas);
|
// 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();
|
// defaultProgram.bind();
|
||||||
AttributeLocations locations{};
|
// AttributeLocations locations{};
|
||||||
|
|
||||||
locations.position = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_position");
|
// locations.position = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_position");
|
||||||
locations.normal = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_normal");
|
// locations.normal = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_normal");
|
||||||
locations.uv = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_texCoord");
|
// locations.uv = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_texCoord");
|
||||||
locations.tangent = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_tangent");
|
// locations.tangent = glGetAttribLocation(defaultProgram.getShaderProgramId(), "a_tangent");
|
||||||
|
|
||||||
ShaderProgram::unbind();
|
// ShaderProgram::unbind();
|
||||||
|
|
||||||
if (!gltf.cameras.empty()) {
|
// if (!gltf.cameras.empty()) {
|
||||||
auto const &gltf_camera = gltf.cameras.at(0);
|
// auto const &gltf_camera = gltf.cameras.at(0);
|
||||||
|
|
||||||
assert(gltf_camera.type == fx::gltf::Camera::Type::Perspective);
|
// assert(gltf_camera.type == fx::gltf::Camera::Type::Perspective);
|
||||||
auto const &perspective = gltf_camera.perspective;
|
// auto const &perspective = gltf_camera.perspective;
|
||||||
|
|
||||||
m_camera = std::make_shared<Camera>(perspective.yfov, perspective.aspectRatio);
|
// m_camera = std::make_shared<Camera>(perspective.yfov, perspective.aspectRatio);
|
||||||
} else {
|
// } else {
|
||||||
m_camera = std::make_shared<Camera>(90., m_gameWindow->aspectRatio());
|
m_camera = std::make_shared<Camera>(90., m_gameWindow->aspectRatio());
|
||||||
}
|
// }
|
||||||
|
|
||||||
std::vector<Model> models;
|
// std::vector<Model> models;
|
||||||
for (auto const &mesh : gltf.meshes) {
|
// for (auto const &mesh : gltf.meshes) {
|
||||||
std::vector<Mesh_> meshes;
|
// std::vector<Mesh_> meshes;
|
||||||
for (auto const &primitive : mesh.primitives) {
|
// for (auto const &primitive : mesh.primitives) {
|
||||||
auto const &material = gltf.materials.at(primitive.material);
|
// auto const &material = gltf.materials.at(primitive.material);
|
||||||
auto baseColorTexture = material.pbrMetallicRoughness.baseColorTexture.index;
|
// auto baseColorTexture = material.pbrMetallicRoughness.baseColorTexture.index;
|
||||||
auto normalTexture = material.normalTexture.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.
|
// // Check if texture already exists, if not load it.
|
||||||
if (baseColorTexture != -1 && !m_textures.contains(baseColorTexture)) {
|
// if (baseColorTexture != -1 && !m_textures.contains(baseColorTexture)) {
|
||||||
auto const &gltf_texture = gltf.textures.at(baseColorTexture);
|
// auto const &gltf_texture = gltf.textures.at(baseColorTexture);
|
||||||
m_textures.emplace(baseColorTexture,
|
// m_textures.emplace(baseColorTexture,
|
||||||
Texture(gltf_texture,
|
// Texture(gltf_texture,
|
||||||
gltf_path.parent_path(),
|
// gltf_path.parent_path(),
|
||||||
gltf.images,
|
// gltf.images,
|
||||||
gltf.bufferViews,
|
// gltf.bufferViews,
|
||||||
gltf.buffers,
|
// gltf.buffers,
|
||||||
gltf.samplers,
|
// gltf.samplers,
|
||||||
TextureType::Diffuse));
|
// 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)) {
|
// if (normalTexture != -1 && !m_textures.contains(normalTexture)) {
|
||||||
auto const &gltf_texture = gltf.textures.at(normalTexture);
|
// auto const &gltf_texture = gltf.textures.at(normalTexture);
|
||||||
m_textures.emplace(normalTexture,
|
// m_textures.emplace(normalTexture,
|
||||||
Texture(gltf_texture,
|
// Texture(gltf_texture,
|
||||||
gltf_path.parent_path(),
|
// gltf_path.parent_path(),
|
||||||
gltf.images,
|
// gltf.images,
|
||||||
gltf.bufferViews,
|
// gltf.bufferViews,
|
||||||
gltf.buffers,
|
// gltf.buffers,
|
||||||
gltf.samplers,
|
// gltf.samplers,
|
||||||
TextureType::Normal));
|
// 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));
|
// meshes.emplace_back(Mesh_({primitive, gltf, locations}, primitive_textures));
|
||||||
}
|
// }
|
||||||
models.emplace_back(Model(mesh.name, std::move(meshes)));
|
// models.emplace_back(Model(mesh.name, std::move(meshes)));
|
||||||
}
|
// }
|
||||||
m_models = std::move(models);
|
// m_models = std::move(models);
|
||||||
|
|
||||||
std::vector<ModelEntity> entities;
|
// std::vector<ModelEntity> entities;
|
||||||
for (auto const &node : gltf.nodes) {
|
// for (auto const &node : gltf.nodes) {
|
||||||
if (node.mesh == -1) {
|
// if (node.mesh == -1) {
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
|
|
||||||
ModelEntity entity(Entity::Prototype(node.name, {}, {}, 1.0F),
|
// ModelEntity entity(Entity::Prototype(node.name, {}, {}, 1.0F),
|
||||||
m_models[static_cast<unsigned>(node.mesh)],
|
// m_models[static_cast<unsigned>(node.mesh)],
|
||||||
defaultProgram);
|
// defaultProgram);
|
||||||
|
|
||||||
if (!node.translation.empty()) {
|
// if (!node.translation.empty()) {
|
||||||
entity.setPosition(
|
// entity.setPosition(
|
||||||
glm::vec3(node.translation[0], node.translation[1], node.translation[2]));
|
// glm::vec3(node.translation[0], node.translation[1], node.translation[2]));
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!node.rotation.empty()) {
|
// if (!node.rotation.empty()) {
|
||||||
entity.setRotation(glm::eulerAngles(
|
// entity.setRotation(glm::eulerAngles(
|
||||||
glm::quat(node.rotation[3], node.rotation[0], node.rotation[1], node.rotation[2])));
|
// glm::quat(node.rotation[3], node.rotation[0], node.rotation[1],
|
||||||
}
|
// node.rotation[2])));
|
||||||
|
// }
|
||||||
|
|
||||||
if (!node.scale.empty()) {
|
// if (!node.scale.empty()) {
|
||||||
entity.setScale(node.scale[0]);
|
// 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 &node : gltf.nodes) {
|
||||||
for (auto const &child : node.children) {
|
// for (auto const &child : node.children) {
|
||||||
if (!node.translation.empty()) {
|
// if (!node.translation.empty()) {
|
||||||
entities[child].translate(
|
// entities[child].translate(
|
||||||
glm::vec3(node.translation[0], node.translation[1], node.translation[2]));
|
// glm::vec3(node.translation[0], node.translation[1], node.translation[2]));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
m_entities = std::move(entities);
|
// m_entities = std::move(entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::run()
|
void Controller::run()
|
||||||
@@ -183,12 +184,19 @@ void Controller::run()
|
|||||||
m_camera->lookForward();
|
m_camera->lookForward();
|
||||||
m_camera->updateVPM();
|
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
|
// Draw scene
|
||||||
defaultProgram.bind();
|
// defaultProgram.bind();
|
||||||
for (auto const &entity : m_entities) {
|
// for (auto const &entity : m_entities) {
|
||||||
entity.draw(m_camera->getViewProj(), m_camera->getPosition());
|
// entity.draw(m_camera->getViewProj(), m_camera->getPosition());
|
||||||
}
|
// }
|
||||||
ShaderProgram::unbind();
|
// ShaderProgram::unbind();
|
||||||
|
|
||||||
m_postProcessFrameBuffer.unbind();
|
m_postProcessFrameBuffer.unbind();
|
||||||
m_postProcessFrameBuffer.drawOnEntireScreen();
|
m_postProcessFrameBuffer.drawOnEntireScreen();
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ void Helper::gl_debug_callback(GLenum source,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (severity == GL_DEBUG_SEVERITY_HIGH || severity == GL_DEBUG_SEVERITY_MEDIUM)
|
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"
|
"Message: {}\n"
|
||||||
"Source: {}\n"
|
"Source: {}\n"
|
||||||
"Type: {}\n"
|
"Type: {}\n"
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#include "Scene.h"
|
#include "Scene.h"
|
||||||
|
#include "ShaderProgram.h"
|
||||||
|
#include "mesh.h"
|
||||||
#include "name.h"
|
#include "name.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
#include "util/Log.h"
|
#include "util/Log.h"
|
||||||
@@ -48,13 +50,50 @@ Scene::Scene()
|
|||||||
Log::logger().info("Hello entity {}!", name);
|
Log::logger().info("Hello entity {}!", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mesh_view = m_registry.view<Mesh>();
|
auto mesh_view = m_registry.view<entt::resource<Mesh>>();
|
||||||
for (auto [entity, mesh] : mesh_view.each()) {
|
for (auto [entity, mesh] : mesh_view.each()) {
|
||||||
Log::logger().info("Convert mesh {}!");
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/Scene.h
13
src/Scene.h
@@ -1,18 +1,23 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "mesh.h"
|
|
||||||
#include "material.h"
|
|
||||||
#include "gltf_loader.h"
|
#include "gltf_loader.h"
|
||||||
|
#include "material.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
|
||||||
#include <entt/entt.hpp>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <entt/entt.hpp>
|
||||||
|
|
||||||
|
class ShaderProgram;
|
||||||
|
|
||||||
class Scene
|
class Scene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Scene();
|
Scene();
|
||||||
|
|
||||||
void update(std::chrono::duration<float> delta);
|
void update(std::chrono::duration<float> delta,
|
||||||
|
ShaderProgram *shaderprogram,
|
||||||
|
glm::mat4 viewProjMatrix,
|
||||||
|
glm::vec3 viewPosition);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
entt::registry m_registry;
|
entt::registry m_registry;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ static auto create_vertex_attribute_data(std::span<uint8_t const> vertex_attribu
|
|||||||
-> VertexAttributeData
|
-> VertexAttributeData
|
||||||
{
|
{
|
||||||
T attribute_data;
|
T attribute_data;
|
||||||
attribute_data.reserve(vertex_attribute_data.size_bytes());
|
attribute_data.resize(vertex_attribute_data.size_bytes());
|
||||||
|
|
||||||
std::memcpy(
|
std::memcpy(
|
||||||
attribute_data.data(), vertex_attribute_data.data(), vertex_attribute_data.size_bytes());
|
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
|
static auto create_indices(std::span<uint8_t const> gltf_index_data) -> Indices
|
||||||
{
|
{
|
||||||
T index_data;
|
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());
|
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,
|
static auto load_attribute(std::string_view attribute_name,
|
||||||
uint32_t attribute_id,
|
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);
|
auto const &attribute_accessor = gltf.accessors.at(attribute_id);
|
||||||
|
|
||||||
@@ -165,13 +165,12 @@ static auto load_attribute(std::string_view attribute_name,
|
|||||||
std::terminate();
|
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,
|
auto load_gltf_primitive(fx::gltf::Primitive const &gltf_primitive,
|
||||||
fx::gltf::Document const &gltf,
|
fx::gltf::Document const &gltf,
|
||||||
std::filesystem::path const &document_path,
|
std::string_view primitive_identifier,
|
||||||
unsigned primitive_id,
|
|
||||||
entt::resource_cache<Material> &material_cache,
|
entt::resource_cache<Material> &material_cache,
|
||||||
entt::resource_cache<Mesh> &mesh_cache) -> GltfPrimitive
|
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;
|
std::map<Mesh::VertexAttributeId, VertexAttributeData> attributes;
|
||||||
for (auto const &attribute : gltf_primitive.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;
|
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
|
// Load indices
|
||||||
@@ -206,11 +205,10 @@ auto load_gltf_primitive(fx::gltf::Primitive const &gltf_primitive,
|
|||||||
std::span<uint8_t const> indices_data_span =
|
std::span<uint8_t const> indices_data_span =
|
||||||
indices_buffer_span.subspan(indices_buffer_view.byteOffset, indices_buffer_view.byteLength);
|
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) {
|
if (indices_accessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedByte) {
|
||||||
return create_indices<Indices::UnsignedByte>(indices_data_span);
|
return create_indices<Indices::UnsignedByte>(indices_data_span);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indices_accessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedShort) {
|
if (indices_accessor.componentType == fx::gltf::Accessor::ComponentType::UnsignedShort) {
|
||||||
return create_indices<Indices::UnsignedShort>(indices_data_span);
|
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::terminate();
|
||||||
}();
|
}();
|
||||||
|
|
||||||
std::string const mesh_name =
|
entt::hashed_string const mesh_hash(primitive_identifier.data());
|
||||||
document_path.string() + ".primitive." + std::to_string(primitive_id);
|
|
||||||
entt::hashed_string const mesh_hash(mesh_name.c_str());
|
|
||||||
|
|
||||||
entt::resource<Mesh> mesh =
|
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;
|
.first->second;
|
||||||
|
|
||||||
// Get material by hash
|
// Get material by hash
|
||||||
@@ -274,8 +270,13 @@ auto GltfLoader::operator()(std::filesystem::path const &document_path) -> resul
|
|||||||
primitives.reserve(gltf_mesh.primitives.size());
|
primitives.reserve(gltf_mesh.primitives.size());
|
||||||
|
|
||||||
for (auto const &gltf_primitive : gltf_mesh.primitives) {
|
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(
|
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()) {
|
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) {
|
for (std::size_t i = 0; i < gltf.nodes.size(); ++i) {
|
||||||
auto const &node = gltf.nodes.at(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) {
|
if (node.mesh != -1) {
|
||||||
// Get mesh by hash
|
auto const &gltf_mesh = gltf_meshes.at(node.mesh);
|
||||||
auto const &gltf_mesh = gltf.meshes.at(node.mesh);
|
return {gltf_mesh};
|
||||||
entt::hashed_string mesh_hash(gltf_mesh.name.c_str());
|
|
||||||
entt::resource<GltfMesh> mesh = gltf_mesh_cache[mesh_hash];
|
|
||||||
return {mesh};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
69
src/mesh.cpp
69
src/mesh.cpp
@@ -1,30 +1,81 @@
|
|||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
#include "util/Log.h"
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
GpuMesh::GpuMesh(Mesh const &mesh)
|
GpuMesh::GpuMesh(Mesh const &mesh)
|
||||||
{
|
{
|
||||||
glGenVertexArrays(1, &vao);
|
glGenVertexArrays(1, &vao);
|
||||||
glBindVertexArray(vao);
|
glBindVertexArray(vao);
|
||||||
|
|
||||||
|
// Vertex attributes
|
||||||
for (auto const &[attribute_id, attribute_data] : mesh.attributes) {
|
for (auto const &[attribute_id, attribute_data] : mesh.attributes) {
|
||||||
// BUG: https://github.com/llvm/llvm-project/issues/48582
|
// BUG: https://github.com/llvm/llvm-project/issues/48582
|
||||||
auto attr_id = attribute_id;
|
auto attr_id = attribute_id;
|
||||||
|
|
||||||
std::visit([=](auto&& arg) {
|
|
||||||
GLuint vbo{};
|
GLuint vbo{};
|
||||||
glGenBuffers(1, &vbo);
|
glGenBuffers(1, &vbo);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
|
||||||
|
std::visit(
|
||||||
|
[attr_id](auto &&arg) {
|
||||||
glBufferData(GL_ARRAY_BUFFER, arg.size(), arg.data(), GL_STATIC_DRAW);
|
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);
|
glEnableVertexAttribArray(attr_id);
|
||||||
glVertexAttribPointer(
|
glVertexAttribPointer(
|
||||||
attr_id,
|
attr_id,
|
||||||
accessor_byte_size(position_accessor.type),
|
components,
|
||||||
static_cast<GLenum>(position_accessor.componentType),
|
GL_FLOAT, // static_cast<GLenum>(position_accessor.componentType),
|
||||||
position_accessor.normalized ? GL_TRUE : GL_FALSE,
|
false, // position_accessor.normalized ? GL_TRUE : GL_FALSE,
|
||||||
position_buffer_view.byteStride,
|
0,
|
||||||
reinterpret_cast<void *>(
|
nullptr);
|
||||||
position_accessor
|
},
|
||||||
.byteOffset)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,
|
attribute_data.values);
|
||||||
// performance-no-int-to-ptr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|||||||
16
src/mesh.h
16
src/mesh.h
@@ -1,11 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <glad/gl.h>
|
#include <glad/gl.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
|
||||||
|
|
||||||
struct VertexAttributeData
|
struct VertexAttributeData
|
||||||
{
|
{
|
||||||
@@ -45,11 +45,20 @@ struct GpuMesh
|
|||||||
GpuMesh(GpuMesh const &) = delete;
|
GpuMesh(GpuMesh const &) = delete;
|
||||||
auto operator=(GpuMesh const &) -> GpuMesh & = 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 &
|
auto operator=(GpuMesh &&other) noexcept -> GpuMesh &
|
||||||
{
|
{
|
||||||
vao = other.vao;
|
vao = other.vao;
|
||||||
|
indices_count = other.indices_count;
|
||||||
|
indices_type = other.indices_type;
|
||||||
|
|
||||||
|
// Deinitialize other
|
||||||
other.vao = 0;
|
other.vao = 0;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -57,4 +66,7 @@ struct GpuMesh
|
|||||||
|
|
||||||
// TODO: also store vertex buffers.
|
// TODO: also store vertex buffers.
|
||||||
GLuint vao{};
|
GLuint vao{};
|
||||||
|
|
||||||
|
GLsizei indices_count{};
|
||||||
|
GLenum indices_type{};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user