diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index c7512346c9137b77c365e807b679b3950925f535..493534f77a0f930cbd0d292a504300f51ebc0f76 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -223,6 +223,11 @@ namespace vkcv bool supportStorage = false, bool supportColorAttachment = false); + [[nodiscard]] + const uint32_t getImageWidth(ImageHandle imageHandle); + [[nodiscard]] + const uint32_t getImageHeight(ImageHandle imageHandle); + /** TODO: * @param setDescriptions * @return diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 5edb802b3adf16878c2dec4050d8444278739026..28b2184b2a83515a514f1428733bcf8cf1499633 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -1,6 +1,7 @@ # Add new modules here: add_subdirectory(asset_loader) +add_subdirectory(material) add_subdirectory(camera) add_subdirectory(gui) add_subdirectory(shader_compiler) diff --git a/modules/material/CMakeLists.txt b/modules/material/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d5b654cc6d00ce77d93b4666f48b7a5097e674b3 --- /dev/null +++ b/modules/material/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.16) +project(vkcv_material) + +# setting c++ standard for the module +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(vkcv_material_source ${PROJECT_SOURCE_DIR}/src) +set(vkcv_material_include ${PROJECT_SOURCE_DIR}/include) + +# Add source and header files to the module +set(vkcv_material_sources + ${vkcv_material_include}/vkcv/material/Material.hpp + ${vkcv_material_source}/vkcv/material/Material.cpp + ${vkcv_material_include}/vkcv/material/PBRMaterial.hpp + ${vkcv_material_source}/vkcv/material/PBRMaterial.cpp +) + +# adding source files to the module +add_library(vkcv_material STATIC ${vkcv_material_sources}) + +# link the required libraries to the module +target_link_libraries(vkcv_material vkcv ${vkcv_libraries}) + +# including headers of dependencies and the VkCV framework +target_include_directories(vkcv_material SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes}) + +# add the own include directory for public headers +target_include_directories(vkcv_material BEFORE PUBLIC ${vkcv_material_include}) diff --git a/modules/material/include/vkcv/material/Material.hpp b/modules/material/include/vkcv/material/Material.hpp new file mode 100644 index 0000000000000000000000000000000000000000..00b492072fa4ef8b7b41f70202d515ee4ac828fa --- /dev/null +++ b/modules/material/include/vkcv/material/Material.hpp @@ -0,0 +1,14 @@ +#pragma once +#include <vkcv/Handles.hpp> + +namespace vkcv::material { + + class Material { + private: + public: + const DescriptorSetHandle m_DescriptorSetHandle; + protected: + Material(const DescriptorSetHandle& setHandle); + }; + +} diff --git a/modules/material/include/vkcv/material/PBRMaterial.hpp b/modules/material/include/vkcv/material/PBRMaterial.hpp new file mode 100644 index 0000000000000000000000000000000000000000..09a5214b0e748a09ef8caefe5bf2b1a69ecbd8e1 --- /dev/null +++ b/modules/material/include/vkcv/material/PBRMaterial.hpp @@ -0,0 +1,103 @@ +#pragma once + +#include <vector> + +#include <vkcv/DescriptorConfig.hpp> +#include <vkcv/Core.hpp> + + +#include "Material.hpp" + +namespace vkcv::material +{ + class PBRMaterial : Material + { + private: + struct vec3 { + float x, y, z; + }; + struct vec4 { + float x, y, z, a; + }; + PBRMaterial(const ImageHandle& colorImg, + const SamplerHandle& colorSmp, + const ImageHandle& normalImg, + const SamplerHandle& normalSmp, + const ImageHandle& metRoughImg, + const SamplerHandle& metRoughSmp, + const ImageHandle& occlusionImg, + const SamplerHandle& occlusionSmp, + const ImageHandle& emissiveImg, + const SamplerHandle& emissiveSmp, + const DescriptorSetHandle& setHandle, + vec4 baseColorFactor, + float metallicFactor, + float roughnessFactor, + float normalScale, + float occlusionStrength, + vec3 emissiveFactor) noexcept; + + + public: + PBRMaterial() = delete; + + const ImageHandle m_ColorTexture; + const SamplerHandle m_ColorSampler; + + const ImageHandle m_NormalTexture; + const SamplerHandle m_NormalSampler; + + const ImageHandle m_MetRoughTexture; + const SamplerHandle m_MetRoughSampler; + + const ImageHandle m_OcclusionTexture; + const SamplerHandle m_OcclusionSampler; + + const ImageHandle m_EmissiveTexture; + const SamplerHandle m_EmissiveSampler; + + // + const vec4 m_BaseColorFactor; + const float m_MetallicFactor; + const float m_RoughnessFactor; + const float m_NormalScale; + const float m_OcclusionStrength; + const vec3 m_EmissiveFactor; + + /* + * Returns the material's necessary descriptor bindings which serves as its descriptor layout + * The binding is in the following order: + * 0 - diffuse texture + * 1 - diffuse sampler + * 2 - normal texture + * 3 - normal sampler + * 4 - metallic roughness texture + * 5 - metallic roughness sampler + * 6 - occlusion texture + * 7 - occlusion sampler + * 8 - emissive texture + * 9 - emissive sampler + */ + static std::vector<DescriptorBinding> getDescriptorBindings() noexcept; + + static PBRMaterial create( + vkcv::Core* core, + ImageHandle &colorImg, + SamplerHandle &colorSmp, + ImageHandle &normalImg, + SamplerHandle &normalSmp, + ImageHandle &metRoughImg, + SamplerHandle &metRoughSmp, + ImageHandle &occlusionImg, + SamplerHandle &occlusionSmp, + ImageHandle &emissiveImg, + SamplerHandle &emissiveSmp, + vec4 baseColorFactor, + float metallicFactor, + float roughnessFactor, + float normalScale, + float occlusionStrength, + vec3 emissiveFactor); + + }; +} \ No newline at end of file diff --git a/modules/material/src/vkcv/material/Material.cpp b/modules/material/src/vkcv/material/Material.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9168bcfbf924e9868ceaaff74aef5d3c6b99739c --- /dev/null +++ b/modules/material/src/vkcv/material/Material.cpp @@ -0,0 +1,12 @@ + +#include "vkcv/material/Material.hpp" + +namespace vkcv::material { + + //TODO + + Material::Material(const DescriptorSetHandle& setHandle) : m_DescriptorSetHandle(setHandle) + { + } + +} diff --git a/modules/material/src/vkcv/material/PBRMaterial.cpp b/modules/material/src/vkcv/material/PBRMaterial.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d27e755c06a39e369d22efc997a0b411d067c132 --- /dev/null +++ b/modules/material/src/vkcv/material/PBRMaterial.cpp @@ -0,0 +1,194 @@ +#include "vkcv/material/PBRMaterial.hpp" + + +namespace vkcv::material +{ + PBRMaterial::PBRMaterial( + const ImageHandle& colorImg, + const SamplerHandle& colorSmp, + const ImageHandle& normalImg, + const SamplerHandle& normalSmp, + const ImageHandle& metRoughImg, + const SamplerHandle& metRoughSmp, + const ImageHandle& occlusionImg, + const SamplerHandle& occlusionSmp, + const ImageHandle& emissiveImg, + const SamplerHandle& emissiveSmp, + const DescriptorSetHandle& setHandle, + vec4 baseColorFactor, + float metallicFactor, + float roughnessFactor, + float normalScale, + float occlusionStrength, + vec3 emissiveFactor) noexcept : + m_ColorTexture(colorImg), + m_ColorSampler(colorSmp), + m_NormalTexture(normalImg), + m_NormalSampler(normalSmp), + m_MetRoughTexture(metRoughImg), + m_MetRoughSampler(metRoughSmp), + m_OcclusionTexture(occlusionImg), + m_OcclusionSampler(occlusionSmp), + m_EmissiveTexture(emissiveImg), + m_EmissiveSampler(emissiveSmp), + Material(setHandle), + m_BaseColorFactor(baseColorFactor), + m_MetallicFactor(metallicFactor), + m_RoughnessFactor(roughnessFactor), + m_NormalScale(normalScale), + m_OcclusionStrength(occlusionStrength), + m_EmissiveFactor(emissiveFactor) + { + } + + std::vector<DescriptorBinding> PBRMaterial::getDescriptorBindings() noexcept + { + static std::vector<DescriptorBinding> bindings; + + if (bindings.empty()) { + bindings.emplace_back(0, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); + bindings.emplace_back(1, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); + bindings.emplace_back(2, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); + bindings.emplace_back(3, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); + bindings.emplace_back(4, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); + bindings.emplace_back(5, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); + bindings.emplace_back(6, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); + bindings.emplace_back(7, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); + bindings.emplace_back(8, DescriptorType::IMAGE_SAMPLED, 1, ShaderStage::FRAGMENT); + bindings.emplace_back(9, DescriptorType::SAMPLER, 1, ShaderStage::FRAGMENT); + } + + return bindings; + } + + PBRMaterial PBRMaterial::create( + vkcv::Core* core, + ImageHandle& colorImg, + SamplerHandle& colorSmp, + ImageHandle& normalImg, + SamplerHandle& normalSmp, + ImageHandle& metRoughImg, + SamplerHandle& metRoughSmp, + ImageHandle& occlusionImg, + SamplerHandle& occlusionSmp, + ImageHandle& emissiveImg, + SamplerHandle& emissiveSmp, + vec4 baseColorFactor, + float metallicFactor, + float roughnessFactor, + float normalScale, + float occlusionStrength, + vec3 emissiveFactor) + { + //Test if Images and samplers valid, if not use default + if (!colorImg) { + vkcv::Image defaultColor = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1); + vec4 colorData{ 228, 51, 255,1 }; + defaultColor.fill(&colorData); + colorImg = defaultColor.getHandle(); + } + if (!normalImg) { + vkcv::Image defaultNormal = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1); + vec4 normalData{ 0, 0, 1,0 }; + defaultNormal.fill(&normalData); + normalImg = defaultNormal.getHandle(); + } + if (!metRoughImg) { + vkcv::Image defaultRough = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1); + vec4 roughData{ 228, 51, 255,1 }; + defaultRough.fill(&roughData); + metRoughImg = defaultRough.getHandle(); + } + if (!occlusionImg) { + vkcv::Image defaultOcclusion = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1); + vec4 occlusionData{ 228, 51, 255,1 }; + defaultOcclusion.fill(&occlusionData); + occlusionImg = defaultOcclusion.getHandle(); + } + if (!emissiveImg) { + vkcv::Image defaultEmissive = core->createImage(vk::Format::eR8G8B8A8Srgb, 1, 1); + vec4 emissiveData{ 0, 0, 0,1 }; + defaultEmissive.fill(&emissiveData); + emissiveImg = defaultEmissive.getHandle(); + } + if (!colorSmp) { + colorSmp = core->createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + if (!normalSmp) { + normalSmp = core->createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + if (!metRoughSmp) { + metRoughSmp = core->createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + if (!occlusionSmp) { + occlusionSmp = core->createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + if (!emissiveSmp) { + emissiveSmp = core->createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT + ); + } + + + + //create descriptorset + vkcv::DescriptorSetHandle descriptorSetHandle = core->createDescriptorSet(getDescriptorBindings()); + //writes + vkcv::DescriptorWrites setWrites; + setWrites.sampledImageWrites = { + vkcv::SampledImageDescriptorWrite(0, colorImg), + vkcv::SampledImageDescriptorWrite(2, normalImg), + vkcv::SampledImageDescriptorWrite(4, metRoughImg), + vkcv::SampledImageDescriptorWrite(6, occlusionImg), + vkcv::SampledImageDescriptorWrite(8, emissiveImg) }; + setWrites.samplerWrites = { + vkcv::SamplerDescriptorWrite(1, colorSmp), + vkcv::SamplerDescriptorWrite(3, normalSmp), + vkcv::SamplerDescriptorWrite(5, metRoughSmp), + vkcv::SamplerDescriptorWrite(7, occlusionSmp), + vkcv::SamplerDescriptorWrite(9, emissiveSmp) }; + core->writeDescriptorSet(descriptorSetHandle, setWrites); + + return PBRMaterial( + colorImg, + colorSmp, + normalImg, + normalSmp, + metRoughImg, + metRoughSmp, + occlusionImg, + occlusionSmp, + emissiveImg, + emissiveSmp, + descriptorSetHandle, + baseColorFactor, + metallicFactor, + roughnessFactor, + normalScale, + occlusionStrength, + emissiveFactor); + } +} \ No newline at end of file diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 1492b1afa563543e6a9eef380295bcb71fef58b8..59f2cf3b652a88854b9ea4a4077f18749b9e6d51 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -462,6 +462,16 @@ namespace vkcv supportColorAttachment); } + const uint32_t Core::getImageWidth(ImageHandle imageHandle) + { + return m_ImageManager->getImageWidth(imageHandle); + } + + const uint32_t Core::getImageHeight(ImageHandle imageHandle) + { + return m_ImageManager->getImageHeight(imageHandle); + } + DescriptorSetHandle Core::createDescriptorSet(const std::vector<DescriptorBinding>& bindings) { return m_DescriptorManager->createDescriptorSet(bindings);