17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-03 01:30:16 +01:00

Replace cubemap scenery reflections with SSR, add Vulkan ray traced reflections

This commit is contained in:
2026-10-25 13:54:49 +01:00
parent 89f11895fc
commit f20b1a3071
45 changed files with 2725 additions and 174 deletions

View File

@@ -190,6 +190,8 @@ std::array<std::array<VkImageView, vk14::bindings::PASS_BINDING_COUNT>, 3> pass_
views[HEADLIGHT_SHADOW_TEX] = (headlights != nullptr ? headlights->view() : scene.headlight_shadow_empty->view());
// the depth of the scene of the main view drawn before its colour, which the contact shadows read
views[SCENE_DEPTH_TEX] = (colour && (false == scene.targets.empty()) && scene.targets.front().scene_depth ? scene.targets.front().scene_depth->view() : scene.depth_empty->view());
// the image of the last frame of the main view, which the screen space reflections take their colour from
views[SSR_HISTORY_TEX] = (colour && (false == scene.targets.empty()) && scene.targets.front().ssr_history ? scene.targets.front().ssr_history->view() : scene.white->view());
}
return result;
}
@@ -303,7 +305,20 @@ bool vulkan14_renderer::init_scene(std::string &Reason)
}
}
VkPushConstantRange const graphicsconstants{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, PUSH_CONSTANTS_SIZE};
scene.scene_layout = vk14::make_pipeline_layout(device, {scene.pass_layout, scene.material_set.layout}, {graphicsconstants}, "scene");
// the ray traced reflections: the scenery around the camera, set RT_SET of the scene, which the shaders of the scene read when they
// were made with REFLECTION_RAYS (vk14::binding_preamble())
std::vector<VkDescriptorSetLayout> scenesets{scene.pass_layout, scene.material_set.layout};
if (ctx.device.raytracing_enabled())
{
scene.raytracing = std::make_unique<vk14::ray_tracing>();
static_assert(RT_SET == 2, "the set of the ray tracing follows the pass set and the material set");
if (false == scene.raytracing->init(ctx.device, ctx.memory, ctx.deletions, frames, Reason))
{
return false;
}
scenesets.push_back(scene.raytracing->layout());
}
scene.scene_layout = vk14::make_pipeline_layout(device, scenesets, {graphicsconstants}, "scene");
if ((scene.scene_layout == VK_NULL_HANDLE) || (false == scene.material_set.create_template(device, scene.scene_layout, "material textures")))
{
Reason = "no layout of the pipelines of the scene";
@@ -386,6 +401,10 @@ bool vulkan14_renderer::init_scene(std::string &Reason)
}
std::uint32_t const white{0xffffffff};
ctx.uploads.upload(scene.white, &white, sizeof(white), {{0, {1, 1, 1}}}, false);
if (scene.raytracing)
{
scene.raytracing->set_white(scene.white->view(), ctx.sampling.repeat_aniso);
}
}
{
vk14::image_desc desc;
@@ -518,6 +537,13 @@ bool vulkan14_renderer::init_scene(std::string &Reason)
{
scene.bloom_format = VK_FORMAT_R16G16B16A16_SFLOAT;
}
// the history of the screen space reflections is copied and filtered by blits
vkGetPhysicalDeviceFormatProperties(ctx.device.physical(), scene.history_format, &properties);
auto const blits{VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT};
if ((properties.optimalTilingFeatures & blits) != blits)
{
scene.history_format = VK_FORMAT_R16G16B16A16_SFLOAT;
}
}
// the formats of the passes which don't depend on the viewport
scene.shadow_formats.depth = VK_FORMAT_D32_SFLOAT;
@@ -737,6 +763,11 @@ void vulkan14_renderer::destroy_scene()
return;
}
destroy_cull();
if (scene.raytracing)
{
scene.raytracing->destroy();
scene.raytracing.reset();
}
scene.lamps.destroy();
scene.terrain.reset();
scene.grass.destroy();
@@ -939,6 +970,7 @@ void vulkan14_renderer::write_pass_sets(vk14::instance_cull *Cull)
write(handle, LOCAL_SHADOW_LAMPS_TEX, nullptr, image(ctx.sampling.shadow, views[LOCAL_SHADOW_LAMPS_TEX]));
write(handle, HEADLIGHT_SHADOW_TEX, nullptr, image(ctx.sampling.shadow, views[HEADLIGHT_SHADOW_TEX]));
write(handle, SCENE_DEPTH_TEX, nullptr, image(ctx.sampling.clamp_nearest, views[SCENE_DEPTH_TEX]));
write(handle, SSR_HISTORY_TEX, nullptr, image(ctx.sampling.clamp_linear, views[SSR_HISTORY_TEX]));
}
vkUpdateDescriptorSets(device, static_cast<std::uint32_t>(writes.size()), writes.data(), 0, nullptr);
}
@@ -1003,6 +1035,19 @@ void vulkan14_renderer::bind_pass_set()
info.pDynamicOffsets = offsets.data();
draw.commands->bind_descriptor_sets2(&info);
draw.set_dirty = false;
// the set of the ray tracing of the frame, which the shaders of the scene made with REFLECTION_RAYS read
if (scene.raytracing)
{
VkDescriptorSet const rtset{scene.raytracing->set(m_context->slot)};
VkBindDescriptorSetsInfo rt{};
rt.sType = VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO;
rt.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
rt.layout = scene.scene_layout;
rt.firstSet = vk14::bindings::RT_SET;
rt.descriptorSetCount = 1;
rt.pDescriptorSets = &rtset;
draw.commands->bind_descriptor_sets2(&rt);
}
}
// the pass set of the colour of the main view bound for the compute kernels (their layouts share set 0 and the push constants),
@@ -1575,6 +1620,13 @@ std::uint32_t vulkan14_renderer::push_draw_block()
std::uint32_t vulkan14_renderer::walk_instances(glm::mat4 const *Modelviews, std::size_t const Count)
{
if (m_rtgather)
{
// noted for the ray tracing: the base is the index of the first of them among those noted
auto const base{static_cast<std::uint32_t>(m_rtinstances.size())};
m_rtinstances.insert(m_rtinstances.end(), Modelviews, Modelviews + Count);
return base;
}
auto &scene{m_context->scene};
auto &instances{scene.instances};
auto const capacity{static_cast<std::size_t>(instances.window / instances.stride) - 1};
@@ -1618,6 +1670,11 @@ void vulkan14_renderer::open_instance_window()
void vulkan14_renderer::walk_draw(gfx::geometry_handle const &Geometry)
{
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
if (m_rtgather)
{
gather_ray_draw(Geometry);
return;
}
if (m_indirectrecording)
{
// the draw is made later, from the gpu culling, with this state
@@ -1630,6 +1687,14 @@ void vulkan14_renderer::walk_draw(gfx::geometry_handle const &Geometry)
void vulkan14_renderer::walk_draw(std::vector<gfx::geometrybank_handle>::iterator First, std::vector<gfx::geometrybank_handle>::iterator Last)
{
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
if (m_rtgather)
{
for (; First != Last; ++First)
{
gather_ray_draw(*First);
}
return;
}
// the chunks drawn together share the block of the draw
auto newblock{true};
for (; First != Last; ++First)