300 lines · 12.6 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 <gpu/Context.h>#include <gpu/StandardShaderLib.h> #include "DeferredLightingEffect.h"#include "TextureCache.h"#include "render/DrawTask.h" #include "model_vert.h"#include "model_shadow_vert.h"#include "model_normal_map_vert.h"#include "model_lightmap_vert.h"#include "model_lightmap_normal_map_vert.h"#include "skin_model_vert.h"#include "skin_model_shadow_vert.h"#include "skin_model_normal_map_vert.h" #include "model_frag.h"#include "model_unlit_frag.h"#include "model_shadow_frag.h"#include "model_normal_map_frag.h"#include "model_normal_specular_map_frag.h"#include "model_specular_map_frag.h"#include "model_lightmap_frag.h"#include "model_lightmap_normal_map_frag.h"#include "model_lightmap_normal_specular_map_frag.h"#include "model_lightmap_specular_map_frag.h"#include "model_translucent_frag.h"#include "model_translucent_unlit_frag.h" #include "overlay3D_vert.h"#include "overlay3D_frag.h"#include "overlay3D_translucent_frag.h"#include "overlay3D_unlit_frag.h"#include "overlay3D_translucent_unlit_frag.h" #include "drawOpaqueStencil_frag.h" using namespace render; void initStencilPipeline(gpu::PipelinePointer& pipeline) {    const gpu::int8 STENCIL_OPAQUE = 1;    auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();    auto ps = gpu::Shader::createPixel(std::string(drawOpaqueStencil_frag));    auto program = gpu::Shader::createProgram(vs, ps);    gpu::Shader::makeProgram((*program));     auto state = std::make_shared<gpu::State>();    state->setDepthTest(true, false, gpu::LESS_EQUAL);    state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_REPLACE));    state->setColorWriteMask(0);     pipeline = gpu::Pipeline::create(program, state);} gpu::BufferView getDefaultMaterialBuffer() {    model::Material::Schema schema;    schema._albedo = vec3(1.0f);    schema._opacity = 1.0f;    schema._metallic = 0.1f;    schema._roughness = 0.9f;    return gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(model::Material::Schema), (const gpu::Byte*) &schema));} void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {    // Set a default albedo map    batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,        DependencyManager::get<TextureCache>()->getWhiteTexture());    // Set a default normal map    batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING,        DependencyManager::get<TextureCache>()->getNormalFittingTexture());     // Set a default material    if (pipeline.locations->materialBufferUnit >= 0) {        static const gpu::BufferView OPAQUE_SCHEMA_BUFFER = getDefaultMaterialBuffer();        batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::MATERIAL, OPAQUE_SCHEMA_BUFFER);    }} void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {    batchSetter(pipeline, batch);    // Set the light    if (pipeline.locations->lightBufferUnit >= 0) {        DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(batch,            pipeline.locations->lightBufferUnit,            pipeline.locations->lightAmbientMapUnit);    }} void initOverlay3DPipelines(ShapePlumber& plumber) {    auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert));    auto pixel = gpu::Shader::createPixel(std::string(overlay3D_frag));    auto pixelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_translucent_frag));    auto pixelUnlit = gpu::Shader::createPixel(std::string(overlay3D_unlit_frag));    auto pixelTranslucentUnlit = gpu::Shader::createPixel(std::string(overlay3D_translucent_unlit_frag));     auto opaqueProgram = gpu::Shader::createProgram(vertex, pixel);    auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent);    auto unlitOpaqueProgram = gpu::Shader::createProgram(vertex, pixelUnlit);    auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit);     for (int i = 0; i < 8; i++) {        bool isCulled = (i & 1);        bool isBiased = (i & 2);        bool isOpaque = (i & 4);         auto state = std::make_shared<gpu::State>();        state->setDepthTest(false);        state->setCullMode(isCulled ? gpu::State::CULL_BACK : gpu::State::CULL_NONE);        if (isBiased) {            state->setDepthBias(1.0f);            state->setDepthBiasSlopeScale(1.0f);        }        if (isOpaque) {            // Soft edges            state->setBlendFunction(true,                gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);        } else {            state->setBlendFunction(true,                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::Filter::Builder builder;        isCulled ? builder.withCullFace() : builder.withoutCullFace();        isBiased ? builder.withDepthBias() : builder.withoutDepthBias();        isOpaque ? builder.withOpaque() : builder.withTranslucent();         auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram;        auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram;        plumber.addPipeline(builder.withoutUnlit().build(), simpleProgram, state, &lightBatchSetter);        plumber.addPipeline(builder.withUnlit().build(), unlitProgram, state, &batchSetter);    }} void initDeferredPipelines(render::ShapePlumber& plumber) {    using Key = render::ShapeKey;    using ShaderPointer = gpu::ShaderPointer;     auto addPipeline = [&plumber](const Key& key, const ShaderPointer& vertexShader, const ShaderPointer& pixelShader) {        // These keyvalues' pipelines will be added by this lamdba in addition to the key passed        assert(!key.isWireFrame());        assert(!key.isDepthBiased());        assert(key.isCullFace());         ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader);         for (int i = 0; i < 8; i++) {            bool isCulled = (i & 1);            bool isBiased = (i & 2);            bool isWireframed = (i & 4);             ShapeKey::Builder builder(key);            auto state = std::make_shared<gpu::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);             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);            }             plumber.addPipeline(builder.build(), program, state,                key.isTranslucent() ? &lightBatchSetter : &batchSetter);        }    };     // Vertex shaders    auto modelVertex = gpu::Shader::createVertex(std::string(model_vert));    auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert));    auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert));    auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert));    auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert));    auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert));    auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert));    auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert));     // Pixel shaders    auto modelPixel = gpu::Shader::createPixel(std::string(model_frag));    auto modelUnlitPixel = gpu::Shader::createPixel(std::string(model_unlit_frag));    auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag));    auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag));    auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag));    auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag));    auto modelTranslucentUnlitPixel = gpu::Shader::createPixel(std::string(model_translucent_unlit_frag));    auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag));    auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag));    auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag));    auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag));    auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag));     // TODO: Refactor this to use a filter    // Opaques    addPipeline(        Key::Builder(),        modelVertex, modelPixel);    addPipeline(        Key::Builder().withUnlit(),        modelVertex, modelUnlitPixel);    addPipeline(        Key::Builder().withTangents(),        modelNormalMapVertex, modelNormalMapPixel);    addPipeline(        Key::Builder().withSpecular(),        modelVertex, modelSpecularMapPixel);    addPipeline(        Key::Builder().withTangents().withSpecular(),        modelNormalMapVertex, modelNormalSpecularMapPixel);    // Translucents    addPipeline(        Key::Builder().withTranslucent(),        modelVertex, modelTranslucentPixel);    addPipeline(        Key::Builder().withTranslucent().withUnlit(),        modelVertex, modelTranslucentUnlitPixel);    addPipeline(        Key::Builder().withTranslucent().withTangents(),        modelNormalMapVertex, modelTranslucentPixel);    addPipeline(        Key::Builder().withTranslucent().withSpecular(),        modelVertex, modelTranslucentPixel);    addPipeline(        Key::Builder().withTranslucent().withTangents().withSpecular(),        modelNormalMapVertex, modelTranslucentPixel);    addPipeline(        // FIXME: Ignore lightmap for translucents meshpart        Key::Builder().withTranslucent().withLightmap(),        modelVertex, modelTranslucentPixel);    // Lightmapped    addPipeline(        Key::Builder().withLightmap(),        modelLightmapVertex, modelLightmapPixel);    addPipeline(        Key::Builder().withLightmap().withTangents(),        modelLightmapNormalMapVertex, modelLightmapNormalMapPixel);    addPipeline(        Key::Builder().withLightmap().withSpecular(),        modelLightmapVertex, modelLightmapSpecularMapPixel);    addPipeline(        Key::Builder().withLightmap().withTangents().withSpecular(),        modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel);    // Skinned    addPipeline(        Key::Builder().withSkinned(),        skinModelVertex, modelPixel);    addPipeline(        Key::Builder().withSkinned().withTangents(),        skinModelNormalMapVertex, modelNormalMapPixel);    addPipeline(        Key::Builder().withSkinned().withSpecular(),        skinModelVertex, modelSpecularMapPixel);    addPipeline(        Key::Builder().withSkinned().withTangents().withSpecular(),        skinModelNormalMapVertex, modelNormalSpecularMapPixel);    // Skinned and Translucent    addPipeline(        Key::Builder().withSkinned().withTranslucent(),        skinModelVertex, modelTranslucentPixel);    addPipeline(        Key::Builder().withSkinned().withTranslucent().withTangents(),        skinModelNormalMapVertex, modelTranslucentPixel);    addPipeline(        Key::Builder().withSkinned().withTranslucent().withSpecular(),        skinModelVertex, modelTranslucentPixel);    addPipeline(        Key::Builder().withSkinned().withTranslucent().withTangents().withSpecular(),        skinModelNormalMapVertex, modelTranslucentPixel);    // Depth-only    addPipeline(        Key::Builder().withDepthOnly(),        modelShadowVertex, modelShadowPixel);    addPipeline(        Key::Builder().withSkinned().withDepthOnly(),        skinModelShadowVertex, modelShadowPixel); }