* Added helper function for easy pipeline vertex input state create info structure setup from glTF model vertex class * Split glTF loader into header and implementation * Updated sample to use glTF * Removed collada files Replaced assets are now part of the asset pack * Return value for glTF model vertex input state create info helper * Removed unused assets * Use glTF assets * Added default material for glTF node's without materials * Use glTF assets * Apply pre-transforms to normals * Use glTF assets * Use glTF assets * Use vertex input state from glTF model class * Scene setup * Use glTF assets * Use glTF assets * Display error message and exit if glTF file could not be loaded * Use glTF assets * Use glTF assets * Use glTF assets * Remove unused buffer binds * Use glTF assets * Remove no longer used model files * Remove no longer used model files * Added support for rendering glTF models with images * glTF model normal pre-transform ignores translation * Use glTF assets * Use glTF assets * Use glTF assets * Use glTF assets * Use glTF assets * Only add combined image samplers to pool if actually used in the scene * Use global descriptor set layouts * Use global descriptor set layouts * Use glTF assets * Use glTF assets * Use glTF assets Code cleanup Updated GLSL and HLSL shaders * Use glTF assets Code cleanup * Use glTF assets Code cleanup Updated GLSL and HLSL shaders * Remove no-longer used model * Use glTF assets Code cleanup Updated GLSL and HLSL shaders * Use glTF assets Code cleanup Updated GLSL and HLSL shaders Removed no-longer used model * Use glTF assets Code cleanup Use RGBA texture instead of different compressed formats Removed no-longer used assets * Adnrdoid build file * Use glTF assets Code cleanup and refactoring Updated GLSL and HLSL shaders * Added vertex count and way of passing additional memory property type flags to glTF loader * Use glTF assets Updated GLSL and HLSL shaders Removed no-longer used assets * Use glTF assets Updated GLSL and HLSL shaders * Remove unfinished sample * Completely reworked push constants sample Use glTF assets Updated GLSL and HLSL shaders Removed no-longer used assets * Android CMake build files * Removed un-used asset * Explicit buffer binding function * Use glTF assets Code cleanup Updated GLSL and HLSL shaders * Use glTF assets Code cleanup * Use glTF assets Code cleanup Removed no-longer used assets * Use glTF assets Code cleanup Updated GLSL and HLSL shaders Removed no-longer used assets * Remove no-longer used asset * Use glTF assets Code cleanup and refactoring Performance optimizations Updated GLSL and HLSL shaders Removed no-longer used assets * Use glTF assets Code cleanup and refactoring Updated GLSL and HLSL shaders Removed no-longer used assets * Use glTF assets Code cleanup and refactoring Updated GLSL and HLSL shaders Removed no-longer used assets * Use glTF assets Code cleanup and refactoring Removed no-longer used assets * Use glTF assets Code cleanup and refactoring Removed no-longer used assets * Use glTF assets Code cleanup and refactoring * Use glTF assets Code cleanup and refactoring * Use glTF assets Code cleanup and refactoring Removed no-longer used assets * Pass vertex size and calculate multiplier in shaders instead of hard-coding With this, changes to the glTF vertex structure won't break the ray tracing samples * Load tangents (if present) * Use glTF assets Code cleanup and heavy refactoring Reworked debug display code * Android build * Normal mapping fixes Udpated HLSL shaders * Use glTF assets Code cleanup and heavy refactoring Reworked debug display code Updated GLSL and HLSL shaders * Code cleanup, comments * Use glTF assets Code cleanup and heavy refactoring Reworked debug display code Updated GLSL and HLSL shaders * Added sample count to framebuffer create info * Removed no-longer used assets * Android build Removed no-longer used assets * Code cleanup and heavy refactoring Updated GLSL and HLSL shaders Use tangents stored in GLSL instead of calculating them in the fragment shader * Renamed textured PBR sample main cpp file * Use glTF assets Code cleanup and refactoring Updated GLSL and HLSL shaders Removed no-longer used assets * Use glTF assets Removed no-longer used assets * Android build files * Android build files * Use glTF assets Removed no-longer used assets * Fixed HLSL shaders * Android build files * Use glTF assets Updated GLSL and HLSL shaders Removed no-longer used assets * Use glTF assets Updated GLSL and HLSL shaders Removed no-longer used assets * Added flag to disable glTF image loading Useful for samples that use their own textures or don't use textures at all to speed up loading * Use glTF assets Code cleanup Use Sponza scene instead of Sibenik to better highlight the effect Updated GLSL and HLSL shaders * Updated Android build files * Removed left-over comment * Use Sponza scene for the SSAO sample * Removed unused code * Removed ASSIMP No longer required as all samples now use the glTF file format * Added missing vertex shader stage * Removed old ASSIMP-based model loader * Added support for loading external glTF images from ktx Android fixes for loading external buffer files * Scene setup * Added missing shader stages * Removed ASSIMP from build files * Fixed compiler warning * Removed ASSIMP from readmes * Android build files cleanup * Replaced ktx submodule with only the files required for this repo The ktx submodule was a tad too big and contained lots of files not required for this repo * Moved ktx build files into base project * Use glTF assets * Use glTF assets * Removed license files, will be moved to asset pack * Use RGBA textures * Use RGBA cubemp texture with face assignment based on original images Refs #679 * Android build files * Removed textures All textures will be moved to the asset pack * Ignore asset folders * Removed font Fonts will be moved to the asset pack * Link to gltf asset pack * Updated gitignore * Android build file
297 lines
No EOL
8 KiB
C++
297 lines
No EOL
8 KiB
C++
/*
|
|
* Vulkan glTF model and texture loading class based on tinyglTF (https://github.com/syoyo/tinygltf)
|
|
*
|
|
* Copyright (C) 2018 by Sascha Willems - www.saschawillems.de
|
|
*
|
|
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdlib.h>
|
|
#include <string>
|
|
#include <fstream>
|
|
#include <vector>
|
|
|
|
#include "vulkan/vulkan.h"
|
|
#include "VulkanDevice.hpp"
|
|
|
|
#include <ktx.h>
|
|
#include <ktxvulkan.h>
|
|
|
|
#define GLM_FORCE_RADIANS
|
|
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
|
#include <glm/glm.hpp>
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
|
|
#define TINYGLTF_NO_STB_IMAGE_WRITE
|
|
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
|
#define TINYGLTF_ANDROID_LOAD_FROM_ASSETS
|
|
#endif
|
|
#include "tiny_gltf.h"
|
|
|
|
#if defined(__ANDROID__)
|
|
#include <android/asset_manager.h>
|
|
#endif
|
|
|
|
namespace vkglTF
|
|
{
|
|
extern VkDescriptorSetLayout descriptorSetLayoutImage;
|
|
extern VkDescriptorSetLayout descriptorSetLayoutUbo;
|
|
extern VkMemoryPropertyFlags memoryPropertyFlags;
|
|
|
|
struct Node;
|
|
|
|
/*
|
|
glTF texture loading class
|
|
*/
|
|
struct Texture {
|
|
vks::VulkanDevice* device;
|
|
VkImage image;
|
|
VkImageLayout imageLayout;
|
|
VkDeviceMemory deviceMemory;
|
|
VkImageView view;
|
|
uint32_t width, height;
|
|
uint32_t mipLevels;
|
|
uint32_t layerCount;
|
|
VkDescriptorImageInfo descriptor;
|
|
VkSampler sampler;
|
|
void updateDescriptor();
|
|
void destroy();
|
|
void fromglTfImage(tinygltf::Image& gltfimage, std::string path, vks::VulkanDevice* device, VkQueue copyQueue);
|
|
};
|
|
|
|
/*
|
|
glTF material class
|
|
*/
|
|
struct Material {
|
|
vks::VulkanDevice* device;
|
|
enum AlphaMode { ALPHAMODE_OPAQUE, ALPHAMODE_MASK, ALPHAMODE_BLEND };
|
|
AlphaMode alphaMode = ALPHAMODE_OPAQUE;
|
|
float alphaCutoff = 1.0f;
|
|
float metallicFactor = 1.0f;
|
|
float roughnessFactor = 1.0f;
|
|
glm::vec4 baseColorFactor = glm::vec4(1.0f);
|
|
vkglTF::Texture* baseColorTexture = nullptr;
|
|
vkglTF::Texture* metallicRoughnessTexture = nullptr;
|
|
vkglTF::Texture* normalTexture = nullptr;
|
|
vkglTF::Texture* occlusionTexture = nullptr;
|
|
vkglTF::Texture* emissiveTexture = nullptr;
|
|
|
|
vkglTF::Texture* specularGlossinessTexture;
|
|
vkglTF::Texture* diffuseTexture;
|
|
|
|
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
|
|
|
Material(vks::VulkanDevice* device) : device(device) {};
|
|
void createDescriptorSet(VkDescriptorPool descriptorPool, VkDescriptorSetLayout descriptorSetLayout);
|
|
};
|
|
|
|
/*
|
|
glTF primitive
|
|
*/
|
|
struct Primitive {
|
|
uint32_t firstIndex;
|
|
uint32_t indexCount;
|
|
uint32_t firstVertex;
|
|
uint32_t vertexCount;
|
|
Material& material;
|
|
|
|
struct Dimensions {
|
|
glm::vec3 min = glm::vec3(FLT_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) {};
|
|
};
|
|
|
|
/*
|
|
glTF mesh
|
|
*/
|
|
struct Mesh {
|
|
vks::VulkanDevice* device;
|
|
|
|
std::vector<Primitive*> primitives;
|
|
std::string name;
|
|
|
|
struct UniformBuffer {
|
|
VkBuffer buffer;
|
|
VkDeviceMemory memory;
|
|
VkDescriptorBufferInfo descriptor;
|
|
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
|
void* mapped;
|
|
} uniformBuffer;
|
|
|
|
struct UniformBlock {
|
|
glm::mat4 matrix;
|
|
glm::mat4 jointMatrix[64]{};
|
|
float jointcount{ 0 };
|
|
} uniformBlock;
|
|
|
|
Mesh(vks::VulkanDevice* device, glm::mat4 matrix);
|
|
~Mesh();
|
|
};
|
|
|
|
/*
|
|
glTF skin
|
|
*/
|
|
struct Skin {
|
|
std::string name;
|
|
Node* skeletonRoot = nullptr;
|
|
std::vector<glm::mat4> inverseBindMatrices;
|
|
std::vector<Node*> joints;
|
|
};
|
|
|
|
/*
|
|
glTF node
|
|
*/
|
|
struct Node {
|
|
Node* parent;
|
|
uint32_t index;
|
|
std::vector<Node*> children;
|
|
glm::mat4 matrix;
|
|
std::string name;
|
|
Mesh* mesh;
|
|
Skin* skin;
|
|
int32_t skinIndex = -1;
|
|
glm::vec3 translation{};
|
|
glm::vec3 scale{ 1.0f };
|
|
glm::quat rotation{};
|
|
glm::mat4 localMatrix();
|
|
glm::mat4 getMatrix();
|
|
void update();
|
|
~Node();
|
|
};
|
|
|
|
/*
|
|
glTF animation channel
|
|
*/
|
|
struct AnimationChannel {
|
|
enum PathType { TRANSLATION, ROTATION, SCALE };
|
|
PathType path;
|
|
Node* node;
|
|
uint32_t samplerIndex;
|
|
};
|
|
|
|
/*
|
|
glTF animation sampler
|
|
*/
|
|
struct AnimationSampler {
|
|
enum InterpolationType { LINEAR, STEP, CUBICSPLINE };
|
|
InterpolationType interpolation;
|
|
std::vector<float> inputs;
|
|
std::vector<glm::vec4> outputsVec4;
|
|
};
|
|
|
|
/*
|
|
glTF animation
|
|
*/
|
|
struct Animation {
|
|
std::string name;
|
|
std::vector<AnimationSampler> samplers;
|
|
std::vector<AnimationChannel> channels;
|
|
float start = std::numeric_limits<float>::max();
|
|
float end = std::numeric_limits<float>::min();
|
|
};
|
|
|
|
/*
|
|
glTF default vertex layout with easy Vulkan mapping functions
|
|
*/
|
|
enum class VertexComponent { Position, Normal, UV, Color, Tangent, Joint0, Weight0 };
|
|
|
|
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);
|
|
};
|
|
|
|
enum FileLoadingFlags {
|
|
None = 0x00000000,
|
|
PreTransformVertices = 0x00000001,
|
|
PreMultiplyVertexColors = 0x00000002,
|
|
FlipY = 0x00000004,
|
|
DontLoadImages = 0x00000008
|
|
};
|
|
|
|
enum RenderFlags {
|
|
BindImages = 0x00000001
|
|
};
|
|
|
|
/*
|
|
glTF model loading and rendering class
|
|
*/
|
|
class Model {
|
|
private:
|
|
vkglTF::Texture* getTexture(uint32_t index);
|
|
public:
|
|
vks::VulkanDevice* device;
|
|
VkDescriptorPool descriptorPool;
|
|
|
|
struct Vertices {
|
|
int count;
|
|
VkBuffer buffer;
|
|
VkDeviceMemory memory;
|
|
} vertices;
|
|
struct Indices {
|
|
int count;
|
|
VkBuffer buffer;
|
|
VkDeviceMemory memory;
|
|
} indices;
|
|
|
|
std::vector<Node*> nodes;
|
|
std::vector<Node*> linearNodes;
|
|
|
|
std::vector<Skin*> skins;
|
|
|
|
std::vector<Texture> textures;
|
|
std::vector<Material> materials;
|
|
std::vector<Animation> animations;
|
|
|
|
struct Dimensions {
|
|
glm::vec3 min = glm::vec3(FLT_MAX);
|
|
glm::vec3 max = glm::vec3(-FLT_MAX);
|
|
glm::vec3 size;
|
|
glm::vec3 center;
|
|
float radius;
|
|
} dimensions;
|
|
|
|
bool metallicRoughnessWorkflow = true;
|
|
bool buffersBound = false;
|
|
std::string path;
|
|
|
|
Model() {};
|
|
~Model();
|
|
void loadNode(vkglTF::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 loadImages(tinygltf::Model& gltfModel, vks::VulkanDevice* device, VkQueue transferQueue);
|
|
void loadMaterials(tinygltf::Model& gltfModel);
|
|
void loadAnimations(tinygltf::Model& gltfModel);
|
|
void loadFromFile(std::string filename, vks::VulkanDevice* device, VkQueue transferQueue, uint32_t fileLoadingFlags = vkglTF::FileLoadingFlags::None, float scale = 1.0f);
|
|
void bindBuffers(VkCommandBuffer commandBuffer);
|
|
void drawNode(Node* node, VkCommandBuffer commandBuffer, uint32_t renderFlags = 0, VkPipelineLayout pipelineLayout = VK_NULL_HANDLE, uint32_t bindImageSet = 1);
|
|
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 updateAnimation(uint32_t index, float time);
|
|
Node* findNode(Node* parent, uint32_t index);
|
|
Node* nodeFromIndex(uint32_t index);
|
|
void prepareNodeDescriptor(vkglTF::Node* node, VkDescriptorSetLayout descriptorSetLayout);
|
|
};
|
|
} |