//// RenderPipelines.cpp// render-utils/src///// Created by Zach Pomerantz on 1/28/2016.// Copyright 2016 High Fidelity, Inc.// Copyright 2024 Overte e.V.//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #include "RenderPipelines.h" #include <material-networking/TextureCache.h>#include <render/DrawTask.h>#include <graphics/ShaderConstants.h>#include <procedural/ReferenceMaterial.h> #include "render-utils/ShaderConstants.h"#include "DeferredLightingEffect.h" using namespace render;using namespace gpu; namespace gr { using graphics::slot::texture::Texture; using graphics::slot::buffer::Buffer;} bool RenderPipelines::bindMaterial(graphics::MaterialPointer& material, Batch& batch, Args::RenderMode renderMode, bool enableTextures) { graphics::MultiMaterial multiMaterial; multiMaterial.push(graphics::MaterialLayer(material, 0)); return bindMaterials(multiMaterial, batch, renderMode, enableTextures);} void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial) { auto& drawMaterialTextures = multiMaterial.getTextureTables(); multiMaterial.setTexturesLoading(false); multiMaterial.resetReferenceTexturesAndMaterials(); if (!multiMaterial.empty() && multiMaterial.top().material) { multiMaterial.setisMToonAndLayers(multiMaterial.top().material->isMToon(), std::max(1, std::min((int)multiMaterial.size(), (int)multiMaterial.top().material->getLayers()))); } else { multiMaterial.setisMToonAndLayers(false, 1); } multiMaterial.resetOutline(); multiMaterial.resetSamplers(); multiMaterial.setSplatMap(nullptr); // The total list of things we need to look for static std::set<uint> allFlags; static std::once_flag once; std::call_once(once, [] { for (int i = 0; i < graphics::Material::NUM_TOTAL_FLAGS; i++) { // The opacity mask/map are derived from the albedo map // FIXME: OPACITY_MAP_MODE_BIT is supposed to support fallthrough if (i != graphics::MaterialKey::OPACITY_MASK_MAP_BIT && i != graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT && i != graphics::MaterialKey::OPACITY_MAP_MODE_BIT) { allFlags.insert(i); } } }); graphics::MultiMaterial materials = multiMaterial; std::array<graphics::MultiMaterial::Schema, 3> schemas; std::array<graphics::MultiMaterial::MToonSchema, 3> toonSchemas; std::array<graphics::MaterialKey, 3> schemaKeys; std::array<std::set<uint>, 3> flagsToCheck; flagsToCheck.fill(allFlags); // We only look for splat maps on the first material for (int i = 1; i < 3; i++) { flagsToCheck[i].erase(graphics::MaterialKey::SPLAT_MAP_BIT); } std::array<std::set<uint>, 3> flagsToSetDefault; uint8_t layerIndex = 0; while (!materials.empty()) { auto material = materials.top().material; if (!material) { break; } materials.pop(); if (material->isReference()) { multiMaterial.addReferenceMaterial(std::static_pointer_cast<ReferenceMaterial>(material)->getReferenceOperator()); } bool defaultFallthrough = material->getDefaultFallthrough(); const auto materialKey = material->getKey(); const auto textureMaps = material->getTextureMaps(); auto it = flagsToCheck[layerIndex].begin(); while (it != flagsToCheck[layerIndex].end()) { auto flag = *it; bool fallthrough = defaultFallthrough || material->getPropertyFallthrough(flag); bool wasSet = false; bool forceDefault = false; if (!multiMaterial.isMToon()) { switch (flag) { case graphics::MaterialKey::EMISSIVE_VAL_BIT: if (materialKey.isEmissive()) { schemas[layerIndex]._emissive = material->getEmissive(false); schemaKeys[layerIndex].setEmissive(true); wasSet = true; } break; case graphics::MaterialKey::UNLIT_VAL_BIT: if (materialKey.isUnlit()) { schemaKeys[layerIndex].setUnlit(true); wasSet = true; } break; case graphics::MaterialKey::ALBEDO_VAL_BIT: if (materialKey.isAlbedo()) { schemas[layerIndex]._albedo = material->getAlbedo(false); schemaKeys[layerIndex].setAlbedo(true); wasSet = true; } break; case graphics::MaterialKey::METALLIC_VAL_BIT: if (materialKey.isMetallic()) { schemas[layerIndex]._metallic = material->getMetallic(); schemaKeys[layerIndex].setMetallic(true); wasSet = true; } break; case graphics::MaterialKey::GLOSSY_VAL_BIT: if (materialKey.isRough() || materialKey.isGlossy()) { schemas[layerIndex]._roughness = material->getRoughness(); schemaKeys[layerIndex].setGlossy(materialKey.isGlossy()); wasSet = true; } break; case graphics::MaterialKey::OPACITY_VAL_BIT: if (materialKey.isTranslucentFactor()) { schemas[layerIndex]._opacity = material->getOpacity(); schemaKeys[layerIndex].setTranslucentFactor(true); wasSet = true; } break; case graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT: if (materialKey.isOpacityCutoff()) { schemas[layerIndex]._opacityCutoff = material->getOpacityCutoff(); schemaKeys[layerIndex].setOpacityCutoff(true); wasSet = true; } break; case graphics::MaterialKey::SCATTERING_VAL_BIT: if (materialKey.isScattering()) { schemas[layerIndex]._scattering = material->getScattering(); schemaKeys[layerIndex].setScattering(true); wasSet = true; } break; case graphics::MaterialKey::ALBEDO_MAP_BIT: if (materialKey.isAlbedoMap()) { auto itr = textureMaps.find(graphics::MaterialKey::ALBEDO_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { material->resetOpacityMap(); drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialAlbedo, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::ALBEDO_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setAlbedoMap(true); schemaKeys[layerIndex].setOpacityMaskMap(material->getKey().isOpacityMaskMap()); schemaKeys[layerIndex].setTranslucentMap(material->getKey().isTranslucentMap()); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialAlbedo, material->getTexCoordSet(graphics::MaterialKey::ALBEDO_MAP)); } break; case graphics::MaterialKey::METALLIC_MAP_BIT: if (materialKey.isMetallicMap()) { auto itr = textureMaps.find(graphics::MaterialKey::METALLIC_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialMetallic, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::METALLIC_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setMetallicMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialMetallic, material->getTexCoordSet(graphics::MaterialKey::METALLIC_MAP)); } break; case graphics::MaterialKey::ROUGHNESS_MAP_BIT: if (materialKey.isRoughnessMap()) { auto itr = textureMaps.find(graphics::MaterialKey::ROUGHNESS_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialRoughness, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::ROUGHNESS_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setRoughnessMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialRoughness, material->getTexCoordSet(graphics::MaterialKey::ROUGHNESS_MAP)); } break; case graphics::MaterialKey::NORMAL_MAP_BIT: if (materialKey.isNormalMap()) { auto itr = textureMaps.find(graphics::MaterialKey::NORMAL_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialNormal, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::NORMAL_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setNormalMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialNormal, material->getTexCoordSet(graphics::MaterialKey::NORMAL_MAP)); } break; case graphics::MaterialKey::OCCLUSION_MAP_BIT: if (materialKey.isOcclusionMap()) { auto itr = textureMaps.find(graphics::MaterialKey::OCCLUSION_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialOcclusion, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::OCCLUSION_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setOcclusionMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialOcclusion, material->getTexCoordSet(graphics::MaterialKey::OCCLUSION_MAP)); } break; case graphics::MaterialKey::SCATTERING_MAP_BIT: if (materialKey.isScatteringMap()) { auto itr = textureMaps.find(graphics::MaterialKey::SCATTERING_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialScattering, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::SCATTERING_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setScatteringMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialScattering, material->getTexCoordSet(graphics::MaterialKey::SCATTERING_MAP)); } break; case graphics::MaterialKey::EMISSIVE_MAP_BIT: // Lightmap takes precendence over emissive map for legacy reasons if (materialKey.isEmissiveMap() && !materialKey.isLightMap()) { auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::EMISSIVE_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setEmissiveMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialEmissiveLightmap, material->getTexCoordSet(graphics::MaterialKey::EMISSIVE_MAP)); } else if (materialKey.isLightMap()) { // We'll set this later when we check the lightmap wasSet = true; } break; case graphics::MaterialKey::LIGHT_MAP_BIT: if (materialKey.isLightMap()) { auto itr = textureMaps.find(graphics::MaterialKey::LIGHT_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::LIGHT_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setLightMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialEmissiveLightmap, material->getTexCoordSet(graphics::MaterialKey::LIGHT_MAP)); } break; case graphics::MaterialKey::SPLAT_MAP_BIT: { auto itr = textureMaps.find(graphics::MaterialKey::SPLAT_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { multiMaterial.setSplatMap(itr->second->getTextureView()._texture); multiMaterial.addSamplerFunc([=]() { material->applySampler(graphics::MaterialKey::SPLAT_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialSplat, material->getTexCoordSet(graphics::MaterialKey::SPLAT_MAP)); } else { forceDefault = true; } break; } case graphics::Material::TEXCOORDTRANSFORM0: if (!fallthrough) { schemas[layerIndex]._texcoordTransforms[0] = material->getTexCoordTransform(0); wasSet = true; } break; case graphics::Material::TEXCOORDTRANSFORM1: if (!fallthrough) { schemas[layerIndex]._texcoordTransforms[1] = material->getTexCoordTransform(1); wasSet = true; } break; case graphics::Material::LIGHTMAP_PARAMS: if (!fallthrough) { schemas[layerIndex]._lightmapParams = material->getLightmapParams(); wasSet = true; } break; case graphics::Material::MATERIAL_PARAMS: if (!fallthrough) { schemas[layerIndex]._materialParams = material->getMaterialParams(); wasSet = true; } break; case graphics::Material::CULL_FACE_MODE: if (!fallthrough) { multiMaterial.setCullFaceMode(material->getCullFaceMode()); wasSet = true; } break; default: break; } } else { switch (flag) { case graphics::MaterialKey::EMISSIVE_VAL_BIT: if (materialKey.isEmissive()) { toonSchemas[layerIndex]._emissive = material->getEmissive(false); schemaKeys[layerIndex].setEmissive(true); wasSet = true; } break; case graphics::MaterialKey::ALBEDO_VAL_BIT: if (materialKey.isAlbedo()) { toonSchemas[layerIndex]._albedo = material->getAlbedo(false); schemaKeys[layerIndex].setAlbedo(true); wasSet = true; } break; case graphics::MaterialKey::OPACITY_VAL_BIT: if (materialKey.isTranslucentFactor()) { toonSchemas[layerIndex]._opacity = material->getOpacity(); schemaKeys[layerIndex].setTranslucentFactor(true); wasSet = true; } break; case graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT: if (materialKey.isOpacityCutoff()) { toonSchemas[layerIndex]._opacityCutoff = material->getOpacityCutoff(); schemaKeys[layerIndex].setOpacityCutoff(true); wasSet = true; } break; case graphics::MaterialKey::ALBEDO_MAP_BIT: if (materialKey.isAlbedoMap()) { auto itr = textureMaps.find(graphics::MaterialKey::ALBEDO_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { material->resetOpacityMap(); drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialAlbedo, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::ALBEDO_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setAlbedoMap(true); schemaKeys[layerIndex].setOpacityMaskMap(material->getKey().isOpacityMaskMap()); schemaKeys[layerIndex].setTranslucentMap(material->getKey().isTranslucentMap()); toonSchemas[layerIndex].setTexCoordSet(gr::Texture::MaterialAlbedo, material->getTexCoordSet(graphics::MaterialKey::ALBEDO_MAP)); } break; case graphics::MaterialKey::NORMAL_MAP_BIT: if (materialKey.isNormalMap()) { auto itr = textureMaps.find(graphics::MaterialKey::NORMAL_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialNormal, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::NORMAL_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setNormalMap(true); toonSchemas[layerIndex].setTexCoordSet(gr::Texture::MaterialNormal, material->getTexCoordSet(graphics::MaterialKey::NORMAL_MAP)); } break; case graphics::MaterialKey::EMISSIVE_MAP_BIT: // Lightmap takes precendence over emissive map for legacy reasons if (materialKey.isEmissiveMap() && !materialKey.isLightMap()) { auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::EMISSIVE_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setEmissiveMap(true); toonSchemas[layerIndex].setTexCoordSet(gr::Texture::MaterialEmissiveLightmap, material->getTexCoordSet(graphics::MaterialKey::EMISSIVE_MAP)); } else if (materialKey.isLightMap()) { // We'll set this later when we check the lightmap wasSet = true; } break; case graphics::MaterialKey::SPLAT_MAP_BIT: {Lines 1–500 of 988. Load more
// // RenderPipelines.cpp // render-utils/src/ // // Created by Zach Pomerantz on 1/28/2016. // Copyright 2016 High Fidelity, Inc. // Copyright 2024 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "RenderPipelines.h" #include <material-networking/TextureCache.h> #include <render/DrawTask.h> #include <graphics/ShaderConstants.h> #include <procedural/ReferenceMaterial.h> #include "render-utils/ShaderConstants.h" #include "DeferredLightingEffect.h" using namespace render; using namespace gpu; namespace gr { using graphics::slot::texture::Texture; using graphics::slot::buffer::Buffer; } bool RenderPipelines::bindMaterial(graphics::MaterialPointer& material, Batch& batch, Args::RenderMode renderMode, bool enableTextures) { graphics::MultiMaterial multiMaterial; multiMaterial.push(graphics::MaterialLayer(material, 0)); return bindMaterials(multiMaterial, batch, renderMode, enableTextures); } void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial) { auto& drawMaterialTextures = multiMaterial.getTextureTables(); multiMaterial.setTexturesLoading(false); multiMaterial.resetReferenceTexturesAndMaterials(); if (!multiMaterial.empty() && multiMaterial.top().material) { multiMaterial.setisMToonAndLayers(multiMaterial.top().material->isMToon(), std::max(1, std::min((int)multiMaterial.size(), (int)multiMaterial.top().material->getLayers()))); } else { multiMaterial.setisMToonAndLayers(false, 1); } multiMaterial.resetOutline(); multiMaterial.resetSamplers(); multiMaterial.setSplatMap(nullptr); // The total list of things we need to look for static std::set<uint> allFlags; static std::once_flag once; std::call_once(once, [] { for (int i = 0; i < graphics::Material::NUM_TOTAL_FLAGS; i++) { // The opacity mask/map are derived from the albedo map // FIXME: OPACITY_MAP_MODE_BIT is supposed to support fallthrough if (i != graphics::MaterialKey::OPACITY_MASK_MAP_BIT && i != graphics::MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT && i != graphics::MaterialKey::OPACITY_MAP_MODE_BIT) { allFlags.insert(i); } } }); graphics::MultiMaterial materials = multiMaterial; std::array<graphics::MultiMaterial::Schema, 3> schemas; std::array<graphics::MultiMaterial::MToonSchema, 3> toonSchemas; std::array<graphics::MaterialKey, 3> schemaKeys; std::array<std::set<uint>, 3> flagsToCheck; flagsToCheck.fill(allFlags); // We only look for splat maps on the first material for (int i = 1; i < 3; i++) { flagsToCheck[i].erase(graphics::MaterialKey::SPLAT_MAP_BIT); } std::array<std::set<uint>, 3> flagsToSetDefault; uint8_t layerIndex = 0; while (!materials.empty()) { auto material = materials.top().material; if (!material) { break; } materials.pop(); if (material->isReference()) { multiMaterial.addReferenceMaterial(std::static_pointer_cast<ReferenceMaterial>(material)->getReferenceOperator()); } bool defaultFallthrough = material->getDefaultFallthrough(); const auto materialKey = material->getKey(); const auto textureMaps = material->getTextureMaps(); auto it = flagsToCheck[layerIndex].begin(); while (it != flagsToCheck[layerIndex].end()) { auto flag = *it; bool fallthrough = defaultFallthrough || material->getPropertyFallthrough(flag); bool wasSet = false; bool forceDefault = false; if (!multiMaterial.isMToon()) { switch (flag) { case graphics::MaterialKey::EMISSIVE_VAL_BIT: if (materialKey.isEmissive()) { schemas[layerIndex]._emissive = material->getEmissive(false); schemaKeys[layerIndex].setEmissive(true); wasSet = true; } break; case graphics::MaterialKey::UNLIT_VAL_BIT: if (materialKey.isUnlit()) { schemaKeys[layerIndex].setUnlit(true); wasSet = true; } break; case graphics::MaterialKey::ALBEDO_VAL_BIT: if (materialKey.isAlbedo()) { schemas[layerIndex]._albedo = material->getAlbedo(false); schemaKeys[layerIndex].setAlbedo(true); wasSet = true; } break; case graphics::MaterialKey::METALLIC_VAL_BIT: if (materialKey.isMetallic()) { schemas[layerIndex]._metallic = material->getMetallic(); schemaKeys[layerIndex].setMetallic(true); wasSet = true; } break; case graphics::MaterialKey::GLOSSY_VAL_BIT: if (materialKey.isRough() || materialKey.isGlossy()) { schemas[layerIndex]._roughness = material->getRoughness(); schemaKeys[layerIndex].setGlossy(materialKey.isGlossy()); wasSet = true; } break; case graphics::MaterialKey::OPACITY_VAL_BIT: if (materialKey.isTranslucentFactor()) { schemas[layerIndex]._opacity = material->getOpacity(); schemaKeys[layerIndex].setTranslucentFactor(true); wasSet = true; } break; case graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT: if (materialKey.isOpacityCutoff()) { schemas[layerIndex]._opacityCutoff = material->getOpacityCutoff(); schemaKeys[layerIndex].setOpacityCutoff(true); wasSet = true; } break; case graphics::MaterialKey::SCATTERING_VAL_BIT: if (materialKey.isScattering()) { schemas[layerIndex]._scattering = material->getScattering(); schemaKeys[layerIndex].setScattering(true); wasSet = true; } break; case graphics::MaterialKey::ALBEDO_MAP_BIT: if (materialKey.isAlbedoMap()) { auto itr = textureMaps.find(graphics::MaterialKey::ALBEDO_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { material->resetOpacityMap(); drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialAlbedo, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::ALBEDO_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setAlbedoMap(true); schemaKeys[layerIndex].setOpacityMaskMap(material->getKey().isOpacityMaskMap()); schemaKeys[layerIndex].setTranslucentMap(material->getKey().isTranslucentMap()); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialAlbedo, material->getTexCoordSet(graphics::MaterialKey::ALBEDO_MAP)); } break; case graphics::MaterialKey::METALLIC_MAP_BIT: if (materialKey.isMetallicMap()) { auto itr = textureMaps.find(graphics::MaterialKey::METALLIC_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialMetallic, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::METALLIC_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setMetallicMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialMetallic, material->getTexCoordSet(graphics::MaterialKey::METALLIC_MAP)); } break; case graphics::MaterialKey::ROUGHNESS_MAP_BIT: if (materialKey.isRoughnessMap()) { auto itr = textureMaps.find(graphics::MaterialKey::ROUGHNESS_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialRoughness, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::ROUGHNESS_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setRoughnessMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialRoughness, material->getTexCoordSet(graphics::MaterialKey::ROUGHNESS_MAP)); } break; case graphics::MaterialKey::NORMAL_MAP_BIT: if (materialKey.isNormalMap()) { auto itr = textureMaps.find(graphics::MaterialKey::NORMAL_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialNormal, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::NORMAL_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setNormalMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialNormal, material->getTexCoordSet(graphics::MaterialKey::NORMAL_MAP)); } break; case graphics::MaterialKey::OCCLUSION_MAP_BIT: if (materialKey.isOcclusionMap()) { auto itr = textureMaps.find(graphics::MaterialKey::OCCLUSION_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialOcclusion, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::OCCLUSION_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setOcclusionMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialOcclusion, material->getTexCoordSet(graphics::MaterialKey::OCCLUSION_MAP)); } break; case graphics::MaterialKey::SCATTERING_MAP_BIT: if (materialKey.isScatteringMap()) { auto itr = textureMaps.find(graphics::MaterialKey::SCATTERING_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialScattering, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::SCATTERING_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setScatteringMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialScattering, material->getTexCoordSet(graphics::MaterialKey::SCATTERING_MAP)); } break; case graphics::MaterialKey::EMISSIVE_MAP_BIT: // Lightmap takes precendence over emissive map for legacy reasons if (materialKey.isEmissiveMap() && !materialKey.isLightMap()) { auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::EMISSIVE_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setEmissiveMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialEmissiveLightmap, material->getTexCoordSet(graphics::MaterialKey::EMISSIVE_MAP)); } else if (materialKey.isLightMap()) { // We'll set this later when we check the lightmap wasSet = true; } break; case graphics::MaterialKey::LIGHT_MAP_BIT: if (materialKey.isLightMap()) { auto itr = textureMaps.find(graphics::MaterialKey::LIGHT_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::LIGHT_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setLightMap(true); schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialEmissiveLightmap, material->getTexCoordSet(graphics::MaterialKey::LIGHT_MAP)); } break; case graphics::MaterialKey::SPLAT_MAP_BIT: { auto itr = textureMaps.find(graphics::MaterialKey::SPLAT_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { multiMaterial.setSplatMap(itr->second->getTextureView()._texture); multiMaterial.addSamplerFunc([=]() { material->applySampler(graphics::MaterialKey::SPLAT_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } schemas[layerIndex].setTexCoordSet(gr::Texture::MaterialSplat, material->getTexCoordSet(graphics::MaterialKey::SPLAT_MAP)); } else { forceDefault = true; } break; } case graphics::Material::TEXCOORDTRANSFORM0: if (!fallthrough) { schemas[layerIndex]._texcoordTransforms[0] = material->getTexCoordTransform(0); wasSet = true; } break; case graphics::Material::TEXCOORDTRANSFORM1: if (!fallthrough) { schemas[layerIndex]._texcoordTransforms[1] = material->getTexCoordTransform(1); wasSet = true; } break; case graphics::Material::LIGHTMAP_PARAMS: if (!fallthrough) { schemas[layerIndex]._lightmapParams = material->getLightmapParams(); wasSet = true; } break; case graphics::Material::MATERIAL_PARAMS: if (!fallthrough) { schemas[layerIndex]._materialParams = material->getMaterialParams(); wasSet = true; } break; case graphics::Material::CULL_FACE_MODE: if (!fallthrough) { multiMaterial.setCullFaceMode(material->getCullFaceMode()); wasSet = true; } break; default: break; } } else { switch (flag) { case graphics::MaterialKey::EMISSIVE_VAL_BIT: if (materialKey.isEmissive()) { toonSchemas[layerIndex]._emissive = material->getEmissive(false); schemaKeys[layerIndex].setEmissive(true); wasSet = true; } break; case graphics::MaterialKey::ALBEDO_VAL_BIT: if (materialKey.isAlbedo()) { toonSchemas[layerIndex]._albedo = material->getAlbedo(false); schemaKeys[layerIndex].setAlbedo(true); wasSet = true; } break; case graphics::MaterialKey::OPACITY_VAL_BIT: if (materialKey.isTranslucentFactor()) { toonSchemas[layerIndex]._opacity = material->getOpacity(); schemaKeys[layerIndex].setTranslucentFactor(true); wasSet = true; } break; case graphics::MaterialKey::OPACITY_CUTOFF_VAL_BIT: if (materialKey.isOpacityCutoff()) { toonSchemas[layerIndex]._opacityCutoff = material->getOpacityCutoff(); schemaKeys[layerIndex].setOpacityCutoff(true); wasSet = true; } break; case graphics::MaterialKey::ALBEDO_MAP_BIT: if (materialKey.isAlbedoMap()) { auto itr = textureMaps.find(graphics::MaterialKey::ALBEDO_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { material->resetOpacityMap(); drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialAlbedo, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::ALBEDO_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setAlbedoMap(true); schemaKeys[layerIndex].setOpacityMaskMap(material->getKey().isOpacityMaskMap()); schemaKeys[layerIndex].setTranslucentMap(material->getKey().isTranslucentMap()); toonSchemas[layerIndex].setTexCoordSet(gr::Texture::MaterialAlbedo, material->getTexCoordSet(graphics::MaterialKey::ALBEDO_MAP)); } break; case graphics::MaterialKey::NORMAL_MAP_BIT: if (materialKey.isNormalMap()) { auto itr = textureMaps.find(graphics::MaterialKey::NORMAL_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialNormal, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::NORMAL_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setNormalMap(true); toonSchemas[layerIndex].setTexCoordSet(gr::Texture::MaterialNormal, material->getTexCoordSet(graphics::MaterialKey::NORMAL_MAP)); } break; case graphics::MaterialKey::EMISSIVE_MAP_BIT: // Lightmap takes precendence over emissive map for legacy reasons if (materialKey.isEmissiveMap() && !materialKey.isLightMap()) { auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP); if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures[layerIndex]->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView()); multiMaterial.addSamplerFunc([=] () { material->applySampler(graphics::MaterialKey::EMISSIVE_MAP); }); if (itr->second->getTextureView().isReference()) { multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); } wasSet = true; } else { multiMaterial.setTexturesLoading(true); forceDefault = true; } } else { forceDefault = true; } schemaKeys[layerIndex].setEmissiveMap(true); toonSchemas[layerIndex].setTexCoordSet(gr::Texture::MaterialEmissiveLightmap, material->getTexCoordSet(graphics::MaterialKey::EMISSIVE_MAP)); } else if (materialKey.isLightMap()) { // We'll set this later when we check the lightmap wasSet = true; } break; case graphics::MaterialKey::SPLAT_MAP_BIT: {