2023-05-26 16:19:12 +08:00
2023-05-17 14:49:05 +08:00
/*
* Vulkan Example - glTF scene loading and rendering
*
* Copyright ( C ) 2020 - 2022 by Sascha Willems - www . saschawillems . de
*
* This code is licensed under the MIT license ( MIT ) ( http : //opensource.org/licenses/MIT)
*/
/*
* Shows how to load and display a simple scene from a glTF file
* Note that this isn ' t a complete glTF loader and only basic functions are shown here
* This means no complex materials , no animations , no skins , etc .
* For details on how glTF 2.0 works , see the official spec at https : //github.com/KhronosGroup/glTF/tree/master/specification/2.0
*
* Other samples will load models using a dedicated model loader with more features ( see base / VulkanglTFModel . hpp )
*
* If you are looking for a complete glTF implementation , check out https : //github.com/SaschaWillems/Vulkan-glTF-PBR/
*/
2023-05-26 14:12:02 +08:00
2023-05-26 16:19:12 +08:00
# ifndef TINYGLTF_IMPLEMENTATION
# define TINYGLTF_IMPLEMENTATION
# endif
# ifndef STB_IMAGE_IMPLEMENTATION
# define STB_IMAGE_IMPLEMENTATION
# endif
2023-05-26 14:12:02 +08:00
2023-05-26 16:19:12 +08:00
# ifndef TINYGLTF_NO_STB_IMAGE_WRITE
# define TINYGLTF_NO_STB_IMAGE_WRITE
# endif
2023-05-26 14:12:02 +08:00
2023-05-26 16:19:12 +08:00
# include "render.h"
2023-06-01 00:05:36 +08:00
# include "GUIFunction.h"
2023-05-26 14:12:02 +08:00
2023-05-17 14:53:31 +08:00
2023-05-25 16:13:37 +08:00
VulkanExample : : VulkanExample ( ) :
VulkanExampleBase ( ENABLE_VALIDATION )
2023-05-17 14:49:05 +08:00
{
2023-05-26 16:19:12 +08:00
title = " render " ;
2023-05-17 14:49:05 +08:00
camera . type = Camera : : CameraType : : lookat ;
camera . flipY = true ;
camera . setPosition ( glm : : vec3 ( 0.0f , - 0.1f , - 1.0f ) ) ;
camera . setRotation ( glm : : vec3 ( 0.0f , 45.0f , 0.0f ) ) ;
camera . setPerspective ( 60.0f , ( float ) width / ( float ) height , 0.1f , 256.0f ) ;
}
2023-05-25 16:13:37 +08:00
void VulkanExample : : getEnabledFeatures ( )
2023-05-17 14:53:31 +08:00
{
// Fill mode non solid is required for wireframe display
if ( deviceFeatures . fillModeNonSolid ) {
enabledFeatures . fillModeNonSolid = VK_TRUE ;
} ;
}
2023-05-17 14:49:05 +08:00
2023-05-25 16:13:37 +08:00
void VulkanExample : : setupFrameBuffer ( )
{
VulkanExampleBase : : setupFrameBuffer ( ) ;
if ( pbrFrameBuffer . bCreate & & ( pbrFrameBuffer . fbo . width ! = width | | pbrFrameBuffer . fbo . height ! = height ) )
{
pbrFrameBuffer . color . destroy ( device ) ;
pbrFrameBuffer . depth . destroy ( device ) ;
pbrFrameBuffer . fbo . destroy ( device ) ;
vkDestroySampler ( device , colorSampler , nullptr ) ;
}
2023-05-23 11:30:21 +08:00
2023-05-25 16:13:37 +08:00
//Create image color attachment
pbrFrameBuffer . fbo . setSize ( width , height ) ;
VkFormat attDepthFormat ;
VkBool32 validDepthFormat = vks : : tools : : getSupportedDepthFormat ( physicalDevice , & attDepthFormat ) ;
assert ( validDepthFormat ) ;
2023-05-23 15:52:04 +08:00
2023-05-25 16:13:37 +08:00
createAttachment ( VK_FORMAT_R8G8B8A8_UNORM , VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT , & pbrFrameBuffer . color , width , height ) ;
createAttachment ( attDepthFormat , VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT , & pbrFrameBuffer . depth , width , height ) ;
{
std : : array < VkAttachmentDescription , 2 > attachs = { } ;
for ( uint32_t i = 0 ; i < static_cast < uint32_t > ( attachs . size ( ) ) ; + + i )
{
attachs [ i ] . samples = VK_SAMPLE_COUNT_1_BIT ;
attachs [ i ] . loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
attachs [ i ] . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
attachs [ i ] . stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE ;
attachs [ i ] . stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE ;
attachs [ i ] . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
attachs [ i ] . finalLayout = i = = 1 ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ;
}
attachs [ 0 ] . format = pbrFrameBuffer . color . format ;
attachs [ 1 ] . format = pbrFrameBuffer . depth . format ;
VkAttachmentReference colorReference = { } ;
colorReference . attachment = 0 ;
colorReference . layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ;
VkAttachmentReference depthReference = { } ;
depthReference . attachment = 1 ;
depthReference . layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ;
VkSubpassDescription subpass = { } ;
subpass . pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS ;
subpass . pColorAttachments = & colorReference ;
subpass . colorAttachmentCount = 1 ;
subpass . pDepthStencilAttachment = & depthReference ;
std : : array < VkSubpassDependency , 2 > dependencies ;
//To test src 0
dependencies [ 0 ] . srcSubpass = VK_SUBPASS_EXTERNAL ;
dependencies [ 0 ] . dstSubpass = 0 ;
dependencies [ 0 ] . srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT ;
dependencies [ 0 ] . dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
dependencies [ 0 ] . srcAccessMask = VK_ACCESS_SHADER_READ_BIT ;
dependencies [ 0 ] . dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
dependencies [ 0 ] . dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT ;
dependencies [ 1 ] . srcSubpass = 0 ;
dependencies [ 1 ] . dstSubpass = VK_SUBPASS_EXTERNAL ;
dependencies [ 1 ] . srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
dependencies [ 1 ] . dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT ;
dependencies [ 1 ] . srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
dependencies [ 1 ] . dstAccessMask = VK_ACCESS_SHADER_READ_BIT ;
dependencies [ 1 ] . dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT ;
VkRenderPassCreateInfo renderPassCI = { } ;
renderPassCI . sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO ;
renderPassCI . pAttachments = attachs . data ( ) ;
renderPassCI . attachmentCount = static_cast < uint32_t > ( attachs . size ( ) ) ;
renderPassCI . pSubpasses = & subpass ;
renderPassCI . subpassCount = 1 ;
renderPassCI . pDependencies = dependencies . data ( ) ;
renderPassCI . dependencyCount = 2 ;
VK_CHECK_RESULT ( vkCreateRenderPass ( device , & renderPassCI , nullptr , & pbrFrameBuffer . fbo . renderPass ) ) ;
//Create FBO
VkImageView attachments [ 2 ] = { pbrFrameBuffer . color . imageView , pbrFrameBuffer . depth . imageView } ;
VkFramebufferCreateInfo fbufCreateInfo = vks : : initializers : : framebufferCreateInfo ( ) ;
fbufCreateInfo . renderPass = pbrFrameBuffer . fbo . renderPass ;
fbufCreateInfo . pAttachments = attachments ;
fbufCreateInfo . attachmentCount = 2 ;
fbufCreateInfo . width = pbrFrameBuffer . fbo . width ;
fbufCreateInfo . height = pbrFrameBuffer . fbo . height ;
fbufCreateInfo . layers = 1 ;
VK_CHECK_RESULT ( vkCreateFramebuffer ( device , & fbufCreateInfo , nullptr , & pbrFrameBuffer . fbo . frameBuffer ) ) ;
}
2023-05-23 15:52:04 +08:00
2023-05-25 16:13:37 +08:00
//Create Image sampler
VkSamplerCreateInfo samplerCI = vks : : initializers : : samplerCreateInfo ( ) ;
samplerCI . magFilter = VK_FILTER_NEAREST ;
samplerCI . minFilter = VK_FILTER_NEAREST ;
samplerCI . mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR ;
samplerCI . addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerCI . addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerCI . addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
//samplerCI.mipLodBias = 0.0f;
//samplerCI.maxAnisotropy = 1.0f;
samplerCI . minLod = 0.0f ;
samplerCI . maxLod = 1.0f ;
samplerCI . borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE ;
VK_CHECK_RESULT ( vkCreateSampler ( device , & samplerCI , nullptr , & colorSampler ) ) ;
2023-05-23 17:32:20 +08:00
2023-05-25 16:13:37 +08:00
if ( tonemappingDescriptorSet ! = VK_NULL_HANDLE ) //Bad logic
{
auto imageInfo = vks : : initializers : : descriptorImageInfo ( colorSampler , pbrFrameBuffer . color . imageView , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ) ;
VkWriteDescriptorSet writeDescriptorSet = vks : : initializers : : writeDescriptorSet ( tonemappingDescriptorSet , VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 0 , & imageInfo ) ;
vkUpdateDescriptorSets ( device , 1 , & writeDescriptorSet , 0 , nullptr ) ;
}
pbrFrameBuffer . bCreate = true ;
2023-05-23 17:32:20 +08:00
}
2023-05-17 14:49:05 +08:00
2023-05-25 16:27:50 +08:00
void VulkanExample : : buildCommandBuffers ( )
2023-05-17 14:49:05 +08:00
{
VkCommandBufferBeginInfo cmdBufInfo = vks : : initializers : : commandBufferBeginInfo ( ) ;
VkClearValue clearValues [ 2 ] ;
2023-05-17 14:53:31 +08:00
clearValues [ 0 ] . color = defaultClearColor ;
2023-05-25 00:29:04 +08:00
clearValues [ 0 ] . color = { { 0.25f , 0.25f , 0.25f , 1.0f } } ;
2023-05-17 14:49:05 +08:00
clearValues [ 1 ] . depthStencil = { 1.0f , 0 } ;
VkRenderPassBeginInfo renderPassBeginInfo = vks : : initializers : : renderPassBeginInfo ( ) ;
2023-05-25 00:29:04 +08:00
renderPassBeginInfo . renderPass = pbrFrameBuffer . fbo . renderPass ;
2023-05-17 14:49:05 +08:00
renderPassBeginInfo . renderArea . offset . x = 0 ;
renderPassBeginInfo . renderArea . offset . y = 0 ;
renderPassBeginInfo . renderArea . extent . width = width ;
renderPassBeginInfo . renderArea . extent . height = height ;
renderPassBeginInfo . clearValueCount = 2 ;
renderPassBeginInfo . pClearValues = clearValues ;
const VkViewport viewport = vks : : initializers : : viewport ( ( float ) width , ( float ) height , 0.0f , 1.0f ) ;
const VkRect2D scissor = vks : : initializers : : rect2D ( width , height , 0 , 0 ) ;
for ( int32_t i = 0 ; i < drawCmdBuffers . size ( ) ; + + i )
{
2023-05-25 00:29:04 +08:00
renderPassBeginInfo . framebuffer = pbrFrameBuffer . fbo . frameBuffer ;
2023-05-17 14:49:05 +08:00
VK_CHECK_RESULT ( vkBeginCommandBuffer ( drawCmdBuffers [ i ] , & cmdBufInfo ) ) ;
vkCmdBeginRenderPass ( drawCmdBuffers [ i ] , & renderPassBeginInfo , VK_SUBPASS_CONTENTS_INLINE ) ;
vkCmdSetViewport ( drawCmdBuffers [ i ] , 0 , 1 , & viewport ) ;
vkCmdSetScissor ( drawCmdBuffers [ i ] , 0 , 1 , & scissor ) ;
// Bind scene matrices descriptor to set 0
2023-05-25 00:29:04 +08:00
vkCmdBindDescriptorSets ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelineLayouts . pbrLayout , 0 , 1 , & descriptorSet , 0 , nullptr ) ;
vkCmdBindDescriptorSets ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelineLayouts . pbrLayout , 6 , 1 , & skinDescriptorSet , 0 , nullptr ) ;
2023-05-17 14:49:05 +08:00
vkCmdBindPipeline ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , wireframe ? pipelines . wireframe : pipelines . solid ) ;
2023-05-26 16:19:12 +08:00
glTFModel . draw ( drawCmdBuffers [ i ] , pipelineLayouts . pbrLayout , false ) ;
2023-05-17 14:49:05 +08:00
vkCmdEndRenderPass ( drawCmdBuffers [ i ] ) ;
2023-05-23 17:32:20 +08:00
2023-05-25 00:29:04 +08:00
{
VkRenderPassBeginInfo renderPassBeginInfo = vks : : initializers : : renderPassBeginInfo ( ) ;
renderPassBeginInfo . renderPass = renderPass ;
renderPassBeginInfo . framebuffer = VulkanExampleBase : : frameBuffers [ i ] ;
renderPassBeginInfo . renderArea . extent . width = width ;
renderPassBeginInfo . renderArea . extent . height = height ;
renderPassBeginInfo . clearValueCount = 2 ;
renderPassBeginInfo . pClearValues = clearValues ;
vkCmdBeginRenderPass ( drawCmdBuffers [ i ] , & renderPassBeginInfo , VK_SUBPASS_CONTENTS_INLINE ) ;
vkCmdSetViewport ( drawCmdBuffers [ i ] , 0 , 1 , & viewport ) ;
vkCmdSetScissor ( drawCmdBuffers [ i ] , 0 , 1 , & scissor ) ;
vkCmdBindDescriptorSets ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelineLayouts . tonemappingLayout , 0 , 1 , & tonemappingDescriptorSet , 0 , NULL ) ;
2023-05-25 15:29:34 +08:00
vkCmdBindPipeline ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelines . toneMapping ) ;
2023-05-25 00:29:04 +08:00
vkCmdDraw ( drawCmdBuffers [ i ] , 3 , 1 , 0 , 0 ) ;
drawUI ( drawCmdBuffers [ i ] ) ;
vkCmdEndRenderPass ( drawCmdBuffers [ i ] ) ;
}
2023-05-17 14:49:05 +08:00
VK_CHECK_RESULT ( vkEndCommandBuffer ( drawCmdBuffers [ i ] ) ) ;
}
}
2023-05-25 16:13:37 +08:00
void VulkanExample : : loadglTFFile ( std : : string filename , VulkanglTFModel & model , bool bSkyboxFlag = false )
2023-05-17 14:49:05 +08:00
{
tinygltf : : Model glTFInput ;
tinygltf : : TinyGLTF gltfContext ;
std : : string error , warning ;
this - > device = device ;
# if defined(__ANDROID__)
// On Android all assets are packed with the apk in a compressed form, so we need to open them using the asset manager
// We let tinygltf handle this, by passing the asset manager of our app
tinygltf : : asset_manager = androidApp - > activity - > assetManager ;
# endif
bool fileLoaded = gltfContext . LoadASCIIFromFile ( & glTFInput , & error , & warning , filename ) ;
// Pass some Vulkan resources required for setup and rendering to the glTF model loading class
2023-05-25 00:29:04 +08:00
model . vulkanDevice = vulkanDevice ;
model . copyQueue = queue ;
2023-05-17 14:49:05 +08:00
std : : vector < uint32_t > indexBuffer ;
std : : vector < VulkanglTFModel : : Vertex > vertexBuffer ;
2023-05-17 14:53:31 +08:00
if ( fileLoaded ) {
2023-05-25 00:29:04 +08:00
model . nodeCount = static_cast < uint32_t > ( glTFInput . nodes . size ( ) ) ;
model . loadImages ( glTFInput ) ;
model . loadMaterials ( glTFInput ) ;
model . loadTextures ( glTFInput ) ;
2023-05-17 14:49:05 +08:00
const tinygltf : : Scene & scene = glTFInput . scenes [ 0 ] ;
for ( size_t i = 0 ; i < scene . nodes . size ( ) ; i + + ) {
const tinygltf : : Node node = glTFInput . nodes [ scene . nodes [ i ] ] ;
2023-05-25 00:29:04 +08:00
model . loadNode ( node , glTFInput , nullptr , scene . nodes [ i ] , indexBuffer , vertexBuffer ) ;
2023-05-17 14:49:05 +08:00
}
2023-05-25 00:29:04 +08:00
model . loadAnimations ( glTFInput ) ;
2023-05-17 14:49:05 +08:00
}
else {
vks : : tools : : exitFatal ( " Could not open the glTF file. \n \n The file is part of the additional asset pack. \n \n Run \" download_assets.py \" in the repository root to download the latest version. " , - 1 ) ;
return ;
}
// Create and upload vertex and index buffer
// We will be using one single vertex buffer and one single index buffer for the whole glTF scene
// Primitives (of the glTF model) will then index into these using index offsets
size_t vertexBufferSize = vertexBuffer . size ( ) * sizeof ( VulkanglTFModel : : Vertex ) ;
size_t indexBufferSize = indexBuffer . size ( ) * sizeof ( uint32_t ) ;
2023-05-25 00:29:04 +08:00
model . indices . count = static_cast < uint32_t > ( indexBuffer . size ( ) ) ;
2023-05-17 14:49:05 +08:00
struct StagingBuffer {
VkBuffer buffer ;
VkDeviceMemory memory ;
} vertexStaging , indexStaging ;
// Create host visible staging buffers (source)
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_TRANSFER_SRC_BIT ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,
vertexBufferSize ,
& vertexStaging . buffer ,
& vertexStaging . memory ,
vertexBuffer . data ( ) ) ) ;
// Index data
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_TRANSFER_SRC_BIT ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,
indexBufferSize ,
& indexStaging . buffer ,
& indexStaging . memory ,
indexBuffer . data ( ) ) ) ;
// Create device local buffers (target)
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT ,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ,
vertexBufferSize ,
2023-05-25 00:29:04 +08:00
& model . vertices . buffer ,
& model . vertices . memory ) ) ;
2023-05-17 14:49:05 +08:00
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT ,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ,
indexBufferSize ,
2023-05-25 00:29:04 +08:00
& model . indices . buffer ,
& model . indices . memory ) ) ;
2023-05-17 14:49:05 +08:00
// Copy data from staging buffers (host) do device local buffer (gpu)
VkCommandBuffer copyCmd = vulkanDevice - > createCommandBuffer ( VK_COMMAND_BUFFER_LEVEL_PRIMARY , true ) ;
VkBufferCopy copyRegion = { } ;
copyRegion . size = vertexBufferSize ;
vkCmdCopyBuffer (
copyCmd ,
vertexStaging . buffer ,
2023-05-25 00:29:04 +08:00
model . vertices . buffer ,
2023-05-17 14:49:05 +08:00
1 ,
& copyRegion ) ;
copyRegion . size = indexBufferSize ;
vkCmdCopyBuffer (
copyCmd ,
indexStaging . buffer ,
2023-05-25 00:29:04 +08:00
model . indices . buffer ,
2023-05-17 14:49:05 +08:00
1 ,
& copyRegion ) ;
vulkanDevice - > flushCommandBuffer ( copyCmd , queue , true ) ;
// Free staging resources
vkDestroyBuffer ( device , vertexStaging . buffer , nullptr ) ;
vkFreeMemory ( device , vertexStaging . memory , nullptr ) ;
vkDestroyBuffer ( device , indexStaging . buffer , nullptr ) ;
vkFreeMemory ( device , indexStaging . memory , nullptr ) ;
}
2023-05-25 16:27:50 +08:00
void VulkanExample : : loadAssets ( )
2023-05-17 14:49:05 +08:00
{
2023-05-25 16:13:37 +08:00
loadglTFFile ( getAssetPath ( ) + " buster_drone/busterDrone.gltf " , glTFModel ) ;
2023-05-24 16:10:36 +08:00
loadglTFFile ( getAssetPath ( ) + " models/cube.gltf " , skyboxModel , true ) ;
ibltextures . skyboxCube . loadFromFile ( getAssetPath ( ) + " textures/hdr/pisa_cube.ktx " , VK_FORMAT_R16G16B16A16_SFLOAT , vulkanDevice , queue ) ;
2023-05-17 14:49:05 +08:00
}
2023-05-25 16:27:50 +08:00
void VulkanExample : : setupDescriptors ( )
2023-05-17 14:49:05 +08:00
{
/*
This sample uses separate descriptor sets ( and layouts ) for the matrices and materials ( textures )
*/
2023-05-25 16:13:37 +08:00
//Descriptor Pool Alloc
{
std : : vector < VkDescriptorPoolSize > poolSizes = {
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , 4 ) ,
// One combined image sampler per model image/texture
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , static_cast < uint32_t > ( glTFModel . images . size ( ) ) ) ,
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 4 ) , // Add aditional sampler descriptor
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_STORAGE_BUFFER , 1 )
} ;
// One set for matrices and one per model image/texture
const uint32_t maxSetCount = static_cast < uint32_t > ( glTFModel . images . size ( ) ) + 6 ;
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks : : initializers : : descriptorPoolCreateInfo ( poolSizes , maxSetCount ) ;
VK_CHECK_RESULT ( vkCreateDescriptorPool ( device , & descriptorPoolInfo , nullptr , & descriptorPool ) ) ;
}
2023-05-17 14:49:05 +08:00
2023-05-25 16:13:37 +08:00
// Descriptor set layout for passing matrices ---and precompute texture add in this descriptor
std : : vector < VkDescriptorSetLayoutBinding > setLayoutBindings =
2023-05-24 11:12:54 +08:00
{
vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT , 0 ) ,
vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , VK_SHADER_STAGE_FRAGMENT_BIT , 1 ) ,
vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , VK_SHADER_STAGE_FRAGMENT_BIT , 2 ) ,
vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , VK_SHADER_STAGE_FRAGMENT_BIT , 3 ) ,
2023-05-17 14:49:05 +08:00
} ;
2023-05-24 11:12:54 +08:00
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI = vks : : initializers : : descriptorSetLayoutCreateInfo ( setLayoutBindings ) ;
2023-05-17 14:49:05 +08:00
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device , & descriptorSetLayoutCI , nullptr , & descriptorSetLayouts . matrices ) ) ;
2023-05-25 00:29:04 +08:00
2023-05-24 11:12:54 +08:00
VkDescriptorSetLayoutBinding materialBufferLayoutBinding = vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , VK_SHADER_STAGE_FRAGMENT_BIT , 0 ) ;
descriptorSetLayoutCI = vks : : initializers : : descriptorSetLayoutCreateInfo ( & materialBufferLayoutBinding , 1 ) ;
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device , & descriptorSetLayoutCI , nullptr , & descriptorSetLayouts . materialUniform ) ) ;
2023-05-25 00:29:04 +08:00
2023-05-17 14:49:05 +08:00
// Descriptor set layout for passing material textures
2023-05-24 11:12:54 +08:00
VkDescriptorSetLayoutBinding setLayoutBinding = vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , VK_SHADER_STAGE_FRAGMENT_BIT , 0 ) ;
descriptorSetLayoutCI = vks : : initializers : : descriptorSetLayoutCreateInfo ( & setLayoutBinding , 1 ) ;
2023-05-17 14:49:05 +08:00
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device , & descriptorSetLayoutCI , nullptr , & descriptorSetLayouts . textures ) ) ;
2023-05-24 11:12:54 +08:00
setLayoutBinding = vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_STORAGE_BUFFER , VK_SHADER_STAGE_VERTEX_BIT , 0 ) ;
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device , & descriptorSetLayoutCI , nullptr , & descriptorSetLayouts . ssbo ) ) ;
2023-05-25 16:13:37 +08:00
//Pbr pipeline layout
2023-05-24 11:12:54 +08:00
{
2023-05-25 16:13:37 +08:00
// Pipeline layout using both descriptor sets (set 0 = matrices, set 1 = material)
std : : array < VkDescriptorSetLayout , 7 > setLayouts =
{ descriptorSetLayouts . matrices ,
descriptorSetLayouts . textures ,
descriptorSetLayouts . textures ,
descriptorSetLayouts . textures ,
descriptorSetLayouts . textures ,
descriptorSetLayouts . materialUniform ,
descriptorSetLayouts . ssbo
} ;
VkPipelineLayoutCreateInfo pipelineLayoutCI = vks : : initializers : : pipelineLayoutCreateInfo ( setLayouts . data ( ) , static_cast < uint32_t > ( setLayouts . size ( ) ) ) ;
VK_CHECK_RESULT ( vkCreatePipelineLayout ( device , & pipelineLayoutCI , nullptr , & pipelineLayouts . pbrLayout ) ) ;
// Descriptor set for scene matrices
VkDescriptorSetAllocateInfo allocInfo = vks : : initializers : : descriptorSetAllocateInfo ( descriptorPool , & descriptorSetLayouts . matrices , 1 ) ;
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & descriptorSet ) ) ;
std : : vector < VkWriteDescriptorSet > writeDescriptorSets =
{
vks : : initializers : : writeDescriptorSet ( descriptorSet , VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , 0 , & shaderData . buffer . descriptor ) ,
vks : : initializers : : writeDescriptorSet ( descriptorSet , VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 1 , & ibltextures . irradianceCube . descriptor ) ,
vks : : initializers : : writeDescriptorSet ( descriptorSet , VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 2 , & ibltextures . lutBrdf . descriptor ) ,
vks : : initializers : : writeDescriptorSet ( descriptorSet , VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 3 , & ibltextures . prefilteredCube . descriptor ) ,
} ;
vkUpdateDescriptorSets ( device , 4 , writeDescriptorSets . data ( ) , 0 , nullptr ) ;
for ( auto & material : glTFModel . materials )
{
const VkDescriptorSetAllocateInfo allocInfo = vks : : initializers : : descriptorSetAllocateInfo ( descriptorPool , & descriptorSetLayouts . materialUniform , 1 ) ;
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & material . materialData . descriptorSet ) ) ;
VkWriteDescriptorSet writeDescriptorSet = vks : : initializers : : writeDescriptorSet (
material . materialData . descriptorSet , VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , 0 , & material . materialData . buffer . descriptor ) ;
vkUpdateDescriptorSets ( device , 1 , & writeDescriptorSet , 0 , nullptr ) ;
}
2023-05-24 11:12:54 +08:00
2023-05-25 16:13:37 +08:00
// Descriptor sets for materials
for ( auto & image : glTFModel . images ) {
const VkDescriptorSetAllocateInfo allocInfo = vks : : initializers : : descriptorSetAllocateInfo ( descriptorPool , & descriptorSetLayouts . textures , 1 ) ;
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & image . descriptorSet ) ) ;
VkWriteDescriptorSet writeDescriptorSet = vks : : initializers : : writeDescriptorSet ( image . descriptorSet , VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 0 , & image . texture . descriptor ) ;
vkUpdateDescriptorSets ( device , 1 , & writeDescriptorSet , 0 , nullptr ) ;
}
{
const VkDescriptorSetAllocateInfo allocInfo = vks : : initializers : : descriptorSetAllocateInfo ( descriptorPool , & descriptorSetLayouts . ssbo , 1 ) ;
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & skinDescriptorSet ) ) ;
VkWriteDescriptorSet writeDescriptorSet = vks : : initializers : : writeDescriptorSet ( skinDescriptorSet , VK_DESCRIPTOR_TYPE_STORAGE_BUFFER , 0 , & shaderData . skinSSBO . descriptor ) ;
vkUpdateDescriptorSets ( device , 1 , & writeDescriptorSet , 0 , nullptr ) ;
}
2023-05-17 14:49:05 +08:00
}
2023-05-25 16:13:37 +08:00
//Tone Mapping pipeline layout
{
auto pipelineLayoutCI = vks : : initializers : : pipelineLayoutCreateInfo ( & descriptorSetLayouts . textures , 1 ) ;
VK_CHECK_RESULT ( vkCreatePipelineLayout ( device , & pipelineLayoutCI , nullptr , & pipelineLayouts . tonemappingLayout ) ) ;
2023-05-17 14:49:05 +08:00
const VkDescriptorSetAllocateInfo allocInfo = vks : : initializers : : descriptorSetAllocateInfo ( descriptorPool , & descriptorSetLayouts . textures , 1 ) ;
2023-05-25 16:13:37 +08:00
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & tonemappingDescriptorSet ) ) ;
auto imageInfo = vks : : initializers : : descriptorImageInfo ( colorSampler , pbrFrameBuffer . color . imageView , VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ) ;
VkWriteDescriptorSet writeDescriptorSet = vks : : initializers : : writeDescriptorSet ( tonemappingDescriptorSet , VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 0 , & imageInfo ) ;
2023-05-17 14:49:05 +08:00
vkUpdateDescriptorSets ( device , 1 , & writeDescriptorSet , 0 , nullptr ) ;
}
}
2023-05-25 16:27:50 +08:00
void VulkanExample : : preparePipelines ( )
2023-05-17 14:49:05 +08:00
{
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks : : initializers : : pipelineInputAssemblyStateCreateInfo ( VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , 0 , VK_FALSE ) ;
VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks : : initializers : : pipelineRasterizationStateCreateInfo ( VK_POLYGON_MODE_FILL , VK_CULL_MODE_BACK_BIT , VK_FRONT_FACE_COUNTER_CLOCKWISE , 0 ) ;
VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks : : initializers : : pipelineColorBlendAttachmentState ( 0xf , VK_FALSE ) ;
VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks : : initializers : : pipelineColorBlendStateCreateInfo ( 1 , & blendAttachmentStateCI ) ;
VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks : : initializers : : pipelineDepthStencilStateCreateInfo ( VK_TRUE , VK_TRUE , VK_COMPARE_OP_LESS_OR_EQUAL ) ;
VkPipelineViewportStateCreateInfo viewportStateCI = vks : : initializers : : pipelineViewportStateCreateInfo ( 1 , 1 , 0 ) ;
VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks : : initializers : : pipelineMultisampleStateCreateInfo ( VK_SAMPLE_COUNT_1_BIT , 0 ) ;
const std : : vector < VkDynamicState > dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR } ;
VkPipelineDynamicStateCreateInfo dynamicStateCI = vks : : initializers : : pipelineDynamicStateCreateInfo ( dynamicStateEnables . data ( ) , static_cast < uint32_t > ( dynamicStateEnables . size ( ) ) , 0 ) ;
// Vertex input bindings and attributes
const std : : vector < VkVertexInputBindingDescription > vertexInputBindings = {
vks : : initializers : : vertexInputBindingDescription ( 0 , sizeof ( VulkanglTFModel : : Vertex ) , VK_VERTEX_INPUT_RATE_VERTEX ) ,
} ;
const std : : vector < VkVertexInputAttributeDescription > vertexInputAttributes = {
vks : : initializers : : vertexInputAttributeDescription ( 0 , 0 , VK_FORMAT_R32G32B32_SFLOAT , offsetof ( VulkanglTFModel : : Vertex , pos ) ) , // Location 0: Position
vks : : initializers : : vertexInputAttributeDescription ( 0 , 1 , VK_FORMAT_R32G32B32_SFLOAT , offsetof ( VulkanglTFModel : : Vertex , normal ) ) , // Location 1: Normal
vks : : initializers : : vertexInputAttributeDescription ( 0 , 2 , VK_FORMAT_R32G32B32_SFLOAT , offsetof ( VulkanglTFModel : : Vertex , uv ) ) , // Location 2: Texture coordinates
vks : : initializers : : vertexInputAttributeDescription ( 0 , 3 , VK_FORMAT_R32G32B32_SFLOAT , offsetof ( VulkanglTFModel : : Vertex , color ) ) , // Location 3: Color
2023-05-24 17:07:38 +08:00
vks : : initializers : : vertexInputAttributeDescription ( 0 , 4 , VK_FORMAT_R32G32B32_SFLOAT , offsetof ( VulkanglTFModel : : Vertex , tangent ) ) , // Location 4 : Tangent
2023-05-17 14:49:05 +08:00
} ;
VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks : : initializers : : pipelineVertexInputStateCreateInfo ( ) ;
vertexInputStateCI . vertexBindingDescriptionCount = static_cast < uint32_t > ( vertexInputBindings . size ( ) ) ;
vertexInputStateCI . pVertexBindingDescriptions = vertexInputBindings . data ( ) ;
vertexInputStateCI . vertexAttributeDescriptionCount = static_cast < uint32_t > ( vertexInputAttributes . size ( ) ) ;
vertexInputStateCI . pVertexAttributeDescriptions = vertexInputAttributes . data ( ) ;
2023-05-25 11:38:10 +08:00
std : : array < VkPipelineShaderStageCreateInfo , 2 > shaderStages = {
2023-05-17 14:49:05 +08:00
loadShader ( getHomeworkShadersPath ( ) + " homework1/mesh.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ,
loadShader ( getHomeworkShadersPath ( ) + " homework1/mesh.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT )
} ;
2023-05-24 17:07:38 +08:00
VkGraphicsPipelineCreateInfo pipelineCI = vks : : initializers : : pipelineCreateInfo ( pipelineLayouts . pbrLayout , pbrFrameBuffer . fbo . renderPass , 0 ) ;
2023-05-17 14:49:05 +08:00
pipelineCI . pVertexInputState = & vertexInputStateCI ;
pipelineCI . pInputAssemblyState = & inputAssemblyStateCI ;
pipelineCI . pRasterizationState = & rasterizationStateCI ;
pipelineCI . pColorBlendState = & colorBlendStateCI ;
pipelineCI . pMultisampleState = & multisampleStateCI ;
pipelineCI . pViewportState = & viewportStateCI ;
pipelineCI . pDepthStencilState = & depthStencilStateCI ;
pipelineCI . pDynamicState = & dynamicStateCI ;
pipelineCI . stageCount = static_cast < uint32_t > ( shaderStages . size ( ) ) ;
pipelineCI . pStages = shaderStages . data ( ) ;
// Solid rendering pipeline
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCI , nullptr , & pipelines . solid ) ) ;
// Wire frame rendering pipeline
if ( deviceFeatures . fillModeNonSolid ) {
rasterizationStateCI . polygonMode = VK_POLYGON_MODE_LINE ;
rasterizationStateCI . lineWidth = 1.0f ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCI , nullptr , & pipelines . wireframe ) ) ;
}
2023-05-25 11:38:10 +08:00
//Create Tone Mapping render pipeline
2023-05-25 16:13:37 +08:00
CreateToneMappingPipeline ( ) ;
2023-05-17 14:49:05 +08:00
}
2023-05-24 17:07:38 +08:00
2023-05-25 16:13:37 +08:00
void VulkanExample : : CreateToneMappingPipeline ( )
2023-05-24 11:12:54 +08:00
{
2023-05-25 15:29:34 +08:00
if ( pipelines . toneMapping ! = VK_NULL_HANDLE )
2023-05-24 11:12:54 +08:00
{
2023-05-25 15:29:34 +08:00
vkDestroyPipeline ( device , pipelines . toneMapping , nullptr ) ;
pipelines . toneMapping = VK_NULL_HANDLE ;
2023-05-24 11:12:54 +08:00
}
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks : : initializers : : pipelineInputAssemblyStateCreateInfo ( VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , 0 , VK_FALSE ) ;
2023-05-25 16:13:37 +08:00
VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks : : initializers : : pipelineRasterizationStateCreateInfo ( VK_POLYGON_MODE_FILL , VK_CULL_MODE_NONE , VK_FRONT_FACE_COUNTER_CLOCKWISE , 0 ) ;
2023-05-24 11:12:54 +08:00
VkPipelineColorBlendAttachmentState blendAttachmentStateCI = vks : : initializers : : pipelineColorBlendAttachmentState ( 0xf , VK_FALSE ) ;
VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks : : initializers : : pipelineColorBlendStateCreateInfo ( 1 , & blendAttachmentStateCI ) ;
2023-05-25 16:13:37 +08:00
VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks : : initializers : : pipelineDepthStencilStateCreateInfo ( VK_FALSE , VK_FALSE , VK_COMPARE_OP_LESS_OR_EQUAL ) ;
2023-05-24 11:12:54 +08:00
VkPipelineViewportStateCreateInfo viewportStateCI = vks : : initializers : : pipelineViewportStateCreateInfo ( 1 , 1 , 0 ) ;
VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks : : initializers : : pipelineMultisampleStateCreateInfo ( VK_SAMPLE_COUNT_1_BIT , 0 ) ;
const std : : vector < VkDynamicState > dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR } ;
VkPipelineDynamicStateCreateInfo dynamicStateCI = vks : : initializers : : pipelineDynamicStateCreateInfo ( dynamicStateEnables . data ( ) , static_cast < uint32_t > ( dynamicStateEnables . size ( ) ) , 0 ) ;
VkPipelineVertexInputStateCreateInfo emptyInputState = vks : : initializers : : pipelineVertexInputStateCreateInfo ( ) ;
2023-05-25 16:13:37 +08:00
2023-05-24 11:12:54 +08:00
const std : : string fragPath = ToneMapping ? " homework1/tonemapping_enable.frag.spv " : " homework1/tonemapping_disable.frag.spv " ;
std : : array < VkPipelineShaderStageCreateInfo , 2 > shaderStages = {
loadShader ( getHomeworkShadersPath ( ) + " homework1/genbrdflut.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ,
loadShader ( getHomeworkShadersPath ( ) + fragPath , VK_SHADER_STAGE_FRAGMENT_BIT )
} ;
VkGraphicsPipelineCreateInfo pipelineCI = vks : : initializers : : pipelineCreateInfo ( pipelineLayouts . tonemappingLayout , renderPass , 0 ) ;
pipelineCI . pVertexInputState = & emptyInputState ;
pipelineCI . pInputAssemblyState = & inputAssemblyStateCI ;
pipelineCI . pRasterizationState = & rasterizationStateCI ;
pipelineCI . pColorBlendState = & colorBlendStateCI ;
pipelineCI . pMultisampleState = & multisampleStateCI ;
pipelineCI . pViewportState = & viewportStateCI ;
pipelineCI . pDepthStencilState = & depthStencilStateCI ;
pipelineCI . pDynamicState = & dynamicStateCI ;
pipelineCI . stageCount = static_cast < uint32_t > ( shaderStages . size ( ) ) ;
pipelineCI . pStages = shaderStages . data ( ) ;
2023-05-25 15:29:34 +08:00
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCI , nullptr , & pipelines . toneMapping ) ) ;
2023-05-17 14:49:05 +08:00
}
2023-05-25 16:13:37 +08:00
//----------------------------Prepare precompute Lighting or BRDF LUT-----------------------------------------------//
//Irradiance map for diffuse lighting
void VulkanExample : : GenerateIrradianceCubemap ( )
2023-05-17 14:49:05 +08:00
{
2023-05-25 16:13:37 +08:00
auto tStart = std : : chrono : : high_resolution_clock : : now ( ) ;
2023-05-24 16:10:36 +08:00
constexpr VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT ;
constexpr int32_t dim = 64 ;
const uint32_t numMips = static_cast < uint32_t > ( floor ( log2 ( dim ) ) ) + 1 ;
VkImageCreateInfo imageCI = vks : : initializers : : imageCreateInfo ( ) ;
imageCI . imageType = VK_IMAGE_TYPE_2D ;
imageCI . format = format ;
imageCI . extent . width = dim ;
imageCI . extent . height = dim ;
imageCI . extent . depth = 1 ;
imageCI . mipLevels = numMips ;
imageCI . arrayLayers = 6 ;
imageCI . samples = VK_SAMPLE_COUNT_1_BIT ;
imageCI . tiling = VK_IMAGE_TILING_OPTIMAL ;
imageCI . usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT ;
imageCI . flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT ;
VK_CHECK_RESULT ( vkCreateImage ( device , & imageCI , nullptr , & ibltextures . irradianceCube . image ) )
VkMemoryAllocateInfo memAlloc = vks : : initializers : : memoryAllocateInfo ( ) ;
VkMemoryRequirements memReqs ;
vkGetImageMemoryRequirements ( device , ibltextures . irradianceCube . image , & memReqs ) ;
memAlloc . allocationSize = memReqs . size ;
memAlloc . memoryTypeIndex = vulkanDevice - > getMemoryType ( memReqs . memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ) ;
VK_CHECK_RESULT ( vkAllocateMemory ( device , & memAlloc , nullptr , & ibltextures . irradianceCube . deviceMemory ) )
VK_CHECK_RESULT ( vkBindImageMemory ( device , ibltextures . irradianceCube . image , ibltextures . irradianceCube . deviceMemory , 0 ) )
VkImageViewCreateInfo viewCI = vks : : initializers : : imageViewCreateInfo ( ) ;
viewCI . viewType = VK_IMAGE_VIEW_TYPE_CUBE ;
viewCI . format = format ;
viewCI . subresourceRange = { } ;
viewCI . subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
viewCI . subresourceRange . levelCount = numMips ;
viewCI . subresourceRange . layerCount = 6 ;
viewCI . image = ibltextures . irradianceCube . image ;
VK_CHECK_RESULT ( vkCreateImageView ( device , & viewCI , nullptr , & ibltextures . irradianceCube . view ) )
VkSamplerCreateInfo samplerCI = vks : : initializers : : samplerCreateInfo ( ) ;
samplerCI . magFilter = VK_FILTER_LINEAR ;
samplerCI . minFilter = VK_FILTER_LINEAR ;
samplerCI . mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR ;
samplerCI . addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerCI . addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerCI . addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerCI . minLod = 0.0f ;
samplerCI . maxLod = static_cast < float > ( numMips ) ;
samplerCI . borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE ;
VK_CHECK_RESULT ( vkCreateSampler ( device , & samplerCI , nullptr , & ibltextures . irradianceCube . sampler ) )
ibltextures . irradianceCube . descriptor . imageView = ibltextures . irradianceCube . view ;
ibltextures . irradianceCube . descriptor . sampler = ibltextures . irradianceCube . sampler ;
ibltextures . irradianceCube . descriptor . imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ;
ibltextures . irradianceCube . device = vulkanDevice ;
//Setup Framebuffer and so on
2023-05-25 16:13:37 +08:00
VkAttachmentDescription attDesc = { } ;
attDesc . format = format ;
attDesc . samples = VK_SAMPLE_COUNT_1_BIT ;
attDesc . loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
attDesc . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
attDesc . stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE ;
attDesc . stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE ;
attDesc . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
attDesc . finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ;
2023-05-24 16:10:36 +08:00
VkAttachmentReference colorReference = { 0 , VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } ;
VkSubpassDescription subpassDescription = { } ;
subpassDescription . pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS ;
subpassDescription . colorAttachmentCount = 1 ;
subpassDescription . pColorAttachments = & colorReference ;
std : : array < VkSubpassDependency , 2 > dependencies ;
dependencies [ 0 ] . srcSubpass = VK_SUBPASS_EXTERNAL ;
dependencies [ 0 ] . dstSubpass = 0 ;
dependencies [ 0 ] . srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT ;
dependencies [ 0 ] . dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
dependencies [ 0 ] . srcAccessMask = VK_ACCESS_MEMORY_READ_BIT ;
dependencies [ 0 ] . dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
dependencies [ 0 ] . dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT ;
dependencies [ 1 ] . srcSubpass = 0 ;
dependencies [ 1 ] . dstSubpass = VK_SUBPASS_EXTERNAL ;
dependencies [ 1 ] . srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
dependencies [ 1 ] . dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT ;
dependencies [ 1 ] . srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
dependencies [ 1 ] . dstAccessMask = VK_ACCESS_MEMORY_READ_BIT ;
dependencies [ 1 ] . dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT ;
2023-05-25 16:13:37 +08:00
2023-05-24 16:10:36 +08:00
VkRenderPassCreateInfo renderPassCI = vks : : initializers : : renderPassCreateInfo ( ) ;
renderPassCI . attachmentCount = 1 ;
2023-05-25 16:13:37 +08:00
renderPassCI . pAttachments = & attDesc ;
2023-05-24 16:10:36 +08:00
renderPassCI . subpassCount = 1 ;
renderPassCI . pSubpasses = & subpassDescription ;
renderPassCI . dependencyCount = 2 ;
renderPassCI . pDependencies = dependencies . data ( ) ;
VkRenderPass renderpass ;
VK_CHECK_RESULT ( vkCreateRenderPass ( device , & renderPassCI , nullptr , & renderpass ) ) ;
2023-05-25 16:13:37 +08:00
{
VkImageCreateInfo imageCreateInfo = vks : : initializers : : imageCreateInfo ( ) ;
imageCreateInfo . imageType = VK_IMAGE_TYPE_2D ;
imageCreateInfo . format = format ;
imageCreateInfo . extent . width = dim ;
imageCreateInfo . extent . height = dim ;
imageCreateInfo . extent . depth = 1 ;
imageCreateInfo . mipLevels = 1 ;
imageCreateInfo . arrayLayers = 1 ;
imageCreateInfo . samples = VK_SAMPLE_COUNT_1_BIT ;
imageCreateInfo . tiling = VK_IMAGE_TILING_OPTIMAL ;
imageCreateInfo . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
imageCreateInfo . usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT ;
imageCreateInfo . sharingMode = VK_SHARING_MODE_EXCLUSIVE ;
VK_CHECK_RESULT ( vkCreateImage ( device , & imageCreateInfo , nullptr , & offscreen . image ) )
VkMemoryAllocateInfo memAlloc = vks : : initializers : : memoryAllocateInfo ( ) ;
VkMemoryRequirements memReqs ;
vkGetImageMemoryRequirements ( device , offscreen . image , & memReqs ) ;
memAlloc . allocationSize = memReqs . size ;
memAlloc . memoryTypeIndex = vulkanDevice - > getMemoryType ( memReqs . memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ) ;
VK_CHECK_RESULT ( vkAllocateMemory ( device , & memAlloc , nullptr , & offscreen . memory ) )
VK_CHECK_RESULT ( vkBindImageMemory ( device , offscreen . image , offscreen . memory , 0 ) )
VkImageViewCreateInfo colorImageView = vks : : initializers : : imageViewCreateInfo ( ) ;
colorImageView . viewType = VK_IMAGE_VIEW_TYPE_2D ;
colorImageView . format = format ;
colorImageView . flags = 0 ;
colorImageView . subresourceRange = { } ;
colorImageView . subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
colorImageView . subresourceRange . baseMipLevel = 0 ;
colorImageView . subresourceRange . levelCount = 1 ;
colorImageView . subresourceRange . baseArrayLayer = 0 ;
colorImageView . subresourceRange . layerCount = 1 ;
colorImageView . image = offscreen . image ;
VK_CHECK_RESULT ( vkCreateImageView ( device , & colorImageView , nullptr , & offscreen . view ) )
VkFramebufferCreateInfo fbufCreateInfo = vks : : initializers : : framebufferCreateInfo ( ) ;
fbufCreateInfo . renderPass = renderpass ;
fbufCreateInfo . attachmentCount = 1 ;
fbufCreateInfo . pAttachments = & offscreen . view ;
fbufCreateInfo . width = dim ;
fbufCreateInfo . height = dim ;
fbufCreateInfo . layers = 1 ;
VK_CHECK_RESULT ( vkCreateFramebuffer ( device , & fbufCreateInfo , nullptr , & offscreen . framebuffer ) )
VkCommandBuffer layoutCmd = vulkanDevice - > createCommandBuffer ( VK_COMMAND_BUFFER_LEVEL_PRIMARY , true ) ;
vks : : tools : : setImageLayout (
layoutCmd ,
offscreen . image ,
VK_IMAGE_ASPECT_COLOR_BIT ,
VK_IMAGE_LAYOUT_UNDEFINED ,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ) ;
vulkanDevice - > flushCommandBuffer ( layoutCmd , queue , true ) ;
}
2023-05-24 16:10:36 +08:00
VkDescriptorSetLayout descriptorsetlayout ;
std : : vector < VkDescriptorSetLayoutBinding > setLayoutBindings =
2023-05-25 16:13:37 +08:00
{
vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , VK_SHADER_STAGE_FRAGMENT_BIT , 0 ) ,
} ;
2023-05-24 16:10:36 +08:00
VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks : : initializers : : descriptorSetLayoutCreateInfo ( setLayoutBindings ) ;
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device , & descriptorsetlayoutCI , nullptr , & descriptorsetlayout ) ) ;
2023-05-25 16:13:37 +08:00
2023-05-24 16:10:36 +08:00
std : : vector < VkDescriptorPoolSize > poolSizes = { vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 1 ) } ;
VkDescriptorPoolCreateInfo descriptorPoolCI = vks : : initializers : : descriptorPoolCreateInfo ( poolSizes , 2 ) ;
VkDescriptorPool descriptorpool ;
VK_CHECK_RESULT ( vkCreateDescriptorPool ( device , & descriptorPoolCI , nullptr , & descriptorpool ) ) ;
2023-05-25 16:13:37 +08:00
2023-05-24 16:10:36 +08:00
VkDescriptorSet descriptorset ;
2023-05-25 16:13:37 +08:00
VkDescriptorSetAllocateInfo allocInfo = vks : : initializers : : descriptorSetAllocateInfo ( descriptorpool , & descriptorsetlayout , 1 ) ;
2023-05-24 16:10:36 +08:00
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & descriptorset ) ) ;
VkWriteDescriptorSet writeDescriptorSet = vks : : initializers : : writeDescriptorSet ( descriptorset , VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 0 , & ibltextures . skyboxCube . descriptor ) ;
vkUpdateDescriptorSets ( device , 1 , & writeDescriptorSet , 0 , nullptr ) ;
2023-05-25 16:13:37 +08:00
2023-05-24 16:10:36 +08:00
VkPipelineLayout pipelinelayout ;
std : : vector < VkPushConstantRange > pushConstantRanges =
2023-05-25 16:13:37 +08:00
{
vks : : initializers : : pushConstantRange ( VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT , sizeof ( IrradiancePushBlock ) , 0 )
} ;
2023-05-24 16:10:36 +08:00
VkPipelineLayoutCreateInfo pipelineLayoutCI = vks : : initializers : : pipelineLayoutCreateInfo ( & descriptorsetlayout , 1 ) ;
pipelineLayoutCI . pushConstantRangeCount = 1 ;
pipelineLayoutCI . pPushConstantRanges = pushConstantRanges . data ( ) ;
VK_CHECK_RESULT ( vkCreatePipelineLayout ( device , & pipelineLayoutCI , nullptr , & pipelinelayout ) ) ;
//Pipeline Setting
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks : : initializers : : pipelineInputAssemblyStateCreateInfo ( VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , 0 , VK_FALSE ) ;
VkPipelineRasterizationStateCreateInfo rasterizationState = vks : : initializers : : pipelineRasterizationStateCreateInfo ( VK_POLYGON_MODE_FILL , VK_CULL_MODE_NONE , VK_FRONT_FACE_COUNTER_CLOCKWISE ) ;
VkPipelineColorBlendAttachmentState blendAttachmentState = vks : : initializers : : pipelineColorBlendAttachmentState ( 0xf , VK_FALSE ) ;
VkPipelineColorBlendStateCreateInfo colorBlendState = vks : : initializers : : pipelineColorBlendStateCreateInfo ( 1 , & blendAttachmentState ) ;
VkPipelineDepthStencilStateCreateInfo depthStencilState = vks : : initializers : : pipelineDepthStencilStateCreateInfo ( VK_FALSE , VK_FALSE , VK_COMPARE_OP_LESS_OR_EQUAL ) ;
VkPipelineViewportStateCreateInfo viewportState = vks : : initializers : : pipelineViewportStateCreateInfo ( 1 , 1 ) ;
VkPipelineMultisampleStateCreateInfo multisampleState = vks : : initializers : : pipelineMultisampleStateCreateInfo ( VK_SAMPLE_COUNT_1_BIT ) ;
std : : vector < VkDynamicState > dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR } ;
VkPipelineDynamicStateCreateInfo dynamicState = vks : : initializers : : pipelineDynamicStateCreateInfo ( dynamicStateEnables ) ;
std : : array < VkPipelineShaderStageCreateInfo , 2 > shaderStages ;
2023-05-25 16:13:37 +08:00
const std : : vector < VkVertexInputBindingDescription > vertexInputBindings =
2023-05-24 16:10:36 +08:00
{
vks : : initializers : : vertexInputBindingDescription ( 0 , sizeof ( VulkanglTFModel : : Vertex ) , VK_VERTEX_INPUT_RATE_VERTEX ) ,
} ;
const std : : vector < VkVertexInputAttributeDescription > vertexInputAttributes = {
vks : : initializers : : vertexInputAttributeDescription ( 0 , 0 , VK_FORMAT_R32G32B32_SFLOAT , offsetof ( VulkanglTFModel : : Vertex , pos ) ) , // Location 0: Position
2023-05-25 16:13:37 +08:00
//vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, normal)),// Location 1: Normal
//vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, uv)), // Location 2: Texture coordinates
//vks::initializers::vertexInputAttributeDescription(0, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, color)), // Location 3: Color
//vks::initializers::vertexInputAttributeDescription(0, 4, VK_FORMAT_R32G32B32_SFLOAT, offsetof(VulkanglTFModel::Vertex, tangent)), // Location 4 : Tangent
2023-05-24 16:10:36 +08:00
} ;
VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks : : initializers : : pipelineVertexInputStateCreateInfo ( ) ;
vertexInputStateCI . vertexBindingDescriptionCount = static_cast < uint32_t > ( vertexInputBindings . size ( ) ) ;
vertexInputStateCI . pVertexBindingDescriptions = vertexInputBindings . data ( ) ;
vertexInputStateCI . vertexAttributeDescriptionCount = static_cast < uint32_t > ( vertexInputAttributes . size ( ) ) ;
vertexInputStateCI . pVertexAttributeDescriptions = vertexInputAttributes . data ( ) ;
VkGraphicsPipelineCreateInfo pipelineCI = vks : : initializers : : pipelineCreateInfo ( pipelinelayout , renderpass ) ;
pipelineCI . pInputAssemblyState = & inputAssemblyState ;
pipelineCI . pRasterizationState = & rasterizationState ;
pipelineCI . pColorBlendState = & colorBlendState ;
pipelineCI . pMultisampleState = & multisampleState ;
pipelineCI . pViewportState = & viewportState ;
pipelineCI . pDepthStencilState = & depthStencilState ;
pipelineCI . pDynamicState = & dynamicState ;
pipelineCI . stageCount = 2 ;
pipelineCI . pStages = shaderStages . data ( ) ;
pipelineCI . renderPass = renderpass ;
pipelineCI . pVertexInputState = & vertexInputStateCI ;
shaderStages [ 0 ] = loadShader ( getHomeworkShadersPath ( ) + " homework1/filtercube.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = loadShader ( getHomeworkShadersPath ( ) + " homework1/irradiancecube.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
VkPipeline pipeline ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCI , nullptr , & pipeline ) ) ;
2023-05-25 16:13:37 +08:00
//Render
2023-05-24 16:10:36 +08:00
VkClearValue clearValues [ 1 ] ;
clearValues [ 0 ] . color = { { 0.0f , 0.0f , 0.2f , 0.0f } } ;
VkRenderPassBeginInfo renderPassBeginInfo = vks : : initializers : : renderPassBeginInfo ( ) ;
renderPassBeginInfo . renderPass = renderpass ;
renderPassBeginInfo . framebuffer = offscreen . framebuffer ;
renderPassBeginInfo . renderArea . extent . width = dim ;
renderPassBeginInfo . renderArea . extent . height = dim ;
renderPassBeginInfo . clearValueCount = 1 ;
renderPassBeginInfo . pClearValues = clearValues ;
//six face in cube map
std : : vector < glm : : mat4 > matrices = {
// POSITIVE_X
glm : : rotate ( glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( 90.0f ) , glm : : vec3 ( 0.0f , 1.0f , 0.0f ) ) , glm : : radians ( 180.0f ) , glm : : vec3 ( 1.0f , 0.0f , 0.0f ) ) ,
// NEGATIVE_X
glm : : rotate ( glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( - 90.0f ) , glm : : vec3 ( 0.0f , 1.0f , 0.0f ) ) , glm : : radians ( 180.0f ) , glm : : vec3 ( 1.0f , 0.0f , 0.0f ) ) ,
// POSITIVE_Y
glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( - 90.0f ) , glm : : vec3 ( 1.0f , 0.0f , 0.0f ) ) ,
// NEGATIVE_Y
glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( 90.0f ) , glm : : vec3 ( 1.0f , 0.0f , 0.0f ) ) ,
// POSITIVE_Z
glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( 180.0f ) , glm : : vec3 ( 1.0f , 0.0f , 0.0f ) ) ,
// NEGATIVE_Z
glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( 180.0f ) , glm : : vec3 ( 0.0f , 0.0f , 1.0f ) ) ,
} ;
VkCommandBuffer cmdBuf = vulkanDevice - > createCommandBuffer ( VK_COMMAND_BUFFER_LEVEL_PRIMARY , true ) ;
VkViewport viewport = vks : : initializers : : viewport ( ( float ) dim , ( float ) dim , 0.0f , 1.0f ) ;
VkRect2D scissor = vks : : initializers : : rect2D ( dim , dim , 0 , 0 ) ;
2023-05-25 16:13:37 +08:00
2023-05-24 16:10:36 +08:00
vkCmdSetViewport ( cmdBuf , 0 , 1 , & viewport ) ;
vkCmdSetScissor ( cmdBuf , 0 , 1 , & scissor ) ;
2023-05-25 16:13:37 +08:00
2023-05-24 16:10:36 +08:00
VkImageSubresourceRange subresourceRange = { } ;
subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
subresourceRange . baseMipLevel = 0 ;
subresourceRange . levelCount = numMips ;
subresourceRange . layerCount = 6 ;
2023-05-25 16:13:37 +08:00
2023-05-24 16:10:36 +08:00
vks : : tools : : setImageLayout (
2023-05-25 16:13:37 +08:00
cmdBuf ,
ibltextures . irradianceCube . image ,
VK_IMAGE_LAYOUT_UNDEFINED ,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,
subresourceRange ) ;
2023-05-24 16:10:36 +08:00
2023-05-25 16:13:37 +08:00
for ( uint32_t m = 0 ; m < numMips ; + + m )
2023-05-24 16:10:36 +08:00
{
2023-05-25 16:13:37 +08:00
for ( uint32_t f = 0 ; f < 6 ; + + f )
2023-05-24 16:10:36 +08:00
{
viewport . width = static_cast < float > ( dim * std : : pow ( 0.5f , m ) ) ;
viewport . height = static_cast < float > ( dim * std : : pow ( 0.5f , m ) ) ;
vkCmdSetViewport ( cmdBuf , 0 , 1 , & viewport ) ;
// Render scene from cube face's point of view
vkCmdBeginRenderPass ( cmdBuf , & renderPassBeginInfo , VK_SUBPASS_CONTENTS_INLINE ) ;
2023-05-25 16:13:37 +08:00
irradiancePushBlock . mvp = glm : : perspective ( ( float ) ( M_PI / 2.0 ) , 1.0f , 0.1f , 512.0f ) * matrices [ f ] ;
vkCmdPushConstants ( cmdBuf , pipelinelayout , VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT , 0 , sizeof ( IrradiancePushBlock ) , & irradiancePushBlock ) ;
2023-05-24 16:10:36 +08:00
vkCmdBindPipeline ( cmdBuf , VK_PIPELINE_BIND_POINT_GRAPHICS , pipeline ) ;
vkCmdBindDescriptorSets ( cmdBuf , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelinelayout , 0 , 1 , & descriptorset , 0 , NULL ) ;
2023-05-25 16:13:37 +08:00
skyboxModel . draw ( cmdBuf , pipelinelayout , false ) ;
2023-05-24 16:10:36 +08:00
vkCmdEndRenderPass ( cmdBuf ) ;
vks : : tools : : setImageLayout (
cmdBuf ,
offscreen . image ,
VK_IMAGE_ASPECT_COLOR_BIT ,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ) ;
VkImageCopy copyRegion = { } ;
copyRegion . srcSubresource . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
copyRegion . srcSubresource . layerCount = 1 ;
copyRegion . srcSubresource . mipLevel = 0 ;
copyRegion . srcSubresource . baseArrayLayer = 0 ;
copyRegion . dstSubresource . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
copyRegion . dstSubresource . layerCount = 1 ;
copyRegion . dstSubresource . mipLevel = m ;
copyRegion . dstSubresource . baseArrayLayer = f ;
copyRegion . extent . width = static_cast < uint32_t > ( viewport . width ) ;
copyRegion . extent . height = static_cast < uint32_t > ( viewport . height ) ;
copyRegion . extent . depth = 1 ;
vkCmdCopyImage (
cmdBuf ,
offscreen . image ,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ,
ibltextures . irradianceCube . image ,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,
1 ,
& copyRegion ) ;
vks : : tools : : setImageLayout ( cmdBuf ,
offscreen . image ,
VK_IMAGE_ASPECT_COLOR_BIT ,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
2023-05-25 16:13:37 +08:00
) ;
2023-05-24 16:10:36 +08:00
}
}
vks : : tools : : setImageLayout ( cmdBuf ,
ibltextures . irradianceCube . image ,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ,
subresourceRange ) ;
vulkanDevice - > flushCommandBuffer ( cmdBuf , queue ) ;
vkDestroyRenderPass ( device , renderpass , nullptr ) ;
vkDestroyFramebuffer ( device , offscreen . framebuffer , nullptr ) ;
vkFreeMemory ( device , offscreen . memory , nullptr ) ;
vkDestroyImageView ( device , offscreen . view , nullptr ) ;
vkDestroyImage ( device , offscreen . image , nullptr ) ;
vkDestroyDescriptorPool ( device , descriptorpool , nullptr ) ;
vkDestroyDescriptorSetLayout ( device , descriptorsetlayout , nullptr ) ;
vkDestroyPipeline ( device , pipeline , nullptr ) ;
vkDestroyPipelineLayout ( device , pipelinelayout , nullptr ) ;
auto tEnd = std : : chrono : : high_resolution_clock : : now ( ) ;
auto tDiff = std : : chrono : : duration < double , std : : milli > ( tEnd - tStart ) . count ( ) ;
std : : cout < < " Generating irradiance cube with " < < numMips < < " mip levels took " < < tDiff < < " ms " < < std : : endl ;
}
2023-05-25 16:13:37 +08:00
void VulkanExample : : GeneratePrefilteredCubemap ( )
2023-05-24 16:10:36 +08:00
{
auto tStart = std : : chrono : : high_resolution_clock : : now ( ) ;
constexpr VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT ;
constexpr int32_t dim = 512 ;
const uint32_t numMips = static_cast < uint32_t > ( floor ( log2 ( dim ) ) ) + 1 ;
VkImageCreateInfo imageCI = vks : : initializers : : imageCreateInfo ( ) ;
imageCI . imageType = VK_IMAGE_TYPE_2D ;
imageCI . format = format ;
imageCI . extent . width = dim ;
imageCI . extent . height = dim ;
imageCI . extent . depth = 1 ;
imageCI . mipLevels = numMips ;
imageCI . arrayLayers = 6 ;
imageCI . samples = VK_SAMPLE_COUNT_1_BIT ;
imageCI . tiling = VK_IMAGE_TILING_OPTIMAL ;
imageCI . usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT ;
imageCI . flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT ;
VK_CHECK_RESULT ( vkCreateImage ( device , & imageCI , nullptr , & ibltextures . prefilteredCube . image ) ) ;
VkMemoryAllocateInfo memAlloc = vks : : initializers : : memoryAllocateInfo ( ) ;
VkMemoryRequirements memReqs ;
vkGetImageMemoryRequirements ( device , ibltextures . prefilteredCube . image , & memReqs ) ;
memAlloc . allocationSize = memReqs . size ;
memAlloc . memoryTypeIndex = vulkanDevice - > getMemoryType ( memReqs . memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ) ;
VK_CHECK_RESULT ( vkAllocateMemory ( device , & memAlloc , nullptr , & ibltextures . prefilteredCube . deviceMemory ) ) ;
VK_CHECK_RESULT ( vkBindImageMemory ( device , ibltextures . prefilteredCube . image , ibltextures . prefilteredCube . deviceMemory , 0 ) ) ;
// Image view
VkImageViewCreateInfo viewCI = vks : : initializers : : imageViewCreateInfo ( ) ;
viewCI . viewType = VK_IMAGE_VIEW_TYPE_CUBE ;
viewCI . format = format ;
viewCI . subresourceRange = { } ;
viewCI . subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
viewCI . subresourceRange . levelCount = numMips ;
viewCI . subresourceRange . layerCount = 6 ;
viewCI . image = ibltextures . prefilteredCube . image ;
VK_CHECK_RESULT ( vkCreateImageView ( device , & viewCI , nullptr , & ibltextures . prefilteredCube . view ) ) ;
// Sampler
VkSamplerCreateInfo samplerCI = vks : : initializers : : samplerCreateInfo ( ) ;
samplerCI . magFilter = VK_FILTER_LINEAR ;
samplerCI . minFilter = VK_FILTER_LINEAR ;
samplerCI . mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR ;
samplerCI . addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerCI . addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerCI . addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerCI . minLod = 0.0f ;
samplerCI . maxLod = static_cast < float > ( numMips ) ;
samplerCI . borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE ;
VK_CHECK_RESULT ( vkCreateSampler ( device , & samplerCI , nullptr , & ibltextures . prefilteredCube . sampler ) ) ;
ibltextures . prefilteredCube . descriptor . imageView = ibltextures . prefilteredCube . view ;
ibltextures . prefilteredCube . descriptor . sampler = ibltextures . prefilteredCube . sampler ;
ibltextures . prefilteredCube . descriptor . imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ;
ibltextures . prefilteredCube . device = vulkanDevice ;
// FB, Att, RP, Pipe, etc.
VkAttachmentDescription attDesc = { } ;
// Color attachment
attDesc . format = format ;
attDesc . samples = VK_SAMPLE_COUNT_1_BIT ;
attDesc . loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
attDesc . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
attDesc . stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE ;
attDesc . stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE ;
attDesc . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
attDesc . finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ;
VkAttachmentReference colorReference = { 0 , VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } ;
VkSubpassDescription subpassDescription = { } ;
subpassDescription . pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS ;
subpassDescription . colorAttachmentCount = 1 ;
subpassDescription . pColorAttachments = & colorReference ;
// Use subpass dependencies for layout transitions
std : : array < VkSubpassDependency , 2 > dependencies ;
dependencies [ 0 ] . srcSubpass = VK_SUBPASS_EXTERNAL ;
dependencies [ 0 ] . dstSubpass = 0 ;
dependencies [ 0 ] . srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT ;
dependencies [ 0 ] . dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
dependencies [ 0 ] . srcAccessMask = VK_ACCESS_MEMORY_READ_BIT ;
dependencies [ 0 ] . dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
dependencies [ 0 ] . dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT ;
dependencies [ 1 ] . srcSubpass = 0 ;
dependencies [ 1 ] . dstSubpass = VK_SUBPASS_EXTERNAL ;
dependencies [ 1 ] . srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
dependencies [ 1 ] . dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT ;
dependencies [ 1 ] . srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
dependencies [ 1 ] . dstAccessMask = VK_ACCESS_MEMORY_READ_BIT ;
dependencies [ 1 ] . dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT ;
// Renderpass
VkRenderPassCreateInfo renderPassCI = vks : : initializers : : renderPassCreateInfo ( ) ;
renderPassCI . attachmentCount = 1 ;
renderPassCI . pAttachments = & attDesc ;
renderPassCI . subpassCount = 1 ;
renderPassCI . pSubpasses = & subpassDescription ;
renderPassCI . dependencyCount = 2 ;
renderPassCI . pDependencies = dependencies . data ( ) ;
VkRenderPass renderpass ;
VK_CHECK_RESULT ( vkCreateRenderPass ( device , & renderPassCI , nullptr , & renderpass ) ) ;
2023-05-25 16:13:37 +08:00
struct {
VkImage image ;
VkImageView view ;
VkDeviceMemory memory ;
VkFramebuffer framebuffer ;
} offscreen ;
2023-05-24 16:10:36 +08:00
//framebuffer
{
// Color attachment
VkImageCreateInfo imageCreateInfo = vks : : initializers : : imageCreateInfo ( ) ;
imageCreateInfo . imageType = VK_IMAGE_TYPE_2D ;
imageCreateInfo . format = format ;
imageCreateInfo . extent . width = dim ;
imageCreateInfo . extent . height = dim ;
imageCreateInfo . extent . depth = 1 ;
imageCreateInfo . mipLevels = 1 ;
imageCreateInfo . arrayLayers = 1 ;
imageCreateInfo . samples = VK_SAMPLE_COUNT_1_BIT ;
imageCreateInfo . tiling = VK_IMAGE_TILING_OPTIMAL ;
imageCreateInfo . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
imageCreateInfo . usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT ;
imageCreateInfo . sharingMode = VK_SHARING_MODE_EXCLUSIVE ;
VK_CHECK_RESULT ( vkCreateImage ( device , & imageCreateInfo , nullptr , & offscreen . image ) ) ;
VkMemoryAllocateInfo memAlloc = vks : : initializers : : memoryAllocateInfo ( ) ;
VkMemoryRequirements memReqs ;
vkGetImageMemoryRequirements ( device , offscreen . image , & memReqs ) ;
memAlloc . allocationSize = memReqs . size ;
memAlloc . memoryTypeIndex = vulkanDevice - > getMemoryType ( memReqs . memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ) ;
VK_CHECK_RESULT ( vkAllocateMemory ( device , & memAlloc , nullptr , & offscreen . memory ) ) ;
VK_CHECK_RESULT ( vkBindImageMemory ( device , offscreen . image , offscreen . memory , 0 ) ) ;
VkImageViewCreateInfo colorImageView = vks : : initializers : : imageViewCreateInfo ( ) ;
colorImageView . viewType = VK_IMAGE_VIEW_TYPE_2D ;
colorImageView . format = format ;
colorImageView . flags = 0 ;
colorImageView . subresourceRange = { } ;
colorImageView . subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
colorImageView . subresourceRange . baseMipLevel = 0 ;
colorImageView . subresourceRange . levelCount = 1 ;
colorImageView . subresourceRange . baseArrayLayer = 0 ;
colorImageView . subresourceRange . layerCount = 1 ;
colorImageView . image = offscreen . image ;
VK_CHECK_RESULT ( vkCreateImageView ( device , & colorImageView , nullptr , & offscreen . view ) ) ;
VkFramebufferCreateInfo fbufCreateInfo = vks : : initializers : : framebufferCreateInfo ( ) ;
fbufCreateInfo . renderPass = renderpass ;
fbufCreateInfo . attachmentCount = 1 ;
fbufCreateInfo . pAttachments = & offscreen . view ;
fbufCreateInfo . width = dim ;
fbufCreateInfo . height = dim ;
fbufCreateInfo . layers = 1 ;
VK_CHECK_RESULT ( vkCreateFramebuffer ( device , & fbufCreateInfo , nullptr , & offscreen . framebuffer ) ) ;
VkCommandBuffer layoutCmd = vulkanDevice - > createCommandBuffer ( VK_COMMAND_BUFFER_LEVEL_PRIMARY , true ) ;
vks : : tools : : setImageLayout (
layoutCmd ,
offscreen . image ,
VK_IMAGE_ASPECT_COLOR_BIT ,
VK_IMAGE_LAYOUT_UNDEFINED ,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ) ;
vulkanDevice - > flushCommandBuffer ( layoutCmd , queue , true ) ;
}
2023-05-25 16:13:37 +08:00
// Descriptors
VkDescriptorSetLayout descriptorsetlayout ;
std : : vector < VkDescriptorSetLayoutBinding > setLayoutBindings = {
vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , VK_SHADER_STAGE_FRAGMENT_BIT , 0 ) ,
} ;
VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks : : initializers : : descriptorSetLayoutCreateInfo ( setLayoutBindings ) ;
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device , & descriptorsetlayoutCI , nullptr , & descriptorsetlayout ) ) ;
// Descriptor Pool
std : : vector < VkDescriptorPoolSize > poolSizes = { vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 1 ) } ;
VkDescriptorPoolCreateInfo descriptorPoolCI = vks : : initializers : : descriptorPoolCreateInfo ( poolSizes , 2 ) ;
VkDescriptorPool descriptorpool ;
VK_CHECK_RESULT ( vkCreateDescriptorPool ( device , & descriptorPoolCI , nullptr , & descriptorpool ) ) ;
VkDescriptorSet descriptorset ;
VkDescriptorSetAllocateInfo allocInfo = vks : : initializers : : descriptorSetAllocateInfo ( descriptorpool , & descriptorsetlayout , 1 ) ;
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & descriptorset ) ) ;
VkWriteDescriptorSet writeDescriptorSet = vks : : initializers : : writeDescriptorSet ( descriptorset , VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 0 , & ibltextures . skyboxCube . descriptor ) ;
vkUpdateDescriptorSets ( device , 1 , & writeDescriptorSet , 0 , nullptr ) ;
struct PushBlock {
glm : : mat4 mvp ;
float roughness ;
uint32_t numSamples = 32u ;
} pushBlock ;
std : : vector < VkPushConstantRange > pushConstantRanges = {
vks : : initializers : : pushConstantRange ( VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT , sizeof ( PushBlock ) , 0 ) ,
} ;
VkPipelineLayoutCreateInfo pipelineLayoutCI = vks : : initializers : : pipelineLayoutCreateInfo ( & descriptorsetlayout , 1 ) ;
pipelineLayoutCI . pushConstantRangeCount = 1 ;
pipelineLayoutCI . pPushConstantRanges = pushConstantRanges . data ( ) ;
VkPipelineLayout pipelinelayout ;
VK_CHECK_RESULT ( vkCreatePipelineLayout ( device , & pipelineLayoutCI , nullptr , & pipelinelayout ) ) ;
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks : : initializers : : pipelineInputAssemblyStateCreateInfo ( VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , 0 , VK_FALSE ) ;
VkPipelineRasterizationStateCreateInfo rasterizationState = vks : : initializers : : pipelineRasterizationStateCreateInfo ( VK_POLYGON_MODE_FILL , VK_CULL_MODE_NONE , VK_FRONT_FACE_COUNTER_CLOCKWISE ) ;
VkPipelineColorBlendAttachmentState blendAttachmentState = vks : : initializers : : pipelineColorBlendAttachmentState ( 0xf , VK_FALSE ) ;
VkPipelineColorBlendStateCreateInfo colorBlendState = vks : : initializers : : pipelineColorBlendStateCreateInfo ( 1 , & blendAttachmentState ) ;
VkPipelineDepthStencilStateCreateInfo depthStencilState = vks : : initializers : : pipelineDepthStencilStateCreateInfo ( VK_FALSE , VK_FALSE , VK_COMPARE_OP_LESS_OR_EQUAL ) ;
VkPipelineViewportStateCreateInfo viewportState = vks : : initializers : : pipelineViewportStateCreateInfo ( 1 , 1 ) ;
VkPipelineMultisampleStateCreateInfo multisampleState = vks : : initializers : : pipelineMultisampleStateCreateInfo ( VK_SAMPLE_COUNT_1_BIT ) ;
std : : vector < VkDynamicState > dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR } ;
VkPipelineDynamicStateCreateInfo dynamicState = vks : : initializers : : pipelineDynamicStateCreateInfo ( dynamicStateEnables ) ;
std : : array < VkPipelineShaderStageCreateInfo , 2 > shaderStages ;
const std : : vector < VkVertexInputBindingDescription > vertexInputBindings =
{
vks : : initializers : : vertexInputBindingDescription ( 0 , sizeof ( VulkanglTFModel : : Vertex ) , VK_VERTEX_INPUT_RATE_VERTEX ) ,
} ;
2023-05-24 16:10:36 +08:00
2023-05-25 16:13:37 +08:00
const std : : vector < VkVertexInputAttributeDescription > vertexInputAttributes = {
vks : : initializers : : vertexInputAttributeDescription ( 0 , 0 , VK_FORMAT_R32G32B32_SFLOAT , offsetof ( VulkanglTFModel : : Vertex , pos ) ) , // Location 0: Position
} ;
VkPipelineVertexInputStateCreateInfo vertexInputStateCI = vks : : initializers : : pipelineVertexInputStateCreateInfo ( ) ;
vertexInputStateCI . vertexBindingDescriptionCount = static_cast < uint32_t > ( vertexInputBindings . size ( ) ) ;
vertexInputStateCI . pVertexBindingDescriptions = vertexInputBindings . data ( ) ;
vertexInputStateCI . vertexAttributeDescriptionCount = static_cast < uint32_t > ( vertexInputAttributes . size ( ) ) ;
vertexInputStateCI . pVertexAttributeDescriptions = vertexInputAttributes . data ( ) ;
VkGraphicsPipelineCreateInfo pipelineCI = vks : : initializers : : pipelineCreateInfo ( pipelinelayout , renderpass ) ;
pipelineCI . pInputAssemblyState = & inputAssemblyState ;
pipelineCI . pRasterizationState = & rasterizationState ;
pipelineCI . pColorBlendState = & colorBlendState ;
pipelineCI . pMultisampleState = & multisampleState ;
pipelineCI . pViewportState = & viewportState ;
pipelineCI . pDepthStencilState = & depthStencilState ;
pipelineCI . pDynamicState = & dynamicState ;
pipelineCI . stageCount = 2 ;
pipelineCI . pStages = shaderStages . data ( ) ;
pipelineCI . renderPass = renderpass ;
pipelineCI . pVertexInputState = & vertexInputStateCI ;
shaderStages [ 0 ] = loadShader ( getHomeworkShadersPath ( ) + " homework1/filtercube.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = loadShader ( getHomeworkShadersPath ( ) + " homework1/prefilterenvmap.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
VkPipeline pipeline ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCI , nullptr , & pipeline ) ) ;
//Render & build cmd
VkClearValue clearValues [ 1 ] ;
clearValues [ 0 ] . color = { { 0.0f , 0.0f , 0.2f , 0.0f } } ;
VkRenderPassBeginInfo renderPassBeginInfo = vks : : initializers : : renderPassBeginInfo ( ) ;
// Reuse render pass from example pass
renderPassBeginInfo . renderPass = renderpass ;
renderPassBeginInfo . framebuffer = offscreen . framebuffer ;
renderPassBeginInfo . renderArea . extent . width = dim ;
renderPassBeginInfo . renderArea . extent . height = dim ;
renderPassBeginInfo . clearValueCount = 1 ;
renderPassBeginInfo . pClearValues = clearValues ;
std : : vector < glm : : mat4 > matrices = {
// POSITIVE_X
glm : : rotate ( glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( 90.0f ) , glm : : vec3 ( 0.0f , 1.0f , 0.0f ) ) , glm : : radians ( 180.0f ) , glm : : vec3 ( 1.0f , 0.0f , 0.0f ) ) ,
// NEGATIVE_X
glm : : rotate ( glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( - 90.0f ) , glm : : vec3 ( 0.0f , 1.0f , 0.0f ) ) , glm : : radians ( 180.0f ) , glm : : vec3 ( 1.0f , 0.0f , 0.0f ) ) ,
// POSITIVE_Y
glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( - 90.0f ) , glm : : vec3 ( 1.0f , 0.0f , 0.0f ) ) ,
// NEGATIVE_Y
glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( 90.0f ) , glm : : vec3 ( 1.0f , 0.0f , 0.0f ) ) ,
// POSITIVE_Z
glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( 180.0f ) , glm : : vec3 ( 1.0f , 0.0f , 0.0f ) ) ,
// NEGATIVE_Z
glm : : rotate ( glm : : mat4 ( 1.0f ) , glm : : radians ( 180.0f ) , glm : : vec3 ( 0.0f , 0.0f , 1.0f ) ) ,
} ;
VkCommandBuffer cmdBuf = vulkanDevice - > createCommandBuffer ( VK_COMMAND_BUFFER_LEVEL_PRIMARY , true ) ;
VkViewport viewport = vks : : initializers : : viewport ( ( float ) dim , ( float ) dim , 0.0f , 1.0f ) ;
VkRect2D scissor = vks : : initializers : : rect2D ( dim , dim , 0 , 0 ) ;
vkCmdSetViewport ( cmdBuf , 0 , 1 , & viewport ) ;
vkCmdSetScissor ( cmdBuf , 0 , 1 , & scissor ) ;
VkImageSubresourceRange subresourceRange = { } ;
subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
subresourceRange . baseMipLevel = 0 ;
subresourceRange . levelCount = numMips ;
subresourceRange . layerCount = 6 ;
vks : : tools : : setImageLayout (
cmdBuf ,
ibltextures . prefilteredCube . image ,
VK_IMAGE_LAYOUT_UNDEFINED ,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,
subresourceRange ) ;
for ( uint32_t m = 0 ; m < numMips ; + + m )
{
//mip level according to roughness
pushBlock . roughness = float ( m ) / float ( numMips - 1 ) ;
for ( uint32_t f = 0 ; f < 6 ; + + f )
2023-05-24 16:10:36 +08:00
{
2023-05-25 16:13:37 +08:00
viewport . width = static_cast < float > ( dim * std : : pow ( 0.5f , m ) ) ;
viewport . height = static_cast < float > ( dim * std : : pow ( 0.5f , m ) ) ;
vkCmdSetViewport ( cmdBuf , 0 , 1 , & viewport ) ;
// Render scene from cube face's point of view
vkCmdBeginRenderPass ( cmdBuf , & renderPassBeginInfo , VK_SUBPASS_CONTENTS_INLINE ) ;
2023-05-24 16:10:36 +08:00
2023-05-25 16:13:37 +08:00
// Update shader push constant block
pushBlock . mvp = glm : : perspective ( ( float ) ( M_PI / 2.0 ) , 1.0f , 0.1f , 512.0f ) * matrices [ f ] ;
2023-05-24 16:10:36 +08:00
2023-05-25 16:13:37 +08:00
vkCmdPushConstants ( cmdBuf , pipelinelayout , VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT , 0 , sizeof ( PushBlock ) , & pushBlock ) ;
vkCmdBindPipeline ( cmdBuf , VK_PIPELINE_BIND_POINT_GRAPHICS , pipeline ) ;
vkCmdBindDescriptorSets ( cmdBuf , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelinelayout , 0 , 1 , & descriptorset , 0 , nullptr ) ;
skyboxModel . draw ( cmdBuf , pipelinelayout , false ) ;
vkCmdEndRenderPass ( cmdBuf ) ;
2023-05-24 16:10:36 +08:00
2023-05-25 16:13:37 +08:00
vks : : tools : : setImageLayout (
cmdBuf ,
offscreen . image ,
VK_IMAGE_ASPECT_COLOR_BIT ,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ) ;
VkImageCopy copyRegion { } ;
copyRegion . srcSubresource . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
copyRegion . srcSubresource . baseArrayLayer = 0 ;
copyRegion . srcSubresource . mipLevel = 0 ;
copyRegion . srcSubresource . layerCount = 1 ;
copyRegion . srcOffset = { 0 , 0 , 0 } ;
copyRegion . dstSubresource . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
copyRegion . dstSubresource . baseArrayLayer = f ;
copyRegion . dstSubresource . mipLevel = m ;
copyRegion . dstSubresource . layerCount = 1 ;
copyRegion . dstOffset = { 0 , 0 , 0 } ;
copyRegion . extent . width = static_cast < uint32_t > ( viewport . width ) ;
copyRegion . extent . height = static_cast < uint32_t > ( viewport . height ) ;
copyRegion . extent . depth = 1 ;
vkCmdCopyImage (
cmdBuf ,
offscreen . image ,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ,
ibltextures . prefilteredCube . image ,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,
1 ,
& copyRegion ) ;
2023-05-24 16:10:36 +08:00
2023-05-25 16:13:37 +08:00
//Reset frame buffer image layout
vks : : tools : : setImageLayout (
cmdBuf ,
offscreen . image ,
VK_IMAGE_ASPECT_COLOR_BIT ,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ) ;
2023-05-24 16:10:36 +08:00
}
}
2023-05-25 16:13:37 +08:00
//Set format shader read
vks : : tools : : setImageLayout (
cmdBuf ,
ibltextures . prefilteredCube . image ,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ,
subresourceRange ) ;
vulkanDevice - > flushCommandBuffer ( cmdBuf , queue ) ;
vkDestroyRenderPass ( device , renderpass , nullptr ) ;
vkDestroyFramebuffer ( device , offscreen . framebuffer , nullptr ) ;
vkFreeMemory ( device , offscreen . memory , nullptr ) ;
vkDestroyImageView ( device , offscreen . view , nullptr ) ;
vkDestroyImage ( device , offscreen . image , nullptr ) ;
vkDestroyDescriptorPool ( device , descriptorpool , nullptr ) ;
vkDestroyDescriptorSetLayout ( device , descriptorsetlayout , nullptr ) ;
vkDestroyPipeline ( device , pipeline , nullptr ) ;
vkDestroyPipelineLayout ( device , pipelinelayout , nullptr ) ;
auto tEnd = std : : chrono : : high_resolution_clock : : now ( ) ;
auto tDiff = std : : chrono : : duration < double , std : : milli > ( tEnd - tStart ) . count ( ) ;
2023-06-01 00:05:36 +08:00
std : : cout < < " Generating pre-filtered environment cube with " < < numMips < < " mip levels took " < < tDiff < < " ms " < < std : : endl ;
2023-05-25 16:13:37 +08:00
}
void VulkanExample : : GenerateBRDFLUT ( )
2023-05-24 16:10:36 +08:00
{
auto tStart = std : : chrono : : high_resolution_clock : : now ( ) ;
constexpr VkFormat format = VK_FORMAT_R16G16_SFLOAT ;
constexpr int32_t dim = 512 ;
// Image
VkImageCreateInfo imageCI = vks : : initializers : : imageCreateInfo ( ) ;
imageCI . imageType = VK_IMAGE_TYPE_2D ;
imageCI . format = format ;
imageCI . extent . width = dim ;
imageCI . extent . height = dim ;
imageCI . extent . depth = 1 ;
imageCI . mipLevels = 1 ;
imageCI . arrayLayers = 1 ;
imageCI . samples = VK_SAMPLE_COUNT_1_BIT ;
imageCI . tiling = VK_IMAGE_TILING_OPTIMAL ;
imageCI . usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT ;
VK_CHECK_RESULT ( vkCreateImage ( device , & imageCI , nullptr , & ibltextures . lutBrdf . image ) ) ;
VkMemoryAllocateInfo memAlloc = vks : : initializers : : memoryAllocateInfo ( ) ;
VkMemoryRequirements memReqs ;
vkGetImageMemoryRequirements ( device , ibltextures . lutBrdf . image , & memReqs ) ;
memAlloc . allocationSize = memReqs . size ;
memAlloc . memoryTypeIndex = vulkanDevice - > getMemoryType ( memReqs . memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ) ;
VK_CHECK_RESULT ( vkAllocateMemory ( device , & memAlloc , nullptr , & ibltextures . lutBrdf . deviceMemory ) ) ;
VK_CHECK_RESULT ( vkBindImageMemory ( device , ibltextures . lutBrdf . image , ibltextures . lutBrdf . deviceMemory , 0 ) ) ;
// Image view
VkImageViewCreateInfo viewCI = vks : : initializers : : imageViewCreateInfo ( ) ;
viewCI . viewType = VK_IMAGE_VIEW_TYPE_2D ;
viewCI . format = format ;
viewCI . subresourceRange = { } ;
viewCI . subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
viewCI . subresourceRange . levelCount = 1 ;
viewCI . subresourceRange . layerCount = 1 ;
viewCI . image = ibltextures . lutBrdf . image ;
VK_CHECK_RESULT ( vkCreateImageView ( device , & viewCI , nullptr , & ibltextures . lutBrdf . view ) ) ;
// Sampler
VkSamplerCreateInfo samplerCI = vks : : initializers : : samplerCreateInfo ( ) ;
samplerCI . magFilter = VK_FILTER_LINEAR ;
samplerCI . minFilter = VK_FILTER_LINEAR ;
samplerCI . mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR ;
samplerCI . addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerCI . addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerCI . addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerCI . minLod = 0.0f ;
samplerCI . maxLod = 1.0f ;
samplerCI . borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE ;
VK_CHECK_RESULT ( vkCreateSampler ( device , & samplerCI , nullptr , & ibltextures . lutBrdf . sampler ) ) ;
ibltextures . lutBrdf . descriptor . imageView = ibltextures . lutBrdf . view ;
ibltextures . lutBrdf . descriptor . sampler = ibltextures . lutBrdf . sampler ;
ibltextures . lutBrdf . descriptor . imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ;
ibltextures . lutBrdf . device = vulkanDevice ;
// FB, Att, RP, Pipe, etc.
VkAttachmentDescription attDesc = { } ;
// Color attachment
attDesc . format = format ;
attDesc . samples = VK_SAMPLE_COUNT_1_BIT ;
attDesc . loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
attDesc . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
attDesc . stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE ;
attDesc . stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE ;
attDesc . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
attDesc . finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ;
VkAttachmentReference colorReference = { 0 , VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } ;
VkSubpassDescription subpassDescription = { } ;
subpassDescription . pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS ;
subpassDescription . colorAttachmentCount = 1 ;
subpassDescription . pColorAttachments = & colorReference ;
// Use subpass dependencies for layout transitions
std : : array < VkSubpassDependency , 2 > dependencies ;
dependencies [ 0 ] . srcSubpass = VK_SUBPASS_EXTERNAL ;
dependencies [ 0 ] . dstSubpass = 0 ;
dependencies [ 0 ] . srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT ;
dependencies [ 0 ] . dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
dependencies [ 0 ] . srcAccessMask = VK_ACCESS_MEMORY_READ_BIT ;
dependencies [ 0 ] . dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
dependencies [ 0 ] . dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT ;
dependencies [ 1 ] . srcSubpass = 0 ;
dependencies [ 1 ] . dstSubpass = VK_SUBPASS_EXTERNAL ;
dependencies [ 1 ] . srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
dependencies [ 1 ] . dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT ;
dependencies [ 1 ] . srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
dependencies [ 1 ] . dstAccessMask = VK_ACCESS_MEMORY_READ_BIT ;
dependencies [ 1 ] . dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT ;
2023-06-01 00:05:36 +08:00
// Create the actual render pass
2023-05-24 16:10:36 +08:00
VkRenderPassCreateInfo renderPassCI = vks : : initializers : : renderPassCreateInfo ( ) ;
renderPassCI . attachmentCount = 1 ;
renderPassCI . pAttachments = & attDesc ;
renderPassCI . subpassCount = 1 ;
renderPassCI . pSubpasses = & subpassDescription ;
renderPassCI . dependencyCount = 2 ;
renderPassCI . pDependencies = dependencies . data ( ) ;
VkRenderPass renderpass ;
VK_CHECK_RESULT ( vkCreateRenderPass ( device , & renderPassCI , nullptr , & renderpass ) ) ;
VkFramebufferCreateInfo framebufferCI = vks : : initializers : : framebufferCreateInfo ( ) ;
framebufferCI . renderPass = renderpass ;
framebufferCI . attachmentCount = 1 ;
framebufferCI . pAttachments = & ibltextures . lutBrdf . view ;
framebufferCI . width = dim ;
framebufferCI . height = dim ;
framebufferCI . layers = 1 ;
VkFramebuffer framebuffer ;
VK_CHECK_RESULT ( vkCreateFramebuffer ( device , & framebufferCI , nullptr , & framebuffer ) ) ;
// Descriptors
VkDescriptorSetLayout descriptorsetlayout ;
std : : vector < VkDescriptorSetLayoutBinding > setLayoutBindings = { } ;
VkDescriptorSetLayoutCreateInfo descriptorsetlayoutCI = vks : : initializers : : descriptorSetLayoutCreateInfo ( setLayoutBindings ) ;
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device , & descriptorsetlayoutCI , nullptr , & descriptorsetlayout ) ) ;
// Descriptor Pool
std : : vector < VkDescriptorPoolSize > poolSizes = { vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 1 ) } ;
VkDescriptorPoolCreateInfo descriptorPoolCI = vks : : initializers : : descriptorPoolCreateInfo ( poolSizes , 2 ) ;
VkDescriptorPool descriptorpool ;
VK_CHECK_RESULT ( vkCreateDescriptorPool ( device , & descriptorPoolCI , nullptr , & descriptorpool ) ) ;
// Descriptor sets
VkDescriptorSet descriptorset ;
VkDescriptorSetAllocateInfo allocInfo = vks : : initializers : : descriptorSetAllocateInfo ( descriptorpool , & descriptorsetlayout , 1 ) ;
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & descriptorset ) ) ;
// Pipeline layout
VkPipelineLayout pipelinelayout ;
VkPipelineLayoutCreateInfo pipelineLayoutCI = vks : : initializers : : pipelineLayoutCreateInfo ( & descriptorsetlayout , 1 ) ;
VK_CHECK_RESULT ( vkCreatePipelineLayout ( device , & pipelineLayoutCI , nullptr , & pipelinelayout ) ) ;
// Pipeline
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks : : initializers : : pipelineInputAssemblyStateCreateInfo ( VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , 0 , VK_FALSE ) ;
VkPipelineRasterizationStateCreateInfo rasterizationState = vks : : initializers : : pipelineRasterizationStateCreateInfo ( VK_POLYGON_MODE_FILL , VK_CULL_MODE_NONE , VK_FRONT_FACE_COUNTER_CLOCKWISE ) ;
VkPipelineColorBlendAttachmentState blendAttachmentState = vks : : initializers : : pipelineColorBlendAttachmentState ( 0xf , VK_FALSE ) ;
VkPipelineColorBlendStateCreateInfo colorBlendState = vks : : initializers : : pipelineColorBlendStateCreateInfo ( 1 , & blendAttachmentState ) ;
VkPipelineDepthStencilStateCreateInfo depthStencilState = vks : : initializers : : pipelineDepthStencilStateCreateInfo ( VK_FALSE , VK_FALSE , VK_COMPARE_OP_LESS_OR_EQUAL ) ;
VkPipelineViewportStateCreateInfo viewportState = vks : : initializers : : pipelineViewportStateCreateInfo ( 1 , 1 ) ;
VkPipelineMultisampleStateCreateInfo multisampleState = vks : : initializers : : pipelineMultisampleStateCreateInfo ( VK_SAMPLE_COUNT_1_BIT ) ;
std : : vector < VkDynamicState > dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR } ;
VkPipelineDynamicStateCreateInfo dynamicState = vks : : initializers : : pipelineDynamicStateCreateInfo ( dynamicStateEnables ) ;
VkPipelineVertexInputStateCreateInfo emptyInputState = vks : : initializers : : pipelineVertexInputStateCreateInfo ( ) ;
std : : array < VkPipelineShaderStageCreateInfo , 2 > shaderStages ;
VkGraphicsPipelineCreateInfo pipelineCI = vks : : initializers : : pipelineCreateInfo ( pipelinelayout , renderpass ) ;
pipelineCI . pInputAssemblyState = & inputAssemblyState ;
pipelineCI . pRasterizationState = & rasterizationState ;
pipelineCI . pColorBlendState = & colorBlendState ;
pipelineCI . pMultisampleState = & multisampleState ;
pipelineCI . pViewportState = & viewportState ;
pipelineCI . pDepthStencilState = & depthStencilState ;
pipelineCI . pDynamicState = & dynamicState ;
pipelineCI . stageCount = 2 ;
pipelineCI . pStages = shaderStages . data ( ) ;
pipelineCI . pVertexInputState = & emptyInputState ;
// Look-up-table (from BRDF) pipeline
shaderStages [ 0 ] = loadShader ( getHomeworkShadersPath ( ) + " homework1/genbrdflut.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = loadShader ( getHomeworkShadersPath ( ) + " homework1/genbrdflut.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
VkPipeline pipeline ;
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCI , nullptr , & pipeline ) ) ;
// Render
VkClearValue clearValues [ 1 ] ;
clearValues [ 0 ] . color = { { 0.0f , 0.0f , 0.0f , 1.0f } } ;
VkRenderPassBeginInfo renderPassBeginInfo = vks : : initializers : : renderPassBeginInfo ( ) ;
renderPassBeginInfo . renderPass = renderpass ;
renderPassBeginInfo . renderArea . extent . width = dim ;
renderPassBeginInfo . renderArea . extent . height = dim ;
renderPassBeginInfo . clearValueCount = 1 ;
renderPassBeginInfo . pClearValues = clearValues ;
renderPassBeginInfo . framebuffer = framebuffer ;
VkCommandBuffer cmdBuf = vulkanDevice - > createCommandBuffer ( VK_COMMAND_BUFFER_LEVEL_PRIMARY , true ) ;
vkCmdBeginRenderPass ( cmdBuf , & renderPassBeginInfo , VK_SUBPASS_CONTENTS_INLINE ) ;
VkViewport viewport = vks : : initializers : : viewport ( ( float ) dim , ( float ) dim , 0.0f , 1.0f ) ;
VkRect2D scissor = vks : : initializers : : rect2D ( dim , dim , 0 , 0 ) ;
vkCmdSetViewport ( cmdBuf , 0 , 1 , & viewport ) ;
vkCmdSetScissor ( cmdBuf , 0 , 1 , & scissor ) ;
vkCmdBindPipeline ( cmdBuf , VK_PIPELINE_BIND_POINT_GRAPHICS , pipeline ) ;
vkCmdDraw ( cmdBuf , 3 , 1 , 0 , 0 ) ;
vkCmdEndRenderPass ( cmdBuf ) ;
vulkanDevice - > flushCommandBuffer ( cmdBuf , queue ) ;
vkQueueWaitIdle ( queue ) ;
vkDestroyPipeline ( device , pipeline , nullptr ) ;
vkDestroyPipelineLayout ( device , pipelinelayout , nullptr ) ;
vkDestroyRenderPass ( device , renderpass , nullptr ) ;
vkDestroyFramebuffer ( device , framebuffer , nullptr ) ;
vkDestroyDescriptorSetLayout ( device , descriptorsetlayout , nullptr ) ;
vkDestroyDescriptorPool ( device , descriptorpool , nullptr ) ;
auto tEnd = std : : chrono : : high_resolution_clock : : now ( ) ;
auto tDiff = std : : chrono : : duration < double , std : : milli > ( tEnd - tStart ) . count ( ) ;
std : : cout < < " Generating BRDF LUT took " < < tDiff < < " ms " < < std : : endl ;
2023-05-25 16:13:37 +08:00
}
//----------------------------End Precompute brick------------------------------------------------------------------//
2023-05-23 11:30:21 +08:00
# pragma region pbr render pass setting
2023-05-25 16:13:37 +08:00
void VulkanExample : : createAttachment (
VkFormat format ,
VkImageUsageFlagBits usage ,
FrameBufferAttachment * attachment ,
uint32_t width ,
uint32_t height )
2023-05-23 11:30:21 +08:00
{
VkImageAspectFlags aspectMask = 0 ;
VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT ;
attachment - > format = format ;
if ( usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT )
{
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
imageUsage | = VK_IMAGE_USAGE_SAMPLED_BIT ;
}
if ( usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT )
{
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT ;
if ( format > = VK_FORMAT_D16_UNORM_S8_UINT )
aspectMask | = VK_IMAGE_ASPECT_STENCIL_BIT ;
}
assert ( aspectMask > 0 ) ;
VkImageCreateInfo image = vks : : initializers : : imageCreateInfo ( ) ;
image . imageType = VK_IMAGE_TYPE_2D ;
image . format = format ;
image . extent . width = width ;
image . extent . height = height ;
image . extent . depth = 1 ;
image . mipLevels = 1 ;
image . arrayLayers = 1 ;
image . samples = VK_SAMPLE_COUNT_1_BIT ;
image . tiling = VK_IMAGE_TILING_OPTIMAL ;
image . usage = imageUsage | usage ;
VkMemoryAllocateInfo memAlloc = vks : : initializers : : memoryAllocateInfo ( ) ;
VkMemoryRequirements memReqs ;
VK_CHECK_RESULT ( vkCreateImage ( device , & image , nullptr , & attachment - > image ) ) ;
vkGetImageMemoryRequirements ( device , attachment - > image , & memReqs ) ;
memAlloc . allocationSize = memReqs . size ;
memAlloc . memoryTypeIndex = vulkanDevice - > getMemoryType ( memReqs . memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ) ;
VK_CHECK_RESULT ( vkAllocateMemory ( device , & memAlloc , nullptr , & attachment - > deviceMemory ) ) ;
VK_CHECK_RESULT ( vkBindImageMemory ( device , attachment - > image , attachment - > deviceMemory , 0 ) ) ;
VkImageViewCreateInfo imageView = vks : : initializers : : imageViewCreateInfo ( ) ;
imageView . viewType = VK_IMAGE_VIEW_TYPE_2D ;
imageView . format = format ;
imageView . subresourceRange = { } ;
imageView . subresourceRange . aspectMask = aspectMask ;
imageView . subresourceRange . baseMipLevel = 0 ;
imageView . subresourceRange . levelCount = 1 ;
imageView . subresourceRange . baseArrayLayer = 0 ;
imageView . subresourceRange . layerCount = 1 ;
imageView . image = attachment - > image ;
VK_CHECK_RESULT ( vkCreateImageView ( device , & imageView , nullptr , & attachment - > imageView ) ) ;
}
# pragma endregion
2023-05-17 14:49:05 +08:00
// Prepare and initialize uniform buffer containing shader uniforms
2023-05-25 16:27:50 +08:00
void VulkanExample : : prepareUniformBuffers ( )
2023-05-17 14:49:05 +08:00
{
// Vertex shader uniform buffer block
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,
& shaderData . buffer ,
sizeof ( shaderData . values ) ) ) ;
2023-05-25 16:13:37 +08:00
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,
& shaderData . skinSSBO ,
sizeof ( glm : : mat4 ) * glTFModel . nodeCount ) ) ;
2023-05-23 11:30:21 +08:00
2023-05-17 14:49:05 +08:00
// Map persistent
VK_CHECK_RESULT ( shaderData . buffer . map ( ) ) ;
2023-05-25 16:13:37 +08:00
VK_CHECK_RESULT ( shaderData . skinSSBO . map ( ) ) ;
for ( auto & material : glTFModel . materials )
{
VK_CHECK_RESULT ( vulkanDevice - > createBuffer (
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT ,
& material . materialData . buffer ,
sizeof ( VulkanglTFModel : : MaterialData : : Values ) ,
& material . materialData . values ) ) ;
}
2023-05-17 14:49:05 +08:00
updateUniformBuffers ( ) ;
}
2023-05-25 16:27:50 +08:00
void VulkanExample : : updateUniformBuffers ( )
2023-05-17 14:49:05 +08:00
{
shaderData . values . projection = camera . matrices . perspective ;
shaderData . values . model = camera . matrices . view ;
2023-05-17 14:53:31 +08:00
shaderData . values . viewPos = camera . viewPos ;
2023-05-25 16:13:37 +08:00
shaderData . values . bFlagSet . x = normalMapping ;
shaderData . values . bFlagSet . y = pbrEnabled ;
2023-05-17 14:49:05 +08:00
memcpy ( shaderData . buffer . mapped , & shaderData . values , sizeof ( shaderData . values ) ) ;
}
2023-05-25 16:27:50 +08:00
void VulkanExample : : prepare ( )
2023-05-17 14:49:05 +08:00
{
VulkanExampleBase : : prepare ( ) ;
loadAssets ( ) ;
2023-05-25 16:13:37 +08:00
GenerateBRDFLUT ( ) ;
GenerateIrradianceCubemap ( ) ;
GeneratePrefilteredCubemap ( ) ;
2023-05-17 14:49:05 +08:00
prepareUniformBuffers ( ) ;
setupDescriptors ( ) ;
preparePipelines ( ) ;
buildCommandBuffers ( ) ;
prepared = true ;
}
2023-05-25 16:27:50 +08:00
void VulkanExample : : render ( )
2023-05-17 14:49:05 +08:00
{
renderFrame ( ) ;
if ( camera . updated ) {
updateUniformBuffers ( ) ;
}
2023-05-25 16:13:37 +08:00
if ( ! paused )
glTFModel . updateAnimation ( frameTimer , shaderData . skinSSBO ) ;
2023-05-17 14:49:05 +08:00
}
2023-05-25 16:27:50 +08:00
void VulkanExample : : viewChanged ( )
2023-05-17 14:49:05 +08:00
{
updateUniformBuffers ( ) ;
}
2023-05-25 16:27:50 +08:00
void VulkanExample : : OnUpdateUIOverlay ( vks : : UIOverlay * overlay )
2023-05-17 14:49:05 +08:00
{
if ( overlay - > header ( " Settings " ) ) {
if ( overlay - > checkBox ( " Wireframe " , & wireframe ) ) {
buildCommandBuffers ( ) ;
}
2023-05-25 16:13:37 +08:00
if ( overlay - > checkBox ( " NormalMapping " , & normalMapping ) )
{
}
if ( overlay - > checkBox ( " ToneMapping " , & ToneMapping ) )
{
CreateToneMappingPipeline ( ) ;
}
if ( overlay - > checkBox ( " PbrIndirect " , & pbrEnabled ) )
{
}
2023-05-17 14:49:05 +08:00
}
2023-06-01 09:32:07 +08:00
2023-05-18 11:49:09 +08:00
if ( overlay - > header ( " Animation " ) )
{
2023-05-25 16:13:37 +08:00
overlay - > checkBox ( " Pause " , & paused ) ;
2023-05-17 14:49:05 +08:00
}
2023-06-01 09:32:07 +08:00
2023-06-01 00:05:36 +08:00
if ( overlay - > header ( " file " ) )
{
if ( overlay - > button ( " select model " ) )
{
GUIFunction guiFunc { } ;
if ( guiFunc . openFileFolderDialog ( ) )
{
2023-06-01 09:32:07 +08:00
MessageBoxW ( NULL , guiFunc . filePath , L " File Path " , MB_OK ) ;
2023-06-01 00:05:36 +08:00
}
else
{
std : : cerr < < " file select error " < < std : : endl ;
}
}
}
2023-05-17 14:49:05 +08:00
}
2023-05-25 16:27:50 +08:00
2023-05-17 14:49:05 +08:00
VULKAN_EXAMPLE_MAIN ( )