mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-06 06:58:35 +01:00
Vulkan ray tracing: shade the heightmap terrain from its layers; longer default SSR range
This commit is contained in:
@@ -97,12 +97,14 @@ constexpr std::uint32_t POST_EXPOSURE_SSBO = 4;
|
||||
constexpr std::uint32_t COMPUTE_SET = 1;
|
||||
|
||||
// the ray traced reflections (gfx.raytracing, vk14::ray_tracing): set 2 of the pipelines of the scene, one for each frame in flight,
|
||||
// written with the frame: the acceleration structure of the scenery around the camera, the records of its instances, and the
|
||||
// textures they read (an array of as many as the device allows, partly bound, the last binding)
|
||||
// written with the frame: the acceleration structure of the scenery around the camera, the records of its instances, the layers
|
||||
// of the heightmap terrain (the texture array of their diffuse maps, partly bound) and the textures they read (an array of as many
|
||||
// as the device allows, partly bound, the last binding)
|
||||
constexpr std::uint32_t RT_SET = 2;
|
||||
constexpr std::uint32_t RT_SCENE = 0;
|
||||
constexpr std::uint32_t RT_RECORDS = 1;
|
||||
constexpr std::uint32_t RT_TEXTURES = 2;
|
||||
constexpr std::uint32_t RT_TERRAIN = 2;
|
||||
constexpr std::uint32_t RT_TEXTURES = 3;
|
||||
|
||||
// the push constants of the graphics pipelines of the scene and of the post-processing (vk14::draw_constants): the draw, and
|
||||
// the parameters of the special shaders (the celestial bodies, the post-processing)
|
||||
|
||||
@@ -1785,6 +1785,12 @@ void vulkan14_renderer::render_ray_scene(viewport_config &Viewport)
|
||||
m_shadowskipvehicle = simulation::Train->Dynamic();
|
||||
}
|
||||
auto const colourpass{m_renderpass};
|
||||
// the chunks of the heightmap terrain are told by their programs (mat_terrain.frag, mat_terrain_holes.frag)
|
||||
auto const program_of = [&](char const *Name) -> vk14::scene_program const * {
|
||||
auto const lookup{scene.materials.find(Name)};
|
||||
return (lookup != scene.materials.end() ? lookup->second.get() : nullptr);
|
||||
};
|
||||
m_rtterrain = {program_of("terrain"), program_of("terrain_holes")};
|
||||
m_rtgather = true;
|
||||
setup_pass(Viewport, m_renderpass, rendermode::reflections);
|
||||
setup_matrices();
|
||||
@@ -1840,15 +1846,30 @@ void vulkan14_renderer::gather_ray_draw(gfx::geometry_handle const &Geometry)
|
||||
auto const value{std::max({model_ubs.param[0].r, model_ubs.param[0].g, model_ubs.param[0].b})};
|
||||
ray.colour = (value > 0.f ? colour * (model_ubs.param[1].x / value) : glm::vec3{0.f});
|
||||
ray.glow = model_ubs.emission;
|
||||
// the diffuse texture of the material, and its alpha test when it has an alpha channel
|
||||
if (draw.textures[0] != null_handle)
|
||||
{
|
||||
auto &texture{m_context->textures->mark_as_used(draw.textures[0])};
|
||||
if (texture.create() && (m_context->images.find(texture.get_id()) != nullptr))
|
||||
// the id of a texture of the material in the image table, 0: none (yet)
|
||||
auto const image_of = [&](texture_handle const Texture) -> std::uint64_t {
|
||||
if (Texture == null_handle)
|
||||
{
|
||||
ray.texture = texture.get_id();
|
||||
ray.cutoff = (texture.get_has_alpha() ? std::max(model_ubs.opacity, 0.f) : 0.f);
|
||||
return 0;
|
||||
}
|
||||
auto &texture{m_context->textures->mark_as_used(Texture)};
|
||||
return ((texture.create() && (m_context->images.find(texture.get_id()) != nullptr)) ? texture.get_id() : 0);
|
||||
};
|
||||
if ((draw.program != nullptr) && ((draw.program == m_rtterrain[0]) || (draw.program == m_rtterrain[1])))
|
||||
{
|
||||
// a chunk of the heightmap terrain: its layers blended by its weights (mat_terrain.glsl: weights0 1, weights1 2, the array of the
|
||||
// diffuse maps of the layers 3, the table 6, the placement param[2])
|
||||
ray.terrain_weights[0] = image_of(draw.textures[1]);
|
||||
ray.terrain_weights[1] = image_of(draw.textures[2]);
|
||||
ray.terrain_layers = image_of(draw.textures[3]);
|
||||
ray.terrain_table = image_of(draw.textures[6]);
|
||||
ray.placement = model_ubs.param[2];
|
||||
}
|
||||
else if (auto const texture{image_of(draw.textures[0])}; texture != 0)
|
||||
{
|
||||
// the diffuse texture of the material, and its alpha test when it has an alpha channel
|
||||
ray.texture = texture;
|
||||
ray.cutoff = (m_context->textures->mark_as_used(draw.textures[0]).get_has_alpha() ? std::max(model_ubs.opacity, 0.f) : 0.f);
|
||||
}
|
||||
glm::mat4 const modelview{model_ubs.modelview};
|
||||
if (m_current_instance_count > 0)
|
||||
|
||||
@@ -37,6 +37,9 @@ struct record
|
||||
static_assert(sizeof(record) == 48, "the record of an instance of the ray tracing doesn't match the shaders");
|
||||
|
||||
std::uint32_t constexpr record_alpha{1};
|
||||
// a chunk of the heightmap terrain: texture holds the index of its first weights, the bits of cutoff the second weights, the bits of
|
||||
// glow the table of its layers, colour the placement of the chunk (param[2] of its material)
|
||||
std::uint32_t constexpr record_terrain{2};
|
||||
// the bottom level structures built in a frame at most, and their triangles: the rest waits for the next frames
|
||||
std::uint32_t constexpr builds_per_frame{96};
|
||||
std::uint64_t constexpr triangles_per_frame{2000000};
|
||||
@@ -94,11 +97,14 @@ bool ray_tracing::init(device const &Device, allocator &Memory, deletion_queue &
|
||||
m_texturecount = std::min<std::uint32_t>(Device.caps().max_indexed_textures, 16384);
|
||||
auto const handle{Device.handle()};
|
||||
|
||||
// the structure, the records and the textures, the last binding as many as the set is made with and partly bound
|
||||
std::array<VkDescriptorSetLayoutBinding, 3> bindings{{{RT_SCENE, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr},
|
||||
// the structure, the records, the layers of the terrain (written once a chunk of it is met) and the textures, the last binding as
|
||||
// many as the set is made with and partly bound
|
||||
static_assert((RT_TERRAIN == 2) && (RT_TEXTURES == 3), "the bindings of the set of the ray tracing go in this order");
|
||||
std::array<VkDescriptorSetLayoutBinding, 4> bindings{{{RT_SCENE, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr},
|
||||
{RT_RECORDS, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr},
|
||||
{RT_TERRAIN, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr},
|
||||
{RT_TEXTURES, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, m_texturecount, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}}};
|
||||
std::array<VkDescriptorBindingFlags, 3> const flags{0, 0, VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT};
|
||||
std::array<VkDescriptorBindingFlags, 4> const flags{0, 0, VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT, VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT};
|
||||
VkDescriptorSetLayoutBindingFlagsCreateInfo bindingflags{};
|
||||
bindingflags.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO;
|
||||
bindingflags.bindingCount = static_cast<std::uint32_t>(flags.size());
|
||||
@@ -116,7 +122,7 @@ bool ray_tracing::init(device const &Device, allocator &Memory, deletion_queue &
|
||||
}
|
||||
name_object(handle, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, handle_value(m_layout), "ray tracing set");
|
||||
|
||||
std::array<VkDescriptorPoolSize, 3> const sizes{{{VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, Frames}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, Frames}, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, m_texturecount * Frames}}};
|
||||
std::array<VkDescriptorPoolSize, 3> const sizes{{{VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, Frames}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, Frames}, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, (m_texturecount + 1) * Frames}}};
|
||||
VkDescriptorPoolCreateInfo pool{};
|
||||
pool.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
pool.maxSets = Frames;
|
||||
@@ -597,6 +603,23 @@ void ray_tracing::build(command_stream *Commands, std::uint32_t const Slot, std:
|
||||
auto *records{reinterpret_cast<record *>(frame.records ? frame.records->mapped() : nullptr)};
|
||||
auto *instances{reinterpret_cast<VkAccelerationStructureInstanceKHR *>(frame.instances ? frame.instances->mapped() : nullptr)};
|
||||
std::vector<std::uint32_t> usedtextures;
|
||||
// the texture array of the layers of the terrain the chunks read: a 2d array of the image table, or the chunks shade with their
|
||||
// colour (the binding is read only for the chunks marked as terrain)
|
||||
std::uint64_t terrainlayers{0};
|
||||
std::uint64_t checkedlayers{0};
|
||||
image_table::entry const *layersentry{nullptr};
|
||||
auto const layers_valid = [&](std::uint64_t const Id) {
|
||||
if (Id != checkedlayers)
|
||||
{
|
||||
checkedlayers = Id;
|
||||
layersentry = Images.find(Id);
|
||||
if ((layersentry != nullptr) && ((false == bool(layersentry->target)) || (layersentry->target->desc().view_type != VK_IMAGE_VIEW_TYPE_2D_ARRAY) || (layersentry->sampler == VK_NULL_HANDLE)))
|
||||
{
|
||||
layersentry = nullptr;
|
||||
}
|
||||
}
|
||||
return (layersentry != nullptr) && ((terrainlayers == 0) || (terrainlayers == Id));
|
||||
};
|
||||
std::uint32_t written{0};
|
||||
for (auto const &draw : Draws)
|
||||
{
|
||||
@@ -610,7 +633,8 @@ void ray_tracing::build(command_stream *Commands, std::uint32_t const Slot, std:
|
||||
continue;
|
||||
}
|
||||
auto const &source{draw.source};
|
||||
auto const texture{texture_index(draw.texture, Frame)};
|
||||
auto const terrain{draw.terrain_table != 0};
|
||||
auto const texture{texture_index(terrain ? draw.terrain_weights[0] : draw.texture, Frame)};
|
||||
if (texture != 0)
|
||||
{
|
||||
usedtextures.push_back(texture);
|
||||
@@ -619,11 +643,36 @@ void ray_tracing::build(command_stream *Commands, std::uint32_t const Slot, std:
|
||||
entry.vertices = source.vertex_address + vertex_stride * source.vertexfirst;
|
||||
entry.indices = (lookup->second.index_address != 0 ? lookup->second.index_address : source.indices != VK_NULL_HANDLE ? source.index_address + sizeof(std::uint32_t) * source.first : 0);
|
||||
entry.texture = texture;
|
||||
auto const alpha{(texture != 0) && (draw.cutoff > 0.f)};
|
||||
auto const alpha{(false == terrain) && (texture != 0) && (draw.cutoff > 0.f)};
|
||||
entry.flags = (alpha ? record_alpha : 0);
|
||||
entry.cutoff = draw.cutoff;
|
||||
entry.glow = draw.glow;
|
||||
entry.colour = glm::vec4{draw.colour, 1.f};
|
||||
if (terrain)
|
||||
{
|
||||
// the shading blends the layers as the terrain shader does, from the weights and the table (indices in the bits of the floats)
|
||||
auto const weights{texture_index(draw.terrain_weights[1], Frame)};
|
||||
auto const table{texture_index(draw.terrain_table, Frame)};
|
||||
for (auto const index : {weights, table})
|
||||
{
|
||||
if (index != 0)
|
||||
{
|
||||
usedtextures.push_back(index);
|
||||
}
|
||||
}
|
||||
if ((texture != 0) && (weights != 0) && (table != 0) && (draw.terrain_layers != 0) && layers_valid(draw.terrain_layers))
|
||||
{
|
||||
entry.flags = record_terrain;
|
||||
std::memcpy(&entry.cutoff, &weights, sizeof(weights));
|
||||
std::memcpy(&entry.glow, &table, sizeof(table));
|
||||
entry.colour = draw.placement;
|
||||
terrainlayers = draw.terrain_layers;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.texture = 0;
|
||||
}
|
||||
}
|
||||
auto &instance{instances[written]};
|
||||
// the rows of the transform, which glm keeps by the columns
|
||||
for (int row = 0; row < 3; ++row)
|
||||
@@ -720,6 +769,25 @@ void ray_tracing::build(command_stream *Commands, std::uint32_t const Slot, std:
|
||||
write.pImageInfo = &images.back();
|
||||
writes.push_back(write);
|
||||
}
|
||||
VkDescriptorImageInfo terraininfo{};
|
||||
if ((terrainlayers != 0) && layers_valid(terrainlayers))
|
||||
{
|
||||
auto const &target{layersentry->target};
|
||||
auto &cached{frame.written_terrain};
|
||||
if ((cached.view != target->view()) || (cached.sampler != layersentry->sampler) || (cached.source.lock() != target))
|
||||
{
|
||||
cached = {target->view(), layersentry->sampler, target};
|
||||
terraininfo = {layersentry->sampler, target->view(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
|
||||
VkWriteDescriptorSet write{};
|
||||
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
write.dstSet = frame.set;
|
||||
write.dstBinding = vk14::bindings::RT_TERRAIN;
|
||||
write.descriptorCount = 1;
|
||||
write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
write.pImageInfo = &terraininfo;
|
||||
writes.push_back(write);
|
||||
}
|
||||
}
|
||||
if (false == writes.empty())
|
||||
{
|
||||
vkUpdateDescriptorSets(handle, static_cast<std::uint32_t>(writes.size()), writes.data(), 0, nullptr);
|
||||
|
||||
@@ -43,6 +43,12 @@ struct ray_draw
|
||||
glm::vec3 colour{1.f}; // the diffuse colour of the material, linear
|
||||
float cutoff{0.f}; // the alpha test of the texture, 0: none
|
||||
float glow{0.f}; // the light of its own
|
||||
// a chunk of the heightmap terrain: its weights (two maps of four layers), its table of the layers (the ids of the images) and
|
||||
// the texture array of the diffuse maps of the layers, shared by the chunks; placement: param[2] of its material
|
||||
std::uint64_t terrain_weights[2]{0, 0};
|
||||
std::uint64_t terrain_table{0};
|
||||
std::uint64_t terrain_layers{0};
|
||||
glm::vec4 placement{0.f};
|
||||
};
|
||||
|
||||
class ray_tracing
|
||||
@@ -122,6 +128,7 @@ class ray_tracing
|
||||
std::weak_ptr<image> source; // a view made after this one is gone can get its handle
|
||||
};
|
||||
std::vector<written_texture> written_textures;
|
||||
written_texture written_terrain;
|
||||
};
|
||||
|
||||
// a buffer of the frame at least Size bytes, grown when it isn't (the old one stays when the new one can't be made)
|
||||
|
||||
@@ -35,6 +35,8 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "vehicle/Camera.h"
|
||||
#include "gl/ubo.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
class world_environment;
|
||||
struct VkRenderingInfo;
|
||||
namespace vk14
|
||||
@@ -282,6 +284,7 @@ class vulkan14_renderer : public gfx_renderer, public gfx::scene_walk
|
||||
bool m_rtgather{false};
|
||||
bool m_raytracingon{true}; // switched off in the debug window
|
||||
bool m_rtfoliage{true}; // the alpha tested geometry in the traced reflections, switched off in the debug window
|
||||
std::array<vk14::scene_program const *, 2> m_rtterrain{nullptr, nullptr}; // the programs of the heightmap terrain, the draws of it noted as such
|
||||
double m_rtwalkms{0.0}; // the processor time of the walk and of the build of the ray tracing, averaged
|
||||
double m_rtbuildms{0.0};
|
||||
std::vector<vk14::ray_draw> m_rtdraws;
|
||||
|
||||
@@ -818,6 +818,7 @@ std::string binding_preamble(bool const Raytracing)
|
||||
define("RT_SET", RT_SET);
|
||||
define("RT_SCENE", RT_SCENE);
|
||||
define("RT_RECORDS", RT_RECORDS);
|
||||
define("RT_TERRAIN", RT_TERRAIN);
|
||||
define("RT_TEXTURES", RT_TEXTURES);
|
||||
define("PUSH_CONSTANTS_SIZE", PUSH_CONSTANTS_SIZE);
|
||||
define("SPEC_OUTPUT_GAMMA", SPEC_OUTPUT_GAMMA);
|
||||
|
||||
Reference in New Issue
Block a user