- 动画:HumanoidRig 三层架构(standard 标准槽 / dialects 方言映射 / mapper 配对), 指/趾统一走世界增量两遍式烘焙;AnimationAttach 拆为纯算法 + facade;修正 HumanoidBasis 行走基朝向与跨骨架去重、根运动通道 - 物理:CharacterController 角色互碰撞 / shapeOffset / 接触事件;PhysicsWorld 接触合成与 字符冲量判定 - 渲染与材质:Model 多材质按材质拆子 mesh 与贴图路径解析、DDS 直传、GLB 内嵌纹理落盘、 不透明通道 alpha 固定 1.0、glTF FlipUVs 对齐;SceneSerializer 支持 meshIndex 与材质覆盖 - 脚本:FractureLib 抽为共享库(HostView 桥接)、WallFracture 参数直绑、新增 ThirdPersonCamera / Follower / WASDMove 玩法;移除 GameDirector / PlayerController / Target - 编辑器:新增 GamepadPanel、LogPanel(LogRing),改进 Inspector / 材质 / 统计 / 视口面板 - 依赖:vendored ufbx(FBX 5.x/6.x/7.x 全版本解析,替代 assimp 对 FBX 6.1 的拒读)
162 lines
8.5 KiB
C++
162 lines
8.5 KiB
C++
//
|
||
// Created by atdunbg on 2026/9/21.
|
||
//
|
||
// Material:PBR 材质 = 纹理槽组 + 因子参数 UBO + 一个描述符集。
|
||
//
|
||
// 槽位(binding = 槽位序号,与 simple_shader.frag 契约一致):
|
||
// 0 albedo(BaseColor,sRGB) 1 normal(切线空间法线,线性)
|
||
// 2 metallicRoughness(线性:G=粗糙度,B=金属度,glTF 约定)
|
||
// 3 emissive(自发光,sRGB) 4 ao(环境光遮蔽,线性)
|
||
// 5 roughness(独立粗糙度图,R 通道——FBX/OBJ specular 工作流,
|
||
// glTF 合图工作流不用此槽)
|
||
// 6 材质参数 UBO(fragment,kParamsBinding)
|
||
//
|
||
// 纹理非拥有(Model 的纹理缓存持有);缺槽由调用方传默认纹理。
|
||
// 因子(metallicFactor/roughnessFactor)乘在贴图上:
|
||
// glTF(MR 合图 B=金属度语义)→ 因子取 glTF 声明(默认 1/1),
|
||
// factors.z=0 → shader 直接读 MR.g 当粗糙度
|
||
// FBX(metalness 独立图 + roughness 独立图)→ metal 图落 MR 槽
|
||
// (灰度 R=G=B,.b 读金属度恰好正确),roughness 图落 Roughness
|
||
// 槽,factors.z=1 → shader 用 Roughness.r 替换 MR.g
|
||
// OBJ(specular 工作流)→ metallic=0,独立 roughness 图同 FBX;
|
||
// 无图时 roughness 因子按 Ns 换算
|
||
//
|
||
|
||
#ifndef HELLOVULKAN_MATERIAL_H
|
||
#define HELLOVULKAN_MATERIAL_H
|
||
|
||
#include <Engine/Core/Types.h>
|
||
#include <Engine/Core/FrameContext.h>
|
||
#include <glm/glm.hpp>
|
||
#include <vulkan/vulkan.hpp>
|
||
#include <array>
|
||
#include <string>
|
||
|
||
namespace Engine {
|
||
|
||
class Device;
|
||
class MemoryAllocator;
|
||
class DescriptorManager;
|
||
class Texture;
|
||
class UniformBuffer;
|
||
|
||
// 材质因子(乘贴图;无贴图时即最终值)
|
||
// x = metallic 因子 y = roughness 因子
|
||
// z = 独立粗糙度图开关(1 = 用 Roughness 槽 R 通道替换 MR.g)
|
||
// 注意:与 shader MaterialParams UBO 严格同序同布局(全 vec4,std140
|
||
// 无填充歧义),加字段必须双端同步(simple_shader*.frag)
|
||
struct MaterialParams {
|
||
// x = metallic 因子,y = roughness 因子,z = 独立粗糙度图开关,w = MASK 镂空开关
|
||
// 默认 = 电介质表面推荐值(Unity/UE 同款):
|
||
// metallic = 0 皮肤/头发/布料等非金属的正确值
|
||
// roughness = 1.0 因子语义是"乘贴图",1.0 = 贴图值直用(同 glTF
|
||
// roughnessFactor 缺省);配合兜底 MR 纹理 G=128
|
||
// 得 effective roughness ≈ 0.5,不再是 ×0.5 后的
|
||
// 0.25 假高光(ufbx 路径不写 factors,全靠这里兜底)
|
||
glm::vec4 factors{0.0f, 1.0f, 0.0f, 0.0f};
|
||
// glTF baseColorFactor:rgb 乘进 albedo,a 作 BLEND 透明度
|
||
glm::vec4 baseColor{1.0f, 1.0f, 1.0f, 1.0f};
|
||
// glTF 表面扩展(KHR_materials_ior / transmission / volume /
|
||
// emissive_strength):x = 折射率(F0 = ((ior-1)/(ior+1))²),
|
||
// y = 透射率(0 = 普通表面),z = 自发光强度,w = 体积厚度
|
||
//(折射屏幕偏移的世界距离,0 = 无弯曲直透)
|
||
glm::vec4 surface{1.5f, 0.0f, 1.0f, 0.0f};
|
||
// 杂项语义:
|
||
// x = unlit(KHR_materials_unlit,shader 早退直出 albedo)
|
||
// y = UV 左右镜像(u → 1-u,1 = 开启)
|
||
// z = UV 上下镜像(v → 1-v,1 = 开启)
|
||
// w = 保留
|
||
// 镜像作用于材质全部纹理槽,叠加在每槽 UV 变换(uvA/uvT)之后:
|
||
// 用于纠正源资产 UV 朝向(部分角色 rip 的 UV 与 glTF 上左原点
|
||
// 约定相反,贴图整体翻转)。材质级语义,非单槽
|
||
glm::vec4 misc{0.0f, 0.0f, 0.0f, 0.0f};
|
||
// glTF emissiveFactor:自发光颜色(rgb;黑 = 不发光)。emissive
|
||
// 槽默认兜底纹理是纯黑,无贴图时 Emissive Strength 乘出来恒黑
|
||
// ——无贴图想要发光就调这里(rgb × 贴图 × surface.z)
|
||
glm::vec4 emissiveFactor{0.0f, 0.0f, 0.0f, 0.0f};
|
||
// 每槽 KHR_texture_transform(glTF2 每个 textureInfo 独立声明
|
||
// offset/scale/rotation——烘焙单份顶点 UV 无法表达"一材质多槽
|
||
// 各异变换",收敛为 shader 侧线性式 uv' = A·uv + t,作用在 glTF
|
||
// 规范 UV 空间(v=0 = 图像顶);顶点 UV 经 aiProcess_FlipUVs 已
|
||
// 归一至该空间,A/t 即规范式 off + R(rot)·S(scale)·uv 的摊平,
|
||
// 换算推导见 Model.cpp glTF 分支注释)。
|
||
// uvA[slot] = (a11, a12, a21, a22)(行主 2×2),uvT[slot] = (tx, ty, 0, 0)。
|
||
// 长度必须 = Material::kSlotCount;std140 vec4 数组步长 16B 与
|
||
// CPU 布局天然对齐
|
||
glm::vec4 uvA[6] = {{1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f},
|
||
{1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f},
|
||
{1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}};
|
||
glm::vec4 uvT[6] = {};
|
||
// albedo 贴图 alpha 作细节叠加遮罩(脸部腮红/卧蚕等局部效果):
|
||
// rgb = 叠加色(与 baseColor 同款直乘/直用,不做空间换算),
|
||
// a = 强度(0 = 关闭,mix 恒等无副作用)。alpha 遮罩来自贴图本身,
|
||
// 无 alpha 或 alpha 恒 1 的贴图开启后即等效整体染色
|
||
glm::vec4 alphaOverlay{0.0f, 0.0f, 0.0f, 0.0f};
|
||
};
|
||
|
||
class Material {
|
||
public:
|
||
// 槽位序号(与 binding 对齐)
|
||
enum Slot : u32 {
|
||
Albedo = 0,
|
||
Normal = 1,
|
||
MetallicRoughness = 2,
|
||
Emissive = 3,
|
||
Ao = 4,
|
||
Roughness = 5, // 独立粗糙度图(R 通道)
|
||
kSlotCount = 6, // 纹理槽数
|
||
kParamsBinding = 6, // 参数 UBO binding
|
||
};
|
||
|
||
Material(Device& device, MemoryAllocator& allocator,
|
||
DescriptorManager& descriptorManager,
|
||
vk::DescriptorSetLayout layout,
|
||
const std::array<Texture*, kSlotCount>& textures,
|
||
const MaterialParams& params,
|
||
bool transparent = false);
|
||
~Material();
|
||
|
||
Material(const Material&) = delete;
|
||
Material& operator=(const Material&) = delete;
|
||
|
||
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; }
|
||
|
||
// ---- 编辑器调参入口(零 GPU 重建路径)----
|
||
// 参数直写:全 in-flight 槽同步覆盖写,与 ctor 初始化同一绑定
|
||
// 语义(binding 覆盖写,ring 槽位共用同一 descriptor binding)。
|
||
// 理论上存在 in-flight 帧读到半新半旧参数的撕裂窗口(动态偏移
|
||
// ring 是根治演进点)——UI 段低频编辑 + 48B 小块 memcpy 下实践
|
||
// 无感。纹理槽变化不走这里(那是重建路径,见 MaterialAsset)。
|
||
// 实现外置(UniformBuffer 头文件内仅前置声明)
|
||
void UpdateParams(const MaterialParams& params);
|
||
// 队列归属切换(收集侧 CPU 标志,描述符不变):透明 ↔ 不透明
|
||
void SetTransparent(bool t) { m_Transparent = t; }
|
||
|
||
// 材质缓存键:同贴图组合+同因子+同透明语义共享一份(Model 层使用)
|
||
static std::string MakeCacheKey(const std::string paths[kSlotCount],
|
||
const MaterialParams& params,
|
||
bool transparent);
|
||
|
||
// ---- 预览缩略图身份(editor tile 池的缓存键,game 不消费)----
|
||
// serial:出生唯一号(进程内单调递增,不复用)——裸指针做键有
|
||
// ABA 风险(旧材质析构后新材质恰好分配到同一地址,池误判命中)
|
||
u64 GetSerial() const { return m_Serial; }
|
||
// editVersion:参数编辑代数,UpdateParams 每次 ++
|
||
//(tile 池以此判定"缓存的球已过期需重渲")
|
||
u32 GetEditVersion() const { return m_EditVersion; }
|
||
|
||
private:
|
||
std::array<Texture*, kSlotCount> m_Textures{};
|
||
vk::DescriptorSet m_DescriptorSet;
|
||
Scope<UniformBuffer> m_ParamsBuffer; // per-slot 参数 ring(创建时写死)
|
||
bool m_Transparent = false;
|
||
u64 m_Serial = 0; // ctor 取号(定义见 Material.cpp)
|
||
u32 m_EditVersion = 0;
|
||
};
|
||
} // namespace Engine
|
||
|
||
#endif //HELLOVULKAN_MATERIAL_H
|