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; }
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); }
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); } }
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; } }
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; }