vertex data no longer hard coded

This commit is contained in:
tylermurphy534 2022-09-25 12:07:49 -04:00
parent f81d611f0e
commit 7c1dfec943
15 changed files with 132 additions and 120 deletions

View file

@ -2,6 +2,7 @@
#include <cassert>
#include <stdexcept>
#include <iostream>
namespace xe {

View file

@ -35,16 +35,17 @@ std::shared_ptr<Model> Engine::loadModelFromFile(const std::string &filename) {
return Model::createModelFromFile(xeDevice, filename);
}
std::shared_ptr<Model> Engine::loadModelFromData(std::vector<Model::Vertex> vertices, std::vector<uint32_t> indices) {
std::shared_ptr<Model> Engine::loadModelFromData(std::vector<float> vertexData, uint32_t vertexSize, std::vector<uint32_t> indices) {
Model::Builder builder{};
builder.vertices = vertices;
builder.vertexData = vertexData;
builder.vertexSize = vertexSize;
if(indices.size() > 0) {
builder.indices = indices;
}
return std::make_shared<Model>(xeDevice, builder);
}
std::shared_ptr<Image> Engine::loadImage(const std::string &filename) {
std::shared_ptr<Image> Engine::loadImageFromFile(const std::string &filename) {
return std::make_shared<Image>(xeDevice, filename);
}

View file

@ -26,8 +26,8 @@ class Engine {
Camera& getCamera() {return xeCamera;}
std::shared_ptr<Model> loadModelFromFile(const std::string &filename);
std::shared_ptr<Model> loadModelFromData(std::vector<Model::Vertex> vertices, std::vector<uint32_t> indices);
std::shared_ptr<Image> loadImage(const std::string &filename);
std::shared_ptr<Model> loadModelFromData(std::vector<float> vertexData, uint32_t vertexSize, std::vector<uint32_t> indices);
std::shared_ptr<Image> loadImageFromFile(const std::string &filename);
bool beginFrame() { return xeRenderer.beginFrame(); }
void endFrame() { xeRenderer.endFrame(); }

View file

@ -1,5 +1,4 @@
#include "xe_model.hpp"
#include "xe_utils.hpp"
#define TINYOBJLOADER_IMPLEMENTATION
#include "xe_obj_loader.hpp"
@ -10,22 +9,12 @@
#include <cassert>
#include <cstring>
#include <unordered_map>
namespace std {
template<>
struct hash<xe::Model::Vertex> {
size_t operator()(xe::Model::Vertex const &vertex) const {
size_t seed = 0;
xe::hashCombine(seed, vertex.position, vertex.normal, vertex.uv);
return seed;
}
};
}
#include <iostream>
namespace xe {
Model::Model(Device &device, const Model::Builder &builder) : xeDevice{device} {
createVertexBuffers(builder.vertices);
createVertexBuffers(builder.vertexData, builder.vertexSize);
createIndexBuffers(builder.indices);
}
@ -37,11 +26,10 @@ std::unique_ptr<Model> Model::createModelFromFile(Device &device, const std::str
return std::make_unique<Model>(device, builder);
}
void Model::createVertexBuffers(const std::vector<Vertex> &vertices) {
vertexCount = static_cast<uint32_t>(vertices.size());
void Model::createVertexBuffers(const std::vector<float> &vertexData, uint32_t vertexSize) {
vertexCount = static_cast<uint32_t>(vertexData.size()) / (vertexSize / 4);
assert(vertexCount >= 3 && "Vertex count must be atleast 3");
VkDeviceSize bufferSize = sizeof(vertices[0]) * vertexCount;
uint32_t vertexSize = sizeof(vertices[0]);
VkDeviceSize bufferSize = vertexData.size() * 4;
Buffer stagingBuffer {
xeDevice,
@ -52,7 +40,7 @@ void Model::createVertexBuffers(const std::vector<Vertex> &vertices) {
};
stagingBuffer.map();
stagingBuffer.writeToBuffer((void *)vertices.data());
stagingBuffer.writeToBuffer((void *)vertexData.data());
vertexBuffer = std::make_unique<Buffer>(
xeDevice,
@ -65,16 +53,16 @@ void Model::createVertexBuffers(const std::vector<Vertex> &vertices) {
xeDevice.copyBuffer(stagingBuffer.getBuffer(), vertexBuffer->getBuffer(), bufferSize);
}
void Model::createIndexBuffers(const std::vector<uint32_t> &indices) {
indexCount = static_cast<uint32_t>(indices.size());
void Model::createIndexBuffers(const std::vector<uint32_t> &indexData) {
indexCount = static_cast<uint32_t>(indexData.size());
hasIndexBuffer = indexCount > 0;
if (!hasIndexBuffer) {
return;
}
VkDeviceSize bufferSize = sizeof(indices[0]) * indexCount;
uint32_t indexSize = sizeof(indices[0]);
VkDeviceSize bufferSize = sizeof(indexData[0]) * indexCount;
uint32_t indexSize = sizeof(indexData[0]);
Buffer stagingBuffer {
xeDevice,
@ -85,7 +73,7 @@ void Model::createIndexBuffers(const std::vector<uint32_t> &indices) {
};
stagingBuffer.map();
stagingBuffer.writeToBuffer((void *)indices.data());
stagingBuffer.writeToBuffer((void *)indexData.data());
indexBuffer = std::make_unique<Buffer>(
xeDevice,
@ -116,25 +104,6 @@ void Model::draw(VkCommandBuffer commandBuffer) {
}
}
std::vector<VkVertexInputBindingDescription> Model::Vertex::getBindingDescriptions() {
std::vector<VkVertexInputBindingDescription> bindingDescriptions(1);
bindingDescriptions[0].binding = 0;
bindingDescriptions[0].stride = sizeof(Vertex);
bindingDescriptions[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
return bindingDescriptions;
}
std::vector<VkVertexInputAttributeDescription> Model::Vertex::getAttributeDescriptions() {
std::vector<VkVertexInputAttributeDescription> attributeDescptions{};
attributeDescptions.push_back({0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, position)});
attributeDescptions.push_back({1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color)});
attributeDescptions.push_back({2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal)});
attributeDescptions.push_back({3, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)});
return attributeDescptions;
}
void Model::Builder::loadModel(const std::string &filepath) {
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
@ -144,50 +113,52 @@ void Model::Builder::loadModel(const std::string &filepath) {
throw std::runtime_error(warn + err);
}
vertices.clear();
vertexData.clear();
indices.clear();
vertexSize = 0;
bool vertex, color, normal, uvs;
std::unordered_map<Vertex, uint32_t> uniqueVertices{};
for (const auto &shape : shapes) {
for (const auto &index : shape.mesh.indices) {
Vertex vertex{};
if(index.vertex_index >= 0) {
vertex.position = {
attrib.vertices[3 * index.vertex_index + 0],
attrib.vertices[3 * index.vertex_index + 1],
attrib.vertices[3 * index.vertex_index + 2]
};
vertexData.push_back(attrib.vertices[3 * index.vertex_index + 0]);
vertexData.push_back(attrib.vertices[3 * index.vertex_index + 1]);
vertexData.push_back(attrib.vertices[3 * index.vertex_index + 2]);
vertex = true;
vertex.color = {
attrib.colors[3 * index.vertex_index + 0],
attrib.colors[3 * index.vertex_index + 1],
attrib.colors[3 * index.vertex_index + 2]
};
vertexData.push_back(attrib.colors[3 * index.vertex_index + 0]);
vertexData.push_back(attrib.colors[3 * index.vertex_index + 1]);
vertexData.push_back(attrib.colors[3 * index.vertex_index + 2]);
color = true;
}
if(index.normal_index >= 0) {
vertex.normal = {
attrib.normals[3 * index.normal_index + 0],
attrib.normals[3 * index.normal_index + 1],
attrib.normals[3 * index.normal_index + 2]
};
vertexData.push_back(attrib.normals[3 * index.normal_index + 0]);
vertexData.push_back(attrib.normals[3 * index.normal_index + 1]);
vertexData.push_back(attrib.normals[3 * index.normal_index + 2]);
normal = true;
}
if(index.texcoord_index >= 0) {
vertex.uv = {
attrib.texcoords[2 * index.texcoord_index + 0],
attrib.texcoords[2 * index.texcoord_index + 1],
};
vertexData.push_back(attrib.texcoords[2 * index.texcoord_index + 0]);
vertexData.push_back(attrib.texcoords[2 * index.texcoord_index + 1]);
uvs = true;
}
if (uniqueVertices.count(vertex) == 0) {
uniqueVertices[vertex] = static_cast<uint32_t>(vertices.size());
vertices.push_back(vertex);
}
indices.push_back(uniqueVertices[vertex]);
}
}
if(vertex)
vertexSize += 12;
if(color)
vertexSize += 12;
if(normal)
vertexSize += 12;
if(uvs)
vertexSize += 8;
}
}

View file

@ -14,22 +14,10 @@ namespace xe {
class Model {
public:
struct Vertex {
glm::vec3 position;
glm::vec3 color;
glm::vec3 normal;
glm::vec2 uv;
static std::vector<VkVertexInputBindingDescription> getBindingDescriptions();
static std::vector<VkVertexInputAttributeDescription> getAttributeDescriptions();
bool operator==(const Vertex &other) const {
return position == other.position && color == other.color && normal == other.normal && uv == other.uv;
}
};
struct Builder {
std::vector<Vertex> vertices{};
std::vector<float> vertexData{};
uint32_t vertexSize;
std::vector<uint32_t> indices{};
void loadModel(const std::string &filepath);
@ -47,8 +35,8 @@ class Model {
void draw(VkCommandBuffer commandBuffer);
private:
void createVertexBuffers(const std::vector<Vertex> &vertices);
void createIndexBuffers(const std::vector<uint32_t> &indices);
void createVertexBuffers(const std::vector<float> &vertexData, uint32_t vertexSize);
void createIndexBuffers(const std::vector<uint32_t> &indexData);
Device &xeDevice;

View file

@ -16,9 +16,11 @@ namespace xe {
Device &device,
const std::string& vertFilepath,
const std::string& fragFilepath,
const PipelineConfigInfo& configInfo)
: xeDevice{device} {
createGraphicsPipeline(vertFilepath, fragFilepath, configInfo);
const PipelineConfigInfo& configInfo,
std::vector<VkVertexInputAttributeDescription> &attributeDescptions,
uint32_t vertexSize
) : xeDevice{device} {
createGraphicsPipeline(vertFilepath, fragFilepath, configInfo, attributeDescptions, vertexSize);
}
Pipeline::~Pipeline() {
@ -48,7 +50,10 @@ namespace xe {
void Pipeline::createGraphicsPipeline(
const std::string& vertFilePath,
const std::string& fragFilepath,
const PipelineConfigInfo& configInfo) {
const PipelineConfigInfo& configInfo,
std::vector<VkVertexInputAttributeDescription> &attributeDescptions,
uint32_t vertexSize
) {
assert(
configInfo.pipelineLayout != VK_NULL_HANDLE &&
@ -78,8 +83,13 @@ namespace xe {
shaderStages[1].pNext = nullptr;
shaderStages[1].pSpecializationInfo = nullptr;
auto bindingDescriptions = Model::Vertex::getBindingDescriptions();
auto attributeDescptions = Model::Vertex::getAttributeDescriptions();
VkVertexInputBindingDescription bindingDescription;
bindingDescription.binding = 0;
bindingDescription.stride = vertexSize;
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
std::vector<VkVertexInputBindingDescription> bindingDescriptions{bindingDescription};
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescptions.size());

View file

@ -33,7 +33,10 @@ class Pipeline {
Device &device,
const std::string& vertFilepath,
const std::string& fragFilepath,
const PipelineConfigInfo& configInfo);
const PipelineConfigInfo& configInfo,
std::vector<VkVertexInputAttributeDescription> &attributeDescptions,
uint32_t vertexSize
);
~Pipeline();
Pipeline(const Pipeline&) = delete;
@ -48,7 +51,10 @@ class Pipeline {
void createGraphicsPipeline(
const std::string& vertFilePath,
const std::string& fragFilepath,
const PipelineConfigInfo& configInfo);
const PipelineConfigInfo& configInfo,
std::vector<VkVertexInputAttributeDescription> &attributeDescptions,
uint32_t vertexSize
);
void createShaderModule(const std::vector<char>& code, VkShaderModule* shaderModule);

View file

@ -23,7 +23,9 @@ RenderSystem::RenderSystem(
std::map<uint32_t, uint32_t> uniformBindings,
std::map<uint32_t, Image*> imageBindings,
uint32_t pushCunstantDataSize,
bool cullingEnabled
bool cullingEnabled,
std::vector<VkVertexInputAttributeDescription> attributeDescptions,
uint32_t vertexSize
) : xeDevice{xeEngine.xeDevice},
xeRenderer{xeEngine.xeRenderer},
xeDescriptorPool{xeEngine.xeDescriptorPool},
@ -35,10 +37,9 @@ RenderSystem::RenderSystem(
createUniformBuffers();
createDescriptorSets();
createPipelineLayout();
createPipeline(xeRenderer.getSwapChainRenderPass(), vert, frag, cullingEnabled);
createPipeline(xeRenderer.getSwapChainRenderPass(), vert, frag, cullingEnabled, attributeDescptions, vertexSize);
}
RenderSystem::~RenderSystem() {
vkDestroyPipelineLayout(xeDevice.device(), pipelineLayout, nullptr);
vkDestroySampler(xeDevice.device(), textureSampler, nullptr);
@ -164,7 +165,7 @@ void RenderSystem::createPipelineLayout() {
}
void RenderSystem::createPipeline(VkRenderPass renderPass, std::string vert, std::string frag, bool cullingEnabled) {
void RenderSystem::createPipeline(VkRenderPass renderPass, std::string vert, std::string frag, bool cullingEnabled, std::vector<VkVertexInputAttributeDescription> attributeDescptions, uint32_t vertexSize) {
assert(pipelineLayout != nullptr && "Cannot create pipeline before pipeline layout");
PipelineConfigInfo pipelineConfig{};
@ -178,7 +179,9 @@ void RenderSystem::createPipeline(VkRenderPass renderPass, std::string vert, std
xeDevice,
vert,
frag,
pipelineConfig
pipelineConfig,
attributeDescptions,
vertexSize
);
}

View file

@ -11,6 +11,7 @@
#include <memory>
#include <map>
#include <vector>
namespace xe {
@ -21,6 +22,21 @@ class RenderSystem {
public:
Builder(Engine &xeEngine, std::string vert, std::string frag) : xeEngine{xeEngine}, vert{vert}, frag{frag} {}
Builder& addVertexBinding(uint32_t binding, uint32_t dimension, uint32_t offset){
if(dimension == 1)
attributeDescptions.push_back({binding, 0, VK_FORMAT_R32_SFLOAT, offset});
if(dimension == 2)
attributeDescptions.push_back({binding, 0, VK_FORMAT_R32G32_SFLOAT, offset});
if(dimension == 3)
attributeDescptions.push_back({binding, 0, VK_FORMAT_R32G32B32_SFLOAT, offset});
return *this;
}
Builder& setVertexSize(uint32_t size) {
vertexSize = size;
return *this;
}
Builder& addPushConstant(uint32_t size) {
pushCunstantDataSize = size;
return *this;
@ -42,7 +58,7 @@ class RenderSystem {
}
std::unique_ptr<RenderSystem> build() {
return std::make_unique<RenderSystem>(xeEngine, std::move(vert), std::move(frag), std::move(uniformBindings), std::move(imageBindings), std::move(pushCunstantDataSize), std::move(cullingEnabled));
return std::make_unique<RenderSystem>(xeEngine, std::move(vert), std::move(frag), std::move(uniformBindings), std::move(imageBindings), std::move(pushCunstantDataSize), std::move(cullingEnabled), std::move(attributeDescptions), std::move(vertexSize));
}
private:
@ -51,6 +67,9 @@ class RenderSystem {
std::map<uint32_t, Image*> imageBindings{};
uint32_t pushCunstantDataSize{0};
std::vector<VkVertexInputAttributeDescription> attributeDescptions{};
uint32_t vertexSize;
std::string vert;
std::string frag;
@ -66,7 +85,9 @@ class RenderSystem {
std::map<uint32_t, uint32_t> uniformBindings,
std::map<uint32_t, Image*> imageBindings,
uint32_t pushCunstantDataSize,
bool cullingEnabled
bool cullingEnabled,
std::vector<VkVertexInputAttributeDescription> attributeDescptions,
uint32_t vertexSize
);
~RenderSystem();
@ -89,7 +110,7 @@ class RenderSystem {
void createDescriptorSets();
void updateDescriptorSet(int frameIndex, bool allocate);
void createPipelineLayout();
void createPipeline(VkRenderPass renderPass, std::string vert, std::string frag, bool cullingEnabled);
void createPipeline(VkRenderPass renderPass, std::string vert, std::string frag, bool cullingEnabled, std::vector<VkVertexInputAttributeDescription> attributeDescptions, uint32_t vertexSize);
bool boundPipeline{false};
bool boundDescriptor{false};

View file

@ -1,11 +0,0 @@
#pragma once
namespace xe {
template <typename T, typename... Rest>
void hashCombine(std::size_t& seed, const T& v, const Rest&... rest) {
seed ^= std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
(hashCombine(seed, rest), ...);
};
}

View file

@ -10,6 +10,11 @@ layout (binding = 0) uniform GlobalUbo {
vec3 directionToLight;
} ubo;
layout (binding = 2) uniform Deez {
mat4 projectionViewMatrix;
vec3 directionToLight;
} deez;
layout (binding = 1) uniform sampler2D texSampler;
layout(push_constant) uniform Push {

View file

@ -13,6 +13,11 @@ layout (binding = 0) uniform GlobalUbo {
vec3 directionToLight;
} ubo;
layout (binding = 2) uniform Deez {
mat4 projectionViewMatrix;
vec3 directionToLight;
} deez;
layout (push_constant) uniform Push {
mat4 modelMatrix;
mat4 normalMatrix;

View file

@ -27,8 +27,8 @@ FirstApp::~FirstApp() {}
void FirstApp::run() {
std::shared_ptr<xe::Image> image = xeEngine.loadImage("res/image/texture.png");
std::shared_ptr<xe::Image> image2 = xeEngine.loadImage("res/image/ltt.");
std::shared_ptr<xe::Image> image = xeEngine.loadImageFromFile("res/image/texture.png");
std::shared_ptr<xe::Image> image2 = xeEngine.loadImageFromFile("res/image/scaly.png");
SimpleRenderer renderer{xeEngine, image.get()};

View file

@ -7,6 +7,11 @@ namespace app {
SimpleRenderer::SimpleRenderer(xe::Engine &xeEngine, xe::Image *xeImage) {
xeRenderSystem = xe::RenderSystem::Builder(xeEngine, "res/shaders/simple_shader.vert.spv", "res/shaders/simple_shader.frag.spv")
.addVertexBinding(0, 3, 0)
.addVertexBinding(1, 3, 12)
.addVertexBinding(2, 3, 24)
.addVertexBinding(3, 2, 36)
.setVertexSize(sizeof(Vertex))
.addPushConstant(sizeof(PushConstant))
.addUniformBinding(0, sizeof(UniformBuffer))
.addTextureBinding(1, xeImage)

View file

@ -15,6 +15,13 @@ struct PushConstant {
alignas(16) glm::mat4 normalMatrix{1.f};
};
struct Vertex {
glm::vec3 position;
glm::vec3 color;
glm::vec3 normal;
glm::vec2 uv;
};
class SimpleRenderer {
public: