feat: 透明材质 alpha blending——独立队列 + 线性 over 混合 + 距离排序
透明来源:glTF alphaMode=BLEND(解析期读取,OBJ/FBX 恒不透明—— 资产格式定义写死);MASK 后续演进。Material 加透明语义(入缓存键), 程序化测试资产 CreateTransparentPlane(RGBA 纯色纹理)。 SceneRenderer:透明材质实例收集进独立 scratch(仅主视图,不投 阴影——alpha 阴影后续演进),batch 按平均距离降序排序(远→近, batchMats 同步重排),SSBO 扁平化顺序 = 排序后顺序。 ForwardPass 两段绘制:不透明(无混合 + 深度写)→ 透明(Shader Object 动态状态切 SRC_ALPHA/ONE_MINUS_SRC_ALPHA 线性 over + 深度 只测不写);velocity 附件透明段直写(透明表面 velocity 即自身运动)。 frag alpha = albedo 贴图 a 直通,预乘在 tonemap 段(hard constraint 不变)。已知边界:TAA alpha 时域混合(透明边缘几帧渐显);同 batch 多实例不做实例级排序。
This commit is contained in:
@@ -157,6 +157,9 @@ namespace Engine
|
||||
|
||||
// 程序化平面(纯色贴图):size 为半边长。带缓存,同参数共享一份。
|
||||
ModelRef CreatePlane(f32 halfSize, u8 r, u8 g, u8 b);
|
||||
// 半透明平面(alpha 0-255,透明绘制队列):同参数缓存去重
|
||||
ModelRef CreateTransparentPlane(f32 halfSize,
|
||||
u8 r, u8 g, u8 b, u8 a);
|
||||
|
||||
// 环境资产(HDR → IBL 预积分四件套)。路径缓存去重,
|
||||
// 重复 Load 同一路径零成本(动态切换场景直接反复调用)
|
||||
|
||||
@@ -37,6 +37,10 @@ namespace Engine::Assets {
|
||||
// 程序化纯色平面(size 为半边长)
|
||||
virtual Scope<Model> CreatePlane(f32 halfSize, u8 r, u8 g, u8 b) = 0;
|
||||
|
||||
// 半透明纯色平面(alpha 0-255,透明绘制队列)
|
||||
virtual Scope<Model> CreateTransparentPlane(f32 halfSize,
|
||||
u8 r, u8 g, u8 b, u8 a) = 0;
|
||||
|
||||
// 环境 HDR → IBL 预积分四件套(compute 生成,毫秒级;失败返回 nullptr)
|
||||
virtual Scope<Cubemap> LoadEnvironment(const std::string& path) = 0;
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ namespace Engine {
|
||||
DescriptorManager& descriptorManager,
|
||||
vk::DescriptorSetLayout layout,
|
||||
const std::array<Texture*, kSlotCount>& textures,
|
||||
const MaterialParams& params);
|
||||
const MaterialParams& params,
|
||||
bool transparent = false);
|
||||
~Material();
|
||||
|
||||
Material(const Material&) = delete;
|
||||
@@ -63,15 +64,19 @@ namespace Engine {
|
||||
|
||||
vk::DescriptorSet GetDescriptorSet() const { return m_DescriptorSet; }
|
||||
Texture* GetTexture(Slot slot) const { return m_Textures[slot]; }
|
||||
// 透明队列归属(glTF alphaMode=BLEND;CPU 收集侧用)
|
||||
bool IsTransparent() const { return m_Transparent; }
|
||||
|
||||
// 材质缓存键:同贴图组合+同因子共享一份(Model 层使用)
|
||||
// 材质缓存键:同贴图组合+同因子+同透明语义共享一份(Model 层使用)
|
||||
static std::string MakeCacheKey(const std::string paths[kSlotCount],
|
||||
const MaterialParams& params);
|
||||
const MaterialParams& params,
|
||||
bool transparent);
|
||||
|
||||
private:
|
||||
std::array<Texture*, kSlotCount> m_Textures{};
|
||||
vk::DescriptorSet m_DescriptorSet;
|
||||
Scope<UniformBuffer> m_ParamsBuffer; // per-slot 参数 ring(创建时写死)
|
||||
bool m_Transparent = false;
|
||||
};
|
||||
} // namespace Engine
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Engine
|
||||
std::vector<std::vector<u32>> lods;
|
||||
std::array<std::string, Material::kSlotCount> texPaths;
|
||||
MaterialParams params;
|
||||
bool transparent = false; // glTF alphaMode=BLEND(透明绘制队列)
|
||||
};
|
||||
struct ParsedModel {
|
||||
std::string path;
|
||||
@@ -74,6 +75,12 @@ namespace Engine
|
||||
DescriptorManager& descriptorManager,
|
||||
vk::DescriptorSetLayout textureLayout,
|
||||
f32 halfSize, u8 r, u8 g, u8 b);
|
||||
// 半透明纯色平面(alpha 0-255,预乘 alpha 链):透明管线验证用
|
||||
static Scope<Model> CreateTransparentPlane(
|
||||
Device& device, MemoryAllocator& allocator,
|
||||
DescriptorManager& descriptorManager,
|
||||
vk::DescriptorSetLayout textureLayout,
|
||||
f32 halfSize, u8 r, u8 g, u8 b, u8 a);
|
||||
|
||||
~Model();
|
||||
|
||||
@@ -89,7 +96,8 @@ namespace Engine
|
||||
Model(Device& device, MemoryAllocator& allocator,
|
||||
DescriptorManager& descriptorManager,
|
||||
vk::DescriptorSetLayout textureLayout,
|
||||
ProceduralTag, f32 halfSize, const std::array<u8, 3>& color);
|
||||
ProceduralTag, f32 halfSize, const std::array<u8, 4>& rgba,
|
||||
bool transparent);
|
||||
|
||||
// 空模型骨架(FromParsed 用):只建默认纹理,mesh 由调用方填
|
||||
Model(Device& device, MemoryAllocator& allocator,
|
||||
@@ -111,11 +119,12 @@ namespace Engine
|
||||
|
||||
Texture* GetOrLoadTexture(const std::string& path, bool srgb);
|
||||
|
||||
// 材质缓存入口:同贴图组合+因子共享同一 Material(一个描述符集),
|
||||
// 材质缓存入口:同贴图组合+同因子+同透明语义共享一份 Material,
|
||||
// 槽位路径为空/文件缺失折到对应默认纹理。路径已做反斜杠归一化。
|
||||
// paths 下标 = Material::Slot;params = metallic/roughness 因子
|
||||
Material* GetOrCreateMaterial(const std::string paths[Material::kSlotCount],
|
||||
const MaterialParams& params);
|
||||
const MaterialParams& params,
|
||||
bool transparent = false);
|
||||
|
||||
Device& m_Device;
|
||||
MemoryAllocator& m_Allocator;
|
||||
|
||||
@@ -80,6 +80,8 @@ namespace Engine {
|
||||
// firstInstance + 连续区间,实体序收集不满足(多实体共享 mesh
|
||||
// 时实例分散各处),扁平化成连续数组推迟到 appendView
|
||||
std::vector<std::vector<InstanceMatrices>> batchMats;
|
||||
// 每 batch 实例距离累加(透明排序用:平均距离降序 = 远→近)
|
||||
std::vector<f32> batchDistSum;
|
||||
// batch 查找:数组寻址(下标 = Mesh::GetSlot(),值 = 每 LOD 的
|
||||
// batchIdx+1,0 = 未用)——逐实例 hash 在大场景是毫秒级开销
|
||||
std::vector<std::array<u32, kMeshLodCount>> lookup;
|
||||
@@ -89,11 +91,13 @@ namespace Engine {
|
||||
result.batches.clear();
|
||||
result.instanceCount = 0;
|
||||
batchMats.clear();
|
||||
batchDistSum.clear();
|
||||
for (auto& e : lookup) e.fill(0); // 容量保留,置零复用
|
||||
}
|
||||
};
|
||||
ViewScratch m_MainScratch;
|
||||
ViewScratch m_CascScratch[kMaxCascades];
|
||||
ViewScratch m_TranslucentScratch; // 透明材质(仅主视图,不投阴影)
|
||||
|
||||
// ---- TAA 时域状态 ----
|
||||
u64 m_FrameIndex = 0; // 抖动序列游标(Halton 2,3 ×8 采样)
|
||||
|
||||
@@ -91,6 +91,9 @@ namespace Engine {
|
||||
// 每级联独立剔除结果(Shadow pass 按 region 各画各的——
|
||||
// 级联盒沿光方向加了 caster pad,影子不会被剔除裁掉)
|
||||
CullResult shadowCascades[kMaxCascades];
|
||||
// 透明批次(预乘 alpha 混合,深度只测不写,远→近排序);
|
||||
// 不参与阴影投射
|
||||
CullResult translucentView;
|
||||
|
||||
// ---- 运行时开关/调试视图(ImGui 经 Renderer 门面写入,
|
||||
// SceneRenderer 唯一落帧,各 pass 只读;每帧确定性)----
|
||||
|
||||
@@ -35,6 +35,8 @@ namespace Engine {
|
||||
Scope<Model> LoadModel(const std::string& path,
|
||||
ParsedModel&& parsed) override;
|
||||
Scope<Model> CreatePlane(f32 halfSize, u8 r, u8 g, u8 b) override;
|
||||
Scope<Model> CreateTransparentPlane(f32 halfSize,
|
||||
u8 r, u8 g, u8 b, u8 a) override;
|
||||
Scope<Cubemap> LoadEnvironment(const std::string& path) override;
|
||||
Scope<Cubemap> LoadEnvironment(const std::string& path,
|
||||
DecodedEquirect&& decoded) override;
|
||||
|
||||
@@ -31,6 +31,9 @@ namespace Engine {
|
||||
struct ProceduralTag {};
|
||||
static Scope<Texture> CreateSolidColor(Device& device, MemoryAllocator& allocator,
|
||||
u8 r, u8 g, u8 b, bool srgb = true);
|
||||
// 带 alpha 的纯色纹理(透明管线验证等)
|
||||
static Scope<Texture> CreateSolidColorRGBA(Device& device, MemoryAllocator& allocator,
|
||||
u8 r, u8 g, u8 b, u8 a, bool srgb = true);
|
||||
|
||||
~Texture();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user