Commit d85734c7 authored by Alexander Gauggel's avatar Alexander Gauggel
Browse files

[#66] Added barrier/transition function for sampled images and implemented shadow mapping as a test

parent 2aa1441f
Pipeline #25456 passed with stages
in 3 minutes and 21 seconds
......@@ -258,5 +258,6 @@ namespace vkcv
void submitCommandStream(const CommandStreamHandle handle);
void prepareSwapchainImageForPresent(const CommandStreamHandle handle);
void prepareImageForSampling(const CommandStreamHandle cmdStream, const ImageHandle image);
};
}
......@@ -27,7 +27,7 @@ namespace vkcv {
const ShaderProgram& shaderProgram,
uint32_t width,
uint32_t height,
PassHandle &passHandle,
const PassHandle &passHandle,
const std::vector<VertexAttribute> &vertexAttributes,
const std::vector<vk::DescriptorSetLayout> &descriptorLayouts,
bool useDynamicViewport);
......
......@@ -58,10 +58,12 @@ namespace vkcv {
void reflectShader(ShaderStage shaderStage);
const VertexLayout &getVertexLayout() const;
size_t getPushConstantSize() const;
private:
std::unordered_map<ShaderStage, Shader> m_Shaders;
VertexLayout m_VertexLayout;
size_t m_pushConstantSize = 0;
};
}
%VULKAN_SDK%\Bin32\glslc.exe shader.vert -o vert.spv
%VULKAN_SDK%\Bin32\glslc.exe shader.frag -o frag.spv
%VULKAN_SDK%\Bin32\glslc.exe shadow.vert -o shadow_vert.spv
%VULKAN_SDK%\Bin32\glslc.exe shadow.frag -o shadow_frag.spv
pause
\ No newline at end of file
......@@ -3,12 +3,42 @@
layout(location = 0) in vec3 passNormal;
layout(location = 1) in vec2 passUV;
layout(location = 2) in vec3 passPos;
layout(location = 0) out vec3 outColor;
layout(set=0, binding=0) uniform texture2D meshTexture;
layout(set=0, binding=1) uniform sampler textureSampler;
layout(set=0, binding=2) uniform sunBuffer {
vec3 L; float padding;
mat4 lightMatrix;
};
layout(set=0, binding=3) uniform texture2D shadowMap;
layout(set=0, binding=4) uniform sampler shadowMapSampler;
float shadowTest(vec3 worldPos){
vec4 lightPos = lightMatrix * vec4(worldPos, 1);
lightPos /= lightPos.w;
lightPos.xy = lightPos.xy * 0.5 + 0.5;
if(any(lessThan(lightPos.xy, vec2(0))) || any(greaterThan(lightPos.xy, vec2(1)))){
return 1;
}
lightPos.z = clamp(lightPos.z, 0, 1);
float shadowMapSample = texture(sampler2D(shadowMap, shadowMapSampler), lightPos.xy).r;
float bias = 0.01f;
shadowMapSample += bias;
return shadowMapSample < lightPos.z ? 0 : 1;
}
void main() {
outColor = texture(sampler2D(meshTexture, textureSampler), passUV).rgb;
vec3 N = normalize(passNormal);
vec3 sunColor = vec3(1);
vec3 sun = sunColor * clamp(dot(N, L), 0, 1);
sun *= shadowTest(passPos);
vec3 ambient = vec3(0.1);
vec3 albedo = texture(sampler2D(meshTexture, textureSampler), passUV).rgb;
outColor = albedo * (sun + ambient);
}
\ No newline at end of file
......@@ -7,13 +7,16 @@ layout(location = 2) in vec2 inUV;
layout(location = 0) out vec3 passNormal;
layout(location = 1) out vec2 passUV;
layout(location = 2) out vec3 passPos;
layout( push_constant ) uniform constants{
mat4 mvp;
mat4 model;
};
void main() {
gl_Position = mvp * vec4(inPosition, 1.0);
passNormal = inNormal;
passUV = inUV;
passPos = (model * vec4(inPosition, 1)).xyz;
}
\ No newline at end of file
#version 450
#extension GL_ARB_separate_shader_objects : enable
void main() {
}
\ No newline at end of file
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 inPosition;
layout( push_constant ) uniform constants{
mat4 mvp;
};
void main() {
gl_Position = mvp * vec4(inPosition, 1.0);
}
\ No newline at end of file
......@@ -20,6 +20,7 @@ int main(int argc, const char** argv) {
vkcv::CameraManager cameraManager(window, windowWidth, windowHeight);
cameraManager.getCamera().setPosition(glm::vec3(0.f, 0.f, 3.f));
cameraManager.getCamera().setNearFar(0.1, 30);
window.initEvents();
......@@ -103,8 +104,11 @@ int main(int argc, const char** argv) {
triangleShaderProgram.reflectShader(vkcv::ShaderStage::FRAGMENT);
std::vector<vkcv::DescriptorBinding> descriptorBindings = {
vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED, 1, vkcv::ShaderStage::FRAGMENT),
vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER, 1, vkcv::ShaderStage::FRAGMENT)};
vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED, 1, vkcv::ShaderStage::FRAGMENT),
vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER, 1, vkcv::ShaderStage::FRAGMENT),
vkcv::DescriptorBinding(vkcv::DescriptorType::UNIFORM_BUFFER, 1, vkcv::ShaderStage::FRAGMENT),
vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED, 1, vkcv::ShaderStage::FRAGMENT) ,
vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER, 1, vkcv::ShaderStage::FRAGMENT) };
vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings);
const vkcv::PipelineConfig trianglePipelineDefinition(
......@@ -132,10 +136,12 @@ int main(int argc, const char** argv) {
vkcv::SamplerAddressMode::REPEAT
);
vkcv::DescriptorWrites setWrites;
setWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) };
core.writeResourceDescription(descriptorSet, 0, setWrites);
vkcv::SamplerHandle shadowSampler = core.createSampler(
vkcv::SamplerFilterType::NEAREST,
vkcv::SamplerFilterType::NEAREST,
vkcv::SamplerMipmapMode::NEAREST,
vkcv::SamplerAddressMode::CLAMP_TO_EDGE
);
vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle();
......@@ -147,19 +153,69 @@ int main(int argc, const char** argv) {
glm::vec3( 0.f, -2.f, 0.f),
glm::vec3( 3.f, 0.f, 0.f),
glm::vec3(-3.f, 0.f, 0.f),
glm::vec3( 0.f, 2.f, 0.f)
glm::vec3( 0.f, 2.f, 0.f),
glm::vec3( 0.f, -5.f, 0.f)
};
std::vector<glm::mat4> modelMatrices;
std::vector<vkcv::DrawcallInfo> drawcalls;
std::vector<vkcv::DrawcallInfo> shadowDrawcalls;
for (const auto& position : instancePositions) {
modelMatrices.push_back(glm::translate(glm::mat4(1.f), position));
drawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { descriptorUsage }));
shadowDrawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, {}));
}
std::vector<glm::mat4> mvpMatrices;
modelMatrices.back() *= glm::scale(glm::mat4(1.f), glm::vec3(10.f, 1.f, 10.f));
std::vector<std::array<glm::mat4, 2>> mainPassMatrices;
std::vector<glm::mat4> mvpLight;
vkcv::ShaderProgram shadowShader;
shadowShader.addShader(vkcv::ShaderStage::VERTEX, "resources/shaders/shadow_vert.spv");
shadowShader.addShader(vkcv::ShaderStage::FRAGMENT, "resources/shaders/shadow_frag.spv");
shadowShader.reflectShader(vkcv::ShaderStage::VERTEX);
shadowShader.reflectShader(vkcv::ShaderStage::FRAGMENT);
const vk::Format shadowMapFormat = vk::Format::eD16Unorm;
const std::vector<vkcv::AttachmentDescription> shadowAttachments = {
vkcv::AttachmentDescription(vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, shadowMapFormat)
};
const vkcv::PassConfig shadowPassConfig(shadowAttachments);
const vkcv::PassHandle shadowPass = core.createPass(shadowPassConfig);
const uint32_t shadowMapResolution = 1024;
const vkcv::Image shadowMap = core.createImage(shadowMapFormat, shadowMapResolution, shadowMapResolution, 1);
const vkcv::PipelineConfig shadowPipeConfig(
shadowShader,
shadowMapResolution,
shadowMapResolution,
shadowPass,
attributes,
{},
false);
const vkcv::PipelineHandle shadowPipe = core.createGraphicsPipeline(shadowPipeConfig);
struct LightInfo {
glm::vec3 direction;
float padding;
glm::mat4 lightMatrix;
};
LightInfo lightInfo;
vkcv::Buffer lightBuffer = core.createBuffer<LightInfo>(vkcv::BufferType::UNIFORM, sizeof(glm::vec3));
vkcv::DescriptorWrites setWrites;
setWrites.sampledImageWrites = {
vkcv::SampledImageDescriptorWrite(0, texture.getHandle()),
vkcv::SampledImageDescriptorWrite(3, shadowMap.getHandle()) };
setWrites.samplerWrites = {
vkcv::SamplerDescriptorWrite(1, sampler),
vkcv::SamplerDescriptorWrite(4, shadowSampler) };
setWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(2, lightBuffer.getHandle()) };
core.writeResourceDescription(descriptorSet, 0, setWrites);
auto start = std::chrono::system_clock::now();
const auto appStartTime = start;
while (window.isWindowOpen()) {
vkcv::Window::pollEvents();
......@@ -180,16 +236,54 @@ int main(int argc, const char** argv) {
start = end;
cameraManager.getCamera().updateView(std::chrono::duration<double>(deltatime).count());
const glm::mat4 viewProjection = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView();
mvpMatrices.clear();
const float sunTheta = (end - appStartTime).count() * 0.0000001;
lightInfo.direction = glm::normalize(glm::vec3(cos(sunTheta), 1, sin(sunTheta)));
const float shadowProjectionSize = 5.f;
glm::mat4 projectionLight = glm::ortho(
-shadowProjectionSize,
shadowProjectionSize,
-shadowProjectionSize,
shadowProjectionSize,
-shadowProjectionSize,
shadowProjectionSize);
glm::mat4 vulkanCorrectionMatrix(1.f);
vulkanCorrectionMatrix[2][2] = 0.5;
vulkanCorrectionMatrix[3][2] = 0.5;
projectionLight = vulkanCorrectionMatrix * projectionLight;
const glm::mat4 viewLight = glm::lookAt(glm::vec3(0), -lightInfo.direction, glm::vec3(0, -1, 0));
lightInfo.lightMatrix = projectionLight * viewLight;
lightBuffer.fill({ lightInfo });
const glm::mat4 viewProjectionCamera = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView();
mainPassMatrices.clear();
mvpLight.clear();
for (const auto& m : modelMatrices) {
mvpMatrices.push_back(viewProjection * m);
mainPassMatrices.push_back({ viewProjectionCamera * m, m });
mvpLight.push_back(lightInfo.lightMatrix* m);
}
vkcv::PushConstantData pushConstantData((void*)mvpMatrices.data(), sizeof(glm::mat4));
const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer };
vkcv::PushConstantData pushConstantData((void*)mainPassMatrices.data(), 2 * sizeof(glm::mat4));
const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer };
vkcv::PushConstantData shadowPushConstantData((void*)mvpLight.data(), sizeof(glm::mat4));
auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
core.recordDrawcallsToCmdStream(
cmdStream,
shadowPass,
shadowPipe,
shadowPushConstantData,
shadowDrawcalls,
{ shadowMap.getHandle() });
core.prepareImageForSampling(cmdStream, shadowMap.getHandle());
core.recordDrawcallsToCmdStream(
cmdStream,
trianglePass,
......
......@@ -375,7 +375,9 @@ namespace vkcv
const FinishCommandFunction &finish) {
m_CommandStreamManager->recordCommandsToStream(cmdStreamHandle, record);
m_CommandStreamManager->addFinishCallbackToStream(cmdStreamHandle, finish);
if (finish) {
m_CommandStreamManager->addFinishCallbackToStream(cmdStreamHandle, finish);
}
}
void Core::submitCommandStream(const CommandStreamHandle handle) {
......@@ -457,4 +459,10 @@ namespace vkcv
recordSwapchainImageLayoutTransition(cmdBuffer, vk::ImageLayout::ePresentSrcKHR);
});
}
void Core::prepareImageForSampling(const CommandStreamHandle cmdStream, const ImageHandle image) {
recordCommandsToStream(cmdStream, [image, this](const vk::CommandBuffer cmdBuffer) {
m_ImageManager->recordImageLayoutTransition(image, vk::ImageLayout::eShaderReadOnlyOptimal, cmdBuffer);
}, nullptr);
}
}
......@@ -9,13 +9,13 @@
namespace vkcv {
PipelineConfig::PipelineConfig(
const ShaderProgram& shaderProgram,
uint32_t width,
uint32_t height,
PassHandle &passHandle,
const std::vector<VertexAttribute> &vertexAttributes,
const std::vector<vk::DescriptorSetLayout> &descriptorLayouts,
bool useDynamicViewport)
const ShaderProgram& shaderProgram,
uint32_t width,
uint32_t height,
const PassHandle &passHandle,
const std::vector<VertexAttribute> &vertexAttributes,
const std::vector<vk::DescriptorSetLayout> &descriptorLayouts,
bool useDynamicViewport)
:
m_ShaderProgram(shaderProgram),
m_Height(height),
......
......@@ -174,7 +174,7 @@ namespace vkcv
{ 1.f,1.f,1.f,1.f }
);
const size_t matrixPushConstantSize = 4 * 4 * sizeof(float);
const size_t matrixPushConstantSize = config.m_ShaderProgram.getPushConstantSize();
const vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eAll, 0, matrixPushConstantSize);
// pipeline layout
......
......@@ -5,6 +5,7 @@
*/
#include "vkcv/ShaderProgram.hpp"
#include <algorithm>
namespace vkcv {
/**
......@@ -128,9 +129,19 @@ namespace vkcv {
m_VertexLayout = VertexLayout(inputVec);
}
for (const auto &pushConstantBuffer : resources.push_constant_buffers) {
for (const auto &range : comp.get_active_buffer_ranges(pushConstantBuffer.id)) {
const size_t size = range.range + range.offset;
m_pushConstantSize = std::max(m_pushConstantSize, size);
}
}
}
const VertexLayout& ShaderProgram::getVertexLayout() const{
return m_VertexLayout;
}
size_t ShaderProgram::getPushConstantSize() const {
return m_pushConstantSize;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment