mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
move materialcache et al to material-networking library
This commit is contained in:
parent
e601f6c59f
commit
f7a487a020
37 changed files with 480 additions and 451 deletions
|
@ -14,7 +14,7 @@ link_hifi_libraries(
|
|||
audio avatars octree gpu graphics shaders fbx hfm entities
|
||||
networking animation recording shared script-engine embedded-webserver
|
||||
controllers physics plugins midi image
|
||||
model-networking ktx shaders
|
||||
material-networking model-networking ktx shaders
|
||||
)
|
||||
|
||||
add_dependencies(${TARGET_NAME} oven)
|
||||
|
|
|
@ -205,8 +205,8 @@ endif()
|
|||
# link required hifi libraries
|
||||
link_hifi_libraries(
|
||||
shared workload task octree ktx gpu gl procedural graphics graphics-scripting render
|
||||
pointers
|
||||
recording hfm fbx networking model-networking model-baker entities avatars trackers
|
||||
pointers recording hfm fbx networking material-networking
|
||||
model-networking model-baker entities avatars trackers
|
||||
audio audio-client animation script-engine physics
|
||||
render-utils entities-renderer avatars-renderer ui qml auto-updater midi
|
||||
controllers plugins image trackers
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
#include <MessagesClient.h>
|
||||
#include <hfm/ModelFormatRegistry.h>
|
||||
#include <model-networking/ModelCacheScriptingInterface.h>
|
||||
#include <model-networking/TextureCacheScriptingInterface.h>
|
||||
#include <material-networking/TextureCacheScriptingInterface.h>
|
||||
#include <ModelEntityItem.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <NetworkingConstants.h>
|
||||
|
@ -153,7 +153,7 @@
|
|||
#include <avatars-renderer/ScriptAvatar.h>
|
||||
#include <RenderableEntityItem.h>
|
||||
#include <RenderableWebEntityItem.h>
|
||||
#include <model-networking/MaterialCache.h>
|
||||
#include <material-networking/MaterialCache.h>
|
||||
#include "recording/ClipCache.h"
|
||||
|
||||
#include "AudioClient.h"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(TARGET_NAME avatars-renderer)
|
||||
setup_hifi_library(Network Script)
|
||||
link_hifi_libraries(shared shaders gpu graphics animation model-networking script-engine render render-utils image trackers entities-renderer)
|
||||
link_hifi_libraries(shared shaders gpu graphics animation material-networking model-networking script-engine render render-utils image trackers entities-renderer)
|
||||
include_hifi_library_headers(avatars)
|
||||
include_hifi_library_headers(networking)
|
||||
include_hifi_library_headers(hfm)
|
||||
|
|
|
@ -2,6 +2,7 @@ set(TARGET_NAME display-plugins)
|
|||
setup_hifi_library(Gui)
|
||||
link_hifi_libraries(shared shaders plugins ui-plugins gl ui render-utils ${PLATFORM_GL_BACKEND})
|
||||
include_hifi_library_headers(gpu)
|
||||
include_hifi_library_headers(material-networking)
|
||||
include_hifi_library_headers(model-networking)
|
||||
include_hifi_library_headers(networking)
|
||||
include_hifi_library_headers(graphics)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(TARGET_NAME entities-renderer)
|
||||
setup_hifi_library(Network Script)
|
||||
link_hifi_libraries(shared workload gpu shaders procedural graphics model-networking script-engine render render-utils image qml ui pointers)
|
||||
link_hifi_libraries(shared workload gpu shaders procedural graphics material-networking model-networking script-engine render render-utils image qml ui pointers)
|
||||
include_hifi_library_headers(networking)
|
||||
include_hifi_library_headers(gl)
|
||||
include_hifi_library_headers(ktx)
|
||||
|
|
|
@ -6,4 +6,4 @@ include_hifi_library_headers(fbx)
|
|||
include_hifi_library_headers(gpu)
|
||||
include_hifi_library_headers(image)
|
||||
include_hifi_library_headers(ktx)
|
||||
link_hifi_libraries(shared shaders networking octree avatars graphics model-networking)
|
||||
link_hifi_libraries(shared shaders networking octree avatars graphics material-networking model-networking)
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "MaterialMappingMode.h"
|
||||
#include <model-networking/ModelCache.h>
|
||||
#include <model-networking/MaterialCache.h>
|
||||
#include <material-networking/MaterialCache.h>
|
||||
|
||||
class MaterialEntityItem : public EntityItem {
|
||||
using Pointer = std::shared_ptr<MaterialEntityItem>;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
set(TARGET_NAME graphics-scripting)
|
||||
setup_hifi_library()
|
||||
link_hifi_libraries(shared networking graphics fbx image model-networking script-engine)
|
||||
link_hifi_libraries(shared networking graphics fbx image material-networking model-networking script-engine)
|
||||
include_hifi_library_headers(gpu)
|
||||
|
|
5
libraries/material-networking/CMakeLists.txt
Normal file
5
libraries/material-networking/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
set(TARGET_NAME material-networking)
|
||||
setup_hifi_library()
|
||||
link_hifi_libraries(shared shaders networking graphics fbx ktx image gl)
|
||||
include_hifi_library_headers(gpu)
|
||||
include_hifi_library_headers(hfm)
|
|
@ -426,4 +426,310 @@ QSharedPointer<Resource> MaterialCache::createResource(const QUrl& url) {
|
|||
|
||||
QSharedPointer<Resource> MaterialCache::createResourceCopy(const QSharedPointer<Resource>& resource) {
|
||||
return QSharedPointer<Resource>(new NetworkMaterialResource(*resource.staticCast<NetworkMaterialResource>().data()), &Resource::deleter);
|
||||
}
|
||||
|
||||
NetworkMaterial::NetworkMaterial(const NetworkMaterial& m) :
|
||||
Material(m),
|
||||
_textures(m._textures),
|
||||
_albedoTransform(m._albedoTransform),
|
||||
_lightmapTransform(m._lightmapTransform),
|
||||
_lightmapParams(m._lightmapParams),
|
||||
_isOriginal(m._isOriginal)
|
||||
{}
|
||||
|
||||
const QString NetworkMaterial::NO_TEXTURE = QString();
|
||||
|
||||
const QString& NetworkMaterial::getTextureName(MapChannel channel) {
|
||||
if (_textures[channel].texture) {
|
||||
return _textures[channel].name;
|
||||
}
|
||||
return NO_TEXTURE;
|
||||
}
|
||||
|
||||
QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const HFMTexture& texture) {
|
||||
if (texture.content.isEmpty()) {
|
||||
// External file: search relative to the baseUrl, in case filename is relative
|
||||
return baseUrl.resolved(QUrl(texture.filename));
|
||||
} else {
|
||||
// Inlined file: cache under the fbx file to avoid namespace clashes
|
||||
// NOTE: We cannot resolve the path because filename may be an absolute path
|
||||
assert(texture.filename.size() > 0);
|
||||
auto baseUrlStripped = baseUrl.toDisplayString(QUrl::RemoveFragment | QUrl::RemoveQuery | QUrl::RemoveUserInfo);
|
||||
if (texture.filename.at(0) == '/') {
|
||||
return baseUrlStripped + texture.filename;
|
||||
} else {
|
||||
return baseUrlStripped + '/' + texture.filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, const HFMTexture& hfmTexture,
|
||||
image::TextureUsage::Type type, MapChannel channel) {
|
||||
|
||||
if (baseUrl.isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto url = getTextureUrl(baseUrl, hfmTexture);
|
||||
const auto texture = DependencyManager::get<TextureCache>()->getTexture(url, type, hfmTexture.content, hfmTexture.maxNumPixels);
|
||||
_textures[channel] = Texture { hfmTexture.name, texture };
|
||||
|
||||
auto map = std::make_shared<graphics::TextureMap>();
|
||||
if (texture) {
|
||||
map->setTextureSource(texture->_textureSource);
|
||||
}
|
||||
map->setTextureTransform(hfmTexture.transform);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel) {
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
if (textureCache && !url.isEmpty()) {
|
||||
auto texture = textureCache->getTexture(url, type);
|
||||
_textures[channel].texture = texture;
|
||||
|
||||
auto map = std::make_shared<graphics::TextureMap>();
|
||||
if (texture) {
|
||||
map->setTextureSource(texture->_textureSource);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NetworkMaterial::setAlbedoMap(const QUrl& url, bool useAlphaChannel) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP);
|
||||
if (map) {
|
||||
map->setUseAlphaChannel(useAlphaChannel);
|
||||
setTextureMap(MapChannel::ALBEDO_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setNormalMap(const QUrl& url, bool isBumpmap) {
|
||||
auto map = fetchTextureMap(url, isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::NORMAL_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setRoughnessMap(const QUrl& url, bool isGloss) {
|
||||
auto map = fetchTextureMap(url, isGloss ? image::TextureUsage::GLOSS_TEXTURE : image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::ROUGHNESS_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setMetallicMap(const QUrl& url, bool isSpecular) {
|
||||
auto map = fetchTextureMap(url, isSpecular ? image::TextureUsage::SPECULAR_TEXTURE : image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::METALLIC_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setOcclusionMap(const QUrl& url) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::OCCLUSION_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setEmissiveMap(const QUrl& url) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::EMISSIVE_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setScatteringMap(const QUrl& url) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::SCATTERING_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setLightmapMap(const QUrl& url) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP);
|
||||
if (map) {
|
||||
//map->setTextureTransform(_lightmapTransform);
|
||||
//map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y);
|
||||
setTextureMap(MapChannel::LIGHTMAP_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkMaterial::NetworkMaterial(const HFMMaterial& material, const QUrl& textureBaseUrl) :
|
||||
graphics::Material(*material._material),
|
||||
_textures(MapChannel::NUM_MAP_CHANNELS)
|
||||
{
|
||||
_name = material.name.toStdString();
|
||||
if (!material.albedoTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP);
|
||||
if (map) {
|
||||
_albedoTransform = material.albedoTexture.transform;
|
||||
map->setTextureTransform(_albedoTransform);
|
||||
|
||||
if (!material.opacityTexture.filename.isEmpty()) {
|
||||
if (material.albedoTexture.filename == material.opacityTexture.filename) {
|
||||
// Best case scenario, just indicating that the albedo map contains transparency
|
||||
// TODO: Different albedo/opacity maps are not currently supported
|
||||
map->setUseAlphaChannel(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTextureMap(MapChannel::ALBEDO_MAP, map);
|
||||
}
|
||||
|
||||
|
||||
if (!material.normalTexture.filename.isEmpty()) {
|
||||
auto type = (material.normalTexture.isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE);
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.normalTexture, type, MapChannel::NORMAL_MAP);
|
||||
setTextureMap(MapChannel::NORMAL_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.roughnessTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.roughnessTexture, image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP);
|
||||
setTextureMap(MapChannel::ROUGHNESS_MAP, map);
|
||||
} else if (!material.glossTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.glossTexture, image::TextureUsage::GLOSS_TEXTURE, MapChannel::ROUGHNESS_MAP);
|
||||
setTextureMap(MapChannel::ROUGHNESS_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.metallicTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.metallicTexture, image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP);
|
||||
setTextureMap(MapChannel::METALLIC_MAP, map);
|
||||
} else if (!material.specularTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.specularTexture, image::TextureUsage::SPECULAR_TEXTURE, MapChannel::METALLIC_MAP);
|
||||
setTextureMap(MapChannel::METALLIC_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.occlusionTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.occlusionTexture, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP);
|
||||
if (map) {
|
||||
map->setTextureTransform(material.occlusionTexture.transform);
|
||||
}
|
||||
setTextureMap(MapChannel::OCCLUSION_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.emissiveTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.emissiveTexture, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP);
|
||||
setTextureMap(MapChannel::EMISSIVE_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.scatteringTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.scatteringTexture, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP);
|
||||
setTextureMap(MapChannel::SCATTERING_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.lightmapTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP);
|
||||
if (map) {
|
||||
_lightmapTransform = material.lightmapTexture.transform;
|
||||
_lightmapParams = material.lightmapParams;
|
||||
map->setTextureTransform(_lightmapTransform);
|
||||
map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y);
|
||||
}
|
||||
setTextureMap(MapChannel::LIGHTMAP_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setTextures(const QVariantMap& textureMap) {
|
||||
_isOriginal = false;
|
||||
|
||||
const auto& albedoName = getTextureName(MapChannel::ALBEDO_MAP);
|
||||
const auto& normalName = getTextureName(MapChannel::NORMAL_MAP);
|
||||
const auto& roughnessName = getTextureName(MapChannel::ROUGHNESS_MAP);
|
||||
const auto& metallicName = getTextureName(MapChannel::METALLIC_MAP);
|
||||
const auto& occlusionName = getTextureName(MapChannel::OCCLUSION_MAP);
|
||||
const auto& emissiveName = getTextureName(MapChannel::EMISSIVE_MAP);
|
||||
const auto& lightmapName = getTextureName(MapChannel::LIGHTMAP_MAP);
|
||||
const auto& scatteringName = getTextureName(MapChannel::SCATTERING_MAP);
|
||||
|
||||
if (!albedoName.isEmpty()) {
|
||||
auto url = textureMap.contains(albedoName) ? textureMap[albedoName].toUrl() : QUrl();
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP);
|
||||
if (map) {
|
||||
map->setTextureTransform(_albedoTransform);
|
||||
// when reassigning the albedo texture we also check for the alpha channel used as opacity
|
||||
map->setUseAlphaChannel(true);
|
||||
}
|
||||
setTextureMap(MapChannel::ALBEDO_MAP, map);
|
||||
}
|
||||
|
||||
if (!normalName.isEmpty()) {
|
||||
auto url = textureMap.contains(normalName) ? textureMap[normalName].toUrl() : QUrl();
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP);
|
||||
setTextureMap(MapChannel::NORMAL_MAP, map);
|
||||
}
|
||||
|
||||
if (!roughnessName.isEmpty()) {
|
||||
auto url = textureMap.contains(roughnessName) ? textureMap[roughnessName].toUrl() : QUrl();
|
||||
// FIXME: If passing a gloss map instead of a roughmap how do we know?
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP);
|
||||
setTextureMap(MapChannel::ROUGHNESS_MAP, map);
|
||||
}
|
||||
|
||||
if (!metallicName.isEmpty()) {
|
||||
auto url = textureMap.contains(metallicName) ? textureMap[metallicName].toUrl() : QUrl();
|
||||
// FIXME: If passing a specular map instead of a metallic how do we know?
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP);
|
||||
setTextureMap(MapChannel::METALLIC_MAP, map);
|
||||
}
|
||||
|
||||
if (!occlusionName.isEmpty()) {
|
||||
auto url = textureMap.contains(occlusionName) ? textureMap[occlusionName].toUrl() : QUrl();
|
||||
// FIXME: we need to handle the occlusion map transform here
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP);
|
||||
setTextureMap(MapChannel::OCCLUSION_MAP, map);
|
||||
}
|
||||
|
||||
if (!emissiveName.isEmpty()) {
|
||||
auto url = textureMap.contains(emissiveName) ? textureMap[emissiveName].toUrl() : QUrl();
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP);
|
||||
setTextureMap(MapChannel::EMISSIVE_MAP, map);
|
||||
}
|
||||
|
||||
if (!scatteringName.isEmpty()) {
|
||||
auto url = textureMap.contains(scatteringName) ? textureMap[scatteringName].toUrl() : QUrl();
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP);
|
||||
setTextureMap(MapChannel::SCATTERING_MAP, map);
|
||||
}
|
||||
|
||||
if (!lightmapName.isEmpty()) {
|
||||
auto url = textureMap.contains(lightmapName) ? textureMap[lightmapName].toUrl() : QUrl();
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP);
|
||||
if (map) {
|
||||
map->setTextureTransform(_lightmapTransform);
|
||||
map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y);
|
||||
}
|
||||
setTextureMap(MapChannel::LIGHTMAP_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkMaterial::isMissingTexture() {
|
||||
for (auto& networkTexture : _textures) {
|
||||
auto& texture = networkTexture.texture;
|
||||
if (!texture) {
|
||||
continue;
|
||||
}
|
||||
// Failed texture downloads need to be considered as 'loaded'
|
||||
// or the object will never fade in
|
||||
bool finished = texture->isFailed() || (texture->isLoaded() && texture->getGPUTexture() && texture->getGPUTexture()->isDefined());
|
||||
if (!finished) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetworkMaterial::checkResetOpacityMap() {
|
||||
// If material textures are loaded, check the material translucency
|
||||
// FIXME: This should not be done here. The opacity map should already be reset in Material::setTextureMap.
|
||||
// However, currently that code can be called before the albedo map is defined, so resetOpacityMap will fail.
|
||||
// Geometry::areTexturesLoaded() is called repeatedly until it returns true, so we do the check here for now
|
||||
const auto& albedoTexture = _textures[NetworkMaterial::MapChannel::ALBEDO_MAP];
|
||||
if (albedoTexture.texture) {
|
||||
resetOpacityMap();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// Created by Sam Gondelman on 2/9/2018
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_MaterialCache_h
|
||||
#define hifi_MaterialCache_h
|
||||
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
#include <ResourceCache.h>
|
||||
#include <graphics/Material.h>
|
||||
#include <hfm/HFM.h>
|
||||
|
||||
#include "TextureCache.h"
|
||||
|
||||
class NetworkMaterial : public graphics::Material {
|
||||
public:
|
||||
using MapChannel = graphics::Material::MapChannel;
|
||||
|
||||
NetworkMaterial() : _textures(MapChannel::NUM_MAP_CHANNELS) {}
|
||||
NetworkMaterial(const HFMMaterial& material, const QUrl& textureBaseUrl);
|
||||
NetworkMaterial(const NetworkMaterial& material);
|
||||
|
||||
void setAlbedoMap(const QUrl& url, bool useAlphaChannel);
|
||||
void setNormalMap(const QUrl& url, bool isBumpmap);
|
||||
void setRoughnessMap(const QUrl& url, bool isGloss);
|
||||
void setMetallicMap(const QUrl& url, bool isSpecular);
|
||||
void setOcclusionMap(const QUrl& url);
|
||||
void setEmissiveMap(const QUrl& url);
|
||||
void setScatteringMap(const QUrl& url);
|
||||
void setLightmapMap(const QUrl& url);
|
||||
|
||||
bool isMissingTexture();
|
||||
void checkResetOpacityMap();
|
||||
|
||||
protected:
|
||||
friend class Geometry;
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
QString name;
|
||||
NetworkTexturePointer texture;
|
||||
};
|
||||
using Textures = std::vector<Texture>;
|
||||
|
||||
Textures _textures;
|
||||
|
||||
static const QString NO_TEXTURE;
|
||||
const QString& getTextureName(MapChannel channel);
|
||||
|
||||
void setTextures(const QVariantMap& textureMap);
|
||||
|
||||
const bool& isOriginal() const { return _isOriginal; }
|
||||
|
||||
private:
|
||||
// Helpers for the ctors
|
||||
QUrl getTextureUrl(const QUrl& baseUrl, const HFMTexture& hfmTexture);
|
||||
graphics::TextureMapPointer fetchTextureMap(const QUrl& baseUrl, const HFMTexture& hfmTexture,
|
||||
image::TextureUsage::Type type, MapChannel channel);
|
||||
graphics::TextureMapPointer fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel);
|
||||
|
||||
Transform _albedoTransform;
|
||||
Transform _lightmapTransform;
|
||||
vec2 _lightmapParams;
|
||||
|
||||
bool _isOriginal { true };
|
||||
};
|
||||
|
||||
class NetworkMaterialResource : public Resource {
|
||||
public:
|
||||
NetworkMaterialResource(const QUrl& url);
|
||||
|
||||
QString getType() const override { return "NetworkMaterial"; }
|
||||
|
||||
virtual void downloadFinished(const QByteArray& data) override;
|
||||
|
||||
typedef struct ParsedMaterials {
|
||||
uint version { 1 };
|
||||
std::vector<std::string> names;
|
||||
std::unordered_map<std::string, std::shared_ptr<NetworkMaterial>> networkMaterials;
|
||||
|
||||
void reset() {
|
||||
version = 1;
|
||||
names.clear();
|
||||
networkMaterials.clear();
|
||||
}
|
||||
|
||||
} ParsedMaterials;
|
||||
|
||||
ParsedMaterials parsedMaterials;
|
||||
|
||||
static ParsedMaterials parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl);
|
||||
static std::pair<std::string, std::shared_ptr<NetworkMaterial>> parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl);
|
||||
|
||||
private:
|
||||
static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB);
|
||||
};
|
||||
|
||||
using NetworkMaterialResourcePointer = QSharedPointer<NetworkMaterialResource>;
|
||||
|
||||
class MaterialCache : public ResourceCache {
|
||||
public:
|
||||
static MaterialCache& instance();
|
||||
|
||||
NetworkMaterialResourcePointer getMaterial(const QUrl& url);
|
||||
|
||||
protected:
|
||||
virtual QSharedPointer<Resource> createResource(const QUrl& url) override;
|
||||
QSharedPointer<Resource> createResourceCopy(const QSharedPointer<Resource>& resource) override;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// Created by Sam Gondelman on 2/7/2019
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "MaterialNetworkingLogging.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(materialnetworking, "hifi.gpu-material-network")
|
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// Created by Sam Gondelman on 2/7/2019
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QLoggingCategory>
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(materialnetworking)
|
|
@ -44,7 +44,7 @@
|
|||
#include <Profile.h>
|
||||
|
||||
#include "NetworkLogging.h"
|
||||
#include "ModelNetworkingLogging.h"
|
||||
#include "MaterialNetworkingLogging.h"
|
||||
#include "NetworkingConstants.h"
|
||||
#include <Trace.h>
|
||||
#include <StatTracker.h>
|
||||
|
@ -938,7 +938,7 @@ void NetworkTexture::handleFinishedInitialLoad() {
|
|||
cache::FilePointer file;
|
||||
auto& ktxCache = textureCache->_ktxCache;
|
||||
if (!memKtx || !(file = ktxCache->writeFile(data, KTXCache::Metadata(filename, length)))) {
|
||||
qCWarning(modelnetworking) << url << " failed to write cache file";
|
||||
qCWarning(materialnetworking) << url << " failed to write cache file";
|
||||
QMetaObject::invokeMethod(resource.data(), "setImage",
|
||||
Q_ARG(gpu::TexturePointer, nullptr),
|
||||
Q_ARG(int, 0),
|
||||
|
@ -1126,7 +1126,7 @@ void ImageReader::listSupportedImageFormats() {
|
|||
static std::once_flag once;
|
||||
std::call_once(once, []{
|
||||
auto supportedFormats = QImageReader::supportedImageFormats();
|
||||
qCDebug(modelnetworking) << "List of supported Image formats:" << supportedFormats.join(", ");
|
||||
qCDebug(materialnetworking) << "List of supported Image formats:" << supportedFormats.join(", ");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1174,7 +1174,7 @@ void ImageReader::read() {
|
|||
if (texture) {
|
||||
texture = textureCache->cacheTextureByHash(hash, texture);
|
||||
} else {
|
||||
qCWarning(modelnetworking) << "Invalid cached KTX " << _url << " under hash " << hash.c_str() << ", recreating...";
|
||||
qCWarning(materialnetworking) << "Invalid cached KTX " << _url << " under hash " << hash.c_str() << ", recreating...";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
set(TARGET_NAME model-baker)
|
||||
setup_hifi_library()
|
||||
|
||||
link_hifi_libraries(shared task gpu graphics hfm)
|
||||
link_hifi_libraries(shared shaders task gpu graphics hfm material-networking)
|
||||
include_hifi_library_headers(networking)
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include "ModelBakerLogging.h"
|
||||
|
||||
#include <material-networking/MaterialCache.h>
|
||||
|
||||
void ApplyMaterialMappingTask::run(const baker::BakeContextPointer& context, const Input& input, Output& output) {
|
||||
const auto& materialsIn = input.get0();
|
||||
const auto& mapping = input.get1();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
set(TARGET_NAME model-networking)
|
||||
setup_hifi_library()
|
||||
link_hifi_libraries(shared shaders networking graphics fbx ktx image gl model-baker)
|
||||
include_hifi_library_headers(gpu)
|
||||
link_hifi_libraries(shared shaders networking graphics fbx material-networking model-baker)
|
||||
include_hifi_library_headers(hfm)
|
||||
include_hifi_library_headers(task)
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
//
|
||||
// Created by Sam Gondelman on 2/9/2018
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_MaterialCache_h
|
||||
#define hifi_MaterialCache_h
|
||||
|
||||
#include <ResourceCache.h>
|
||||
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
#include "ModelCache.h"
|
||||
|
||||
class NetworkMaterialResource : public Resource {
|
||||
public:
|
||||
NetworkMaterialResource(const QUrl& url);
|
||||
|
||||
QString getType() const override { return "NetworkMaterial"; }
|
||||
|
||||
virtual void downloadFinished(const QByteArray& data) override;
|
||||
|
||||
typedef struct ParsedMaterials {
|
||||
uint version { 1 };
|
||||
std::vector<std::string> names;
|
||||
std::unordered_map<std::string, std::shared_ptr<NetworkMaterial>> networkMaterials;
|
||||
|
||||
void reset() {
|
||||
version = 1;
|
||||
names.clear();
|
||||
networkMaterials.clear();
|
||||
}
|
||||
|
||||
} ParsedMaterials;
|
||||
|
||||
ParsedMaterials parsedMaterials;
|
||||
|
||||
static ParsedMaterials parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl);
|
||||
static std::pair<std::string, std::shared_ptr<NetworkMaterial>> parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl);
|
||||
|
||||
private:
|
||||
static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB);
|
||||
};
|
||||
|
||||
using NetworkMaterialResourcePointer = QSharedPointer<NetworkMaterialResource>;
|
||||
|
||||
class MaterialCache : public ResourceCache {
|
||||
public:
|
||||
static MaterialCache& instance();
|
||||
|
||||
NetworkMaterialResourcePointer getMaterial(const QUrl& url);
|
||||
|
||||
protected:
|
||||
virtual QSharedPointer<Resource> createResource(const QUrl& url) override;
|
||||
QSharedPointer<Resource> createResourceCopy(const QSharedPointer<Resource>& resource) override;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -556,310 +556,4 @@ void GeometryResourceWatcher::resourceRefreshed() {
|
|||
// _instance.reset();
|
||||
}
|
||||
|
||||
NetworkMaterial::NetworkMaterial(const NetworkMaterial& m) :
|
||||
Material(m),
|
||||
_textures(m._textures),
|
||||
_albedoTransform(m._albedoTransform),
|
||||
_lightmapTransform(m._lightmapTransform),
|
||||
_lightmapParams(m._lightmapParams),
|
||||
_isOriginal(m._isOriginal)
|
||||
{}
|
||||
|
||||
const QString NetworkMaterial::NO_TEXTURE = QString();
|
||||
|
||||
const QString& NetworkMaterial::getTextureName(MapChannel channel) {
|
||||
if (_textures[channel].texture) {
|
||||
return _textures[channel].name;
|
||||
}
|
||||
return NO_TEXTURE;
|
||||
}
|
||||
|
||||
QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const HFMTexture& texture) {
|
||||
if (texture.content.isEmpty()) {
|
||||
// External file: search relative to the baseUrl, in case filename is relative
|
||||
return baseUrl.resolved(QUrl(texture.filename));
|
||||
} else {
|
||||
// Inlined file: cache under the fbx file to avoid namespace clashes
|
||||
// NOTE: We cannot resolve the path because filename may be an absolute path
|
||||
assert(texture.filename.size() > 0);
|
||||
auto baseUrlStripped = baseUrl.toDisplayString(QUrl::RemoveFragment | QUrl::RemoveQuery | QUrl::RemoveUserInfo);
|
||||
if (texture.filename.at(0) == '/') {
|
||||
return baseUrlStripped + texture.filename;
|
||||
} else {
|
||||
return baseUrlStripped + '/' + texture.filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, const HFMTexture& hfmTexture,
|
||||
image::TextureUsage::Type type, MapChannel channel) {
|
||||
|
||||
if (baseUrl.isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto url = getTextureUrl(baseUrl, hfmTexture);
|
||||
const auto texture = DependencyManager::get<TextureCache>()->getTexture(url, type, hfmTexture.content, hfmTexture.maxNumPixels);
|
||||
_textures[channel] = Texture { hfmTexture.name, texture };
|
||||
|
||||
auto map = std::make_shared<graphics::TextureMap>();
|
||||
if (texture) {
|
||||
map->setTextureSource(texture->_textureSource);
|
||||
}
|
||||
map->setTextureTransform(hfmTexture.transform);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel) {
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
if (textureCache && !url.isEmpty()) {
|
||||
auto texture = textureCache->getTexture(url, type);
|
||||
_textures[channel].texture = texture;
|
||||
|
||||
auto map = std::make_shared<graphics::TextureMap>();
|
||||
if (texture) {
|
||||
map->setTextureSource(texture->_textureSource);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NetworkMaterial::setAlbedoMap(const QUrl& url, bool useAlphaChannel) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP);
|
||||
if (map) {
|
||||
map->setUseAlphaChannel(useAlphaChannel);
|
||||
setTextureMap(MapChannel::ALBEDO_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setNormalMap(const QUrl& url, bool isBumpmap) {
|
||||
auto map = fetchTextureMap(url, isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::NORMAL_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setRoughnessMap(const QUrl& url, bool isGloss) {
|
||||
auto map = fetchTextureMap(url, isGloss ? image::TextureUsage::GLOSS_TEXTURE : image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::ROUGHNESS_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setMetallicMap(const QUrl& url, bool isSpecular) {
|
||||
auto map = fetchTextureMap(url, isSpecular ? image::TextureUsage::SPECULAR_TEXTURE : image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::METALLIC_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setOcclusionMap(const QUrl& url) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::OCCLUSION_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setEmissiveMap(const QUrl& url) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::EMISSIVE_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setScatteringMap(const QUrl& url) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP);
|
||||
if (map) {
|
||||
setTextureMap(MapChannel::SCATTERING_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setLightmapMap(const QUrl& url) {
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP);
|
||||
if (map) {
|
||||
//map->setTextureTransform(_lightmapTransform);
|
||||
//map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y);
|
||||
setTextureMap(MapChannel::LIGHTMAP_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
NetworkMaterial::NetworkMaterial(const HFMMaterial& material, const QUrl& textureBaseUrl) :
|
||||
graphics::Material(*material._material),
|
||||
_textures(MapChannel::NUM_MAP_CHANNELS)
|
||||
{
|
||||
_name = material.name.toStdString();
|
||||
if (!material.albedoTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP);
|
||||
if (map) {
|
||||
_albedoTransform = material.albedoTexture.transform;
|
||||
map->setTextureTransform(_albedoTransform);
|
||||
|
||||
if (!material.opacityTexture.filename.isEmpty()) {
|
||||
if (material.albedoTexture.filename == material.opacityTexture.filename) {
|
||||
// Best case scenario, just indicating that the albedo map contains transparency
|
||||
// TODO: Different albedo/opacity maps are not currently supported
|
||||
map->setUseAlphaChannel(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTextureMap(MapChannel::ALBEDO_MAP, map);
|
||||
}
|
||||
|
||||
|
||||
if (!material.normalTexture.filename.isEmpty()) {
|
||||
auto type = (material.normalTexture.isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE);
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.normalTexture, type, MapChannel::NORMAL_MAP);
|
||||
setTextureMap(MapChannel::NORMAL_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.roughnessTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.roughnessTexture, image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP);
|
||||
setTextureMap(MapChannel::ROUGHNESS_MAP, map);
|
||||
} else if (!material.glossTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.glossTexture, image::TextureUsage::GLOSS_TEXTURE, MapChannel::ROUGHNESS_MAP);
|
||||
setTextureMap(MapChannel::ROUGHNESS_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.metallicTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.metallicTexture, image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP);
|
||||
setTextureMap(MapChannel::METALLIC_MAP, map);
|
||||
} else if (!material.specularTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.specularTexture, image::TextureUsage::SPECULAR_TEXTURE, MapChannel::METALLIC_MAP);
|
||||
setTextureMap(MapChannel::METALLIC_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.occlusionTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.occlusionTexture, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP);
|
||||
if (map) {
|
||||
map->setTextureTransform(material.occlusionTexture.transform);
|
||||
}
|
||||
setTextureMap(MapChannel::OCCLUSION_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.emissiveTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.emissiveTexture, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP);
|
||||
setTextureMap(MapChannel::EMISSIVE_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.scatteringTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.scatteringTexture, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP);
|
||||
setTextureMap(MapChannel::SCATTERING_MAP, map);
|
||||
}
|
||||
|
||||
if (!material.lightmapTexture.filename.isEmpty()) {
|
||||
auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP);
|
||||
if (map) {
|
||||
_lightmapTransform = material.lightmapTexture.transform;
|
||||
_lightmapParams = material.lightmapParams;
|
||||
map->setTextureTransform(_lightmapTransform);
|
||||
map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y);
|
||||
}
|
||||
setTextureMap(MapChannel::LIGHTMAP_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkMaterial::setTextures(const QVariantMap& textureMap) {
|
||||
_isOriginal = false;
|
||||
|
||||
const auto& albedoName = getTextureName(MapChannel::ALBEDO_MAP);
|
||||
const auto& normalName = getTextureName(MapChannel::NORMAL_MAP);
|
||||
const auto& roughnessName = getTextureName(MapChannel::ROUGHNESS_MAP);
|
||||
const auto& metallicName = getTextureName(MapChannel::METALLIC_MAP);
|
||||
const auto& occlusionName = getTextureName(MapChannel::OCCLUSION_MAP);
|
||||
const auto& emissiveName = getTextureName(MapChannel::EMISSIVE_MAP);
|
||||
const auto& lightmapName = getTextureName(MapChannel::LIGHTMAP_MAP);
|
||||
const auto& scatteringName = getTextureName(MapChannel::SCATTERING_MAP);
|
||||
|
||||
if (!albedoName.isEmpty()) {
|
||||
auto url = textureMap.contains(albedoName) ? textureMap[albedoName].toUrl() : QUrl();
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP);
|
||||
if (map) {
|
||||
map->setTextureTransform(_albedoTransform);
|
||||
// when reassigning the albedo texture we also check for the alpha channel used as opacity
|
||||
map->setUseAlphaChannel(true);
|
||||
}
|
||||
setTextureMap(MapChannel::ALBEDO_MAP, map);
|
||||
}
|
||||
|
||||
if (!normalName.isEmpty()) {
|
||||
auto url = textureMap.contains(normalName) ? textureMap[normalName].toUrl() : QUrl();
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP);
|
||||
setTextureMap(MapChannel::NORMAL_MAP, map);
|
||||
}
|
||||
|
||||
if (!roughnessName.isEmpty()) {
|
||||
auto url = textureMap.contains(roughnessName) ? textureMap[roughnessName].toUrl() : QUrl();
|
||||
// FIXME: If passing a gloss map instead of a roughmap how do we know?
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP);
|
||||
setTextureMap(MapChannel::ROUGHNESS_MAP, map);
|
||||
}
|
||||
|
||||
if (!metallicName.isEmpty()) {
|
||||
auto url = textureMap.contains(metallicName) ? textureMap[metallicName].toUrl() : QUrl();
|
||||
// FIXME: If passing a specular map instead of a metallic how do we know?
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP);
|
||||
setTextureMap(MapChannel::METALLIC_MAP, map);
|
||||
}
|
||||
|
||||
if (!occlusionName.isEmpty()) {
|
||||
auto url = textureMap.contains(occlusionName) ? textureMap[occlusionName].toUrl() : QUrl();
|
||||
// FIXME: we need to handle the occlusion map transform here
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP);
|
||||
setTextureMap(MapChannel::OCCLUSION_MAP, map);
|
||||
}
|
||||
|
||||
if (!emissiveName.isEmpty()) {
|
||||
auto url = textureMap.contains(emissiveName) ? textureMap[emissiveName].toUrl() : QUrl();
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP);
|
||||
setTextureMap(MapChannel::EMISSIVE_MAP, map);
|
||||
}
|
||||
|
||||
if (!scatteringName.isEmpty()) {
|
||||
auto url = textureMap.contains(scatteringName) ? textureMap[scatteringName].toUrl() : QUrl();
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP);
|
||||
setTextureMap(MapChannel::SCATTERING_MAP, map);
|
||||
}
|
||||
|
||||
if (!lightmapName.isEmpty()) {
|
||||
auto url = textureMap.contains(lightmapName) ? textureMap[lightmapName].toUrl() : QUrl();
|
||||
auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP);
|
||||
if (map) {
|
||||
map->setTextureTransform(_lightmapTransform);
|
||||
map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y);
|
||||
}
|
||||
setTextureMap(MapChannel::LIGHTMAP_MAP, map);
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkMaterial::isMissingTexture() {
|
||||
for (auto& networkTexture : _textures) {
|
||||
auto& texture = networkTexture.texture;
|
||||
if (!texture) {
|
||||
continue;
|
||||
}
|
||||
// Failed texture downloads need to be considered as 'loaded'
|
||||
// or the object will never fade in
|
||||
bool finished = texture->isFailed() || (texture->isLoaded() && texture->getGPUTexture() && texture->getGPUTexture()->isDefined());
|
||||
if (!finished) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetworkMaterial::checkResetOpacityMap() {
|
||||
// If material textures are loaded, check the material translucency
|
||||
// FIXME: This should not be done here. The opacity map should already be reset in Material::setTextureMap.
|
||||
// However, currently that code can be called before the albedo map is defined, so resetOpacityMap will fail.
|
||||
// Geometry::areTexturesLoaded() is called repeatedly until it returns true, so we do the check here for now
|
||||
const auto& albedoTexture = _textures[NetworkMaterial::MapChannel::ALBEDO_MAP];
|
||||
if (albedoTexture.texture) {
|
||||
resetOpacityMap();
|
||||
}
|
||||
}
|
||||
|
||||
#include "ModelCache.moc"
|
||||
|
|
|
@ -15,17 +15,13 @@
|
|||
#include <DependencyManager.h>
|
||||
#include <ResourceCache.h>
|
||||
|
||||
#include <graphics/Material.h>
|
||||
#include <graphics/Asset.h>
|
||||
|
||||
#include "FBXSerializer.h"
|
||||
#include "TextureCache.h"
|
||||
#include <material-networking/MaterialCache.h>
|
||||
#include <material-networking/TextureCache.h>
|
||||
#include "ModelLoader.h"
|
||||
|
||||
// Alias instead of derive to avoid copying
|
||||
|
||||
class NetworkTexture;
|
||||
class NetworkMaterial;
|
||||
class MeshPart;
|
||||
|
||||
class GeometryMappingResource;
|
||||
|
@ -166,59 +162,6 @@ private:
|
|||
ModelLoader _modelLoader;
|
||||
};
|
||||
|
||||
class NetworkMaterial : public graphics::Material {
|
||||
public:
|
||||
using MapChannel = graphics::Material::MapChannel;
|
||||
|
||||
NetworkMaterial() : _textures(MapChannel::NUM_MAP_CHANNELS) {}
|
||||
NetworkMaterial(const HFMMaterial& material, const QUrl& textureBaseUrl);
|
||||
NetworkMaterial(const NetworkMaterial& material);
|
||||
|
||||
void setAlbedoMap(const QUrl& url, bool useAlphaChannel);
|
||||
void setNormalMap(const QUrl& url, bool isBumpmap);
|
||||
void setRoughnessMap(const QUrl& url, bool isGloss);
|
||||
void setMetallicMap(const QUrl& url, bool isSpecular);
|
||||
void setOcclusionMap(const QUrl& url);
|
||||
void setEmissiveMap(const QUrl& url);
|
||||
void setScatteringMap(const QUrl& url);
|
||||
void setLightmapMap(const QUrl& url);
|
||||
|
||||
bool isMissingTexture();
|
||||
void checkResetOpacityMap();
|
||||
|
||||
protected:
|
||||
friend class Geometry;
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
QString name;
|
||||
NetworkTexturePointer texture;
|
||||
};
|
||||
using Textures = std::vector<Texture>;
|
||||
|
||||
Textures _textures;
|
||||
|
||||
static const QString NO_TEXTURE;
|
||||
const QString& getTextureName(MapChannel channel);
|
||||
|
||||
void setTextures(const QVariantMap& textureMap);
|
||||
|
||||
const bool& isOriginal() const { return _isOriginal; }
|
||||
|
||||
private:
|
||||
// Helpers for the ctors
|
||||
QUrl getTextureUrl(const QUrl& baseUrl, const HFMTexture& hfmTexture);
|
||||
graphics::TextureMapPointer fetchTextureMap(const QUrl& baseUrl, const HFMTexture& hfmTexture,
|
||||
image::TextureUsage::Type type, MapChannel channel);
|
||||
graphics::TextureMapPointer fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel);
|
||||
|
||||
Transform _albedoTransform;
|
||||
Transform _lightmapTransform;
|
||||
vec2 _lightmapParams;
|
||||
|
||||
bool _isOriginal { true };
|
||||
};
|
||||
|
||||
class MeshPart {
|
||||
public:
|
||||
MeshPart(int mesh, int part, int material) : meshID { mesh }, partID { part }, materialID { material } {}
|
||||
|
|
|
@ -8,4 +8,4 @@
|
|||
|
||||
#include "ModelNetworkingLogging.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(modelnetworking, "hifi.gpu-network")
|
||||
Q_LOGGING_CATEGORY(modelnetworking, "hifi.gpu-model-network")
|
||||
|
|
|
@ -7,6 +7,7 @@ include_hifi_library_headers(avatars)
|
|||
include_hifi_library_headers(audio)
|
||||
include_hifi_library_headers(octree)
|
||||
include_hifi_library_headers(animation)
|
||||
include_hifi_library_headers(material-networking)
|
||||
include_hifi_library_headers(model-networking)
|
||||
include_hifi_library_headers(image)
|
||||
include_hifi_library_headers(ktx)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
set(TARGET_NAME procedural)
|
||||
setup_hifi_library()
|
||||
link_hifi_libraries(shared gpu shaders networking graphics model-networking ktx image)
|
||||
link_hifi_libraries(shared gpu shaders networking graphics material-networking ktx image)
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
#include <gpu/Shader.h>
|
||||
#include <gpu/Pipeline.h>
|
||||
#include <gpu/Batch.h>
|
||||
#include <model-networking/ShaderCache.h>
|
||||
#include <model-networking/TextureCache.h>
|
||||
#include <material-networking/ShaderCache.h>
|
||||
#include <material-networking/TextureCache.h>
|
||||
|
||||
using UniformLambdas = std::list<std::function<void(gpu::Batch& batch)>>;
|
||||
const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 };
|
||||
|
|
|
@ -3,7 +3,7 @@ set(TARGET_NAME render-utils)
|
|||
# pull in the resources.qrc file
|
||||
qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts.qrc")
|
||||
setup_hifi_library(Gui Network Qml Quick Script)
|
||||
link_hifi_libraries(shared task ktx gpu shaders graphics graphics-scripting model-networking render animation fbx image procedural)
|
||||
link_hifi_libraries(shared task ktx gpu shaders graphics graphics-scripting material-networking model-networking render animation fbx image procedural)
|
||||
include_hifi_library_headers(audio)
|
||||
include_hifi_library_headers(networking)
|
||||
include_hifi_library_headers(octree)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <functional>
|
||||
|
||||
#include <gpu/Context.h>
|
||||
#include <model-networking/TextureCache.h>
|
||||
#include <material-networking/TextureCache.h>
|
||||
#include <render/DrawTask.h>
|
||||
#include <shaders/Shaders.h>
|
||||
#include <graphics/ShaderConstants.h>
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
// Compatibility
|
||||
#include <model-networking/TextureCache.h>
|
||||
#include <material-networking/TextureCache.h>
|
||||
|
|
|
@ -17,6 +17,6 @@ if (NOT ANDROID)
|
|||
|
||||
endif ()
|
||||
|
||||
link_hifi_libraries(shared networking octree shaders gpu procedural graphics model-networking ktx recording avatars fbx hfm entities controllers animation audio physics image midi)
|
||||
link_hifi_libraries(shared networking octree shaders gpu procedural graphics material-networking model-networking ktx recording avatars fbx hfm entities controllers animation audio physics image midi)
|
||||
# ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit
|
||||
include_hifi_library_headers(gl)
|
||||
|
|
|
@ -11,7 +11,7 @@ if (WIN32 AND (NOT USE_GLES))
|
|||
setup_hifi_plugin(Gui Qml Multimedia)
|
||||
link_hifi_libraries(shared task gl qml networking controllers ui
|
||||
plugins display-plugins ui-plugins input-plugins script-engine
|
||||
audio-client render-utils graphics shaders gpu render model-networking model-baker hfm fbx ktx image procedural ${PLATFORM_GL_BACKEND})
|
||||
audio-client render-utils graphics shaders gpu render material-networking model-networking model-baker hfm fbx ktx image procedural ${PLATFORM_GL_BACKEND})
|
||||
include_hifi_library_headers(octree)
|
||||
|
||||
target_openvr()
|
||||
|
|
Loading…
Reference in a new issue