Add shadow pass
This commit is contained in:
parent
af1b3b9845
commit
78f56d1509
12 changed files with 439 additions and 35 deletions
|
@ -51,7 +51,8 @@ add_executable(Graph
|
|||
src/postpass.cpp
|
||||
src/dofpass.cpp
|
||||
src/imguipass.cpp
|
||||
src/skypass.cpp)
|
||||
src/skypass.cpp
|
||||
src/shadowpass.cpp)
|
||||
target_compile_options(Graph
|
||||
PUBLIC
|
||||
-fno-exceptions
|
||||
|
@ -81,7 +82,8 @@ add_shaders(Graph
|
|||
shaders/imgui.vert
|
||||
shaders/imgui.frag
|
||||
shaders/sky.vert
|
||||
shaders/sky.frag)
|
||||
shaders/sky.frag
|
||||
shaders/shadow.vert)
|
||||
|
||||
add_data(Graph
|
||||
data/suzanne.obj
|
||||
|
|
|
@ -10,6 +10,8 @@ enum class LightType {
|
|||
class Light {
|
||||
public:
|
||||
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::mat4 matrix = glm::mat4(1.0f);
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "dofpass.h"
|
||||
#include "imguipass.h"
|
||||
#include "skypass.h"
|
||||
#include "shadowpass.h"
|
||||
|
||||
constexpr int numFrameResources = 2;
|
||||
|
||||
|
@ -128,6 +129,10 @@ public:
|
|||
return *worldPass_;
|
||||
}
|
||||
|
||||
ShadowPass& getShadowPass() const {
|
||||
return *shadowPass_;
|
||||
}
|
||||
|
||||
private:
|
||||
void createInstance();
|
||||
#ifdef DEBUG
|
||||
|
@ -174,4 +179,5 @@ private:
|
|||
DoFPass* dofPass_ = nullptr;
|
||||
ImGuiPass* imguiPass_ = nullptr;
|
||||
SkyPass* skyPass_ = nullptr;
|
||||
ShadowPass* shadowPass_ = nullptr;
|
||||
};
|
||||
|
|
40
include/shadowpass.h
Normal file
40
include/shadowpass.h
Normal 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_;
|
||||
};
|
|
@ -1,8 +1,9 @@
|
|||
#version 460 core
|
||||
|
||||
layout(location = 0) in vec3 inFragPos;
|
||||
layout(location = 1) in vec3 inNormal;
|
||||
layout(location = 2) in vec2 inUV;
|
||||
layout(location = 1) in vec4 inShadowPos;
|
||||
layout(location = 2) in vec3 inNormal;
|
||||
layout(location = 3) in vec2 inUV;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
|
@ -15,8 +16,41 @@ layout(set = 0, binding = 0) uniform Lights {
|
|||
Light lights[32];
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 1) uniform sampler2D shadowSampler;
|
||||
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() {
|
||||
vec3 diffuse = vec3(0);
|
||||
for(int i = 0; i < 32; i++) {
|
||||
|
@ -29,7 +63,7 @@ void main() {
|
|||
lightDir = normalize(-lights[i].direction.xyz);
|
||||
|
||||
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);
|
||||
|
|
|
@ -5,16 +5,24 @@ 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(location = 1) out vec4 outShadowPos;
|
||||
layout(location = 2) out vec3 outNormal;
|
||||
layout(location = 3) out vec2 outUV;
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat4 mvp;
|
||||
mat4 vp, lightSpace;
|
||||
} 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() {
|
||||
gl_Position = pushConstants.mvp * vec4(inPosition, 1.0);
|
||||
gl_Position = pushConstants.vp * vec4(inPosition, 1.0);
|
||||
outFragPos = inPosition;
|
||||
outShadowPos = (biasMat * pushConstants.lightSpace) * vec4(inPosition, 1.0);
|
||||
outNormal = inNormal;
|
||||
outUV = inUV;
|
||||
}
|
||||
|
|
11
shaders/shadow.vert
Normal file
11
shaders/shadow.vert
Normal 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);
|
||||
}
|
|
@ -239,7 +239,7 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
auto light = new Light();
|
||||
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);
|
||||
|
||||
|
@ -362,7 +362,8 @@ int main(int argc, char* argv[]) {
|
|||
if(SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS)
|
||||
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::DragFloat("Aperture", &camera.aperture, 0.01f, 0.0f, 1.0f);
|
||||
ImGui::DragFloat("Focus Distance", &camera.focusDistance);
|
||||
|
|
|
@ -26,6 +26,7 @@ Renderer::Renderer() {
|
|||
createDescriptorPool();
|
||||
createMaterialSetLayout();
|
||||
|
||||
shadowPass_ = new ShadowPass(*this);
|
||||
worldPass_ = new WorldPass(*this);
|
||||
postPass_ = new PostPass(*this);
|
||||
dofPass_ = new DoFPass(*this);
|
||||
|
@ -41,6 +42,7 @@ Renderer::~Renderer() {
|
|||
delete dofPass_;
|
||||
delete postPass_;
|
||||
delete worldPass_;
|
||||
delete shadowPass_;
|
||||
|
||||
vkDestroyDescriptorSetLayout(device_, materialSetLayout_, nullptr);
|
||||
|
||||
|
@ -74,6 +76,8 @@ void Renderer::render(World& world, Camera& camera, RenderTarget* target) {
|
|||
|
||||
vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
||||
|
||||
shadowPass_->render(commandBuffer, world);
|
||||
|
||||
VkViewport viewport = {};
|
||||
viewport.width = target->extent.width;
|
||||
viewport.height = target->extent.height;
|
||||
|
|
266
src/shadowpass.cpp
Normal file
266
src/shadowpass.cpp
Normal 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);
|
||||
}
|
|
@ -41,7 +41,7 @@ void WorldPass::render(VkCommandBuffer commandBuffer, World& world, Camera& came
|
|||
|
||||
for(const auto& light : world.lights) {
|
||||
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++;
|
||||
|
@ -55,12 +55,13 @@ void WorldPass::render(VkCommandBuffer commandBuffer, World& world, Camera& came
|
|||
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));
|
||||
mvp = glm::translate(mvp, mesh->position);
|
||||
glm::mat4 vp;
|
||||
vp = glm::perspective(glm::radians(75.0f), (float)target->extent.width / target->extent.height, camera.near, camera.far);
|
||||
vp *= glm::lookAt(camera.position, camera.target, glm::vec3(0, -1, 0));
|
||||
|
||||
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};
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &mesh->vertexBuffer, offsets);
|
||||
|
@ -144,10 +145,21 @@ void WorldPass::createDescriptorSetLayout() {
|
|||
lightBufferBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
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 = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
createInfo.bindingCount = 1;
|
||||
createInfo.pBindings = &lightBufferBinding;
|
||||
createInfo.bindingCount = bindings.size();
|
||||
createInfo.pBindings = bindings.data();
|
||||
|
||||
vkCreateDescriptorSetLayout(renderer_.getDevice(), &createInfo, nullptr, &setLayout_);
|
||||
}
|
||||
|
@ -245,7 +257,7 @@ void WorldPass::createPipeline() {
|
|||
dynamicState.pDynamicStates = dynamicStates.data();
|
||||
|
||||
VkPushConstantRange mvpPushConstant = {};
|
||||
mvpPushConstant.size = sizeof(glm::mat4);
|
||||
mvpPushConstant.size = sizeof(glm::mat4) * 2;
|
||||
mvpPushConstant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
|
||||
const std::array<VkDescriptorSetLayout, 2> setLayouts = {
|
||||
|
@ -317,14 +329,32 @@ void WorldPass::createDescriptorSet() {
|
|||
bufferInfo.buffer = lightBuffer_;
|
||||
bufferInfo.range = sizeof(float) * (4 + 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;
|
||||
VkDescriptorImageInfo imageInfo = {};
|
||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
imageInfo.imageView = renderer_.getShadowPass().getImageView();
|
||||
imageInfo.sampler = renderer_.getShadowPass().getSampler();
|
||||
|
||||
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;
|
||||
vkMapMemory(renderer_.getDevice(), lightMemory_, 0, sizeof(float) * (4 + 4 + 3) * 32, 0, reinterpret_cast<void**>(&data));
|
||||
|
|
Reference in a new issue