plumageRender/src/render/render.h

373 lines
10 KiB
C++

#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);
};