988 lines · 59.8 KB · C++
RawDownload
 ////  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.