parent
58212f943e
commit
b18564c1f5
File diff suppressed because it is too large
Load Diff
|
@ -34,27 +34,35 @@
|
||||||
namespace glTFModel
|
namespace glTFModel
|
||||||
{
|
{
|
||||||
|
|
||||||
struct Node;
|
enum DescriptorBindingFlags {
|
||||||
|
ImageBaseColor = 0x00000001,
|
||||||
struct BoundingBox {
|
ImageNormalMap = 0x00000002
|
||||||
glm::vec3 min;
|
|
||||||
glm::vec3 max;
|
|
||||||
bool valid = false;
|
|
||||||
BoundingBox();
|
|
||||||
BoundingBox(glm::vec3 min, glm::vec3 max);
|
|
||||||
BoundingBox getAABB(glm::mat4 m);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextureSampler {
|
enum FileLoadingFlags {
|
||||||
VkFilter magFilter;
|
None = 0x00000000,
|
||||||
VkFilter minFilter;
|
PreTransformVertices = 0x00000001,
|
||||||
VkSamplerAddressMode addressModeU;
|
PreMultiplyVertexColors = 0x00000002,
|
||||||
VkSamplerAddressMode addressModeV;
|
FlipY = 0x00000004,
|
||||||
VkSamplerAddressMode addressModeW;
|
DontLoadImages = 0x00000008
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum RenderFlags {
|
||||||
|
BindImages = 0x00000001,
|
||||||
|
RenderOpaqueNodes = 0x00000002,
|
||||||
|
RenderAlphaMaskedNodes = 0x00000004,
|
||||||
|
RenderAlphaBlendedNodes = 0x00000008
|
||||||
|
};
|
||||||
|
|
||||||
|
extern VkDescriptorSetLayout descriptorSetLayoutImage;
|
||||||
|
extern VkDescriptorSetLayout descriptorSetLayoutUbo;
|
||||||
|
extern VkMemoryPropertyFlags memoryPropertyFlags;
|
||||||
|
extern uint32_t descriptorBindingFlags;
|
||||||
|
|
||||||
|
// A glTF texture stores a reference to the image and a sampler
|
||||||
struct Texture {
|
struct Texture {
|
||||||
vks::VulkanDevice* device;
|
int32_t imageIndex;
|
||||||
|
vks::VulkanDevice* device = nullptr;
|
||||||
VkImage image;
|
VkImage image;
|
||||||
VkImageLayout imageLayout;
|
VkImageLayout imageLayout;
|
||||||
VkDeviceMemory deviceMemory;
|
VkDeviceMemory deviceMemory;
|
||||||
|
@ -66,85 +74,96 @@ namespace glTFModel
|
||||||
VkSampler sampler;
|
VkSampler sampler;
|
||||||
void updateDescriptor();
|
void updateDescriptor();
|
||||||
void destroy();
|
void destroy();
|
||||||
// Load a texture from a glTF image (stored as vector of chars loaded via stb_image) and generate a full mip chaing for it
|
void fromglTfImage(tinygltf::Image& gltfimage, std::string path, vks::VulkanDevice* device, VkQueue copyQueue);
|
||||||
void fromglTfImage(tinygltf::Image& gltfimage, TextureSampler textureSampler, vks::VulkanDevice* device, VkQueue copyQueue);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A glTF material stores information in e.g. the texture that is attached to it and colors
|
||||||
struct Material {
|
struct Material {
|
||||||
|
vks::VulkanDevice* device = nullptr;
|
||||||
enum AlphaMode { ALPHAMODE_OPAQUE, ALPHAMODE_MASK, ALPHAMODE_BLEND };
|
enum AlphaMode { ALPHAMODE_OPAQUE, ALPHAMODE_MASK, ALPHAMODE_BLEND };
|
||||||
AlphaMode alphaMode = ALPHAMODE_OPAQUE;
|
AlphaMode alphaMode = ALPHAMODE_OPAQUE;
|
||||||
float alphaCutoff = 1.0f;
|
float alphaCutoff = 1.0f;
|
||||||
float metallicFactor = 1.0f;
|
float metallicFactor = 1.0f;
|
||||||
float roughnessFactor = 1.0f;
|
float roughnessFactor = 1.0f;
|
||||||
glm::vec4 baseColorFactor = glm::vec4(1.0f);
|
glm::vec4 baseColorFactor = glm::vec4(1.0f);
|
||||||
glm::vec4 emissiveFactor = glm::vec4(1.0f);
|
glTFModel::Texture* baseColorTexture = nullptr;
|
||||||
glTFModel::Texture* baseColorTexture;
|
glTFModel::Texture* metallicRoughnessTexture = nullptr;
|
||||||
glTFModel::Texture* metallicRoughnessTexture;
|
glTFModel::Texture* normalTexture = nullptr;
|
||||||
glTFModel::Texture* normalTexture;
|
glTFModel::Texture* occlusionTexture = nullptr;
|
||||||
glTFModel::Texture* occlusionTexture;
|
glTFModel::Texture* emissiveTexture = nullptr;
|
||||||
glTFModel::Texture* emissiveTexture;
|
|
||||||
bool doubleSided = false;
|
glTFModel::Texture* specularGlossinessTexture;
|
||||||
struct TexCoordSets {
|
glTFModel::Texture* diffuseTexture;
|
||||||
uint8_t baseColor = 0;
|
|
||||||
uint8_t metallicRoughness = 0;
|
|
||||||
uint8_t specularGlossiness = 0;
|
|
||||||
uint8_t normal = 0;
|
|
||||||
uint8_t occlusion = 0;
|
|
||||||
uint8_t emissive = 0;
|
|
||||||
} texCoordSets;
|
|
||||||
struct Extension {
|
|
||||||
glTFModel::Texture* specularGlossinessTexture;
|
|
||||||
glTFModel::Texture* diffuseTexture;
|
|
||||||
glm::vec4 diffuseFactor = glm::vec4(1.0f);
|
|
||||||
glm::vec3 specularFactor = glm::vec3(0.0f);
|
|
||||||
} extension;
|
|
||||||
struct PbrWorkflows {
|
|
||||||
bool metallicRoughness = true;
|
|
||||||
bool specularGlossiness = false;
|
|
||||||
} pbrWorkflows;
|
|
||||||
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
Material(vks::VulkanDevice* device) : device(device) {};
|
||||||
|
void createDescriptorSet(VkDescriptorPool descriptorPool, VkDescriptorSetLayout descriptorSetLayout, uint32_t descriptorBindingFlags);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A primitive contains the data for a single draw call
|
||||||
struct Primitive {
|
struct Primitive {
|
||||||
uint32_t firstIndex;
|
uint32_t firstIndex;
|
||||||
uint32_t indexCount;
|
uint32_t indexCount;
|
||||||
|
uint32_t firstVertex;
|
||||||
uint32_t vertexCount;
|
uint32_t vertexCount;
|
||||||
Material& material;
|
Material& material;
|
||||||
bool hasIndices;
|
|
||||||
BoundingBox bb;
|
struct Dimensions {
|
||||||
Primitive(uint32_t firstIndex, uint32_t indexCount, uint32_t vertexCount, Material& material);
|
glm::vec3 min = glm::vec3(FLT_MAX);
|
||||||
void setBoundingBox(glm::vec3 min, glm::vec3 max);
|
glm::vec3 max = glm::vec3(-FLT_MAX);
|
||||||
|
glm::vec3 size;
|
||||||
|
glm::vec3 center;
|
||||||
|
float radius;
|
||||||
|
} dimensions;
|
||||||
|
|
||||||
|
void setDimensions(glm::vec3 min, glm::vec3 max);
|
||||||
|
Primitive(uint32_t firstIndex, uint32_t indexCount, Material& material) : firstIndex(firstIndex), indexCount(indexCount), material(material) {};
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Contains the node's (optional) geometry and can be made up of an arbitrary number of primitives
|
||||||
struct Mesh {
|
struct Mesh {
|
||||||
vks::VulkanDevice* device;
|
vks::VulkanDevice* device;
|
||||||
|
|
||||||
std::vector<Primitive*> primitives;
|
std::vector<Primitive*> primitives;
|
||||||
BoundingBox bb;
|
std::string name;
|
||||||
BoundingBox aabb;
|
|
||||||
struct UniformBuffer {
|
struct UniformBuffer {
|
||||||
VkBuffer buffer;
|
VkBuffer buffer;
|
||||||
VkDeviceMemory memory;
|
VkDeviceMemory memory;
|
||||||
VkDescriptorBufferInfo descriptor;
|
VkDescriptorBufferInfo descriptor;
|
||||||
VkDescriptorSet descriptorSet;
|
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
||||||
void* mapped;
|
void* mapped;
|
||||||
} uniformBuffer;
|
} uniformBuffer;
|
||||||
|
|
||||||
struct UniformBlock {
|
struct UniformBlock {
|
||||||
glm::mat4 matrix;
|
glm::mat4 matrix;
|
||||||
glm::mat4 jointMatrix[128]{};
|
glm::mat4 jointMatrix[64]{};
|
||||||
float jointcount{ 0 };
|
float jointCount{ 0 };
|
||||||
} uniformBlock;
|
} uniformBlock;
|
||||||
|
|
||||||
Mesh(vks::VulkanDevice* device, glm::mat4 matrix);
|
Mesh(vks::VulkanDevice* device, glm::mat4 matrix);
|
||||||
~Mesh();
|
~Mesh();
|
||||||
void setBoundingBox(glm::vec3 min, glm::vec3 max);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Node;
|
||||||
|
|
||||||
|
/*
|
||||||
|
glTF skin
|
||||||
|
*/
|
||||||
struct Skin {
|
struct Skin {
|
||||||
std::string name;
|
std::string name;
|
||||||
Node* skeletonRoot = nullptr;
|
Node* skeletonRoot = nullptr;
|
||||||
std::vector<glm::mat4> inverseBindMatrices;
|
std::vector<glm::mat4> inverseBindMatrices;
|
||||||
std::vector<Node*> joints;
|
std::vector<Node*> joints;
|
||||||
};
|
};
|
||||||
|
// A node represents an object in the glTF scene graph
|
||||||
struct Node {
|
struct Node {
|
||||||
Node* parent;
|
Node* parent;
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
|
@ -157,102 +176,133 @@ namespace glTFModel
|
||||||
glm::vec3 translation{};
|
glm::vec3 translation{};
|
||||||
glm::vec3 scale{ 1.0f };
|
glm::vec3 scale{ 1.0f };
|
||||||
glm::quat rotation{};
|
glm::quat rotation{};
|
||||||
BoundingBox bvh;
|
|
||||||
BoundingBox aabb;
|
|
||||||
glm::mat4 localMatrix();
|
glm::mat4 localMatrix();
|
||||||
glm::mat4 getMatrix();
|
glm::mat4 getMatrix();
|
||||||
void update();
|
void update();
|
||||||
~Node();
|
~Node();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnimationChannel {
|
/*
|
||||||
enum PathType { TRANSLATION, ROTATION, SCALE };
|
glTF default vertex layout with easy Vulkan mapping functions
|
||||||
PathType path;
|
*/
|
||||||
Node* node;
|
enum class VertexComponent { Position, Normal, UV, Color, Tangent, Joint0, Weight0 };
|
||||||
uint32_t samplerIndex;
|
|
||||||
|
// The vertex layout for the samples' model
|
||||||
|
struct Vertex {
|
||||||
|
glm::vec3 pos;
|
||||||
|
glm::vec3 normal;
|
||||||
|
glm::vec2 uv;
|
||||||
|
glm::vec4 color;
|
||||||
|
glm::vec4 joint0;
|
||||||
|
glm::vec4 weight0;
|
||||||
|
glm::vec4 tangent;
|
||||||
|
static VkVertexInputBindingDescription vertexInputBindingDescription;
|
||||||
|
static std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions;
|
||||||
|
static VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo;
|
||||||
|
static VkVertexInputBindingDescription inputBindingDescription(uint32_t binding);
|
||||||
|
static VkVertexInputAttributeDescription inputAttributeDescription(uint32_t binding, uint32_t location, VertexComponent component);
|
||||||
|
static std::vector<VkVertexInputAttributeDescription> inputAttributeDescriptions(uint32_t binding, const std::vector<VertexComponent> components);
|
||||||
|
/** @brief Returns the default pipeline vertex input state create info structure for the requested vertex components */
|
||||||
|
static VkPipelineVertexInputStateCreateInfo* getPipelineVertexInputState(const std::vector<VertexComponent> components);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnimationSampler {
|
|
||||||
|
|
||||||
|
|
||||||
|
struct AnimationSampler
|
||||||
|
{
|
||||||
enum InterpolationType { LINEAR, STEP, CUBICSPLINE };
|
enum InterpolationType { LINEAR, STEP, CUBICSPLINE };
|
||||||
InterpolationType interpolation;
|
InterpolationType interpolation;
|
||||||
std::vector<float> inputs;
|
std::vector<float> inputs;
|
||||||
std::vector<glm::vec4> outputsVec4;
|
std::vector<glm::vec4> outputsVec4;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Animation {
|
struct AnimationChannel
|
||||||
|
{
|
||||||
|
enum PathType { TRANSLATION, ROTATION, SCALE };
|
||||||
|
PathType path;
|
||||||
|
Node* node;
|
||||||
|
uint32_t samplerIndex;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Animation
|
||||||
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<AnimationSampler> samplers;
|
std::vector<AnimationSampler> samplers;
|
||||||
std::vector<AnimationChannel> channels;
|
std::vector<AnimationChannel> channels;
|
||||||
|
|
||||||
float start = std::numeric_limits<float>::max();
|
float start = std::numeric_limits<float>::max();
|
||||||
float end = std::numeric_limits<float>::min();
|
float end = std::numeric_limits<float>::min();
|
||||||
|
float currentTime = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Model {
|
/*
|
||||||
|
glTF model loading and rendering class
|
||||||
|
*/
|
||||||
|
class Model {
|
||||||
|
private:
|
||||||
|
glTFModel::Texture* getTexture(uint32_t index);
|
||||||
|
glTFModel::Texture emptyTexture;
|
||||||
|
void createEmptyTexture(VkQueue transferQueue);
|
||||||
|
public:
|
||||||
vks::VulkanDevice* device;
|
vks::VulkanDevice* device;
|
||||||
|
VkDescriptorPool descriptorPool;
|
||||||
struct Vertex {
|
|
||||||
glm::vec3 pos;
|
|
||||||
glm::vec3 normal;
|
|
||||||
glm::vec2 uv0;
|
|
||||||
glm::vec2 uv1;
|
|
||||||
glm::vec4 joint0;
|
|
||||||
glm::vec4 weight0;
|
|
||||||
glm::vec4 color;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Vertices {
|
struct Vertices {
|
||||||
VkBuffer buffer = VK_NULL_HANDLE;
|
int count;
|
||||||
|
VkBuffer buffer;
|
||||||
VkDeviceMemory memory;
|
VkDeviceMemory memory;
|
||||||
} vertices;
|
} vertices;
|
||||||
struct Indices {
|
struct Indices {
|
||||||
VkBuffer buffer = VK_NULL_HANDLE;
|
int count;
|
||||||
|
VkBuffer buffer;
|
||||||
VkDeviceMemory memory;
|
VkDeviceMemory memory;
|
||||||
} indices;
|
} indices;
|
||||||
|
|
||||||
glm::mat4 aabb;
|
|
||||||
|
|
||||||
std::vector<Node*> nodes;
|
std::vector<Node*> nodes;
|
||||||
std::vector<Node*> linearNodes;
|
std::vector<Node*> linearNodes;
|
||||||
|
|
||||||
std::vector<Skin*> skins;
|
std::vector<Skin*> skins;
|
||||||
|
|
||||||
std::vector<Texture> textures;
|
std::vector<Texture> textures;
|
||||||
std::vector<TextureSampler> textureSamplers;
|
|
||||||
std::vector<Material> materials;
|
std::vector<Material> materials;
|
||||||
std::vector<Animation> animations;
|
std::vector<Animation> animations;
|
||||||
std::vector<std::string> extensions;
|
|
||||||
|
|
||||||
struct Dimensions {
|
struct Dimensions {
|
||||||
glm::vec3 min = glm::vec3(FLT_MAX);
|
glm::vec3 min = glm::vec3(FLT_MAX);
|
||||||
glm::vec3 max = glm::vec3(-FLT_MAX);
|
glm::vec3 max = glm::vec3(-FLT_MAX);
|
||||||
|
glm::vec3 size;
|
||||||
|
glm::vec3 center;
|
||||||
|
float radius;
|
||||||
} dimensions;
|
} dimensions;
|
||||||
|
|
||||||
struct LoaderInfo {
|
bool metallicRoughnessWorkflow = true;
|
||||||
uint32_t* indexBuffer;
|
bool buffersBound = false;
|
||||||
Vertex* vertexBuffer;
|
std::string path;
|
||||||
size_t indexPos = 0;
|
|
||||||
size_t vertexPos = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
void destroy(VkDevice device);
|
Model() {};
|
||||||
void loadNode(glTFModel::Node* parent, const tinygltf::Node& node, uint32_t nodeIndex, const tinygltf::Model& model, LoaderInfo& loaderInfo, float globalscale);
|
~Model();
|
||||||
void getNodeProps(const tinygltf::Node& node, const tinygltf::Model& model, size_t& vertexCount, size_t& indexCount);
|
void loadNode(glTFModel::Node* parent, const tinygltf::Node& node, uint32_t nodeIndex, const tinygltf::Model& model, std::vector<uint32_t>& indexBuffer, std::vector<Vertex>& vertexBuffer, float globalscale);
|
||||||
void loadSkins(tinygltf::Model& gltfModel);
|
void loadSkins(tinygltf::Model& gltfModel);
|
||||||
void loadTextures(tinygltf::Model& gltfModel, vks::VulkanDevice* device, VkQueue transferQueue);
|
void loadImages(tinygltf::Model& gltfModel, vks::VulkanDevice* device, VkQueue transferQueue);
|
||||||
VkSamplerAddressMode getVkWrapMode(int32_t wrapMode);
|
|
||||||
VkFilter getVkFilterMode(int32_t filterMode);
|
|
||||||
void loadTextureSamplers(tinygltf::Model& gltfModel);
|
|
||||||
void loadMaterials(tinygltf::Model& gltfModel);
|
void loadMaterials(tinygltf::Model& gltfModel);
|
||||||
void loadAnimations(tinygltf::Model& gltfModel);
|
void loadAnimations(tinygltf::Model& gltfModel);
|
||||||
void loadFromFile(std::string filename, vks::VulkanDevice* device, VkQueue transferQueue, float scale = 1.0f);
|
void loadFromFile(std::string filename, vks::VulkanDevice* device, VkQueue transferQueue, uint32_t fileLoadingFlags = glTFModel::FileLoadingFlags::None, float scale = 1.0f);
|
||||||
void drawNode(Node* node, VkCommandBuffer commandBuffer);
|
void bindBuffers(VkCommandBuffer commandBuffer);
|
||||||
void draw(VkCommandBuffer commandBuffer);
|
void drawNode(Node* node, VkCommandBuffer commandBuffer, uint32_t renderFlags = 0, VkPipelineLayout pipelineLayout = VK_NULL_HANDLE, uint32_t bindImageSet = 1);
|
||||||
void calculateBoundingBox(Node* node, Node* parent);
|
void draw(VkCommandBuffer commandBuffer, uint32_t renderFlags = 0, VkPipelineLayout pipelineLayout = VK_NULL_HANDLE, uint32_t bindImageSet = 1);
|
||||||
|
void getNodeDimensions(Node* node, glm::vec3& min, glm::vec3& max);
|
||||||
void getSceneDimensions();
|
void getSceneDimensions();
|
||||||
void updateAnimation(uint32_t index, float time);
|
void updateAnimation(uint32_t index, float time);
|
||||||
Node* findNode(Node* parent, uint32_t index);
|
Node* findNode(Node* parent, uint32_t index);
|
||||||
Node* nodeFromIndex(uint32_t index);
|
Node* nodeFromIndex(uint32_t index);
|
||||||
|
void prepareNodeDescriptor(glTFModel::Node* node, VkDescriptorSetLayout descriptorSetLayout);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,83 +49,7 @@ PlumageRender::PlumageRender():
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFModel::Material::AlphaMode alphaMode) {
|
|
||||||
if (node->mesh) {
|
|
||||||
// Render mesh primitives
|
|
||||||
for (glTFModel::Primitive* primitive : node->mesh->primitives) {
|
|
||||||
if (primitive->material.alphaMode == alphaMode) {
|
|
||||||
|
|
||||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
|
||||||
switch (alphaMode) {
|
|
||||||
case glTFModel::Material::ALPHAMODE_OPAQUE:
|
|
||||||
case glTFModel::Material::ALPHAMODE_MASK:
|
|
||||||
pipeline = primitive->material.doubleSided ? pipelines.pbrDoubleSided : pipelines.pbr;
|
|
||||||
break;
|
|
||||||
case glTFModel::Material::ALPHAMODE_BLEND:
|
|
||||||
pipeline = pipelines.pbrAlphaBlend;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pipeline != boundPipeline) {
|
|
||||||
vkCmdBindPipeline(commandBuffers[cbIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
|
||||||
boundPipeline = pipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<VkDescriptorSet> descriptorsets = {
|
|
||||||
descriptorSets[cbIndex].scene,
|
|
||||||
primitive->material.descriptorSet,
|
|
||||||
node->mesh->uniformBuffer.descriptorSet,
|
|
||||||
};
|
|
||||||
vkCmdBindDescriptorSets(commandBuffers[cbIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, static_cast<uint32_t>(descriptorsets.size()), descriptorsets.data(), 0, NULL);
|
|
||||||
|
|
||||||
// Pass material parameters as push constants
|
|
||||||
PushConstBlockMaterial pushConstBlockMaterial{};
|
|
||||||
pushConstBlockMaterial.emissiveFactor = primitive->material.emissiveFactor;
|
|
||||||
// To save push constant space, availabilty and texture coordiante set are combined
|
|
||||||
// -1 = texture not used for this material, >= 0 texture used and index of texture coordinate set
|
|
||||||
pushConstBlockMaterial.colorTextureSet = primitive->material.baseColorTexture != nullptr ? primitive->material.texCoordSets.baseColor : -1;
|
|
||||||
pushConstBlockMaterial.normalTextureSet = primitive->material.normalTexture != nullptr ? primitive->material.texCoordSets.normal : -1;
|
|
||||||
pushConstBlockMaterial.occlusionTextureSet = primitive->material.occlusionTexture != nullptr ? primitive->material.texCoordSets.occlusion : -1;
|
|
||||||
pushConstBlockMaterial.emissiveTextureSet = primitive->material.emissiveTexture != nullptr ? primitive->material.texCoordSets.emissive : -1;
|
|
||||||
pushConstBlockMaterial.alphaMask = static_cast<float>(primitive->material.alphaMode == vkglTF::Material::ALPHAMODE_MASK);
|
|
||||||
pushConstBlockMaterial.alphaMaskCutoff = primitive->material.alphaCutoff;
|
|
||||||
|
|
||||||
// TODO: glTF specs states that metallic roughness should be preferred, even if specular glosiness is present
|
|
||||||
|
|
||||||
if (primitive->material.pbrWorkflows.metallicRoughness) {
|
|
||||||
// Metallic roughness workflow
|
|
||||||
pushConstBlockMaterial.workflow = static_cast<float>(PBR_WORKFLOW_METALLIC_ROUGHNESS);
|
|
||||||
pushConstBlockMaterial.baseColorFactor = primitive->material.baseColorFactor;
|
|
||||||
pushConstBlockMaterial.metallicFactor = primitive->material.metallicFactor;
|
|
||||||
pushConstBlockMaterial.roughnessFactor = primitive->material.roughnessFactor;
|
|
||||||
pushConstBlockMaterial.PhysicalDescriptorTextureSet = primitive->material.metallicRoughnessTexture != nullptr ? primitive->material.texCoordSets.metallicRoughness : -1;
|
|
||||||
pushConstBlockMaterial.colorTextureSet = primitive->material.baseColorTexture != nullptr ? primitive->material.texCoordSets.baseColor : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (primitive->material.pbrWorkflows.specularGlossiness) {
|
|
||||||
// Specular glossiness workflow
|
|
||||||
pushConstBlockMaterial.workflow = static_cast<float>(PBR_WORKFLOW_SPECULAR_GLOSINESS);
|
|
||||||
pushConstBlockMaterial.PhysicalDescriptorTextureSet = primitive->material.extension.specularGlossinessTexture != nullptr ? primitive->material.texCoordSets.specularGlossiness : -1;
|
|
||||||
pushConstBlockMaterial.colorTextureSet = primitive->material.extension.diffuseTexture != nullptr ? primitive->material.texCoordSets.baseColor : -1;
|
|
||||||
pushConstBlockMaterial.diffuseFactor = primitive->material.extension.diffuseFactor;
|
|
||||||
pushConstBlockMaterial.specularFactor = glm::vec4(primitive->material.extension.specularFactor, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
vkCmdPushConstants(commandBuffers[cbIndex], pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstBlockMaterial), &pushConstBlockMaterial);
|
|
||||||
|
|
||||||
if (primitive->hasIndices) {
|
|
||||||
vkCmdDrawIndexed(commandBuffers[cbIndex], primitive->indexCount, 1, primitive->firstIndex, 0, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vkCmdDraw(commandBuffers[cbIndex], primitive->vertexCount, 1, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
for (auto child : node->children) {
|
|
||||||
renderNode(child, cbIndex, alphaMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlumageRender::buildCommandBuffers()
|
void PlumageRender::buildCommandBuffers()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,18 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <chrono>
|
|
||||||
#include <map>
|
|
||||||
#include "algorithm"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
#include "glTFModel.h"
|
#include "glTFModel.h"
|
||||||
|
|
||||||
|
@ -33,7 +21,7 @@ public:
|
||||||
{
|
{
|
||||||
glTFModel::Model scene;
|
glTFModel::Model scene;
|
||||||
glTFModel::Model skybox;
|
glTFModel::Model skybox;
|
||||||
}models;
|
};
|
||||||
|
|
||||||
struct Textures {
|
struct Textures {
|
||||||
vks::TextureCubeMap environmentCube;
|
vks::TextureCubeMap environmentCube;
|
||||||
|
@ -54,9 +42,9 @@ public:
|
||||||
} shaderData;
|
} shaderData;
|
||||||
|
|
||||||
struct UniformBufferSet {
|
struct UniformBufferSet {
|
||||||
vks::Buffer scene;
|
Buffer scene;
|
||||||
vks::Buffer skybox;
|
Buffer skybox;
|
||||||
vks::Buffer params;
|
Buffer params;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UBOMatrices {
|
struct UBOMatrices {
|
||||||
|
@ -103,20 +91,6 @@ public:
|
||||||
|
|
||||||
} filePath;
|
} filePath;
|
||||||
|
|
||||||
bool rotateModel = false;
|
|
||||||
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";
|
|
||||||
|
|
||||||
|
|
||||||
int32_t debugViewInputs = 0;
|
|
||||||
int32_t debugViewEquation = 0;
|
|
||||||
|
|
||||||
struct StagingBuffer {
|
struct StagingBuffer {
|
||||||
VkBuffer buffer;
|
VkBuffer buffer;
|
||||||
VkDeviceMemory memory;
|
VkDeviceMemory memory;
|
||||||
|
@ -132,8 +106,6 @@ public:
|
||||||
VkPipeline toneMapping = VK_NULL_HANDLE;
|
VkPipeline toneMapping = VK_NULL_HANDLE;
|
||||||
} pipelines;
|
} pipelines;
|
||||||
|
|
||||||
VkPipeline boundPipeline = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
struct PipelineLayouts
|
struct PipelineLayouts
|
||||||
{
|
{
|
||||||
VkDescriptorSetLayout scene;
|
VkDescriptorSetLayout scene;
|
||||||
|
@ -143,45 +115,23 @@ public:
|
||||||
} pipelineLayouts;
|
} pipelineLayouts;
|
||||||
|
|
||||||
VkPipelineLayout pipelineLayout;
|
VkPipelineLayout pipelineLayout;
|
||||||
|
|
||||||
struct DescriptorSets {
|
struct DescriptorSets {
|
||||||
VkDescriptorSet scene;
|
VkDescriptorSet scene;
|
||||||
VkDescriptorSet skybox;
|
VkDescriptorSet skybox;
|
||||||
VkDescriptorSet tonemappingDescriptorSet = VK_NULL_HANDLE;
|
VkDescriptorSet tonemappingDescriptorSet = VK_NULL_HANDLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct DescriptorSetLayouts {
|
struct DescriptorSetLayouts {
|
||||||
VkDescriptorSetLayout scene;
|
VkDescriptorSetLayout scene;
|
||||||
VkDescriptorSetLayout material;
|
VkDescriptorSetLayout material;
|
||||||
VkDescriptorSetLayout node;
|
VkDescriptorSetLayout node;
|
||||||
} descriptorSetLayouts;
|
} 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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
struct OffScreen
|
struct OffScreen
|
||||||
{
|
{
|
||||||
VkImage image;
|
VkImage image;
|
||||||
|
@ -189,7 +139,7 @@ public:
|
||||||
VkDeviceMemory memory;
|
VkDeviceMemory memory;
|
||||||
VkFramebuffer framebuffer;
|
VkFramebuffer framebuffer;
|
||||||
} offscreen;
|
} offscreen;
|
||||||
*/
|
|
||||||
struct IrradiancePushBlock
|
struct IrradiancePushBlock
|
||||||
{
|
{
|
||||||
glm::mat4 mvp;
|
glm::mat4 mvp;
|
||||||
|
@ -211,42 +161,30 @@ public:
|
||||||
{
|
{
|
||||||
// Clean up used Vulkan resources
|
// Clean up used Vulkan resources
|
||||||
// Note : Inherited destructor cleans up resources stored in base class
|
// Note : Inherited destructor cleans up resources stored in base class
|
||||||
vkDestroyPipeline(device, pipelines.skybox, nullptr);
|
vkDestroyPipeline(device, pipelines.solid, nullptr);
|
||||||
vkDestroyPipeline(device, pipelines.pbr, nullptr);
|
vkDestroyPipeline(device, pipelines.toneMapping, nullptr);
|
||||||
vkDestroyPipeline(device, pipelines.pbrAlphaBlend, nullptr);
|
if (pipelines.wireframe != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyPipeline(device, pipelines.wireframe, 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();
|
vkDestroyPipelineLayout(device, pipelineLayouts.pbrLayout, nullptr);
|
||||||
textures.irradianceCube.destroy();
|
vkDestroyPipelineLayout(device, pipelineLayouts.tonemappingLayout, nullptr);
|
||||||
textures.prefilteredCube.destroy();
|
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.matrices, nullptr);
|
||||||
textures.lutBrdf.destroy();
|
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textures, nullptr);
|
||||||
textures.empty.destroy();
|
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.materialUniform, nullptr);
|
||||||
|
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.ssbo, nullptr);
|
||||||
|
|
||||||
|
pbrFrameBuffer.color.destroy(device);
|
||||||
|
pbrFrameBuffer.depth.destroy(device);
|
||||||
|
pbrFrameBuffer.fbo.destroy(device);
|
||||||
|
vkDestroySampler(device, colorSampler, nullptr);
|
||||||
|
|
||||||
|
shaderData.buffer.destroy();
|
||||||
|
shaderData.skinSSBO.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getEnabledFeatures();
|
virtual void getEnabledFeatures();
|
||||||
void renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFModel::Material::AlphaMode alphaMode);
|
void createAttachment(VkFormat format, VkImageUsageFlagBits usage, FrameBufferAttachment* attachment, uint32_t width, uint32_t height);
|
||||||
virtual void setupFrameBuffer();
|
virtual void setupFrameBuffer();
|
||||||
void buildCommandBuffers();
|
void buildCommandBuffers();
|
||||||
void loadAssets();
|
void loadAssets();
|
||||||
|
|
Loading…
Reference in New Issue