Skip to content

Commit

Permalink
add texture resource (#479)
Browse files Browse the repository at this point in the history
  • Loading branch information
T-rvw authored Feb 27, 2024
1 parent 1446323 commit 8170d50
Show file tree
Hide file tree
Showing 13 changed files with 442 additions and 227 deletions.
25 changes: 12 additions & 13 deletions Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Rendering/RenderContext.h"
#include "Rendering/Resources/MeshResource.h"
#include "Rendering/Resources/ResourceContext.h"
#include "Rendering/Resources/TextureResource.h"
#include "Rendering/ShaderFeature.h"
#include "Resources/ResourceBuilder.h"
#include "Resources/ResourceLoader.h"
Expand All @@ -22,7 +23,7 @@ namespace editor
{

ECWorldConsumer::ECWorldConsumer(engine::SceneWorld* pSceneWorld, engine::RenderContext* pRenderContext) :
m_pSceneWorld(pSceneWorld), m_pRenderContext(pRenderContext), m_pResourceContext(m_pRenderContext->GetResourceContext())
m_pSceneWorld(pSceneWorld), m_pRenderContext(pRenderContext), m_pResourceContext(pRenderContext->GetResourceContext())
{
}

Expand Down Expand Up @@ -296,21 +297,19 @@ void ECWorldConsumer::AddMaterial(engine::Entity entity, const cd::Material* pMa
// Textures.
for (const auto& [type, path, pTexture] : outputTypeToData)
{
auto textureFileBlob = engine::ResourceLoader::LoadFile(path.c_str());
if (!textureFileBlob.empty())
engine::TextureResource* pTextureResource = m_pResourceContext->AddTextureResource(engine::StringCrc(path));
pTextureResource->SetTextureAsset(pTexture);
pTextureResource->SetDDSBuiltTexturePath(path);
pTextureResource->UpdateTextureType(type);
pTextureResource->UpdateUVMapMode(pTexture->GetUMapMode(), pTexture->GetVMapMode());
materialComponent.SetTextureResource(type, pMaterial, pTextureResource);

if (auto pPropertyGroup = materialComponent.GetPropertyGroup(type); pPropertyGroup)
{
// TODO : Store TextureFileBlob multiple times, a temporary solution here.
// Should use something like TextureResource to avoid duplicate storage.
materialComponent.AddTextureFileBlob(type, pMaterial, *pTexture, cd::MoveTemp(textureFileBlob));
if (auto pPropertyGroup = materialComponent.GetPropertyGroup(type); pPropertyGroup)
{
pPropertyGroup->useTexture = true;
materialComponent.ActivateShaderFeature(engine::MaterialTextureTypeToShaderFeature.at(type));
}
pPropertyGroup->useTexture = true;
materialComponent.ActivateShaderFeature(engine::MaterialTextureTypeToShaderFeature.at(type));
}
}

materialComponent.Build();
}

void ECWorldConsumer::AddBlendShape(engine::Entity entity, const cd::Mesh* pMesh, const cd::BlendShape& blendShape, const cd::SceneDatabase* pSceneDatabase)
Expand Down
2 changes: 0 additions & 2 deletions Engine/Source/Editor/UILayers/EntityList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ void EntityList::AddEntity(engine::SceneWorld* pSceneWorld)
materialComponent.Init();
materialComponent.SetMaterialType(pMaterialType);
materialComponent.ActivateShaderFeature(engine::GetSkyTypeShaderFeature(pSceneWorld->GetSkyComponent(pSceneWorld->GetSkyEntity())->GetSkyType()));
materialComponent.Build();

auto& transformComponent = pWorld->CreateComponent<engine::TransformComponent>(entity);
transformComponent.SetTransform(cd::Transform::Identity());
Expand Down Expand Up @@ -139,7 +138,6 @@ void EntityList::AddEntity(engine::SceneWorld* pSceneWorld)
materialComponent.SetMaterialType(pTerrainMaterialType);
materialComponent.SetTwoSided(true);
materialComponent.ActivateShaderFeature(engine::GetSkyTypeShaderFeature(pSceneWorld->GetSkyComponent(pSceneWorld->GetSkyEntity())->GetSkyType()));
materialComponent.Build();

auto& transformComponent = pWorld->CreateComponent<engine::TransformComponent>(entity);
transformComponent.SetTransform(cd::Transform::Identity());
Expand Down
7 changes: 5 additions & 2 deletions Engine/Source/Editor/UILayers/Inspector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "Rendering/RenderContext.h"
#include "Rendering/ShaderCollections.h"
#include "Rendering/Resources/TextureResource.h"
#include "Graphics/GraphicsBackend.h"
#include "ImGui/ImGuiUtils.hpp"
#include "Path/Path.h"
Expand Down Expand Up @@ -239,9 +240,11 @@ void UpdateComponentWidget<engine::MaterialComponent>(engine::SceneWorld* pScene
ImGui::PushID(textureTypeValue);

auto& textureInfo = pPropertyGroup->textureInfo;
if (bgfx::kInvalidHandle != textureInfo.textureHandle)
engine::TextureResource* pTextureResource = textureInfo.pTextureResource;
if (pTextureResource &&
(pTextureResource->GetStatus() == engine::ResourceStatus::Ready || pTextureResource->GetStatus() == engine::ResourceStatus::Optimized))
{
ImGui::Image(reinterpret_cast<ImTextureID>(textureInfo.textureHandle), ImVec2(64, 64));
ImGui::Image(reinterpret_cast<ImTextureID>(pTextureResource->GetTextureHandle()), ImVec2(64, 64));
}
else
{
Expand Down
165 changes: 11 additions & 154 deletions Engine/Source/Runtime/ECWorld/MaterialComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,100 +3,10 @@
#include "Log/Log.h"
#include "Material/MaterialType.h"
#include "Scene/Material.h"
#include "Scene/Texture.h"

#include <bgfx/bgfx.h>
#include <bimg/decode.h>
#include <bx/allocator.h>

#include <cassert>
#include <filesystem>
#include <unordered_map>

namespace
{

static uint32_t textureIndex = 0;

static bx::AllocatorI* GetResourceAllocator()
{
static bx::DefaultAllocator s_allocator;
return &s_allocator;
}

bgfx::TextureHandle BGFXCreateTexture(
uint16_t width,
uint16_t height,
uint16_t depth,
bool isCubeMap,
bool hasMips,
uint16_t numLayers,
bgfx::TextureFormat::Enum textureFormat,
uint64_t textureFlags,
const bgfx::Memory* pMemory)
{
bgfx::TextureHandle textureHandle = BGFX_INVALID_HANDLE;
if (isCubeMap)
{
textureHandle = bgfx::createTextureCube(width, hasMips, numLayers, textureFormat, textureFlags, pMemory);
}
else if (depth > 1)
{
textureHandle = bgfx::createTexture3D(width, height, depth, hasMips, textureFormat, textureFlags, pMemory);
}
else if (bgfx::isTextureValid(0, false, numLayers, textureFormat, textureFlags))
{
textureHandle = bgfx::createTexture2D(width, height, hasMips, numLayers, textureFormat, textureFlags, pMemory);
}
return textureHandle;
}

uint64_t GetBGFXTextureFlag(cd::MaterialTextureType textureType, cd::TextureMapMode uMapMode, cd::TextureMapMode vMapMode)
{
uint64_t textureFlag = 0;
if (cd::MaterialTextureType::BaseColor == textureType ||
cd::MaterialTextureType::Emissive == textureType)
{
textureFlag |= BGFX_TEXTURE_SRGB;
}

switch (uMapMode)
{
case cd::TextureMapMode::Clamp:
textureFlag |= BGFX_SAMPLER_U_CLAMP;
break;
case cd::TextureMapMode::Mirror:
textureFlag |= BGFX_SAMPLER_U_MIRROR;
break;
case cd::TextureMapMode::Border:
textureFlag |= BGFX_SAMPLER_U_BORDER;
break;
case cd::TextureMapMode::Wrap:
default:
break;
}

switch (vMapMode)
{
case cd::TextureMapMode::Clamp:
textureFlag |= BGFX_SAMPLER_V_CLAMP;
break;
case cd::TextureMapMode::Mirror:
textureFlag |= BGFX_SAMPLER_V_MIRROR;
break;
case cd::TextureMapMode::Border:
textureFlag |= BGFX_SAMPLER_V_BORDER;
break;
case cd::TextureMapMode::Wrap:
default:
break;
}

return textureFlag;
}

}

namespace engine
{

Expand Down Expand Up @@ -129,6 +39,15 @@ void MaterialComponent::Init()
m_propertyGroups[cd::MaterialPropertyGroup::Emissive] = cd::MoveTemp(propertyGroup);
}

void MaterialComponent::SetMaterialData(const cd::Material* pMaterialData)
{
m_pMaterialData = pMaterialData;
if (m_pMaterialData)
{
m_name = m_pMaterialData->GetName();
}
}

MaterialComponent::PropertyGroup* MaterialComponent::GetPropertyGroup(cd::MaterialPropertyGroup propertyGroup)
{
auto it = m_propertyGroups.find(propertyGroup);
Expand Down Expand Up @@ -208,35 +127,7 @@ void MaterialComponent::Reset()
m_propertyGroups.clear();
}

void MaterialComponent::AddTextureBlob(cd::MaterialTextureType textureType, cd::TextureFormat textureFormat, cd::TextureMapMode uMapMode, cd::TextureMapMode vMapMode,
TextureBlob textureBlob, uint32_t width, uint32_t height, uint32_t depth /* = 1 */)
{
std::optional<uint8_t> optTextureSlot = m_pMaterialType->GetTextureSlot(textureType);
if (!optTextureSlot.has_value())
{
return;
}

PropertyGroup& propertyGroup = m_propertyGroups[textureType];
propertyGroup.useTexture = true;

TextureInfo& textureInfo = propertyGroup.textureInfo;
textureInfo.slot = optTextureSlot.value();
textureInfo.width = width;
textureInfo.height = height;
textureInfo.depth = depth;
textureInfo.mipCount = 0;
textureInfo.format = textureFormat;
textureInfo.data = bgfx::makeRef(textureBlob.data(), static_cast<uint32_t>(textureBlob.size()));
textureInfo.flag = GetBGFXTextureFlag(textureType, uMapMode, vMapMode);
textureInfo.uvOffset = cd::Vec2f::Zero();
textureInfo.uvScale = cd::Vec2f::One();

// TODO : generic CPU/GPU resource manager.
m_cacheTextureBlobs.emplace_back(cd::MoveTemp(textureBlob));
}

void MaterialComponent::AddTextureFileBlob(cd::MaterialTextureType textureType, const cd::Material* pMaterial, const cd::Texture& texture, TextureBlob textureBlob)
void MaterialComponent::SetTextureResource(cd::MaterialTextureType textureType, const cd::Material* pMaterial, TextureResource* pTextureResource)
{
std::optional<uint8_t> optTextureSlot = m_pMaterialType->GetTextureSlot(textureType);
if (!optTextureSlot.has_value())
Expand All @@ -247,16 +138,9 @@ void MaterialComponent::AddTextureFileBlob(cd::MaterialTextureType textureType,
PropertyGroup& propertyGroup = m_propertyGroups[textureType];
propertyGroup.useTexture = true;

bimg::ImageContainer* pImageContainer = bimg::imageParse(GetResourceAllocator(), textureBlob.data(), static_cast<uint32_t>(textureBlob.size()));
TextureInfo& textureInfo = propertyGroup.textureInfo;
textureInfo.slot = optTextureSlot.value();
textureInfo.width = pImageContainer->m_width;
textureInfo.height = pImageContainer->m_height;
textureInfo.depth = pImageContainer->m_depth;
textureInfo.mipCount = pImageContainer->m_numMips;
textureInfo.format = static_cast<cd::TextureFormat>(pImageContainer->m_format);
textureInfo.data = bgfx::makeRef(pImageContainer->m_data, pImageContainer->m_size);
textureInfo.flag = GetBGFXTextureFlag(textureType, texture.GetUMapMode(), texture.GetVMapMode());
textureInfo.pTextureResource = pTextureResource;
if (auto optUVScale = pMaterial->GetVec2fProperty(textureType, cd::MaterialProperty::UVScale); optUVScale.has_value())
{
textureInfo.uvScale = optUVScale.value();
Expand All @@ -267,31 +151,4 @@ void MaterialComponent::AddTextureFileBlob(cd::MaterialTextureType textureType,
}
}

void MaterialComponent::Build()
{
if (m_pMaterialData)
{
m_name = m_pMaterialData->GetName();
}

for (auto& [textureType, propertyGroup] : m_propertyGroups)
{
if (!propertyGroup.useTexture)
{
continue;
}

TextureInfo& textureInfo = propertyGroup.textureInfo;
textureInfo.textureHandle = BGFXCreateTexture(textureInfo.width, textureInfo.height, textureInfo.depth, false, textureInfo.mipCount > 1,
1, static_cast<bgfx::TextureFormat::Enum>(textureInfo.format), textureInfo.flag, textureInfo.data).idx;

std::string samplerUniformName = "s_textureSampler";
samplerUniformName += std::to_string(textureIndex++);
textureInfo.samplerHandle = bgfx::createUniform(samplerUniformName.c_str(), bgfx::UniformType::Sampler).idx;

assert(textureInfo.textureHandle != bgfx::kInvalidHandle);
assert(textureInfo.samplerHandle != bgfx::kInvalidHandle);
}
}

}
19 changes: 4 additions & 15 deletions Engine/Source/Runtime/ECWorld/MaterialComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace engine

class MaterialType;
class RenderContext;
class TextureResource;

class MaterialComponent final
{
Expand All @@ -45,20 +46,10 @@ class MaterialComponent final
using TextureBlob = std::vector<std::byte>;
struct TextureInfo
{
static constexpr uint16_t BGFXInvalidHandle = (1 << 16) - 1;

const bgfx::Memory* data;
uint64_t flag;
uint32_t width;
uint32_t height;
uint32_t depth;
cd::TextureFormat format;
cd::Vec2f uvOffset = cd::Vec2f::Zero();
cd::Vec2f uvScale = cd::Vec2f::One();
uint16_t samplerHandle = BGFXInvalidHandle;
uint16_t textureHandle = BGFXInvalidHandle;
uint8_t slot;
uint8_t mipCount;
TextureResource* pTextureResource = nullptr;

// TODO : Improve TextureInfo
cd::Vec2f& GetUVOffset() { return uvOffset; }
Expand Down Expand Up @@ -86,15 +77,14 @@ class MaterialComponent final

void Init();

void SetMaterialData(const cd::Material* pMaterialData) { m_pMaterialData = pMaterialData; }
void SetMaterialData(const cd::Material* pMaterialData);
cd::Material* GetMaterialData() { return const_cast<cd::Material*>(m_pMaterialData); }
const cd::Material* GetMaterialData() const { return m_pMaterialData; }

void SetMaterialType(const engine::MaterialType* pMaterialType) { m_pMaterialType = pMaterialType; }
const engine::MaterialType* GetMaterialType() const { return m_pMaterialType; }

void Reset();
void Build();

// Basic data.
void SetName(std::string name) { m_name = cd::MoveTemp(name); }
Expand All @@ -111,8 +101,7 @@ class MaterialComponent final
const std::string& GetFeaturesCombine();

// Texture data.
void AddTextureBlob(cd::MaterialTextureType textureType, cd::TextureFormat textureFormat, cd::TextureMapMode uMapMode, cd::TextureMapMode vMapMode, TextureBlob textureBlob, uint32_t width, uint32_t height, uint32_t depth = 1);
void AddTextureFileBlob(cd::MaterialTextureType textureType, const cd::Material* pMaterial, const cd::Texture& texture, TextureBlob textureBlob);
void SetTextureResource(cd::MaterialTextureType textureType, const cd::Material* pMaterial, TextureResource* pTextureResource);

const std::map<cd::MaterialPropertyGroup, PropertyGroup>& GetPropertyGroups() const { return m_propertyGroups; }
PropertyGroup* GetPropertyGroup(cd::MaterialPropertyGroup propertyGroup);
Expand Down
7 changes: 7 additions & 0 deletions Engine/Source/Runtime/Rendering/Resources/IResource.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "Core/StringCrc.h"

namespace engine
{

Expand Down Expand Up @@ -32,10 +34,15 @@ class IResource
virtual ~IResource() = default;

virtual void Update() = 0;

StringCrc GetName() const { return m_nameCrc; }
void SetName(StringCrc crc) { m_nameCrc = crc; }

ResourceStatus GetStatus() const { return m_status; }
void SetStatus(ResourceStatus status) { m_status = status; }

private:
StringCrc m_nameCrc;
ResourceStatus m_status = ResourceStatus::Loading;
};

Expand Down
Loading

0 comments on commit 8170d50

Please sign in to comment.