#pragma once #if defined(_WIN32) #include <io.h> #include <direct.h> #else #include<sys/io.h> #include<dirent.h> #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <vector> #include <chrono> #include <map> #include <locale> #include <codecvt> #include "algorithm" #include <iostream> #include <sys/stat.h> #include <filesystem> #include <vulkan/vulkan.h> #include "VulkanExampleBase.h" #include "glTFModel.h" #include <VulkanTexture.hpp> #include "VulkanDevice.hpp" #include "ui.hpp" #include <VulkanUtils.hpp> #define ENABLE_VALIDATION false class PlumageRender : public VulkanExampleBase { public: bool wireframe = false; bool normalMapping = true; bool ToneMapping = true; bool pbrEnabled = true; struct stat { } info ; struct Signal { bool imageSequenceOutputComplete = false; bool imageSequenceToVideoComplete = false; }signal; struct Models { glTFModel::Model scene; glTFModel::Model skybox; } models; struct Textures { vks::TextureCubeMap environmentCube; vks::Texture2D empty; vks::Texture2D lutBrdf; vks::TextureCubeMap irradianceCube; vks::TextureCubeMap prefilteredCube; } textures; struct ShaderData { glm::vec4 lightDir; float exposure = 4.5f; float gamma = 2.2f; float prefilteredCubeMipLevels; float scaleIBLAmbient = 1.0f; float debugViewInputs = 0; float debugViewEquation = 0; } shaderData; struct ChinesesUI { const char * model = "模型"; const char* environmentMap = "环境贴图"; const char* environmentBackGround = "启用背景贴图"; const char* debugInput = "输入"; const char* debugPBREquation = "PBR计算参数"; const char* animation = "动画"; const char* pauseAnimation = "启用动画"; const char* animationSeq = "动画序列"; // menu item const char* menuFile = "文件"; const char* menuOpenNewModel = "新模型.."; const char* menuEnvironment = "环境光照"; const char* menuEnvironmentConfig = "设置"; const char* menuAnimation = "动画"; const char* menuDebugFrameRate = "fps"; const char* menuDebugInput = "输入"; const char* menuAnimationNoAnimation = "当前模型没有动画!"; const char* menuAnimationActivation = "开关"; const char* menuAnimationAnimationSequence = "动画序列"; }chineseUI; struct UniformBufferSet { Buffer scene; Buffer skybox; Buffer params; }; struct UBOMatrices { glm::mat4 projection; glm::mat4 model; glm::mat4 view; glm::vec3 camPos; } shaderDataScene, shaderDataSkybox; struct PushConstBlockMaterial { glm::vec4 baseColorFactor; glm::vec4 emissiveFactor; glm::vec4 diffuseFactor; glm::vec4 specularFactor; float workflow; int colorTextureSet; int PhysicalDescriptorTextureSet; int normalTextureSet; int occlusionTextureSet; int emissiveTextureSet; float metallicFactor; float roughnessFactor; float alphaMask; float alphaMaskCutoff; } pushConstBlockMaterial; struct FilePath { //model path std::string glTFModelFilePath = getAssetPath() + "models/DamagedHelmet/DamagedHelmet.gltf"; std::string modelVertShaderPath = getAssetPath() + "buster_drone/shaders/glsl/mesh.vert.spv"; std::string modelFragShaderPath = getAssetPath() + "buster_drone/shaders/glsl/mesh.frag.spv"; //ui std::string uiVertShaderPath = getAssetPath() + "shaders/ui.vert.spv"; std::string uiFragShaderPath = getAssetPath() + "shaders/ui.frag.spv"; // skybox path std::string skyboxModleFilePath = getAssetPath() + "models/cube.gltf"; std::string skyboxVertShaderPath = getAssetPath() + "shaders/skybox.vert.spv"; std::string skyboxFragShaderPath = getAssetPath() + "shaders/skybox.frag.spv"; std::string iblTexturesFilePath = getAssetPath() + "textures/hdr/pisa_cube.ktx"; //tonemapping std::string tonemappingVertShaderPath = getAssetPath() + "buster_drone/shaders/glsl/genbrdflut.vert.spv"; std::string tonemappingEnableFragShaderPath = getAssetPath() + "buster_drone/shaders/glsl/tonemapping_enable.frag.spv"; std::string tonemappingDisableFragShaderPath = getAssetPath() + "buster_drone/shaders/glsl/tonemapping_disable.frag.spv"; // cube map std::string irradianceFragShaderPath = getAssetPath() + "shaders/irradiancecube.frag.spv"; std::string filterVertShaderPath = getAssetPath() + "shaders/filtercube.vert.spv"; std::string prefilterEnvmapFragShaderPath = getAssetPath() + "shaders/prefilterenvmap.frag.spv"; //brdf cube map std::string brdfVertShaderPath = getAssetPath() + "shaders/genbrdflut.vert.spv"; std::string brdfFragShaderPath = getAssetPath() + "shaders/genbrdflut.frag.spv"; // environment map texture std::string envMapFilePath = getAssetPath() + "environments/papermill.ktx"; std::string emptyEnvmapFilePath = getAssetPath() + "textures/empty.ktx"; // pbr shader std::string pbrVertShaderPath = getAssetPath() + "shaders/pbr.vert.spv"; std::string pbrFragShaderPath = getAssetPath() + "shaders/pbr_khr.frag.spv"; //ttf file path std::string ttfFilePath = getAssetPath() + "/data/Roboto-Medium.ttf"; // output file path std::string imageOutputPath = getAssetPath() + "output/imageSequence"; std::string videoOutputPath = getAssetPath() + "output/video"; std::string totalImageOutputPath; // script file path std::string image2videoBatFilePath = getAssetPath() + "script/image2video.bat"; std::string image2videoShFilePath = getAssetPath() + "script/image2video.sh"; } filePath; glm::vec3 modelrot = glm::vec3(0.0f); glm::vec3 modelPos = glm::vec3(0.0f); enum PBRWorkflows { PBR_WORKFLOW_METALLIC_ROUGHNESS = 0, PBR_WORKFLOW_SPECULAR_GLOSINESS = 1 }; std::map<std::string, std::string> environments; std::string selectedEnvironment = "papermill"; std::map<std::string, std::string> scenes; std::string selectedScene = "DamagedHelmet"; int32_t debugViewInputs = 0; int32_t debugViewEquation = 0; struct StagingBuffer { VkBuffer buffer; VkDeviceMemory memory; } vertexStaging, indexStaging; struct Pipelines { VkPipeline skybox; VkPipeline pbr; VkPipeline pbrDoubleSided; VkPipeline pbrAlphaBlend; VkPipeline solid; VkPipeline wireframe = VK_NULL_HANDLE; VkPipeline toneMapping = VK_NULL_HANDLE; } pipelines; VkPipeline boundPipeline = VK_NULL_HANDLE; struct PipelineLayouts { VkDescriptorSetLayout scene; VkDescriptorSetLayout material; VkDescriptorSetLayout node; VkPipelineLayout tonemappingLayout; } pipelineLayouts; VkPipelineLayout pipelineLayout; struct DescriptorSets { VkDescriptorSet scene; VkDescriptorSet skybox; VkDescriptorSet tonemappingDescriptorSet = VK_NULL_HANDLE; }; struct DescriptorSetLayouts { VkDescriptorSetLayout scene; VkDescriptorSetLayout material; VkDescriptorSetLayout node; } descriptorSetLayouts; std::vector<DescriptorSets> descriptorSets; std::vector<VkCommandBuffer> commandBuffers; std::vector<UniformBufferSet> uniformBuffers; std::vector<VkFence> waitFences; std::vector<VkSemaphore> renderCompleteSemaphores; std::vector<VkSemaphore> presentCompleteSemaphores; const uint32_t renderAhead = 2; uint32_t frameIndex = 0; //VkImage swapChainImage; int32_t animationIndex = 0; float animationTimer = 0.0f; bool animate = true; bool displayBackground = true; struct LightSource { glm::vec3 color = glm::vec3(1.0f); glm::vec3 rotation = glm::vec3(75.0f, 40.0f, 0.0f); } lightSource; //cube map generation struct OffScreen { VkImage image; VkImageView view; VkDeviceMemory memory; VkFramebuffer framebuffer; } offscreen; struct IrradiancePushBlock { glm::mat4 mvp; // Sampling deltas float deltaPhi = (2.0f * float(M_PI)) / 180.0f; float deltaTheta = (0.5f * float(M_PI)) / 64.0f; } irradiancePushBlock; struct PrefilterPushBlock { glm::mat4 mvp; float roughness; uint32_t numSamples = 32u; } prefilterPushBlock; UI* gui; uint64_t savedFrameCounter = settings.startFrameCount; PlumageRender(); ~PlumageRender() { // Clean up used Vulkan resources // Note : Inherited destructor cleans up resources stored in base class vkDestroyPipeline(device, pipelines.skybox, nullptr); vkDestroyPipeline(device, pipelines.pbr, nullptr); vkDestroyPipeline(device, pipelines.pbrAlphaBlend, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.scene, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.material, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.node, nullptr); models.scene.destroy(device); models.skybox.destroy(device); for (auto buffer : uniformBuffers) { buffer.params.destroy(); buffer.scene.destroy(); buffer.skybox.destroy(); } for (auto fence : waitFences) { vkDestroyFence(device, fence, nullptr); } for (auto semaphore : renderCompleteSemaphores) { vkDestroySemaphore(device, semaphore, nullptr); } for (auto semaphore : presentCompleteSemaphores) { vkDestroySemaphore(device, semaphore, nullptr); } textures.environmentCube.destroy(); textures.irradianceCube.destroy(); textures.prefilteredCube.destroy(); textures.lutBrdf.destroy(); textures.empty.destroy(); delete gui; } void renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFModel::Material::AlphaMode alphaMode); void loadScene(std::string filename); void loadEnvironment(std::string filename); void buildCommandBuffers(); void loadAssets(); void setupNodeDescriptorSet(glTFModel::Node* node); void setupDescriptors(); void preparePipelines(); // void tonemappingPipelin(); void generateCubemaps(); void generateBRDFLUT(); void prepareUniformBuffers(); void updateUniformBuffers(); void updateShaderData(); void windowResized(); void prepare(); void submitWork(VkCommandBuffer cmdBuffer, VkQueue queue); void writeImageToFile(std::string filePath); void outputImageSequence(); void imageSequenceToVideo(); //void outputScreenShot(); uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties); virtual void render(); virtual void updateUIOverlay(); virtual void fileDropped(std::string filename); };