Improve PBR quality: mip chains, anisotropic filtering, baseColorFactor

Root causes behind blurry/unphysical materials (4K pocket watch render
mushy, glass fully opaque, watch hands unreadable):

- Textures loaded via stbi had a single mip level: 4096x4096 albedo/MR
  maps sampled with no LOD -> minification aliasing turned fine detail
  (watch hands) into noise. Generate a full blit-based mip chain with
  per-level layout transitions.
- samplerAnisotropy was never enabled on the device and every sampler
  was created with anisotropy disabled: grazing-angle surfaces (watch
  face, ground) collapsed into a blur. Enable the device feature and
  16x anisotropic filtering on material texture samplers.
- glTF baseColorFactor was ignored: the glass material (alphaMode
  BLEND, no baseColor texture, baseColorFactor.a = 0.3) fell back to
  the default white texture with alpha = 1 and rendered fully opaque.
  MaterialParams gains a baseColor vec4 (rgb tints albedo, a scales
  the blend alpha) threaded through both PBR shaders.
- alphaMode MASK was treated as opaque: add a factors.w switch that
  performs an alpha cutout test in the opaque shader.
- Fix material cache key dropping factors.z (separate-roughness
  switch); it now encodes the full factors and baseColor vectors.
This commit is contained in:
2026-10-05 12:01:07 +08:00
parent a3037cd401
commit 5d88ed2057
9 changed files with 124 additions and 23 deletions
@@ -43,7 +43,10 @@ namespace Engine {
// x = metallic 因子 y = roughness 因子
// z = 独立粗糙度图开关(1 = 用 Roughness 槽 R 通道替换 MR.g)
struct MaterialParams {
// x = metallic 因子,y = roughness 因子,z = 独立粗糙度图开关,w = MASK 镂空开关
glm::vec4 factors{0.0f, 0.5f, 0.0f, 0.0f};
// glTF baseColorFactor:rgb 乘进 albedo,a 作 BLEND 透明度
glm::vec4 baseColor{1.0f, 1.0f, 1.0f, 1.0f};
};
class Material {
+5
View File
@@ -45,6 +45,9 @@ public:
bool IsSynchronization2Supported() const { return m_Synchronization2Supported; }
// MDI:drawCount>1 的 drawIndexedIndirect(Count) 必需(core 特性位)
bool IsMultiDrawIndirectSupported() const { return m_MultiDrawIndirectSupported; }
// 各向异性过滤:纹理采样器清晰度(掠射角材质锐利度)的硬件开关
bool IsSamplerAnisotropySupported() const { return m_SamplerAnisotropySupported; }
float MaxSamplerAnisotropy() const { return m_MaxSamplerAnisotropy; }
private:
void CreateInstance();
@@ -76,6 +79,8 @@ private:
bool m_Synchronization2Supported = false;
bool m_MultiDrawIndirectSupported = false;
bool m_DrawIndirectCountSupported = false;
bool m_SamplerAnisotropySupported = false;
float m_MaxSamplerAnisotropy = 1.0f;
std::vector<const char*> m_ValidationLayers = { "VK_LAYER_KHRONOS_validation" };
std::vector<const char*> m_DeviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
+2 -1
View File
@@ -54,7 +54,8 @@ namespace Engine {
Texture(Device& device, MemoryAllocator& allocator, ProceduralTag,
const std::array<u8, 4>& rgba, bool srgb);
// 公共路径:staging → device local image → view/sampler(RGBA8 单 mip)
// 公共路径:staging → device local image → blit 生成完整 mip 链 →
// view/sampler(RGBA8,各向异性过滤)
void InitFromPixels(const void* pixels, u32 width, u32 height, bool srgb);
// DDS 路径:压缩数据直传(BC 硬件采样解码)+ 文件自带 mip 链