mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 01:24:05 +02:00
Adding state sorting for free
This commit is contained in:
parent
d2cb017a04
commit
0531f90675
5 changed files with 107 additions and 4 deletions
libraries
render-utils/src
render/src/render
|
@ -246,8 +246,8 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
|
|||
|
||||
// Texcoord transforms ?
|
||||
if (locations->texcoordMatrices >= 0) {
|
||||
//batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*)&texcoordTransform);
|
||||
batch._glUniformMatrix4fv(locations->texcoordMatrices, (materialKey.isLightmapMap() ? 2 : 1), false, (const float*)&texcoordTransform);
|
||||
batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*)&texcoordTransform);
|
||||
// batch._glUniformMatrix4fv(locations->texcoordMatrices, (materialKey.isLightmapMap() ? 2 : 1), false, (const float*)&texcoordTransform);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
|
|||
addJob<PrepareDeferred>("PrepareDeferred");
|
||||
|
||||
// Render opaque objects in DeferredBuffer
|
||||
addJob<DrawDeferred>("DrawOpaqueDeferred", opaques, shapePlumber);
|
||||
addJob<DrawStateSortDeferred>("DrawOpaqueDeferred", opaques, shapePlumber);
|
||||
|
||||
// Once opaque is all rendered create stencil background
|
||||
addJob<DrawStencilDeferred>("DrawOpaqueStencil");
|
||||
|
@ -170,7 +170,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
|
|||
for (auto job : _jobs) {
|
||||
job.run(sceneContext, renderContext);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
|
||||
assert(renderContext->args);
|
||||
|
@ -200,6 +200,39 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
|
|||
config->setNumDrawn((int)inItems.size());
|
||||
}
|
||||
|
||||
|
||||
void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
if (_stateSort) {
|
||||
renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn);
|
||||
} else {
|
||||
renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn);
|
||||
}
|
||||
args->_batch = nullptr;
|
||||
});
|
||||
|
||||
config->setNumDrawn((int)inItems.size());
|
||||
}
|
||||
|
||||
DrawOverlay3D::DrawOverlay3D(bool opaque) :
|
||||
_shapePlumber(std::make_shared<ShapePlumber>()),
|
||||
_opaquePass(opaque) {
|
||||
|
|
|
@ -41,6 +41,7 @@ class DrawConfig : public render::Job::Config {
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged)
|
||||
Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
|
||||
Q_PROPERTY(bool stateSort MEMBER stateSort NOTIFY dirty)
|
||||
|
||||
public:
|
||||
|
||||
|
@ -48,6 +49,7 @@ public:
|
|||
void setNumDrawn(int num) { _numDrawn = num; emit numDrawnChanged(); }
|
||||
|
||||
int maxDrawn{ -1 };
|
||||
bool stateSort{ true };
|
||||
|
||||
signals:
|
||||
void numDrawnChanged();
|
||||
|
@ -72,6 +74,22 @@ protected:
|
|||
int _maxDrawn; // initialized by Config
|
||||
};
|
||||
|
||||
class DrawStateSortDeferred {
|
||||
public:
|
||||
using Config = DrawConfig;
|
||||
using JobModel = render::Job::ModelI<DrawStateSortDeferred, render::ItemBounds, Config>;
|
||||
|
||||
DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
|
||||
|
||||
void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; }
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemBounds& inItems);
|
||||
|
||||
protected:
|
||||
render::ShapePlumberPointer _shapePlumber;
|
||||
int _maxDrawn; // initialized by Config
|
||||
bool _stateSort;
|
||||
};
|
||||
|
||||
class DrawStencilDeferred {
|
||||
public:
|
||||
using JobModel = render::Job::Model<DrawStencilDeferred>;
|
||||
|
|
|
@ -65,6 +65,57 @@ void render::renderShapes(const SceneContextPointer& sceneContext, const RenderC
|
|||
}
|
||||
}
|
||||
|
||||
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: invalid key ?" << key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// THen render
|
||||
for (auto& pipelineKey : sortedPipelines) {
|
||||
auto& bucket = sortedShapes[pipelineKey];
|
||||
args->_pipeline = shapeContext->pickPipeline(args, pipelineKey);
|
||||
for (auto& item : bucket) {
|
||||
item.render(args);
|
||||
}
|
||||
}
|
||||
args->_pipeline = nullptr;
|
||||
for (auto& item : ownPipelineBucket) {
|
||||
item.render(args);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace render {
|
|||
|
||||
void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, int maxDrawnItems = -1);
|
||||
void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1);
|
||||
void renderStateSortShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1);
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue