static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key, gpu::Batch& batch) {
    if (!polylinePipeline) {
        gpu::ShaderPointer program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke);
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
        auto fadeVS = gpu::Shader::createVertex(std::string(paintStroke_fade_vert));
        auto fadePS = gpu::Shader::createPixel(std::string(paintStroke_fade_frag));
        gpu::ShaderPointer fadeProgram = gpu::Shader::createProgram(fadeVS, fadePS);
#endif
        gpu::StatePointer state = gpu::StatePointer(new gpu::State());
        state->setDepthTest(true, true, gpu::LESS_EQUAL);
        PrepareStencil::testMask(*state);
        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);
        polylinePipeline = gpu::Pipeline::create(program, state);
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
        _fadePipeline = gpu::Pipeline::create(fadeProgram, state);
#endif
    }

#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
    if (key.isFaded()) {
        auto fadeEffect = DependencyManager::get<FadeEffect>();
        return std::make_shared<render::ShapePipeline>(_fadePipeline, nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
    } else {
#endif
        return std::make_shared<render::ShapePipeline>(polylinePipeline, nullptr, nullptr, nullptr);
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
    }
#endif
}
static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key, gpu::Batch& batch) {
    if (!polylinePipeline) {
        auto VS = paintStroke_vert::getShader();
        auto PS = paintStroke_frag::getShader();
        gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS);
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
        auto fadeVS = gpu::Shader::createVertex(std::string(paintStroke_fade_vert));
        auto fadePS = gpu::Shader::createPixel(std::string(paintStroke_fade_frag));
        gpu::ShaderPointer fadeProgram = gpu::Shader::createProgram(fadeVS, fadePS);
#endif
        batch.runLambda([program
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
            , fadeProgram
#endif
        ] {
            gpu::Shader::BindingSet slotBindings;
            slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), PAINTSTROKE_TEXTURE_SLOT));
            slotBindings.insert(gpu::Shader::Binding(std::string("polyLineBuffer"), PAINTSTROKE_UNIFORM_SLOT));
            gpu::Shader::makeProgram(*program, slotBindings);
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
            slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), PAINTSTROKE_TEXTURE_SLOT + 1));
            slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), PAINTSTROKE_UNIFORM_SLOT + 1));
            gpu::Shader::makeProgram(*fadeProgram, slotBindings);
#endif
        });
        gpu::StatePointer state = gpu::StatePointer(new gpu::State());
        state->setDepthTest(true, true, gpu::LESS_EQUAL);
        PrepareStencil::testMask(*state);
        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);
        polylinePipeline = gpu::Pipeline::create(program, state);
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
        _fadePipeline = gpu::Pipeline::create(fadeProgram, state);
#endif
    }

#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
    if (key.isFaded()) {
        auto fadeEffect = DependencyManager::get<FadeEffect>();
        return std::make_shared<render::ShapePipeline>(_fadePipeline, nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
    } else {
#endif
        return std::make_shared<render::ShapePipeline>(polylinePipeline, nullptr, nullptr, nullptr);
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
    }
#endif
}