Add material class
This commit is contained in:
parent
b53e2bb9ce
commit
0c970b0236
12 changed files with 4643 additions and 2363 deletions
|
@ -75,4 +75,5 @@ add_data(Graph
|
|||
data/suzanne.obj
|
||||
data/test.cim
|
||||
data/bokeh.png
|
||||
data/scene.obj)
|
||||
data/scene.obj
|
||||
data/tile.jpg)
|
||||
|
|
12
data/scene.mtl
Normal file
12
data/scene.mtl
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Blender MTL File: 'None'
|
||||
# Material Count: 1
|
||||
|
||||
newmtl None
|
||||
Ns 96.078431
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.640000 0.640000 0.640000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
6614
data/scene.obj
6614
data/scene.obj
File diff suppressed because it is too large
Load diff
BIN
data/tile.jpg
Normal file
BIN
data/tile.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
16
include/material.h
Normal file
16
include/material.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class Material {
|
||||
public:
|
||||
std::string albedoTexturePath;
|
||||
|
||||
VkImage albedoImage = nullptr;
|
||||
VkDeviceMemory albedoMemory = nullptr;
|
||||
VkImageView albedoImageView = nullptr;
|
||||
VkSampler albedoSampler = nullptr;
|
||||
|
||||
VkDescriptorSet set = nullptr;
|
||||
};
|
|
@ -6,8 +6,11 @@
|
|||
#include <glm/glm.hpp>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
class Material;
|
||||
|
||||
struct Vertex {
|
||||
glm::vec3 position, normal;
|
||||
glm::vec2 uv;
|
||||
};
|
||||
|
||||
class Mesh {
|
||||
|
@ -15,6 +18,8 @@ public:
|
|||
std::string name;
|
||||
glm::vec3 position;
|
||||
|
||||
Material* material = nullptr;
|
||||
|
||||
std::vector<Vertex> vertices;
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ struct RenderTarget {
|
|||
class World;
|
||||
class Mesh;
|
||||
class Camera;
|
||||
class Material;
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
|
@ -91,6 +92,9 @@ public:
|
|||
void fillMeshBuffers(Mesh* mesh);
|
||||
void destroyMeshBuffers(Mesh* mesh);
|
||||
|
||||
void fillMaterialBuffers(Material* material);
|
||||
void destroyMaterialBuffers(Material* material);
|
||||
|
||||
VkInstance getInstance() const {
|
||||
return instance_;
|
||||
}
|
||||
|
@ -115,6 +119,10 @@ public:
|
|||
return descriptorPool_;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout getMaterialSetLayout() const {
|
||||
return materialSetLayout_;
|
||||
}
|
||||
|
||||
private:
|
||||
void createInstance();
|
||||
#ifdef DEBUG
|
||||
|
@ -124,6 +132,7 @@ private:
|
|||
void createCommandPool();
|
||||
void createPresentationRenderPass();
|
||||
void createDescriptorPool();
|
||||
void createMaterialSetLayout();
|
||||
|
||||
VkInstance instance_ = nullptr;
|
||||
|
||||
|
@ -153,6 +162,8 @@ private:
|
|||
|
||||
VkDescriptorPool descriptorPool_ = nullptr;
|
||||
|
||||
VkDescriptorSetLayout materialSetLayout_ = nullptr;
|
||||
|
||||
WorldPass* worldPass_ = nullptr;
|
||||
PostPass* postPass_ = nullptr;
|
||||
DoFPass* dofPass_ = nullptr;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
layout(location = 0) in vec3 inFragPos;
|
||||
layout(location = 1) in vec3 inNormal;
|
||||
layout(location = 2) in vec2 inUV;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
|
@ -10,10 +11,12 @@ struct Light {
|
|||
vec3 color;
|
||||
};
|
||||
|
||||
layout(binding = 0) uniform Lights {
|
||||
layout(set = 0, binding = 0) uniform Lights {
|
||||
Light lights[32];
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 0) uniform sampler2D albedoSampler;
|
||||
|
||||
void main() {
|
||||
vec3 diffuse = vec3(0);
|
||||
for(int i = 0; i < 32; i++) {
|
||||
|
@ -24,5 +27,5 @@ void main() {
|
|||
diffuse += vec3(diff) * lights[i].color;
|
||||
}
|
||||
|
||||
outColor = vec4(vec3(0.1) + diffuse, 1.0);
|
||||
outColor = vec4(vec3(0.1) + diffuse * texture(albedoSampler, inUV).rgb, 1.0);
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
layout(location = 0) in vec3 inPosition;
|
||||
layout(location = 1) in vec3 inNormal;
|
||||
layout(location = 2) in vec2 inUV;
|
||||
|
||||
layout(location = 0) out vec3 outFragPos;
|
||||
layout(location = 1) out vec3 outNormal;
|
||||
layout(location = 2) out vec2 outUV;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat4 mvp;
|
||||
|
@ -14,4 +16,5 @@ void main() {
|
|||
gl_Position = pushConstants.mvp * vec4(inPosition, 1.0);
|
||||
outFragPos = inPosition;
|
||||
outNormal = inNormal;
|
||||
outUV = inUV;
|
||||
}
|
||||
|
|
18
src/main.cpp
18
src/main.cpp
|
@ -16,6 +16,7 @@
|
|||
#include "light.h"
|
||||
#include "camera.h"
|
||||
#include "cinematic.h"
|
||||
#include "material.h"
|
||||
|
||||
SDL_Window* window = nullptr;
|
||||
Renderer* renderer = nullptr;
|
||||
|
@ -111,6 +112,7 @@ Mesh* loadMesh(const char* path) {
|
|||
Vertex vertex;
|
||||
vertex.position = glm::vec3(m->mVertices[i].x, m->mVertices[i].y, m->mVertices[i].z);
|
||||
vertex.normal = glm::vec3(m->mNormals[i].x, m->mNormals[i].y, m->mNormals[i].z);
|
||||
vertex.uv = glm::vec2(m->mTextureCoords[0][i].x, m->mTextureCoords[0][i].y);
|
||||
|
||||
mesh->vertices.push_back(vertex);
|
||||
}
|
||||
|
@ -245,8 +247,17 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
if(cinematicMode)
|
||||
cinematic = loadCinematic(argv[2]);
|
||||
else
|
||||
world.meshes.push_back(loadMesh("data/scene.obj"));
|
||||
else {
|
||||
Material* material = new Material();
|
||||
material->albedoTexturePath = "data/tile.jpg";
|
||||
|
||||
renderer->fillMaterialBuffers(material);
|
||||
|
||||
Mesh* mesh = loadMesh("data/scene.obj");
|
||||
mesh->material = material;
|
||||
|
||||
world.meshes.push_back(mesh);
|
||||
}
|
||||
|
||||
float currentTime = 0.0f, lastTime = 0.0f, animationTime = 0.0f;
|
||||
Shot* currentShot = nullptr;
|
||||
|
@ -369,6 +380,9 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
|
||||
if(cinematic == nullptr) {
|
||||
renderer->destroyMaterialBuffers(world.meshes[0]->material);
|
||||
delete world.meshes[0]->material;
|
||||
|
||||
renderer->destroyMeshBuffers(world.meshes[0]);
|
||||
delete world.meshes[0];
|
||||
}
|
||||
|
|
119
src/renderer.cpp
119
src/renderer.cpp
|
@ -7,10 +7,12 @@
|
|||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <array>
|
||||
#include <stb_image.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "mesh.h"
|
||||
#include "camera.h"
|
||||
#include "material.h"
|
||||
|
||||
Renderer::Renderer() {
|
||||
createInstance();
|
||||
|
@ -22,6 +24,7 @@ Renderer::Renderer() {
|
|||
createCommandPool();
|
||||
createPresentationRenderPass();
|
||||
createDescriptorPool();
|
||||
createMaterialSetLayout();
|
||||
|
||||
worldPass_ = new WorldPass(*this);
|
||||
postPass_ = new PostPass(*this);
|
||||
|
@ -37,6 +40,8 @@ Renderer::~Renderer() {
|
|||
delete postPass_;
|
||||
delete worldPass_;
|
||||
|
||||
vkDestroyDescriptorSetLayout(device_, materialSetLayout_, nullptr);
|
||||
|
||||
vkDestroyDescriptorPool(device_, descriptorPool_, nullptr);
|
||||
|
||||
vkDestroyRenderPass(device_, presentationRenderPass_, nullptr);
|
||||
|
@ -1012,6 +1017,106 @@ void Renderer::fillMeshBuffers(Mesh* mesh) {
|
|||
}
|
||||
}
|
||||
|
||||
void Renderer::fillMaterialBuffers(Material* material) {
|
||||
int width = 0, height = 0, channels = 0;
|
||||
stbi_uc* pixels = stbi_load(material->albedoTexturePath.c_str(), &width, &height, &channels, STBI_rgb_alpha);
|
||||
if(pixels == nullptr)
|
||||
return; // haha what
|
||||
|
||||
VkImageCreateInfo imageCreateInfo = {};
|
||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageCreateInfo.extent.width = width;
|
||||
imageCreateInfo.extent.height = height;
|
||||
imageCreateInfo.extent.depth = 1;
|
||||
imageCreateInfo.mipLevels = 1;
|
||||
imageCreateInfo.arrayLayers = 1;
|
||||
imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
vkCreateImage(device_, &imageCreateInfo, nullptr, &material->albedoImage);
|
||||
|
||||
VkMemoryRequirements memRequirements;
|
||||
vkGetImageMemoryRequirements(device_, material->albedoImage, &memRequirements);
|
||||
|
||||
VkMemoryAllocateInfo allocInfo = {};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocInfo.allocationSize = memRequirements.size;
|
||||
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
vkAllocateMemory(device_, &allocInfo, nullptr, &material->albedoMemory);
|
||||
vkBindImageMemory(device_, material->albedoImage, material->albedoMemory, 0);
|
||||
|
||||
uploadImageData(
|
||||
material->albedoImage,
|
||||
width,
|
||||
height,
|
||||
width * height * 4,
|
||||
pixels
|
||||
);
|
||||
|
||||
stbi_image_free(pixels);
|
||||
|
||||
VkImageViewCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
createInfo.image = material->albedoImage;
|
||||
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
createInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
createInfo.subresourceRange.levelCount = 1;
|
||||
createInfo.subresourceRange.layerCount = 1;
|
||||
|
||||
vkCreateImageView(device_, &createInfo, nullptr, &material->albedoImageView);
|
||||
|
||||
VkSamplerCreateInfo samplerInfo = {};
|
||||
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
samplerInfo.magFilter = VK_FILTER_LINEAR;
|
||||
samplerInfo.minFilter = VK_FILTER_LINEAR;
|
||||
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
|
||||
vkCreateSampler(device_, &samplerInfo, nullptr, &material->albedoSampler);
|
||||
|
||||
VkDescriptorSetAllocateInfo setAllocInfo = {};
|
||||
setAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
setAllocInfo.descriptorPool = descriptorPool_;
|
||||
setAllocInfo.descriptorSetCount = 1;
|
||||
setAllocInfo.pSetLayouts = &materialSetLayout_;
|
||||
|
||||
vkAllocateDescriptorSets(device_, &setAllocInfo, &material->set);
|
||||
|
||||
VkDescriptorImageInfo albedoImageInfo = {};
|
||||
albedoImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
albedoImageInfo.imageView = material->albedoImageView;
|
||||
albedoImageInfo.sampler = material->albedoSampler;
|
||||
|
||||
VkWriteDescriptorSet albedoDescriptorWrite = {};
|
||||
albedoDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
albedoDescriptorWrite.descriptorCount = 1;
|
||||
albedoDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
albedoDescriptorWrite.dstSet = material->set;
|
||||
albedoDescriptorWrite.pImageInfo = &albedoImageInfo;
|
||||
|
||||
vkUpdateDescriptorSets(device_, 1, &albedoDescriptorWrite, 0, nullptr);
|
||||
}
|
||||
|
||||
void Renderer::destroyMaterialBuffers(Material* material) {
|
||||
vkDeviceWaitIdle(device_);
|
||||
|
||||
vkFreeDescriptorSets(device_, descriptorPool_, 1, &material->set);
|
||||
|
||||
vkDestroySampler(device_, material->albedoSampler, nullptr);
|
||||
vkDestroyImageView(device_, material->albedoImageView, nullptr);
|
||||
vkFreeMemory(device_, material->albedoMemory, nullptr);
|
||||
vkDestroyImage(device_, material->albedoImage, nullptr);
|
||||
}
|
||||
|
||||
void Renderer::destroyMeshBuffers(Mesh* mesh) {
|
||||
vkDeviceWaitIdle(device_);
|
||||
|
||||
|
@ -1203,3 +1308,17 @@ void Renderer::createDescriptorPool() {
|
|||
|
||||
vkCreateDescriptorPool(device_, &poolInfo, nullptr, &descriptorPool_);
|
||||
}
|
||||
|
||||
void Renderer::createMaterialSetLayout() {
|
||||
VkDescriptorSetLayoutBinding albedoSamplerBinding = {};
|
||||
albedoSamplerBinding.descriptorCount = 1;
|
||||
albedoSamplerBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
albedoSamplerBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
createInfo.bindingCount = 1;
|
||||
createInfo.pBindings = &albedoSamplerBinding;
|
||||
|
||||
vkCreateDescriptorSetLayout(device_, &createInfo, nullptr, &materialSetLayout_);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "mesh.h"
|
||||
#include "light.h"
|
||||
#include "camera.h"
|
||||
#include "material.h"
|
||||
|
||||
WorldPass::WorldPass(Renderer& renderer) : renderer_(renderer) {
|
||||
createRenderPass();
|
||||
|
@ -64,6 +65,8 @@ void WorldPass::render(VkCommandBuffer commandBuffer, World& world, Camera& came
|
|||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &descriptorSet_, 0, nullptr);
|
||||
|
||||
for(const auto& mesh : world.meshes) {
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 1, 1, &mesh->material->set, 0, nullptr);
|
||||
|
||||
glm::mat4 mvp;
|
||||
mvp = glm::perspective(glm::radians(75.0f), (float)target->extent.width / target->extent.height, camera.near, camera.far);
|
||||
mvp *= glm::lookAt(camera.position, camera.target, glm::vec3(0, -1, 0));
|
||||
|
@ -173,9 +176,15 @@ void WorldPass::createPipeline() {
|
|||
normalAttributeDescription.offset = offsetof(Vertex, normal);
|
||||
normalAttributeDescription.format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
|
||||
const std::array<VkVertexInputAttributeDescription, 2> attributes = {
|
||||
VkVertexInputAttributeDescription uvAttributeDescription = {};
|
||||
uvAttributeDescription.location = 2;
|
||||
uvAttributeDescription.offset = offsetof(Vertex, uv);
|
||||
uvAttributeDescription .format = VK_FORMAT_R32G32_SFLOAT;
|
||||
|
||||
const std::array<VkVertexInputAttributeDescription, 3> attributes = {
|
||||
positionAttributeDescription,
|
||||
normalAttributeDescription
|
||||
normalAttributeDescription,
|
||||
uvAttributeDescription
|
||||
};
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
|
||||
|
@ -234,10 +243,15 @@ void WorldPass::createPipeline() {
|
|||
mvpPushConstant.size = sizeof(glm::mat4);
|
||||
mvpPushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
|
||||
const std::array<VkDescriptorSetLayout, 2> setLayouts = {
|
||||
setLayout_,
|
||||
renderer_.getMaterialSetLayout()
|
||||
};
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
|
||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipelineLayoutInfo.setLayoutCount = 1;
|
||||
pipelineLayoutInfo.pSetLayouts = &setLayout_;
|
||||
pipelineLayoutInfo.setLayoutCount = setLayouts.size();
|
||||
pipelineLayoutInfo.pSetLayouts = setLayouts.data();
|
||||
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
||||
pipelineLayoutInfo.pPushConstantRanges = &mvpPushConstant;
|
||||
|
||||
|
|
Reference in a new issue