Archived
1
Fork 0

Add shadow pass

This commit is contained in:
Joshua Goins 2018-11-08 08:57:41 -05:00
parent af1b3b9845
commit 78f56d1509
12 changed files with 439 additions and 35 deletions

View file

@ -51,7 +51,8 @@ add_executable(Graph
src/postpass.cpp src/postpass.cpp
src/dofpass.cpp src/dofpass.cpp
src/imguipass.cpp src/imguipass.cpp
src/skypass.cpp) src/skypass.cpp
src/shadowpass.cpp)
target_compile_options(Graph target_compile_options(Graph
PUBLIC PUBLIC
-fno-exceptions -fno-exceptions
@ -81,7 +82,8 @@ add_shaders(Graph
shaders/imgui.vert shaders/imgui.vert
shaders/imgui.frag shaders/imgui.frag
shaders/sky.vert shaders/sky.vert
shaders/sky.frag) shaders/sky.frag
shaders/shadow.vert)
add_data(Graph add_data(Graph
data/suzanne.obj data/suzanne.obj

View file

@ -10,6 +10,8 @@ enum class LightType {
class Light { class Light {
public: public:
LightType type = LightType::Point; LightType type = LightType::Point;
glm::vec3 position = glm::vec3(0), direction = glm::vec3(0); glm::vec3 position = glm::vec3(0);
glm::vec3 color = glm::vec3(1); glm::vec3 color = glm::vec3(1);
glm::mat4 matrix = glm::mat4(1.0f);
}; };

View file

@ -7,6 +7,7 @@
#include "dofpass.h" #include "dofpass.h"
#include "imguipass.h" #include "imguipass.h"
#include "skypass.h" #include "skypass.h"
#include "shadowpass.h"
constexpr int numFrameResources = 2; constexpr int numFrameResources = 2;
@ -128,6 +129,10 @@ public:
return *worldPass_; return *worldPass_;
} }
ShadowPass& getShadowPass() const {
return *shadowPass_;
}
private: private:
void createInstance(); void createInstance();
#ifdef DEBUG #ifdef DEBUG
@ -174,4 +179,5 @@ private:
DoFPass* dofPass_ = nullptr; DoFPass* dofPass_ = nullptr;
ImGuiPass* imguiPass_ = nullptr; ImGuiPass* imguiPass_ = nullptr;
SkyPass* skyPass_ = nullptr; SkyPass* skyPass_ = nullptr;
ShadowPass* shadowPass_ = nullptr;
}; };

40
include/shadowpass.h Normal file
View file

@ -0,0 +1,40 @@
#pragma once
#include <vulkan/vulkan.h>
class Renderer;
class World;
class ShadowPass {
public:
ShadowPass(Renderer& renderer);
~ShadowPass();
void render(VkCommandBuffer commandBuffer, World& world);
VkImageView getImageView() const {
return shadowImageView_;
}
VkSampler getSampler() const {
return shadowSampler_;
}
private:
void createRenderPass();
void createFramebuffer();
void createPipeline();
VkRenderPass renderPass_ = nullptr;
VkImage shadowImage_ = nullptr;
VkDeviceMemory shadowMemory_ = nullptr;
VkImageView shadowImageView_ = nullptr;
VkFramebuffer shadowFramebuffer_ = nullptr;
VkSampler shadowSampler_ = nullptr;
VkPipeline pipeline_ = nullptr;
VkPipelineLayout pipelineLayout_ = nullptr;
Renderer& renderer_;
};

View file

@ -1,8 +1,9 @@
#version 460 core #version 460 core
layout(location = 0) in vec3 inFragPos; layout(location = 0) in vec3 inFragPos;
layout(location = 1) in vec3 inNormal; layout(location = 1) in vec4 inShadowPos;
layout(location = 2) in vec2 inUV; layout(location = 2) in vec3 inNormal;
layout(location = 3) in vec2 inUV;
layout(location = 0) out vec4 outColor; layout(location = 0) out vec4 outColor;
@ -15,8 +16,41 @@ layout(set = 0, binding = 0) uniform Lights {
Light lights[32]; Light lights[32];
}; };
layout(set = 0, binding = 1) uniform sampler2D shadowSampler;
layout(set = 1, binding = 0) uniform sampler2D albedoSampler; layout(set = 1, binding = 0) uniform sampler2D albedoSampler;
float textureProj(vec4 P, vec2 off) {
const vec4 shadowCoord = P / P.w; // perspective divide
float shadow = 1.0;
if(shadowCoord.z > -1.0 && shadowCoord.z < 1.0) {
const float dist = texture(shadowSampler, shadowCoord.st + off).r;
if(shadowCoord.w > 0.0 && dist < shadowCoord.z)
shadow = 0.1;
}
return shadow;
}
float filterPCF(vec4 sc) {
const ivec2 texDim = textureSize(shadowSampler, 0);
const float scale = 1.5;
const float dx = scale * 1.0 / float(texDim.x);
const float dy = scale * 1.0 / float(texDim.y);
const int range = 2;
float shadowFactor = 0.0;
int count = 0;
for(int x = -range; x <= range; x++) {
for(int y = -range; y <= range; y++) {
shadowFactor += textureProj(sc, vec2(dx * x, dy * y));
count++;
}
}
return shadowFactor / count;
}
void main() { void main() {
vec3 diffuse = vec3(0); vec3 diffuse = vec3(0);
for(int i = 0; i < 32; i++) { for(int i = 0; i < 32; i++) {
@ -29,7 +63,7 @@ void main() {
lightDir = normalize(-lights[i].direction.xyz); lightDir = normalize(-lights[i].direction.xyz);
const float diff = max(dot(norm, lightDir), 0.0); const float diff = max(dot(norm, lightDir), 0.0);
diffuse += vec3(diff) * lights[i].color; diffuse += vec3(diff) * lights[i].color * filterPCF(inShadowPos / inShadowPos.w);
} }
outColor = vec4(vec3(0.1) + diffuse * texture(albedoSampler, inUV).rgb, 1.0); outColor = vec4(vec3(0.1) + diffuse * texture(albedoSampler, inUV).rgb, 1.0);

View file

@ -5,16 +5,24 @@ layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec2 inUV; layout(location = 2) in vec2 inUV;
layout(location = 0) out vec3 outFragPos; layout(location = 0) out vec3 outFragPos;
layout(location = 1) out vec3 outNormal; layout(location = 1) out vec4 outShadowPos;
layout(location = 2) out vec2 outUV; layout(location = 2) out vec3 outNormal;
layout(location = 3) out vec2 outUV;
layout(push_constant) uniform PushConstants { layout(push_constant) uniform PushConstants {
mat4 mvp; mat4 vp, lightSpace;
} pushConstants; } pushConstants;
const mat4 biasMat = mat4(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.5, 0.5, 0.0, 1.0);
void main() { void main() {
gl_Position = pushConstants.mvp * vec4(inPosition, 1.0); gl_Position = pushConstants.vp * vec4(inPosition, 1.0);
outFragPos = inPosition; outFragPos = inPosition;
outShadowPos = (biasMat * pushConstants.lightSpace) * vec4(inPosition, 1.0);
outNormal = inNormal; outNormal = inNormal;
outUV = inUV; outUV = inUV;
} }

11
shaders/shadow.vert Normal file
View file

@ -0,0 +1,11 @@
#version 460 core
layout(location = 0) in vec3 inPosition;
layout(push_constant) uniform PushConstants {
mat4 mvp;
} pushConstants;
void main() {
gl_Position = pushConstants.mvp * vec4(inPosition, 1.0);
}

View file

@ -239,7 +239,7 @@ int main(int argc, char* argv[]) {
auto light = new Light(); auto light = new Light();
light->type = LightType::Directional; light->type = LightType::Directional;
light->direction = glm::vec3(-0.2, -0.8, 0); light->position = glm::vec3(66, 56, 25);
world.lights.push_back(light); world.lights.push_back(light);
@ -362,7 +362,8 @@ int main(int argc, char* argv[]) {
if(SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) if(SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS)
io.MousePos = ImVec2(static_cast<float>(mouseX), static_cast<float>(mouseY)); io.MousePos = ImVec2(static_cast<float>(mouseX), static_cast<float>(mouseY));
ImGui::DragFloat3("Position", &camera.position[0], 0.1f); ImGui::DragFloat3("Light Position", &world.lights[0]->position[0]);
ImGui::DragFloat3("Camera Position", &camera.position[0], 0.1f);
ImGui::DragFloat3("Target", &camera.target[0], 0.1f); ImGui::DragFloat3("Target", &camera.target[0], 0.1f);
ImGui::DragFloat("Aperture", &camera.aperture, 0.01f, 0.0f, 1.0f); ImGui::DragFloat("Aperture", &camera.aperture, 0.01f, 0.0f, 1.0f);
ImGui::DragFloat("Focus Distance", &camera.focusDistance); ImGui::DragFloat("Focus Distance", &camera.focusDistance);

View file

@ -26,6 +26,7 @@ Renderer::Renderer() {
createDescriptorPool(); createDescriptorPool();
createMaterialSetLayout(); createMaterialSetLayout();
shadowPass_ = new ShadowPass(*this);
worldPass_ = new WorldPass(*this); worldPass_ = new WorldPass(*this);
postPass_ = new PostPass(*this); postPass_ = new PostPass(*this);
dofPass_ = new DoFPass(*this); dofPass_ = new DoFPass(*this);
@ -41,6 +42,7 @@ Renderer::~Renderer() {
delete dofPass_; delete dofPass_;
delete postPass_; delete postPass_;
delete worldPass_; delete worldPass_;
delete shadowPass_;
vkDestroyDescriptorSetLayout(device_, materialSetLayout_, nullptr); vkDestroyDescriptorSetLayout(device_, materialSetLayout_, nullptr);
@ -74,6 +76,8 @@ void Renderer::render(World& world, Camera& camera, RenderTarget* target) {
vkBeginCommandBuffer(commandBuffer, &beginInfo); vkBeginCommandBuffer(commandBuffer, &beginInfo);
shadowPass_->render(commandBuffer, world);
VkViewport viewport = {}; VkViewport viewport = {};
viewport.width = target->extent.width; viewport.width = target->extent.width;
viewport.height = target->extent.height; viewport.height = target->extent.height;

266
src/shadowpass.cpp Normal file
View file

@ -0,0 +1,266 @@
#include "shadowpass.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "renderer.h"
#include "world.h"
#include "mesh.h"
#include "light.h"
ShadowPass::ShadowPass(Renderer& renderer) : renderer_(renderer) {
createRenderPass();
createFramebuffer();
createPipeline();
}
ShadowPass::~ShadowPass() {
vkDestroyPipeline(renderer_.getDevice(), pipeline_, nullptr);
vkDestroyPipelineLayout(renderer_.getDevice(), pipelineLayout_, nullptr);
vkDestroySampler(renderer_.getDevice(), shadowSampler_, nullptr);
vkDestroyFramebuffer(renderer_.getDevice(), shadowFramebuffer_, nullptr);
vkDestroyImageView(renderer_.getDevice(), shadowImageView_, nullptr);
vkFreeMemory(renderer_.getDevice(), shadowMemory_, nullptr);
vkDestroyImage(renderer_.getDevice(), shadowImage_, nullptr);
vkDestroyRenderPass(renderer_.getDevice(), renderPass_, nullptr);
}
void ShadowPass::render(VkCommandBuffer commandBuffer, World& world) {
VkViewport viewport = {};
viewport.width = 512;
viewport.height = 512;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
VkRect2D scissor = {};
scissor.extent.width = 512;
scissor.extent.height = 512;
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
VkClearValue clearColor = {};
clearColor.depthStencil.depth = 1.0f;
VkRenderPassBeginInfo renderPassBeginInfo = {};
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassBeginInfo.framebuffer = shadowFramebuffer_;
renderPassBeginInfo.renderPass = renderPass_;
renderPassBeginInfo.renderArea.extent.width = 512;
renderPassBeginInfo.renderArea.extent.height = 512;
renderPassBeginInfo.clearValueCount = 1;
renderPassBeginInfo.pClearValues = &clearColor;
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
glm::mat4 lightSpace = glm::mat4(1.0f);
//lightSpace = glm::perspective(glm::radians(75.0f), 1.0f, 0.1f, 100.0f);
lightSpace = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, 0.1f, 100.0f);
lightSpace *= glm::lookAt(world.lights[0]->position, glm::vec3(0), glm::vec3(0, -1, 0));
world.lights[0]->matrix = lightSpace;
for(const auto& mesh : world.meshes) {
glm::mat4 mvp = world.lights[0]->matrix;
mvp = glm::translate(mvp, mesh->position);
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &mvp);
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);
}
vkCmdEndRenderPass(commandBuffer);
}
void ShadowPass::createRenderPass() {
VkAttachmentDescription depthAttachment = {};
depthAttachment.format = VK_FORMAT_D32_SFLOAT;
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkAttachmentReference depthAttachmentRef = {};
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.pDepthStencilAttachment = &depthAttachmentRef;
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1;
renderPassInfo.pAttachments = &depthAttachment;
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
vkCreateRenderPass(renderer_.getDevice(), &renderPassInfo, nullptr, &renderPass_);
}
void ShadowPass::createFramebuffer() {
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = VK_FORMAT_D32_SFLOAT;
imageCreateInfo.extent.width = 512;
imageCreateInfo.extent.height = 512;
imageCreateInfo.extent.depth = 1;
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
vkCreateImage(renderer_.getDevice(), &imageCreateInfo, nullptr, &shadowImage_);
VkMemoryRequirements memoryRequirements = {};
vkGetImageMemoryRequirements(renderer_.getDevice(), shadowImage_, &memoryRequirements);
VkMemoryAllocateInfo allocateInfo = {};
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocateInfo.allocationSize = memoryRequirements.size;
allocateInfo.memoryTypeIndex = renderer_.findMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
vkAllocateMemory(renderer_.getDevice(), &allocateInfo, nullptr, &shadowMemory_);
vkBindImageMemory(renderer_.getDevice(), shadowImage_, shadowMemory_, 0);
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = shadowImage_;
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = VK_FORMAT_D32_SFLOAT;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.layerCount = 1;
vkCreateImageView(renderer_.getDevice(), &createInfo, nullptr, &shadowImageView_);
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = renderPass_;
framebufferInfo.attachmentCount = 1;
framebufferInfo.pAttachments = &shadowImageView_;
framebufferInfo.width = 512;
framebufferInfo.height = 512;
framebufferInfo.layers = 1;
vkCreateFramebuffer(renderer_.getDevice(), &framebufferInfo, nullptr, &shadowFramebuffer_);
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_FLOAT_OPAQUE_BLACK;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
vkCreateSampler(renderer_.getDevice(), &samplerInfo, nullptr, &shadowSampler_);
}
void ShadowPass::createPipeline() {
VkShaderModule vertShaderModule = renderer_.createShader("shaders/shadow.vert.spv");
VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";
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 = 1;
vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDescription;
vertexInputInfo.vertexAttributeDescriptionCount = 1;
vertexInputInfo.pVertexAttributeDescriptions = &positionAttributeDescription;
VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
VkPipelineViewportStateCreateInfo viewportState = {};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
VkPipelineRasterizationStateCreateInfo rasterizer = {};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT;
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizer.depthBiasEnable = VK_TRUE;
rasterizer.depthBiasConstantFactor = 1.25f;
rasterizer.depthBiasSlopeFactor = 1.75f;
VkPipelineMultisampleStateCreateInfo multisampling = {};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendStateCreateInfo colorBlending = {};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
VkPipelineDepthStencilStateCreateInfo depthState = {};
depthState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthState.depthTestEnable = VK_TRUE;
depthState.depthWriteEnable = VK_TRUE;
depthState.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
const std::array<VkDynamicState, 2> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState = {};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = dynamicStates.size();
dynamicState.pDynamicStates = dynamicStates.data();
VkPushConstantRange pushConstant = {};
pushConstant.size = sizeof(glm::mat4);
pushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &pushConstant;
vkCreatePipelineLayout(renderer_.getDevice(), &pipelineLayoutInfo, nullptr, &pipelineLayout_);
VkGraphicsPipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 1;
pipelineInfo.pStages = &vertShaderStageInfo;
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDepthStencilState = &depthState;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = pipelineLayout_;
pipelineInfo.renderPass = renderPass_;
vkCreateGraphicsPipelines(renderer_.getDevice(), nullptr, 1, &pipelineInfo, nullptr, &pipeline_);
vkDestroyShaderModule(renderer_.getDevice(), vertShaderModule, nullptr);
}

View file

@ -41,7 +41,7 @@ void WorldPass::render(VkCommandBuffer commandBuffer, World& world, Camera& came
for(const auto& light : world.lights) { for(const auto& light : world.lights) {
data->position = glm::vec4(light->position, (int)light->type); data->position = glm::vec4(light->position, (int)light->type);
data->direction = glm::vec4(light->direction, 0.0); data->direction = glm::vec4(glm::normalize(glm::vec3(0) - light->position), 0.0);
data->color = light->color; data->color = light->color;
data++; data++;
@ -55,12 +55,13 @@ void WorldPass::render(VkCommandBuffer commandBuffer, World& world, Camera& came
for(const auto& mesh : world.meshes) { for(const auto& mesh : world.meshes) {
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 1, 1, &mesh->material->set, 0, nullptr); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_, 1, 1, &mesh->material->set, 0, nullptr);
glm::mat4 mvp; glm::mat4 vp;
mvp = glm::perspective(glm::radians(75.0f), (float)target->extent.width / target->extent.height, camera.near, camera.far); vp = 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)); vp *= glm::lookAt(camera.position, camera.target, glm::vec3(0, -1, 0));
mvp = glm::translate(mvp, mesh->position);
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &mvp); vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &vp);
vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), sizeof(glm::mat4), &world.lights[0]->matrix);
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh->vertexBuffer, offsets); vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh->vertexBuffer, offsets);
@ -144,10 +145,21 @@ void WorldPass::createDescriptorSetLayout() {
lightBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; lightBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
lightBufferBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; lightBufferBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
VkDescriptorSetLayoutBinding shadowBinding = {};
shadowBinding.descriptorCount = 1;
shadowBinding.binding = 1;
shadowBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
shadowBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
const std::array<VkDescriptorSetLayoutBinding, 2> bindings = {
lightBufferBinding,
shadowBinding
};
VkDescriptorSetLayoutCreateInfo createInfo = {}; VkDescriptorSetLayoutCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
createInfo.bindingCount = 1; createInfo.bindingCount = bindings.size();
createInfo.pBindings = &lightBufferBinding; createInfo.pBindings = bindings.data();
vkCreateDescriptorSetLayout(renderer_.getDevice(), &createInfo, nullptr, &setLayout_); vkCreateDescriptorSetLayout(renderer_.getDevice(), &createInfo, nullptr, &setLayout_);
} }
@ -245,7 +257,7 @@ void WorldPass::createPipeline() {
dynamicState.pDynamicStates = dynamicStates.data(); dynamicState.pDynamicStates = dynamicStates.data();
VkPushConstantRange mvpPushConstant = {}; VkPushConstantRange mvpPushConstant = {};
mvpPushConstant.size = sizeof(glm::mat4); mvpPushConstant.size = sizeof(glm::mat4) * 2;
mvpPushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; mvpPushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
const std::array<VkDescriptorSetLayout, 2> setLayouts = { const std::array<VkDescriptorSetLayout, 2> setLayouts = {
@ -317,14 +329,32 @@ void WorldPass::createDescriptorSet() {
bufferInfo.buffer = lightBuffer_; bufferInfo.buffer = lightBuffer_;
bufferInfo.range = sizeof(float) * (4 + 4 + 3) * 32; bufferInfo.range = sizeof(float) * (4 + 4 + 3) * 32;
VkWriteDescriptorSet descriptorWrite = {}; VkDescriptorImageInfo imageInfo = {};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
descriptorWrite.descriptorCount = 1; imageInfo.imageView = renderer_.getShadowPass().getImageView();
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; imageInfo.sampler = renderer_.getShadowPass().getSampler();
descriptorWrite.dstSet = descriptorSet_;
descriptorWrite.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(renderer_.getDevice(), 1, &descriptorWrite, 0, nullptr); VkWriteDescriptorSet bufferDescriptorWrite = {};
bufferDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
bufferDescriptorWrite.descriptorCount = 1;
bufferDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
bufferDescriptorWrite.dstSet = descriptorSet_;
bufferDescriptorWrite.pBufferInfo = &bufferInfo;
VkWriteDescriptorSet shadowDescriptorWrite = {};
shadowDescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
shadowDescriptorWrite.descriptorCount = 1;
shadowDescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
shadowDescriptorWrite.dstBinding = 1;
shadowDescriptorWrite.dstSet = descriptorSet_;
shadowDescriptorWrite.pImageInfo = &imageInfo;
const std::array<VkWriteDescriptorSet, 2> descriptorWrites = {
bufferDescriptorWrite,
shadowDescriptorWrite
};
vkUpdateDescriptorSets(renderer_.getDevice(), descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);
float* data; float* data;
vkMapMemory(renderer_.getDevice(), lightMemory_, 0, sizeof(float) * (4 + 4 + 3) * 32, 0, reinterpret_cast<void**>(&data)); vkMapMemory(renderer_.getDevice(), lightMemory_, 0, sizeof(float) * (4 + 4 + 3) * 32, 0, reinterpret_cast<void**>(&data));