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>
|
||||
|
||||
class Mesh;
|
||||
class Light;
|
||||
|
||||
class World {
|
||||
public:
|
||||
std::vector<Mesh*> meshes;
|
||||
std::vector<Light*> lights;
|
||||
};
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
@ -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() {
|
||||
const vec3 norm = normalize(inNormal);
|
||||
const vec3 lightDir = normalize(vec3(5) - inFragPos);
|
||||
vec3 diffuse = vec3(0);
|
||||
for(int i = 0; i < 32; i++) {
|
||||
const vec3 norm = normalize(inNormal);
|
||||
const vec3 lightDir = normalize(lights[i].position.xyz - inFragPos);
|
||||
|
||||
const float diff = max(dot(norm, lightDir), 0.0);
|
||||
diffuse += vec3(diff) * lights[i].color;
|
||||
}
|
||||
|
||||
const float diff = max(dot(norm, lightDir), 0.0);
|
||||
outColor = vec4(vec3(0.1) + vec3(diff), 1.0);
|
||||
outColor = vec4(vec3(0.1) + diffuse, 1.0);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "platform.h"
|
||||
#include "world.h"
|
||||
#include "mesh.h"
|
||||
#include "light.h"
|
||||
|
||||
SDL_Window* window = nullptr;
|
||||
|
||||
|
@ -138,6 +139,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) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <array>
|
||||
|
||||
#include "platform.h"
|
||||
#include "mesh.h"
|
||||
|
@ -51,7 +52,7 @@ void Renderer::render(World& world, RenderTarget* target) {
|
|||
|
||||
vkWaitForFences(device_, 1, &target->fences[target->currentImage], true, UINT64_MAX);
|
||||
vkResetFences(device_, 1, &target->fences[target->currentImage]);
|
||||
|
||||
|
||||
const VkCommandBuffer commandBuffer = target->commandBuffers[target->currentImage];
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo = {};
|
||||
|
@ -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_);
|
||||
|
|
|
@ -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,7 +54,8 @@ 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;
|
||||
mvp = glm::perspective(glm::radians(75.0f), (float)target->extent.width / target->extent.height, 0.1f, 100.0f);
|
||||
|
@ -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_);
|
||||
}
|
||||
|
|
Reference in a new issue