Archived
1
Fork 0

Add model loading

This commit is contained in:
Joshua Goins 2018-10-16 08:49:25 -04:00
parent 0568c6e5d2
commit 4378a90f74
10 changed files with 1737 additions and 70 deletions

View file

@ -16,7 +16,7 @@ add_executable(Graph
src/main.cpp
src/renderer.cpp
src/worldpass.cpp)
target_link_libraries(Graph PUBLIC SDL2::SDL2 SDL2::SDL2main ${Vulkan_LIBRARY})
target_link_libraries(Graph PUBLIC SDL2::SDL2 SDL2::SDL2main ${Vulkan_LIBRARY} assimp)
target_include_directories(Graph PUBLIC include ${Vulkan_INCLUDE_DIRS})
macro(compile_shader src)
@ -34,3 +34,5 @@ compile_shader(triangle.frag)
add_custom_target(BuildShaders DEPENDS ${SPV_FILES})
add_dependencies(Graph BuildShaders)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/data/suzanne.obj ${CMAKE_CURRENT_SOURCE_DIR}/build/suzanne.obj COPYONLY)

1512
data/suzanne.obj Normal file

File diff suppressed because it is too large Load diff

22
include/mesh.h Normal file
View file

@ -0,0 +1,22 @@
#pragma once
#include <vector>
#include <cstdint>
#include <glm/glm.hpp>
#include <vulkan/vulkan.h>
struct Vertex {
glm::vec3 position;
};
class Mesh {
public:
std::vector<Vertex> vertices;
std::vector<uint32_t> indices;
VkBuffer vertexBuffer = nullptr;
VkDeviceMemory vertexMemory = nullptr;
VkBuffer indexBuffer = nullptr;
VkDeviceMemory indexMemory = nullptr;
};

View file

@ -22,18 +22,25 @@ struct RenderTarget {
VkFence* fences = nullptr;
};
class World;
class Mesh;
class Renderer {
public:
Renderer();
~Renderer();
void render(RenderTarget* target);
void render(World& world, RenderTarget* target);
RenderTarget* createSurfaceRenderTarget(VkSurfaceKHR surface, RenderTarget* oldRenderTarget = nullptr);
void destroyRenderTarget(RenderTarget* target);
VkShaderModule createShader(const char* path);
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
void fillMeshBuffers(Mesh* mesh);
VkInstance getInstance() const {
return instance_;
}

10
include/world.h Normal file
View file

@ -0,0 +1,10 @@
#pragma once
#include <vector>
class Mesh;
class World {
public:
std::vector<Mesh*> meshes;
};

View file

@ -3,13 +3,14 @@
#include <vulkan/vulkan.h>
class Renderer;
class World;
class WorldPass {
public:
WorldPass(Renderer& renderer);
~WorldPass();
void render(VkCommandBuffer commandBuffer);
void render(World& world, VkCommandBuffer commandBuffer);
private:
void createPipeline();

View file

@ -1,11 +1,7 @@
#version 460 core
vec2 positions[3] = vec2[](
vec2(0.0, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, 0.5)
);
layout(location = 0) in vec3 inPosition;
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
gl_Position = vec4(inPosition, 1.0);
}

View file

@ -2,8 +2,14 @@
#include <SDL_vulkan.h>
#include <iostream>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include "renderer.h"
#include "platform.h"
#include "world.h"
#include "mesh.h"
SDL_Window* window = nullptr;
@ -33,6 +39,30 @@ int main(int, char*[]) {
RenderTarget* target = renderer->createSurfaceRenderTarget(surface);
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile("suzanne.obj", aiProcess_Triangulate);
aiMesh* m = scene->mMeshes[0];
Mesh* mesh = new Mesh();
for(unsigned int i = 0; i < m->mNumVertices; i++) {
Vertex vertex;
vertex.position = glm::vec3(m->mVertices[i].x, m->mVertices[i].y, m->mVertices[i].z);
mesh->vertices.push_back(vertex);
}
for(unsigned int i = 0; i < m->mNumFaces; i++) {
aiFace face = m->mFaces[i];
for(unsigned int j = 0; j < face.mNumIndices; j++)
mesh->indices.push_back(face.mIndices[j]);
}
renderer->fillMeshBuffers(mesh);
World world;
world.meshes.push_back(mesh);
bool running = true;
while(running) {
SDL_Event event = {};
@ -46,7 +76,7 @@ int main(int, char*[]) {
}
}
renderer->render(target);
renderer->render(world, target);
}
renderer->destroyRenderTarget(target);

View file

@ -8,6 +8,7 @@
#include <cmath>
#include "platform.h"
#include "mesh.h"
Renderer::Renderer() {
createInstance();
@ -40,7 +41,7 @@ Renderer::~Renderer() {
vkDestroyInstance(instance_, nullptr);
}
void Renderer::render(RenderTarget* target) {
void Renderer::render(World& world, RenderTarget* target) {
uint32_t imageIndex = 0;
vkAcquireNextImageKHR(device_, target->swapchain, UINT64_MAX, target->imageAvailableSemaphore, nullptr, &imageIndex);
@ -81,7 +82,7 @@ void Renderer::render(RenderTarget* target) {
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
worldPass_->render(commandBuffer);
worldPass_->render(world, commandBuffer);
vkCmdEndRenderPass(commandBuffer);
@ -277,6 +278,75 @@ VkShaderModule Renderer::createShader(const char* path) {
return shaderModule;
}
uint32_t Renderer::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
VkPhysicalDeviceMemoryProperties memProperties;
vkGetPhysicalDeviceMemoryProperties(physicalDevice_, &memProperties);
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
return i;
}
}
return 0;
}
void Renderer::fillMeshBuffers(Mesh* mesh) {
// vertex
{
VkBufferCreateInfo bufferInfo = {};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = sizeof(Vertex) * mesh->vertices.size();
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
vkCreateBuffer(device_, &bufferInfo, nullptr, &mesh->vertexBuffer);
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device_, mesh->vertexBuffer, &memRequirements);
VkMemoryAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
vkAllocateMemory(device_, &allocInfo, nullptr, &mesh->vertexMemory);
vkBindBufferMemory(device_, mesh->vertexBuffer, mesh->vertexMemory, 0);
void* data;
vkMapMemory(device_, mesh->vertexMemory, 0, bufferInfo.size, 0, &data);
memcpy(data, mesh->vertices.data(), bufferInfo.size);
vkUnmapMemory(device_, mesh->vertexMemory);
}
// index
{
VkBufferCreateInfo bufferInfo = {};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = sizeof(uint32_t) * mesh->indices.size();
bufferInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
vkCreateBuffer(device_, &bufferInfo, nullptr, &mesh->indexBuffer);
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device_, mesh->indexBuffer, &memRequirements);
VkMemoryAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
vkAllocateMemory(device_, &allocInfo, nullptr, &mesh->indexMemory);
vkBindBufferMemory(device_, mesh->indexBuffer, mesh->indexMemory, 0);
void* data;
vkMapMemory(device_, mesh->indexMemory, 0, bufferInfo.size, 0, &data);
memcpy(data, mesh->indices.data(), bufferInfo.size);
vkUnmapMemory(device_, mesh->indexMemory);
}
}
void Renderer::createInstance() {
uint32_t layerCount = 0;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);

View file

@ -3,6 +3,8 @@
#include <array>
#include "renderer.h"
#include "world.h"
#include "mesh.h"
WorldPass::WorldPass(Renderer& renderer) : renderer_(renderer) {
createPipeline();
@ -13,9 +15,16 @@ WorldPass::~WorldPass() {
vkDestroyPipelineLayout(renderer_.getDevice(), pipelineLayout_, nullptr);
}
void WorldPass::render(VkCommandBuffer commandBuffer) {
void WorldPass::render(World& world, VkCommandBuffer commandBuffer) {
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
for(const auto& mesh : world.meshes) {
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh->vertexBuffer, offsets);
vkCmdBindIndexBuffer(commandBuffer, mesh->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(commandBuffer, mesh->indices.size(), 1, 0, 0, 0);
}
}
void WorldPass::createPipeline() {
@ -36,10 +45,18 @@ void WorldPass::createPipeline() {
const std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages = {vertShaderStageInfo, fragShaderStageInfo};
VkVertexInputBindingDescription vertexBindingDescription = {};
vertexBindingDescription.stride = sizeof(Vertex);
VkVertexInputAttributeDescription positionAttributeDescription = {};
positionAttributeDescription.format = VK_FORMAT_R32G32B32_SFLOAT;
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 0;
vertexInputInfo.vertexAttributeDescriptionCount = 0;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDescription;
vertexInputInfo.vertexAttributeDescriptionCount = 1;
vertexInputInfo.pVertexAttributeDescriptions = &positionAttributeDescription;
VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;