Add movable lights
This commit is contained in:
parent
e010cb356b
commit
d9c6bb8e00
7 changed files with 146 additions and 13 deletions
9
include/light.h
Normal file
9
include/light.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
class Light {
|
||||||
|
public:
|
||||||
|
glm::vec3 position;
|
||||||
|
glm::vec3 color = glm::vec3(1);
|
||||||
|
};
|
|
@ -3,8 +3,10 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class Mesh;
|
class Mesh;
|
||||||
|
class Light;
|
||||||
|
|
||||||
class World {
|
class World {
|
||||||
public:
|
public:
|
||||||
std::vector<Mesh*> meshes;
|
std::vector<Mesh*> meshes;
|
||||||
|
std::vector<Light*> lights;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,12 +19,22 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createRenderPass();
|
void createRenderPass();
|
||||||
|
void createDescriptorSetLayout();
|
||||||
void createPipeline();
|
void createPipeline();
|
||||||
|
void createUniformBuffer();
|
||||||
|
void createDescriptorSet();
|
||||||
|
|
||||||
VkRenderPass renderPass_ = nullptr;
|
VkRenderPass renderPass_ = nullptr;
|
||||||
|
|
||||||
|
VkDescriptorSetLayout setLayout_ = nullptr;
|
||||||
|
|
||||||
VkPipelineLayout pipelineLayout_ = nullptr;
|
VkPipelineLayout pipelineLayout_ = nullptr;
|
||||||
VkPipeline pipeline_ = nullptr;
|
VkPipeline pipeline_ = nullptr;
|
||||||
|
|
||||||
|
VkDeviceMemory lightMemory_ = nullptr;
|
||||||
|
VkBuffer lightBuffer_ = nullptr;
|
||||||
|
|
||||||
|
VkDescriptorSet descriptorSet_ = nullptr;
|
||||||
|
|
||||||
Renderer& renderer_;
|
Renderer& renderer_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,10 +5,24 @@ layout(location = 1) in vec3 inNormal;
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
|
struct Light {
|
||||||
|
vec4 position;
|
||||||
|
vec3 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 0) uniform Lights {
|
||||||
|
Light lights[32];
|
||||||
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
vec3 diffuse = vec3(0);
|
||||||
|
for(int i = 0; i < 32; i++) {
|
||||||
const vec3 norm = normalize(inNormal);
|
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);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
#include "light.h"
|
||||||
|
|
||||||
SDL_Window* window = nullptr;
|
SDL_Window* window = nullptr;
|
||||||
|
|
||||||
|
@ -139,6 +140,11 @@ int main(int, char*[]) {
|
||||||
World world;
|
World world;
|
||||||
world.meshes.push_back(mesh);
|
world.meshes.push_back(mesh);
|
||||||
|
|
||||||
|
Light* light = new Light();
|
||||||
|
light->position.y = 5;
|
||||||
|
|
||||||
|
world.lights.push_back(light);
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
while(running) {
|
while(running) {
|
||||||
SDL_Event event = {};
|
SDL_Event event = {};
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
@ -599,15 +600,16 @@ void Renderer::createPresentationRenderPass() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::createDescriptorPool() {
|
void Renderer::createDescriptorPool() {
|
||||||
VkDescriptorPoolSize poolSize = {};
|
const std::array<VkDescriptorPoolSize, 2> poolSizes = {
|
||||||
poolSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 15},
|
||||||
poolSize.descriptorCount = 15;
|
VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 15}
|
||||||
|
};
|
||||||
|
|
||||||
VkDescriptorPoolCreateInfo poolInfo = {};
|
VkDescriptorPoolCreateInfo poolInfo = {};
|
||||||
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||||
poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||||
poolInfo.poolSizeCount = 1;
|
poolInfo.poolSizeCount = poolSizes.size();
|
||||||
poolInfo.pPoolSizes = &poolSize;
|
poolInfo.pPoolSizes = poolSizes.data();
|
||||||
poolInfo.maxSets = 15;
|
poolInfo.maxSets = 15;
|
||||||
|
|
||||||
vkCreateDescriptorPool(device_, &poolInfo, nullptr, &descriptorPool_);
|
vkCreateDescriptorPool(device_, &poolInfo, nullptr, &descriptorPool_);
|
||||||
|
|
|
@ -6,10 +6,14 @@
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
#include "light.h"
|
||||||
|
|
||||||
WorldPass::WorldPass(Renderer& renderer) : renderer_(renderer) {
|
WorldPass::WorldPass(Renderer& renderer) : renderer_(renderer) {
|
||||||
createRenderPass();
|
createRenderPass();
|
||||||
|
createDescriptorSetLayout();
|
||||||
createPipeline();
|
createPipeline();
|
||||||
|
createUniformBuffer();
|
||||||
|
createDescriptorSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldPass::~WorldPass() {
|
WorldPass::~WorldPass() {
|
||||||
|
@ -20,6 +24,23 @@ WorldPass::~WorldPass() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPass::render(VkCommandBuffer commandBuffer, World& world, RenderTarget* target) {
|
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 = {};
|
VkClearValue clearColor = {};
|
||||||
|
|
||||||
VkRenderPassBeginInfo renderPassBeginInfo = {};
|
VkRenderPassBeginInfo renderPassBeginInfo = {};
|
||||||
|
@ -33,6 +54,7 @@ void WorldPass::render(VkCommandBuffer commandBuffer, World& world, RenderTarget
|
||||||
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
|
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) {
|
for(const auto& mesh : world.meshes) {
|
||||||
glm::mat4 mvp;
|
glm::mat4 mvp;
|
||||||
|
@ -80,6 +102,20 @@ void WorldPass::createRenderPass() {
|
||||||
vkCreateRenderPass(renderer_.getDevice(), &renderPassInfo, nullptr, &renderPass_);
|
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() {
|
void WorldPass::createPipeline() {
|
||||||
VkShaderModule vertShaderModule = renderer_.createShader("triangle.vert.spv");
|
VkShaderModule vertShaderModule = renderer_.createShader("triangle.vert.spv");
|
||||||
VkShaderModule fragShaderModule = renderer_.createShader("triangle.frag.spv");
|
VkShaderModule fragShaderModule = renderer_.createShader("triangle.frag.spv");
|
||||||
|
@ -166,6 +202,8 @@ void WorldPass::createPipeline() {
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
|
||||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
|
pipelineLayoutInfo.setLayoutCount = 1;
|
||||||
|
pipelineLayoutInfo.pSetLayouts = &setLayout_;
|
||||||
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
||||||
pipelineLayoutInfo.pPushConstantRanges = &mvpPushConstant;
|
pipelineLayoutInfo.pPushConstantRanges = &mvpPushConstant;
|
||||||
|
|
||||||
|
@ -190,3 +228,55 @@ void WorldPass::createPipeline() {
|
||||||
vkDestroyShaderModule(renderer_.getDevice(), fragShaderModule, nullptr);
|
vkDestroyShaderModule(renderer_.getDevice(), fragShaderModule, nullptr);
|
||||||
vkDestroyShaderModule(renderer_.getDevice(), vertShaderModule, 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_);
|
||||||
|
}
|
||||||
|
|
Reference in a new issue