17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-10 19:33:02 +01:00

Light the cab with the sun coming in through its windows

This commit is contained in:
2026-10-28 12:19:43 +01:00
parent 1447dcf075
commit e8a90507f0
28 changed files with 342 additions and 29 deletions

View File

@@ -176,7 +176,7 @@ bool vulkan14_renderer::compute_ao_lighting(std::size_t const Index)
// the block of the scene of the colour pass set up to read the occlusion (light_common.glsl, ambient_occlusion())
void vulkan14_renderer::setup_ao_lighting()
{
scene_ubs.ao_params = glm::vec4{1.f, Global.gfx_postfx_ao_strength, 0.f, 0.f};
scene_ubs.ao_params = glm::vec4{1.f, Global.gfx_postfx_ao_strength, Global.gfx_postfx_ao_cab, 0.f};
upload_scene_block();
}

View File

@@ -84,7 +84,9 @@ constexpr std::uint32_t CAB_PROBE_SSBO = 30;
// the scenery and the shares of the sky and the limits of the key light, read texel by texel
constexpr std::uint32_t SKY_OCCLUSION_HEIGHT_TEX = 31;
constexpr std::uint32_t SKY_OCCLUSION_TEX = 32;
constexpr std::uint32_t PASS_BINDING_COUNT = 33;
// the probe of the cab drawn last, a small level of its albedo, which the drawing of the probe reads to tell where the windows are
constexpr std::uint32_t CAB_PROBE_MASK_TEX = 33;
constexpr std::uint32_t PASS_BINDING_COUNT = 34;
// the offsets of the bindings above with dynamic offsets, in the order of the bindings
constexpr std::uint32_t PASS_DYNAMIC_OFFSETS = 6;
// the textures of a material take the bindings of their units (#pragma texture(name, unit, ...)), 0 .. MAX_TEXTURES - 1

View File

@@ -178,8 +178,28 @@ bool cab_probe_maps::gpu_allocate(int const Size)
let_go();
return false;
}
// the mask: the level of the albedo of at most CAB_PROBE_MASK_SIZE pixels a face, as mask_size() has it once the size is set
auto masksize{size};
while (masksize > static_cast<std::uint32_t>(gl::CAB_PROBE_MASK_SIZE))
{
masksize >>= 1;
}
image_desc mask;
mask.format = ALBEDO_FORMAT;
mask.extent = {std::max(masksize, 1u), std::max(masksize, 1u), 1};
mask.layers = 6;
mask.view_type = VK_IMAGE_VIEW_TYPE_CUBE;
mask.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
mask.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
m_mask = std::make_shared<image>();
if (false == m_mask->create(*m_memory, mask, "cab probe mask"))
{
let_go();
return false;
}
m_target = draw_target{m_light.get(), m_albedo.get(), m_depth.get(), m_lightview, m_albedoview, size};
m_drawn = false;
m_maskcopied = false;
return true;
}
@@ -192,6 +212,7 @@ void cab_probe_maps::let_go()
{
m_target = draw_target{};
m_drawn = false;
m_maskcopied = false;
std::vector<VkImageView> views;
for (auto *view : {&m_lightview, &m_albedoview})
{
@@ -204,7 +225,7 @@ void cab_probe_maps::let_go()
if (m_deletions != nullptr)
{
// the frames in flight may still read them
m_deletions->push(m_value, [device = m_device, views = std::move(views), light = std::move(m_light), albedo = std::move(m_albedo), depth = std::move(m_depth)]() {
m_deletions->push(m_value, [device = m_device, views = std::move(views), light = std::move(m_light), albedo = std::move(m_albedo), depth = std::move(m_depth), mask = std::move(m_mask)]() {
for (auto *view : views)
{
vkDestroyImageView(device, view, nullptr);
@@ -221,6 +242,7 @@ void cab_probe_maps::let_go()
m_light.reset();
m_albedo.reset();
m_depth.reset();
m_mask.reset();
}
} // namespace vk14
@@ -341,6 +363,12 @@ void vulkan14_renderer::render_cab_probe()
// the lamp with its shadow map, when the map holds the shadows of the lamp where it is
auto const shadows{(lamp != nullptr) && scene.lamps.ready(vehicle) && (scene.lamps.lamp() == m_locallights.cab_lamp_local())};
probe.setup_drawing(scene_ubs, lamp, m_locallights.cab_lamp_local(), shadows, scene.lamps.weights());
// the sun coming in through the windows, as the shading of the last frame got it. the mask is read once it was copied
probe.setup_sun(scene_ubs, vehicle, -m_sunlight.direction, glm::vec3{light_data.lights[0].color} * light_data.lights[0].intensity, m_colorpass.pass_camera.position());
if (probe.mask_map() == nullptr)
{
scene_ubs.cab_probe_sun.w = 0.f;
}
// the cab drawn by the colour mode with the programs of the probe. the camera is put at the vehicle, which Render_cab() places the cab
// relative to, and the modelview takes the cab model to the space of the probe
m_renderpass.draw_mode = rendermode::color;
@@ -389,6 +417,30 @@ void vulkan14_renderer::render_cab_probe()
// the mipmaps, and the light the cab lights itself with again from a small level of the light reflected
make_cube_mipmaps(commands, *target.light);
make_cube_mipmaps(commands, *target.albedo);
// where the windows are, for the next drawing: a small level of the albedo copied to the mask
if (auto *mask{probe.mask_target()})
{
vk14::barriers(commands, {vk14::use_of(*target.albedo, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_READ_BIT),
vk14::use_of(*mask, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_2_COPY_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT)});
auto const masksize{static_cast<std::uint32_t>(probe.mask_size())};
VkImageCopy2 region{};
region.sType = VK_STRUCTURE_TYPE_IMAGE_COPY_2;
region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, static_cast<std::uint32_t>(probe.mask_level()), 0, 6};
region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 6};
region.extent = {masksize, masksize, 1};
VkCopyImageInfo2 copy{};
copy.sType = VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2;
copy.srcImage = target.albedo->handle();
copy.srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
copy.dstImage = mask->handle();
copy.dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
copy.regionCount = 1;
copy.pRegions = &region;
commands->copy_image2(&copy);
vk14::barriers(commands, {vk14::use_of(*target.albedo, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, sampled_stage, sampled_access),
vk14::use_of(*mask, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, sampled_stage, sampled_access)});
probe.mask_copied();
}
struct
{
glm::ivec2 level;

View File

@@ -61,6 +61,21 @@ class cab_probe_maps : public gfx::cab_probe
{
return m_drawn ? m_albedo.get() : nullptr;
}
// the copy of a small level of the albedo of the last drawing (gfx::cab_probe, the mask), which the next drawing reads to tell
// where the windows are; null until it was copied: the stand-in is read
image *mask_map() const
{
return m_maskcopied ? m_mask.get() : nullptr;
}
image *mask_target() const
{
return m_mask.get();
}
// the mask was copied and is in the layout the shading reads it in
void mask_copied()
{
m_maskcopied = true;
}
// the maps were drawn and are in the layout the shading reads them in
void drawn()
{
@@ -84,10 +99,12 @@ class cab_probe_maps : public gfx::cab_probe
std::shared_ptr<image> m_light;
std::shared_ptr<image> m_albedo;
std::shared_ptr<image> m_depth;
std::shared_ptr<image> m_mask;
VkImageView m_lightview{VK_NULL_HANDLE};
VkImageView m_albedoview{VK_NULL_HANDLE};
draw_target m_target;
bool m_drawn{false};
bool m_maskcopied{false};
};
} // namespace vk14

View File

@@ -1531,7 +1531,7 @@ void vulkan14_renderer::render_viewport(std::size_t const Index)
scene_ubs.shadow_fit = glm::vec4{0.f};
// the reflections: the ground below the horizon of the environment map, and the screen space ones set up for the colour pass of
// the main view only
scene_ubs.env_params = glm::vec4{Global.gfx_ambient_groundalbedo, (m_rtfoliage ? 0.f : 1.f), 0.f, 0.f};
scene_ubs.env_params = glm::vec4{Global.gfx_ambient_groundalbedo, (m_rtfoliage ? 0.f : 1.f), Global.gfx_interior_bounce, 0.f};
gfx::screen_reflections::clear(scene_ubs);
if (vp.main)

View File

@@ -206,6 +206,9 @@ std::array<std::array<VkImageView, vk14::bindings::PASS_BINDING_COUNT>, 3> pass_
auto const probeempty{scene.cabprobe_empty ? scene.cabprobe_empty->view() : scene.env_empty->view()};
views[CAB_PROBE_TEX] = (colour && (probelight != nullptr) ? probelight->view() : probeempty);
views[CAB_PROBE_ALBEDO_TEX] = (colour && (probealbedo != nullptr) ? probealbedo->view() : probeempty);
// the probe drawn last, which the drawing of the probe (the plain set) reads to tell where the windows are
auto const *probemask{scene.cabprobe.mask_map()};
views[CAB_PROBE_MASK_TEX] = (probemask != nullptr ? probemask->view() : probeempty);
// the occlusion of the sky by the scenery (the track T), for every pass which shades
auto const *occlusionheights{scene.skyocclusion.heights()};
auto const *occlusion{scene.skyocclusion.occlusion()};
@@ -1116,6 +1119,7 @@ void vulkan14_renderer::write_pass_sets(vk14::instance_cull *Cull)
write(handle, CAB_PROBE_TEX, nullptr, image(ctx.sampling.clamp_linear, views[CAB_PROBE_TEX]));
write(handle, CAB_PROBE_ALBEDO_TEX, nullptr, image(ctx.sampling.clamp_linear, views[CAB_PROBE_ALBEDO_TEX]));
write(handle, CAB_PROBE_SSBO, &cabprobe, nullptr);
write(handle, CAB_PROBE_MASK_TEX, nullptr, image(ctx.sampling.clamp_linear, views[CAB_PROBE_MASK_TEX]));
write(handle, SKY_OCCLUSION_HEIGHT_TEX, nullptr, image(ctx.sampling.repeat_nearest, views[SKY_OCCLUSION_HEIGHT_TEX]));
write(handle, SKY_OCCLUSION_TEX, nullptr, image(ctx.sampling.repeat_nearest, views[SKY_OCCLUSION_TEX]));
}

View File

@@ -857,6 +857,7 @@ std::string binding_preamble(bool const Raytracing)
define("CAB_PROBE_SSBO", CAB_PROBE_SSBO);
define("SKY_OCCLUSION_HEIGHT_TEX", SKY_OCCLUSION_HEIGHT_TEX);
define("SKY_OCCLUSION_TEX", SKY_OCCLUSION_TEX);
define("CAB_PROBE_MASK_TEX", CAB_PROBE_MASK_TEX);
define("PASS_BINDING_COUNT", PASS_BINDING_COUNT);
define("MATERIAL_TEXTURE_FIRST", MATERIAL_TEXTURE_FIRST);
define("CL_CLUSTER_UBO", CL_CLUSTER_UBO);