diff --git a/include/gfx.h b/include/gfx.h index 41f1c80..da4ba3e 100644 --- a/include/gfx.h +++ b/include/gfx.h @@ -119,8 +119,8 @@ struct PipelineInfo { std::string vert_shader_path; std::string frag_shader_path; VertexFormat vertex_format; + CullMode face_cull_mode; bool alpha_blending; - bool backface_culling; bool write_z; bool line_primitives; // false for triangles, true for lines std::vector descriptor_set_layouts; diff --git a/include/renderer.h b/include/renderer.h index 33237a9..07e2a38 100644 --- a/include/renderer.h +++ b/include/renderer.h @@ -85,8 +85,12 @@ class Renderer : private ApplicationComponent { */ // in vertex shader - UniformDescriptor global_uniform; // rarely updates; set 0 - UniformDescriptor frame_uniform; // updates once per frame; set 1 + struct GlobalUniformData { + glm::mat4 proj; + glm::mat4 lightSpaceMatrix; + }; + UniformDescriptor global_uniform; // rarely updates; set 0 binding 0 + UniformDescriptor frame_uniform; // updates once per frame; set 1 binding 0 // in fragment shader const gfx::DescriptorSetLayout* material_set_layout; // set 2; set bound per material @@ -106,6 +110,9 @@ class Renderer : private ApplicationComponent { const gfx::Pipeline* skybox_pipeline = nullptr; const gfx::Buffer* skybox_buffer = nullptr; + gfx::Image* shadow_map = nullptr; + const gfx::Sampler* shadow_map_sampler = nullptr; + void DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& render_list); }; diff --git a/res/engine/shaders/fancy.frag b/res/engine/shaders/fancy.frag index abea1ac..0510c20 100644 --- a/res/engine/shaders/fancy.frag +++ b/res/engine/shaders/fancy.frag @@ -4,6 +4,7 @@ #define PI_INV 0.31830988618379067153776752674503 layout(set = 0, binding = 1) uniform samplerCube globalSetSkybox; +layout(set = 0, binding = 2) uniform sampler2D globalSetShadowmap; layout(set = 2, binding = 0) uniform sampler2D materialSetAlbedoSampler; layout(set = 2, binding = 1) uniform sampler2D materialSetNormalSampler; @@ -16,6 +17,7 @@ layout(location = 3) in vec3 fragLightPosTangentSpace; layout(location = 4) in vec3 fragNormWorldSpace; layout(location = 5) in vec3 fragViewPosWorldSpace; layout(location = 6) in vec3 fragPosWorldSpace; +layout(location = 7) in vec4 fragPosLightSpace; layout(location = 0) out vec4 outColor; @@ -81,5 +83,13 @@ void main() { vec3 ambient_light = vec3(0.09082, 0.13281, 0.18164); lighting += mix(ambient_light, texture(globalSetSkybox, R).rgb, metallic) * ao * diffuse_brdf; // this is NOT physically-based, it just looks cool + // perform perspective divide + vec3 projCoords = fragPosLightSpace.xyz; + projCoords.x = projCoords.x * 0.5 + 0.5; + projCoords.y = projCoords.y * 0.5 + 0.5; + float closestDepth = texture(globalSetShadowmap, projCoords.xy).r; + float currentDepth = projCoords.z; + float shadow = currentDepth > closestDepth ? 1.0 : 0.0; outColor = vec4(min(emission + lighting, 1.0), 1.0); + //outColor = vec4(shadow, 0.0, 0.0, 1.0); } diff --git a/res/engine/shaders/fancy.vert b/res/engine/shaders/fancy.vert index fcb99d2..5fadbc5 100644 --- a/res/engine/shaders/fancy.vert +++ b/res/engine/shaders/fancy.vert @@ -2,6 +2,7 @@ layout(set = 0, binding = 0) uniform GlobalSetUniformBuffer { mat4 proj; + mat4 lightSpaceMatrix; } globalSetUniformBuffer; layout(set = 1, binding = 0) uniform FrameSetUniformBuffer { @@ -24,6 +25,7 @@ layout(location = 3) out vec3 fragLightPosTangentSpace; layout(location = 4) out vec3 fragNormWorldSpace; layout(location = 5) out vec3 fragViewPosWorldSpace; layout(location = 6) out vec3 fragPosWorldSpace; +layout(location = 7) out vec4 fragPosLightSpace; void main() { vec4 worldPosition = constants.model * vec4(inPosition, 1.0); @@ -43,5 +45,7 @@ void main() { fragViewPosWorldSpace = vec3(inverse(frameSetUniformBuffer.view) * vec4(0.0, 0.0, 0.0, 1.0)); fragPosWorldSpace = worldPosition.xyz; + fragPosLightSpace = globalSetUniformBuffer.lightSpaceMatrix * vec4(worldPosition.xyz, 1.0); + gl_Position.y *= -1.0; } diff --git a/res/engine/shaders/skybox.vert b/res/engine/shaders/skybox.vert index d8cda9b..e509a4e 100644 --- a/res/engine/shaders/skybox.vert +++ b/res/engine/shaders/skybox.vert @@ -2,6 +2,7 @@ layout(set = 0, binding = 0) uniform GlobalSetUniformBuffer { mat4 proj; + mat4 lightSpaceMatrix; } globalSetUniformBuffer; layout(set = 1, binding = 0) uniform FrameSetUniformBuffer { diff --git a/src/gfx_device_vulkan.cpp b/src/gfx_device_vulkan.cpp index de6a6fa..d8cf1cd 100644 --- a/src/gfx_device_vulkan.cpp +++ b/src/gfx_device_vulkan.cpp @@ -176,12 +176,12 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type) [[maybe_unused]] static VkSamplerAddressMode getSamplerAddressMode(gfx::WrapMode mode) { switch (mode) { - case gfx::WrapMode::kRepeat: - return VK_SAMPLER_ADDRESS_MODE_REPEAT; - case gfx::WrapMode::kMirroredRepeat: - return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; - case gfx::WrapMode::kClampToEdge: - return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + case gfx::WrapMode::kRepeat: + return VK_SAMPLER_ADDRESS_MODE_REPEAT; + case gfx::WrapMode::kMirroredRepeat: + return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; + case gfx::WrapMode::kClampToEdge: + return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; } throw std::runtime_error("Unknown wrap mode"); } @@ -189,10 +189,10 @@ static VkBufferUsageFlagBits getBufferUsageFlag(gfx::BufferType type) [[maybe_unused]] static VkSamplerMipmapMode getSamplerMipmapMode(gfx::Filter filter) { switch (filter) { - case gfx::Filter::kLinear: - return VK_SAMPLER_MIPMAP_MODE_LINEAR; - case gfx::Filter::kNearest: - return VK_SAMPLER_MIPMAP_MODE_NEAREST; + case gfx::Filter::kLinear: + return VK_SAMPLER_MIPMAP_MODE_LINEAR; + case gfx::Filter::kNearest: + return VK_SAMPLER_MIPMAP_MODE_NEAREST; } throw std::runtime_error("Unknown filter"); } @@ -235,7 +235,7 @@ static VkShaderStageFlags getShaderStageFlags(gfx::ShaderStageFlags::Flags flags return out; } -[[maybe_unused]] static VkCullModeFlags getCullModeFlags(gfx::CullMode mode) +static VkCullModeFlags getCullModeFlags(gfx::CullMode mode) { switch (mode) { case gfx::CullMode::kCullNone: @@ -254,12 +254,12 @@ static VkShaderStageFlags getShaderStageFlags(gfx::ShaderStageFlags::Flags flags static VkFormat getImageFormat(gfx::ImageFormat format) { switch (format) { - case gfx::ImageFormat::kLinear: - return VK_FORMAT_R8G8B8A8_UNORM; - case gfx::ImageFormat::kSRGB: - return VK_FORMAT_R8G8B8A8_SRGB; - default: - throw std::runtime_error("Unknown image format"); + case gfx::ImageFormat::kLinear: + return VK_FORMAT_R8G8B8A8_UNORM; + case gfx::ImageFormat::kSRGB: + return VK_FORMAT_R8G8B8A8_SRGB; + default: + throw std::runtime_error("Unknown image format"); } } @@ -646,7 +646,7 @@ gfx::DrawBuffer* GFXDevice::BeginRender() VKCHECK(res); /* perform any pending uniform buffer writes */ - VKCHECK(vkResetCommandPool(pimpl->device.device, frameData.transferPool, 0)); + VKCHECK(vkResetCommandPool(pimpl->device.device, frameData.transferPool, 0)); // TODO: possibly delete this VkCommandBufferBeginInfo transferBeginInfo{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -658,36 +658,64 @@ gfx::DrawBuffer* GFXDevice::BeginRender() // transfer cmds... - std::vector barriers{}; - for (gfx::UniformBuffer* uniformBuffer : pimpl->write_queues[currentFrameIndex].uniform_buffer_writes) { - VkBufferCopy copyRegion{}; - copyRegion.srcOffset = 0; - copyRegion.dstOffset = 0; - copyRegion.size = uniformBuffer->stagingBuffer.size; - vkCmdCopyBuffer(frameData.transferBuf, uniformBuffer->stagingBuffer.buffer, uniformBuffer->gpuBuffers[currentFrameIndex].buffer, 1, ©Region); - - VkBufferMemoryBarrier2& barrier = barriers.emplace_back(); - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2; - barrier.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT; - barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; - barrier.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT; - barrier.dstAccessMask = 0; - barrier.srcQueueFamilyIndex = pimpl->device.queues.transferQueueFamily; - barrier.dstQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; - barrier.buffer = uniformBuffer->gpuBuffers[currentFrameIndex].buffer; - barrier.offset = 0; - barrier.size = uniformBuffer->gpuBuffers[currentFrameIndex].size; + if (pimpl->FRAMECOUNT >= FRAMES_IN_FLIGHT) { // cannot (and don't need to) do ownership transfer on first frame[s] + // acquire ownership of buffers + std::vector acquireBarriers{}; + for (gfx::UniformBuffer* uniformBuffer : pimpl->write_queues[currentFrameIndex].uniform_buffer_writes) { + VkBufferMemoryBarrier2& barrier = acquireBarriers.emplace_back(); + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2; + barrier.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT; + barrier.srcAccessMask = 0; + barrier.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT; + barrier.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; + barrier.srcQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; + barrier.dstQueueFamilyIndex = pimpl->device.queues.transferQueueFamily; + barrier.buffer = uniformBuffer->gpuBuffers[currentFrameIndex].buffer; + barrier.offset = 0; + barrier.size = uniformBuffer->gpuBuffers[currentFrameIndex].size; + } + VkDependencyInfo dependencyInfo{}; + dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; + dependencyInfo.bufferMemoryBarrierCount = (uint32_t)acquireBarriers.size(); + dependencyInfo.pBufferMemoryBarriers = acquireBarriers.data(); + vkCmdPipelineBarrier2(frameData.transferBuf, &dependencyInfo); } - pimpl->write_queues[currentFrameIndex].uniform_buffer_writes.clear(); - VkDependencyInfo dependencyInfo{}; - dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; - dependencyInfo.bufferMemoryBarrierCount = (uint32_t)barriers.size(); - dependencyInfo.pBufferMemoryBarriers = barriers.data(); - vkCmdPipelineBarrier2(frameData.transferBuf, &dependencyInfo); + { + // copy stagings buffers to GPU buffer + for (gfx::UniformBuffer* uniformBuffer : pimpl->write_queues[currentFrameIndex].uniform_buffer_writes) { + VkBufferCopy copyRegion{}; + copyRegion.srcOffset = 0; + copyRegion.dstOffset = 0; + copyRegion.size = uniformBuffer->stagingBuffer.size; + vkCmdCopyBuffer(frameData.transferBuf, uniformBuffer->stagingBuffer.buffer, uniformBuffer->gpuBuffers[currentFrameIndex].buffer, 1, ©Region); + } + } + + { + // release buffers to graphics queue + std::vector releaseBarriers{}; + for (gfx::UniformBuffer* uniformBuffer : pimpl->write_queues[currentFrameIndex].uniform_buffer_writes) { + VkBufferMemoryBarrier2& barrier = releaseBarriers.emplace_back(); + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2; + barrier.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT; + barrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; + barrier.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT; + barrier.dstAccessMask = 0; + barrier.srcQueueFamilyIndex = pimpl->device.queues.transferQueueFamily; + barrier.dstQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; + barrier.buffer = uniformBuffer->gpuBuffers[currentFrameIndex].buffer; + barrier.offset = 0; + barrier.size = uniformBuffer->gpuBuffers[currentFrameIndex].size; + } + VkDependencyInfo dependencyInfo{}; + dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; + dependencyInfo.bufferMemoryBarrierCount = (uint32_t)releaseBarriers.size(); + dependencyInfo.pBufferMemoryBarriers = releaseBarriers.data(); + vkCmdPipelineBarrier2(frameData.transferBuf, &dependencyInfo); + } VKCHECK(vkEndCommandBuffer(frameData.transferBuf)); - VkSubmitInfo transferSubmitInfo{ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = nullptr, @@ -733,13 +761,25 @@ gfx::DrawBuffer* GFXDevice::BeginRender() { // RECORDING - /* change barriers to perform a queue ownership acquire operation */ - for (VkBufferMemoryBarrier2& barrier : barriers) { + // acquire ownership of buffers + std::vector acquireBarriers{}; + for (gfx::UniformBuffer* uniformBuffer : pimpl->write_queues[currentFrameIndex].uniform_buffer_writes) { + VkBufferMemoryBarrier2& barrier = acquireBarriers.emplace_back(); + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2; barrier.srcStageMask = VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT; barrier.srcAccessMask = 0; barrier.dstStageMask = VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT; barrier.dstAccessMask = VK_ACCESS_2_UNIFORM_READ_BIT; + barrier.srcQueueFamilyIndex = pimpl->device.queues.transferQueueFamily; + barrier.dstQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; + barrier.buffer = uniformBuffer->gpuBuffers[currentFrameIndex].buffer; + barrier.offset = 0; + barrier.size = uniformBuffer->gpuBuffers[currentFrameIndex].size; } + VkDependencyInfo dependencyInfo{}; + dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; + dependencyInfo.bufferMemoryBarrierCount = (uint32_t)acquireBarriers.size(); + dependencyInfo.pBufferMemoryBarriers = acquireBarriers.data(); vkCmdPipelineBarrier2(frameData.drawBuf, &dependencyInfo); std::array clearValues{}; // Using same value for all components enables @@ -801,6 +841,27 @@ void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer) vkCmdEndRenderPass(drawBuffer->frameData.drawBuf); + // transfer ownership of uniform buffers back to transfer queue + std::vector releaseBarriers{}; + for (gfx::UniformBuffer* uniformBuffer : pimpl->write_queues[drawBuffer->currentFrameIndex].uniform_buffer_writes) { + VkBufferMemoryBarrier2& barrier = releaseBarriers.emplace_back(); + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2; + barrier.srcStageMask = VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT; + barrier.srcAccessMask = VK_ACCESS_2_UNIFORM_READ_BIT; + barrier.dstStageMask = VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT; + barrier.dstAccessMask = 0; + barrier.srcQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; + barrier.dstQueueFamilyIndex = pimpl->device.queues.transferQueueFamily; + barrier.buffer = uniformBuffer->gpuBuffers[drawBuffer->currentFrameIndex].buffer; + barrier.offset = 0; + barrier.size = uniformBuffer->gpuBuffers[drawBuffer->currentFrameIndex].size; + } + VkDependencyInfo dependencyInfo{}; + dependencyInfo.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; + dependencyInfo.bufferMemoryBarrierCount = (uint32_t)releaseBarriers.size(); + dependencyInfo.pBufferMemoryBarriers = releaseBarriers.data(); + vkCmdPipelineBarrier2(drawBuffer->frameData.drawBuf, &dependencyInfo); + res = vkEndCommandBuffer(drawBuffer->frameData.drawBuf); VKCHECK(res); @@ -846,6 +907,9 @@ void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer) else if (res != VK_SUCCESS) throw std::runtime_error("Failed to queue present! Code: " + std::to_string(res)); + // clear write queue + pimpl->write_queues[drawBuffer->currentFrameIndex].uniform_buffer_writes.clear(); + pimpl->FRAMECOUNT++; delete drawBuffer; @@ -1011,12 +1075,7 @@ gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info) rasterizer.rasterizerDiscardEnable = VK_FALSE; // enabling this will not run the fragment shaders at all rasterizer.polygonMode = VK_POLYGON_MODE_FILL; rasterizer.lineWidth = 1.0f; - if (info.backface_culling == true) { - rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - } - else { - rasterizer.cullMode = VK_CULL_MODE_NONE; - } + rasterizer.cullMode = converters::getCullModeFlags(info.face_cull_mode); rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rasterizer.depthBiasEnable = VK_FALSE; rasterizer.depthBiasConstantFactor = 0.0f; // ignored @@ -1488,8 +1547,8 @@ gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat inpu beforeCopyBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; beforeCopyBarrier.srcStageMask = VK_PIPELINE_STAGE_2_NONE; beforeCopyBarrier.srcAccessMask = VK_ACCESS_2_NONE; - beforeCopyBarrier.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT; - beforeCopyBarrier.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; + beforeCopyBarrier.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT | VK_PIPELINE_STAGE_2_BLIT_BIT; // all subresources will be COPYed or BLITed to next + beforeCopyBarrier.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; // Image must be TRANSFER_DST_OPTIMAL before either stage performs a TRANSFER_WRITE beforeCopyBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; beforeCopyBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; beforeCopyBarrier.srcQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; @@ -1528,10 +1587,11 @@ gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat inpu // Must happen after TRANSFER_WRITE in the COPY stage and BLIT stage. VkImageMemoryBarrier2 beforeBlitBarrier{}; beforeBlitBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; - beforeBlitBarrier.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT | VK_PIPELINE_STAGE_2_BLIT_BIT; - beforeBlitBarrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; - beforeBlitBarrier.dstStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT; - beforeBlitBarrier.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT; + beforeBlitBarrier.srcStageMask = + VK_PIPELINE_STAGE_2_COPY_BIT | VK_PIPELINE_STAGE_2_BLIT_BIT; // previous mip level was either just COPYed to or just BLITed to + beforeBlitBarrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; // these actions were TRANSFER_WRITEs + beforeBlitBarrier.dstStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT; // the image will be BLITed from next + beforeBlitBarrier.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT; // this is a TRANSFER_READ beforeBlitBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; beforeBlitBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; beforeBlitBarrier.srcQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; @@ -1570,9 +1630,9 @@ gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat inpu VkImageMemoryBarrier2 afterBlitBarrier{}; afterBlitBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; afterBlitBarrier.srcStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT; - afterBlitBarrier.srcAccessMask = 0; + afterBlitBarrier.srcAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT; // previous mip level was just READ from in a BLIT afterBlitBarrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; - afterBlitBarrier.dstAccessMask = VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_2_SHADER_READ_BIT; + afterBlitBarrier.dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT; // it will next be sampled in a frag shader afterBlitBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; afterBlitBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; afterBlitBarrier.srcQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; @@ -1597,10 +1657,17 @@ gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat inpu // barrier: (mipLevels - 1) TRANSFER_DST_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL VkImageMemoryBarrier2 finalBlitBarrier{}; finalBlitBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; - finalBlitBarrier.srcStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT | VK_PIPELINE_STAGE_2_COPY_BIT; + if (mipLevels == 1) { + // if no mipmaps were generated, the image was just COPYed to with a WRITE + finalBlitBarrier.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT; // the final mip level was BLITed to with a WRITE + } + else { + // mips were generated, therefore last mip level was just BLITed to + finalBlitBarrier.srcStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT; + } finalBlitBarrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; finalBlitBarrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; - finalBlitBarrier.dstAccessMask = VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_2_SHADER_READ_BIT; + finalBlitBarrier.dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT; finalBlitBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; finalBlitBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; finalBlitBarrier.srcQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; @@ -1649,7 +1716,7 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm if (pimpl->FRAMECOUNT != 0) abort(); // TODO. This is annoying gfx::Image* out = new gfx::Image{}; - + uint32_t mipLevels = static_cast(std::floor(std::log2(std::max(w, h)))) + 1; VkFormat imageFormat = converters::getImageFormat(input_format); @@ -1733,7 +1800,7 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; VKCHECK(vkBeginCommandBuffer(commandBuffer, &beginInfo)); - // barrier: (all mip levels): UNDEFINED -> TRANSFER_DST_OPTIMAL + // barrier: (all mip levels, all faces): UNDEFINED -> TRANSFER_DST_OPTIMAL // Used for copying staging buffer AND blitting mipmaps // Must happen before vkCmdCopyBufferToImage performs a TRANSFER_WRITE in // the COPY stage. @@ -1741,7 +1808,8 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm beforeCopyBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; beforeCopyBarrier.srcStageMask = VK_PIPELINE_STAGE_2_NONE; beforeCopyBarrier.srcAccessMask = VK_ACCESS_2_NONE; - beforeCopyBarrier.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT; + beforeCopyBarrier.dstStageMask = + VK_PIPELINE_STAGE_2_COPY_BIT | VK_PIPELINE_STAGE_2_BLIT_BIT; // all parts of the image will be either TRANSFERed to or BLITed to next beforeCopyBarrier.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; beforeCopyBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; beforeCopyBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; @@ -1782,10 +1850,12 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm // Must happen after TRANSFER_WRITE in the COPY stage and BLIT stage. VkImageMemoryBarrier2 beforeBlitBarrier{}; beforeBlitBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; - beforeBlitBarrier.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT | VK_PIPELINE_STAGE_2_BLIT_BIT; - beforeBlitBarrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; - beforeBlitBarrier.dstStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT; - beforeBlitBarrier.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT; + beforeBlitBarrier.srcStageMask = + VK_PIPELINE_STAGE_2_COPY_BIT | VK_PIPELINE_STAGE_2_BLIT_BIT; // subresource was either just copied to or just blitted to + beforeBlitBarrier.srcAccessMask = + VK_ACCESS_2_TRANSFER_WRITE_BIT; // wait until CopyBufferToImage and BlitImage have performed TRANSFER_WRITE on subresource + beforeBlitBarrier.dstStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT; // subresource is going to be blitted from + beforeBlitBarrier.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT; // subresource will be READ from during the blit beforeBlitBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; beforeBlitBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; beforeBlitBarrier.srcQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; @@ -1807,16 +1877,16 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm blit.srcSubresource.mipLevel = i - 1; blit.srcSubresource.baseArrayLayer = face; blit.srcSubresource.layerCount = 1; - blit.srcOffsets[0] = { 0, 0, 0 }; - blit.srcOffsets[1] = { mipWidth, mipHeight, 1 }; + blit.srcOffsets[0] = {0, 0, 0}; + blit.srcOffsets[1] = {mipWidth, mipHeight, 1}; blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blit.dstSubresource.mipLevel = i; blit.dstSubresource.baseArrayLayer = face; blit.dstSubresource.layerCount = 1; - blit.dstOffsets[0] = { 0, 0, 0 }; - blit.dstOffsets[1] = { mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 }; + blit.dstOffsets[0] = {0, 0, 0}; + blit.dstOffsets[1] = {mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1}; vkCmdBlitImage(commandBuffer, out->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, out->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, - VK_FILTER_LINEAR); + VK_FILTER_LINEAR); // WRITE-AFTER-WRITE error here // barrier: (i - 1) TRANSFER_SRC_OPTIMAL -> SHADER_READ_ONLY_OPTIMALs // Must happen after usage in the BLIT stage. @@ -1824,9 +1894,9 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm VkImageMemoryBarrier2 afterBlitBarrier{}; afterBlitBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; afterBlitBarrier.srcStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT; - afterBlitBarrier.srcAccessMask = 0; + afterBlitBarrier.srcAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT; afterBlitBarrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; - afterBlitBarrier.dstAccessMask = VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_2_SHADER_READ_BIT; + afterBlitBarrier.dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT; afterBlitBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; afterBlitBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; afterBlitBarrier.srcQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; @@ -1851,10 +1921,10 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm // barrier: (mipLevels - 1) TRANSFER_DST_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL VkImageMemoryBarrier2 finalBlitBarrier{}; finalBlitBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; - finalBlitBarrier.srcStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT | VK_PIPELINE_STAGE_2_COPY_BIT; + finalBlitBarrier.srcStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT; finalBlitBarrier.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT; finalBlitBarrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; - finalBlitBarrier.dstAccessMask = VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_2_SHADER_READ_BIT; + finalBlitBarrier.dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT; finalBlitBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; finalBlitBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; finalBlitBarrier.srcQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily; @@ -1870,7 +1940,6 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm afterBlitDependency.imageMemoryBarrierCount = 1; afterBlitDependency.pImageMemoryBarriers = &finalBlitBarrier; vkCmdPipelineBarrier2(commandBuffer, &afterBlitDependency); - } VKCHECK(vkEndCommandBuffer(commandBuffer)); @@ -1893,7 +1962,6 @@ gfx::Image* GFXDevice::CreateImageCubemap(uint32_t w, uint32_t h, gfx::ImageForm return out; } - void GFXDevice::DestroyImage(const gfx::Image* image) { assert(image != nullptr); @@ -1905,7 +1973,7 @@ void GFXDevice::DestroyImage(const gfx::Image* image) const gfx::Sampler* GFXDevice::CreateSampler(const gfx::SamplerInfo& info) { gfx::Sampler* out = new gfx::Sampler{}; - + VkSamplerCreateInfo samplerInfo{}; samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; samplerInfo.magFilter = converters::getFilter(info.magnify); diff --git a/src/renderer.cpp b/src/renderer.cpp index bb926fe..7324d27 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -26,13 +26,21 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati auto& binding1 = globalSetBindings.emplace_back(); binding1.descriptor_type = gfx::DescriptorType::kCombinedImageSampler; binding1.stage_flags = gfx::ShaderStageFlags::kFragment; + auto& binding2 = globalSetBindings.emplace_back(); + binding2.descriptor_type = gfx::DescriptorType::kCombinedImageSampler; + binding2.stage_flags = gfx::ShaderStageFlags::kFragment; } global_uniform.layout = device_->CreateDescriptorSetLayout(globalSetBindings); global_uniform.set = device_->AllocateDescriptorSet(global_uniform.layout); - global_uniform.uniform_buffer_data.data = glm::mat4{1.0f}; + global_uniform.uniform_buffer_data.data.proj = glm::mat4{1.0f}; + const glm::vec3 light_location{ -0.4278, 0.7923, 0.43502 }; + const glm::mat4 light_proj = glm::orthoRH_ZO(-32.0f, 32.0f, -32.0f, 32.0f, -100.0f, 100.0f); + const glm::mat4 light_view = glm::lookAtRH(light_location, glm::vec3{ 0.0f, 0.0f, 0.0f }, glm::vec3{ 0.0f, 0.0f, 1.0f }); + global_uniform.uniform_buffer_data.data.lightSpaceMatrix = light_proj * light_view; global_uniform.uniform_buffer = device_->CreateUniformBuffer(sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data); device_->UpdateDescriptorUniformBuffer(global_uniform.set, 0, global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data)); // binding1 is updated towards the end of the constructor once the skybox texture is loaded + // binding2 is updated just after that std::vector frameSetBindings; { @@ -68,30 +76,29 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati debug_pipeline_info.frag_shader_path = GetResourcePath("engine/shaders/debug.frag"); debug_pipeline_info.vertex_format = debug_vertex_format; debug_pipeline_info.alpha_blending = false; - debug_pipeline_info.backface_culling = false; // probably ignored for line rendering - debug_pipeline_info.write_z = false; // lines don't need the depth buffer + debug_pipeline_info.face_cull_mode = gfx::CullMode::kCullNone; // probably ignored for line rendering + debug_pipeline_info.write_z = false; // lines don't need the depth buffer // debug_pipeline_info.descriptor_set_layouts = empty; debug_pipeline_info.line_primitives = true; debug_rendering_things_.pipeline = device_->CreatePipeline(debug_pipeline_info); } - // create the skybox cubemap + // create the skybox cubemap and update global skybox combined-image-sampler { constexpr uint32_t cubemap_w = 2048; constexpr uint32_t cubemap_h = 2048; int w{}, h{}; std::array>, 6> face_unq_ptrs{}; std::array face_unsafe_ptrs{}; - + for (int face = 0; face < 6; ++face) { std::string path = std::string("engine/textures/skybox") + std::to_string(face) + std::string(".jpg"); face_unq_ptrs[face] = util::ReadImageFile(GetResourcePath(path), w, h); if (cubemap_w != w || cubemap_h != h) throw std::runtime_error("Skybox textures must be 512x512!"); face_unsafe_ptrs[face] = face_unq_ptrs[face]->data(); } - - + skybox_cubemap = device_->CreateImageCubemap(cubemap_w, cubemap_h, gfx::ImageFormat::kSRGB, face_unsafe_ptrs); gfx::SamplerInfo sampler_info{}; sampler_info.magnify = gfx::Filter::kLinear; @@ -102,6 +109,8 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati sampler_info.wrap_w = gfx::WrapMode::kClampToEdge; sampler_info.anisotropic_filtering = true; skybox_sampler = device_->CreateSampler(sampler_info); + + device_->UpdateDescriptorCombinedImageSampler(global_uniform.set, 1, skybox_cubemap, skybox_sampler); } // create skybox shader @@ -115,15 +124,13 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati pipeline_info.frag_shader_path = GetResourcePath("engine/shaders/skybox.frag"); pipeline_info.vertex_format = vertex_format; pipeline_info.alpha_blending = false; - pipeline_info.backface_culling = true; + pipeline_info.face_cull_mode = gfx::CullMode::kCullBack; pipeline_info.write_z = false; pipeline_info.line_primitives = false; pipeline_info.descriptor_set_layouts.push_back(GetGlobalSetLayout()); pipeline_info.descriptor_set_layouts.push_back(GetFrameSetLayout()); skybox_pipeline = device_->CreatePipeline(pipeline_info); - - device_->UpdateDescriptorCombinedImageSampler(global_uniform.set, 1, skybox_cubemap, skybox_sampler); } // create skybox vertex buffer @@ -136,40 +143,40 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati v.push_back({2.0f, 0.0f, 2.0f}); v.push_back({0.0f, 0.0f, 2.0f}); // back - v.push_back({2.0f, 2.0f, 2.0f }); - v.push_back({ 2.0f, 2.0f, 0.0f}); + v.push_back({2.0f, 2.0f, 2.0f}); + v.push_back({2.0f, 2.0f, 0.0f}); v.push_back({0.0f, 2.0f, 0.0f}); v.push_back({0.0f, 2.0f, 0.0f}); - v.push_back({0.0f, 2.0f, 2.0f }); - v.push_back({ 2.0f, 2.0f, 2.0f }); + v.push_back({0.0f, 2.0f, 2.0f}); + v.push_back({2.0f, 2.0f, 2.0f}); // left - v.push_back({0.0f, 2.0f, 2.0f }); + v.push_back({0.0f, 2.0f, 2.0f}); v.push_back({0.0f, 2.0f, 0.0f}); v.push_back({0.0f, 0.0f, 0.0f}); v.push_back({0.0f, 0.0f, 0.0f}); - v.push_back({0.0f, 0.0f, 2.0f }); - v.push_back({0.0f, 2.0f, 2.0f }); + v.push_back({0.0f, 0.0f, 2.0f}); + v.push_back({0.0f, 2.0f, 2.0f}); // right - v.push_back({ 2.0f, 0.0f, 2.0f }); - v.push_back({ 2.0f, 0.0f, 0.0f}); - v.push_back({ 2.0f, 2.0f, 0.0f}); - v.push_back({ 2.0f, 2.0f, 0.0f}); - v.push_back({ 2.0f, 2.0f, 2.0f }); - v.push_back({ 2.0f, 0.0f, 2.0f }); + v.push_back({2.0f, 0.0f, 2.0f}); + v.push_back({2.0f, 0.0f, 0.0f}); + v.push_back({2.0f, 2.0f, 0.0f}); + v.push_back({2.0f, 2.0f, 0.0f}); + v.push_back({2.0f, 2.0f, 2.0f}); + v.push_back({2.0f, 0.0f, 2.0f}); // top - v.push_back({0.0f, 2.0f, 2.0f }); - v.push_back({0.0f, 0.0f, 2.0f }); - v.push_back({ 2.0f, 0.0f, 2.0f }); - v.push_back({ 2.0f, 0.0f, 2.0f }); - v.push_back({ 2.0f, 2.0f, 2.0f }); - v.push_back({0.0f, 2.0f, 2.0f }); + v.push_back({0.0f, 2.0f, 2.0f}); + v.push_back({0.0f, 0.0f, 2.0f}); + v.push_back({2.0f, 0.0f, 2.0f}); + v.push_back({2.0f, 0.0f, 2.0f}); + v.push_back({2.0f, 2.0f, 2.0f}); + v.push_back({0.0f, 2.0f, 2.0f}); // bottom - v.push_back({ 2.0f, 2.0f, 0.0f}); - v.push_back({ 2.0f, 0.0f, 0.0f}); + v.push_back({2.0f, 2.0f, 0.0f}); + v.push_back({2.0f, 0.0f, 0.0f}); v.push_back({0.0f, 0.0f, 0.0f}); v.push_back({0.0f, 0.0f, 0.0f}); v.push_back({0.0f, 2.0f, 0.0f}); - v.push_back({ 2.0f, 2.0f, 0.0f}); + v.push_back({2.0f, 2.0f, 0.0f}); for (glm::vec3& pos : v) { pos.x -= 1.0f; pos.y -= 1.0f; @@ -181,10 +188,31 @@ Renderer::Renderer(Application& app, gfx::GraphicsSettings settings) : Applicati skybox_buffer = device_->CreateBuffer(gfx::BufferType::kVertex, v.size() * sizeof(glm::vec3), v.data()); } + + // shadow mapping... + { + int w{}, h{}; + auto shadowmap_image = util::ReadImageFile(GetResourcePath("textures/shadow_map.png"), w, h); + shadow_map = device_->CreateImage(w, h, gfx::ImageFormat::kLinear, shadowmap_image->data()); + gfx::SamplerInfo sampler_info{}; + sampler_info.magnify = gfx::Filter::kLinear; + sampler_info.minify = gfx::Filter::kLinear; + sampler_info.mipmap = gfx::Filter::kLinear; // trilinear is apparently good for shadow maps + sampler_info.wrap_u = gfx::WrapMode::kClampToEdge; + sampler_info.wrap_v = gfx::WrapMode::kClampToEdge; + sampler_info.wrap_w = gfx::WrapMode::kClampToEdge; + sampler_info.anisotropic_filtering = false; // Copilot says not to use aniso for shadow maps + shadow_map_sampler = device_->CreateSampler(sampler_info); + + device_->UpdateDescriptorCombinedImageSampler(global_uniform.set, 2, shadow_map, shadow_map_sampler); + } }; Renderer::~Renderer() { + device_->DestroySampler(shadow_map_sampler); + device_->DestroyImage(shadow_map); + device_->DestroyBuffer(skybox_buffer); device_->DestroyPipeline(skybox_pipeline); device_->DestroySampler(skybox_sampler); @@ -213,15 +241,19 @@ void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform) const glm::mat4 proj_matrix = glm::perspectiveRH_ZO(camera_settings_.vertical_fov_radians, viewport_aspect_ratio_, camera_settings_.clip_near, camera_settings_.clip_far); /* update SET 0 (rarely changing uniforms)*/ - global_uniform.uniform_buffer_data.data = proj_matrix; + global_uniform.uniform_buffer_data.data.proj = proj_matrix; device_->WriteUniformBuffer(global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data); } - // set camera view matrix uniform - /* update SET 1 (per frame uniforms) */ const glm::mat4 view_matrix = glm::inverse(camera_transform); frame_uniform.uniform_buffer_data.data = view_matrix; device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data); + + // override with light matrix + frame_uniform.uniform_buffer_data.data = glm::mat4{1.0f}; + device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data); + global_uniform.uniform_buffer_data.data.proj = global_uniform.uniform_buffer_data.data.lightSpaceMatrix; + device_->WriteUniformBuffer(global_uniform.uniform_buffer, 0, sizeof(global_uniform.uniform_buffer_data), &global_uniform.uniform_buffer_data); } void Renderer::Render(const RenderList* static_list, const RenderList* dynamic_list, const std::vector& debug_lines) @@ -260,8 +292,8 @@ void Renderer::Render(const RenderList* static_list, const RenderList* dynamic_l device_->CmdBindPipeline(draw_buffer, debug_rendering_things_.pipeline); DebugPush push{}; for (const Line& l : debug_lines) { - push.pos1 = global_uniform.uniform_buffer_data.data * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos1, 1.0f); - push.pos2 = global_uniform.uniform_buffer_data.data * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos2, 1.0f); + push.pos1 = global_uniform.uniform_buffer_data.data.proj * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos1, 1.0f); + push.pos2 = global_uniform.uniform_buffer_data.data.proj * frame_uniform.uniform_buffer_data.data * glm::vec4(l.pos2, 1.0f); push.color = l.color; device_->CmdPushConstants(draw_buffer, debug_rendering_things_.pipeline, 0, sizeof(DebugPush), &push); device_->CmdDraw(draw_buffer, 2, 1, 0, 0); diff --git a/src/resources/shader.cpp b/src/resources/shader.cpp index a00e73b..e643505 100644 --- a/src/resources/shader.cpp +++ b/src/resources/shader.cpp @@ -48,7 +48,7 @@ Shader::Shader(Renderer* renderer, const std::string& vertPath, const std::strin info.frag_shader_path = fragPath; info.vertex_format = vertFormat; info.alpha_blending = settings.alpha_blending; - info.backface_culling = settings.cull_backface; + info.face_cull_mode = settings.cull_backface ? gfx::CullMode::kCullBack : gfx::CullMode::kCullNone; info.write_z = settings.write_z; info.line_primitives = false; info.descriptor_set_layouts.push_back(renderer->GetGlobalSetLayout()); diff --git a/src/util/gltf_loader.cpp b/src/util/gltf_loader.cpp index 9271211..c2abc95 100644 --- a/src/util/gltf_loader.cpp +++ b/src/util/gltf_loader.cpp @@ -555,12 +555,12 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic) // get AABB AABB box{}; - box.min.x = pos_accessor.minValues.at(0); - box.min.y = pos_accessor.minValues.at(1); - box.min.z = pos_accessor.minValues.at(2); - box.max.x = pos_accessor.maxValues.at(0); - box.max.y = pos_accessor.maxValues.at(1); - box.max.z = pos_accessor.maxValues.at(2); + box.min.x = static_cast(pos_accessor.minValues.at(0)); + box.min.y = static_cast(pos_accessor.minValues.at(1)); + box.min.z = static_cast(pos_accessor.minValues.at(2)); + box.max.x = static_cast(pos_accessor.maxValues.at(0)); + box.max.y = static_cast(pos_accessor.maxValues.at(1)); + box.max.z = static_cast(pos_accessor.maxValues.at(2)); primitive_array.emplace_back(engine_mesh, engine_material, box); } diff --git a/src/vulkan/swapchain.cpp b/src/vulkan/swapchain.cpp index 1ccb65b..058de90 100644 --- a/src/vulkan/swapchain.cpp +++ b/src/vulkan/swapchain.cpp @@ -204,17 +204,17 @@ namespace engine { .srcStageMask = VK_PIPELINE_STAGE_NONE, .dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, .dependencyFlags = 0, }, { // Image Layout Transition .srcSubpass = VK_SUBPASS_EXTERNAL, .dstSubpass = 0, - .srcStageMask = VK_PIPELINE_STAGE_NONE, + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, .dependencyFlags = 0, }, }; diff --git a/test/res/textures/shadow_map.png b/test/res/textures/shadow_map.png new file mode 100644 index 0000000..d0b9203 Binary files /dev/null and b/test/res/textures/shadow_map.png differ diff --git a/test/src/game.cpp b/test/src/game.cpp index f790e88..b6ac6f8 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -89,7 +89,7 @@ void PlayGame(GameSettings settings) /* floor */ engine::Entity floor = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/floor.glb")); - main_scene->GetComponent(main_scene->GetEntity("Cube", floor))->visible = false; + //main_scene->GetComponent(main_scene->GetEntity("Cube", floor))->visible = false; engine::Entity monke = engine::util::LoadGLTF(*main_scene, app.GetResourcePath("models/monke.glb")); main_scene->GetComponent(monke)->position.y += 10.0f;