Archived
1
Fork 0

Add movable lights

This commit is contained in:
Joshua Goins 2018-10-18 21:46:48 -04:00
parent e010cb356b
commit d9c6bb8e00
7 changed files with 146 additions and 13 deletions

9
include/light.h Normal file
View file

@ -0,0 +1,9 @@
#pragma once
#include <glm/glm.hpp>
class Light {
public:
glm::vec3 position;
glm::vec3 color = glm::vec3(1);
};

View file

@ -3,8 +3,10 @@
#include <vector>
class Mesh;
class Light;
class World {
public:
std::vector<Mesh*> meshes;
std::vector<Light*> lights;
};

View file

@ -19,12 +19,22 @@ public:
private:
void createRenderPass();
void createDescriptorSetLayout();
void createPipeline();
void createUniformBuffer();
void createDescriptorSet();
VkRenderPass renderPass_ = nullptr;
VkDescriptorSetLayout setLayout_ = nullptr;
VkPipelineLayout pipelineLayout_ = nullptr;
VkPipeline pipeline_ = nullptr;
VkDeviceMemory lightMemory_ = nullptr;
VkBuffer lightBuffer_ = nullptr;
VkDescriptorSet descriptorSet_ = nullptr;
Renderer& renderer_;
};

View file

@ -5,10 +5,24 @@ layout(location = 1) in vec3 inNormal;
layout(location = 0) out vec4 outColor;
struct Light {
vec4 position;
vec3 color;
};
layout(binding = 0) uniform Lights {
Light lights[32];
};
void main() {
vec3 diffuse = vec3(0);
for(int i = 0; i < 32; i++) {
const vec3 norm = normalize(inNormal);
const vec3 lightDir = normalize(vec3(5) - inFragPos);
const vec3 lightDir = normalize(lights[i].position.xyz - inFragPos);
const float diff = max(dot(norm, lightDir), 0.0);
outColor = vec4(vec3(0.1) + vec3(diff), 1.0);
diffuse += vec3(diff) * lights[i].color;
}
outColor = vec4(vec3(0.1) + diffuse, 1.0);
}

View file

@ -12,6 +12,7 @@
#include "platform.h"
#include "world.h"
#include "mesh.h"
#include "light.h"
SDL_Window* window = nullptr;
@ -139,6 +140,11 @@ int main(int, char*[]) {
World world;
world.meshes.push_back(mesh);
Light* light = new Light();
light->position.y = 5;
world.lights.push_back(light);
bool running = true;
while(running) {
SDL_Event event = {};

View file

@ -6,6 +6,7 @@
#include <fstream>
#include <cstring>
#include <cmath>
#include <array>
#include "platform.h"
#include "mesh.h"
@ -599,15 +600,16 @@ void Renderer::createPresentationRenderPass() {
}
void Renderer::createDescriptorPool() {
VkDescriptorPoolSize poolSize = {};
poolSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSize.descriptorCount = 15;
const std::array<VkDescriptorPoolSize, 2> poolSizes = {
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 15},
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 15}
};
VkDescriptorPoolCreateInfo poolInfo = {};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
poolInfo.poolSizeCount = 1;
poolInfo.pPoolSizes = &poolSize;
poolInfo.poolSizeCount = poolSizes.size();
poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = 15;
vkCreateDescriptorPool(device_, &poolInfo, nullptr, &descriptorPool_);

View file

@ -6,10 +6,14 @@
#include "renderer.h"
#include "world.h"
#include "mesh.h"
#include "light.h"
WorldPass::WorldPass(Renderer& renderer) : renderer_(renderer) {
createRenderPass();
createDescriptorSetLayout();
createPipeline();
createUniformBuffer();
createDescriptorSet();
}
WorldPass::~WorldPass() {
@ -20,6 +24,23 @@ WorldPass::~WorldPass() {
}
void WorldPass::render(VkCommandBuffer commandBuffer, World& world, RenderTarget* target) {
struct ShaderLight {
glm::vec4 position;
glm::vec3 color;
};
ShaderLight* data;
vkMapMemory(renderer_.getDevice(), lightMemory_, 0, sizeof(float) * (4 + 3) * 32, 0, (void**)&data);
for(size_t i = 0; i < world.lights.size(); i++) {
data->position = glm::vec4(world.lights[i]->position, 0.0);
data->color = world.lights[i]->color;
data++;
}
vkUnmapMemory(renderer_.getDevice(), lightMemory_);
VkClearValue clearColor = {};
VkRenderPassBeginInfo renderPassBeginInfo = {};
@ -33,6 +54,7 @@ void WorldPass::render(VkCommandBuffer commandBuffer, World& world, RenderTarget
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 0, 1, &descriptorSet_, 0, nullptr);
for(const auto& mesh : world.meshes) {
glm::mat4 mvp;
@ -80,6 +102,20 @@ void WorldPass::createRenderPass() {
vkCreateRenderPass(renderer_.getDevice(), &renderPassInfo, nullptr, &renderPass_);
}
void WorldPass::createDescriptorSetLayout() {
VkDescriptorSetLayoutBinding lightBufferBinding = {};
lightBufferBinding.descriptorCount = 1;
lightBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
lightBufferBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
VkDescriptorSetLayoutCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
createInfo.bindingCount = 1;
createInfo.pBindings = &lightBufferBinding;
vkCreateDescriptorSetLayout(renderer_.getDevice(), &createInfo, nullptr, &setLayout_);
}
void WorldPass::createPipeline() {
VkShaderModule vertShaderModule = renderer_.createShader("triangle.vert.spv");
VkShaderModule fragShaderModule = renderer_.createShader("triangle.frag.spv");
@ -166,6 +202,8 @@ void WorldPass::createPipeline() {
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &setLayout_;
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &mvpPushConstant;
@ -190,3 +228,55 @@ void WorldPass::createPipeline() {
vkDestroyShaderModule(renderer_.getDevice(), fragShaderModule, nullptr);
vkDestroyShaderModule(renderer_.getDevice(), vertShaderModule, nullptr);
}
void WorldPass::createUniformBuffer() {
VkBufferCreateInfo bufferInfo = {};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = sizeof(float) * (4 + 3) * 32;
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
vkCreateBuffer(renderer_.getDevice(), &bufferInfo, nullptr, &lightBuffer_);
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(renderer_.getDevice(), lightBuffer_, &memRequirements);
VkMemoryAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = renderer_.findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
vkAllocateMemory(renderer_.getDevice(), &allocInfo, nullptr, &lightMemory_);
vkBindBufferMemory(renderer_.getDevice(), lightBuffer_, lightMemory_, 0);
}
void WorldPass::createDescriptorSet() {
VkDescriptorSetAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = renderer_.getDescriptorPool();
allocInfo.descriptorSetCount = 1;
allocInfo.pSetLayouts = &setLayout_;
vkAllocateDescriptorSets(renderer_.getDevice(), &allocInfo, &descriptorSet_);
VkDescriptorBufferInfo bufferInfo = {};
bufferInfo.buffer = lightBuffer_;
bufferInfo.range = sizeof(float) * (4 + 3) * 32;
VkWriteDescriptorSet descriptorWrite = {};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.descriptorCount = 1;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrite.dstSet = descriptorSet_;
descriptorWrite.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(renderer_.getDevice(), 1, &descriptorWrite, 0, nullptr);
float* data;
vkMapMemory(renderer_.getDevice(), lightMemory_, 0, sizeof(float) * (4 + 3) * 32, 0, (void**)&data);
for(uint32_t i = 0; i < (4 + 3) * 32; i++)
data[i] = 0.0f;
vkUnmapMemory(renderer_.getDevice(), lightMemory_);
}