fix: 视锥剔除平面归一化(透视因数误剔)+ 材质去重 + 描述符池可增长
- Frustum::FromMatrix 平面归一化:Gribb-Hartmann 提取的 left/right/ bottom/top 法线模长含 1/tan(fov/2) 因子(>1),未归一化时包围球 距离测试被放大,视锥边缘物体被误剔(SunTemple 全场景可见)—— 修正注释:必须传 [0,1] 重映射矩阵 - 材质去重:Model 新增 MaterialCache(按贴图路径共享 Material), Mesh 改持 Material* 非拥有指针。1056 mesh 渲染只需 48 个描述符集 (对齐 UE/Unity 材质实例化思路,大场景第一道闸门) - DescriptorManager 池改可增长分块(chunk=4096,OutOfPool/Fragmented 自动续块):材质集数量不可预估(1G 资产可能上万),固定上限迟早爆
This commit is contained in:
@@ -18,8 +18,8 @@ namespace Engine
|
||||
Mesh::Mesh(Device& device, MemoryAllocator& allocator,
|
||||
const std::vector<Vertex>& vertices,
|
||||
const std::vector<u32>& indices,
|
||||
Scope<Material> material)
|
||||
: m_Material(std::move(material))
|
||||
Material* material)
|
||||
: m_Material(material)
|
||||
{
|
||||
if (vertices.empty() || indices.empty())
|
||||
{
|
||||
|
||||
@@ -59,14 +59,12 @@ Model::Model(Device& device, MemoryAllocator& allocator,
|
||||
};
|
||||
const std::vector<u32> indices = {0, 1, 2, 0, 2, 3};
|
||||
|
||||
auto mat = CreateScope<Material>(
|
||||
m_Device, m_DescriptorManager, m_TextureLayout, tex.get());
|
||||
// 贴图/材质生命周期随模型(缓存持有)
|
||||
m_DefaultTexture = std::move(tex);
|
||||
Material* mat = GetOrCreateMaterial(""); // 兜底材质
|
||||
|
||||
m_Meshes.push_back(CreateScope<Mesh>(
|
||||
m_Device, m_Allocator, vertices, indices, std::move(mat)));
|
||||
|
||||
// 贴图生命周期随模型
|
||||
m_DefaultTexture = std::move(tex);
|
||||
m_Device, m_Allocator, vertices, indices, mat));
|
||||
}
|
||||
|
||||
Scope<Model> Model::CreatePlane(Device& device, MemoryAllocator& allocator,
|
||||
@@ -134,6 +132,34 @@ Texture* Model::GetOrLoadTexture(const std::string& rawPath)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
Material* Model::GetOrCreateMaterial(const std::string& rawPath)
|
||||
{
|
||||
// 路径归一化 + 空路径/缺文件统一折到兜底材质(缓存键 "")
|
||||
std::string path = rawPath;
|
||||
std::replace(path.begin(), path.end(), '\\', '/');
|
||||
|
||||
if (path.empty() || !std::filesystem::exists(path)) {
|
||||
if (!rawPath.empty()) {
|
||||
ENGINE_WARN("Texture not found, using default: {}", path);
|
||||
}
|
||||
path.clear();
|
||||
}
|
||||
|
||||
if (auto it = m_MaterialCache.find(path); it != m_MaterialCache.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
Texture* tex = path.empty()
|
||||
? m_DefaultTexture.get()
|
||||
: GetOrLoadTexture(path);
|
||||
|
||||
auto mat = CreateScope<Material>(
|
||||
m_Device, m_DescriptorManager, m_TextureLayout, tex);
|
||||
Material* ptr = mat.get();
|
||||
m_MaterialCache.emplace(path, std::move(mat));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
Scope<Mesh> Model::ProcessMesh(aiMesh* mesh, const aiScene* scene)
|
||||
{
|
||||
std::vector<Vertex> vertices;
|
||||
@@ -189,16 +215,11 @@ Scope<Mesh> Model::ProcessMesh(aiMesh* mesh, const aiScene* scene)
|
||||
}
|
||||
}
|
||||
|
||||
// 从缓存拿,没有才加载
|
||||
Texture* tex = texturePath.empty()
|
||||
? m_DefaultTexture.get()
|
||||
: GetOrLoadTexture(texturePath);
|
||||
|
||||
auto mat = CreateScope<Material>(
|
||||
m_Device, m_DescriptorManager, m_TextureLayout, tex);
|
||||
// 材质缓存:同贴图 → 同一 Material(一个描述符集),mesh 数 ≠ 集数
|
||||
Material* mat = GetOrCreateMaterial(texturePath);
|
||||
|
||||
return CreateScope<Mesh>(
|
||||
m_Device, m_Allocator, vertices, indices, std::move(mat));
|
||||
m_Device, m_Allocator, vertices, indices, mat);
|
||||
}
|
||||
|
||||
} // namespace Engine
|
||||
Reference in New Issue
Block a user