498 lines · 21.1 KB · C++
RawDownload
 ////  RenderPipelines.cpp//  render-utils/src/////  Created by Zach Pomerantz on 1/28/2016.//  Copyright 2016 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 "RenderPipelines.h" #include <functional> #include <gpu/Context.h>#include <model-networking/TextureCache.h>#include <render/DrawTask.h>#include <shaders/Shaders.h>#include <graphics/ShaderConstants.h> #include "render-utils/ShaderConstants.h"#include "StencilMaskPass.h"#include "DeferredLightingEffect.h"#include "TextureCache.h" using namespace render;using namespace std::placeholders; namespace ru {    using render_utils::slot::texture::Texture;    using render_utils::slot::buffer::Buffer;} namespace gr {    using graphics::slot::texture::Texture;    using graphics::slot::buffer::Buffer;} void initDeferredPipelines(ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter);void initForwardPipelines(ShapePlumber& plumber);void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); void addPlumberPipeline(ShapePlumber& plumber,        const ShapeKey& key, int programId,        const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter); void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args);static bool forceLightBatchSetter{ false }; void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter) {    using namespace shader::render_utils::program;    using Key = render::ShapeKey;    auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4);    // TODO: Refactor this to use a filter    // Opaques    addPipeline(        Key::Builder().withMaterial(),        model, nullptr, nullptr);    addPipeline(        Key::Builder(),        simple_textured, nullptr, nullptr);    addPipeline(        Key::Builder().withMaterial().withUnlit(),        model_unlit, nullptr, nullptr);    addPipeline(        Key::Builder().withUnlit(),        simple_textured_unlit, nullptr, nullptr);    addPipeline(        Key::Builder().withMaterial().withTangents(),        model_normal_map, nullptr, nullptr);     // Same thing but with Fade on    addPipeline(        Key::Builder().withMaterial().withFade(),        model_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withFade(),        simple_textured_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withMaterial().withUnlit().withFade(),        model_unlit_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withUnlit().withFade(),        simple_textured_unlit_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withMaterial().withTangents().withFade(),        model_normal_map_fade, batchSetter, itemSetter);     // Translucents    addPipeline(        Key::Builder().withMaterial().withTranslucent(),        model_translucent, nullptr, nullptr);    addPipeline(        Key::Builder().withTranslucent(),        simple_transparent_textured, nullptr, nullptr);    addPipeline(        Key::Builder().withMaterial().withTranslucent().withUnlit(),        model_translucent_unlit, nullptr, nullptr);    addPipeline(        Key::Builder().withTranslucent().withUnlit(),        simple_transparent_textured_unlit, nullptr, nullptr);    addPipeline(        Key::Builder().withMaterial().withTranslucent().withTangents(),        model_translucent_normal_map, nullptr, nullptr);    addPipeline(        // FIXME: Ignore lightmap for translucents meshpart        Key::Builder().withMaterial().withTranslucent().withLightmap(),        model_translucent, nullptr, nullptr);    // Same thing but with Fade on    addPipeline(        Key::Builder().withMaterial().withTranslucent().withFade(),        model_translucent_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withTranslucent().withFade(),        simple_transparent_textured_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withMaterial().withTranslucent().withUnlit().withFade(),        model_translucent_unlit_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withTranslucent().withUnlit().withFade(),        simple_transparent_textured_unlit_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withMaterial().withTranslucent().withTangents().withFade(),        model_translucent_normal_map_fade, batchSetter, itemSetter);    addPipeline(        // FIXME: Ignore lightmap for translucents meshpart        Key::Builder().withMaterial().withTranslucent().withLightmap().withFade(),        model_translucent_fade, batchSetter, itemSetter);    // Lightmapped    addPipeline(        Key::Builder().withMaterial().withLightmap(),        model_lightmap, nullptr, nullptr);    addPipeline(        Key::Builder().withMaterial().withLightmap().withTangents(),        model_lightmap_normal_map, nullptr, nullptr);    // Same thing but with Fade on    addPipeline(        Key::Builder().withMaterial().withLightmap().withFade(),        model_lightmap_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withMaterial().withLightmap().withTangents().withFade(),        model_lightmap_normal_map_fade, batchSetter, itemSetter);     // matrix palette skinned    addPipeline(        Key::Builder().withMaterial().withSkinned(),        skin_model, nullptr, nullptr);    addPipeline(        Key::Builder().withMaterial().withSkinned().withTangents(),        skin_model_normal_map, nullptr, nullptr);    // Same thing but with Fade on    addPipeline(        Key::Builder().withMaterial().withSkinned().withFade(),        skin_model_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withMaterial().withSkinned().withTangents().withFade(),        skin_model_normal_map_fade, batchSetter, itemSetter);    // matrix palette skinned and translucent    addPipeline(        Key::Builder().withMaterial().withSkinned().withTranslucent(),        skin_model_translucent, nullptr, nullptr);    addPipeline(        Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(),        skin_model_normal_map_translucent, nullptr, nullptr);    // Same thing but with Fade on    addPipeline(        Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(),        skin_model_translucent_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withFade(),        skin_model_normal_map_translucent_fade, batchSetter, itemSetter);     // dual quaternion skinned    addPipeline(        Key::Builder().withMaterial().withSkinned().withDualQuatSkinned(),        skin_model_dq, nullptr, nullptr);    addPipeline(        Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents(),        skin_model_normal_map_dq, nullptr, nullptr);    // Same thing but with Fade on    addPipeline(        Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withFade(),        skin_model_fade_dq, batchSetter, itemSetter);    addPipeline(        Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTangents().withFade(),        skin_model_normal_map_fade_dq, batchSetter, itemSetter);    // dual quaternion skinned and translucent    addPipeline(        Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent(),        skin_model_translucent_dq, nullptr, nullptr);    addPipeline(        Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents(),        skin_model_normal_map_translucent_dq, nullptr, nullptr);    // Same thing but with Fade on    addPipeline(        Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withFade(),        skin_model_translucent_fade_dq, batchSetter, itemSetter);    addPipeline(        Key::Builder().withMaterial().withSkinned().withDualQuatSkinned().withTranslucent().withTangents().withFade(),        skin_model_normal_map_translucent_fade_dq, batchSetter, itemSetter);     // Depth-only    addPipeline(        Key::Builder().withDepthOnly(),        model_shadow, nullptr, nullptr);    addPipeline(        Key::Builder().withSkinned().withDepthOnly(),        skin_model_shadow, nullptr, nullptr);    // Same thing but with Fade on    addPipeline(        Key::Builder().withDepthOnly().withFade(),        model_shadow_fade, batchSetter, itemSetter);    addPipeline(        Key::Builder().withSkinned().withDepthOnly().withFade(),        skin_model_shadow_fade, batchSetter, itemSetter);     // Now repeat for dual quaternion    // Depth-only    addPipeline(        Key::Builder().withSkinned().withDualQuatSkinned().withDepthOnly(),        skin_model_shadow_dq, nullptr, nullptr);    // Same thing but with Fade on    addPipeline(        Key::Builder().withSkinned().withDualQuatSkinned().withDepthOnly().withFade(),        skin_model_shadow_fade_dq, batchSetter, itemSetter);} void initForwardPipelines(ShapePlumber& plumber) {    using namespace shader::render_utils::program;     using Key = render::ShapeKey;    auto addPipelineBind = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3, _4);     // Disable fade on the forward pipeline, all shaders get added twice, once with the fade key and once without    auto addPipeline = [&](const ShapeKey& key, int programId) {        addPipelineBind(key, programId, nullptr, nullptr);        addPipelineBind(Key::Builder(key).withFade(), programId, nullptr, nullptr);    };     // Forward pipelines need the lightBatchSetter for opaques and transparents    forceLightBatchSetter = true;     // Simple Opaques    addPipeline(Key::Builder(), simple);    addPipeline(Key::Builder().withUnlit(), simpleUnlit);     // Simple Translucents    addPipeline(Key::Builder().withTranslucent(), simpleTranslucent);    addPipeline(Key::Builder().withTranslucent().withUnlit(), simpleTranslucentUnlit);     // Opaques    addPipeline(Key::Builder().withMaterial(), forward_model);    addPipeline(Key::Builder().withMaterial().withUnlit(), forward_model_unlit);    addPipeline(Key::Builder().withMaterial().withTangents(), forward_model_translucent);     // Skinned Opaques    addPipeline(Key::Builder().withMaterial().withSkinned(), forward_skin_model);    addPipeline(Key::Builder().withMaterial().withSkinned().withTangents(), forward_skin_model_normal_map);    addPipeline(Key::Builder().withMaterial().withSkinned().withDualQuatSkinned(), forward_skin_model_dq);    addPipeline(Key::Builder().withMaterial().withSkinned().withTangents().withDualQuatSkinned(), forward_skin_model_normal_map_dq);     // Translucents    addPipeline(Key::Builder().withMaterial().withTranslucent(), forward_model_translucent);    addPipeline(Key::Builder().withMaterial().withTranslucent().withTangents(), forward_model_normal_map_translucent);     // Skinned Translucents    addPipeline(Key::Builder().withMaterial().withSkinned().withTranslucent(), forward_skin_translucent);    addPipeline(Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), forward_skin_translucent_normal_map);    addPipeline(Key::Builder().withMaterial().withSkinned().withTranslucent().withDualQuatSkinned(), forward_skin_translucent_dq);    addPipeline(Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withDualQuatSkinned(), forward_skin_translucent_normal_map_dq);     forceLightBatchSetter = false;} void addPlumberPipeline(ShapePlumber& plumber,        const ShapeKey& key, int programId,        const render::ShapePipeline::BatchSetter& extraBatchSetter, const render::ShapePipeline::ItemSetter& itemSetter) {    // These key-values' pipelines are added by this functor in addition to the key passed    assert(!key.isWireframe());    assert(!key.isDepthBiased());    assert(key.isCullFace());     gpu::ShaderPointer program = gpu::Shader::createProgram(programId);     for (int i = 0; i < 8; i++) {        bool isCulled = (i & 1);        bool isBiased = (i & 2);        bool isWireframed = (i & 4);         auto state = std::make_shared<gpu::State>();        key.isTranslucent() ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state);         // Depth test depends on transparency        state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL);        state->setBlendFunction(key.isTranslucent(),                gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,                gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);         ShapeKey::Builder builder(key);        if (!isCulled) {            builder.withoutCullFace();        }        state->setCullMode(isCulled ? gpu::State::CULL_BACK : gpu::State::CULL_NONE);        if (isWireframed) {            builder.withWireframe();            state->setFillMode(gpu::State::FILL_LINE);        }        if (isBiased) {            builder.withDepthBias();            state->setDepthBias(1.0f);            state->setDepthBiasSlopeScale(1.0f);        }         auto baseBatchSetter = (forceLightBatchSetter || key.isTranslucent()) ? &lightBatchSetter : &batchSetter;        render::ShapePipeline::BatchSetter finalBatchSetter;        if (extraBatchSetter) {            finalBatchSetter = [baseBatchSetter, extraBatchSetter](const ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) {                baseBatchSetter(pipeline, batch, args);                extraBatchSetter(pipeline, batch, args);            };        }        else {            finalBatchSetter = baseBatchSetter;        }        plumber.addPipeline(builder.build(), program, state, finalBatchSetter, itemSetter);    }} void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args) {    // Set a default albedo map    batch.setResourceTexture(gr::Texture::MaterialAlbedo,        DependencyManager::get<TextureCache>()->getWhiteTexture());     // Set a default material    if (pipeline.locations->materialBufferUnit) {        // Create a default schema        static bool isMaterialSet = false;        static graphics::Material material;        if (!isMaterialSet) {            material.setAlbedo(vec3(1.0f));            material.setOpacity(1.0f);            material.setMetallic(0.1f);            material.setRoughness(0.9f);            isMaterialSet = true;        }         // Set a default schema        batch.setUniformBuffer(gr::Buffer::Material, material.getSchemaBuffer());    }} void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args) {    // Set the batch    batchSetter(pipeline, batch, args);     // Set the light    if (pipeline.locations->keyLightBufferUnit) {        DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch);    }} void initZPassPipelines(ShapePlumber& shapePlumber, gpu::StatePointer state) {    using namespace shader::render_utils::program;    gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(model_shadow);    shapePlumber.addPipeline(        ShapeKey::Filter::Builder().withoutSkinned().withoutFade(),        modelProgram, state);     gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skin_model_shadow);    shapePlumber.addPipeline(        ShapeKey::Filter::Builder().withSkinned().withoutDualQuatSkinned().withoutFade(),        skinProgram, state);     gpu::ShaderPointer modelFadeProgram = gpu::Shader::createProgram(model_shadow_fade);    shapePlumber.addPipeline(        ShapeKey::Filter::Builder().withoutSkinned().withFade(),        modelFadeProgram, state);     gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skin_model_shadow_fade);    shapePlumber.addPipeline(        ShapeKey::Filter::Builder().withSkinned().withoutDualQuatSkinned().withFade(),        skinFadeProgram, state);     gpu::ShaderPointer skinModelShadowDualQuatProgram = gpu::Shader::createProgram(skin_model_shadow_dq);    shapePlumber.addPipeline(        ShapeKey::Filter::Builder().withSkinned().withDualQuatSkinned().withoutFade(),        skinModelShadowDualQuatProgram, state);     gpu::ShaderPointer skinModelShadowFadeDualQuatProgram = gpu::Shader::createProgram(skin_model_shadow_fade_dq);    shapePlumber.addPipeline(        ShapeKey::Filter::Builder().withSkinned().withDualQuatSkinned().withFade(),        skinModelShadowFadeDualQuatProgram, state);} // FIXME find a better way to setup the default texturesvoid RenderPipelines::bindMaterial(const graphics::MaterialPointer& material, gpu::Batch& batch, bool enableTextures) {    if (!material) {        return;    }     auto textureCache = DependencyManager::get<TextureCache>();     batch.setUniformBuffer(gr::Buffer::Material, material->getSchemaBuffer());    batch.setUniformBuffer(gr::Buffer::TexMapArray, material->getTexMapArrayBuffer());     const auto& materialKey = material->getKey();    const auto& textureMaps = material->getTextureMaps();     int numUnlit = 0;    if (materialKey.isUnlit()) {        numUnlit++;    }     const auto& drawMaterialTextures = material->getTextureTable();     // Albedo    if (materialKey.isAlbedoMap()) {        auto itr = textureMaps.find(graphics::MaterialKey::ALBEDO_MAP);        if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {            drawMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, itr->second->getTextureView());        } else {            drawMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, textureCache->getWhiteTexture());        }    }     // Roughness map    if (materialKey.isRoughnessMap()) {        auto itr = textureMaps.find(graphics::MaterialKey::ROUGHNESS_MAP);        if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {            drawMaterialTextures->setTexture(gr::Texture::MaterialRoughness, itr->second->getTextureView());        } else {            drawMaterialTextures->setTexture(gr::Texture::MaterialRoughness, textureCache->getWhiteTexture());        }    }     // Normal map    if (materialKey.isNormalMap()) {        auto itr = textureMaps.find(graphics::MaterialKey::NORMAL_MAP);        if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {            drawMaterialTextures->setTexture(gr::Texture::MaterialNormal, itr->second->getTextureView());        } else {            drawMaterialTextures->setTexture(gr::Texture::MaterialNormal, textureCache->getBlueTexture());        }    }     // Metallic map    if (materialKey.isMetallicMap()) {        auto itr = textureMaps.find(graphics::MaterialKey::METALLIC_MAP);        if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {            drawMaterialTextures->setTexture(gr::Texture::MaterialMetallic, itr->second->getTextureView());        } else {            drawMaterialTextures->setTexture(gr::Texture::MaterialMetallic, textureCache->getBlackTexture());        }    }     // Occlusion map    if (materialKey.isOcclusionMap()) {        auto itr = textureMaps.find(graphics::MaterialKey::OCCLUSION_MAP);        if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {            drawMaterialTextures->setTexture(gr::Texture::MaterialOcclusion, itr->second->getTextureView());        } else {            drawMaterialTextures->setTexture(gr::Texture::MaterialOcclusion, textureCache->getWhiteTexture());        }    }     // Scattering map    if (materialKey.isScatteringMap()) {        auto itr = textureMaps.find(graphics::MaterialKey::SCATTERING_MAP);        if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {            drawMaterialTextures->setTexture(gr::Texture::MaterialScattering, itr->second->getTextureView());        } else {            drawMaterialTextures->setTexture(gr::Texture::MaterialScattering, textureCache->getWhiteTexture());        }    }     // Emissive / Lightmap    if (materialKey.isLightmapMap()) {        auto itr = textureMaps.find(graphics::MaterialKey::LIGHTMAP_MAP);         if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {            drawMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView());        } else {            drawMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getGrayTexture());        }    } else if (materialKey.isEmissiveMap()) {        auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP);        if (enableTextures && itr != textureMaps.end() && itr->second->isDefined()) {            drawMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView());        } else {            drawMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getBlackTexture());        }    }     batch.setResourceTextureTable(material->getTextureTable());}