Get textureless rendering mostly working
This commit is contained in:
@@ -1 +1 @@
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/spdlog)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/spdlog ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
@@ -108,9 +108,9 @@
|
||||
|
||||
set(FGL_CONFIG "-std=c++23 -fmax-errors=3 -fconcepts-diagnostics-depth=8 -march=native -flto -ftree-vectorize")
|
||||
|
||||
if (DEFINED USE_WERROR)
|
||||
set(FGL_CONFIG "${FGL_CONFIG} -Werror")
|
||||
endif ()
|
||||
#if (DEFINED USE_WERROR)
|
||||
#set(FGL_CONFIG "${FGL_CONFIG} -Werror")
|
||||
#endif ()
|
||||
|
||||
# Safe for debug
|
||||
# TODO: Figure out LTO with Alaestor's retarded compiler
|
||||
|
||||
1
dependencies/spdlog
vendored
Submodule
1
dependencies/spdlog
vendored
Submodule
Submodule dependencies/spdlog added at c3aed4b683
@@ -48,8 +48,4 @@ void main()
|
||||
out_albedo = tex_value;
|
||||
|
||||
out_position.a = linearDepth(out_position.z);
|
||||
|
||||
//out_color = vec4(0.0);
|
||||
//out_color = vec4(in_tex_coord, 0.0f, 0.0f);
|
||||
//out_color = texture(tex[0], in_tex_coord);
|
||||
}
|
||||
41
shaders/textureless-gbuffer.frag
Normal file
41
shaders/textureless-gbuffer.frag
Normal file
@@ -0,0 +1,41 @@
|
||||
#version 450
|
||||
#extension GL_EXT_nonuniform_qualifier: enable
|
||||
#extension GL_EXT_debug_printf: enable
|
||||
|
||||
layout (location = 0) in vec3 in_normal;
|
||||
layout (location = 1) in vec2 in_tex_coord;
|
||||
layout (location = 2) in vec3 in_world_pos;
|
||||
layout (location = 3) in vec3 in_color;
|
||||
|
||||
layout (location = 0) out vec4 out_color;
|
||||
layout (location = 1) out vec4 out_position;
|
||||
layout (location = 2) out vec4 out_normal;
|
||||
layout (location = 3) out vec4 out_albedo;
|
||||
|
||||
layout (set = 0, binding = 0) uniform CameraInfo {
|
||||
mat4 projection;
|
||||
mat4 view;
|
||||
mat4 inverse_view;
|
||||
} ubo;
|
||||
|
||||
#define NEAR_PLANE 0.01f
|
||||
#define FAR_PLANE 1000.0f
|
||||
|
||||
float linearDepth(float depth)
|
||||
{
|
||||
float z = depth * 2.0f - 1.0f;
|
||||
return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
out_position = vec4(in_world_pos, 1.0f);
|
||||
|
||||
vec3 N = normalize(in_normal);
|
||||
|
||||
out_normal = vec4(N, 1.0);
|
||||
|
||||
out_position.a = linearDepth(out_position.z);
|
||||
|
||||
out_albedo = vec4(in_color, 1.0);
|
||||
}
|
||||
36
shaders/textureless-gbuffer.vert
Normal file
36
shaders/textureless-gbuffer.vert
Normal file
@@ -0,0 +1,36 @@
|
||||
#version 450
|
||||
#extension GL_EXT_debug_printf: enable
|
||||
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec3 color;
|
||||
layout (location = 2) in vec3 normal;
|
||||
layout (location = 3) in vec2 uv;
|
||||
|
||||
layout (location = 4) in mat4 instance_model_matrix;// 4, 5, 6, 7
|
||||
|
||||
layout (location = 0) out vec3 out_normal;
|
||||
layout (location = 1) out vec2 out_tex_coord;
|
||||
layout (location = 2) out vec3 out_world_pos;
|
||||
layout (location = 3) out vec3 out_color;
|
||||
|
||||
layout (set = 0, binding = 0) uniform CameraInfo {
|
||||
mat4 projection;
|
||||
mat4 view;
|
||||
mat4 inverse_view;
|
||||
} ubo;
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 position_world = instance_model_matrix * vec4(position, 1.0);
|
||||
|
||||
gl_Position = ubo.projection * ubo.view * position_world;
|
||||
out_world_pos = vec3(gl_Position);
|
||||
|
||||
mat3 normal_matrix = transpose(inverse(mat3(instance_model_matrix)));
|
||||
|
||||
out_normal = normalize(normal_matrix * normal);
|
||||
|
||||
out_tex_coord = uv;
|
||||
|
||||
out_color = color;
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
|
||||
add_executable(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${FGL_FLAGS}")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Tracy::TracyClient FGLEngine)
|
||||
@@ -5,9 +5,12 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "engine/EngineContext.hpp"
|
||||
#include "engine/logging.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
spdlog::set_level( spdlog::level::debug );
|
||||
|
||||
fgl::engine::EngineContext engine_ctx {};
|
||||
|
||||
engine_ctx.run();
|
||||
|
||||
@@ -25,6 +25,7 @@ target_precompile_headers(FGLEngine PRIVATE
|
||||
<glm/gtc/matrix_transform.hpp>
|
||||
<glm/gtc/constants.hpp>
|
||||
<glm/vec3.hpp>
|
||||
<glm/vec2.hpp>
|
||||
<glm/mat4x4.hpp>
|
||||
|
||||
<imgui/imgui.h>
|
||||
@@ -32,7 +33,9 @@ target_precompile_headers(FGLEngine PRIVATE
|
||||
|
||||
target_compile_definitions(FGLEngine PUBLIC VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC)
|
||||
|
||||
target_link_libraries(FGLEngine PUBLIC Vulkan::Vulkan glfw glm FGLImGui Tracy::TracyClient VMA FGLLoader)
|
||||
include(dependencies/spdlog)
|
||||
|
||||
target_link_libraries(FGLEngine PUBLIC Vulkan::Vulkan glfw glm FGLImGui Tracy::TracyClient VMA FGLLoader spdlog)
|
||||
target_include_directories(FGLEngine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
set_target_properties(FGLEngine PROPERTIES COMPILE_FLAGS ${FGL_FLAGS})
|
||||
target_compile_features(FGLEngine PRIVATE cxx_std_23)
|
||||
|
||||
@@ -7,20 +7,9 @@
|
||||
#include <glm/glm.hpp>
|
||||
#include <tracy/TracyVulkan.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#include "KeyboardMovementController.hpp"
|
||||
#include "engine/Average.hpp"
|
||||
#include "engine/buffers/UniqueFrameSuballocation.hpp"
|
||||
#include "engine/debug/drawers.hpp"
|
||||
#include "engine/descriptors/DescriptorPool.hpp"
|
||||
#include "engine/literals/size.hpp"
|
||||
#include "engine/model/prebuilt/terrainModel.hpp"
|
||||
#include "engine/pipeline/PipelineT.hpp"
|
||||
#include "engine/systems/EntityRendererSystem.hpp"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
@@ -32,6 +21,17 @@
|
||||
#include "imgui/imgui_internal.h"
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include "KeyboardMovementController.hpp"
|
||||
#include "engine/Average.hpp"
|
||||
#include "engine/buffers/UniqueFrameSuballocation.hpp"
|
||||
#include "engine/debug/drawers.hpp"
|
||||
#include "engine/descriptors/DescriptorPool.hpp"
|
||||
#include "engine/literals/size.hpp"
|
||||
#include "engine/model/prebuilt/terrainModel.hpp"
|
||||
#include "engine/pipeline/PipelineT.hpp"
|
||||
#include "engine/systems/EntityRendererSystem.hpp"
|
||||
#include "model/builders/SceneBuilder.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
constexpr float MAX_DELTA_TIME { 0.5 };
|
||||
@@ -289,6 +289,27 @@ namespace fgl::engine
|
||||
}
|
||||
}*/
|
||||
|
||||
{
|
||||
std::vector< std::shared_ptr< Model > > models { Model::createModelsFromScene(
|
||||
Device::getInstance(),
|
||||
"models/PhysicsTest.glb",
|
||||
m_entity_renderer.getVertexBuffer(),
|
||||
m_entity_renderer.getIndexBuffer() ) };
|
||||
|
||||
for ( auto& model : models )
|
||||
{
|
||||
GameObject object { GameObject::createGameObject() };
|
||||
object.m_model = std::move( model );
|
||||
object.m_transform.translation = WorldCoordinate( 0.0f );
|
||||
object.object_flags |= IS_VISIBLE | IS_ENTITY;
|
||||
|
||||
assert( object.m_model );
|
||||
object.m_model->syncBuffers( command_buffer );
|
||||
|
||||
m_game_objects_root.addGameObject( std::move( object ) );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto model {
|
||||
generateTerrainModel( m_terrain_system.getVertexBuffer(), m_terrain_system.getIndexBuffer() )
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace fgl::engine
|
||||
|
||||
OrientedBoundingBox< CoordinateSpace::World > GameObject::getBoundingBox() const
|
||||
{
|
||||
assert( this->m_transform.translation.vec() != constants::DEFAULT_VEC3 );
|
||||
assert( this->m_transform.scale != constants::DEFAULT_VEC3 );
|
||||
return this->m_transform.mat() * this->m_model->getBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,13 @@ namespace fgl::engine
|
||||
MASK_DEFAULT = IS_VISIBLE,
|
||||
};
|
||||
|
||||
enum GameObjectFilterOptions
|
||||
{
|
||||
NONE = 0,
|
||||
//! Only find objects with no texture
|
||||
TEXTURELESS = 1 << 0,
|
||||
};
|
||||
|
||||
class GameObject
|
||||
{
|
||||
public:
|
||||
@@ -48,9 +55,9 @@ namespace fgl::engine
|
||||
|
||||
GameObject( ID obj_id ) : m_id( obj_id ) {}
|
||||
|
||||
public:
|
||||
GameObject() = delete;
|
||||
|
||||
GameObject() {}
|
||||
public:
|
||||
|
||||
GameObject( const GameObject& other ) = delete;
|
||||
GameObject& operator=( const GameObject& other ) = delete;
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
// Created by kj16609 on 3/11/24.
|
||||
//
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#if TRACY_ENABLE
|
||||
|
||||
void* operator new( std::size_t count )
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "BufferVector.hpp"
|
||||
#include "HostVector.hpp"
|
||||
#include "engine/logging.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
@@ -20,6 +21,7 @@ namespace fgl::engine
|
||||
|
||||
DeviceVector( Buffer& buffer, const std::uint32_t count = 1 ) : BufferVector( buffer, count, sizeof( T ) )
|
||||
{
|
||||
spdlog::debug( "Creating DeviceVector of size {}", count );
|
||||
assert( count != 0 && "BufferSuballocationVector::BufferSuballocationVector() called with count == 0" );
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
class ImageView;
|
||||
|
||||
@@ -8,7 +8,15 @@
|
||||
#include "engine/primitives/boxes/AxisAlignedBoundingBox.hpp"
|
||||
#include "engine/primitives/boxes/AxisAlignedBoundingCube.hpp"
|
||||
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#include "imgui/imgui.h"
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include "tracy_colors.hpp"
|
||||
|
||||
#if ENABLE_IMGUI_DRAWERS
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include "engine/concepts/is_valid_pipeline_input.hpp"
|
||||
|
||||
|
||||
13
src/engine/logging.hpp
Normal file
13
src/engine/logging.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// Created by kj16609 on 5/22/24.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#include <spdlog/spdlog.h>
|
||||
#pragma GCC diagnostic pop
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
#include "generator.hpp"
|
||||
|
||||
#include <glm/geometric.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
|
||||
namespace fgl::engine
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <bits/stdint-uintn.h>
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
@@ -5,19 +5,13 @@
|
||||
#include "Model.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtx/hash.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "builders/ModelBuilder.hpp"
|
||||
#include "builders/SceneBuilder.hpp"
|
||||
#include "engine/buffers/Buffer.hpp"
|
||||
#include "engine/buffers/SuballocationView.hpp"
|
||||
#include "engine/descriptors/DescriptorSet.hpp"
|
||||
#include "engine/image/ImageView.hpp"
|
||||
#include "engine/image/Sampler.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
@@ -73,15 +67,22 @@ namespace fgl::engine
|
||||
|
||||
Model::Model(
|
||||
Device& device, ModelBuilder& builder, const OrientedBoundingBox< CoordinateSpace::Model > bounding_box ) :
|
||||
Model( device, std::move( builder.m_primitives ), bounding_box )
|
||||
{}
|
||||
|
||||
Model::Model(
|
||||
Device& device,
|
||||
std::vector< Primitive >&& primitives,
|
||||
const OrientedBoundingBox< CoordinateSpace::Model > bounding_box ) :
|
||||
m_device( device ),
|
||||
m_draw_parameters( buildParameters( builder.m_primitives ) ),
|
||||
m_draw_parameters( buildParameters( primitives ) ),
|
||||
m_bounding_box( bounding_box )
|
||||
{
|
||||
assert( bounding_box.middle.vec() != constants::DEFAULT_VEC3 );
|
||||
m_primitives = std::move( builder.m_primitives );
|
||||
m_primitives = std::move( primitives );
|
||||
}
|
||||
|
||||
std::unique_ptr< Model > Model::
|
||||
std::shared_ptr< Model > Model::
|
||||
createModel( Device& device, const std::filesystem::path& path, Buffer& vertex_buffer, Buffer& index_buffer )
|
||||
{
|
||||
std::cout << "Creating model: " << path << std::endl;
|
||||
@@ -91,13 +92,25 @@ namespace fgl::engine
|
||||
//Calculate bounding box
|
||||
OrientedBoundingBox bounding_box { buildBoundingBox( builder.m_primitives ) };
|
||||
|
||||
auto model_ptr { std::make_unique< Model >( device, builder, bounding_box ) };
|
||||
auto model_ptr { std::make_shared< Model >( device, builder, bounding_box ) };
|
||||
|
||||
std::cout << "Finished making model: " << path << std::endl;
|
||||
return model_ptr;
|
||||
}
|
||||
|
||||
std::unique_ptr< Model > Model::createModelFromVerts(
|
||||
std::vector< std::shared_ptr< Model > > Model::createModelsFromScene(
|
||||
Device& device, const std::filesystem::path& path, Buffer& vertex_buffer, Buffer& index_buffer )
|
||||
{
|
||||
std::cout << "Loading scene: " << path << std::endl;
|
||||
SceneBuilder builder { vertex_buffer, index_buffer };
|
||||
builder.loadScene( path );
|
||||
|
||||
std::cout << "Finished loading scene: " << path << std::endl;
|
||||
|
||||
return builder.getModels();
|
||||
}
|
||||
|
||||
std::shared_ptr< Model > Model::createModelFromVerts(
|
||||
Device& device,
|
||||
std::vector< Vertex > verts,
|
||||
std::vector< std::uint32_t > indicies,
|
||||
@@ -109,13 +122,14 @@ namespace fgl::engine
|
||||
|
||||
OrientedBoundingBox bounding_box { buildBoundingBox( builder.m_primitives ) };
|
||||
|
||||
auto model_ptr { std::make_unique< Model >( device, builder, bounding_box ) };
|
||||
auto model_ptr { std::make_shared< Model >( device, builder, bounding_box ) };
|
||||
|
||||
return model_ptr;
|
||||
}
|
||||
|
||||
void Model::syncBuffers( vk::CommandBuffer& cmd_buffer )
|
||||
{
|
||||
assert( !m_primitives.empty() );
|
||||
for ( auto& primitive : m_primitives )
|
||||
{
|
||||
primitive.m_vertex_buffer.stage( cmd_buffer );
|
||||
@@ -128,27 +142,4 @@ namespace fgl::engine
|
||||
}
|
||||
}
|
||||
|
||||
void ModelBuilder::loadModel( const std::filesystem::path& filepath )
|
||||
{
|
||||
if ( filepath.extension() == ".obj" )
|
||||
{
|
||||
loadObj( filepath );
|
||||
}
|
||||
else if ( filepath.extension() == ".gltf" )
|
||||
{
|
||||
loadGltf( filepath );
|
||||
}
|
||||
else
|
||||
throw std::runtime_error( "Unknown model file extension" );
|
||||
}
|
||||
|
||||
void ModelBuilder::loadVerts( std::vector< Vertex > verts, std::vector< std::uint32_t > indicies )
|
||||
{
|
||||
VertexBufferSuballocation vertex_suballoc { this->m_vertex_buffer, verts };
|
||||
IndexBufferSuballocation index_suballoc { this->m_index_buffer, std::move( indicies ) };
|
||||
|
||||
this->m_primitives.emplace_back(
|
||||
std::move( vertex_suballoc ), std::move( index_suballoc ), generateBoundingFromVerts( verts ) );
|
||||
}
|
||||
|
||||
} // namespace fgl::engine
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
struct ModelBuilder;
|
||||
|
||||
struct ModelMatrixInfo
|
||||
{
|
||||
@@ -24,26 +25,6 @@ namespace fgl::engine
|
||||
std::uint32_t texture_idx;
|
||||
};
|
||||
|
||||
struct ModelBuilder
|
||||
{
|
||||
Buffer& m_vertex_buffer;
|
||||
Buffer& m_index_buffer;
|
||||
|
||||
std::vector< Primitive > m_primitives {};
|
||||
|
||||
ModelBuilder() = delete;
|
||||
|
||||
ModelBuilder( Buffer& parent_vertex_buffer, Buffer& parent_index_buffer ) :
|
||||
m_vertex_buffer( parent_vertex_buffer ),
|
||||
m_index_buffer( parent_index_buffer )
|
||||
{}
|
||||
|
||||
void loadModel( const std::filesystem::path& filepath );
|
||||
void loadObj( const std::filesystem::path& filepath );
|
||||
void loadGltf( const std::filesystem::path& filepath );
|
||||
void loadVerts( std::vector< Vertex > verts, std::vector< std::uint32_t > indicies );
|
||||
};
|
||||
|
||||
class Model
|
||||
{
|
||||
Device& m_device;
|
||||
@@ -69,16 +50,20 @@ namespace fgl::engine
|
||||
|
||||
std::vector< vk::DrawIndexedIndirectCommand > getDrawCommand( const std::uint32_t index ) const;
|
||||
|
||||
static std::unique_ptr< Model > createModel(
|
||||
//TODO: Switch to using shared_ptr instead of unique_ptr
|
||||
static std::shared_ptr< Model > createModel(
|
||||
Device& device, const std::filesystem::path& path, Buffer& vertex_buffer, Buffer& index_buffer );
|
||||
|
||||
static std::unique_ptr< Model > createModelFromVerts(
|
||||
static std::shared_ptr< Model > createModelFromVerts(
|
||||
Device& device,
|
||||
std::vector< Vertex > verts,
|
||||
std::vector< std::uint32_t > indicies,
|
||||
Buffer& vertex_buffer,
|
||||
Buffer& index_buffer );
|
||||
|
||||
static std::vector< std::shared_ptr< Model > > createModelsFromScene(
|
||||
Device& device, const std::filesystem::path& path, Buffer& vertex_buffer, Buffer& index_buffer );
|
||||
|
||||
void syncBuffers( vk::CommandBuffer& cmd_buffer );
|
||||
|
||||
const std::string& getName() const { return m_name; }
|
||||
@@ -86,6 +71,11 @@ namespace fgl::engine
|
||||
Model(
|
||||
Device& device, ModelBuilder& builder, const OrientedBoundingBox< CoordinateSpace::Model > bounding_box );
|
||||
|
||||
Model(
|
||||
Device& device,
|
||||
std::vector< Primitive >&& primitives,
|
||||
const OrientedBoundingBox< CoordinateSpace::Model > bounding_box );
|
||||
|
||||
~Model() = default;
|
||||
|
||||
Model( const Model& model ) = delete;
|
||||
|
||||
32
src/engine/model/Primitive.cpp
Normal file
32
src/engine/model/Primitive.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// Created by kj16609 on 5/23/24.
|
||||
//
|
||||
|
||||
#include "Primitive.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
Primitive Primitive::fromVerts(
|
||||
const std::vector< Vertex >&& verts,
|
||||
const PrimitiveMode mode,
|
||||
const std::vector< std::uint32_t >&& indicies,
|
||||
Buffer& vertex_buffer,
|
||||
Buffer& index_buffer )
|
||||
{
|
||||
const auto bounds { generateBoundingFromVerts( verts ) };
|
||||
VertexBufferSuballocation vertex_buffer_suballoc { vertex_buffer, std::move( verts ) };
|
||||
IndexBufferSuballocation index_buffer_suballoc { index_buffer, std::move( indicies ) };
|
||||
|
||||
return { std::move( vertex_buffer_suballoc ), std::move( index_buffer_suballoc ), bounds, mode };
|
||||
}
|
||||
|
||||
TextureID Primitive::getTextureID() const
|
||||
{
|
||||
if ( m_texture )
|
||||
return m_texture->getID();
|
||||
else
|
||||
return std::numeric_limits< TextureID >::max();
|
||||
}
|
||||
|
||||
} // namespace fgl::engine
|
||||
@@ -12,43 +12,74 @@
|
||||
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
|
||||
#include "engine/texture/Texture.hpp"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#include "objectloaders/tiny_gltf.h"
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
using VertexBufferSuballocation = DeviceVector< Vertex >;
|
||||
|
||||
using IndexBufferSuballocation = DeviceVector< std::uint32_t >;
|
||||
|
||||
enum PrimitiveMode
|
||||
{
|
||||
POINTS = TINYGLTF_MODE_POINTS,
|
||||
LINE = TINYGLTF_MODE_LINE,
|
||||
LINE_LOOP = TINYGLTF_MODE_LINE_LOOP,
|
||||
LINE_STRIP = TINYGLTF_MODE_LINE_STRIP,
|
||||
TRIS = TINYGLTF_MODE_TRIANGLES,
|
||||
TRI_STRIP = TINYGLTF_MODE_TRIANGLE_STRIP,
|
||||
TRI_FAN = TINYGLTF_MODE_TRIANGLE_FAN
|
||||
};
|
||||
|
||||
struct Primitive
|
||||
{
|
||||
VertexBufferSuballocation m_vertex_buffer;
|
||||
IndexBufferSuballocation m_index_buffer;
|
||||
OrientedBoundingBox< CoordinateSpace::Model > m_bounding_box;
|
||||
PrimitiveMode m_mode;
|
||||
|
||||
std::optional< Texture > m_texture { std::nullopt };
|
||||
|
||||
Primitive(
|
||||
VertexBufferSuballocation&& vertex_buffer,
|
||||
IndexBufferSuballocation&& index_buffer,
|
||||
const OrientedBoundingBox< CoordinateSpace::Model >& bounding_box ) :
|
||||
const OrientedBoundingBox< CoordinateSpace::Model >& bounding_box,
|
||||
const PrimitiveMode mode ) :
|
||||
m_vertex_buffer( std::move( vertex_buffer ) ),
|
||||
m_index_buffer( std::move( index_buffer ) ),
|
||||
m_bounding_box( bounding_box )
|
||||
m_bounding_box( bounding_box ),
|
||||
m_mode( mode )
|
||||
{}
|
||||
|
||||
Primitive(
|
||||
VertexBufferSuballocation&& vertex_buffer,
|
||||
IndexBufferSuballocation&& index_buffer,
|
||||
const OrientedBoundingBox< CoordinateSpace::Model >& bounding_box,
|
||||
Texture&& texture ) :
|
||||
Texture&& texture,
|
||||
const PrimitiveMode mode ) :
|
||||
m_vertex_buffer( std::move( vertex_buffer ) ),
|
||||
m_index_buffer( std::move( index_buffer ) ),
|
||||
m_bounding_box( bounding_box ),
|
||||
m_mode( mode ),
|
||||
m_texture( std::move( texture ) )
|
||||
{}
|
||||
|
||||
Primitive() = delete;
|
||||
Primitive( const Primitive& other ) = delete;
|
||||
Primitive( Primitive&& other ) = default;
|
||||
|
||||
static Primitive fromVerts(
|
||||
const std::vector< Vertex >&& verts,
|
||||
const PrimitiveMode mode,
|
||||
const std::vector< std::uint32_t >&& indicies,
|
||||
Buffer& vertex_buffer,
|
||||
Buffer& index_buffer );
|
||||
|
||||
TextureID getTextureID() const;
|
||||
};
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
38
src/engine/model/builders/ModelBuilder.cpp
Normal file
38
src/engine/model/builders/ModelBuilder.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// Created by kj16609 on 5/18/24.
|
||||
//
|
||||
|
||||
#include "ModelBuilder.hpp"
|
||||
|
||||
#include "engine/model/Primitive.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
void ModelBuilder::loadModel( const std::filesystem::path& filepath )
|
||||
{
|
||||
if ( filepath.extension() == ".obj" )
|
||||
{
|
||||
loadObj( filepath );
|
||||
}
|
||||
else if ( filepath.extension() == ".gltf" )
|
||||
{
|
||||
loadGltf( filepath );
|
||||
}
|
||||
else
|
||||
throw std::runtime_error( "Unknown model file extension" );
|
||||
}
|
||||
|
||||
void ModelBuilder::loadVerts( std::vector< Vertex > verts, std::vector< std::uint32_t > indicies )
|
||||
{
|
||||
VertexBufferSuballocation vertex_suballoc { this->m_vertex_buffer, verts };
|
||||
IndexBufferSuballocation index_suballoc { this->m_index_buffer, std::move( indicies ) };
|
||||
|
||||
this->m_primitives.emplace_back(
|
||||
std::move( vertex_suballoc ),
|
||||
std::move( index_suballoc ),
|
||||
generateBoundingFromVerts( verts ),
|
||||
PrimitiveMode::TRIS );
|
||||
}
|
||||
|
||||
} // namespace fgl::engine
|
||||
36
src/engine/model/builders/ModelBuilder.hpp
Normal file
36
src/engine/model/builders/ModelBuilder.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Created by kj16609 on 5/18/24.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
namespace fgl ::engine
|
||||
{
|
||||
struct Vertex;
|
||||
struct Primitive;
|
||||
class Buffer;
|
||||
|
||||
struct ModelBuilder
|
||||
{
|
||||
Buffer& m_vertex_buffer;
|
||||
Buffer& m_index_buffer;
|
||||
|
||||
std::vector< Primitive > m_primitives {};
|
||||
|
||||
ModelBuilder() = delete;
|
||||
|
||||
ModelBuilder( Buffer& parent_vertex_buffer, Buffer& parent_index_buffer ) :
|
||||
m_vertex_buffer( parent_vertex_buffer ),
|
||||
m_index_buffer( parent_index_buffer )
|
||||
{}
|
||||
|
||||
void loadModel( const std::filesystem::path& filepath );
|
||||
void loadObj( const std::filesystem::path& filepath );
|
||||
void loadGltf( const std::filesystem::path& filepath );
|
||||
void loadVerts( std::vector< Vertex > verts, std::vector< std::uint32_t > indicies );
|
||||
};
|
||||
|
||||
} // namespace fgl::engine
|
||||
386
src/engine/model/builders/SceneBuilder.cpp
Normal file
386
src/engine/model/builders/SceneBuilder.cpp
Normal file
@@ -0,0 +1,386 @@
|
||||
//
|
||||
// Created by kj16609 on 5/18/24.
|
||||
//
|
||||
|
||||
#include "SceneBuilder.hpp"
|
||||
|
||||
#include "engine/model/Model.hpp"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#include "objectloaders/tiny_gltf.h"
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <engine/logging.hpp>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
SceneBuilder::SceneBuilder( Buffer& vertex_buffer, Buffer& index_buffer ) :
|
||||
m_vertex_buffer( vertex_buffer ),
|
||||
m_index_buffer( index_buffer )
|
||||
{}
|
||||
|
||||
int SceneBuilder::getTexcoordCount( const tinygltf::Primitive& prim ) const
|
||||
{
|
||||
int counter { 0 };
|
||||
for ( const auto& [ key, value ] : prim.attributes )
|
||||
{
|
||||
if ( key.starts_with( "TEXCOORD" ) ) ++counter;
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::vector< T > extractData( const tinygltf::Model& model, const tinygltf::Accessor& accessor )
|
||||
{
|
||||
if ( accessor.sparse.isSparse )
|
||||
{
|
||||
//Sparse loading required
|
||||
throw std::runtime_error( "Sparse loading not implemeneted" );
|
||||
}
|
||||
|
||||
const auto& buffer_view { model.bufferViews.at( accessor.bufferView ) };
|
||||
const auto& buffer { model.buffers.at( buffer_view.buffer ) };
|
||||
|
||||
std::vector< T > data {};
|
||||
data.reserve( accessor.count );
|
||||
|
||||
std::uint16_t copy_size { 0 };
|
||||
switch ( accessor.componentType )
|
||||
{
|
||||
default:
|
||||
throw std::runtime_error( "Unhandled access size" );
|
||||
case TINYGLTF_COMPONENT_TYPE_FLOAT:
|
||||
copy_size = 32 / 8;
|
||||
break;
|
||||
case TINYGLTF_COMPONENT_TYPE_BYTE:
|
||||
copy_size = 8 / 8;
|
||||
break;
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
|
||||
copy_size = 32 / 8;
|
||||
break;
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
|
||||
copy_size = 16 / 8;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( accessor.type )
|
||||
{
|
||||
default:
|
||||
throw std::runtime_error( "Unhandled access type" );
|
||||
case TINYGLTF_TYPE_VEC3:
|
||||
copy_size *= 3;
|
||||
break;
|
||||
case TINYGLTF_TYPE_VEC2:
|
||||
copy_size *= 2;
|
||||
break;
|
||||
case TINYGLTF_TYPE_SCALAR:
|
||||
copy_size *= 1;
|
||||
break;
|
||||
}
|
||||
|
||||
constexpr auto T_SIZE { sizeof( T ) };
|
||||
|
||||
if ( T_SIZE != copy_size )
|
||||
throw std::runtime_error(
|
||||
std::string( "Accessor copy values not matching sizeof(T): sizeof(" )
|
||||
+ std::string( typeid( T ).name() ) + ") == " + std::to_string( T_SIZE )
|
||||
+ " vs copy_size = " + std::to_string( copy_size ) );
|
||||
|
||||
const auto real_size { copy_size * accessor.count };
|
||||
|
||||
data.resize( accessor.count );
|
||||
|
||||
std::memcpy( data.data(), buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset, real_size );
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
std::vector< std::uint32_t > SceneBuilder::
|
||||
extractIndicies( const tinygltf::Primitive& prim, const tinygltf::Model& model )
|
||||
{
|
||||
const auto& indicies_accessor { model.accessors.at( prim.indices ) };
|
||||
|
||||
if ( indicies_accessor.componentType == TINYGLTF_COMPONENT_TYPE_INT )
|
||||
{
|
||||
return extractData< std::uint32_t >( model, indicies_accessor );
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: Figure out any time we can use a smaller indicies value instead of a 32 bit number all the time
|
||||
std::vector< std::uint32_t > indicies {};
|
||||
|
||||
const auto tmp { extractData< std::uint16_t >( model, indicies_accessor ) };
|
||||
|
||||
indicies.reserve( tmp.size() );
|
||||
|
||||
for ( const auto val : tmp ) indicies.emplace_back( val );
|
||||
|
||||
return indicies;
|
||||
}
|
||||
}
|
||||
|
||||
const tinygltf::Accessor& SceneBuilder::getAccessorForAttribute(
|
||||
const tinygltf::Primitive& prim, const tinygltf::Model& root, const std::string attrib ) const
|
||||
{
|
||||
return root.accessors.at( prim.attributes.at( attrib ) );
|
||||
}
|
||||
|
||||
Texture SceneBuilder::loadTexture( const tinygltf::Primitive& prim, const tinygltf::Model& root )
|
||||
{
|
||||
const auto mat_idx { prim.material };
|
||||
if ( mat_idx == -1 )
|
||||
{
|
||||
//There is no matrial for this
|
||||
throw std::runtime_error( "No material for primitive. One was expected" );
|
||||
}
|
||||
|
||||
const auto& material { root.materials[ mat_idx ] };
|
||||
|
||||
for ( const auto& [ key, value ] : material.values )
|
||||
{
|
||||
spdlog::debug( "Parsing texture for key {}", key );
|
||||
}
|
||||
|
||||
//TODO:
|
||||
throw std::runtime_error( "No material loader implemented" );
|
||||
}
|
||||
|
||||
std::vector< std::shared_ptr< Model > > SceneBuilder::getModels()
|
||||
{
|
||||
std::vector< std::shared_ptr< Model > > new_models { std::move( models ) };
|
||||
|
||||
return new_models;
|
||||
}
|
||||
|
||||
std::vector< glm::vec3 > SceneBuilder::
|
||||
extractPositionInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root )
|
||||
{
|
||||
const tinygltf::Accessor& accessor { getAccessorForAttribute( prim, root, "POSITION" ) };
|
||||
|
||||
return extractData< glm::vec3 >( root, accessor );
|
||||
}
|
||||
|
||||
std::vector< glm::vec3 > SceneBuilder::
|
||||
extractNormalInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root )
|
||||
{
|
||||
if ( !hasAttribute( prim, "NORMAL" ) ) return {};
|
||||
const tinygltf::Accessor& accessor { getAccessorForAttribute( prim, root, "NORMAL" ) };
|
||||
|
||||
return extractData< glm::vec3 >( root, accessor );
|
||||
}
|
||||
|
||||
std::vector< glm::vec2 > SceneBuilder::extractUVInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root )
|
||||
{
|
||||
spdlog::debug( "Extracting UV info" );
|
||||
|
||||
//TODO: Figure out how I can use multiple textures for various things.
|
||||
if ( !hasAttribute( prim, "TEXCOORD_0" ) ) return {};
|
||||
|
||||
const tinygltf::Accessor& accessor { getAccessorForAttribute( prim, root, "TEXCOORD_0" ) };
|
||||
|
||||
return extractData< glm::vec2 >( root, accessor );
|
||||
}
|
||||
|
||||
bool SceneBuilder::hasAttribute( const tinygltf::Primitive& prim, const std::string_view str )
|
||||
{
|
||||
return prim.attributes.contains( std::string( str ) );
|
||||
}
|
||||
|
||||
std::vector< Vertex > SceneBuilder::
|
||||
extractVertexInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root )
|
||||
{
|
||||
spdlog::debug( "Extracting vert info" );
|
||||
const auto pos { extractPositionInfo( prim, root ) };
|
||||
|
||||
std::vector< Vertex > verts {};
|
||||
|
||||
verts.reserve( pos.size() );
|
||||
|
||||
const std::vector< glm::vec3 > normals { extractNormalInfo( prim, root ) };
|
||||
|
||||
//TODO: If we don't have normals we likely will need to compute them ourselves.
|
||||
// I have no idea if this is actually going to be needed for us. But I might wanna implement it
|
||||
// anyways, Just in case.
|
||||
const bool has_normals { !normals.empty() };
|
||||
|
||||
const std::vector< glm::vec2 > uvs { extractUVInfo( prim, root ) };
|
||||
const bool has_uv { !uvs.empty() };
|
||||
|
||||
for ( std::size_t i = 0; i < pos.size(); ++i )
|
||||
{
|
||||
Vertex vert {};
|
||||
vert.m_position = pos[ i ];
|
||||
vert.m_normal = has_normals ? normals[ i ] : glm::vec3();
|
||||
vert.m_uv = has_uv ? uvs[ i ] : glm::vec2();
|
||||
vert.m_color = glm::vec3( 0.1f );
|
||||
verts.emplace_back( vert );
|
||||
}
|
||||
|
||||
spdlog::debug(
|
||||
"Found {} verts.\n\t- Has UV info: {}\n\t- Has normals: {}",
|
||||
verts.size(),
|
||||
has_uv ? "Yes" : "No",
|
||||
has_normals ? "Yes" : "No" );
|
||||
|
||||
return verts;
|
||||
}
|
||||
|
||||
Primitive SceneBuilder::loadPrimitive( const tinygltf::Primitive& prim, const tinygltf::Model& root )
|
||||
{
|
||||
std::string att_str;
|
||||
for ( const auto& attrib : prim.attributes )
|
||||
{
|
||||
att_str += "Attribute: " + attrib.first + "\n";
|
||||
}
|
||||
spdlog::debug( "Attributes for primitive:\n{}", att_str );
|
||||
|
||||
const bool has_normal { hasAttribute( prim, "NORMAL" ) };
|
||||
const bool has_position { hasAttribute( prim, "POSITION" ) };
|
||||
const bool has_texcoord { hasAttribute( prim, "TEXCOORD_0" ) };
|
||||
const int texcoord_count { has_texcoord ? getTexcoordCount( prim ) : 0 };
|
||||
|
||||
if ( !has_position ) throw std::runtime_error( "Failed to load model. Missing expected POSITION attribute" );
|
||||
|
||||
switch ( static_cast< PrimitiveMode >( prim.mode ) )
|
||||
{
|
||||
case POINTS:
|
||||
[[fallthrough]];
|
||||
case LINE:
|
||||
[[fallthrough]];
|
||||
case LINE_LOOP:
|
||||
[[fallthrough]];
|
||||
case LINE_STRIP:
|
||||
[[fallthrough]];
|
||||
case TRIS:
|
||||
[[fallthrough]];
|
||||
case TRI_STRIP:
|
||||
[[fallthrough]];
|
||||
case TRI_FAN:
|
||||
{
|
||||
std::vector< Vertex > verts { extractVertexInfo( prim, root ) };
|
||||
std::vector< std::uint32_t > indicies { extractIndicies( prim, root ) };
|
||||
|
||||
Primitive primitive_mesh { Primitive::fromVerts(
|
||||
std::move( verts ),
|
||||
static_cast< PrimitiveMode >( prim.mode ),
|
||||
std::move( indicies ),
|
||||
m_vertex_buffer,
|
||||
m_index_buffer ) };
|
||||
|
||||
if ( !has_texcoord ) return primitive_mesh;
|
||||
|
||||
primitive_mesh.m_texture = loadTexture( prim, root );
|
||||
|
||||
return primitive_mesh;
|
||||
}
|
||||
default:
|
||||
{
|
||||
spdlog::error( "Unsupported mode for primtiive loading: {}", prim.mode );
|
||||
throw std::runtime_error( "Unsupported mode for primitive loading" );
|
||||
}
|
||||
}
|
||||
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
OrientedBoundingBox< CoordinateSpace::Model > createModelBoundingBox( const std::vector< Primitive >& primitives )
|
||||
{
|
||||
if ( primitives.size() <= 0 ) return {};
|
||||
|
||||
OrientedBoundingBox< CoordinateSpace::Model > box { primitives.at( 0 ).m_bounding_box };
|
||||
|
||||
for ( std::uint64_t i = 1; i < primitives.size(); i++ ) box = box.combine( primitives[ i ].m_bounding_box );
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
std::shared_ptr< Model > SceneBuilder::loadModel( const int mesh_idx, const tinygltf::Model& root )
|
||||
{
|
||||
const auto mesh { root.meshes[ mesh_idx ] };
|
||||
const auto& primitives { mesh.primitives };
|
||||
|
||||
spdlog::debug( "Mesh idx {} has {} primitives", mesh_idx, primitives.size() );
|
||||
|
||||
std::vector< Primitive > finished_primitives {};
|
||||
|
||||
for ( const auto& prim : primitives )
|
||||
{
|
||||
Primitive primitive { loadPrimitive( prim, root ) };
|
||||
finished_primitives.emplace_back( std::move( primitive ) );
|
||||
}
|
||||
|
||||
spdlog::debug( "Finished loading model with {} primitives", finished_primitives.size() );
|
||||
|
||||
const auto bounding_box { createModelBoundingBox( finished_primitives ) };
|
||||
|
||||
return std::make_shared< Model >( Device::getInstance(), std::move( finished_primitives ), bounding_box );
|
||||
}
|
||||
|
||||
void SceneBuilder::handleNode( const int node_idx, const tinygltf::Model& root )
|
||||
{
|
||||
const auto& node { root.nodes[ node_idx ] };
|
||||
spdlog::debug( "Handling node: Index:{} Name:\"{}\"", node_idx, node.name );
|
||||
|
||||
const auto mesh_idx { node.mesh };
|
||||
const auto skin_idx { node.skin };
|
||||
|
||||
spdlog::debug( "Mesh IDX: {}", mesh_idx );
|
||||
spdlog::debug( "Skin IDX: {}", skin_idx );
|
||||
|
||||
std::shared_ptr< Model > model { loadModel( mesh_idx, root ) };
|
||||
|
||||
assert( model );
|
||||
|
||||
//TODO: Material.
|
||||
this->models.emplace_back( std::move( model ) );
|
||||
}
|
||||
|
||||
void SceneBuilder::handleScene( const tinygltf::Scene& scene, const tinygltf::Model& root )
|
||||
{
|
||||
spdlog::debug( "Handling scene: ", scene.name );
|
||||
|
||||
spdlog::debug( "Scene has {} nodes", scene.nodes.size() );
|
||||
for ( const auto node_idx : scene.nodes )
|
||||
{
|
||||
handleNode( node_idx, root );
|
||||
}
|
||||
}
|
||||
|
||||
void SceneBuilder::loadScene( const std::filesystem::path path )
|
||||
{
|
||||
if ( !std::filesystem::exists( path ) ) throw std::runtime_error( "Failed to find scene at filepath" );
|
||||
|
||||
tinygltf::TinyGLTF loader {};
|
||||
tinygltf::Model gltf_model {};
|
||||
|
||||
std::string err;
|
||||
std::string warn;
|
||||
|
||||
if ( !loader.LoadBinaryFromFile( &gltf_model, &err, &warn, path ) )
|
||||
{
|
||||
throw std::runtime_error( "Failed to load binary model" );
|
||||
}
|
||||
|
||||
if ( !err.empty() )
|
||||
{
|
||||
spdlog::error( "Error loading model {}: \"{}\"", path.string(), err );
|
||||
throw std::runtime_error( err );
|
||||
}
|
||||
|
||||
if ( !warn.empty() )
|
||||
{
|
||||
spdlog::warn( "Warning loading model {}: \"{}\"", path.string(), warn );
|
||||
}
|
||||
|
||||
const auto scenes { gltf_model.scenes };
|
||||
|
||||
for ( const auto& scene : scenes )
|
||||
{
|
||||
handleScene( scene, gltf_model );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fgl::engine
|
||||
75
src/engine/model/builders/SceneBuilder.hpp
Normal file
75
src/engine/model/builders/SceneBuilder.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// Created by kj16609 on 5/18/24.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
struct Vertex;
|
||||
class Model;
|
||||
struct Primitive;
|
||||
class Texture;
|
||||
class Buffer;
|
||||
} // namespace fgl::engine
|
||||
|
||||
namespace tinygltf
|
||||
{
|
||||
struct Scene;
|
||||
class Model;
|
||||
struct Primitive;
|
||||
struct Accessor;
|
||||
} // namespace tinygltf
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
class SceneBuilder
|
||||
{
|
||||
Buffer& m_vertex_buffer;
|
||||
Buffer& m_index_buffer;
|
||||
|
||||
std::vector< std::shared_ptr< Model > > models {};
|
||||
|
||||
void handleScene( const tinygltf::Scene& scene, const tinygltf::Model& root );
|
||||
void handleNode( const int node_idx, const tinygltf::Model& root );
|
||||
std::shared_ptr< Model > loadModel( const int mesh_idx, const tinygltf::Model& root );
|
||||
Primitive loadPrimitive( const tinygltf::Primitive& prim, const tinygltf::Model& model );
|
||||
|
||||
int getTexcoordCount( const tinygltf::Primitive& prim ) const;
|
||||
|
||||
std::vector< std::uint32_t > extractIndicies( const tinygltf::Primitive& prim, const tinygltf::Model& model );
|
||||
|
||||
std::vector< Vertex > extractVertexInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root );
|
||||
|
||||
std::vector< glm::vec3 > extractPositionInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root );
|
||||
|
||||
//! Returns an empty vector if no normals could be extracted
|
||||
std::vector< glm::vec3 > extractNormalInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root );
|
||||
|
||||
std::vector< glm::vec2 > extractUVInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root );
|
||||
|
||||
bool hasAttribute( const tinygltf::Primitive& prim, const std::string_view str );
|
||||
|
||||
const tinygltf::Accessor& getAccessorForAttribute(
|
||||
const tinygltf::Primitive& prim, const tinygltf::Model& root, const std::string attrib ) const;
|
||||
|
||||
Texture loadTexture( const tinygltf::Primitive& prim, const tinygltf::Model& root );
|
||||
|
||||
public:
|
||||
|
||||
std::vector< std::shared_ptr< Model > > getModels();
|
||||
|
||||
SceneBuilder() = delete;
|
||||
|
||||
SceneBuilder( Buffer& vertex_buffer, Buffer& index_buffer );
|
||||
|
||||
void loadScene( const std::filesystem::path path );
|
||||
};
|
||||
|
||||
} // namespace fgl::engine
|
||||
@@ -1,89 +1,87 @@
|
||||
//
|
||||
// Created by kj16609 on 2/5/24.
|
||||
// Created by kj16609 on 5/18/24.
|
||||
//
|
||||
|
||||
#include "Model.hpp"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#include "engine/image/Sampler.hpp"
|
||||
#include "objectloaders/tiny_gltf.h"
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include "ModelBuilder.hpp"
|
||||
#include "engine/descriptors/DescriptorSet.hpp"
|
||||
#include "engine/image/ImageView.hpp"
|
||||
#include "engine/image/Sampler.hpp"
|
||||
#include "engine/model/Primitive.hpp"
|
||||
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
|
||||
#include "engine/primitives/points/Coordinate.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
template < typename T >
|
||||
std::vector< T > extractData( const tinygltf::Model& model, const tinygltf::Accessor& accessor )
|
||||
{
|
||||
if ( accessor.sparse.isSparse )
|
||||
{
|
||||
//Sparse loading required
|
||||
|
||||
throw std::runtime_error( "Sparse loading not implemeneted" );
|
||||
}
|
||||
else
|
||||
|
||||
const auto& buffer_view { model.bufferViews.at( accessor.bufferView ) };
|
||||
const auto& buffer { model.buffers.at( buffer_view.buffer ) };
|
||||
|
||||
std::vector< T > data {};
|
||||
data.reserve( accessor.count );
|
||||
|
||||
std::uint16_t copy_size { 0 };
|
||||
switch ( accessor.componentType )
|
||||
{
|
||||
const auto& buffer_view { model.bufferViews.at( accessor.bufferView ) };
|
||||
const auto& buffer { model.buffers.at( buffer_view.buffer ) };
|
||||
|
||||
std::vector< T > data {};
|
||||
data.reserve( accessor.count );
|
||||
|
||||
std::uint16_t copy_size { 0 };
|
||||
switch ( accessor.componentType )
|
||||
{
|
||||
default:
|
||||
throw std::runtime_error( "Unhandled access size" );
|
||||
case TINYGLTF_COMPONENT_TYPE_FLOAT:
|
||||
copy_size = 32 / 8;
|
||||
break;
|
||||
case TINYGLTF_COMPONENT_TYPE_BYTE:
|
||||
copy_size = 8 / 8;
|
||||
break;
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
|
||||
copy_size = 32 / 8;
|
||||
break;
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
|
||||
copy_size = 16 / 8;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( accessor.type )
|
||||
{
|
||||
default:
|
||||
throw std::runtime_error( "Unhandled access type" );
|
||||
case TINYGLTF_TYPE_VEC3:
|
||||
copy_size *= 3;
|
||||
break;
|
||||
case TINYGLTF_TYPE_VEC2:
|
||||
copy_size *= 2;
|
||||
break;
|
||||
case TINYGLTF_TYPE_SCALAR:
|
||||
copy_size *= 1;
|
||||
break;
|
||||
}
|
||||
|
||||
constexpr auto T_SIZE { sizeof( T ) };
|
||||
|
||||
if ( T_SIZE != copy_size )
|
||||
throw std::runtime_error(
|
||||
std::string( "Accessor copy values not matching sizeof(T): sizeof(" )
|
||||
+ std::string( typeid( T ).name() ) + ") == " + std::to_string( T_SIZE )
|
||||
+ " vs copy_size = " + std::to_string( copy_size ) );
|
||||
|
||||
const auto real_size { copy_size * accessor.count };
|
||||
|
||||
data.resize( accessor.count );
|
||||
|
||||
std::memcpy( data.data(), buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset, real_size );
|
||||
|
||||
return data;
|
||||
default:
|
||||
throw std::runtime_error( "Unhandled access size" );
|
||||
case TINYGLTF_COMPONENT_TYPE_FLOAT:
|
||||
copy_size = 32 / 8;
|
||||
break;
|
||||
case TINYGLTF_COMPONENT_TYPE_BYTE:
|
||||
copy_size = 8 / 8;
|
||||
break;
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
|
||||
copy_size = 32 / 8;
|
||||
break;
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
|
||||
copy_size = 16 / 8;
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( accessor.type )
|
||||
{
|
||||
default:
|
||||
throw std::runtime_error( "Unhandled access type" );
|
||||
case TINYGLTF_TYPE_VEC3:
|
||||
copy_size *= 3;
|
||||
break;
|
||||
case TINYGLTF_TYPE_VEC2:
|
||||
copy_size *= 2;
|
||||
break;
|
||||
case TINYGLTF_TYPE_SCALAR:
|
||||
copy_size *= 1;
|
||||
break;
|
||||
}
|
||||
|
||||
constexpr auto T_SIZE { sizeof( T ) };
|
||||
|
||||
if ( T_SIZE != copy_size )
|
||||
throw std::runtime_error(
|
||||
std::string( "Accessor copy values not matching sizeof(T): sizeof(" )
|
||||
+ std::string( typeid( T ).name() ) + ") == " + std::to_string( T_SIZE )
|
||||
+ " vs copy_size = " + std::to_string( copy_size ) );
|
||||
|
||||
const auto real_size { copy_size * accessor.count };
|
||||
|
||||
data.resize( accessor.count );
|
||||
|
||||
std::memcpy( data.data(), buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset, real_size );
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void ModelBuilder::loadGltf( const std::filesystem::path& filepath )
|
||||
@@ -125,14 +123,11 @@ namespace fgl::engine
|
||||
}
|
||||
else if ( indicies_accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT )
|
||||
{
|
||||
auto tmp { extractData< std::uint16_t >( model, model.accessors.at( primitive.indices ) ) };
|
||||
const auto tmp { extractData< std::uint16_t >( model, model.accessors.at( primitive.indices ) ) };
|
||||
|
||||
indicies_data.reserve( tmp.size() );
|
||||
|
||||
for ( auto& val : tmp )
|
||||
{
|
||||
indicies_data.emplace_back( val );
|
||||
}
|
||||
for ( auto& val : tmp ) indicies_data.emplace_back( val );
|
||||
}
|
||||
|
||||
//Load positions
|
||||
@@ -276,9 +271,11 @@ namespace fgl::engine
|
||||
Device::getInstance().endSingleTimeCommands( cmd );
|
||||
tex.dropStaging();
|
||||
|
||||
Primitive prim {
|
||||
std::move( vertex_buffer ), std::move( index_buffer ), bounding_box, std::move( tex )
|
||||
};
|
||||
Primitive prim { std::move( vertex_buffer ),
|
||||
std::move( index_buffer ),
|
||||
bounding_box,
|
||||
std::move( tex ),
|
||||
PrimitiveMode::TRIS };
|
||||
|
||||
m_primitives.emplace_back( std::move( prim ) );
|
||||
|
||||
@@ -288,7 +285,9 @@ namespace fgl::engine
|
||||
else
|
||||
std::cout << "No material" << std::endl;
|
||||
|
||||
Primitive prim { std::move( vertex_buffer ), std::move( index_buffer ), bounding_box };
|
||||
Primitive prim {
|
||||
std::move( vertex_buffer ), std::move( index_buffer ), bounding_box, PrimitiveMode::TRIS
|
||||
};
|
||||
|
||||
m_primitives.emplace_back( std::move( prim ) );
|
||||
}
|
||||
@@ -313,5 +312,4 @@ namespace fgl::engine
|
||||
std::cout << "Finished loading model: " << filepath << std::endl;
|
||||
}
|
||||
|
||||
|
||||
} // namespace fgl::engine
|
||||
@@ -1,20 +1,22 @@
|
||||
//
|
||||
// Created by kj16609 on 2/5/24.
|
||||
// Created by kj16609 on 5/18/24.
|
||||
//
|
||||
|
||||
#include "Model.hpp"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#include "objectloaders/tiny_obj_loader.h"
|
||||
#include <objectloaders/tiny_obj_loader.h>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include "Vertex.hpp"
|
||||
#include <unordered_map>
|
||||
|
||||
#include "ModelBuilder.hpp"
|
||||
#include "engine/model/Primitive.hpp"
|
||||
#include "engine/model/Vertex.hpp"
|
||||
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
void ModelBuilder::loadObj( const std::filesystem::path& filepath )
|
||||
{
|
||||
m_primitives.clear();
|
||||
@@ -99,7 +101,8 @@ namespace fgl::engine
|
||||
[[maybe_unused]] auto& itter = m_primitives.emplace_back(
|
||||
VertexBufferSuballocation( m_vertex_buffer, std::move( verts ) ),
|
||||
IndexBufferSuballocation( m_index_buffer, std::move( indicies ) ),
|
||||
bounding_box );
|
||||
bounding_box,
|
||||
PrimitiveMode::TRIS );
|
||||
|
||||
std::cout << unique_verts.size() << " unique verts" << std::endl;
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace fgl::engine
|
||||
info.rasterization_info.rasterizerDiscardEnable = VK_FALSE;
|
||||
info.rasterization_info.polygonMode = vk::PolygonMode::eFill;
|
||||
info.rasterization_info.cullMode = vk::CullModeFlagBits::eBack;
|
||||
info.rasterization_info.frontFace = vk::FrontFace::eClockwise;
|
||||
info.rasterization_info.frontFace = vk::FrontFace::eCounterClockwise;
|
||||
info.rasterization_info.depthBiasEnable = VK_FALSE;
|
||||
info.rasterization_info.depthBiasConstantFactor = 0.0f;
|
||||
info.rasterization_info.depthBiasClamp = 0.0f;
|
||||
@@ -122,6 +122,11 @@ namespace fgl::engine
|
||||
info.color_blend_info.attachmentCount = static_cast< std::uint32_t >( info.color_blend_attachment.size() );
|
||||
}
|
||||
|
||||
void PipelineConfigInfo::disableCulling( PipelineConfigInfo& info )
|
||||
{
|
||||
info.rasterization_info.cullMode = vk::CullModeFlagBits::eNone;
|
||||
}
|
||||
|
||||
PipelineConfigInfo::PipelineConfigInfo( vk::RenderPass pass )
|
||||
{
|
||||
render_pass = pass;
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace fgl::engine
|
||||
static void defaultConfig( PipelineConfigInfo& info );
|
||||
static void enableAlphaBlending( PipelineConfigInfo& config );
|
||||
static void addColorAttachmentConfig( PipelineConfigInfo& info );
|
||||
static void disableCulling( PipelineConfigInfo& info );
|
||||
};
|
||||
|
||||
} // namespace fgl::engine
|
||||
@@ -2,11 +2,12 @@
|
||||
// Created by kj16609 on 3/13/24.
|
||||
//
|
||||
|
||||
#ifndef SHADER_HPP
|
||||
#define SHADER_HPP
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "engine/logging.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
@@ -60,7 +61,10 @@ namespace fgl::engine
|
||||
stage_info.module = shader_module;
|
||||
}
|
||||
else
|
||||
{
|
||||
spdlog::critical( "Failed to load shader module {}. Path not found", path.string() );
|
||||
throw std::runtime_error( "Failed to load shader module. Path not found" );
|
||||
}
|
||||
}
|
||||
|
||||
ShaderHandle( const ShaderHandle& other ) = delete;
|
||||
@@ -152,5 +156,3 @@ namespace fgl::engine
|
||||
};
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
#endif //SHADER_HPP
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <numbers>
|
||||
#include <utility>
|
||||
|
||||
#include "engine/primitives/matricies/RotationMatrix.hpp"
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace fgl::engine
|
||||
//TransformComponent is always in world space
|
||||
struct TransformComponent
|
||||
{
|
||||
WorldCoordinate translation { constants::DEFAULT_VEC3 };
|
||||
WorldCoordinate translation { constants::WORLD_CENTER };
|
||||
glm::vec3 scale { 1.0f, 1.0f, 1.0f };
|
||||
|
||||
Rotation rotation { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
@@ -118,8 +118,14 @@ namespace fgl::engine
|
||||
{
|
||||
if ( oobb.rotation == Rotation() ) // If default rotation then we can simply just take it as the box is
|
||||
{
|
||||
assert( oobb.topRightForward().vec() != constants::DEFAULT_VEC3 );
|
||||
assert( oobb.bottomLeftBack().vec() != -constants::DEFAULT_VEC3 );
|
||||
|
||||
m_top_right_forward = oobb.topRightForward();
|
||||
m_bottom_left_back = oobb.bottomLeftBack();
|
||||
|
||||
assert( m_top_right_forward.vec() != constants::DEFAULT_VEC3 );
|
||||
assert( m_bottom_left_back.vec() != -constants::DEFAULT_VEC3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -134,9 +140,10 @@ namespace fgl::engine
|
||||
m_bottom_left_back.y = std::min( m_bottom_left_back.y, point.y );
|
||||
m_bottom_left_back.z = std::min( m_bottom_left_back.z, point.z );
|
||||
}
|
||||
|
||||
assert( m_top_right_forward.vec() != constants::DEFAULT_VEC3 );
|
||||
assert( m_bottom_left_back.vec() != -constants::DEFAULT_VEC3 );
|
||||
}
|
||||
assert( m_top_right_forward.vec() != constants::DEFAULT_VEC3 );
|
||||
assert( m_bottom_left_back.vec() != -constants::DEFAULT_VEC3 );
|
||||
}
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
|
||||
#include "OrientedBoundingBox.hpp"
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "engine/logging.hpp"
|
||||
#include "engine/model/Vertex.hpp"
|
||||
#include "engine/primitives/lines/LineSegment.hpp"
|
||||
#include "engine/primitives/points/Coordinate.hpp"
|
||||
@@ -235,6 +238,7 @@ namespace fgl::engine
|
||||
|
||||
OrientedBoundingBox< CoordinateSpace::Model > generateBoundingFromVerts( const std::vector< Vertex >& verts )
|
||||
{
|
||||
spdlog::debug( "Generating bounding box for {} verts", verts.size() );
|
||||
// neg (min)
|
||||
glm::vec3 top_right_forward { verts[ 0 ].m_position };
|
||||
// pos (max)
|
||||
|
||||
@@ -39,7 +39,10 @@ namespace fgl::engine
|
||||
middle( pos ),
|
||||
scale( inital_scale ),
|
||||
rotation( inital_rotation )
|
||||
{}
|
||||
{
|
||||
assert( pos.vec() != constants::DEFAULT_VEC3 );
|
||||
assert( inital_scale != constants::DEFAULT_VEC3 );
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -70,10 +73,14 @@ namespace fgl::engine
|
||||
OrientedBoundingBox< EvolvedType< MType >() >
|
||||
operator*( const Matrix< MType > matrix, const OrientedBoundingBox< CType > bounding_box )
|
||||
{
|
||||
assert( bounding_box.middle.vec() != constants::DEFAULT_VEC3 );
|
||||
assert( bounding_box.scale != glm::vec3( 0.0f ) );
|
||||
|
||||
const Coordinate< EvolvedType< MType >() > new_middle { matrix * bounding_box.middle };
|
||||
const glm::vec3 new_scale { matrix * glm::vec4( bounding_box.scale, 0.0f ) };
|
||||
//TODO: Fix this stupid rot shit
|
||||
const Rotation new_rot { bounding_box.rotation };
|
||||
|
||||
return OrientedBoundingBox< EvolvedType< MType >() >( new_middle, new_scale, new_rot );
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "LineBase.hpp"
|
||||
|
||||
#include <glm/geometric.hpp>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
|
||||
@@ -41,21 +41,21 @@ namespace fgl::engine
|
||||
|
||||
explicit Coordinate( const Vector vector );
|
||||
|
||||
float& up() { return z; }
|
||||
inline float& up() { return z; }
|
||||
|
||||
float up() const { return z; }
|
||||
inline float up() const { return z; }
|
||||
|
||||
float& right() { return x; }
|
||||
inline float& right() { return x; }
|
||||
|
||||
float right() const { return x; }
|
||||
inline float right() const { return x; }
|
||||
|
||||
float& forward() { return y; }
|
||||
inline float& forward() { return y; }
|
||||
|
||||
float forward() const { return y; }
|
||||
inline float forward() const { return y; }
|
||||
|
||||
glm::vec3& vec() { return static_cast< glm::vec3& >( *this ); }
|
||||
inline glm::vec3& vec() { return static_cast< glm::vec3& >( *this ); }
|
||||
|
||||
const glm::vec3& vec() const { return static_cast< const glm::vec3& >( *this ); }
|
||||
inline const glm::vec3& vec() const { return static_cast< const glm::vec3& >( *this ); }
|
||||
|
||||
Coordinate operator+( const Vector other ) const;
|
||||
Coordinate operator-( const Vector other ) const;
|
||||
@@ -82,10 +82,16 @@ namespace fgl::engine
|
||||
|
||||
static_assert( sizeof( glm::vec3 ) == sizeof( ModelCoordinate ) );
|
||||
|
||||
template < fgl::engine::CoordinateSpace CType >
|
||||
::std::ostream& operator<<( ::std::ostream& os, const fgl::engine::Coordinate< CType > coordinate )
|
||||
template < CoordinateSpace CType >
|
||||
inline ::std::ostream& operator<<( ::std::ostream& os, const Coordinate< CType > coordinate )
|
||||
{
|
||||
return os << "(" << coordinate.x << ", " << coordinate.y << ", " << coordinate.z << ")";
|
||||
}
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
inline double distance( const Coordinate< CType >& p1, const Coordinate< CType >& p2 )
|
||||
{
|
||||
return length( p1.vec() - p2.vec() );
|
||||
}
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glm/geometric.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include "engine/primitives/CoordinateSpace.hpp"
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "engine/logging.hpp"
|
||||
|
||||
PFN_vkCreateDebugUtilsMessengerEXT pfnVkCreateDebugUtilsMessengerEXT { nullptr };
|
||||
PFN_vkDestroyDebugUtilsMessengerEXT pfnVkDestroyDebugUtilsMessengerEXT { nullptr };
|
||||
PFN_vkSetDebugUtilsObjectNameEXT pfnVkSetDebugUtilsObjectNameEXT { nullptr };
|
||||
@@ -19,6 +21,22 @@ static VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback(
|
||||
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
||||
[[maybe_unused]] void* pUserData )
|
||||
{
|
||||
using Bits = VkDebugUtilsMessageSeverityFlagBitsEXT;
|
||||
|
||||
if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT )
|
||||
{
|
||||
spdlog::info( pCallbackData->pMessage );
|
||||
}
|
||||
if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT )
|
||||
{
|
||||
spdlog::warn( pCallbackData->pMessage );
|
||||
}
|
||||
if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT )
|
||||
{
|
||||
spdlog::error( pCallbackData->pMessage );
|
||||
std::abort();
|
||||
}
|
||||
|
||||
if ( pCallbackData->flags
|
||||
& ( VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
|
||||
| VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT ) )
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace fgl::engine
|
||||
PipelineConfigInfo composition_info { render_pass };
|
||||
PipelineConfigInfo::addColorAttachmentConfig( composition_info );
|
||||
PipelineConfigInfo::disableVertexInput( composition_info );
|
||||
PipelineConfigInfo::disableCulling( composition_info );
|
||||
composition_info.subpass = 1;
|
||||
|
||||
m_pipeline = std::make_unique< CompositionPipeline >( Device::getInstance(), composition_info );
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "CullingSystem.hpp"
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <tracy/TracyC.h>
|
||||
|
||||
#include "engine/FrameInfo.hpp"
|
||||
|
||||
@@ -16,7 +16,10 @@ namespace fgl::engine
|
||||
{
|
||||
|
||||
std::pair< std::vector< vk::DrawIndexedIndirectCommand >, std::vector< ModelMatrixInfo > > getDrawCallsFromTree(
|
||||
OctTreeNode& root, const Frustum< CoordinateSpace::World >& frustum, const GameObjectFlagType flags )
|
||||
OctTreeNode& root,
|
||||
const Frustum< CoordinateSpace::World >& frustum,
|
||||
const GameObjectFlagType flags,
|
||||
const GameObjectFilterOptions options )
|
||||
{
|
||||
ZoneScoped;
|
||||
std::unordered_map< DrawKey, DrawPair > draw_pairs {};
|
||||
@@ -34,15 +37,24 @@ namespace fgl::engine
|
||||
|
||||
// debug::world::drawBoundingBox( obj.getBoundingBox() );
|
||||
|
||||
for ( const auto& primitive : obj.m_model->m_primitives )
|
||||
for ( const Primitive& primitive : obj.m_model->m_primitives )
|
||||
{
|
||||
assert( primitive.m_texture );
|
||||
//assert( primitive.m_texture );
|
||||
const ModelMatrixInfo matrix_info { .model_matrix = obj.m_transform.mat4(),
|
||||
.texture_idx = primitive.m_texture->getID() };
|
||||
.texture_idx = primitive.getTextureID() };
|
||||
|
||||
const auto key {
|
||||
std::make_pair( primitive.m_texture->getID(), primitive.m_index_buffer.getOffset() )
|
||||
};
|
||||
// If the textureless flag is on and we have a texture then skip the primitive.c
|
||||
if ( options & TEXTURELESS )
|
||||
{
|
||||
if ( primitive.m_texture.has_value() ) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Flag is not present
|
||||
if ( !primitive.m_texture.has_value() ) continue;
|
||||
}
|
||||
|
||||
const auto key { std::make_pair( matrix_info.texture_idx, primitive.m_index_buffer.getOffset() ) };
|
||||
|
||||
assert( primitive.m_index_buffer.size() > 0 );
|
||||
|
||||
|
||||
@@ -28,7 +28,10 @@ namespace fgl::engine
|
||||
}
|
||||
|
||||
std::pair< std::vector< vk::DrawIndexedIndirectCommand >, std::vector< ModelMatrixInfo > > getDrawCallsFromTree(
|
||||
OctTreeNode& root, const Frustum< CoordinateSpace::World >& frustum, const GameObjectFlagType flags );
|
||||
OctTreeNode& root,
|
||||
const Frustum< CoordinateSpace::World >& frustum,
|
||||
const GameObjectFlagType flags,
|
||||
const GameObjectFilterOptions options = NONE );
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
|
||||
@@ -36,8 +36,14 @@ namespace fgl::engine
|
||||
|
||||
info.subpass = 0;
|
||||
|
||||
m_pipeline = std::make_unique< Pipeline >( m_device, info );
|
||||
m_pipeline->setDebugName( "Entity pipeline" );
|
||||
//m_pipeline = std::make_unique< Pipeline >( m_device, info );
|
||||
//m_pipeline->setDebugName( "Entity pipeline" );
|
||||
|
||||
m_standard_pipeline = std::make_unique< StandardPipeline >( m_device, info );
|
||||
m_textured_pipeline = std::make_unique< TexturedPipeline >( m_device, info );
|
||||
|
||||
m_standard_pipeline->setDebugName( "Standard entity pipeline" );
|
||||
m_textured_pipeline->setDebugName( "Textured entity pipeline" );
|
||||
|
||||
using namespace fgl::literals::size_literals;
|
||||
|
||||
@@ -49,10 +55,14 @@ namespace fgl::engine
|
||||
vk::CommandBuffer& EntityRendererSystem::setupSystem( FrameInfo& info )
|
||||
{
|
||||
auto& command_buffer { info.command_buffer };
|
||||
m_pipeline->bind( command_buffer );
|
||||
|
||||
m_pipeline->bindDescriptor( command_buffer, 0, info.global_descriptor_set );
|
||||
m_pipeline->bindDescriptor( command_buffer, 1, Texture::getTextureDescriptorSet() );
|
||||
//This function becomes a dummy since we have multiple pipelines.
|
||||
//We will instead bind the pipeline and descriptors for each stage of this pass.
|
||||
|
||||
//m_pipeline->bind( command_buffer );
|
||||
|
||||
//m_pipeline->bindDescriptor( command_buffer, 0, info.global_descriptor_set );
|
||||
//m_pipeline->bindDescriptor( command_buffer, 1, Texture::getTextureDescriptorSet() );
|
||||
|
||||
return command_buffer;
|
||||
}
|
||||
@@ -63,6 +73,10 @@ namespace fgl::engine
|
||||
auto& command_buffer { setupSystem( info ) };
|
||||
TracyVkZone( info.tracy_ctx, command_buffer, "Render entities" );
|
||||
|
||||
texturelessPass( info );
|
||||
//texturedPass( info );
|
||||
|
||||
/*
|
||||
auto [ draw_commands, model_matricies ] =
|
||||
getDrawCallsFromTree( info.game_objects, info.camera_frustum, IS_VISIBLE | IS_ENTITY );
|
||||
|
||||
@@ -101,6 +115,51 @@ namespace fgl::engine
|
||||
|
||||
command_buffer.drawIndexedIndirect(
|
||||
draw_params->getVkBuffer(), draw_params->getOffset(), draw_params->size(), draw_params->stride() );
|
||||
*/
|
||||
}
|
||||
|
||||
void EntityRendererSystem::texturelessPass( FrameInfo& info )
|
||||
{
|
||||
ZoneScopedN( "Textureless pass" );
|
||||
auto& command_buffer { info.command_buffer };
|
||||
TracyVkZone( info.tracy_ctx, command_buffer, "Render textureless entities" );
|
||||
|
||||
//Bind pipeline
|
||||
m_standard_pipeline->bind( command_buffer );
|
||||
|
||||
//Bind only descriptor we need.
|
||||
m_standard_pipeline
|
||||
->bindDescriptor( command_buffer, GlobalDescriptorSet::m_set_idx, info.global_descriptor_set );
|
||||
|
||||
//Get all commands for drawing anything without a texture
|
||||
auto [ draw_commands, model_matricies ] =
|
||||
getDrawCallsFromTree( info.game_objects, info.camera_frustum, IS_VISIBLE | IS_ENTITY, TEXTURELESS );
|
||||
|
||||
//TODO: Filter Textureless models (#6)
|
||||
|
||||
if ( draw_commands.size() == 0 ) return;
|
||||
|
||||
auto& model_matrix_info_buffer { m_simple_model_matrix_info_buffers[ info.frame_idx ] };
|
||||
|
||||
model_matrix_info_buffer =
|
||||
std::make_unique< ModelMatrixInfoBufferSuballocation >( info.model_matrix_info_buffer, model_matricies );
|
||||
|
||||
auto& draw_parameter_buffer { m_draw_simple_parameter_buffers[ info.frame_idx ] };
|
||||
|
||||
draw_parameter_buffer =
|
||||
std::make_unique< DrawParameterBufferSuballocation >( info.draw_parameter_buffer, draw_commands );
|
||||
|
||||
const std::vector< vk::Buffer > vert_buffers { m_vertex_buffer->getVkBuffer(),
|
||||
model_matrix_info_buffer->getVkBuffer() };
|
||||
|
||||
command_buffer.bindVertexBuffers( 0, vert_buffers, { 0, model_matrix_info_buffer->getOffset() } );
|
||||
command_buffer.bindIndexBuffer( m_index_buffer->getVkBuffer(), 0, vk::IndexType::eUint32 );
|
||||
|
||||
command_buffer.drawIndexedIndirect(
|
||||
draw_parameter_buffer->getVkBuffer(),
|
||||
draw_parameter_buffer->getOffset(),
|
||||
draw_parameter_buffer->size(),
|
||||
draw_parameter_buffer->stride() );
|
||||
}
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "engine/GameObject.hpp"
|
||||
#include "engine/descriptors/DescriptorSetCollection.hpp"
|
||||
#include "engine/model/Model.hpp"
|
||||
#include "engine/pipeline/PipelineT.hpp"
|
||||
#include "engine/rendering/SwapChain.hpp"
|
||||
#include "engine/systems/modelRendering/StandardPipeline.hpp"
|
||||
#include "engine/systems/modelRendering/TexturedPipeline.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
@@ -23,6 +23,7 @@ namespace fgl::engine
|
||||
{
|
||||
Device& m_device;
|
||||
|
||||
/*
|
||||
using VertexShader = VertexShaderT< "shaders/gbuffer.vert.spv" >;
|
||||
using FragmentShader = FragmentShaderT< "shaders/gbuffer.frag.spv" >;
|
||||
using Shaders = ShaderCollection< VertexShader, FragmentShader >;
|
||||
@@ -32,6 +33,13 @@ namespace fgl::engine
|
||||
using Pipeline = PipelineT< Shaders, DescriptorSets >;
|
||||
|
||||
std::unique_ptr< Pipeline > m_pipeline {};
|
||||
*/
|
||||
|
||||
//! Standard pipeline for textureless models
|
||||
std::unique_ptr< StandardPipeline > m_standard_pipeline {};
|
||||
|
||||
//! Pipeline for basic textured models (Single texture)
|
||||
std::unique_ptr< TexturedPipeline > m_textured_pipeline {};
|
||||
|
||||
std::unique_ptr< Buffer > m_vertex_buffer { nullptr };
|
||||
std::unique_ptr< Buffer > m_index_buffer { nullptr };
|
||||
@@ -40,11 +48,16 @@ namespace fgl::engine
|
||||
|
||||
using ModelMatrixInfoBufferSuballocation = HostVector< ModelMatrixInfo >;
|
||||
|
||||
std::array< std::unique_ptr< DrawParameterBufferSuballocation >, SwapChain::MAX_FRAMES_IN_FLIGHT >
|
||||
m_draw_parameter_buffers {};
|
||||
template < typename T >
|
||||
using PerFrameArray = std::array< T, SwapChain::MAX_FRAMES_IN_FLIGHT >;
|
||||
|
||||
std::array< std::unique_ptr< ModelMatrixInfoBufferSuballocation >, SwapChain::MAX_FRAMES_IN_FLIGHT >
|
||||
m_model_matrix_info_buffers {};
|
||||
// Simple parameter buffers
|
||||
PerFrameArray< std::unique_ptr< DrawParameterBufferSuballocation > > m_draw_simple_parameter_buffers {};
|
||||
PerFrameArray< std::unique_ptr< ModelMatrixInfoBufferSuballocation > > m_simple_model_matrix_info_buffers {};
|
||||
|
||||
// Textured parameter buffers
|
||||
PerFrameArray< std::unique_ptr< DrawParameterBufferSuballocation > > m_draw_textured_parameter_buffers {};
|
||||
PerFrameArray< std::unique_ptr< ModelMatrixInfoBufferSuballocation > > m_textured_model_matrix_info_buffers {};
|
||||
|
||||
void initVertexBuffer( std::uint32_t size )
|
||||
{
|
||||
@@ -71,6 +84,8 @@ namespace fgl::engine
|
||||
Buffer& getIndexBuffer() { return *m_index_buffer; }
|
||||
|
||||
void pass( FrameInfo& info );
|
||||
void texturelessPass( FrameInfo& info );
|
||||
void texturedPass( FrameInfo& info );
|
||||
|
||||
EntityRendererSystem( Device& device, VkRenderPass render_pass );
|
||||
~EntityRendererSystem() = default;
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
// Created by kj16609 on 3/11/24.
|
||||
//
|
||||
|
||||
#ifndef GAME_CONCEPTS_HPP
|
||||
#define GAME_CONCEPTS_HPP
|
||||
#pragma once
|
||||
|
||||
#include <concepts>
|
||||
|
||||
namespace vk
|
||||
{
|
||||
@@ -37,5 +38,3 @@ namespace fgl::engine
|
||||
};
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
#endif //GAME_CONCEPTS_HPP
|
||||
|
||||
23
src/engine/systems/modelRendering/StandardPipeline.hpp
Normal file
23
src/engine/systems/modelRendering/StandardPipeline.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Created by kj16609 on 5/24/24.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include "engine/FrameInfo.hpp"
|
||||
#include "engine/descriptors/DescriptorSetCollection.hpp"
|
||||
#include "engine/pipeline/PipelineT.hpp"
|
||||
#include "engine/pipeline/Shader.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
using StandardPipelineVertexShader = VertexShaderT< "shaders/textureless-gbuffer.vert.spv" >;
|
||||
using StandardPipelineFragShader = FragmentShaderT< "shaders/textureless-gbuffer.frag.spv" >;
|
||||
using StandardPipelineShaders = ShaderCollection< StandardPipelineVertexShader, StandardPipelineFragShader >;
|
||||
|
||||
using StandardPipelineDescriptorSets = DescriptorSetCollection< GlobalDescriptorSet >;
|
||||
|
||||
//! The standard pipeline is used for models without any form of texturing. They instead rely on Vertex coloring. A UV map is **NOT** expected
|
||||
using StandardPipeline = PipelineT< StandardPipelineShaders, StandardPipelineDescriptorSets >;
|
||||
|
||||
} // namespace fgl::engine
|
||||
23
src/engine/systems/modelRendering/TexturedPipeline.hpp
Normal file
23
src/engine/systems/modelRendering/TexturedPipeline.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Created by kj16609 on 5/24/24.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include "engine/FrameInfo.hpp"
|
||||
#include "engine/descriptors/DescriptorSetCollection.hpp"
|
||||
#include "engine/pipeline/PipelineT.hpp"
|
||||
#include "engine/pipeline/Shader.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
using TexturedPipelineVertexShader = VertexShaderT< "shaders/textured-gbuffer.vert.spv" >;
|
||||
using TexturedPipelineFragShader = FragmentShaderT< "shaders/textured-gbuffer.frag.spv" >;
|
||||
using TexturedPipelineShaders = ShaderCollection< TexturedPipelineVertexShader, TexturedPipelineFragShader >;
|
||||
|
||||
using TexturedPipelineDescriptorSets = DescriptorSetCollection< GlobalDescriptorSet, TextureDescriptorSet >;
|
||||
|
||||
//! The standard pipeline is used for models without any form of texturing. They instead rely on Vertex coloring. A UV map is **NOT** expected
|
||||
using TexturedPipeline = PipelineT< TexturedPipelineShaders, TexturedPipelineDescriptorSets >;
|
||||
|
||||
} // namespace fgl::engine
|
||||
13
src/engine/systems/modelRendering/pipelines.md
Normal file
13
src/engine/systems/modelRendering/pipelines.md
Normal file
@@ -0,0 +1,13 @@
|
||||
| Name | Textured | Normal Textured |
|
||||
|------------------|----------|-----------------|
|
||||
| StandardPipeline | [ ] | [ ] |
|
||||
| TexturedPipeline | [x] | [ ] |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace fgl::engine
|
||||
[[nodiscard]] Texture( const std::vector< std::byte >& data, const int x, const int y, const int channels );
|
||||
[[nodiscard]] Texture( const std::vector< std::byte >& data, const vk::Extent2D extent, const int channels );
|
||||
|
||||
Texture( const Texture& ) = delete;
|
||||
Texture( const Texture& ) = default;
|
||||
Texture& operator=( const Texture& ) = delete;
|
||||
|
||||
Texture( Texture&& other ) = default;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <engine/FrameInfo.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
#include "engine/debug/drawers.hpp"
|
||||
#include "engine/model/Model.hpp"
|
||||
@@ -208,6 +209,7 @@ namespace fgl::engine
|
||||
else
|
||||
{
|
||||
objects.emplace_back( std::move( obj ) );
|
||||
spdlog::info( "Added object" );
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include <bitset>
|
||||
#include <functional>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "engine/GameObject.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
@@ -48,6 +48,10 @@ Index of this file:
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
|
||||
// Configuration file with compile-time options
|
||||
// (edit imconfig.h or '#define IMGUI_USER_CONFIG "myfilename.h" from your build system)
|
||||
@@ -5346,3 +5350,5 @@ enum ImGuiModFlags_
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
Reference in New Issue
Block a user