Split mesh artifacts into material and texture artifacts
This commit is contained in:
@@ -52,6 +52,15 @@ void RemoveTextureBindingByName(
|
||||
}
|
||||
}
|
||||
|
||||
void EnsureTextureProperty(Containers::HashMap<Containers::String, MaterialProperty>& properties,
|
||||
const Containers::String& name) {
|
||||
MaterialProperty prop;
|
||||
prop.name = name;
|
||||
prop.type = MaterialPropertyType::Texture;
|
||||
prop.refCount = 1;
|
||||
properties.Insert(name, prop);
|
||||
}
|
||||
|
||||
void WritePackedMaterialProperty(Core::uint8* destination, const MaterialProperty& property) {
|
||||
std::memset(destination, 0, kMaterialConstantSlotSize);
|
||||
|
||||
@@ -271,15 +280,13 @@ void Material::SetBool(const Containers::String& name, bool value) {
|
||||
}
|
||||
|
||||
void Material::SetTexture(const Containers::String& name, const ResourceHandle<Texture>& texture) {
|
||||
MaterialProperty prop;
|
||||
prop.name = name;
|
||||
prop.type = MaterialPropertyType::Texture;
|
||||
prop.refCount = 1;
|
||||
m_properties.Insert(name, prop);
|
||||
EnsureTextureProperty(m_properties, name);
|
||||
|
||||
for (auto& binding : m_textureBindings) {
|
||||
if (binding.name == name) {
|
||||
binding.texture = texture;
|
||||
binding.texturePath = texture.Get() != nullptr ? texture->GetPath() : Containers::String();
|
||||
binding.pendingLoad.reset();
|
||||
MarkChanged(false);
|
||||
return;
|
||||
}
|
||||
@@ -289,6 +296,33 @@ void Material::SetTexture(const Containers::String& name, const ResourceHandle<T
|
||||
binding.name = name;
|
||||
binding.slot = static_cast<Core::uint32>(m_textureBindings.Size());
|
||||
binding.texture = texture;
|
||||
binding.texturePath = texture.Get() != nullptr ? texture->GetPath() : Containers::String();
|
||||
m_textureBindings.PushBack(binding);
|
||||
MarkChanged(false);
|
||||
}
|
||||
|
||||
void Material::SetTexturePath(const Containers::String& name, const Containers::String& texturePath) {
|
||||
if (texturePath.Empty()) {
|
||||
RemoveProperty(name);
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureTextureProperty(m_properties, name);
|
||||
|
||||
for (auto& binding : m_textureBindings) {
|
||||
if (binding.name == name) {
|
||||
binding.texture.Reset();
|
||||
binding.texturePath = texturePath;
|
||||
binding.pendingLoad.reset();
|
||||
MarkChanged(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MaterialTextureBinding binding;
|
||||
binding.name = name;
|
||||
binding.slot = static_cast<Core::uint32>(m_textureBindings.Size());
|
||||
binding.texturePath = texturePath;
|
||||
m_textureBindings.PushBack(binding);
|
||||
MarkChanged(false);
|
||||
}
|
||||
@@ -343,8 +377,16 @@ bool Material::GetBool(const Containers::String& name) const {
|
||||
}
|
||||
|
||||
ResourceHandle<Texture> Material::GetTexture(const Containers::String& name) const {
|
||||
for (const auto& binding : m_textureBindings) {
|
||||
Material* material = const_cast<Material*>(this);
|
||||
material->ResolvePendingTextureBindings();
|
||||
for (Core::uint32 bindingIndex = 0; bindingIndex < material->m_textureBindings.Size(); ++bindingIndex) {
|
||||
MaterialTextureBinding& binding = material->m_textureBindings[bindingIndex];
|
||||
if (binding.name == name) {
|
||||
if (binding.texture.Get() == nullptr &&
|
||||
binding.pendingLoad == nullptr &&
|
||||
!binding.texturePath.Empty()) {
|
||||
material->BeginAsyncTextureLoad(bindingIndex);
|
||||
}
|
||||
return binding.texture;
|
||||
}
|
||||
}
|
||||
@@ -355,8 +397,24 @@ Containers::String Material::GetTextureBindingName(Core::uint32 index) const {
|
||||
return index < m_textureBindings.Size() ? m_textureBindings[index].name : Containers::String();
|
||||
}
|
||||
|
||||
Containers::String Material::GetTextureBindingPath(Core::uint32 index) const {
|
||||
return index < m_textureBindings.Size() ? m_textureBindings[index].texturePath : Containers::String();
|
||||
}
|
||||
|
||||
ResourceHandle<Texture> Material::GetTextureBindingTexture(Core::uint32 index) const {
|
||||
return index < m_textureBindings.Size() ? m_textureBindings[index].texture : ResourceHandle<Texture>();
|
||||
Material* material = const_cast<Material*>(this);
|
||||
material->ResolvePendingTextureBinding(index);
|
||||
if (index < material->m_textureBindings.Size()) {
|
||||
MaterialTextureBinding& binding = material->m_textureBindings[index];
|
||||
if (binding.texture.Get() == nullptr &&
|
||||
binding.pendingLoad == nullptr &&
|
||||
!binding.texturePath.Empty()) {
|
||||
material->BeginAsyncTextureLoad(index);
|
||||
}
|
||||
return binding.texture;
|
||||
}
|
||||
|
||||
return ResourceHandle<Texture>();
|
||||
}
|
||||
|
||||
std::vector<MaterialProperty> Material::GetProperties() const {
|
||||
@@ -404,6 +462,59 @@ void Material::RecalculateMemorySize() {
|
||||
UpdateMemorySize();
|
||||
}
|
||||
|
||||
void Material::BeginAsyncTextureLoad(Core::uint32 index) {
|
||||
if (index >= m_textureBindings.Size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MaterialTextureBinding& binding = m_textureBindings[index];
|
||||
if (binding.texture.Get() != nullptr || binding.texturePath.Empty() || binding.pendingLoad != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
binding.pendingLoad = std::make_shared<PendingTextureLoadState>();
|
||||
std::weak_ptr<PendingTextureLoadState> weakState = binding.pendingLoad;
|
||||
const Containers::String texturePath = binding.texturePath;
|
||||
ResourceManager::Get().LoadAsync(
|
||||
texturePath,
|
||||
ResourceType::Texture,
|
||||
[weakState](LoadResult result) {
|
||||
if (std::shared_ptr<PendingTextureLoadState> state = weakState.lock()) {
|
||||
state->resource = result.resource;
|
||||
state->errorMessage = result.errorMessage;
|
||||
state->completed = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Material::ResolvePendingTextureBinding(Core::uint32 index) {
|
||||
if (index >= m_textureBindings.Size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MaterialTextureBinding& binding = m_textureBindings[index];
|
||||
if (!binding.pendingLoad || !binding.pendingLoad->completed) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<PendingTextureLoadState> completedLoad = std::move(binding.pendingLoad);
|
||||
binding.pendingLoad.reset();
|
||||
if (completedLoad->resource == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
binding.texture = ResourceHandle<Texture>(static_cast<Texture*>(completedLoad->resource));
|
||||
if (binding.texture.Get() != nullptr) {
|
||||
binding.texturePath = binding.texture->GetPath();
|
||||
}
|
||||
}
|
||||
|
||||
void Material::ResolvePendingTextureBindings() {
|
||||
for (Core::uint32 bindingIndex = 0; bindingIndex < m_textureBindings.Size(); ++bindingIndex) {
|
||||
ResolvePendingTextureBinding(bindingIndex);
|
||||
}
|
||||
}
|
||||
|
||||
bool Material::HasProperty(const Containers::String& name) const {
|
||||
return m_properties.Contains(name);
|
||||
}
|
||||
@@ -457,6 +568,7 @@ void Material::UpdateMemorySize() {
|
||||
|
||||
for (const auto& binding : m_textureBindings) {
|
||||
m_memorySize += binding.name.Length();
|
||||
m_memorySize += binding.texturePath.Length();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user