ADD: planet quadtree texture enabled
This commit is contained in:
@@ -2273,6 +2273,12 @@ namespace
|
||||
auto settings = planets->earth_quadtree_settings();
|
||||
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);
|
||||
if (ImGui::SliderInt("Max LOD level", &maxLevel, 0, 20))
|
||||
{
|
||||
|
||||
@@ -192,6 +192,9 @@ namespace planet
|
||||
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));
|
||||
|
||||
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 du = (u1 - u0) * inv;
|
||||
const double dv = (v1 - v0) * inv;
|
||||
@@ -215,8 +218,13 @@ namespace planet
|
||||
vert.normal = glm::vec3(static_cast<float>(unit_dir.x),
|
||||
static_cast<float>(unit_dir.y),
|
||||
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.tangent = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <filesystem>
|
||||
|
||||
#include "device.h"
|
||||
|
||||
@@ -79,6 +78,16 @@ void PlanetSystem::init(EngineContext *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()
|
||||
{
|
||||
if (!_context)
|
||||
@@ -89,11 +98,11 @@ void PlanetSystem::cleanup()
|
||||
TextureCache *textures = _context->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_free.clear();
|
||||
_earth_patches.clear();
|
||||
_earth_face_materials = {};
|
||||
|
||||
_earth_patch_index_count = 0;
|
||||
_earth_patch_index_resolution = 0;
|
||||
@@ -235,6 +245,46 @@ PlanetSystem::EarthPatch *PlanetSystem::find_earth_patch(const planet::PatchKey
|
||||
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()
|
||||
{
|
||||
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)
|
||||
{
|
||||
FrameResources *frame = _context->currentFrame;
|
||||
TextureCache *textures = _context->textures;
|
||||
|
||||
// Destroy per-patch vertex buffers.
|
||||
for (const auto &kv : _earth_patch_lookup)
|
||||
@@ -286,28 +335,8 @@ void PlanetSystem::ensure_earth_patch_index_buffer()
|
||||
|
||||
_earth_patch_lookup.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.reserve(_earth_patches.size());
|
||||
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);
|
||||
}
|
||||
_earth_patches.clear();
|
||||
|
||||
const AllocatedBuffer ib = _earth_patch_index_buffer;
|
||||
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)
|
||||
{
|
||||
@@ -418,6 +447,7 @@ void PlanetSystem::ensure_earth_patch_material_instance(EarthPatch &patch, const
|
||||
DeviceManager *device = _context->getDevice();
|
||||
SamplerManager *samplers = _context->getSamplers();
|
||||
AssetManager *assets = _context->assets;
|
||||
TextureCache *textures = _context->textures;
|
||||
if (!device || !assets)
|
||||
{
|
||||
return;
|
||||
@@ -438,24 +468,19 @@ void PlanetSystem::ensure_earth_patch_material_instance(EarthPatch &patch, const
|
||||
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
|
||||
{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;
|
||||
}
|
||||
|
||||
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;
|
||||
if (tileSampler == VK_NULL_HANDLE && samplers)
|
||||
{
|
||||
tileSampler = samplers->defaultLinear();
|
||||
}
|
||||
if (tileSampler == VK_NULL_HANDLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
VkImageView checker = assets->fallback_checkerboard_view();
|
||||
VkImageView white = assets->fallback_white_view();
|
||||
@@ -467,8 +492,30 @@ void PlanetSystem::ensure_earth_patch_material_instance(EarthPatch &patch, const
|
||||
if (flatNormal == VK_NULL_HANDLE) flatNormal = 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)
|
||||
{
|
||||
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";
|
||||
};
|
||||
|
||||
for (size_t face_index = 0; face_index < _earth_face_materials.size(); ++face_index)
|
||||
{
|
||||
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)
|
||||
{
|
||||
mat.materialSet = _earth_patch_material_allocator.allocate(device->device(), _earth_patch_material_layout);
|
||||
|
||||
DescriptorWriter writer;
|
||||
writer.write_buffer(0,
|
||||
_earth_patch_material_constants_buffer.buffer,
|
||||
@@ -500,58 +547,23 @@ void PlanetSystem::ensure_earth_patch_material_instance(EarthPatch &patch, const
|
||||
tileSampler,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||
writer.update_set(device->device(), patch.material_instance.materialSet);
|
||||
}
|
||||
writer.update_set(device->device(), mat.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)
|
||||
if (textures && tileSampler != 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::CubeFace face = static_cast<planet::CubeFace>(face_index);
|
||||
const std::string rel = fmt::format("planets/earth/albedo/L0/{}.ktx2", face_legacy(face));
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
std::string resolved_path;
|
||||
for (const std::string &rel : candidates)
|
||||
{
|
||||
std::string abs = assets->assetPath(rel);
|
||||
std::error_code ec;
|
||||
if (!abs.empty() && std::filesystem::exists(abs, ec) && !ec)
|
||||
{
|
||||
resolved_path = std::move(abs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!resolved_path.empty())
|
||||
{
|
||||
TextureCache::TextureKey tk{};
|
||||
tk.kind = TextureCache::TextureKey::SourceKind::FilePath;
|
||||
tk.path = resolved_path;
|
||||
tk.path = assets->assetPath(rel);
|
||||
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);
|
||||
TextureCache::TextureHandle h = textures->request(tk, tileSampler);
|
||||
textures->watchBinding(h, mat.materialSet, 1u, tileSampler, checker);
|
||||
textures->pin(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -584,6 +596,9 @@ PlanetSystem::EarthPatch *PlanetSystem::get_or_create_earth_patch(const PlanetBo
|
||||
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;
|
||||
const glm::dvec3 patch_center_dir =
|
||||
planet::build_cubesphere_patch_vertices(vertices,
|
||||
@@ -593,7 +608,7 @@ PlanetSystem::EarthPatch *PlanetSystem::get_or_create_earth_patch(const PlanetBo
|
||||
key.x,
|
||||
key.y,
|
||||
_earth_patch_resolution,
|
||||
debug_color_for_level(key.level));
|
||||
vertex_color);
|
||||
|
||||
if (vertices.empty())
|
||||
{
|
||||
@@ -647,8 +662,6 @@ PlanetSystem::EarthPatch *PlanetSystem::get_or_create_earth_patch(const PlanetBo
|
||||
_earth_patch_lru.push_front(idx);
|
||||
p.lru_it = _earth_patch_lru.begin();
|
||||
|
||||
ensure_earth_patch_material_instance(p, earth);
|
||||
|
||||
_earth_patch_lookup.emplace(key, idx);
|
||||
return &p;
|
||||
}
|
||||
@@ -677,7 +690,6 @@ void PlanetSystem::trim_earth_patch_cache()
|
||||
}
|
||||
|
||||
FrameResources *frame = _context->currentFrame;
|
||||
TextureCache *textures = _context->textures;
|
||||
const uint32_t now = _earth_patch_frame_stamp;
|
||||
|
||||
size_t guard = 0;
|
||||
@@ -712,11 +724,6 @@ void PlanetSystem::trim_earth_patch_cache()
|
||||
_earth_patch_lru.erase(p.lru_it);
|
||||
_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)
|
||||
{
|
||||
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.material_instance.materialSet = keep_set;
|
||||
_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);
|
||||
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();
|
||||
|
||||
_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();
|
||||
|
||||
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 =
|
||||
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;
|
||||
_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
|
||||
{
|
||||
@@ -850,14 +868,23 @@ void PlanetSystem::update_and_emit(const SceneManager &scene, DrawContext &draw_
|
||||
if (patch.state != EarthPatchState::Ready ||
|
||||
patch.vertex_buffer.buffer == VK_NULL_HANDLE ||
|
||||
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_count == 0)
|
||||
{
|
||||
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 =
|
||||
earth->center_world + patch.patch_center_dir * earth->radius_m;
|
||||
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.vertexBuffer = patch.vertex_buffer.buffer;
|
||||
obj.vertexBufferAddress = patch.vertex_buffer_address;
|
||||
obj.material = &patch.material_instance;
|
||||
obj.material = material;
|
||||
obj.bounds = b;
|
||||
obj.transform = transform;
|
||||
// Planet terrain patches are not meaningful RT occluders; skip BLAS/TLAS builds.
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <scene/planet/planet_quadtree.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -75,6 +76,9 @@ public:
|
||||
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; }
|
||||
|
||||
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:
|
||||
enum class EarthPatchState : uint8_t
|
||||
{
|
||||
@@ -90,8 +94,6 @@ private:
|
||||
AllocatedBuffer vertex_buffer{};
|
||||
VkDeviceAddress vertex_buffer_address = 0;
|
||||
|
||||
MaterialInstance material_instance{};
|
||||
|
||||
glm::vec3 bounds_origin{0.0f};
|
||||
glm::vec3 bounds_extents{0.5f};
|
||||
float bounds_sphere_radius = 0.5f;
|
||||
@@ -109,7 +111,8 @@ private:
|
||||
void ensure_earth_patch_index_buffer();
|
||||
void ensure_earth_patch_material_layout();
|
||||
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();
|
||||
|
||||
EngineContext *_context = nullptr;
|
||||
@@ -132,10 +135,14 @@ private:
|
||||
DescriptorAllocatorGrowable _earth_patch_material_allocator{};
|
||||
bool _earth_patch_material_allocator_initialized = false;
|
||||
AllocatedBuffer _earth_patch_material_constants_buffer{};
|
||||
std::array<MaterialInstance, 6> _earth_face_materials{};
|
||||
|
||||
uint32_t _earth_patch_frame_stamp = 0;
|
||||
uint32_t _earth_patch_resolution = 33;
|
||||
uint32_t _earth_patch_create_budget_per_frame = 16;
|
||||
float _earth_patch_create_budget_ms = 2.0f;
|
||||
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