feat: 解析式 PBR(Cook-Torrance GGX,metallic-roughness 工作流)
- 修 void* 指针算术警告(Texture::InitFromDds) - Material:slot2 语义切为 metallicRoughness(glTF 约定 G=粗糙度 B=金属度)+ 新增材质因子参数 UBO(binding 4,per-slot ring, 创建时写死,metallic/roughness 因子乘 MR 贴图) - simple_shader.frag:Blinn-Phong → Cook-Torrance(GGX 分布 + Smith 几何 + Schlick Fresnel,k=(r+1)²/8 解析光源版);金属不参与 漫反射;环境光暂为常数(IBL 后续) - Model:读 aiTextureType_UNKNOWN(glTF MR 落点)+ AI_MATKEY_ METALLIC/ROUGHNESS_FACTOR(旧资产缺键退化为电介质 0/0.5); 材质缓存键含因子 - main.cpp:演示场景换回 backpack(旧资产走因子路径验证 PBR 全链路) - 旧 specular 贴图不再使用(语义被 MR 取代)
This commit is contained in:
@@ -44,7 +44,7 @@ namespace Engine {
|
||||
m_MouseCapture = std::move(mouse);
|
||||
}
|
||||
|
||||
vk::SurfaceKHR CreateSurface(vk::Instance instance);
|
||||
vk::SurfaceKHR CreateSurface(vk::Instance instance) const;
|
||||
void DestroySurface(vk::Instance instance, vk::SurfaceKHR surface);
|
||||
|
||||
u32 GetWidth() const { return m_Width; }
|
||||
@@ -63,7 +63,7 @@ namespace Engine {
|
||||
// 输入事件系统
|
||||
|
||||
bool IsKeyPressed(int key) const;
|
||||
void GetMouseDelta(float& dx, float& dy);
|
||||
void GetMouseDelta(float& dx, float& dy) const;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,46 +1,58 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/21.
|
||||
//
|
||||
// Material:着色材质 = 一组纹理槽 + 一个描述符集。
|
||||
// Material:PBR 材质 = 纹理槽组 + 因子参数 UBO + 一个描述符集。
|
||||
//
|
||||
// 槽位(binding = 槽位序号,与 simple_shader.frag 契约一致):
|
||||
// 0 albedo(BaseColor,sRGB) 1 normal(切线空间法线,线性)
|
||||
// 2 specular(高光强度/颜色,线性) 3 emissive(自发光,sRGB)
|
||||
// 槽位(binding = 槽位序号,与 simple_shader.frag 契约一致,glTF
|
||||
// metallic-roughness 工作流):
|
||||
// 0 albedo(BaseColor,sRGB) 1 normal(切线空间法线,线性)
|
||||
// 2 metallicRoughness(线性:G=粗糙度,B=金属度,glTF 约定)
|
||||
// 3 emissive(自发光,sRGB) 4 材质参数 UBO(fragment)
|
||||
//
|
||||
// 纹理非拥有(Model 的纹理缓存持有);空槽由调用方传默认纹理
|
||||
//(白/平法线/黑/黑,Model 持有),shader 永远可以安全采样。
|
||||
// 纹理非拥有(Model 的纹理缓存持有);缺槽由调用方传默认纹理。
|
||||
// 因子(metallicFactor/roughnessFactor)乘在 MR 贴图上——无 MR 图的
|
||||
// 旧资产退化为纯因子(电介质 + 常数粗糙度)。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_MATERIAL_H
|
||||
#define HELLOVULKAN_MATERIAL_H
|
||||
|
||||
#include <Engine/Core/Types.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
namespace Engine
|
||||
{
|
||||
namespace Engine {
|
||||
|
||||
class Device;
|
||||
class MemoryAllocator;
|
||||
class DescriptorManager;
|
||||
class Texture;
|
||||
class UniformBuffer;
|
||||
|
||||
class Material
|
||||
{
|
||||
// 材质因子(乘 MR 贴图;无贴图时即最终值)
|
||||
struct MaterialParams {
|
||||
glm::vec4 factors{0.0f, 0.5f, 0.0f, 0.0f}; // x=metallic y=roughness
|
||||
};
|
||||
|
||||
class Material {
|
||||
public:
|
||||
// 槽位序号(与 binding 对齐)
|
||||
enum Slot : u32 {
|
||||
Albedo = 0,
|
||||
Normal = 1,
|
||||
Specular = 2,
|
||||
MetallicRoughness = 2,
|
||||
Emissive = 3,
|
||||
kSlotCount = 4,
|
||||
kSlotCount = 4, // 纹理槽数
|
||||
kParamsBinding = 4, // 参数 UBO binding
|
||||
};
|
||||
|
||||
Material(Device& device,
|
||||
Material(Device& device, MemoryAllocator& allocator,
|
||||
DescriptorManager& descriptorManager,
|
||||
vk::DescriptorSetLayout layout,
|
||||
const std::array<Texture*, kSlotCount>& textures);
|
||||
const std::array<Texture*, kSlotCount>& textures,
|
||||
const MaterialParams& params);
|
||||
~Material();
|
||||
|
||||
Material(const Material&) = delete;
|
||||
@@ -49,12 +61,14 @@ namespace Engine
|
||||
vk::DescriptorSet GetDescriptorSet() const { return m_DescriptorSet; }
|
||||
Texture* GetTexture(Slot slot) const { return m_Textures[slot]; }
|
||||
|
||||
// 材质缓存键:同贴图组合共享一份(Model 层使用)
|
||||
static std::string MakeCacheKey(const std::string paths[kSlotCount]);
|
||||
// 材质缓存键:同贴图组合+同因子共享一份(Model 层使用)
|
||||
static std::string MakeCacheKey(const std::string paths[kSlotCount],
|
||||
const MaterialParams& params);
|
||||
|
||||
private:
|
||||
std::array<Texture*, kSlotCount> m_Textures{};
|
||||
vk::DescriptorSet m_DescriptorSet;
|
||||
Scope<UniformBuffer> m_ParamsBuffer; // per-slot 参数 ring(创建时写死)
|
||||
};
|
||||
} // namespace Engine
|
||||
|
||||
|
||||
@@ -64,10 +64,11 @@ namespace Engine
|
||||
|
||||
Texture* GetOrLoadTexture(const std::string& path, bool srgb);
|
||||
|
||||
// 材质缓存入口:同贴图组合共享同一 Material(一个描述符集),
|
||||
// 材质缓存入口:同贴图组合+因子共享同一 Material(一个描述符集),
|
||||
// 槽位路径为空/文件缺失折到对应默认纹理。路径已做反斜杠归一化。
|
||||
// paths 下标 = Material::Slot(albedo/normal/specular/emissive)
|
||||
Material* GetOrCreateMaterial(const std::string paths[Material::kSlotCount]);
|
||||
// paths 下标 = Material::Slot;params = metallic/roughness 因子
|
||||
Material* GetOrCreateMaterial(const std::string paths[Material::kSlotCount],
|
||||
const MaterialParams& params);
|
||||
|
||||
Device& m_Device;
|
||||
MemoryAllocator& m_Allocator;
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Engine {
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
Renderer(Window& window);
|
||||
explicit Renderer(Window& window);
|
||||
~Renderer();
|
||||
|
||||
Renderer(const Renderer&) = delete;
|
||||
|
||||
@@ -28,10 +28,10 @@ namespace Engine {
|
||||
CommandManager& operator=(const CommandManager&) = delete;
|
||||
|
||||
// 开始录制指定帧槽位的命令缓冲
|
||||
vk::CommandBuffer BeginFrame(u32 frameSlot);
|
||||
vk::CommandBuffer BeginFrame(u32 frameSlot) const;
|
||||
|
||||
// 结束录制
|
||||
void EndFrame(u32 frameSlot);
|
||||
void EndFrame(u32 frameSlot) const;
|
||||
|
||||
vk::CommandBuffer GetBuffer(u32 frameSlot) const { return m_Buffers[frameSlot]; }
|
||||
|
||||
|
||||
@@ -28,21 +28,21 @@ namespace Engine {
|
||||
DescriptorManager(const DescriptorManager&) = delete;
|
||||
DescriptorManager& operator=(const DescriptorManager&) = delete;
|
||||
|
||||
vk::DescriptorSetLayout CreateLayout(const std::vector<DescriptorBinding>& bindings);
|
||||
vk::DescriptorSetLayout CreateLayout(const std::vector<DescriptorBinding>& bindings) const;
|
||||
|
||||
vk::DescriptorSet AllocateDescriptorSet(vk::DescriptorSetLayout layout);
|
||||
|
||||
void UpdateUniformBuffer(vk::DescriptorSet set, u32 binding,
|
||||
vk::Buffer buffer, u64 size);
|
||||
vk::Buffer buffer, u64 size) const;
|
||||
void UpdateStorageBuffer(vk::DescriptorSet set, u32 binding,
|
||||
vk::Buffer buffer, u64 size);
|
||||
vk::Buffer buffer, u64 size) const;
|
||||
|
||||
void UpdateTexture(vk::DescriptorSet set, u32 binding,
|
||||
vk::Sampler sampler, vk::ImageView view);
|
||||
vk::Sampler sampler, vk::ImageView view) const;
|
||||
|
||||
// 单个 set layout 的旧接口(保留)
|
||||
vk::PipelineLayout CreatePipelineLayout(vk::DescriptorSetLayout layout,
|
||||
u32 pushConstantSize);
|
||||
u32 pushConstantSize) const;
|
||||
|
||||
// 多 set layout 的新接口。
|
||||
// push constant range 按程序级 vertex|fragment 声明(与
|
||||
@@ -50,7 +50,7 @@ namespace Engine {
|
||||
// push 调用点必须带同样的双 stage(VUID-01796)
|
||||
vk::PipelineLayout CreatePipelineLayout(
|
||||
const std::vector<vk::DescriptorSetLayout>& layouts,
|
||||
u32 pushConstantSize);
|
||||
u32 pushConstantSize) const;
|
||||
|
||||
private:
|
||||
Device& m_Device;
|
||||
@@ -64,7 +64,7 @@ namespace Engine {
|
||||
// 每块的容量(set 数;各类型描述符数同值)
|
||||
static constexpr u32 kChunkSets = 4096;
|
||||
|
||||
vk::DescriptorPool CreateChunk();
|
||||
vk::DescriptorPool CreateChunk() const;
|
||||
};
|
||||
|
||||
} // namespace Engine
|
||||
|
||||
@@ -39,12 +39,12 @@ namespace Engine {
|
||||
ShaderObject CreateFromSPIRV(const std::vector<u32>& spirv,
|
||||
vk::ShaderStageFlagBits stage,
|
||||
const std::vector<vk::DescriptorSetLayout>& layouts = {},
|
||||
u32 pushConstantSize = 0);
|
||||
u32 pushConstantSize = 0) const;
|
||||
|
||||
void Destroy(const ShaderObject& shader);
|
||||
void Destroy(const ShaderObject& shader) const;
|
||||
|
||||
private:
|
||||
std::vector<u32> ReadSPIRV(const std::string& path);
|
||||
static std::vector<u32> ReadSPIRV(const std::string& path);
|
||||
|
||||
Device& m_Device;
|
||||
};
|
||||
|
||||
@@ -35,8 +35,8 @@ namespace Engine {
|
||||
vk::Fence GetFrameFence(u32 frameIndex) const { return m_FrameFences[frameIndex]; }
|
||||
|
||||
// 等待并重置这一帧的 Fence
|
||||
void WaitFence(u32 frameIndex); // 只等,不 reset
|
||||
void ResetFence(u32 frameIndex); // 只 reset
|
||||
void WaitFence(u32 frameIndex) const; // 只等,不 reset
|
||||
void ResetFence(u32 frameIndex) const; // 只 reset
|
||||
|
||||
private:
|
||||
Device& m_Device;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Engine {
|
||||
u64 GetSize() const { return m_Size; }
|
||||
|
||||
// 写入指定帧槽位的 UBO(仅在该槽位 fence 确认完成后调用)
|
||||
void Update(u32 frameSlot, const void* data, u64 size);
|
||||
void Update(u32 frameSlot, const void* data, u64 size) const;
|
||||
|
||||
private:
|
||||
std::vector<Scope<Buffer>> m_Buffers;
|
||||
|
||||
Reference in New Issue
Block a user