feat: add pbr support

This commit is contained in:
2026-10-13 00:57:35 +02:00
parent ce55f75ac3
commit 21621001c2
34 changed files with 968 additions and 135 deletions
+1 -1
View File
@@ -11,7 +11,7 @@
#include <destrum/Util/ModelDoc.h>
namespace ModelFile {
inline constexpr std::uint32_t Version = 1;
inline constexpr std::uint32_t Version = 2;
inline constexpr std::string_view Extension = ".dmodel";
inline constexpr ModelDoc::LoadOptions CookOptions{};
@@ -50,6 +50,8 @@ public:
void updateMaterialGPU(MaterialID id);
private:
[[nodiscard]] MaterialData toMaterialData(const Material& material) const;
std::vector<Material> materials;
std::vector<std::string> materialKeys;
+27 -8
View File
@@ -5,17 +5,23 @@
#include <utility>
#include <glm/glm.hpp>
#include <destrum/Assets/AssetReference.h>
#include <destrum/Graphics/ids.h>
// Must match MaterialData in materials.glsl
struct alignas(16) MaterialData {
alignas(16) glm::vec4 baseColor;
alignas(16) glm::vec4 metalRoughnessEmissive;
alignas(16) glm::vec4 emissiveColor;
alignas(16) glm::vec4 metallicRoughnessNormalOcclusion;
uint32_t textureFilteringMode;
uint32_t diffuseTex;
uint32_t normalTex;
uint32_t metallicRoughnessTex;
uint32_t metallicTex;
uint32_t roughnessTex;
uint32_t occlusionTex;
uint32_t emissiveTex;
uint32_t _pad0, _pad1, _pad2; // explicit to 64 bytes
uint32_t _pad0;
};
static_assert(sizeof(MaterialData) == 80);
enum class TextureFilteringMode : std::uint32_t {
Nearest,
@@ -23,6 +29,9 @@ enum class TextureFilteringMode : std::uint32_t {
Anisotropic,
};
// Metallic / roughness workflow, matching glTF:
// metallic is read from the blue channel, roughness from green and occlusion from red,
// so a packed (occlusion)metallicRoughness texture can be used for all three slots.
struct Material {
[[nodiscard]] static Material SimpleColor(
glm::vec3 color,
@@ -32,22 +41,32 @@ struct Material {
material.baseColor = color;
material.metallicFactor = 0.0f;
material.roughnessFactor = 1.0f;
material.emissiveFactor = 0.0f;
material.name = std::move(materialName);
return material;
}
[[nodiscard]] bool UsesTexture(ImageID id) const
{
return id != NULL_IMAGE_ID &&
(diffuseTexture == id || normalTexture == id || metallicTexture == id ||
roughnessTexture == id || occlusionTexture == id || emissiveTexture == id);
}
glm::vec3 baseColor{1.f, 1.f, 1.f};
float metallicFactor{0.f};
float roughnessFactor{0.7f};
float emissiveFactor{0.f};
glm::vec3 emissiveColor{0.f};
float normalScale{1.f};
float occlusionStrength{1.f};
TextureFilteringMode textureFilteringMode{TextureFilteringMode::Linear};
ImageID diffuseTexture{NULL_IMAGE_ID};
// ImageId normalMapTexture{NULL_IMAGE_ID};
// ImageId metallicRoughnessTexture{NULL_IMAGE_ID};
// ImageId emissiveTexture{NULL_IMAGE_ID};
ImageID normalTexture{NULL_IMAGE_ID};
ImageID metallicTexture{NULL_IMAGE_ID};
ImageID roughnessTexture{NULL_IMAGE_ID};
ImageID occlusionTexture{NULL_IMAGE_ID};
ImageID emissiveTexture{NULL_IMAGE_ID};
std::string name;
AssetReference assetReference;
@@ -11,6 +11,8 @@
#include <memory>
#include <string_view>
namespace ModelDoc { struct MaterialInfo; }
class GfxDevice;
class RenderResources {
@@ -40,7 +42,7 @@ public:
GfxDevice& gfxDevice,
const std::filesystem::path& path,
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
bool mipMap = false,
bool mipMap = true,
TextureIntent intent = TextureIntent::ColorSrgb);
ImageID addImageToCache(GPUImage image);
@@ -49,6 +51,9 @@ public:
// References are keyed as "source#subresource" in the resource caches.
void loadModelAsset(GfxDevice& gfxDevice, std::string_view sourceReference);
// Creates a PBR material from an imported model material, loading its texture maps.
MaterialID addModelMaterial(GfxDevice& gfxDevice, const ModelDoc::MaterialInfo& sourceMaterial);
[[nodiscard]] const GPUImage& getImage(ImageID id) const;
[[nodiscard]] ImageID getWhiteTextureID() const { return whiteImageId; }
+3
View File
@@ -369,6 +369,9 @@ static MaterialInfo LoadMaterialInfo(const aiScene* scene,
TextureSemantic::Roughness, out.textures);
AddMaterialTextureSlots(scene, material, modelDir, aiTextureType_AMBIENT_OCCLUSION,
TextureSemantic::AmbientOcclusion, out.textures);
// glTF occlusion maps are imported as lightmaps
AddMaterialTextureSlots(scene, material, modelDir, aiTextureType_LIGHTMAP,
TextureSemantic::AmbientOcclusion, out.textures);
AddMaterialTextureSlots(scene, material, modelDir, aiTextureType_EMISSION_COLOR,
TextureSemantic::Emissive, out.textures);