376 lines
10 KiB
C++
376 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 <cstdio>
|
|
#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/gcanyon_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;
|
|
std::string deviceSpecFilePath;
|
|
|
|
// 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 removeImageSequence();
|
|
//void outputScreenShot();
|
|
uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties);
|
|
virtual void render();
|
|
virtual void updateUIOverlay();
|
|
virtual void fileDropped(std::string filename);
|
|
}; |