Reputation: 21
Im making gui in imgui, using example from official repository(example_glfw_vulkan), and i encountered a problem, that i cant apply shader to my popup`s background. expected result
in this image you can see result that i need to achieve, i do know how to write shaders, but i dont know how to properly read them and use in imgui, i was searching internet and asking chatgpt, but i didnt find anywhere some reproducable example or even parts of code that can help me achieve this
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_vulkan.h"
#include <stdio.h>
#include <stdlib.h>
#define GLFW_INCLUDE_NONE
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <vector>
#include <array>
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
#define VOLK_IMPLEMENTATION
#include <volk.h>
#endif
#if defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
#pragma comment(lib, "legacy_stdio_definitions")
#endif
#ifdef _DEBUG
#define APP_USE_VULKAN_DEBUG_REPORT
#endif
const char* vertex_shader_src = R"(
#version 330 core
layout(location = 0) in vec2 inPos;
layout(location = 1) in vec2 inTexCoord;
out vec2 TexCoord;
void main() {
TexCoord = inTexCoord;
gl_Position = vec4(inPos, 0.0, 1.0);
}
)";
const char* fragment_shader_blur_horizontal = R"(
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D screenTexture;
uniform float weight[9];
void main() {
vec2 tex_offset = 1.0 / textureSize(screenTexture, 0);
vec3 result = texture(screenTexture, TexCoord).rgb * weight[0];
for (int i = 1; i < 9; ++i) {
result += texture(screenTexture, TexCoord + vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
result += texture(screenTexture, TexCoord - vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
}
FragColor = vec4(result, 1.0);
}
)";
const char* fragment_shader_blur_vertical = R"(
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D screenTexture;
uniform float weight[9];
void main() {
vec2 tex_offset = 1.0 / textureSize(screenTexture, 0);
vec3 result = texture(screenTexture, TexCoord).rgb * weight[0];
for (int i = 1; i < 9; ++i) {
result += texture(screenTexture, TexCoord + vec2(0.0, tex_offset.y * i)).rgb * weight[i];
result += texture(screenTexture, TexCoord - vec2(0.0, tex_offset.y * i)).rgb * weight[i];
}
FragColor = vec4(result, 1.0);
}
)";
static VkAllocationCallbacks* g_Allocator = nullptr;
static VkInstance g_Instance = VK_NULL_HANDLE;
static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
static VkDevice g_Device = VK_NULL_HANDLE;
static uint32_t g_QueueFamily = (uint32_t)-1;
static VkQueue g_Queue = VK_NULL_HANDLE;
static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
static ImGui_ImplVulkanH_Window g_MainWindowData;
static int g_MinImageCount = 2;
static bool g_SwapChainRebuild = false;
// Blur-specific Vulkan resources
static VkRenderPass g_BlurRenderPass = VK_NULL_HANDLE;
static VkPipeline g_BlurPipeline = VK_NULL_HANDLE;
static VkPipelineLayout g_BlurPipelineLayout = VK_NULL_HANDLE;
static VkFramebuffer g_BlurFramebuffer = VK_NULL_HANDLE;
static VkDescriptorSet g_BlurDescriptorSet = VK_NULL_HANDLE;
static VkImageView g_BlurImageView = VK_NULL_HANDLE;
static VkImage g_BlurImage = VK_NULL_HANDLE;
static VkDeviceMemory g_BlurImageMemory = VK_NULL_HANDLE;
static void glfw_error_callback(int error, const char* description)
{
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
}
static void check_vk_result(VkResult err)
{
if (err == 0)
return;
fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err);
if (err < 0)
abort();
}
#ifdef APP_USE_VULKAN_DEBUG_REPORT
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
{
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix;
fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
return VK_FALSE;
}
#endif
static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properties, const char* extension)
{
for (const VkExtensionProperties& p : properties)
if (strcmp(p.extensionName, extension) == 0)
return true;
return false;
}
static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice()
{
uint32_t gpu_count;
VkResult err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr);
check_vk_result(err);
IM_ASSERT(gpu_count > 0);
ImVector<VkPhysicalDevice> gpus;
gpus.resize(gpu_count);
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus.Data);
check_vk_result(err);
for (VkPhysicalDevice& device : gpus)
{
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(device, &properties);
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
return device;
}
if (gpu_count > 0)
return gpus[0];
return VK_NULL_HANDLE;
}
static void SetupVulkan(ImVector<const char*> instance_extensions)
{
VkResult err;
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
volkInitialize();
#endif
{
VkInstanceCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
uint32_t properties_count;
ImVector<VkExtensionProperties> properties;
vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, nullptr);
properties.resize(properties_count);
err = vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, properties.Data);
check_vk_result(err);
if (IsExtensionAvailable(properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
instance_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
#ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME))
{
instance_extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
}
#endif
#ifdef APP_USE_VULKAN_DEBUG_REPORT
const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
create_info.enabledLayerCount = 1;
create_info.ppEnabledLayerNames = layers;
instance_extensions.push_back("VK_EXT_debug_report");
#endif
create_info.enabledExtensionCount = (uint32_t)instance_extensions.Size;
create_info.ppEnabledExtensionNames = instance_extensions.Data;
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
check_vk_result(err);
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
volkLoadInstance(g_Instance);
#endif
#ifdef APP_USE_VULKAN_DEBUG_REPORT
auto f_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
IM_ASSERT(f_vkCreateDebugReportCallbackEXT != nullptr);
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
debug_report_ci.pfnCallback = debug_report;
debug_report_ci.pUserData = nullptr;
err = f_vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
check_vk_result(err);
#endif
}
g_PhysicalDevice = SetupVulkan_SelectPhysicalDevice();
{
VkPhysicalDeviceFeatures device_features = {};
device_features.samplerAnisotropy = VK_TRUE;
device_features.sampleRateShading = VK_TRUE;
device_features.fragmentStoresAndAtomics = VK_TRUE;
VkDeviceCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
create_info.pEnabledFeatures = &device_features;
create_info.queueCreateInfoCount = 1;
VkDeviceQueueCreateInfo queue_create_info = {};
queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info.queueFamilyIndex = 0;
queue_create_info.queueCount = 1;
float queue_priority = 1.0f;
queue_create_info.pQueuePriorities = &queue_priority;
create_info.pQueueCreateInfos = &queue_create_info;
create_info.enabledExtensionCount = 1;
const char* device_extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
create_info.ppEnabledExtensionNames = device_extensions;
err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device);
check_vk_result(err);
vkGetDeviceQueue(g_Device, 0, 0, &g_Queue);
}
}
static void CleanupVulkan()
{
vkDestroyPipeline(g_Device, g_BlurPipeline, g_Allocator);
vkDestroyPipelineLayout(g_Device, g_BlurPipelineLayout, g_Allocator);
vkDestroyRenderPass(g_Device, g_BlurRenderPass, g_Allocator);
vkDestroyFramebuffer(g_Device, g_BlurFramebuffer, g_Allocator);
vkDestroyImageView(g_Device, g_BlurImageView, g_Allocator);
vkDestroyImage(g_Device, g_BlurImage, g_Allocator);
vkFreeMemory(g_Device, g_BlurImageMemory, g_Allocator);
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
vkDestroyDevice(g_Device, g_Allocator);
vkDestroyInstance(g_Instance, g_Allocator);
}
static void SetupBlurResources()
{
VkResult err;
VkImageCreateInfo image_create_info = {};
image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM;
image_create_info.extent.width = 800;
image_create_info.extent.height = 600;
image_create_info.extent.depth = 1;
image_create_info.mipLevels = 1;
image_create_info.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
err = vkCreateImage(g_Device, &image_create_info, g_Allocator, &g_BlurImage);
check_vk_result(err);
VkMemoryRequirements mem_req;
vkGetImageMemoryRequirements(g_Device, g_BlurImage, &mem_req);
VkMemoryAllocateInfo mem_alloc_info = {};
mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
mem_alloc_info.allocationSize = mem_req.size;
mem_alloc_info.memoryTypeIndex = 0;
err = vkAllocateMemory(g_Device, &mem_alloc_info, g_Allocator, &g_BlurImageMemory);
check_vk_result(err);
err = vkBindImageMemory(g_Device, g_BlurImage, g_BlurImageMemory, 0);
check_vk_result(err);
VkImageViewCreateInfo image_view_create_info = {};
image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
image_view_create_info.image = g_BlurImage;
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_create_info.format = VK_FORMAT_R8G8B8A8_UNORM;
image_view_create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
image_view_create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
image_view_create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
image_view_create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
image_view_create_info.subresourceRange.baseMipLevel = 0;
image_view_create_info.subresourceRange.levelCount = 1;
image_view_create_info.subresourceRange.baseArrayLayer = 0;
image_view_create_info.subresourceRange.layerCount = 1;
err = vkCreateImageView(g_Device, &image_view_create_info, g_Allocator, &g_BlurImageView);
check_vk_result(err);
VkFramebufferCreateInfo framebuffer_create_info = {};
framebuffer_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebuffer_create_info.renderPass = g_BlurRenderPass;
framebuffer_create_info.attachmentCount = 1;
framebuffer_create_info.pAttachments = &g_BlurImageView;
framebuffer_create_info.width = 800;
framebuffer_create_info.height = 600;
framebuffer_create_info.layers = 1;
err = vkCreateFramebuffer(g_Device, &framebuffer_create_info, g_Allocator, &g_BlurFramebuffer);
check_vk_result(err);
}
static void SetupBlurRenderPass()
{
VkResult err;
VkAttachmentDescription color_attachment = {};
color_attachment.format = VK_FORMAT_R8G8B8A8_UNORM;
color_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
color_attachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkAttachmentReference color_attachment_ref = {};
color_attachment_ref.attachment = 0;
color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_attachment_ref;
VkRenderPassCreateInfo render_pass_info = {};
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
render_pass_info.attachmentCount = 1;
render_pass_info.pAttachments = &color_attachment;
render_pass_info.subpassCount = 1;
render_pass_info.pSubpasses = &subpass;
err = vkCreateRenderPass(g_Device, &render_pass_info, g_Allocator, &g_BlurRenderPass);
check_vk_result(err);
}
static void SetupBlurPipeline()
{
VkResult err;
VkShaderModuleCreateInfo vert_shader_info = {};
vert_shader_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
vert_shader_info.codeSize = sizeof(vertex_shader_src);
vert_shader_info.pCode = (const uint32_t*)vertex_shader_src;
VkShaderModule vert_shader_module;
err = vkCreateShaderModule(g_Device, &vert_shader_info, g_Allocator, &vert_shader_module);
check_vk_result(err);
VkShaderModuleCreateInfo frag_shader_info = {};
frag_shader_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
frag_shader_info.codeSize = sizeof(fragment_shader_blur_horizontal);
frag_shader_info.pCode = (const uint32_t*)fragment_shader_blur_horizontal;
VkShaderModule frag_shader_module;
err = vkCreateShaderModule(g_Device, &frag_shader_info, g_Allocator, &frag_shader_module);
check_vk_result(err);
VkPipelineShaderStageCreateInfo vert_shader_stage_info = {};
vert_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vert_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT;
vert_shader_stage_info.module = vert_shader_module;
vert_shader_stage_info.pName = "main";
VkPipelineShaderStageCreateInfo frag_shader_stage_info = {};
frag_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
frag_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
frag_shader_stage_info.module = frag_shader_module;
frag_shader_stage_info.pName = "main";
VkPipelineShaderStageCreateInfo shader_stages[] = { vert_shader_stage_info, frag_shader_stage_info };
VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
VkPipelineInputAssemblyStateCreateInfo input_assembly = {};
input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
VkPipelineViewportStateCreateInfo viewport_state = {};
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport_state.viewportCount = 1;
viewport_state.scissorCount = 1;
VkPipelineRasterizationStateCreateInfo rasterizer = {};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.lineWidth = 1.0f;
VkPipelineMultisampleStateCreateInfo multisampling = {};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
VkPipelineColorBlendAttachmentState color_blend_attachment = {};
color_blend_attachment.blendEnable = VK_FALSE;
color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
VkPipelineColorBlendStateCreateInfo color_blending = {};
color_blending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
color_blending.attachmentCount = 1;
color_blending.pAttachments = &color_blend_attachment;
VkPipelineLayoutCreateInfo pipeline_layout_info = {};
pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipeline_layout_info.pushConstantRangeCount = 0;
err = vkCreatePipelineLayout(g_Device, &pipeline_layout_info, g_Allocator, &g_BlurPipelineLayout);
check_vk_result(err);
VkGraphicsPipelineCreateInfo pipeline_info = {};
pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline_info.stageCount = 2;
pipeline_info.pStages = shader_stages;
pipeline_info.pVertexInputState = &vertex_input_info;
pipeline_info.pInputAssemblyState = &input_assembly;
pipeline_info.pViewportState = &viewport_state;
pipeline_info.pRasterizationState = &rasterizer;
pipeline_info.pMultisampleState = &multisampling;
pipeline_info.pColorBlendState = &color_blending;
pipeline_info.pDepthStencilState = nullptr;
pipeline_info.pDynamicState = nullptr;
pipeline_info.layout = g_BlurPipelineLayout;
pipeline_info.renderPass = g_BlurRenderPass;
pipeline_info.subpass = 0;
err = vkCreateGraphicsPipelines(g_Device, VK_NULL_HANDLE, 1, &pipeline_info, g_Allocator, &g_BlurPipeline);
check_vk_result(err);
vkDestroyShaderModule(g_Device, frag_shader_module, g_Allocator);
vkDestroyShaderModule(g_Device, vert_shader_module, g_Allocator);
}
static void ApplyBlurToPopupBackground()
{
// ??
}
int main()
{
if (!glfwInit())
return -1;
glfwSetErrorCallback(glfw_error_callback);
if (!glfwVulkanSupported())
{
fprintf(stderr, "Vulkan not supported\n");
return -1;
}
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui Vulkan Example", nullptr, nullptr);
if (window == nullptr)
return -1;
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
ImVector<const char*> instance_extensions;
instance_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
SetupVulkan(instance_extensions);
SetupBlurResources();
SetupBlurRenderPass();
SetupBlurPipeline();
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGui_ImplGlfw_InitForVulkan(window, true);
ImGui_ImplVulkan_InitInfo init_info = {};
init_info.Instance = g_Instance;
init_info.PhysicalDevice = g_PhysicalDevice;
init_info.Device = g_Device;
init_info.QueueFamily = g_QueueFamily;
init_info.Queue = g_Queue;
init_info.PipelineCache = g_PipelineCache;
init_info.DescriptorPool = g_DescriptorPool;
init_info.Allocator = g_Allocator;
init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info);
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
if (ImGui::BeginPopup("Popup"))
{
ApplyBlurToPopupBackground();
ImGui::Text("This is a popup with blur effect!");
ImGui::EndPopup();
}
ImGui::Render();
ApplyBlurToPopupBackground();
}
CleanupVulkan();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
in my code there is missing function to apply blur, and i dont even know if i'm proccesing shaders correctly
Upvotes: 2
Views: 234