Texture tree and terrain scene, refactoring and cleanup
This commit is contained in:
parent
34942b08c5
commit
75b2a72957
13 changed files with 200 additions and 97 deletions
|
|
@ -3,15 +3,12 @@
|
||||||
layout (binding = 1) uniform sampler2DArray shadowMap;
|
layout (binding = 1) uniform sampler2DArray shadowMap;
|
||||||
|
|
||||||
layout (location = 0) in vec2 inUV;
|
layout (location = 0) in vec2 inUV;
|
||||||
|
layout (location = 1) flat in uint inCascadeIndex;
|
||||||
|
|
||||||
layout (location = 0) out vec4 outFragColor;
|
layout (location = 0) out vec4 outFragColor;
|
||||||
|
|
||||||
layout(push_constant) uniform PushConsts {
|
|
||||||
uint cascadeIndex;
|
|
||||||
} pushConsts;
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
float depth = texture(shadowMap, vec3(inUV, float(pushConsts.cascadeIndex))).r;
|
float depth = texture(shadowMap, vec3(inUV, float(inCascadeIndex))).r;
|
||||||
outFragColor = vec4(vec3((depth)), 1.0);
|
outFragColor = vec4(vec3((depth)), 1.0);
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
|
@ -1,14 +1,20 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
|
layout(push_constant) uniform PushConsts {
|
||||||
|
vec4 position;
|
||||||
|
uint cascadeIndex;
|
||||||
|
} pushConsts;
|
||||||
|
|
||||||
layout (location = 0) out vec2 outUV;
|
layout (location = 0) out vec2 outUV;
|
||||||
|
layout (location = 1) out uint outCascadeIndex;
|
||||||
|
|
||||||
out gl_PerVertex {
|
out gl_PerVertex {
|
||||||
vec4 gl_Position;
|
vec4 gl_Position;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||||
|
outCascadeIndex = pushConsts.cascadeIndex;
|
||||||
gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
|
gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,5 +1,13 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
|
layout (set = 1, binding = 0) uniform sampler2D colorMap;
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 inUV;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
float alpha = texture(colorMap, inUV).a;
|
||||||
|
if (alpha < 0.5) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
|
@ -1,11 +1,13 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout (location = 0) in vec3 inPos;
|
layout (location = 0) in vec3 inPos;
|
||||||
|
layout (location = 1) in vec2 inUV;
|
||||||
|
|
||||||
// todo: pass via specialization constant
|
// todo: pass via specialization constant
|
||||||
#define SHADOW_MAP_CASCADE_COUNT 4
|
#define SHADOW_MAP_CASCADE_COUNT 4
|
||||||
|
|
||||||
layout(push_constant) uniform PushConsts {
|
layout(push_constant) uniform PushConsts {
|
||||||
|
vec4 position;
|
||||||
uint cascadeIndex;
|
uint cascadeIndex;
|
||||||
} pushConsts;
|
} pushConsts;
|
||||||
|
|
||||||
|
|
@ -13,11 +15,15 @@ layout (binding = 0) uniform UBO {
|
||||||
mat4[SHADOW_MAP_CASCADE_COUNT] cascadeViewProjMat;
|
mat4[SHADOW_MAP_CASCADE_COUNT] cascadeViewProjMat;
|
||||||
} ubo;
|
} ubo;
|
||||||
|
|
||||||
|
layout (location = 0) out vec2 outUV;
|
||||||
|
|
||||||
out gl_PerVertex {
|
out gl_PerVertex {
|
||||||
vec4 gl_Position;
|
vec4 gl_Position;
|
||||||
};
|
};
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = ubo.cascadeViewProjMat[pushConsts.cascadeIndex] * vec4(inPos, 1.0);
|
outUV = inUV;
|
||||||
|
vec3 pos = inPos + pushConsts.position.xyz;
|
||||||
|
gl_Position = ubo.cascadeViewProjMat[pushConsts.cascadeIndex] * vec4(pos, 1.0);
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
|
@ -2,20 +2,22 @@
|
||||||
|
|
||||||
#define SHADOW_MAP_CASCADE_COUNT 4
|
#define SHADOW_MAP_CASCADE_COUNT 4
|
||||||
|
|
||||||
layout (binding = 1) uniform sampler2DArray shadowMap;
|
layout (set = 0, binding = 1) uniform sampler2DArray shadowMap;
|
||||||
|
layout (set = 1, binding = 0) uniform sampler2D colorMap;
|
||||||
|
|
||||||
layout (location = 0) in vec3 inNormal;
|
layout (location = 0) in vec3 inNormal;
|
||||||
layout (location = 1) in vec3 inColor;
|
layout (location = 1) in vec3 inColor;
|
||||||
layout (location = 2) in vec3 inViewPos;
|
layout (location = 2) in vec3 inViewPos;
|
||||||
layout (location = 3) in vec3 inPos;
|
layout (location = 3) in vec3 inPos;
|
||||||
|
layout (location = 4) in vec2 inUV;
|
||||||
|
|
||||||
layout (constant_id = 0) const int enablePCF = 0;
|
layout (constant_id = 0) const int enablePCF = 0;
|
||||||
|
|
||||||
layout (location = 0) out vec4 outFragColor;
|
layout (location = 0) out vec4 outFragColor;
|
||||||
|
|
||||||
#define ambient 0.1
|
#define ambient 0.3
|
||||||
|
|
||||||
layout (binding = 2) uniform UBO {
|
layout (set = 0, binding = 2) uniform UBO {
|
||||||
vec4 cascadeSplits;
|
vec4 cascadeSplits;
|
||||||
mat4 cascadeViewProjMat[SHADOW_MAP_CASCADE_COUNT];
|
mat4 cascadeViewProjMat[SHADOW_MAP_CASCADE_COUNT];
|
||||||
mat4 inverseViewMat;
|
mat4 inverseViewMat;
|
||||||
|
|
@ -69,6 +71,11 @@ float filterPCF(vec4 sc, uint cascadeIndex)
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
vec4 color = texture(colorMap, inUV);
|
||||||
|
if (color.a < 0.5) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
// Get cascade index for the current fragment's view position
|
// Get cascade index for the current fragment's view position
|
||||||
uint cascadeIndex = 0;
|
uint cascadeIndex = 0;
|
||||||
for(uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; ++i) {
|
for(uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; ++i) {
|
||||||
|
|
@ -91,10 +98,11 @@ void main()
|
||||||
vec3 N = normalize(inNormal);
|
vec3 N = normalize(inNormal);
|
||||||
vec3 L = normalize(-ubo.lightDir);
|
vec3 L = normalize(-ubo.lightDir);
|
||||||
vec3 H = normalize(L + inViewPos);
|
vec3 H = normalize(L + inViewPos);
|
||||||
float diffuse = max(dot(N, L), 0.0);
|
float diffuse = max(dot(N, L), ambient);
|
||||||
vec3 lightColor = vec3(1.0);
|
vec3 lightColor = vec3(1.0);
|
||||||
outFragColor.rgb = max(lightColor * (diffuse * inColor), vec3(0.0));
|
outFragColor.rgb = max(lightColor * (diffuse * color.rgb), vec3(0.0));
|
||||||
outFragColor.rgb *= shadow;
|
outFragColor.rgb *= shadow;
|
||||||
|
outFragColor.a = color.a;
|
||||||
|
|
||||||
// Color cascades (if enabled)
|
// Color cascades (if enabled)
|
||||||
if (ubo.colorCascades == 1) {
|
if (ubo.colorCascades == 1) {
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -15,6 +15,12 @@ layout (location = 0) out vec3 outNormal;
|
||||||
layout (location = 1) out vec3 outColor;
|
layout (location = 1) out vec3 outColor;
|
||||||
layout (location = 2) out vec3 outViewPos;
|
layout (location = 2) out vec3 outViewPos;
|
||||||
layout (location = 3) out vec3 outPos;
|
layout (location = 3) out vec3 outPos;
|
||||||
|
layout (location = 4) out vec2 outUV;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PushConsts {
|
||||||
|
vec4 position;
|
||||||
|
uint cascadeIndex;
|
||||||
|
} pushConsts;
|
||||||
|
|
||||||
out gl_PerVertex {
|
out gl_PerVertex {
|
||||||
vec4 gl_Position;
|
vec4 gl_Position;
|
||||||
|
|
@ -24,8 +30,10 @@ void main()
|
||||||
{
|
{
|
||||||
outColor = inColor;
|
outColor = inColor;
|
||||||
outNormal = inNormal;
|
outNormal = inNormal;
|
||||||
outPos = inPos;
|
outUV = inUV;
|
||||||
outViewPos = (ubo.view * vec4(inPos.xyz, 1.0)).xyz;
|
vec3 pos = inPos + pushConsts.position.xyz;
|
||||||
gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos.xyz, 1.0);
|
outPos = pos;
|
||||||
|
outViewPos = (ubo.view * vec4(pos.xyz, 1.0)).xyz;
|
||||||
|
gl_Position = ubo.projection * ubo.view * ubo.model * vec4(pos.xyz, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -21,6 +21,7 @@
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include "vulkanexamplebase.h"
|
#include "vulkanexamplebase.h"
|
||||||
#include "VulkanBuffer.hpp"
|
#include "VulkanBuffer.hpp"
|
||||||
|
#include "VulkanTexture.hpp"
|
||||||
#include "VulkanModel.hpp"
|
#include "VulkanModel.hpp"
|
||||||
|
|
||||||
#define ENABLE_VALIDATION false
|
#define ENABLE_VALIDATION false
|
||||||
|
|
@ -28,7 +29,7 @@
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
#define SHADOWMAP_DIM 1024
|
#define SHADOWMAP_DIM 1024
|
||||||
#else
|
#else
|
||||||
#define SHADOWMAP_DIM 2048
|
#define SHADOWMAP_DIM 4096
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SHADOW_MAP_CASCADE_COUNT 4
|
#define SHADOW_MAP_CASCADE_COUNT 4
|
||||||
|
|
@ -41,7 +42,7 @@ public:
|
||||||
bool colorCascades = false;
|
bool colorCascades = false;
|
||||||
bool filterPCF = false;
|
bool filterPCF = false;
|
||||||
|
|
||||||
float cascadeSplitLambda = 1.0f;
|
float cascadeSplitLambda = 0.95f;
|
||||||
|
|
||||||
float zNear = 0.5f;
|
float zNear = 0.5f;
|
||||||
float zFar = 48.0f;
|
float zFar = 48.0f;
|
||||||
|
|
@ -56,23 +57,27 @@ public:
|
||||||
vks::VERTEX_COMPONENT_NORMAL,
|
vks::VERTEX_COMPONENT_NORMAL,
|
||||||
});
|
});
|
||||||
|
|
||||||
std::vector<vks::Model> scenes;
|
std::vector<vks::Model> models;
|
||||||
std::vector<std::string> sceneNames;
|
|
||||||
int32_t sceneIndex = 0;
|
|
||||||
|
|
||||||
struct {
|
struct Material {
|
||||||
|
vks::Texture2D texture;
|
||||||
|
VkDescriptorSet descriptorSet;
|
||||||
|
};
|
||||||
|
std::vector<Material> materials;
|
||||||
|
|
||||||
|
struct uniformBuffers {
|
||||||
vks::Buffer VS;
|
vks::Buffer VS;
|
||||||
vks::Buffer FS;
|
vks::Buffer FS;
|
||||||
} uniformBuffers;
|
} uniformBuffers;
|
||||||
|
|
||||||
struct {
|
struct UBOVS {
|
||||||
glm::mat4 projection;
|
glm::mat4 projection;
|
||||||
glm::mat4 view;
|
glm::mat4 view;
|
||||||
glm::mat4 model;
|
glm::mat4 model;
|
||||||
glm::vec3 lightDir;
|
glm::vec3 lightDir;
|
||||||
} uboVS;
|
} uboVS;
|
||||||
|
|
||||||
struct {
|
struct UBOFS {
|
||||||
float cascadeSplits[4];
|
float cascadeSplits[4];
|
||||||
glm::mat4 cascadeViewProjMat[4];
|
glm::mat4 cascadeViewProjMat[4];
|
||||||
glm::mat4 inverseViewMat;
|
glm::mat4 inverseViewMat;
|
||||||
|
|
@ -81,15 +86,24 @@ public:
|
||||||
int32_t colorCascades;
|
int32_t colorCascades;
|
||||||
} uboFS;
|
} uboFS;
|
||||||
|
|
||||||
struct {
|
VkPipelineLayout pipelineLayout;
|
||||||
|
struct Pipelines {
|
||||||
VkPipeline debugShadowMap;
|
VkPipeline debugShadowMap;
|
||||||
VkPipeline sceneShadow;
|
VkPipeline sceneShadow;
|
||||||
VkPipeline sceneShadowPCF;
|
VkPipeline sceneShadowPCF;
|
||||||
} pipelines;
|
} pipelines;
|
||||||
|
|
||||||
VkPipelineLayout pipelineLayout;
|
struct DescriptorSetLayouts {
|
||||||
|
VkDescriptorSetLayout base;
|
||||||
|
VkDescriptorSetLayout material;
|
||||||
|
} descriptorSetLayouts;
|
||||||
VkDescriptorSet descriptorSet;
|
VkDescriptorSet descriptorSet;
|
||||||
VkDescriptorSetLayout descriptorSetLayout;
|
|
||||||
|
// For simplicity all pipelines use the same push constant block layout
|
||||||
|
struct PushConstBlock {
|
||||||
|
glm::vec4 position;
|
||||||
|
uint32_t cascadeIndex;
|
||||||
|
};
|
||||||
|
|
||||||
// Resources of the depth map generation pass
|
// Resources of the depth map generation pass
|
||||||
struct DepthPass {
|
struct DepthPass {
|
||||||
|
|
@ -139,15 +153,18 @@ public:
|
||||||
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
|
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
|
||||||
{
|
{
|
||||||
title = "Cascaded shadow mapping";
|
title = "Cascaded shadow mapping";
|
||||||
timerSpeed *= 0.05f;
|
timerSpeed *= 0.025f;
|
||||||
camera.type = Camera::CameraType::firstperson;
|
camera.type = Camera::CameraType::firstperson;
|
||||||
camera.movementSpeed = 2.5f;
|
camera.movementSpeed = 2.5f;
|
||||||
camera.setPerspective(45.0f, (float)width / (float)height, zNear, zFar);
|
camera.setPerspective(45.0f, (float)width / (float)height, zNear, zFar);
|
||||||
camera.setPosition(glm::vec3(2.0f, 0.375f, -1.25f));
|
camera.setPosition(glm::vec3(0.0f, 0.62f, -2.4f));
|
||||||
camera.setRotation(glm::vec3(-19.0f, 42.0f, 0.0f));
|
camera.setRotation(glm::vec3(0.0f, -13.0f, 0.0f));
|
||||||
|
|
||||||
|
camera.setPosition(glm::vec3(-0.12f, 1.14f, -2.25f));
|
||||||
|
camera.setRotation(glm::vec3(-17.0f, 7.0f, 0.0f));
|
||||||
|
|
||||||
settings.overlay = true;
|
settings.overlay = true;
|
||||||
timer = 0.317028880f;
|
timer = 0.2f;
|
||||||
paused = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~VulkanExample()
|
~VulkanExample()
|
||||||
|
|
@ -167,10 +184,14 @@ public:
|
||||||
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
||||||
vkDestroyPipelineLayout(device, depthPass.pipelineLayout, nullptr);
|
vkDestroyPipelineLayout(device, depthPass.pipelineLayout, nullptr);
|
||||||
|
|
||||||
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
|
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.base, nullptr);
|
||||||
|
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.material, nullptr);
|
||||||
|
|
||||||
for (auto scene : scenes) {
|
for (auto model : models) {
|
||||||
scene.destroy();
|
model.destroy();
|
||||||
|
}
|
||||||
|
for (auto material : materials) {
|
||||||
|
material.texture.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
depthPass.uniformBuffer.destroy();
|
depthPass.uniformBuffer.destroy();
|
||||||
|
|
@ -183,6 +204,7 @@ public:
|
||||||
|
|
||||||
virtual void getEnabledFeatures()
|
virtual void getEnabledFeatures()
|
||||||
{
|
{
|
||||||
|
enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy;
|
||||||
// Depth clamp to avoid near plane clipping
|
// Depth clamp to avoid near plane clipping
|
||||||
enabledFeatures.depthClamp = deviceFeatures.depthClamp;
|
enabledFeatures.depthClamp = deviceFeatures.depthClamp;
|
||||||
}
|
}
|
||||||
|
|
@ -194,7 +216,7 @@ public:
|
||||||
vks::tools::getSupportedDepthFormat(physicalDevice, &depthFormat);
|
vks::tools::getSupportedDepthFormat(physicalDevice, &depthFormat);
|
||||||
|
|
||||||
depthPass.commandBuffer = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, false);
|
depthPass.commandBuffer = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, false);
|
||||||
// Create a semaphore used to synchronize offscreen rendering and usage
|
// Create a semaphore used to synchronize depth map generation and use
|
||||||
VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo();
|
VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo();
|
||||||
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &depthPass.semaphore));
|
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &depthPass.semaphore));
|
||||||
|
|
||||||
|
|
@ -328,6 +350,48 @@ public:
|
||||||
VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &depth.sampler));
|
VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &depth.sampler));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void renderScene(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VkDescriptorSet descriptorSet, uint32_t cascadeIndex = 0) {
|
||||||
|
const VkDeviceSize offsets[1] = { 0 };
|
||||||
|
PushConstBlock pushConstBlock = { glm::vec4(0.0f), cascadeIndex };
|
||||||
|
|
||||||
|
std::array<VkDescriptorSet,2> sets;
|
||||||
|
sets[0] = descriptorSet;
|
||||||
|
|
||||||
|
// Floor
|
||||||
|
sets[1] = materials[0].descriptorSet;
|
||||||
|
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, sets.data(), 0, NULL);
|
||||||
|
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
|
||||||
|
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &models[0].vertices.buffer, offsets);
|
||||||
|
vkCmdBindIndexBuffer(commandBuffer, models[0].indices.buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||||
|
vkCmdDrawIndexed(commandBuffer, models[0].indexCount, 1, 0, 0, 0);
|
||||||
|
|
||||||
|
// Trees
|
||||||
|
const std::vector<glm::vec3> positions = {
|
||||||
|
glm::vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec3(1.25f, 0.25f, 1.25f),
|
||||||
|
glm::vec3(-1.25f, -0.2f, 1.25f),
|
||||||
|
glm::vec3(1.25f, 0.1f, -1.25f),
|
||||||
|
glm::vec3(-1.25f, -0.25f, -1.25f),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto position : positions) {
|
||||||
|
pushConstBlock.position = glm::vec4(position, 0.0f);
|
||||||
|
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
|
||||||
|
|
||||||
|
sets[1] = materials[1].descriptorSet;
|
||||||
|
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, sets.data(), 0, NULL);
|
||||||
|
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &models[1].vertices.buffer, offsets);
|
||||||
|
vkCmdBindIndexBuffer(commandBuffer, models[1].indices.buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||||
|
vkCmdDrawIndexed(commandBuffer, models[1].indexCount, 1, 0, 0, 0);
|
||||||
|
|
||||||
|
sets[1] = materials[2].descriptorSet;
|
||||||
|
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, sets.data(), 0, NULL);
|
||||||
|
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &models[2].vertices.buffer, offsets);
|
||||||
|
vkCmdBindIndexBuffer(commandBuffer, models[2].indices.buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||||
|
vkCmdDrawIndexed(commandBuffer, models[2].indexCount, 1, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void buildOffscreenCommandBuffer()
|
void buildOffscreenCommandBuffer()
|
||||||
{
|
{
|
||||||
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
|
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
|
||||||
|
|
@ -358,12 +422,9 @@ public:
|
||||||
renderPassBeginInfo.framebuffer = cascades[i].frameBuffer;
|
renderPassBeginInfo.framebuffer = cascades[i].frameBuffer;
|
||||||
vkCmdBeginRenderPass(depthPass.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(depthPass.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
vkCmdBindPipeline(depthPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, depthPass.pipeline);
|
vkCmdBindPipeline(depthPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, depthPass.pipeline);
|
||||||
vkCmdPushConstants(depthPass.commandBuffer, depthPass.pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(uint32_t), &i);
|
|
||||||
VkDeviceSize offsets[1] = { 0 };
|
VkDeviceSize offsets[1] = { 0 };
|
||||||
vkCmdBindDescriptorSets(depthPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, depthPass.pipelineLayout, 0, 1, &cascades[i].descriptorSet, 0, NULL);
|
vkCmdBindDescriptorSets(depthPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, depthPass.pipelineLayout, 0, 1, &cascades[i].descriptorSet, 0, NULL);
|
||||||
vkCmdBindVertexBuffers(depthPass.commandBuffer, 0, 1, &scenes[sceneIndex].vertices.buffer, offsets);
|
renderScene(depthPass.commandBuffer, depthPass.pipelineLayout, cascades[i].descriptorSet, i);
|
||||||
vkCmdBindIndexBuffer(depthPass.commandBuffer, scenes[sceneIndex].indices.buffer, 0, VK_INDEX_TYPE_UINT32);
|
|
||||||
vkCmdDrawIndexed(depthPass.commandBuffer, scenes[sceneIndex].indexCount, 1, 0, 0, 0);
|
|
||||||
vkCmdEndRenderPass(depthPass.commandBuffer);
|
vkCmdEndRenderPass(depthPass.commandBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -407,16 +468,15 @@ public:
|
||||||
if (displayDepthMap) {
|
if (displayDepthMap) {
|
||||||
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL);
|
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL);
|
||||||
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.debugShadowMap);
|
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.debugShadowMap);
|
||||||
vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(uint32_t), &displayDepthMapCascadeIndex);
|
PushConstBlock pushConstBlock = {};
|
||||||
|
pushConstBlock.cascadeIndex = displayDepthMapCascadeIndex;
|
||||||
|
vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
|
||||||
vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0);
|
vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render shadowed scene
|
// Render shadowed scene
|
||||||
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL);
|
|
||||||
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, (filterPCF) ? pipelines.sceneShadowPCF : pipelines.sceneShadow);
|
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, (filterPCF) ? pipelines.sceneShadowPCF : pipelines.sceneShadow);
|
||||||
vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &scenes[sceneIndex].vertices.buffer, offsets);
|
renderScene(drawCmdBuffers[i], pipelineLayout, descriptorSet);
|
||||||
vkCmdBindIndexBuffer(drawCmdBuffers[i], scenes[sceneIndex].indices.buffer, 0, VK_INDEX_TYPE_UINT32);
|
|
||||||
vkCmdDrawIndexed(drawCmdBuffers[i], scenes[sceneIndex].indexCount, 1, 0, 0, 0);
|
|
||||||
|
|
||||||
vkCmdEndRenderPass(drawCmdBuffers[i]);
|
vkCmdEndRenderPass(drawCmdBuffers[i]);
|
||||||
|
|
||||||
|
|
@ -426,80 +486,65 @@ public:
|
||||||
|
|
||||||
void loadAssets()
|
void loadAssets()
|
||||||
{
|
{
|
||||||
scenes.resize(2);
|
materials.resize(3);
|
||||||
scenes[0].loadFromFile(getAssetPath() + "models/trees.dae", vertexLayout, 1.0f, vulkanDevice, queue);
|
materials[0].texture.loadFromFile(getAssetPath() + "textures/gridlines.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue);
|
||||||
scenes[1].loadFromFile(getAssetPath() + "models/samplescene.dae", vertexLayout, 0.25f, vulkanDevice, queue);
|
materials[1].texture.loadFromFile(getAssetPath() + "textures/oak_bark.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue);
|
||||||
sceneNames = { "Trees", "Teapots and pillars" };
|
materials[2].texture.loadFromFile(getAssetPath() + "textures/oak_leafs.ktx", VK_FORMAT_R8G8B8A8_UNORM, vulkanDevice, queue);
|
||||||
|
|
||||||
}
|
models.resize(3);
|
||||||
|
models[0].loadFromFile(getAssetPath() + "models/terrain_simple.dae", vertexLayout, 1.0f, vulkanDevice, queue);
|
||||||
void setupDescriptorPool()
|
models[1].loadFromFile(getAssetPath() + "models/oak_trunk.dae", vertexLayout, 2.0f, vulkanDevice, queue);
|
||||||
{
|
models[2].loadFromFile(getAssetPath() + "models/oak_leafs.dae", vertexLayout, 2.0f, vulkanDevice, queue);
|
||||||
std::vector<VkDescriptorPoolSize> poolSizes = {
|
|
||||||
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 12),
|
|
||||||
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 32)
|
|
||||||
};
|
|
||||||
VkDescriptorPoolCreateInfo descriptorPoolInfo =
|
|
||||||
vks::initializers::descriptorPoolCreateInfo(static_cast<uint32_t>(poolSizes.size()), poolSizes.data(), 3 + SHADOW_MAP_CASCADE_COUNT);
|
|
||||||
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupLayoutsAndDescriptors()
|
void setupLayoutsAndDescriptors()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Layouts
|
Descriptor pool
|
||||||
|
*/
|
||||||
|
std::vector<VkDescriptorPoolSize> poolSizes = {
|
||||||
|
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 32),
|
||||||
|
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 32)
|
||||||
|
};
|
||||||
|
VkDescriptorPoolCreateInfo descriptorPoolInfo =
|
||||||
|
vks::initializers::descriptorPoolCreateInfo(static_cast<uint32_t>(poolSizes.size()), poolSizes.data(), 4 + SHADOW_MAP_CASCADE_COUNT);
|
||||||
|
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Descriptor set layouts
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Shared matrices and samplers
|
||||||
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
|
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
|
||||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0),
|
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0),
|
||||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1),
|
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1),
|
||||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 2),
|
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT, 2),
|
||||||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 3),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VkDescriptorSetLayoutCreateInfo descriptorLayout =
|
VkDescriptorSetLayoutCreateInfo descriptorLayout =
|
||||||
vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
|
vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
|
||||||
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout));
|
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.base));
|
||||||
|
|
||||||
// Shared pipeline layout
|
// Material texture
|
||||||
{
|
setLayoutBindings = {
|
||||||
// Pass cascade index as push constant
|
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 0),
|
||||||
VkPushConstantRange pushConstantRange =
|
};
|
||||||
vks::initializers::pushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(uint32_t), 0);
|
descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
|
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayouts.material));
|
||||||
vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);
|
|
||||||
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
|
||||||
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
|
|
||||||
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offscreen pipeline layout
|
|
||||||
{
|
|
||||||
// Pass cascade matrix as push constant
|
|
||||||
VkPushConstantRange pushConstantRange =
|
|
||||||
vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(glm::mat4), 0);
|
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
|
|
||||||
vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);
|
|
||||||
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
|
||||||
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
|
|
||||||
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &depthPass.pipelineLayout));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Dscriptor sets
|
Descriptor sets
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::vector<VkWriteDescriptorSet> writeDescriptorSets;
|
std::vector<VkWriteDescriptorSet> writeDescriptorSets;
|
||||||
|
|
||||||
VkDescriptorSetAllocateInfo allocInfo =
|
|
||||||
vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1);
|
|
||||||
|
|
||||||
// Scene rendering / debug display
|
|
||||||
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));
|
|
||||||
|
|
||||||
VkDescriptorImageInfo depthMapDescriptor =
|
VkDescriptorImageInfo depthMapDescriptor =
|
||||||
vks::initializers::descriptorImageInfo(depth.sampler, depth.view, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
|
vks::initializers::descriptorImageInfo(depth.sampler, depth.view, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
|
||||||
|
|
||||||
|
VkDescriptorSetAllocateInfo allocInfo =
|
||||||
|
vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.base, 1);
|
||||||
|
|
||||||
|
// Scene rendering / debug display
|
||||||
|
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));
|
||||||
writeDescriptorSets = {
|
writeDescriptorSets = {
|
||||||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.VS.descriptor),
|
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers.VS.descriptor),
|
||||||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &depthMapDescriptor),
|
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &depthMapDescriptor),
|
||||||
|
|
@ -507,7 +552,7 @@ public:
|
||||||
};
|
};
|
||||||
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
|
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
|
||||||
|
|
||||||
// Per-cascade descriptor set
|
// Per-cascade descriptor sets
|
||||||
// Each descriptor set represents a single layer of the array texture
|
// Each descriptor set represents a single layer of the array texture
|
||||||
for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) {
|
for (uint32_t i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) {
|
||||||
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &cascades[i].descriptorSet));
|
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &cascades[i].descriptorSet));
|
||||||
|
|
@ -518,6 +563,38 @@ public:
|
||||||
};
|
};
|
||||||
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
|
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Per-material descriptor sets
|
||||||
|
allocInfo.pSetLayouts = &descriptorSetLayouts.material;
|
||||||
|
for (auto& material : materials) {
|
||||||
|
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &material.descriptorSet));
|
||||||
|
VkWriteDescriptorSet writeDescriptorSet = vks::initializers::writeDescriptorSet(material.descriptorSet, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, &material.texture.descriptor);
|
||||||
|
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pipeline layouts
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Shared pipeline layout (scene and depth map debug display)
|
||||||
|
{
|
||||||
|
VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstBlock), 0);
|
||||||
|
std::array<VkDescriptorSetLayout, 2> setLayouts = { descriptorSetLayouts.base, descriptorSetLayouts.material };
|
||||||
|
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast<uint32_t>(setLayouts.size()));
|
||||||
|
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
||||||
|
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
|
||||||
|
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Depth pass pipeline layout
|
||||||
|
{
|
||||||
|
VkPushConstantRange pushConstantRange = vks::initializers::pushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, sizeof(PushConstBlock), 0);
|
||||||
|
std::array<VkDescriptorSetLayout, 2> setLayouts = { descriptorSetLayouts.base, descriptorSetLayouts.material };
|
||||||
|
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(setLayouts.data(), static_cast<uint32_t>(setLayouts.size()));
|
||||||
|
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
||||||
|
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
|
||||||
|
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &depthPass.pipelineLayout));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void preparePipelines()
|
void preparePipelines()
|
||||||
|
|
@ -597,7 +674,7 @@ public:
|
||||||
/*
|
/*
|
||||||
Shadow mapped scene rendering
|
Shadow mapped scene rendering
|
||||||
*/
|
*/
|
||||||
rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT;
|
rasterizationState.cullMode = VK_CULL_MODE_NONE;
|
||||||
shaderStages[0] = loadShader(getAssetPath() + "shaders/shadowmappingcascade/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
shaderStages[0] = loadShader(getAssetPath() + "shaders/shadowmappingcascade/scene.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||||
shaderStages[1] = loadShader(getAssetPath() + "shaders/shadowmappingcascade/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
shaderStages[1] = loadShader(getAssetPath() + "shaders/shadowmappingcascade/scene.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
// Use specialization constants to select between horizontal and vertical blur
|
// Use specialization constants to select between horizontal and vertical blur
|
||||||
|
|
@ -605,9 +682,7 @@ public:
|
||||||
VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t));
|
VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t));
|
||||||
VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(uint32_t), &enablePCF);
|
VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(uint32_t), &enablePCF);
|
||||||
shaderStages[1].pSpecializationInfo = &specializationInfo;
|
shaderStages[1].pSpecializationInfo = &specializationInfo;
|
||||||
// No filtering
|
|
||||||
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.sceneShadow));
|
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.sceneShadow));
|
||||||
// PCF filtering
|
|
||||||
enablePCF = 1;
|
enablePCF = 1;
|
||||||
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.sceneShadowPCF));
|
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.sceneShadowPCF));
|
||||||
|
|
||||||
|
|
@ -816,7 +891,6 @@ public:
|
||||||
updateCascades();
|
updateCascades();
|
||||||
prepareShadowMaps();
|
prepareShadowMaps();
|
||||||
prepareUniformBuffers();
|
prepareUniformBuffers();
|
||||||
setupDescriptorPool();
|
|
||||||
setupLayoutsAndDescriptors();
|
setupLayoutsAndDescriptors();
|
||||||
preparePipelines();
|
preparePipelines();
|
||||||
buildCommandBuffers();
|
buildCommandBuffers();
|
||||||
|
|
@ -845,10 +919,6 @@ public:
|
||||||
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)
|
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)
|
||||||
{
|
{
|
||||||
if (overlay->header("Settings")) {
|
if (overlay->header("Settings")) {
|
||||||
if (overlay->comboBox("Scenes", &sceneIndex, sceneNames)) {
|
|
||||||
buildCommandBuffers();
|
|
||||||
buildOffscreenCommandBuffer();
|
|
||||||
}
|
|
||||||
if (overlay->sliderFloat("Split lambda", &cascadeSplitLambda, 0.1f, 1.0f)) {
|
if (overlay->sliderFloat("Split lambda", &cascadeSplitLambda, 0.1f, 1.0f)) {
|
||||||
updateCascades();
|
updateCascades();
|
||||||
updateUniformBuffers();
|
updateUniformBuffers();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue