ADD: planet quadtree texture enabled
This commit is contained in:
@@ -2273,6 +2273,12 @@ namespace
|
|||||||
auto settings = planets->earth_quadtree_settings();
|
auto settings = planets->earth_quadtree_settings();
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
|
bool tint = planets->earth_debug_tint_patches_by_lod();
|
||||||
|
if (ImGui::Checkbox("Debug: tint patches by LOD", &tint))
|
||||||
|
{
|
||||||
|
planets->set_earth_debug_tint_patches_by_lod(tint);
|
||||||
|
}
|
||||||
|
|
||||||
int maxLevel = static_cast<int>(settings.max_level);
|
int maxLevel = static_cast<int>(settings.max_level);
|
||||||
if (ImGui::SliderInt("Max LOD level", &maxLevel, 0, 20))
|
if (ImGui::SliderInt("Max LOD level", &maxLevel, 0, 20))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -192,6 +192,9 @@ namespace planet
|
|||||||
const uint32_t skirt_vertex_count = 4u * resolution;
|
const uint32_t skirt_vertex_count = 4u * resolution;
|
||||||
out_vertices.resize(static_cast<size_t>(base_vertex_count) + static_cast<size_t>(skirt_vertex_count));
|
out_vertices.resize(static_cast<size_t>(base_vertex_count) + static_cast<size_t>(skirt_vertex_count));
|
||||||
|
|
||||||
|
const uint32_t tiles_per_axis = (level < 31u) ? (1u << level) : 1u;
|
||||||
|
const double inv_tiles = (tiles_per_axis > 0u) ? (1.0 / static_cast<double>(tiles_per_axis)) : 1.0;
|
||||||
|
|
||||||
const double inv = 1.0 / static_cast<double>(resolution - 1u);
|
const double inv = 1.0 / static_cast<double>(resolution - 1u);
|
||||||
const double du = (u1 - u0) * inv;
|
const double du = (u1 - u0) * inv;
|
||||||
const double dv = (v1 - v0) * inv;
|
const double dv = (v1 - v0) * inv;
|
||||||
@@ -215,8 +218,13 @@ namespace planet
|
|||||||
vert.normal = glm::vec3(static_cast<float>(unit_dir.x),
|
vert.normal = glm::vec3(static_cast<float>(unit_dir.x),
|
||||||
static_cast<float>(unit_dir.y),
|
static_cast<float>(unit_dir.y),
|
||||||
static_cast<float>(unit_dir.z));
|
static_cast<float>(unit_dir.z));
|
||||||
vert.uv_x = s;
|
|
||||||
vert.uv_y = t;
|
// UVs cover the entire cube face (0..1) so all patches on this face
|
||||||
|
// sample from a single per-face texture.
|
||||||
|
const double u_face = (static_cast<double>(x) + static_cast<double>(s)) * inv_tiles;
|
||||||
|
const double v_face = (static_cast<double>(y) + static_cast<double>(t)) * inv_tiles;
|
||||||
|
vert.uv_x = static_cast<float>(u_face);
|
||||||
|
vert.uv_y = static_cast<float>(v_face);
|
||||||
vert.color = vertex_color;
|
vert.color = vertex_color;
|
||||||
vert.tangent = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);
|
vert.tangent = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
@@ -79,6 +78,16 @@ void PlanetSystem::init(EngineContext *context)
|
|||||||
_context = context;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlanetSystem::set_earth_debug_tint_patches_by_lod(bool enabled)
|
||||||
|
{
|
||||||
|
if (_earth_debug_tint_patches_by_lod == enabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_earth_debug_tint_patches_by_lod = enabled;
|
||||||
|
_earth_patch_cache_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
void PlanetSystem::cleanup()
|
void PlanetSystem::cleanup()
|
||||||
{
|
{
|
||||||
if (!_context)
|
if (!_context)
|
||||||
@@ -89,11 +98,11 @@ void PlanetSystem::cleanup()
|
|||||||
TextureCache *textures = _context->textures;
|
TextureCache *textures = _context->textures;
|
||||||
if (textures)
|
if (textures)
|
||||||
{
|
{
|
||||||
for (EarthPatch &p : _earth_patches)
|
for (MaterialInstance &mat : _earth_face_materials)
|
||||||
{
|
{
|
||||||
if (p.material_instance.materialSet != VK_NULL_HANDLE)
|
if (mat.materialSet != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
textures->unwatchSet(p.material_instance.materialSet);
|
textures->unwatchSet(mat.materialSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,6 +155,7 @@ void PlanetSystem::cleanup()
|
|||||||
_earth_patch_lru.clear();
|
_earth_patch_lru.clear();
|
||||||
_earth_patch_free.clear();
|
_earth_patch_free.clear();
|
||||||
_earth_patches.clear();
|
_earth_patches.clear();
|
||||||
|
_earth_face_materials = {};
|
||||||
|
|
||||||
_earth_patch_index_count = 0;
|
_earth_patch_index_count = 0;
|
||||||
_earth_patch_index_resolution = 0;
|
_earth_patch_index_resolution = 0;
|
||||||
@@ -235,6 +245,46 @@ PlanetSystem::EarthPatch *PlanetSystem::find_earth_patch(const planet::PatchKey
|
|||||||
return &_earth_patches[idx];
|
return &_earth_patches[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlanetSystem::clear_earth_patch_cache()
|
||||||
|
{
|
||||||
|
if (!_context)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceManager *rm = _context->getResources();
|
||||||
|
FrameResources *frame = _context->currentFrame;
|
||||||
|
|
||||||
|
if (rm)
|
||||||
|
{
|
||||||
|
for (EarthPatch &p : _earth_patches)
|
||||||
|
{
|
||||||
|
if (p.vertex_buffer.buffer == VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AllocatedBuffer vb = p.vertex_buffer;
|
||||||
|
if (frame)
|
||||||
|
{
|
||||||
|
frame->_deletionQueue.push_function([rm, vb]() { rm->destroy_buffer(vb); });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rm->destroy_buffer(vb);
|
||||||
|
}
|
||||||
|
|
||||||
|
p.vertex_buffer = {};
|
||||||
|
p.vertex_buffer_address = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_earth_patch_lookup.clear();
|
||||||
|
_earth_patch_lru.clear();
|
||||||
|
_earth_patch_free.clear();
|
||||||
|
_earth_patches.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void PlanetSystem::ensure_earth_patch_index_buffer()
|
void PlanetSystem::ensure_earth_patch_index_buffer()
|
||||||
{
|
{
|
||||||
if (_earth_patch_index_buffer.buffer != VK_NULL_HANDLE && _earth_patch_index_resolution == _earth_patch_resolution)
|
if (_earth_patch_index_buffer.buffer != VK_NULL_HANDLE && _earth_patch_index_resolution == _earth_patch_resolution)
|
||||||
@@ -257,7 +307,6 @@ void PlanetSystem::ensure_earth_patch_index_buffer()
|
|||||||
if (_earth_patch_index_buffer.buffer != VK_NULL_HANDLE)
|
if (_earth_patch_index_buffer.buffer != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
FrameResources *frame = _context->currentFrame;
|
FrameResources *frame = _context->currentFrame;
|
||||||
TextureCache *textures = _context->textures;
|
|
||||||
|
|
||||||
// Destroy per-patch vertex buffers.
|
// Destroy per-patch vertex buffers.
|
||||||
for (const auto &kv : _earth_patch_lookup)
|
for (const auto &kv : _earth_patch_lookup)
|
||||||
@@ -286,28 +335,8 @@ void PlanetSystem::ensure_earth_patch_index_buffer()
|
|||||||
|
|
||||||
_earth_patch_lookup.clear();
|
_earth_patch_lookup.clear();
|
||||||
_earth_patch_lru.clear();
|
_earth_patch_lru.clear();
|
||||||
|
|
||||||
if (textures)
|
|
||||||
{
|
|
||||||
for (EarthPatch &p : _earth_patches)
|
|
||||||
{
|
|
||||||
if (p.material_instance.materialSet != VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
textures->unwatchSet(p.material_instance.materialSet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_earth_patch_free.clear();
|
_earth_patch_free.clear();
|
||||||
_earth_patch_free.reserve(_earth_patches.size());
|
_earth_patches.clear();
|
||||||
for (uint32_t idx = 0; idx < static_cast<uint32_t>(_earth_patches.size()); ++idx)
|
|
||||||
{
|
|
||||||
EarthPatch &p = _earth_patches[idx];
|
|
||||||
const VkDescriptorSet keep_set = p.material_instance.materialSet;
|
|
||||||
p = EarthPatch{};
|
|
||||||
p.material_instance.materialSet = keep_set;
|
|
||||||
_earth_patch_free.push_back(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
const AllocatedBuffer ib = _earth_patch_index_buffer;
|
const AllocatedBuffer ib = _earth_patch_index_buffer;
|
||||||
if (frame)
|
if (frame)
|
||||||
@@ -408,7 +437,7 @@ void PlanetSystem::ensure_earth_patch_material_constants_buffer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlanetSystem::ensure_earth_patch_material_instance(EarthPatch &patch, const PlanetBody &earth)
|
void PlanetSystem::ensure_earth_face_materials(const PlanetBody &earth)
|
||||||
{
|
{
|
||||||
if (!_context || !earth.material)
|
if (!_context || !earth.material)
|
||||||
{
|
{
|
||||||
@@ -418,6 +447,7 @@ void PlanetSystem::ensure_earth_patch_material_instance(EarthPatch &patch, const
|
|||||||
DeviceManager *device = _context->getDevice();
|
DeviceManager *device = _context->getDevice();
|
||||||
SamplerManager *samplers = _context->getSamplers();
|
SamplerManager *samplers = _context->getSamplers();
|
||||||
AssetManager *assets = _context->assets;
|
AssetManager *assets = _context->assets;
|
||||||
|
TextureCache *textures = _context->textures;
|
||||||
if (!device || !assets)
|
if (!device || !assets)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -438,24 +468,19 @@ void PlanetSystem::ensure_earth_patch_material_instance(EarthPatch &patch, const
|
|||||||
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
|
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
|
||||||
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6},
|
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6},
|
||||||
};
|
};
|
||||||
_earth_patch_material_allocator.init(device->device(), 128, sizes);
|
_earth_patch_material_allocator.init(device->device(), 16, sizes);
|
||||||
_earth_patch_material_allocator_initialized = true;
|
_earth_patch_material_allocator_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patch.material_instance.materialSet == VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
patch.material_instance.materialSet =
|
|
||||||
_earth_patch_material_allocator.allocate(device->device(), _earth_patch_material_layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
patch.material_instance.pipeline = earth.material->data.pipeline;
|
|
||||||
patch.material_instance.passType = earth.material->data.passType;
|
|
||||||
|
|
||||||
VkSampler tileSampler = samplers ? samplers->linearClampEdge() : VK_NULL_HANDLE;
|
VkSampler tileSampler = samplers ? samplers->linearClampEdge() : VK_NULL_HANDLE;
|
||||||
if (tileSampler == VK_NULL_HANDLE && samplers)
|
if (tileSampler == VK_NULL_HANDLE && samplers)
|
||||||
{
|
{
|
||||||
tileSampler = samplers->defaultLinear();
|
tileSampler = samplers->defaultLinear();
|
||||||
}
|
}
|
||||||
|
if (tileSampler == VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VkImageView checker = assets->fallback_checkerboard_view();
|
VkImageView checker = assets->fallback_checkerboard_view();
|
||||||
VkImageView white = assets->fallback_white_view();
|
VkImageView white = assets->fallback_white_view();
|
||||||
@@ -467,92 +492,79 @@ void PlanetSystem::ensure_earth_patch_material_instance(EarthPatch &patch, const
|
|||||||
if (flatNormal == VK_NULL_HANDLE) flatNormal = white;
|
if (flatNormal == VK_NULL_HANDLE) flatNormal = white;
|
||||||
if (black == VK_NULL_HANDLE) black = white;
|
if (black == VK_NULL_HANDLE) black = white;
|
||||||
|
|
||||||
if (patch.material_instance.materialSet != VK_NULL_HANDLE)
|
auto face_legacy = [](planet::CubeFace f) -> const char * {
|
||||||
{
|
switch (f)
|
||||||
DescriptorWriter writer;
|
|
||||||
writer.write_buffer(0,
|
|
||||||
_earth_patch_material_constants_buffer.buffer,
|
|
||||||
sizeof(GLTFMetallic_Roughness::MaterialConstants),
|
|
||||||
0,
|
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
|
||||||
writer.write_image(1,
|
|
||||||
checker,
|
|
||||||
tileSampler,
|
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
||||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
|
||||||
writer.write_image(2,
|
|
||||||
white,
|
|
||||||
tileSampler,
|
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
||||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
|
||||||
writer.write_image(3,
|
|
||||||
flatNormal,
|
|
||||||
tileSampler,
|
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
||||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
|
||||||
writer.write_image(4,
|
|
||||||
white,
|
|
||||||
tileSampler,
|
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
||||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
|
||||||
writer.write_image(5,
|
|
||||||
black,
|
|
||||||
tileSampler,
|
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
||||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
|
||||||
writer.update_set(device->device(), patch.material_instance.materialSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per-patch tiled textures via TextureCache (albedo only for now).
|
|
||||||
if (_context->textures && tileSampler != VK_NULL_HANDLE && patch.material_instance.materialSet != VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
auto face_legacy = [](planet::CubeFace f) -> const char * {
|
|
||||||
switch (f)
|
|
||||||
{
|
|
||||||
case planet::CubeFace::PosX: return "px";
|
|
||||||
case planet::CubeFace::NegX: return "nx";
|
|
||||||
case planet::CubeFace::PosY: return "py";
|
|
||||||
case planet::CubeFace::NegY: return "ny";
|
|
||||||
case planet::CubeFace::PosZ: return "pz";
|
|
||||||
case planet::CubeFace::NegZ: return "nz";
|
|
||||||
}
|
|
||||||
return "px";
|
|
||||||
};
|
|
||||||
|
|
||||||
const planet::PatchKey &k = patch.key;
|
|
||||||
const uint32_t face_index = static_cast<uint32_t>(k.face);
|
|
||||||
|
|
||||||
std::vector<std::string> candidates;
|
|
||||||
candidates.reserve(2);
|
|
||||||
candidates.push_back(fmt::format("planets/earth/albedo/face{}/L{}/X{}_Y{}.ktx2", face_index, k.level, k.x, k.y));
|
|
||||||
if (k.level == 0u && k.x == 0u && k.y == 0u)
|
|
||||||
{
|
{
|
||||||
candidates.push_back(fmt::format("planets/earth/albedo/L0/{}.ktx2", face_legacy(k.face)));
|
case planet::CubeFace::PosX: return "px";
|
||||||
|
case planet::CubeFace::NegX: return "nx";
|
||||||
|
case planet::CubeFace::PosY: return "py";
|
||||||
|
case planet::CubeFace::NegY: return "ny";
|
||||||
|
case planet::CubeFace::PosZ: return "pz";
|
||||||
|
case planet::CubeFace::NegZ: return "nz";
|
||||||
}
|
}
|
||||||
|
return "px";
|
||||||
|
};
|
||||||
|
|
||||||
std::string resolved_path;
|
for (size_t face_index = 0; face_index < _earth_face_materials.size(); ++face_index)
|
||||||
for (const std::string &rel : candidates)
|
{
|
||||||
|
MaterialInstance &mat = _earth_face_materials[face_index];
|
||||||
|
|
||||||
|
mat.pipeline = earth.material->data.pipeline;
|
||||||
|
mat.passType = earth.material->data.passType;
|
||||||
|
|
||||||
|
if (mat.materialSet == VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
std::string abs = assets->assetPath(rel);
|
mat.materialSet = _earth_patch_material_allocator.allocate(device->device(), _earth_patch_material_layout);
|
||||||
std::error_code ec;
|
|
||||||
if (!abs.empty() && std::filesystem::exists(abs, ec) && !ec)
|
DescriptorWriter writer;
|
||||||
|
writer.write_buffer(0,
|
||||||
|
_earth_patch_material_constants_buffer.buffer,
|
||||||
|
sizeof(GLTFMetallic_Roughness::MaterialConstants),
|
||||||
|
0,
|
||||||
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||||
|
writer.write_image(1,
|
||||||
|
checker,
|
||||||
|
tileSampler,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||||
|
writer.write_image(2,
|
||||||
|
white,
|
||||||
|
tileSampler,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||||
|
writer.write_image(3,
|
||||||
|
flatNormal,
|
||||||
|
tileSampler,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||||
|
writer.write_image(4,
|
||||||
|
white,
|
||||||
|
tileSampler,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||||
|
writer.write_image(5,
|
||||||
|
black,
|
||||||
|
tileSampler,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||||
|
writer.update_set(device->device(), mat.materialSet);
|
||||||
|
|
||||||
|
if (textures && tileSampler != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
resolved_path = std::move(abs);
|
const planet::CubeFace face = static_cast<planet::CubeFace>(face_index);
|
||||||
break;
|
const std::string rel = fmt::format("planets/earth/albedo/L0/{}.ktx2", face_legacy(face));
|
||||||
|
|
||||||
|
TextureCache::TextureKey tk{};
|
||||||
|
tk.kind = TextureCache::TextureKey::SourceKind::FilePath;
|
||||||
|
tk.path = assets->assetPath(rel);
|
||||||
|
tk.srgb = true;
|
||||||
|
tk.mipmapped = true;
|
||||||
|
|
||||||
|
TextureCache::TextureHandle h = textures->request(tk, tileSampler);
|
||||||
|
textures->watchBinding(h, mat.materialSet, 1u, tileSampler, checker);
|
||||||
|
textures->pin(h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resolved_path.empty())
|
|
||||||
{
|
|
||||||
TextureCache::TextureKey tk{};
|
|
||||||
tk.kind = TextureCache::TextureKey::SourceKind::FilePath;
|
|
||||||
tk.path = resolved_path;
|
|
||||||
tk.srgb = true;
|
|
||||||
tk.mipmapped = true;
|
|
||||||
|
|
||||||
TextureCache::TextureHandle h = _context->textures->request(tk, tileSampler);
|
|
||||||
_context->textures->watchBinding(h, patch.material_instance.materialSet, 1u, tileSampler, checker);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,6 +596,9 @@ PlanetSystem::EarthPatch *PlanetSystem::get_or_create_earth_patch(const PlanetBo
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const glm::vec4 vertex_color =
|
||||||
|
_earth_debug_tint_patches_by_lod ? debug_color_for_level(key.level) : glm::vec4(1.0f);
|
||||||
|
|
||||||
std::vector<Vertex> vertices;
|
std::vector<Vertex> vertices;
|
||||||
const glm::dvec3 patch_center_dir =
|
const glm::dvec3 patch_center_dir =
|
||||||
planet::build_cubesphere_patch_vertices(vertices,
|
planet::build_cubesphere_patch_vertices(vertices,
|
||||||
@@ -593,7 +608,7 @@ PlanetSystem::EarthPatch *PlanetSystem::get_or_create_earth_patch(const PlanetBo
|
|||||||
key.x,
|
key.x,
|
||||||
key.y,
|
key.y,
|
||||||
_earth_patch_resolution,
|
_earth_patch_resolution,
|
||||||
debug_color_for_level(key.level));
|
vertex_color);
|
||||||
|
|
||||||
if (vertices.empty())
|
if (vertices.empty())
|
||||||
{
|
{
|
||||||
@@ -647,8 +662,6 @@ PlanetSystem::EarthPatch *PlanetSystem::get_or_create_earth_patch(const PlanetBo
|
|||||||
_earth_patch_lru.push_front(idx);
|
_earth_patch_lru.push_front(idx);
|
||||||
p.lru_it = _earth_patch_lru.begin();
|
p.lru_it = _earth_patch_lru.begin();
|
||||||
|
|
||||||
ensure_earth_patch_material_instance(p, earth);
|
|
||||||
|
|
||||||
_earth_patch_lookup.emplace(key, idx);
|
_earth_patch_lookup.emplace(key, idx);
|
||||||
return &p;
|
return &p;
|
||||||
}
|
}
|
||||||
@@ -677,7 +690,6 @@ void PlanetSystem::trim_earth_patch_cache()
|
|||||||
}
|
}
|
||||||
|
|
||||||
FrameResources *frame = _context->currentFrame;
|
FrameResources *frame = _context->currentFrame;
|
||||||
TextureCache *textures = _context->textures;
|
|
||||||
const uint32_t now = _earth_patch_frame_stamp;
|
const uint32_t now = _earth_patch_frame_stamp;
|
||||||
|
|
||||||
size_t guard = 0;
|
size_t guard = 0;
|
||||||
@@ -712,11 +724,6 @@ void PlanetSystem::trim_earth_patch_cache()
|
|||||||
_earth_patch_lru.erase(p.lru_it);
|
_earth_patch_lru.erase(p.lru_it);
|
||||||
_earth_patch_lookup.erase(p.key);
|
_earth_patch_lookup.erase(p.key);
|
||||||
|
|
||||||
if (textures && p.material_instance.materialSet != VK_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
textures->unwatchSet(p.material_instance.materialSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p.vertex_buffer.buffer != VK_NULL_HANDLE)
|
if (p.vertex_buffer.buffer != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
const AllocatedBuffer vb = p.vertex_buffer;
|
const AllocatedBuffer vb = p.vertex_buffer;
|
||||||
@@ -730,9 +737,7 @@ void PlanetSystem::trim_earth_patch_cache()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VkDescriptorSet keep_set = p.material_instance.materialSet;
|
|
||||||
p = EarthPatch{};
|
p = EarthPatch{};
|
||||||
p.material_instance.materialSet = keep_set;
|
|
||||||
_earth_patch_free.push_back(idx);
|
_earth_patch_free.push_back(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -755,6 +760,12 @@ void PlanetSystem::update_and_emit(const SceneManager &scene, DrawContext &draw_
|
|||||||
PlanetBody *earth = get_body(BodyID::Earth);
|
PlanetBody *earth = get_body(BodyID::Earth);
|
||||||
if (earth && earth->visible && earth->material && _context)
|
if (earth && earth->visible && earth->material && _context)
|
||||||
{
|
{
|
||||||
|
if (_earth_patch_cache_dirty)
|
||||||
|
{
|
||||||
|
clear_earth_patch_cache();
|
||||||
|
_earth_patch_cache_dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
const Clock::time_point t0 = Clock::now();
|
const Clock::time_point t0 = Clock::now();
|
||||||
|
|
||||||
_earth_quadtree.set_settings(_earth_quadtree_settings);
|
_earth_quadtree.set_settings(_earth_quadtree_settings);
|
||||||
@@ -772,6 +783,17 @@ void PlanetSystem::update_and_emit(const SceneManager &scene, DrawContext &draw_
|
|||||||
const Clock::time_point t_q1 = Clock::now();
|
const Clock::time_point t_q1 = Clock::now();
|
||||||
|
|
||||||
ensure_earth_patch_index_buffer();
|
ensure_earth_patch_index_buffer();
|
||||||
|
ensure_earth_face_materials(*earth);
|
||||||
|
if (_context->textures)
|
||||||
|
{
|
||||||
|
for (const MaterialInstance &mat : _earth_face_materials)
|
||||||
|
{
|
||||||
|
if (mat.materialSet != VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
_context->textures->markSetUsed(mat.materialSet, _context->frameIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t desired_capacity =
|
size_t desired_capacity =
|
||||||
static_cast<size_t>(_earth_patches.size()) +
|
static_cast<size_t>(_earth_patches.size()) +
|
||||||
@@ -809,10 +831,6 @@ void PlanetSystem::update_and_emit(const SceneManager &scene, DrawContext &draw_
|
|||||||
{
|
{
|
||||||
patch->last_used_frame = frame_index;
|
patch->last_used_frame = frame_index;
|
||||||
_earth_patch_lru.splice(_earth_patch_lru.begin(), _earth_patch_lru, patch->lru_it);
|
_earth_patch_lru.splice(_earth_patch_lru.begin(), _earth_patch_lru, patch->lru_it);
|
||||||
if (patch->material_instance.materialSet == VK_NULL_HANDLE || patch->material_instance.pipeline == nullptr)
|
|
||||||
{
|
|
||||||
ensure_earth_patch_material_instance(*patch, *earth);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -850,14 +868,23 @@ void PlanetSystem::update_and_emit(const SceneManager &scene, DrawContext &draw_
|
|||||||
if (patch.state != EarthPatchState::Ready ||
|
if (patch.state != EarthPatchState::Ready ||
|
||||||
patch.vertex_buffer.buffer == VK_NULL_HANDLE ||
|
patch.vertex_buffer.buffer == VK_NULL_HANDLE ||
|
||||||
patch.vertex_buffer_address == 0 ||
|
patch.vertex_buffer_address == 0 ||
|
||||||
patch.material_instance.materialSet == VK_NULL_HANDLE ||
|
|
||||||
patch.material_instance.pipeline == nullptr ||
|
|
||||||
_earth_patch_index_buffer.buffer == VK_NULL_HANDLE ||
|
_earth_patch_index_buffer.buffer == VK_NULL_HANDLE ||
|
||||||
_earth_patch_index_count == 0)
|
_earth_patch_index_count == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint32_t face_index = static_cast<uint32_t>(patch.key.face);
|
||||||
|
if (face_index >= _earth_face_materials.size())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
MaterialInstance *material = &_earth_face_materials[face_index];
|
||||||
|
if (material->materialSet == VK_NULL_HANDLE || material->pipeline == nullptr)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const WorldVec3 patch_center_world =
|
const WorldVec3 patch_center_world =
|
||||||
earth->center_world + patch.patch_center_dir * earth->radius_m;
|
earth->center_world + patch.patch_center_dir * earth->radius_m;
|
||||||
const glm::vec3 patch_center_local = world_to_local(patch_center_world, origin_world);
|
const glm::vec3 patch_center_local = world_to_local(patch_center_world, origin_world);
|
||||||
@@ -875,7 +902,7 @@ void PlanetSystem::update_and_emit(const SceneManager &scene, DrawContext &draw_
|
|||||||
obj.indexBuffer = _earth_patch_index_buffer.buffer;
|
obj.indexBuffer = _earth_patch_index_buffer.buffer;
|
||||||
obj.vertexBuffer = patch.vertex_buffer.buffer;
|
obj.vertexBuffer = patch.vertex_buffer.buffer;
|
||||||
obj.vertexBufferAddress = patch.vertex_buffer_address;
|
obj.vertexBufferAddress = patch.vertex_buffer_address;
|
||||||
obj.material = &patch.material_instance;
|
obj.material = material;
|
||||||
obj.bounds = b;
|
obj.bounds = b;
|
||||||
obj.transform = transform;
|
obj.transform = transform;
|
||||||
// Planet terrain patches are not meaningful RT occluders; skip BLAS/TLAS builds.
|
// Planet terrain patches are not meaningful RT occluders; skip BLAS/TLAS builds.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <scene/planet/planet_quadtree.h>
|
#include <scene/planet/planet_quadtree.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <array>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -75,6 +76,9 @@ public:
|
|||||||
uint32_t earth_patch_cache_max() const { return _earth_patch_cache_max; }
|
uint32_t earth_patch_cache_max() const { return _earth_patch_cache_max; }
|
||||||
void set_earth_patch_cache_max(uint32_t max_patches) { _earth_patch_cache_max = max_patches; }
|
void set_earth_patch_cache_max(uint32_t max_patches) { _earth_patch_cache_max = max_patches; }
|
||||||
|
|
||||||
|
bool earth_debug_tint_patches_by_lod() const { return _earth_debug_tint_patches_by_lod; }
|
||||||
|
void set_earth_debug_tint_patches_by_lod(bool enabled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class EarthPatchState : uint8_t
|
enum class EarthPatchState : uint8_t
|
||||||
{
|
{
|
||||||
@@ -90,8 +94,6 @@ private:
|
|||||||
AllocatedBuffer vertex_buffer{};
|
AllocatedBuffer vertex_buffer{};
|
||||||
VkDeviceAddress vertex_buffer_address = 0;
|
VkDeviceAddress vertex_buffer_address = 0;
|
||||||
|
|
||||||
MaterialInstance material_instance{};
|
|
||||||
|
|
||||||
glm::vec3 bounds_origin{0.0f};
|
glm::vec3 bounds_origin{0.0f};
|
||||||
glm::vec3 bounds_extents{0.5f};
|
glm::vec3 bounds_extents{0.5f};
|
||||||
float bounds_sphere_radius = 0.5f;
|
float bounds_sphere_radius = 0.5f;
|
||||||
@@ -109,7 +111,8 @@ private:
|
|||||||
void ensure_earth_patch_index_buffer();
|
void ensure_earth_patch_index_buffer();
|
||||||
void ensure_earth_patch_material_layout();
|
void ensure_earth_patch_material_layout();
|
||||||
void ensure_earth_patch_material_constants_buffer();
|
void ensure_earth_patch_material_constants_buffer();
|
||||||
void ensure_earth_patch_material_instance(EarthPatch &patch, const PlanetBody &earth);
|
void ensure_earth_face_materials(const PlanetBody &earth);
|
||||||
|
void clear_earth_patch_cache();
|
||||||
void trim_earth_patch_cache();
|
void trim_earth_patch_cache();
|
||||||
|
|
||||||
EngineContext *_context = nullptr;
|
EngineContext *_context = nullptr;
|
||||||
@@ -132,10 +135,14 @@ private:
|
|||||||
DescriptorAllocatorGrowable _earth_patch_material_allocator{};
|
DescriptorAllocatorGrowable _earth_patch_material_allocator{};
|
||||||
bool _earth_patch_material_allocator_initialized = false;
|
bool _earth_patch_material_allocator_initialized = false;
|
||||||
AllocatedBuffer _earth_patch_material_constants_buffer{};
|
AllocatedBuffer _earth_patch_material_constants_buffer{};
|
||||||
|
std::array<MaterialInstance, 6> _earth_face_materials{};
|
||||||
|
|
||||||
uint32_t _earth_patch_frame_stamp = 0;
|
uint32_t _earth_patch_frame_stamp = 0;
|
||||||
uint32_t _earth_patch_resolution = 33;
|
uint32_t _earth_patch_resolution = 33;
|
||||||
uint32_t _earth_patch_create_budget_per_frame = 16;
|
uint32_t _earth_patch_create_budget_per_frame = 16;
|
||||||
float _earth_patch_create_budget_ms = 2.0f;
|
float _earth_patch_create_budget_ms = 2.0f;
|
||||||
uint32_t _earth_patch_cache_max = 2048;
|
uint32_t _earth_patch_cache_max = 2048;
|
||||||
|
|
||||||
|
bool _earth_debug_tint_patches_by_lod = false;
|
||||||
|
bool _earth_patch_cache_dirty = false;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user