Implement extra render outputs for metallic and emissives
This commit is contained in:
@@ -13,7 +13,7 @@ enable_testing()
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_MESSAGE_LOG_LEVEL DEBUG CACHE STRING "CMake messaging level")
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
|
||||
set(GLM_ENABLE_CXX_20 ON)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/glm)
|
||||
@@ -209,7 +209,7 @@ namespace fgl::engine::gui
|
||||
camera.getSwapchain().g_buffer_composite_img[ frame_index ]->drawImGui( target_size );
|
||||
break;
|
||||
case Albedo:
|
||||
camera.getSwapchain().g_buffer_albedo_img[ frame_index ]->drawImGui( target_size );
|
||||
camera.getSwapchain().g_buffer_color_img[ frame_index ]->drawImGui( target_size );
|
||||
break;
|
||||
case Normal:
|
||||
camera.getSwapchain().g_buffer_normal_img[ frame_index ]->drawImGui( target_size );
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#define FGL_DELETE_ALL_Ro5( ClassName ) \
|
||||
FGL_DELETE_DEFAULT_CTOR( ClassName ) FGL_DELETE_COPY( ClassName ) FGL_DELETE_MOVE( ClassName )
|
||||
|
||||
#define FGL_PACKED __attribute__(( packed ))
|
||||
#define FGL_PACKED_ALIGNED( al ) __attribute__(( packed, aligned( al ) ))
|
||||
#define FGL_FLATTEN [[gnu::flatten]]
|
||||
#define FGL_ARTIFICIAL [[gnu::artificial]]
|
||||
#define FGL_HOT [[gnu::hot]]
|
||||
|
||||
@@ -53,12 +53,14 @@ namespace fgl::engine
|
||||
|
||||
constexpr vk::ShaderStageFlags FRAG_STAGE { vk::ShaderStageFlagBits::eFragment };
|
||||
|
||||
constexpr descriptors::AttachmentDescriptor position_descriptor { 0, FRAG_STAGE };
|
||||
constexpr descriptors::AttachmentDescriptor normal_descriptor { 1, FRAG_STAGE };
|
||||
constexpr descriptors::AttachmentDescriptor albedo_descriptor { 2, FRAG_STAGE };
|
||||
constexpr descriptors::AttachmentDescriptor color_descriptor { 0, FRAG_STAGE };
|
||||
constexpr descriptors::AttachmentDescriptor position_descriptor { 1, FRAG_STAGE };
|
||||
constexpr descriptors::AttachmentDescriptor normal_descriptor { 2, FRAG_STAGE };
|
||||
constexpr descriptors::AttachmentDescriptor metallic_descriptor { 3, FRAG_STAGE };
|
||||
constexpr descriptors::AttachmentDescriptor emissive_descriptor { 4, FRAG_STAGE };
|
||||
|
||||
inline static descriptors::DescriptorSetLayout gbuffer_set {
|
||||
0, position_descriptor, normal_descriptor, albedo_descriptor
|
||||
0, color_descriptor, position_descriptor, normal_descriptor, metallic_descriptor, emissive_descriptor
|
||||
};
|
||||
|
||||
constexpr descriptors::AttachmentDescriptor input_descriptor { 0, vk::ShaderStageFlagBits::eFragment };
|
||||
|
||||
@@ -55,7 +55,6 @@ namespace fgl::engine
|
||||
|
||||
Material::Material() : m_id( material_id_counter.getID() )
|
||||
{
|
||||
update();
|
||||
getDescriptorSet().bindArray( 0, getDeviceMaterialGPUData().getHandle(), m_id, sizeof( DeviceMaterialData ) );
|
||||
getDescriptorSet().update();
|
||||
}
|
||||
@@ -131,7 +130,6 @@ namespace fgl::engine
|
||||
{
|
||||
set = material_descriptor_set.create();
|
||||
assert( set->setIDX() == MATERIAL_SET_ID );
|
||||
set->setMaxIDX( 1 );
|
||||
//set->bindUniformBuffer( 0, getDeviceMaterialGPUData() );
|
||||
//set->update();
|
||||
//set = std::make_unique< descriptors::DescriptorSet >( std::move( set_layout.value() ) );
|
||||
|
||||
@@ -75,16 +75,19 @@ namespace fgl::engine
|
||||
|
||||
using MaterialID = std::uint32_t;
|
||||
|
||||
#define PAD( id, size ) std::byte pad_##id[ size ];
|
||||
|
||||
//! Material data to be sent to the device
|
||||
// Alignas to prevent the struct from becoming bigger then needed
|
||||
struct DeviceMaterialData
|
||||
{
|
||||
TextureID color_texture_id { constants::INVALID_TEXTURE_ID };
|
||||
|
||||
PAD( 0, 12 );
|
||||
|
||||
glm::vec4 color_factors { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
// Padding to shove metallic_texture_id to offset 32
|
||||
std::byte padd1[ 12 ];
|
||||
|
||||
TextureID metallic_texture_id { constants::INVALID_TEXTURE_ID };
|
||||
float metallic_factor { 0.0f };
|
||||
float roughness_factor { 0.0f };
|
||||
@@ -100,6 +103,7 @@ namespace fgl::engine
|
||||
};
|
||||
|
||||
static_assert( sizeof( DeviceMaterialData ) == 76 );
|
||||
static_assert( offsetof( DeviceMaterialData, color_factors ) == 16 );
|
||||
static_assert( offsetof( DeviceMaterialData, metallic_texture_id ) == 32 );
|
||||
static_assert( offsetof( DeviceMaterialData, normal_texture_id ) == 44 );
|
||||
static_assert( offsetof( DeviceMaterialData, occlusion_texture_id ) == 52 );
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace fgl::engine
|
||||
if ( accessor.type == TINYGLTF_TYPE_SCALAR && T_SIZE >= byte_count )
|
||||
{
|
||||
// If the type is a smaller scalar then we want can still copy the data.
|
||||
log::warn( "Attempting to copy data of size {} into type of size {}", byte_count, T_SIZE );
|
||||
// log::warn( "Attempting to copy data of size {} into type of size {}", byte_count, T_SIZE );
|
||||
|
||||
if constexpr ( std::is_scalar_v< T > )
|
||||
{
|
||||
@@ -308,8 +308,6 @@ namespace fgl::engine
|
||||
std::vector< glm::vec2 > SceneBuilder::extractUVInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root )
|
||||
{
|
||||
ZoneScoped;
|
||||
log::debug( "Extracting UV info" );
|
||||
|
||||
//TODO: Figure out how I can use multiple textures for various things.
|
||||
if ( !hasAttribute( prim, "TEXCOORD_0" ) ) return {};
|
||||
|
||||
@@ -328,7 +326,6 @@ namespace fgl::engine
|
||||
extractVertexInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root )
|
||||
{
|
||||
ZoneScoped;
|
||||
log::debug( "Extracting vert info" );
|
||||
const auto pos { extractPositionInfo( prim, root ) };
|
||||
|
||||
std::vector< ModelVertex > verts {};
|
||||
@@ -355,12 +352,6 @@ namespace fgl::engine
|
||||
verts.emplace_back( vert );
|
||||
}
|
||||
|
||||
log::debug(
|
||||
"Found {} verts. Has UV info: {}, Has normals: {}",
|
||||
verts.size(),
|
||||
has_uv ? "Yes" : "No",
|
||||
has_normals ? "Yes" : "No" );
|
||||
|
||||
return verts;
|
||||
}
|
||||
|
||||
@@ -373,8 +364,6 @@ namespace fgl::engine
|
||||
att_str += attrib.first + ", ";
|
||||
}
|
||||
|
||||
log::debug( "Attributes for primitive: [{}]", att_str );
|
||||
|
||||
//TODO: Get normal colors from texture
|
||||
[[maybe_unused]] const bool has_normal { hasAttribute( prim, "NORMAL" ) };
|
||||
const bool has_position { hasAttribute( prim, "POSITION" ) };
|
||||
@@ -572,7 +561,19 @@ namespace fgl::engine
|
||||
const auto& metallic_roughness { gltf_material.pbrMetallicRoughness };
|
||||
const auto& pbr_tex_id { metallic_roughness.baseColorTexture.index };
|
||||
material->properties.pbr.color_tex = loadTexture( pbr_tex_id, root );
|
||||
material->properties.pbr.color_factors = convertToVec4( metallic_roughness.baseColorFactor );
|
||||
log::debug(
|
||||
"Color factors: {}, {}, {}, {}",
|
||||
metallic_roughness.baseColorFactor[ 0 ],
|
||||
metallic_roughness.baseColorFactor[ 1 ],
|
||||
metallic_roughness.baseColorFactor[ 2 ],
|
||||
metallic_roughness.baseColorFactor[ 3 ]
|
||||
|
||||
);
|
||||
|
||||
material->properties.pbr.color_factors = { metallic_roughness.baseColorFactor[ 0 ],
|
||||
metallic_roughness.baseColorFactor[ 1 ],
|
||||
metallic_roughness.baseColorFactor[ 2 ],
|
||||
metallic_roughness.baseColorFactor[ 3 ] };
|
||||
|
||||
material->properties.pbr.metallic_roughness_tex =
|
||||
loadTexture( metallic_roughness.metallicRoughnessTexture.index, root );
|
||||
|
||||
@@ -236,7 +236,6 @@ namespace fgl::engine
|
||||
else
|
||||
{
|
||||
set = texture_descriptor_set.create();
|
||||
set->setMaxIDX( 1 );
|
||||
set->setName( "Texture descriptor set" );
|
||||
return *set;
|
||||
}
|
||||
|
||||
@@ -342,7 +342,6 @@ namespace fgl::engine
|
||||
for ( std::uint8_t i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i )
|
||||
{
|
||||
auto set { camera_descriptor_set.create() };
|
||||
set->setMaxIDX( 0 );
|
||||
set->bindUniformBuffer( 0, m_camera_frame_info[ i ] );
|
||||
set->update();
|
||||
|
||||
|
||||
@@ -15,31 +15,42 @@ namespace fgl::engine
|
||||
{
|
||||
rendering::RenderPassBuilder builder {};
|
||||
|
||||
constexpr std::size_t PositionIndex { 0 };
|
||||
constexpr std::size_t NormalIndex { 1 };
|
||||
constexpr std::size_t AlbedoIndex { 2 };
|
||||
constexpr std::size_t CompositeIndex { 3 };
|
||||
constexpr std::size_t DepthIndex { 4 };
|
||||
|
||||
builder.setAttachmentCount( 5 );
|
||||
builder.setAttachmentCount( 7 );
|
||||
|
||||
// Set formats for each item in the swapchain
|
||||
|
||||
//XYZ in world space
|
||||
auto position { builder.attachment( PositionIndex ) };
|
||||
position.setFormat( vk::Format::eR16G16B16A16Sfloat ); // position
|
||||
position.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
position.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
|
||||
|
||||
//RGBA
|
||||
auto normal { builder.attachment( NormalIndex ) };
|
||||
normal.setFormat( vk::Format::eR16G16B16A16Sfloat ); // normal
|
||||
normal.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
normal.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
|
||||
|
||||
auto albedo { builder.attachment( AlbedoIndex ) };
|
||||
albedo.setFormat( vk::Format::eR8G8B8A8Unorm ); // albedo
|
||||
albedo.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
albedo.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
|
||||
// RGBA
|
||||
auto color { builder.attachment( ColorIndex ) };
|
||||
color.setFormat( vk::Format::eR8G8B8A8Unorm ); // color
|
||||
color.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
color.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
|
||||
|
||||
// Metallic, Roughness, Occlusion
|
||||
auto metallic_roughness { builder.attachment( MetallicIndex ) };
|
||||
metallic_roughness.setFormat( vk::Format::eR16G16B16A16Sfloat );
|
||||
metallic_roughness.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
metallic_roughness.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
|
||||
|
||||
// RGB
|
||||
auto emissive { builder.attachment( EmissiveIndex ) };
|
||||
emissive.setFormat( vk::Format::eR16G16B16A16Sfloat );
|
||||
emissive.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
emissive.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
|
||||
|
||||
auto composite { builder.attachment( CompositeIndex ) };
|
||||
//TODO: For HDR I think this needs to be a bigger range then 8bits per channel.
|
||||
composite.setFormat( vk::Format::eR8G8B8A8Unorm ); // composite
|
||||
composite.setLayouts( vk::ImageLayout::eUndefined, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
composite.setOps( vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore );
|
||||
@@ -51,9 +62,11 @@ namespace fgl::engine
|
||||
|
||||
auto& g_buffer_subpass { builder.createSubpass( 0 ) };
|
||||
g_buffer_subpass.setDepthLayout( DepthIndex, vk::ImageLayout::eDepthStencilAttachmentOptimal );
|
||||
g_buffer_subpass.addRenderLayout( ColorIndex, vk::ImageLayout::eColorAttachmentOptimal );
|
||||
g_buffer_subpass.addRenderLayout( PositionIndex, vk::ImageLayout::eColorAttachmentOptimal );
|
||||
g_buffer_subpass.addRenderLayout( NormalIndex, vk::ImageLayout::eColorAttachmentOptimal );
|
||||
g_buffer_subpass.addRenderLayout( AlbedoIndex, vk::ImageLayout::eColorAttachmentOptimal );
|
||||
g_buffer_subpass.addRenderLayout( MetallicIndex, vk::ImageLayout::eColorAttachmentOptimal );
|
||||
g_buffer_subpass.addRenderLayout( EmissiveIndex, vk::ImageLayout::eColorAttachmentOptimal );
|
||||
|
||||
g_buffer_subpass.addDependencyFromExternal(
|
||||
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
|
||||
@@ -64,9 +77,11 @@ namespace fgl::engine
|
||||
|
||||
auto& composite_subpass { builder.createSubpass( 1 ) };
|
||||
composite_subpass.addRenderLayout( CompositeIndex, vk::ImageLayout::eColorAttachmentOptimal );
|
||||
composite_subpass.addInputLayout( ColorIndex, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
composite_subpass.addInputLayout( PositionIndex, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
composite_subpass.addInputLayout( NormalIndex, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
composite_subpass.addInputLayout( AlbedoIndex, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
composite_subpass.addInputLayout( MetallicIndex, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
composite_subpass.addInputLayout( EmissiveIndex, vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
|
||||
composite_subpass.addDependency(
|
||||
g_buffer_subpass,
|
||||
|
||||
@@ -19,13 +19,15 @@ namespace fgl::engine
|
||||
//auto set { std::make_unique< descriptors::DescriptorSet >( GBufferDescriptorSet::createLayout() ) };
|
||||
auto set { gbuffer_set.create() };
|
||||
|
||||
set->setMaxIDX( 2 );
|
||||
set->bindAttachment( 0, gbuffer.color.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
|
||||
set->bindAttachment( 0, gbuffer.position.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
set->bindAttachment( 1, gbuffer.position.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
|
||||
set->bindAttachment( 1, gbuffer.normal.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
set->bindAttachment( 2, gbuffer.normal.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
|
||||
set->bindAttachment( 2, gbuffer.albedo.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
set->bindAttachment( 3, gbuffer.metallic.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
|
||||
set->bindAttachment( 4, gbuffer.emissive.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
|
||||
set->update();
|
||||
|
||||
@@ -44,9 +46,12 @@ namespace fgl::engine
|
||||
std::vector< vk::raii::Framebuffer > CameraSwapchain::createFrambuffers()
|
||||
{
|
||||
constexpr auto image_count { SwapChain::MAX_FRAMES_IN_FLIGHT };
|
||||
|
||||
gbuffer.color.createResources( image_count, m_extent );
|
||||
gbuffer.position.createResources( image_count, m_extent );
|
||||
gbuffer.normal.createResources( image_count, m_extent );
|
||||
gbuffer.albedo.createResources( image_count, m_extent );
|
||||
gbuffer.metallic.createResources( image_count, m_extent );
|
||||
gbuffer.emissive.createResources( image_count, m_extent );
|
||||
|
||||
gbuffer.composite.createResources( image_count, m_extent, vk::ImageUsageFlagBits::eTransferSrc );
|
||||
gbuffer.depth.createResources( image_count, m_extent );
|
||||
@@ -58,7 +63,14 @@ namespace fgl::engine
|
||||
for ( FrameIndex i = 0; i < image_count; ++i )
|
||||
{
|
||||
std::vector< vk::ImageView > attachments { getViewsForFrame(
|
||||
i, gbuffer.position, gbuffer.normal, gbuffer.albedo, gbuffer.composite, gbuffer.depth ) };
|
||||
i,
|
||||
gbuffer.color,
|
||||
gbuffer.position,
|
||||
gbuffer.normal,
|
||||
gbuffer.metallic,
|
||||
gbuffer.emissive,
|
||||
gbuffer.composite,
|
||||
gbuffer.depth ) };
|
||||
|
||||
vk::FramebufferCreateInfo info {};
|
||||
info.renderPass = m_renderpass;
|
||||
@@ -69,20 +81,29 @@ namespace fgl::engine
|
||||
|
||||
buffers.emplace_back( Device::getInstance()->createFramebuffer( info ) );
|
||||
|
||||
g_buffer_color_img.emplace_back( std::make_unique< Texture >( gbuffer.color.m_attachment_resources
|
||||
.m_images[ i ]
|
||||
->setName( "GBufferColor" ) ) );
|
||||
|
||||
auto& position_resources { gbuffer.position.m_attachment_resources };
|
||||
assert( position_resources.m_images[ i ] );
|
||||
assert( position_resources.m_image_views[ i ] );
|
||||
auto& position_image { *position_resources.m_images[ i ] };
|
||||
position_image.setName( format_ns::format( "GBufferPosition: {}", i ) );
|
||||
|
||||
g_buffer_position_img.emplace_back( std::make_unique< Texture >( position_image ) );
|
||||
|
||||
g_buffer_normal_img.emplace_back( std::make_unique< Texture >( gbuffer.normal.m_attachment_resources
|
||||
.m_images[ i ]
|
||||
->setName( "GBufferNormal" ) ) );
|
||||
g_buffer_albedo_img.emplace_back( std::make_unique< Texture >( gbuffer.albedo.m_attachment_resources
|
||||
|
||||
g_buffer_metallic_img.emplace_back( std::make_unique< Texture >( gbuffer.metallic.m_attachment_resources
|
||||
.m_images[ i ]
|
||||
->setName( "GBufferAlbedo" ) ) );
|
||||
->setName( "GBufferMetallic" ) ) );
|
||||
|
||||
g_buffer_emissive_img.emplace_back( std::make_unique< Texture >( gbuffer.emissive.m_attachment_resources
|
||||
.m_images[ i ]
|
||||
->setName( "GBufferEmissive" ) ) );
|
||||
|
||||
g_buffer_composite_img.emplace_back( std::make_unique< Texture >( gbuffer.composite.m_attachment_resources
|
||||
.m_images[ i ]
|
||||
->setName( "GBufferComposite" ) ) );
|
||||
@@ -121,8 +142,14 @@ namespace fgl::engine
|
||||
m_extent( extent ),
|
||||
m_renderpass( renderpass ),
|
||||
m_framebuffers( createFrambuffers() ),
|
||||
m_clear_values(
|
||||
gatherClearValues( gbuffer.albedo, gbuffer.composite, gbuffer.depth, gbuffer.normal, gbuffer.position ) ),
|
||||
m_clear_values( gatherClearValues(
|
||||
gbuffer.color,
|
||||
gbuffer.position,
|
||||
gbuffer.normal,
|
||||
gbuffer.metallic,
|
||||
gbuffer.emissive,
|
||||
gbuffer.composite,
|
||||
gbuffer.depth ) ),
|
||||
m_gbuffer_descriptor_set( createGBufferDescriptors() )
|
||||
{
|
||||
gbuffer.depth.setName( "Depth" );
|
||||
|
||||
@@ -4,29 +4,44 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "engine/rendering/pipelines/Attachment.hpp"
|
||||
#include "engine/descriptors/DescriptorSet.hpp"
|
||||
#include "engine/rendering/SwapChain.hpp"
|
||||
#include "engine/rendering/pipelines/Attachment.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
constexpr std::size_t ColorIndex { 0 };
|
||||
constexpr std::size_t PositionIndex { 1 };
|
||||
constexpr std::size_t NormalIndex { 2 };
|
||||
constexpr std::size_t MetallicIndex { 3 };
|
||||
constexpr std::size_t EmissiveIndex { 4 };
|
||||
|
||||
constexpr std::size_t CompositeIndex { 5 };
|
||||
constexpr std::size_t DepthIndex { 6 };
|
||||
|
||||
class CameraSwapchain
|
||||
{
|
||||
struct
|
||||
{
|
||||
ColorAttachment< 0 > position { vk::Format::eR16G16B16A16Sfloat };
|
||||
ColorAttachment< 1 > normal { vk::Format::eR16G16B16A16Sfloat };
|
||||
ColorAttachment< 2 > albedo { vk::Format::eR8G8B8A8Unorm };
|
||||
ColorAttachment< 3 > composite { vk::Format::eR8G8B8A8Unorm };
|
||||
DepthAttachment< 4 > depth { SwapChain::findDepthFormat() };
|
||||
ColorAttachment< ColorIndex > color { vk::Format::eR8G8B8A8Unorm };
|
||||
ColorAttachment< PositionIndex > position { vk::Format::eR16G16B16A16Sfloat };
|
||||
ColorAttachment< NormalIndex > normal { vk::Format::eR16G16B16A16Sfloat };
|
||||
ColorAttachment< MetallicIndex > metallic { vk::Format::eR16G16B16A16Sfloat };
|
||||
ColorAttachment< EmissiveIndex > emissive { vk::Format::eR16G16B16A16Sfloat };
|
||||
|
||||
ColorAttachment< CompositeIndex > composite { vk::Format::eR8G8B8A8Unorm };
|
||||
DepthAttachment< DepthIndex > depth { SwapChain::findDepthFormat() };
|
||||
} gbuffer {};
|
||||
|
||||
public:
|
||||
|
||||
std::vector< std::unique_ptr< Texture > > g_buffer_color_img {};
|
||||
std::vector< std::unique_ptr< Texture > > g_buffer_position_img {};
|
||||
std::vector< std::unique_ptr< Texture > > g_buffer_normal_img {};
|
||||
std::vector< std::unique_ptr< Texture > > g_buffer_albedo_img {};
|
||||
std::vector< std::unique_ptr< Texture > > g_buffer_metallic_img {};
|
||||
std::vector< std::unique_ptr< Texture > > g_buffer_emissive_img {};
|
||||
|
||||
std::vector< std::unique_ptr< Texture > > g_buffer_composite_img {};
|
||||
|
||||
private:
|
||||
|
||||
@@ -18,10 +18,14 @@
|
||||
namespace fgl::engine::descriptors
|
||||
{
|
||||
|
||||
DescriptorSet::DescriptorSet( const vk::raii::DescriptorSetLayout& layout, DescriptorIDX idx ) :
|
||||
DescriptorSet::DescriptorSet(
|
||||
const vk::raii::DescriptorSetLayout& layout, const DescriptorIDX idx, const std::size_t binding_count ) :
|
||||
m_set_idx( idx ),
|
||||
m_set( DescriptorPool::getInstance().allocateSet( layout ) )
|
||||
{}
|
||||
m_set( DescriptorPool::getInstance().allocateSet( layout ) ),
|
||||
m_binding_count( binding_count )
|
||||
{
|
||||
m_infos.resize( m_binding_count );
|
||||
}
|
||||
|
||||
DescriptorSet::DescriptorSet( DescriptorSet&& other ) noexcept :
|
||||
m_set_idx( other.m_set_idx ),
|
||||
@@ -29,9 +33,10 @@ namespace fgl::engine::descriptors
|
||||
descriptor_writes( std::move( other.descriptor_writes ) ),
|
||||
m_resources( std::move( other.m_resources ) ),
|
||||
m_set( std::move( other.m_set ) ),
|
||||
m_max_idx( other.m_max_idx )
|
||||
m_binding_count( other.m_binding_count )
|
||||
{
|
||||
other.m_set = VK_NULL_HANDLE;
|
||||
other.m_binding_count = 0;
|
||||
}
|
||||
|
||||
DescriptorSet& DescriptorSet::operator=( DescriptorSet&& other ) noexcept
|
||||
@@ -42,7 +47,9 @@ namespace fgl::engine::descriptors
|
||||
m_resources = std::move( other.m_resources );
|
||||
m_set = std::move( other.m_set );
|
||||
other.m_set = VK_NULL_HANDLE;
|
||||
m_max_idx = other.m_max_idx;
|
||||
m_binding_count = other.m_binding_count;
|
||||
other.m_binding_count = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -156,13 +163,7 @@ namespace fgl::engine::descriptors
|
||||
//Clear all writes
|
||||
descriptor_writes.clear();
|
||||
|
||||
setMaxIDX( m_max_idx );
|
||||
}
|
||||
|
||||
void DescriptorSet::setMaxIDX( std::uint32_t max_idx )
|
||||
{
|
||||
m_max_idx = max_idx;
|
||||
m_infos.resize( max_idx + 1 );
|
||||
m_infos.resize( m_binding_count );
|
||||
}
|
||||
|
||||
void DescriptorSet::bindAttachment(
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace fgl::engine::descriptors
|
||||
|
||||
vk::raii::DescriptorSet m_set;
|
||||
|
||||
std::uint32_t m_max_idx { 0 };
|
||||
std::size_t m_binding_count;
|
||||
|
||||
public:
|
||||
|
||||
@@ -47,8 +47,6 @@ namespace fgl::engine::descriptors
|
||||
|
||||
void update();
|
||||
|
||||
void setMaxIDX( std::uint32_t max_idx );
|
||||
|
||||
VkDescriptorSet operator*() const { return *m_set; }
|
||||
|
||||
VkDescriptorSet getVkDescriptorSet() const { return *m_set; }
|
||||
@@ -56,7 +54,7 @@ namespace fgl::engine::descriptors
|
||||
inline DescriptorIDX setIDX() const { return m_set_idx; }
|
||||
|
||||
DescriptorSet() = delete;
|
||||
DescriptorSet( const vk::raii::DescriptorSetLayout& layout, const DescriptorIDX idx );
|
||||
DescriptorSet( const vk::raii::DescriptorSetLayout& layout, const DescriptorIDX idx, std::size_t binding_count );
|
||||
|
||||
//Copy
|
||||
DescriptorSet( const DescriptorSet& other ) = delete;
|
||||
|
||||
@@ -12,7 +12,8 @@ namespace fgl::engine::descriptors
|
||||
|
||||
DescriptorSetLayout::DescriptorSetLayout(
|
||||
const DescriptorIDX set_idx, const std::vector< std::reference_wrapper< const Descriptor > >& descriptors ) :
|
||||
m_set_idx( set_idx )
|
||||
m_set_idx( set_idx ),
|
||||
m_binding_count( descriptors.size() )
|
||||
{
|
||||
FGL_ASSERT( descriptors.size() > 0, "Must have more then 1 descriptor set" );
|
||||
|
||||
@@ -38,7 +39,7 @@ namespace fgl::engine::descriptors
|
||||
std::unique_ptr< DescriptorSet > DescriptorSetLayout::create()
|
||||
{
|
||||
if ( !m_layout.has_value() ) m_layout = createLayout();
|
||||
return std::make_unique< DescriptorSet >( *m_layout, m_set_idx );
|
||||
return std::make_unique< DescriptorSet >( *m_layout, m_set_idx, m_binding_count );
|
||||
}
|
||||
|
||||
vk::raii::DescriptorSetLayout DescriptorSetLayout::createLayout() const
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace fgl::engine::descriptors
|
||||
|
||||
DescriptorIDX m_set_idx;
|
||||
|
||||
std::size_t m_binding_count;
|
||||
|
||||
DescriptorSetLayout(
|
||||
DescriptorIDX set_idx, const std::vector< std::reference_wrapper< const Descriptor > >& descriptors );
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace fgl::engine::memory
|
||||
}
|
||||
|
||||
std::shared_ptr< BufferSuballocationHandle > Buffer::
|
||||
allocate( vk::DeviceSize memory_size, std::uint32_t t_alignment )
|
||||
allocate( vk::DeviceSize memory_size, const std::uint32_t t_alignment )
|
||||
{
|
||||
ZoneScoped;
|
||||
//Calculate alignment from alignment, ubo_alignment, and atom_size_alignment
|
||||
@@ -189,14 +189,14 @@ namespace fgl::engine::memory
|
||||
#ifndef NDEBUG
|
||||
//Check that we haven't lost any memory
|
||||
std::size_t sum { 0 };
|
||||
for ( const auto& free_blocks : this->m_free_blocks )
|
||||
for ( const auto& [ _, free_size ] : this->m_free_blocks )
|
||||
{
|
||||
sum += free_blocks.second;
|
||||
sum += free_size;
|
||||
}
|
||||
|
||||
for ( const auto& allocated : this->m_allocations )
|
||||
for ( const auto& [ _, allocated_size ] : this->m_allocations )
|
||||
{
|
||||
sum += allocated.second;
|
||||
sum += allocated_size;
|
||||
}
|
||||
|
||||
assert( sum == this->size() );
|
||||
@@ -227,10 +227,7 @@ namespace fgl::engine::memory
|
||||
if ( m_free_blocks.size() <= 1 ) return;
|
||||
|
||||
//Sort the blocks by offset
|
||||
std::sort(
|
||||
m_free_blocks.begin(),
|
||||
m_free_blocks.end(),
|
||||
[]( const auto& a, const auto& b ) -> bool { return a.first < b.first; } );
|
||||
std::ranges::sort( m_free_blocks, []( const auto& a, const auto& b ) -> bool { return a.first < b.first; } );
|
||||
|
||||
auto itter { m_free_blocks.begin() };
|
||||
auto next_block { std::next( itter ) };
|
||||
@@ -318,7 +315,10 @@ namespace fgl::engine::memory
|
||||
|
||||
if ( m_allocations.size() == 0 ) return total_size;
|
||||
|
||||
for ( const auto& [ offset, size ] : m_allocations ) total_size += size;
|
||||
for ( const auto& [ offset, size ] : m_allocations )
|
||||
{
|
||||
total_size += size;
|
||||
}
|
||||
|
||||
return total_size;
|
||||
}
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <source_location>
|
||||
#include <stacktrace>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "vma/vma_impl.hpp"
|
||||
@@ -87,7 +88,9 @@ namespace fgl::engine::memory
|
||||
|
||||
//! @brief List of all active suballocations
|
||||
//! <offset, size>
|
||||
std::map< vk::DeviceSize, vk::DeviceSize > m_allocations {};
|
||||
using AllocationSize = vk::DeviceSize;
|
||||
|
||||
std::map< vk::DeviceSize, AllocationSize > m_allocations {};
|
||||
|
||||
//! @brief list of any free blocks
|
||||
//! @note All blocks are amalgamated to the largest they can expand to.
|
||||
@@ -123,6 +126,7 @@ namespace fgl::engine::memory
|
||||
/**
|
||||
* @param memory_size Size of each N
|
||||
* @param alignment The alignment to use.
|
||||
* @param source_loc Source location.
|
||||
* @return
|
||||
*
|
||||
* @note Alignment is forced to be at least the size of the largest alignment required by the device.
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace fgl::engine
|
||||
BufferVector( buffer, count, sizeof( T ) )
|
||||
{
|
||||
const auto size_str { fgl::literals::size_literals::to_string( count * sizeof( T ) ) };
|
||||
log::debug( "Creating DeviceVector of size {}", size_str );
|
||||
assert( count != 0 && "BufferSuballocationVector::BufferSuballocationVector() called with count == 0" );
|
||||
}
|
||||
|
||||
|
||||
@@ -69,8 +69,6 @@ namespace fgl::engine
|
||||
auto set { gui_descriptor_set.create() };
|
||||
//auto set { std::make_unique< descriptors::DescriptorSet >( GuiInputDescriptorSet::createLayout() ) };
|
||||
|
||||
set->setMaxIDX( 0 );
|
||||
|
||||
// set->bindAttachment(
|
||||
// 0, render_attachments.input_color.getView( i ), vk::ImageLayout::eShaderReadOnlyOptimal );
|
||||
|
||||
|
||||
@@ -157,6 +157,7 @@ namespace fgl::engine::rendering
|
||||
{
|
||||
m_builder.setFormat( m_index, format );
|
||||
#ifndef NDEBUG
|
||||
assert( !set_format );
|
||||
set_format = true;
|
||||
#endif
|
||||
}
|
||||
@@ -165,6 +166,7 @@ namespace fgl::engine::rendering
|
||||
{
|
||||
m_builder.setLayouts( m_index, image_layout, final_layout );
|
||||
#ifndef NDEBUG
|
||||
assert( !set_layout );
|
||||
set_layout = true;
|
||||
#endif
|
||||
}
|
||||
@@ -173,6 +175,7 @@ namespace fgl::engine::rendering
|
||||
{
|
||||
m_builder.setOps( m_index, load_op, store_op );
|
||||
#ifndef NDEBUG
|
||||
assert( !set_ops );
|
||||
set_ops = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace fgl::engine
|
||||
|
||||
builder.addDescriptorSet( Camera::getDescriptorLayout() );
|
||||
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
@@ -51,6 +53,8 @@ namespace fgl::engine
|
||||
|
||||
PipelineBuilder builder { render_pass, 0 };
|
||||
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace fgl::engine
|
||||
|
||||
builder.addDescriptorSet( Camera::getDescriptorLayout() );
|
||||
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
builder.addColorAttachment().finish();
|
||||
|
||||
@@ -1,32 +1,20 @@
|
||||
#version 450
|
||||
|
||||
layout (input_attachment_index = 0, binding = 0) uniform subpassInput i_position;
|
||||
layout (input_attachment_index = 1, binding = 1) uniform subpassInput i_normal;
|
||||
layout (input_attachment_index = 2, binding = 2) uniform subpassInput i_albedo;
|
||||
layout (input_attachment_index = 0, binding = 0) uniform subpassInput i_color;
|
||||
layout (input_attachment_index = 1, binding = 1) uniform subpassInput i_position;
|
||||
layout (input_attachment_index = 2, binding = 2) uniform subpassInput i_normal;
|
||||
layout (input_attachment_index = 3, binding = 3) uniform subpassInput i_metallic;
|
||||
layout (input_attachment_index = 4, binding = 4) uniform subpassInput i_emissive;
|
||||
|
||||
layout (location = 0) in vec2 in_uv;
|
||||
|
||||
layout (location = 0) out vec4 out_color;
|
||||
|
||||
/*
|
||||
struct Light
|
||||
{
|
||||
vec4 position;
|
||||
vec3 color;
|
||||
float radius;
|
||||
};
|
||||
|
||||
layout (std410, binding = 3) buffer LightBuffer
|
||||
{
|
||||
Light lights[];
|
||||
};
|
||||
*/
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 position = subpassLoad(i_position).xyz;
|
||||
vec3 normal = subpassLoad(i_normal).xyz;
|
||||
vec3 albedo = subpassLoad(i_albedo).xyz;
|
||||
vec3 color = subpassLoad(i_color).xyz;
|
||||
|
||||
#define ambient 0.5
|
||||
|
||||
@@ -41,7 +29,7 @@ void main()
|
||||
//float diff = max(dot(normalize(normal), sun_dir), 0.0);
|
||||
vec3 diffuse = diff * sun_color;
|
||||
|
||||
vec3 frag_color = (ambient + diffuse) * albedo;
|
||||
vec3 frag_color = (ambient + diffuse) * color;
|
||||
|
||||
out_color = vec4(frag_color, 1.0);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
layout (location = 0) out vec4 out_position;
|
||||
layout (location = 1) out vec4 out_normal;
|
||||
layout (location = 2) out vec4 out_albedo;
|
||||
layout (location = 0) out vec4 out_color;
|
||||
layout (location = 1) out vec3 out_position;
|
||||
layout (location = 2) out vec4 out_normal;
|
||||
layout (location = 3) out vec3 out_metallic;
|
||||
layout (location = 4) out vec3 out_emissive;
|
||||
|
||||
@@ -16,7 +16,6 @@ layout (set = 3, binding = 0) uniform Material {
|
||||
vec3 emissive_factors;
|
||||
} materials[];
|
||||
|
||||
|
||||
bool hasColorTexture()
|
||||
{
|
||||
return materials[in_material_id].color_texture_id != INVALID_TEXTURE_ID;
|
||||
|
||||
15
src/shaders/include/pbr.glsl
Normal file
15
src/shaders/include/pbr.glsl
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,6 @@ layout(location = 0) in vec3 in_color;
|
||||
#include "include/gbuffer_out.glsl"
|
||||
|
||||
void main() {
|
||||
out_albedo = vec4(in_color, 1.0f);
|
||||
out_color = vec4(in_color, 1.0f);
|
||||
out_normal = vec4(1.0f);
|
||||
}
|
||||
@@ -19,50 +19,73 @@ layout (set = 2, binding = 0) uniform sampler2D tex[];
|
||||
|
||||
#include "include/material.glsl"
|
||||
|
||||
// Include all helper functions for glsl.
|
||||
#include "include/pbr.glsl"
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
vec3 error_color = vec3(0.475, 0.0, 0.686);
|
||||
|
||||
float MIN_ROUGHNESS = 0.04;
|
||||
|
||||
void main()
|
||||
{
|
||||
out_position = vec4(in_world_pos, 1.0f);
|
||||
out_position = in_world_pos;
|
||||
|
||||
if (in_material_id == INVALID_TEXTURE_ID)
|
||||
{
|
||||
out_albedo = vec4(255.0f / 255.0f, 192.0f / 255.0f, 203.0f / 255.0f, 1.0f);
|
||||
return;
|
||||
}
|
||||
vec3 diffuse_color;
|
||||
vec4 base_color;
|
||||
|
||||
uint normal_id = materials[in_material_id].normal_texture_id;
|
||||
if (isValidTex(normal_id))
|
||||
{
|
||||
vec3 normal_vec = texture(tex[normal_id], in_uv).xyz;
|
||||
out_normal = vec4(normal_vec, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_normal = vec4(in_normal, 1.0f);
|
||||
}
|
||||
vec3 f0 = vec3(0.04);
|
||||
|
||||
uint albedo_id = materials[in_material_id].color_texture_id;
|
||||
uint mat_id = in_material_id;
|
||||
|
||||
if (albedo_id == INVALID_TEXTURE_ID)
|
||||
{
|
||||
out_albedo = vec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec4 tex_value = texture(tex[albedo_id], in_uv);
|
||||
|
||||
if (tex_value.a < 1.0)
|
||||
if (mat_id == INVALID_TEXTURE_ID)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
out_albedo = tex_value;
|
||||
// The Vulkan-glTF-PBR example does some alpha mask stuff. I'm not exactly sure what it's used for
|
||||
// So for now we will just set the base_color to be the texture color
|
||||
uint color_texture_id = materials[mat_id].color_texture_id;
|
||||
if (color_texture_id != INVALID_TEXTURE_ID)
|
||||
{
|
||||
// Load the texture and multiply it against the color factors
|
||||
vec4 color = texture(tex[color_texture_id], in_uv).rgba;
|
||||
vec4 factors = materials[mat_id].color_factors;
|
||||
out_color = color * factors;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we have no color texture, Simply use the color factors as our color
|
||||
out_color = materials[mat_id].color_factors;
|
||||
}
|
||||
|
||||
out_position.a = linearDepth(out_position.z);
|
||||
float metallic_scalar = 0.0;
|
||||
float roughness_scalar = 0.0;
|
||||
|
||||
uint metallic_id = materials[mat_id].metallic_texture_id;
|
||||
if (metallic_id != INVALID_TEXTURE_ID)// If the metallic texture is assigned, Then we should use it. Otherwise we want to use the metallic factor
|
||||
{
|
||||
vec4 tex_sample = texture(tex[metallic_id], in_uv).rgba;
|
||||
// r channel is for occlusion data (optional)
|
||||
// g channel is for roughnes factor
|
||||
// b channel is for metallic factor
|
||||
metallic_scalar = tex_sample.b * materials[mat_id].metallic_factor;
|
||||
roughness_scalar = tex_sample.g * materials[mat_id].roughness_factor;
|
||||
}
|
||||
else // Texture was not present, So we instead use the factor values as our values
|
||||
{
|
||||
metallic_scalar = clamp(materials[mat_id].metallic_factor, MIN_ROUGHNESS, 1.0);
|
||||
roughness_scalar = clamp(materials[mat_id].roughness_factor, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// The example does some magic here that I don't understand?
|
||||
// https://github.com/SaschaWillems/Vulkan-glTF-PBR/blob/master/data/shaders/material_pbr.frag#L242
|
||||
float occlusion_scalar = 0.0;
|
||||
|
||||
out_metallic = vec3(metallic_scalar, roughness_scalar, occlusion_scalar);
|
||||
}
|
||||
Reference in New Issue
Block a user