2017-03-30 19:27:57 +02:00
/*
* Vulkan Example - imGui ( https : //github.com/ocornut/imgui)
*
2024-05-23 21:56:42 +02:00
* Copyright ( C ) 2017 - 2024 by Sascha Willems - www . saschawillems . de
2017-03-30 19:27:57 +02:00
*
* This code is licensed under the MIT license ( MIT ) ( http : //opensource.org/licenses/MIT)
*/
# include <imgui.h>
# include "vulkanexamplebase.h"
2020-07-28 20:20:38 +02:00
# include "VulkanglTFModel.h"
2017-03-30 19:27:57 +02:00
// Options and values to display/toggle from the UI
struct UISettings {
bool displayModels = true ;
bool displayLogos = true ;
bool displayBackground = true ;
bool animateLight = false ;
float lightSpeed = 0.25f ;
2017-04-22 11:50:13 +02:00
std : : array < float , 50 > frameTimes { } ;
2017-03-30 19:27:57 +02:00
float frameTimeMin = 9999.0f , frameTimeMax = 0.0f ;
float lightTimer = 0.0f ;
} uiSettings ;
// ----------------------------------------------------------------------------
// ImGUI class
// ----------------------------------------------------------------------------
class ImGUI {
private :
// Vulkan resources for rendering the UI
VkSampler sampler ;
vks : : Buffer vertexBuffer ;
vks : : Buffer indexBuffer ;
int32_t vertexCount = 0 ;
int32_t indexCount = 0 ;
VkDeviceMemory fontMemory = VK_NULL_HANDLE ;
VkImage fontImage = VK_NULL_HANDLE ;
VkImageView fontView = VK_NULL_HANDLE ;
VkPipelineCache pipelineCache ;
VkPipelineLayout pipelineLayout ;
VkPipeline pipeline ;
VkDescriptorPool descriptorPool ;
VkDescriptorSetLayout descriptorSetLayout ;
VkDescriptorSet descriptorSet ;
vks : : VulkanDevice * device ;
2022-07-12 18:46:39 -04:00
VkPhysicalDeviceDriverProperties driverProperties = { } ;
2017-03-31 09:52:26 +02:00
VulkanExampleBase * example ;
2023-02-25 10:27:47 +01:00
ImGuiStyle vulkanStyle ;
int selectedStyle = 0 ;
2017-03-30 19:27:57 +02:00
public :
// UI params are set via push constants
struct PushConstBlock {
glm : : vec2 scale ;
glm : : vec2 translate ;
} pushConstBlock ;
2020-05-29 16:08:53 +01:00
ImGUI ( VulkanExampleBase * example ) : example ( example )
2017-03-31 09:52:26 +02:00
{
device = example - > vulkanDevice ;
2018-08-29 18:24:39 +02:00
ImGui : : CreateContext ( ) ;
2022-07-12 18:46:39 -04:00
//SRS - Set ImGui font and style scale factors to handle retina and other HiDPI displays
ImGuiIO & io = ImGui : : GetIO ( ) ;
2024-05-23 21:56:42 +02:00
io . FontGlobalScale = example - > ui . scale ;
2022-07-12 18:46:39 -04:00
ImGuiStyle & style = ImGui : : GetStyle ( ) ;
2024-05-23 21:56:42 +02:00
style . ScaleAllSizes ( example - > ui . scale ) ;
2017-03-31 09:52:26 +02:00
} ;
2020-05-29 16:08:53 +01:00
2017-03-30 19:27:57 +02:00
~ ImGUI ( )
{
2018-08-29 18:24:39 +02:00
ImGui : : DestroyContext ( ) ;
2017-03-30 19:27:57 +02:00
// Release all Vulkan resources required for rendering imGui
vertexBuffer . destroy ( ) ;
indexBuffer . destroy ( ) ;
vkDestroyImage ( device - > logicalDevice , fontImage , nullptr ) ;
vkDestroyImageView ( device - > logicalDevice , fontView , nullptr ) ;
vkFreeMemory ( device - > logicalDevice , fontMemory , nullptr ) ;
vkDestroySampler ( device - > logicalDevice , sampler , nullptr ) ;
vkDestroyPipelineCache ( device - > logicalDevice , pipelineCache , nullptr ) ;
vkDestroyPipeline ( device - > logicalDevice , pipeline , nullptr ) ;
vkDestroyPipelineLayout ( device - > logicalDevice , pipelineLayout , nullptr ) ;
vkDestroyDescriptorPool ( device - > logicalDevice , descriptorPool , nullptr ) ;
vkDestroyDescriptorSetLayout ( device - > logicalDevice , descriptorSetLayout , nullptr ) ;
}
// Initialize styles, keys, etc.
void init ( float width , float height )
{
// Color scheme
2023-02-25 10:27:47 +01:00
vulkanStyle = ImGui : : GetStyle ( ) ;
vulkanStyle . Colors [ ImGuiCol_TitleBg ] = ImVec4 ( 1.0f , 0.0f , 0.0f , 0.6f ) ;
vulkanStyle . Colors [ ImGuiCol_TitleBgActive ] = ImVec4 ( 1.0f , 0.0f , 0.0f , 0.8f ) ;
vulkanStyle . Colors [ ImGuiCol_MenuBarBg ] = ImVec4 ( 1.0f , 0.0f , 0.0f , 0.4f ) ;
vulkanStyle . Colors [ ImGuiCol_Header ] = ImVec4 ( 1.0f , 0.0f , 0.0f , 0.4f ) ;
vulkanStyle . Colors [ ImGuiCol_CheckMark ] = ImVec4 ( 0.0f , 1.0f , 0.0f , 1.0f ) ;
setStyle ( 0 ) ;
2017-03-30 19:27:57 +02:00
// Dimensions
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . DisplaySize = ImVec2 ( width , height ) ;
io . DisplayFramebufferScale = ImVec2 ( 1.0f , 1.0f ) ;
2023-02-25 09:37:08 +01:00
# if defined(_WIN32)
// If we directly work with os specific key codes, we need to map special key types like tab
io . KeyMap [ ImGuiKey_Tab ] = VK_TAB ;
io . KeyMap [ ImGuiKey_LeftArrow ] = VK_LEFT ;
io . KeyMap [ ImGuiKey_RightArrow ] = VK_RIGHT ;
io . KeyMap [ ImGuiKey_UpArrow ] = VK_UP ;
io . KeyMap [ ImGuiKey_DownArrow ] = VK_DOWN ;
io . KeyMap [ ImGuiKey_Backspace ] = VK_BACK ;
io . KeyMap [ ImGuiKey_Enter ] = VK_RETURN ;
2023-02-25 09:46:56 +01:00
io . KeyMap [ ImGuiKey_Space ] = VK_SPACE ;
io . KeyMap [ ImGuiKey_Delete ] = VK_DELETE ;
2023-02-25 09:37:08 +01:00
# endif
2017-03-30 19:27:57 +02:00
}
2023-02-25 10:27:47 +01:00
void setStyle ( uint32_t index )
{
switch ( index )
{
case 0 :
{
ImGuiStyle & style = ImGui : : GetStyle ( ) ;
style = vulkanStyle ;
break ;
}
case 1 :
ImGui : : StyleColorsClassic ( ) ;
break ;
case 2 :
ImGui : : StyleColorsDark ( ) ;
break ;
case 3 :
ImGui : : StyleColorsLight ( ) ;
break ;
}
}
2017-03-30 19:27:57 +02:00
// Initialize all Vulkan resources used by the ui
2020-05-29 16:36:27 +01:00
void initResources ( VkRenderPass renderPass , VkQueue copyQueue , const std : : string & shadersPath )
2017-03-30 19:27:57 +02:00
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
// Create font texture
unsigned char * fontData ;
int texWidth , texHeight ;
io . Fonts - > GetTexDataAsRGBA32 ( & fontData , & texWidth , & texHeight ) ;
VkDeviceSize uploadSize = texWidth * texHeight * 4 * sizeof ( char ) ;
2022-07-12 18:46:39 -04:00
//SRS - Get Vulkan device driver information if available, use later for display
if ( device - > extensionSupported ( VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME ) )
{
VkPhysicalDeviceProperties2 deviceProperties2 = { } ;
deviceProperties2 . sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 ;
deviceProperties2 . pNext = & driverProperties ;
driverProperties . sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES ;
vkGetPhysicalDeviceProperties2 ( device - > physicalDevice , & deviceProperties2 ) ;
}
2017-03-30 19:27:57 +02:00
// Create target image for copy
VkImageCreateInfo imageInfo = vks : : initializers : : imageCreateInfo ( ) ;
imageInfo . imageType = VK_IMAGE_TYPE_2D ;
imageInfo . format = VK_FORMAT_R8G8B8A8_UNORM ;
imageInfo . extent . width = texWidth ;
imageInfo . extent . height = texHeight ;
imageInfo . extent . depth = 1 ;
imageInfo . mipLevels = 1 ;
imageInfo . arrayLayers = 1 ;
imageInfo . samples = VK_SAMPLE_COUNT_1_BIT ;
imageInfo . tiling = VK_IMAGE_TILING_OPTIMAL ;
imageInfo . usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT ;
imageInfo . sharingMode = VK_SHARING_MODE_EXCLUSIVE ;
imageInfo . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
VK_CHECK_RESULT ( vkCreateImage ( device - > logicalDevice , & imageInfo , nullptr , & fontImage ) ) ;
VkMemoryRequirements memReqs ;
vkGetImageMemoryRequirements ( device - > logicalDevice , fontImage , & memReqs ) ;
VkMemoryAllocateInfo memAllocInfo = vks : : initializers : : memoryAllocateInfo ( ) ;
memAllocInfo . allocationSize = memReqs . size ;
memAllocInfo . memoryTypeIndex = device - > getMemoryType ( memReqs . memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ) ;
VK_CHECK_RESULT ( vkAllocateMemory ( device - > logicalDevice , & memAllocInfo , nullptr , & fontMemory ) ) ;
VK_CHECK_RESULT ( vkBindImageMemory ( device - > logicalDevice , fontImage , fontMemory , 0 ) ) ;
// Image view
VkImageViewCreateInfo viewInfo = vks : : initializers : : imageViewCreateInfo ( ) ;
viewInfo . image = fontImage ;
viewInfo . viewType = VK_IMAGE_VIEW_TYPE_2D ;
viewInfo . format = VK_FORMAT_R8G8B8A8_UNORM ;
viewInfo . subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
viewInfo . subresourceRange . levelCount = 1 ;
viewInfo . subresourceRange . layerCount = 1 ;
VK_CHECK_RESULT ( vkCreateImageView ( device - > logicalDevice , & viewInfo , nullptr , & fontView ) ) ;
// Staging buffers for font data upload
vks : : Buffer stagingBuffer ;
VK_CHECK_RESULT ( device - > createBuffer (
VK_BUFFER_USAGE_TRANSFER_SRC_BIT ,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,
& stagingBuffer ,
uploadSize ) ) ;
stagingBuffer . map ( ) ;
memcpy ( stagingBuffer . mapped , fontData , uploadSize ) ;
stagingBuffer . unmap ( ) ;
// Copy buffer data to font image
VkCommandBuffer copyCmd = device - > createCommandBuffer ( VK_COMMAND_BUFFER_LEVEL_PRIMARY , true ) ;
// Prepare for transfer
vks : : tools : : setImageLayout (
copyCmd ,
fontImage ,
VK_IMAGE_ASPECT_COLOR_BIT ,
VK_IMAGE_LAYOUT_UNDEFINED ,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,
VK_PIPELINE_STAGE_HOST_BIT ,
VK_PIPELINE_STAGE_TRANSFER_BIT ) ;
// Copy
VkBufferImageCopy bufferCopyRegion = { } ;
bufferCopyRegion . imageSubresource . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
bufferCopyRegion . imageSubresource . layerCount = 1 ;
bufferCopyRegion . imageExtent . width = texWidth ;
bufferCopyRegion . imageExtent . height = texHeight ;
bufferCopyRegion . imageExtent . depth = 1 ;
vkCmdCopyBufferToImage (
copyCmd ,
stagingBuffer . buffer ,
fontImage ,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,
1 ,
& bufferCopyRegion
) ;
// Prepare for shader read
vks : : tools : : setImageLayout (
copyCmd ,
fontImage ,
VK_IMAGE_ASPECT_COLOR_BIT ,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ,
VK_PIPELINE_STAGE_TRANSFER_BIT ,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT ) ;
device - > flushCommandBuffer ( copyCmd , copyQueue , true ) ;
stagingBuffer . destroy ( ) ;
// Font texture Sampler
VkSamplerCreateInfo samplerInfo = vks : : initializers : : samplerCreateInfo ( ) ;
samplerInfo . magFilter = VK_FILTER_LINEAR ;
samplerInfo . minFilter = VK_FILTER_LINEAR ;
samplerInfo . mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR ;
samplerInfo . addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerInfo . addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerInfo . addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE ;
samplerInfo . borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE ;
VK_CHECK_RESULT ( vkCreateSampler ( device - > logicalDevice , & samplerInfo , nullptr , & sampler ) ) ;
// Descriptor pool
std : : vector < VkDescriptorPoolSize > poolSizes = {
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 1 )
} ;
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks : : initializers : : descriptorPoolCreateInfo ( poolSizes , 2 ) ;
VK_CHECK_RESULT ( vkCreateDescriptorPool ( device - > logicalDevice , & descriptorPoolInfo , nullptr , & descriptorPool ) ) ;
// Descriptor set layout
std : : vector < VkDescriptorSetLayoutBinding > setLayoutBindings = {
vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , VK_SHADER_STAGE_FRAGMENT_BIT , 0 ) ,
} ;
VkDescriptorSetLayoutCreateInfo descriptorLayout = vks : : initializers : : descriptorSetLayoutCreateInfo ( setLayoutBindings ) ;
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device - > logicalDevice , & descriptorLayout , nullptr , & descriptorSetLayout ) ) ;
// Descriptor set
VkDescriptorSetAllocateInfo allocInfo = vks : : initializers : : descriptorSetAllocateInfo ( descriptorPool , & descriptorSetLayout , 1 ) ;
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device - > logicalDevice , & allocInfo , & descriptorSet ) ) ;
VkDescriptorImageInfo fontDescriptor = vks : : initializers : : descriptorImageInfo (
sampler ,
fontView ,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
) ;
std : : vector < VkWriteDescriptorSet > writeDescriptorSets = {
vks : : initializers : : writeDescriptorSet ( descriptorSet , VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 0 , & fontDescriptor )
} ;
vkUpdateDescriptorSets ( device - > logicalDevice , static_cast < uint32_t > ( writeDescriptorSets . size ( ) ) , writeDescriptorSets . data ( ) , 0 , nullptr ) ;
// Pipeline cache
VkPipelineCacheCreateInfo pipelineCacheCreateInfo = { } ;
pipelineCacheCreateInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO ;
VK_CHECK_RESULT ( vkCreatePipelineCache ( device - > logicalDevice , & pipelineCacheCreateInfo , nullptr , & pipelineCache ) ) ;
// Pipeline layout
// Push constants for UI rendering parameters
VkPushConstantRange pushConstantRange = vks : : initializers : : pushConstantRange ( VK_SHADER_STAGE_VERTEX_BIT , sizeof ( PushConstBlock ) , 0 ) ;
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks : : initializers : : pipelineLayoutCreateInfo ( & descriptorSetLayout , 1 ) ;
pipelineLayoutCreateInfo . pushConstantRangeCount = 1 ;
pipelineLayoutCreateInfo . pPushConstantRanges = & pushConstantRange ;
VK_CHECK_RESULT ( vkCreatePipelineLayout ( device - > logicalDevice , & pipelineLayoutCreateInfo , nullptr , & pipelineLayout ) ) ;
// Setup graphics pipeline for UI rendering
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 ) ;
// Enable blending
VkPipelineColorBlendAttachmentState blendAttachmentState { } ;
blendAttachmentState . blendEnable = VK_TRUE ;
blendAttachmentState . colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT ;
blendAttachmentState . srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA ;
blendAttachmentState . dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA ;
blendAttachmentState . colorBlendOp = VK_BLEND_OP_ADD ;
blendAttachmentState . srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA ;
blendAttachmentState . dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO ;
blendAttachmentState . alphaBlendOp = VK_BLEND_OP_ADD ;
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 , 0 ) ;
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 { } ;
VkGraphicsPipelineCreateInfo pipelineCreateInfo = vks : : initializers : : pipelineCreateInfo ( pipelineLayout , renderPass ) ;
pipelineCreateInfo . pInputAssemblyState = & inputAssemblyState ;
pipelineCreateInfo . pRasterizationState = & rasterizationState ;
pipelineCreateInfo . pColorBlendState = & colorBlendState ;
pipelineCreateInfo . pMultisampleState = & multisampleState ;
pipelineCreateInfo . pViewportState = & viewportState ;
pipelineCreateInfo . pDepthStencilState = & depthStencilState ;
pipelineCreateInfo . pDynamicState = & dynamicState ;
pipelineCreateInfo . stageCount = static_cast < uint32_t > ( shaderStages . size ( ) ) ;
pipelineCreateInfo . pStages = shaderStages . data ( ) ;
// Vertex bindings an attributes based on ImGui vertex definition
std : : vector < VkVertexInputBindingDescription > vertexInputBindings = {
vks : : initializers : : vertexInputBindingDescription ( 0 , sizeof ( ImDrawVert ) , VK_VERTEX_INPUT_RATE_VERTEX ) ,
} ;
std : : vector < VkVertexInputAttributeDescription > vertexInputAttributes = {
vks : : initializers : : vertexInputAttributeDescription ( 0 , 0 , VK_FORMAT_R32G32_SFLOAT , offsetof ( ImDrawVert , pos ) ) , // Location 0: Position
vks : : initializers : : vertexInputAttributeDescription ( 0 , 1 , VK_FORMAT_R32G32_SFLOAT , offsetof ( ImDrawVert , uv ) ) , // Location 1: UV
vks : : initializers : : vertexInputAttributeDescription ( 0 , 2 , VK_FORMAT_R8G8B8A8_UNORM , offsetof ( ImDrawVert , col ) ) , // Location 0: Color
} ;
VkPipelineVertexInputStateCreateInfo vertexInputState = vks : : initializers : : pipelineVertexInputStateCreateInfo ( ) ;
vertexInputState . vertexBindingDescriptionCount = static_cast < uint32_t > ( vertexInputBindings . size ( ) ) ;
vertexInputState . pVertexBindingDescriptions = vertexInputBindings . data ( ) ;
vertexInputState . vertexAttributeDescriptionCount = static_cast < uint32_t > ( vertexInputAttributes . size ( ) ) ;
vertexInputState . pVertexAttributeDescriptions = vertexInputAttributes . data ( ) ;
pipelineCreateInfo . pVertexInputState = & vertexInputState ;
2020-05-29 16:36:27 +01:00
shaderStages [ 0 ] = example - > loadShader ( shadersPath + " imgui/ui.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = example - > loadShader ( shadersPath + " imgui/ui.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
2017-03-30 19:27:57 +02:00
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device - > logicalDevice , pipelineCache , 1 , & pipelineCreateInfo , nullptr , & pipeline ) ) ;
}
// Starts a new imGui frame and sets up windows and ui elements
void newFrame ( VulkanExampleBase * example , bool updateFrameGraph )
{
ImGui : : NewFrame ( ) ;
// Init imGui windows and elements
2023-02-25 10:27:47 +01:00
// Debug window
2024-05-23 21:56:42 +02:00
ImGui : : SetWindowPos ( ImVec2 ( 20 * example - > ui . scale , 20 * example - > ui . scale ) , ImGuiSetCond_FirstUseEver ) ;
ImGui : : SetWindowSize ( ImVec2 ( 300 * example - > ui . scale , 300 * example - > ui . scale ) , ImGuiSetCond_Always ) ;
2018-05-10 17:22:42 +02:00
ImGui : : TextUnformatted ( example - > title . c_str ( ) ) ;
ImGui : : TextUnformatted ( device - > properties . deviceName ) ;
2022-07-12 18:46:39 -04:00
//SRS - Display Vulkan API version and device driver information if available (otherwise blank)
ImGui : : Text ( " Vulkan API %i.%i.%i " , VK_API_VERSION_MAJOR ( device - > properties . apiVersion ) , VK_API_VERSION_MINOR ( device - > properties . apiVersion ) , VK_API_VERSION_PATCH ( device - > properties . apiVersion ) ) ;
ImGui : : Text ( " %s %s " , driverProperties . driverName , driverProperties . driverInfo ) ;
2017-03-30 19:27:57 +02:00
// Update frame time display
if ( updateFrameGraph ) {
std : : rotate ( uiSettings . frameTimes . begin ( ) , uiSettings . frameTimes . begin ( ) + 1 , uiSettings . frameTimes . end ( ) ) ;
float frameTime = 1000.0f / ( example - > frameTimer * 1000.0f ) ;
uiSettings . frameTimes . back ( ) = frameTime ;
if ( frameTime < uiSettings . frameTimeMin ) {
uiSettings . frameTimeMin = frameTime ;
}
if ( frameTime > uiSettings . frameTimeMax ) {
uiSettings . frameTimeMax = frameTime ;
}
}
ImGui : : PlotLines ( " Frame Times " , & uiSettings . frameTimes [ 0 ] , 50 , 0 , " " , uiSettings . frameTimeMin , uiSettings . frameTimeMax , ImVec2 ( 0 , 80 ) ) ;
ImGui : : Text ( " Camera " ) ;
ImGui : : InputFloat3 ( " position " , & example - > camera . position . x , 2 ) ;
ImGui : : InputFloat3 ( " rotation " , & example - > camera . rotation . x , 2 ) ;
2023-02-25 10:27:47 +01:00
// Example settings window
2024-05-23 21:56:42 +02:00
ImGui : : SetNextWindowPos ( ImVec2 ( 20 * example - > ui . scale , 360 * example - > ui . scale ) , ImGuiSetCond_FirstUseEver ) ;
ImGui : : SetNextWindowSize ( ImVec2 ( 300 * example - > ui . scale , 200 * example - > ui . scale ) , ImGuiSetCond_FirstUseEver ) ;
2017-03-30 19:27:57 +02:00
ImGui : : Begin ( " Example settings " ) ;
ImGui : : Checkbox ( " Render models " , & uiSettings . displayModels ) ;
ImGui : : Checkbox ( " Display logos " , & uiSettings . displayLogos ) ;
ImGui : : Checkbox ( " Display background " , & uiSettings . displayBackground ) ;
ImGui : : Checkbox ( " Animate light " , & uiSettings . animateLight ) ;
ImGui : : SliderFloat ( " Light speed " , & uiSettings . lightSpeed , 0.1f , 1.0f ) ;
2023-02-25 10:27:47 +01:00
//ImGui::ShowStyleSelector("UI style");
if ( ImGui : : Combo ( " UI style " , & selectedStyle , " Vulkan \0 Classic \0 Dark \0 Light \0 " ) ) {
setStyle ( selectedStyle ) ;
}
2017-03-30 19:27:57 +02:00
ImGui : : End ( ) ;
2022-07-12 18:46:39 -04:00
//SRS - ShowDemoWindow() sets its own initial position and size, cannot override here
2018-08-29 18:24:39 +02:00
ImGui : : ShowDemoWindow ( ) ;
2017-03-30 19:27:57 +02:00
// Render to generate draw buffers
ImGui : : Render ( ) ;
}
// Update vertex and index buffer containing the imGui elements when required
void updateBuffers ( )
{
ImDrawData * imDrawData = ImGui : : GetDrawData ( ) ;
// Note: Alignment is done inside buffer creation
VkDeviceSize vertexBufferSize = imDrawData - > TotalVtxCount * sizeof ( ImDrawVert ) ;
VkDeviceSize indexBufferSize = imDrawData - > TotalIdxCount * sizeof ( ImDrawIdx ) ;
2018-08-29 18:24:39 +02:00
if ( ( vertexBufferSize = = 0 ) | | ( indexBufferSize = = 0 ) ) {
return ;
}
2017-03-30 19:27:57 +02:00
// Update buffers only if vertex or index count has been changed compared to current buffer size
// Vertex buffer
if ( ( vertexBuffer . buffer = = VK_NULL_HANDLE ) | | ( vertexCount ! = imDrawData - > TotalVtxCount ) ) {
vertexBuffer . unmap ( ) ;
vertexBuffer . destroy ( ) ;
VK_CHECK_RESULT ( device - > createBuffer ( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT , & vertexBuffer , vertexBufferSize ) ) ;
vertexCount = imDrawData - > TotalVtxCount ;
vertexBuffer . map ( ) ;
}
// Index buffer
if ( ( indexBuffer . buffer = = VK_NULL_HANDLE ) | | ( indexCount < imDrawData - > TotalIdxCount ) ) {
indexBuffer . unmap ( ) ;
indexBuffer . destroy ( ) ;
VK_CHECK_RESULT ( device - > createBuffer ( VK_BUFFER_USAGE_INDEX_BUFFER_BIT , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT , & indexBuffer , indexBufferSize ) ) ;
indexCount = imDrawData - > TotalIdxCount ;
indexBuffer . map ( ) ;
}
// Upload data
ImDrawVert * vtxDst = ( ImDrawVert * ) vertexBuffer . mapped ;
ImDrawIdx * idxDst = ( ImDrawIdx * ) indexBuffer . mapped ;
for ( int n = 0 ; n < imDrawData - > CmdListsCount ; n + + ) {
const ImDrawList * cmd_list = imDrawData - > CmdLists [ n ] ;
memcpy ( vtxDst , cmd_list - > VtxBuffer . Data , cmd_list - > VtxBuffer . Size * sizeof ( ImDrawVert ) ) ;
memcpy ( idxDst , cmd_list - > IdxBuffer . Data , cmd_list - > IdxBuffer . Size * sizeof ( ImDrawIdx ) ) ;
vtxDst + = cmd_list - > VtxBuffer . Size ;
idxDst + = cmd_list - > IdxBuffer . Size ;
}
// Flush to make writes visible to GPU
vertexBuffer . flush ( ) ;
indexBuffer . flush ( ) ;
}
// Draw current imGui frame into a command buffer
void drawFrame ( VkCommandBuffer commandBuffer )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
vkCmdBindDescriptorSets ( commandBuffer , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelineLayout , 0 , 1 , & descriptorSet , 0 , nullptr ) ;
vkCmdBindPipeline ( commandBuffer , VK_PIPELINE_BIND_POINT_GRAPHICS , pipeline ) ;
VkViewport viewport = vks : : initializers : : viewport ( ImGui : : GetIO ( ) . DisplaySize . x , ImGui : : GetIO ( ) . DisplaySize . y , 0.0f , 1.0f ) ;
vkCmdSetViewport ( commandBuffer , 0 , 1 , & viewport ) ;
// UI scale and translate via push constants
pushConstBlock . scale = glm : : vec2 ( 2.0f / io . DisplaySize . x , 2.0f / io . DisplaySize . y ) ;
pushConstBlock . translate = glm : : vec2 ( - 1.0f ) ;
vkCmdPushConstants ( commandBuffer , pipelineLayout , VK_SHADER_STAGE_VERTEX_BIT , 0 , sizeof ( PushConstBlock ) , & pushConstBlock ) ;
// Render commands
ImDrawData * imDrawData = ImGui : : GetDrawData ( ) ;
int32_t vertexOffset = 0 ;
int32_t indexOffset = 0 ;
2018-08-29 18:24:39 +02:00
if ( imDrawData - > CmdListsCount > 0 ) {
VkDeviceSize offsets [ 1 ] = { 0 } ;
vkCmdBindVertexBuffers ( commandBuffer , 0 , 1 , & vertexBuffer . buffer , offsets ) ;
vkCmdBindIndexBuffer ( commandBuffer , indexBuffer . buffer , 0 , VK_INDEX_TYPE_UINT16 ) ;
for ( int32_t i = 0 ; i < imDrawData - > CmdListsCount ; i + + )
2017-03-30 19:27:57 +02:00
{
2018-08-29 18:24:39 +02:00
const ImDrawList * cmd_list = imDrawData - > CmdLists [ i ] ;
for ( int32_t j = 0 ; j < cmd_list - > CmdBuffer . Size ; j + + )
{
const ImDrawCmd * pcmd = & cmd_list - > CmdBuffer [ j ] ;
VkRect2D scissorRect ;
scissorRect . offset . x = std : : max ( ( int32_t ) ( pcmd - > ClipRect . x ) , 0 ) ;
scissorRect . offset . y = std : : max ( ( int32_t ) ( pcmd - > ClipRect . y ) , 0 ) ;
scissorRect . extent . width = ( uint32_t ) ( pcmd - > ClipRect . z - pcmd - > ClipRect . x ) ;
scissorRect . extent . height = ( uint32_t ) ( pcmd - > ClipRect . w - pcmd - > ClipRect . y ) ;
vkCmdSetScissor ( commandBuffer , 0 , 1 , & scissorRect ) ;
vkCmdDrawIndexed ( commandBuffer , pcmd - > ElemCount , 1 , indexOffset , vertexOffset , 0 ) ;
indexOffset + = pcmd - > ElemCount ;
}
vertexOffset + = cmd_list - > VtxBuffer . Size ;
2017-03-30 19:27:57 +02:00
}
}
}
} ;
// ----------------------------------------------------------------------------
// VulkanExample
// ----------------------------------------------------------------------------
class VulkanExample : public VulkanExampleBase
{
public :
ImGUI * imGui = nullptr ;
struct Models {
2020-07-28 20:20:38 +02:00
vkglTF : : Model models ;
vkglTF : : Model logos ;
vkglTF : : Model background ;
2017-03-30 19:27:57 +02:00
} models ;
vks : : Buffer uniformBufferVS ;
struct UBOVS {
glm : : mat4 projection ;
glm : : mat4 modelview ;
glm : : vec4 lightPos ;
} uboVS ;
VkPipelineLayout pipelineLayout ;
VkPipeline pipeline ;
VkDescriptorSetLayout descriptorSetLayout ;
VkDescriptorSet descriptorSet ;
2023-12-30 13:15:37 +01:00
VulkanExample ( ) : VulkanExampleBase ( )
2017-03-30 19:27:57 +02:00
{
title = " Vulkan Example - ImGui " ;
camera . type = Camera : : CameraType : : lookat ;
2020-07-28 20:20:38 +02:00
camera . setPosition ( glm : : vec3 ( 0.0f , 0.0f , - 4.8f ) ) ;
2017-03-30 19:27:57 +02:00
camera . setRotation ( glm : : vec3 ( 4.5f , - 380.0f , 0.0f ) ) ;
camera . setPerspective ( 45.0f , ( float ) width / ( float ) height , 0.1f , 256.0f ) ;
2022-07-12 18:46:39 -04:00
//SRS - Enable VK_KHR_get_physical_device_properties2 to retrieve device driver information for display
enabledInstanceExtensions . push_back ( VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME ) ;
2021-11-10 19:04:02 +01:00
// Don't use the ImGui overlay of the base framework in this sample
settings . overlay = false ;
2017-03-30 19:27:57 +02:00
}
~ VulkanExample ( )
{
vkDestroyPipeline ( device , pipeline , nullptr ) ;
vkDestroyPipelineLayout ( device , pipelineLayout , nullptr ) ;
vkDestroyDescriptorSetLayout ( device , descriptorSetLayout , nullptr ) ;
uniformBufferVS . destroy ( ) ;
delete imGui ;
}
2020-05-29 16:08:53 +01:00
2017-03-30 19:27:57 +02:00
void buildCommandBuffers ( )
{
VkCommandBufferBeginInfo cmdBufInfo = vks : : initializers : : commandBufferBeginInfo ( ) ;
VkClearValue clearValues [ 2 ] ;
clearValues [ 0 ] . color = { { 0.2f , 0.2f , 0.2f , 1.0f } } ;
clearValues [ 1 ] . depthStencil = { 1.0f , 0 } ;
VkRenderPassBeginInfo renderPassBeginInfo = vks : : initializers : : renderPassBeginInfo ( ) ;
renderPassBeginInfo . renderPass = renderPass ;
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 ;
imGui - > newFrame ( this , ( frameCounter = = 0 ) ) ;
imGui - > updateBuffers ( ) ;
for ( int32_t i = 0 ; i < drawCmdBuffers . size ( ) ; + + i )
{
// Set target frame buffer
renderPassBeginInfo . framebuffer = frameBuffers [ i ] ;
VK_CHECK_RESULT ( vkBeginCommandBuffer ( drawCmdBuffers [ i ] , & cmdBufInfo ) ) ;
vkCmdBeginRenderPass ( drawCmdBuffers [ i ] , & renderPassBeginInfo , VK_SUBPASS_CONTENTS_INLINE ) ;
VkViewport viewport = vks : : initializers : : viewport ( ( float ) width , ( float ) height , 0.0f , 1.0f ) ;
vkCmdSetViewport ( drawCmdBuffers [ i ] , 0 , 1 , & viewport ) ;
VkRect2D scissor = vks : : initializers : : rect2D ( width , height , 0 , 0 ) ;
vkCmdSetScissor ( drawCmdBuffers [ i ] , 0 , 1 , & scissor ) ;
// Render scene
vkCmdBindDescriptorSets ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipelineLayout , 0 , 1 , & descriptorSet , 0 , nullptr ) ;
vkCmdBindPipeline ( drawCmdBuffers [ i ] , VK_PIPELINE_BIND_POINT_GRAPHICS , pipeline ) ;
VkDeviceSize offsets [ 1 ] = { 0 } ;
if ( uiSettings . displayBackground ) {
2020-07-28 20:20:38 +02:00
models . background . draw ( drawCmdBuffers [ i ] ) ;
2017-03-30 19:27:57 +02:00
}
if ( uiSettings . displayModels ) {
2020-07-28 20:20:38 +02:00
models . models . draw ( drawCmdBuffers [ i ] ) ;
2017-03-30 19:27:57 +02:00
}
if ( uiSettings . displayLogos ) {
2020-07-28 20:20:38 +02:00
models . logos . draw ( drawCmdBuffers [ i ] ) ;
2017-03-30 19:27:57 +02:00
}
// Render imGui
2024-05-23 21:56:42 +02:00
if ( ui . visible ) {
2022-08-01 16:11:57 -04:00
imGui - > drawFrame ( drawCmdBuffers [ i ] ) ;
}
2017-03-30 19:27:57 +02:00
vkCmdEndRenderPass ( drawCmdBuffers [ i ] ) ;
VK_CHECK_RESULT ( vkEndCommandBuffer ( drawCmdBuffers [ i ] ) ) ;
}
}
void setupLayoutsAndDescriptors ( )
{
// descriptor pool
std : : vector < VkDescriptorPoolSize > poolSizes = {
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , 2 ) ,
vks : : initializers : : descriptorPoolSize ( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , 1 )
} ;
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks : : initializers : : descriptorPoolCreateInfo ( poolSizes , 2 ) ;
VK_CHECK_RESULT ( vkCreateDescriptorPool ( device , & descriptorPoolInfo , nullptr , & descriptorPool ) ) ;
// Set layout
std : : vector < VkDescriptorSetLayoutBinding > setLayoutBindings = {
vks : : initializers : : descriptorSetLayoutBinding ( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , VK_SHADER_STAGE_VERTEX_BIT , 0 ) ,
} ;
VkDescriptorSetLayoutCreateInfo descriptorLayout =
vks : : initializers : : descriptorSetLayoutCreateInfo ( setLayoutBindings ) ;
VK_CHECK_RESULT ( vkCreateDescriptorSetLayout ( device , & descriptorLayout , nullptr , & descriptorSetLayout ) ) ;
// Pipeline layout
2024-01-21 13:15:56 +01:00
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks : : initializers : : pipelineLayoutCreateInfo ( & descriptorSetLayout , 1 ) ;
VK_CHECK_RESULT ( vkCreatePipelineLayout ( device , & pipelineLayoutCreateInfo , nullptr , & pipelineLayout ) ) ;
2017-03-30 19:27:57 +02:00
// Descriptor set
VkDescriptorSetAllocateInfo allocInfo = vks : : initializers : : descriptorSetAllocateInfo ( descriptorPool , & descriptorSetLayout , 1 ) ;
VK_CHECK_RESULT ( vkAllocateDescriptorSets ( device , & allocInfo , & descriptorSet ) ) ;
std : : vector < VkWriteDescriptorSet > writeDescriptorSets = {
vks : : initializers : : writeDescriptorSet ( descriptorSet , VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , 0 , & uniformBufferVS . descriptor ) ,
} ;
vkUpdateDescriptorSets ( device , static_cast < uint32_t > ( writeDescriptorSets . size ( ) ) , writeDescriptorSets . data ( ) , 0 , nullptr ) ;
}
void preparePipelines ( )
{
// Rendering
2020-07-28 20:20:38 +02:00
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_BACK_BIT , 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_TRUE , VK_TRUE , VK_COMPARE_OP_LESS_OR_EQUAL ) ;
VkPipelineViewportStateCreateInfo viewportState = vks : : initializers : : pipelineViewportStateCreateInfo ( 1 , 1 , 0 ) ;
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 ) ;
2017-03-30 19:27:57 +02:00
std : : array < VkPipelineShaderStageCreateInfo , 2 > shaderStages ;
2020-07-28 20:20:38 +02:00
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 = static_cast < uint32_t > ( shaderStages . size ( ) ) ;
pipelineCI . pStages = shaderStages . data ( ) ;
pipelineCI . pVertexInputState = vkglTF : : Vertex : : getPipelineVertexInputState ( { vkglTF : : VertexComponent : : Position , vkglTF : : VertexComponent : : Normal , vkglTF : : VertexComponent : : Color } ) ; ;
2017-03-30 19:27:57 +02:00
2020-05-29 16:08:53 +01:00
shaderStages [ 0 ] = loadShader ( getShadersPath ( ) + " imgui/scene.vert.spv " , VK_SHADER_STAGE_VERTEX_BIT ) ;
shaderStages [ 1 ] = loadShader ( getShadersPath ( ) + " imgui/scene.frag.spv " , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
2020-07-28 20:20:38 +02:00
VK_CHECK_RESULT ( vkCreateGraphicsPipelines ( device , pipelineCache , 1 , & pipelineCI , nullptr , & pipeline ) ) ;
2017-03-30 19:27:57 +02:00
}
// Prepare and initialize uniform buffer containing shader uniforms
void prepareUniformBuffers ( )
{
// 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 ,
& uniformBufferVS ,
sizeof ( uboVS ) ,
& uboVS ) ) ;
updateUniformBuffers ( ) ;
}
void updateUniformBuffers ( )
{
2020-05-29 16:08:53 +01:00
// Vertex shader
2017-03-30 19:27:57 +02:00
uboVS . projection = camera . matrices . perspective ;
2017-09-24 18:17:07 +02:00
uboVS . modelview = camera . matrices . view * glm : : mat4 ( 1.0f ) ;
2017-03-30 19:27:57 +02:00
// Light source
if ( uiSettings . animateLight ) {
uiSettings . lightTimer + = frameTimer * uiSettings . lightSpeed ;
uboVS . lightPos . x = sin ( glm : : radians ( uiSettings . lightTimer * 360.0f ) ) * 15.0f ;
uboVS . lightPos . z = cos ( glm : : radians ( uiSettings . lightTimer * 360.0f ) ) * 15.0f ;
} ;
VK_CHECK_RESULT ( uniformBufferVS . map ( ) ) ;
memcpy ( uniformBufferVS . mapped , & uboVS , sizeof ( uboVS ) ) ;
uniformBufferVS . unmap ( ) ;
}
void draw ( )
{
VulkanExampleBase : : prepareFrame ( ) ;
buildCommandBuffers ( ) ;
submitInfo . commandBufferCount = 1 ;
submitInfo . pCommandBuffers = & drawCmdBuffers [ currentBuffer ] ;
VK_CHECK_RESULT ( vkQueueSubmit ( queue , 1 , & submitInfo , VK_NULL_HANDLE ) ) ;
VulkanExampleBase : : submitFrame ( ) ;
}
void loadAssets ( )
{
2020-07-28 20:20:38 +02:00
const uint32_t glTFLoadingFlags = vkglTF : : FileLoadingFlags : : PreTransformVertices | vkglTF : : FileLoadingFlags : : PreMultiplyVertexColors | vkglTF : : FileLoadingFlags : : FlipY ;
models . models . loadFromFile ( getAssetPath ( ) + " models/vulkanscenemodels.gltf " , vulkanDevice , queue , glTFLoadingFlags ) ;
models . background . loadFromFile ( getAssetPath ( ) + " models/vulkanscenebackground.gltf " , vulkanDevice , queue , glTFLoadingFlags ) ;
models . logos . loadFromFile ( getAssetPath ( ) + " models/vulkanscenelogos.gltf " , vulkanDevice , queue , glTFLoadingFlags ) ;
2017-03-30 19:27:57 +02:00
}
void prepareImGui ( )
{
2017-03-31 09:52:26 +02:00
imGui = new ImGUI ( this ) ;
2017-03-30 19:27:57 +02:00
imGui - > init ( ( float ) width , ( float ) height ) ;
2020-05-29 16:36:27 +01:00
imGui - > initResources ( renderPass , queue , getShadersPath ( ) ) ;
2017-03-30 19:27:57 +02:00
}
void prepare ( )
{
VulkanExampleBase : : prepare ( ) ;
loadAssets ( ) ;
prepareUniformBuffers ( ) ;
setupLayoutsAndDescriptors ( ) ;
preparePipelines ( ) ;
prepareImGui ( ) ;
buildCommandBuffers ( ) ;
prepared = true ;
}
virtual void render ( )
{
if ( ! prepared )
return ;
2023-02-25 09:37:08 +01:00
updateUniformBuffers ( ) ;
2017-03-30 19:27:57 +02:00
// Update imGui
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . DisplaySize = ImVec2 ( ( float ) width , ( float ) height ) ;
io . DeltaTime = frameTimer ;
2024-03-20 07:49:06 +01:00
io . MousePos = ImVec2 ( mouseState . position . x , mouseState . position . y ) ;
2024-05-23 21:56:42 +02:00
io . MouseDown [ 0 ] = mouseState . buttons . left & & ui . visible ;
io . MouseDown [ 1 ] = mouseState . buttons . right & & ui . visible ;
io . MouseDown [ 2 ] = mouseState . buttons . middle & & ui . visible ;
2017-03-30 19:27:57 +02:00
draw ( ) ;
}
2017-10-05 21:22:29 +02:00
virtual void mouseMoved ( double x , double y , bool & handled )
{
2020-05-29 16:08:53 +01:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
2024-05-23 21:56:42 +02:00
handled = io . WantCaptureMouse & & ui . visible ;
2017-10-05 21:22:29 +02:00
}
2023-02-25 09:37:08 +01:00
// Input handling is platform specific, to show how it's basically done this sample implements it for Windows
# if defined(_WIN32)
virtual void OnHandleMessage ( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam ) {
ImGuiIO & io = ImGui : : GetIO ( ) ;
// Only react to keyboard input if ImGui is active
if ( io . WantCaptureKeyboard ) {
// Character input
if ( uMsg = = WM_CHAR ) {
if ( wParam > 0 & & wParam < 0x10000 ) {
io . AddInputCharacter ( ( unsigned short ) wParam ) ;
}
}
// Special keys (tab, cursor, etc.)
if ( ( wParam < 256 ) & & ( uMsg = = WM_KEYDOWN | | uMsg = = WM_SYSKEYDOWN ) ) {
io . KeysDown [ wParam ] = true ;
}
if ( ( wParam < 256 ) & & ( uMsg = = WM_KEYUP | | uMsg = = WM_SYSKEYUP ) ) {
io . KeysDown [ wParam ] = false ;
}
}
}
# endif
2017-03-30 19:27:57 +02:00
} ;
VULKAN_EXAMPLE_MAIN ( )