Extracted vertex into separate class with easy component to Vulkan vertex attribute mappings
Load vertex colors if present Added flag to pre-transform vertices
This commit is contained in:
parent
424de5fab3
commit
107aa35b9e
2 changed files with 86 additions and 18 deletions
|
|
@ -332,6 +332,8 @@ namespace vkglTF
|
||||||
struct Primitive {
|
struct Primitive {
|
||||||
uint32_t firstIndex;
|
uint32_t firstIndex;
|
||||||
uint32_t indexCount;
|
uint32_t indexCount;
|
||||||
|
uint32_t firstVertex;
|
||||||
|
uint32_t vertexCount;
|
||||||
Material &material;
|
Material &material;
|
||||||
|
|
||||||
struct Dimensions {
|
struct Dimensions {
|
||||||
|
|
@ -503,6 +505,44 @@ namespace vkglTF
|
||||||
float end = std::numeric_limits<float>::min();
|
float end = std::numeric_limits<float>::min();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
glTF default vertex layout with easy Vulkan mapping functions
|
||||||
|
*/
|
||||||
|
enum class VertexComponent { Position, Normal, UV, Color, Joint0, Weight0 };
|
||||||
|
|
||||||
|
struct Vertex {
|
||||||
|
glm::vec3 pos;
|
||||||
|
glm::vec3 normal;
|
||||||
|
glm::vec2 uv;
|
||||||
|
glm::vec4 color;
|
||||||
|
glm::vec4 joint0;
|
||||||
|
glm::vec4 weight0;
|
||||||
|
static VkVertexInputBindingDescription inputBindingDescription(uint32_t binding) {
|
||||||
|
return VkVertexInputBindingDescription({ binding, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX });
|
||||||
|
}
|
||||||
|
static VkVertexInputAttributeDescription inputAttributeDescription(uint32_t binding, uint32_t location, VertexComponent component) {
|
||||||
|
switch (component) {
|
||||||
|
case VertexComponent::Position:
|
||||||
|
return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos) });
|
||||||
|
case VertexComponent::Normal:
|
||||||
|
return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal) });
|
||||||
|
case VertexComponent::UV:
|
||||||
|
return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv) });
|
||||||
|
case VertexComponent::Color:
|
||||||
|
return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, color) });
|
||||||
|
case VertexComponent::Joint0:
|
||||||
|
return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, joint0) });
|
||||||
|
case VertexComponent::Weight0:
|
||||||
|
return VkVertexInputAttributeDescription({ location, binding, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, weight0) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum FileLoadingFlags {
|
||||||
|
None = 0,
|
||||||
|
PreTransformVertices = 1,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
glTF model loading and rendering class
|
glTF model loading and rendering class
|
||||||
*/
|
*/
|
||||||
|
|
@ -512,14 +552,6 @@ namespace vkglTF
|
||||||
VkDescriptorPool descriptorPool;
|
VkDescriptorPool descriptorPool;
|
||||||
VkDescriptorSetLayout descriptorSetLayout;
|
VkDescriptorSetLayout descriptorSetLayout;
|
||||||
|
|
||||||
struct Vertex {
|
|
||||||
glm::vec3 pos;
|
|
||||||
glm::vec3 normal;
|
|
||||||
glm::vec2 uv;
|
|
||||||
glm::vec4 joint0;
|
|
||||||
glm::vec4 weight0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Vertices {
|
struct Vertices {
|
||||||
VkBuffer buffer;
|
VkBuffer buffer;
|
||||||
VkDeviceMemory memory;
|
VkDeviceMemory memory;
|
||||||
|
|
@ -619,6 +651,7 @@ namespace vkglTF
|
||||||
uint32_t indexStart = static_cast<uint32_t>(indexBuffer.size());
|
uint32_t indexStart = static_cast<uint32_t>(indexBuffer.size());
|
||||||
uint32_t vertexStart = static_cast<uint32_t>(vertexBuffer.size());
|
uint32_t vertexStart = static_cast<uint32_t>(vertexBuffer.size());
|
||||||
uint32_t indexCount = 0;
|
uint32_t indexCount = 0;
|
||||||
|
uint32_t vertexCount = 0;
|
||||||
glm::vec3 posMin{};
|
glm::vec3 posMin{};
|
||||||
glm::vec3 posMax{};
|
glm::vec3 posMax{};
|
||||||
bool hasSkin = false;
|
bool hasSkin = false;
|
||||||
|
|
@ -627,6 +660,8 @@ namespace vkglTF
|
||||||
const float *bufferPos = nullptr;
|
const float *bufferPos = nullptr;
|
||||||
const float *bufferNormals = nullptr;
|
const float *bufferNormals = nullptr;
|
||||||
const float *bufferTexCoords = nullptr;
|
const float *bufferTexCoords = nullptr;
|
||||||
|
const float* bufferColors = nullptr;
|
||||||
|
uint32_t numColorComponents;
|
||||||
const uint16_t *bufferJoints = nullptr;
|
const uint16_t *bufferJoints = nullptr;
|
||||||
const float *bufferWeights = nullptr;
|
const float *bufferWeights = nullptr;
|
||||||
|
|
||||||
|
|
@ -650,6 +685,13 @@ namespace vkglTF
|
||||||
const tinygltf::BufferView &uvView = model.bufferViews[uvAccessor.bufferView];
|
const tinygltf::BufferView &uvView = model.bufferViews[uvAccessor.bufferView];
|
||||||
bufferTexCoords = reinterpret_cast<const float *>(&(model.buffers[uvView.buffer].data[uvAccessor.byteOffset + uvView.byteOffset]));
|
bufferTexCoords = reinterpret_cast<const float *>(&(model.buffers[uvView.buffer].data[uvAccessor.byteOffset + uvView.byteOffset]));
|
||||||
}
|
}
|
||||||
|
if (primitive.attributes.find("COLOR_0") != primitive.attributes.end()) {
|
||||||
|
const tinygltf::Accessor& colorAccessor = model.accessors[primitive.attributes.find("COLOR_0")->second];
|
||||||
|
const tinygltf::BufferView& colorView = model.bufferViews[colorAccessor.bufferView];
|
||||||
|
// Color buffer are either of type vec3 or vec4
|
||||||
|
numColorComponents = colorAccessor.type == TINYGLTF_PARAMETER_TYPE_FLOAT_VEC3 ? 3 : 4;
|
||||||
|
bufferColors = reinterpret_cast<const float*>(&(model.buffers[colorView.buffer].data[colorAccessor.byteOffset + colorView.byteOffset]));
|
||||||
|
}
|
||||||
|
|
||||||
// Skinning
|
// Skinning
|
||||||
// Joints
|
// Joints
|
||||||
|
|
@ -667,12 +709,24 @@ namespace vkglTF
|
||||||
|
|
||||||
hasSkin = (bufferJoints && bufferWeights);
|
hasSkin = (bufferJoints && bufferWeights);
|
||||||
|
|
||||||
|
vertexCount = static_cast<uint32_t>(posAccessor.count);
|
||||||
|
|
||||||
for (size_t v = 0; v < posAccessor.count; v++) {
|
for (size_t v = 0; v < posAccessor.count; v++) {
|
||||||
Vertex vert{};
|
Vertex vert{};
|
||||||
vert.pos = glm::vec4(glm::make_vec3(&bufferPos[v * 3]), 1.0f);
|
vert.pos = glm::vec4(glm::make_vec3(&bufferPos[v * 3]), 1.0f);
|
||||||
vert.normal = glm::normalize(glm::vec3(bufferNormals ? glm::make_vec3(&bufferNormals[v * 3]) : glm::vec3(0.0f)));
|
vert.normal = glm::normalize(glm::vec3(bufferNormals ? glm::make_vec3(&bufferNormals[v * 3]) : glm::vec3(0.0f)));
|
||||||
vert.uv = bufferTexCoords ? glm::make_vec2(&bufferTexCoords[v * 2]) : glm::vec3(0.0f);
|
vert.uv = bufferTexCoords ? glm::make_vec2(&bufferTexCoords[v * 2]) : glm::vec3(0.0f);
|
||||||
|
if (bufferColors) {
|
||||||
|
switch (numColorComponents) {
|
||||||
|
case 3:
|
||||||
|
vert.color = glm::vec4(glm::make_vec3(&bufferColors[v * 3]), 1.0f);
|
||||||
|
case 4:
|
||||||
|
vert.color = glm::make_vec4(&bufferColors[v * 4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vert.color = glm::vec4(1.0f);
|
||||||
|
}
|
||||||
vert.joint0 = hasSkin ? glm::vec4(glm::make_vec4(&bufferJoints[v * 4])) : glm::vec4(0.0f);
|
vert.joint0 = hasSkin ? glm::vec4(glm::make_vec4(&bufferJoints[v * 4])) : glm::vec4(0.0f);
|
||||||
vert.weight0 = hasSkin ? glm::make_vec4(&bufferWeights[v * 4]) : glm::vec4(0.0f);
|
vert.weight0 = hasSkin ? glm::make_vec4(&bufferWeights[v * 4]) : glm::vec4(0.0f);
|
||||||
vertexBuffer.push_back(vert);
|
vertexBuffer.push_back(vert);
|
||||||
|
|
@ -717,6 +771,8 @@ namespace vkglTF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Primitive *newPrimitive = new Primitive(indexStart, indexCount, materials[primitive.material]);
|
Primitive *newPrimitive = new Primitive(indexStart, indexCount, materials[primitive.material]);
|
||||||
|
newPrimitive->firstVertex = vertexStart;
|
||||||
|
newPrimitive->vertexCount = vertexCount;
|
||||||
newPrimitive->setDimensions(posMin, posMax);
|
newPrimitive->setDimensions(posMin, posMax);
|
||||||
newMesh->primitives.push_back(newPrimitive);
|
newMesh->primitives.push_back(newPrimitive);
|
||||||
}
|
}
|
||||||
|
|
@ -929,7 +985,7 @@ namespace vkglTF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = vkglTF::FileLoadingFlags::None, float scale = 1.0f)
|
||||||
{
|
{
|
||||||
tinygltf::Model gltfModel;
|
tinygltf::Model gltfModel;
|
||||||
tinygltf::TinyGLTF gltfContext;
|
tinygltf::TinyGLTF gltfContext;
|
||||||
|
|
@ -984,6 +1040,20 @@ namespace vkglTF
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pre-transform all vertices by the node matrix hierarchy if requested
|
||||||
|
if (fileLoadingFlags & FileLoadingFlags::PreTransformVertices) {
|
||||||
|
for (Node* node : linearNodes) {
|
||||||
|
const glm::mat4 localMatrix = node->getMatrix();
|
||||||
|
if (node->mesh) {
|
||||||
|
for (Primitive* primitive : node->mesh->primitives) {
|
||||||
|
for (uint32_t i = 0; i < primitive->vertexCount; i++) {
|
||||||
|
vertexBuffer[primitive->firstVertex + i].pos = glm::vec3(localMatrix * glm::vec4(vertexBuffer[primitive->firstVertex + i].pos, 1.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto extension : gltfModel.extensionsUsed) {
|
for (auto extension : gltfModel.extensionsUsed) {
|
||||||
if (extension == "KHR_materials_pbrSpecularGlossiness") {
|
if (extension == "KHR_materials_pbrSpecularGlossiness") {
|
||||||
std::cout << "Required extension: " << extension;
|
std::cout << "Required extension: " << extension;
|
||||||
|
|
|
||||||
|
|
@ -221,17 +221,15 @@ public:
|
||||||
VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast<uint32_t>(dynamicStateEnables.size()), 0);
|
VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(), static_cast<uint32_t>(dynamicStateEnables.size()), 0);
|
||||||
|
|
||||||
// Vertex bindings and attributes
|
// Vertex bindings and attributes
|
||||||
const std::vector<VkVertexInputBindingDescription> vertexInputBindings = {
|
VkVertexInputBindingDescription vertexInputBinding = vkglTF::Vertex::inputBindingDescription(0);
|
||||||
vks::initializers::vertexInputBindingDescription(0, sizeof(vkglTF::Model::Vertex), VK_VERTEX_INPUT_RATE_VERTEX),
|
|
||||||
};
|
|
||||||
const std::vector<VkVertexInputAttributeDescription> vertexInputAttributes = {
|
const std::vector<VkVertexInputAttributeDescription> vertexInputAttributes = {
|
||||||
vks::initializers::vertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0), // Location 0: Position
|
vkglTF::Vertex::inputAttributeDescription(0, 0, vkglTF::VertexComponent::Position),
|
||||||
vks::initializers::vertexInputAttributeDescription(0, 1, VK_FORMAT_R32G32B32_SFLOAT, sizeof(float) * 3), // Location 1: Normal
|
vkglTF::Vertex::inputAttributeDescription(0, 1, vkglTF::VertexComponent::Normal),
|
||||||
vks::initializers::vertexInputAttributeDescription(0, 2, VK_FORMAT_R32G32_SFLOAT, sizeof(float) * 6), // Location 2: UV
|
vkglTF::Vertex::inputAttributeDescription(0, 2, vkglTF::VertexComponent::UV)
|
||||||
};
|
};
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo();
|
VkPipelineVertexInputStateCreateInfo vertexInputState = vks::initializers::pipelineVertexInputStateCreateInfo();
|
||||||
vertexInputState.vertexBindingDescriptionCount = static_cast<uint32_t>(vertexInputBindings.size());
|
vertexInputState.vertexBindingDescriptionCount = 1;
|
||||||
vertexInputState.pVertexBindingDescriptions = vertexInputBindings.data();
|
vertexInputState.pVertexBindingDescriptions = &vertexInputBinding;
|
||||||
vertexInputState.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertexInputAttributes.size());
|
vertexInputState.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertexInputAttributes.size());
|
||||||
vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data();
|
vertexInputState.pVertexAttributeDescriptions = vertexInputAttributes.data();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue