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.
86 lines
2.8 KiB
C++
86 lines
2.8 KiB
C++
//
|
||
// Created by atdunbg on 2026/9/20.
|
||
//
|
||
|
||
#ifndef HELLOVULKAN_TEXTURE_H
|
||
#define HELLOVULKAN_TEXTURE_H
|
||
|
||
#pragma once
|
||
|
||
#include <Engine/Core/Types.h>
|
||
#include <vulkan/vulkan.hpp>
|
||
#include <array>
|
||
#include <string>
|
||
|
||
#include "MemoryAllocator.h"
|
||
|
||
namespace Engine {
|
||
|
||
class Device;
|
||
class MemoryAllocator;
|
||
|
||
class Texture {
|
||
public:
|
||
// 从磁盘图片加载(按扩展名分发:.dds → DdsLoader,其它 → stbi)。
|
||
// srgb:颜色贴图语义(BaseColor/Emissive)为 true;数据图
|
||
//(Normal/Specular 等)为 false —— 决定 vk 格式的 _SRGB 变体
|
||
Texture(Device& device, MemoryAllocator& allocator, const std::string& path,
|
||
bool srgb = true);
|
||
|
||
// 程序化纹理:纯色(1x1),用于地面/调试等不依赖磁盘资产的场景
|
||
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();
|
||
|
||
Texture(const Texture&) = delete;
|
||
Texture& operator=(const Texture&) = delete;
|
||
|
||
vk::Image Get() const { return m_Image; }
|
||
vk::ImageView GetView() const { return m_View; }
|
||
u32 GetWidth() const { return m_Width; }
|
||
u32 GetHeight() const { return m_Height; }
|
||
vk::Format GetFormat() const { return m_Format; }
|
||
u32 GetMipLevels() const { return m_MipLevels; }
|
||
|
||
vk::Sampler GetSampler() const { return m_Sampler; }
|
||
|
||
private:
|
||
// 两段式构造:先确定像素来源(磁盘 / 程序化),再走公共上传路径
|
||
Texture(Device& device, MemoryAllocator& allocator, ProceduralTag,
|
||
const std::array<u8, 4>& rgba, bool srgb);
|
||
|
||
// 公共路径:staging → device local image → blit 生成完整 mip 链 →
|
||
// view/sampler(RGBA8,各向异性过滤)
|
||
void InitFromPixels(const void* pixels, u32 width, u32 height, bool srgb);
|
||
|
||
// DDS 路径:压缩数据直传(BC 硬件采样解码)+ 文件自带 mip 链
|
||
void InitFromDds(const std::string& path, bool srgb);
|
||
|
||
Device& m_Device;
|
||
vk::Image m_Image;
|
||
vk::ImageView m_View;
|
||
|
||
vk::Format m_Format = vk::Format::eUndefined;
|
||
u32 m_MipLevels = 1;
|
||
|
||
vk::Sampler m_Sampler;
|
||
|
||
|
||
u32 m_Width = 0;
|
||
u32 m_Height = 0;
|
||
|
||
u64 m_TextureBytes = 0;
|
||
|
||
MemoryAllocator::Allocation m_ImageAllocation;
|
||
MemoryAllocator& m_Allocator;
|
||
};
|
||
|
||
} // namespace Engine
|
||
|
||
#endif //HELLOVULKAN_TEXTURE_H
|