Пример #1
0
void render::renderStateSortShapes(const RenderContextPointer& renderContext,
    const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems, const ShapeKey& globalKey) {
    auto& scene = renderContext->_scene;
    RenderArgs* args = renderContext->args;

    int numItemsToDraw = (int)inItems.size();
    if (maxDrawnItems != -1) {
        numItemsToDraw = glm::min(numItemsToDraw, maxDrawnItems);
    }

    using SortedPipelines = std::vector<render::ShapeKey>;
    using SortedShapes = std::unordered_map<render::ShapeKey, std::vector<Item>, render::ShapeKey::Hash, render::ShapeKey::KeyEqual>;
    SortedPipelines sortedPipelines;
    SortedShapes sortedShapes;
    std::vector< std::tuple<Item,ShapeKey> > ownPipelineBucket;

    for (auto i = 0; i < numItemsToDraw; ++i) {
        auto& item = scene->getItem(inItems[i].id);

        {
            assert(item.getKey().isShape());
            auto key = item.getShapeKey() | globalKey;
            if (key.isValid() && !key.hasOwnPipeline()) {
                auto& bucket = sortedShapes[key];
                if (bucket.empty()) {
                    sortedPipelines.push_back(key);
                }
                bucket.push_back(item);
            } else if (key.hasOwnPipeline()) {
                ownPipelineBucket.push_back( std::make_tuple(item, key) );
            } else {
                std::call_once(messageIDFlag, [](int* id) { *id = LogHandler::getInstance().newRepeatedMessageID(); },
                    &repeatedInvalidKeyMessageID);
                HIFI_FCDEBUG_ID(renderlogging(), repeatedInvalidKeyMessageID, "Item could not be rendered with invalid key" << key);
            }
        }
    }

    // Then render
    for (auto& pipelineKey : sortedPipelines) {
        auto& bucket = sortedShapes[pipelineKey];
        args->_shapePipeline = shapeContext->pickPipeline(args, pipelineKey);
        if (!args->_shapePipeline) {
            continue;
        }
        args->_itemShapeKey = pipelineKey._flags.to_ulong();
        for (auto& item : bucket) {
            args->_shapePipeline->prepareShapeItem(args, pipelineKey, item);
            item.render(args);
        }
    }
    args->_shapePipeline = nullptr;
    for (auto& itemAndKey : ownPipelineBucket) {
        auto& item = std::get<0>(itemAndKey);
        args->_itemShapeKey = std::get<1>(itemAndKey)._flags.to_ulong();
        item.render(args);
    }
    args->_itemShapeKey = 0;
}
Пример #2
0
RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) {
    cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; };

    // Prepare the ShapePipeline
    ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
    {
        auto state = std::make_shared<gpu::State>();
        state->setCullMode(gpu::State::CULL_BACK);
        state->setDepthTest(true, true, gpu::LESS_EQUAL);

        auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert));
        auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag));
        gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel);
        shapePlumber->addPipeline(
            ShapeKey::Filter::Builder().withoutSkinned(),
            modelProgram, state);

        auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert));
        auto skinPixel = gpu::Shader::createPixel(std::string(skin_model_shadow_frag));
        gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, skinPixel);
        shapePlumber->addPipeline(
            ShapeKey::Filter::Builder().withSkinned(),
            skinProgram, state);
    }

    const auto cachedMode = addJob<RenderShadowSetup>("Setup");

    // CPU jobs:
    // Fetch and cull the items from the scene
    auto shadowFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered();
    const auto shadowSelection = addJob<FetchSpatialTree>("FetchShadowSelection", shadowFilter);
    const auto culledShadowSelection = addJob<CullSpatialSelection>("CullShadowSelection", shadowSelection, cullFunctor, RenderDetails::SHADOW, shadowFilter);

    // Sort
    const auto sortedPipelines = addJob<PipelineSortShapes>("PipelineSortShadowSort", culledShadowSelection);
    const auto sortedShapes = addJob<DepthSortShapes>("DepthSortShadowMap", sortedPipelines);

    // GPU jobs: Render to shadow map
    addJob<RenderShadowMap>("RenderShadowMap", sortedShapes, shapePlumber);

    addJob<RenderShadowTeardown>("Teardown", cachedMode);
}
Пример #3
0
void render::renderStateSortShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext,
    const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems) {
    auto& scene = sceneContext->_scene;
    RenderArgs* args = renderContext->args;

    int numItemsToDraw = (int)inItems.size();
    if (maxDrawnItems != -1) {
        numItemsToDraw = glm::min(numItemsToDraw, maxDrawnItems);
    }

    using SortedPipelines = std::vector<render::ShapeKey>;
    using SortedShapes = std::unordered_map<render::ShapeKey, std::vector<Item>, render::ShapeKey::Hash, render::ShapeKey::KeyEqual>;
    SortedPipelines sortedPipelines;
    SortedShapes sortedShapes;
    std::vector<Item> ownPipelineBucket;

    for (auto i = 0; i < numItemsToDraw; ++i) {
        auto item = scene->getItem(inItems[i].id);

        {
            assert(item.getKey().isShape());
            const auto& key = item.getShapeKey();
            if (key.isValid() && !key.hasOwnPipeline()) {
                auto& bucket = sortedShapes[key];
                if (bucket.empty()) {
                    sortedPipelines.push_back(key);
                }
                bucket.push_back(item);
            } else if (key.hasOwnPipeline()) {
                ownPipelineBucket.push_back(item);
            } else {
                qDebug() << "Item could not be rendered with invalid key" << key;
            }
        }
    }

    // Then render
    for (auto& pipelineKey : sortedPipelines) {
        auto& bucket = sortedShapes[pipelineKey];
        args->_pipeline = shapeContext->pickPipeline(args, pipelineKey);
        if (!args->_pipeline) {
            continue;
        }
        for (auto& item : bucket) {
            item.render(args);
        }
    }
    args->_pipeline = nullptr;
    for (auto& item : ownPipelineBucket) {
        item.render(args);
    }
}
Пример #4
0
void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, const Item& item) {
    assert(item.getKey().isShape());
    const auto& key = item.getShapeKey();
    if (key.isValid() && !key.hasOwnPipeline()) {
        args->_pipeline = shapeContext->pickPipeline(args, key);
        if (args->_pipeline) {
            item.render(args);
        }
        args->_pipeline = nullptr;
    } else if (key.hasOwnPipeline()) {
        item.render(args);
    } else {
        qDebug() << "Item could not be rendered with invalid key" << key;
    }
}
Пример #5
0
void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, const Item& item, const ShapeKey& globalKey) {
    assert(item.getKey().isShape());
    auto key = item.getShapeKey() | globalKey;
    args->_itemShapeKey = key._flags.to_ulong();
    if (key.isValid() && !key.hasOwnPipeline()) {
        args->_shapePipeline = shapeContext->pickPipeline(args, key);
        if (args->_shapePipeline) {
            args->_shapePipeline->prepareShapeItem(args, key, item);
            item.render(args);
        }
        args->_shapePipeline = nullptr;
    } else if (key.hasOwnPipeline()) {
        item.render(args);
    } else {
        std::call_once(messageIDFlag, [](int* id) { *id = LogHandler::getInstance().newRepeatedMessageID(); },
                           &repeatedInvalidKeyMessageID);
        HIFI_FCDEBUG_ID(renderlogging(), repeatedInvalidKeyMessageID, "Item could not be rendered with invalid key" << key);
    }
    args->_itemShapeKey = 0;
}