Groundcover optimisation (#3101)

* groundcover.cpp share state

* groundcover.hpp share state
pull/3108/head
Bo Svensson 3 years ago committed by GitHub
parent 0ab8a7ddd7
commit b6f572578e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,6 +1,7 @@
#include "groundcover.hpp" #include "groundcover.hpp"
#include <osg/AlphaFunc> #include <osg/AlphaFunc>
#include <osg/BlendFunc>
#include <osg/Geometry> #include <osg/Geometry>
#include <osg/VertexAttribDivisor> #include <osg/VertexAttribDivisor>
@ -66,18 +67,6 @@ namespace MWRender
{ {
} }
void apply(osg::Node& node) override
{
osg::ref_ptr<osg::StateSet> ss = node.getStateSet();
if (ss != nullptr)
{
ss->removeAttribute(osg::StateAttribute::MATERIAL);
removeAlpha(ss);
}
traverse(node);
}
void apply(osg::Geometry& geom) override void apply(osg::Geometry& geom) override
{ {
for (unsigned int i = 0; i < geom.getNumPrimitiveSets(); ++i) for (unsigned int i = 0; i < geom.getNumPrimitiveSets(); ++i)
@ -110,32 +99,14 @@ namespace MWRender
// Display lists do not support instancing in OSG 3.4 // Display lists do not support instancing in OSG 3.4
geom.setUseDisplayList(false); geom.setUseDisplayList(false);
geom.setUseVertexBufferObjects(true);
geom.setVertexAttribArray(6, transforms.get(), osg::Array::BIND_PER_VERTEX); geom.setVertexAttribArray(6, transforms.get(), osg::Array::BIND_PER_VERTEX);
geom.setVertexAttribArray(7, rotations.get(), osg::Array::BIND_PER_VERTEX); geom.setVertexAttribArray(7, rotations.get(), osg::Array::BIND_PER_VERTEX);
osg::ref_ptr<osg::StateSet> ss = geom.getOrCreateStateSet();
ss->setAttribute(new osg::VertexAttribDivisor(6, 1));
ss->setAttribute(new osg::VertexAttribDivisor(7, 1));
ss->removeAttribute(osg::StateAttribute::MATERIAL);
removeAlpha(ss);
traverse(geom);
} }
private: private:
std::vector<Groundcover::GroundcoverEntry> mInstances; std::vector<Groundcover::GroundcoverEntry> mInstances;
osg::Vec3f mChunkPosition; osg::Vec3f mChunkPosition;
void removeAlpha(osg::StateSet* stateset)
{
// MGE uses default alpha settings for groundcover, so we can not rely on alpha properties
stateset->removeAttribute(osg::StateAttribute::ALPHAFUNC);
stateset->removeMode(GL_ALPHA_TEST);
stateset->removeAttribute(osg::StateAttribute::BLENDFUNC);
stateset->removeMode(GL_BLEND);
stateset->setRenderBinToInherit();
}
}; };
class DensityCalculator class DensityCalculator
@ -199,7 +170,16 @@ namespace MWRender
: GenericResourceManager<GroundcoverChunkId>(nullptr) : GenericResourceManager<GroundcoverChunkId>(nullptr)
, mSceneManager(sceneManager) , mSceneManager(sceneManager)
, mDensity(density) , mDensity(density)
, mStateset(new osg::StateSet)
{ {
// MGE uses default alpha settings for groundcover, so we can not rely on alpha properties
// Force a unified alpha handling instead of data from meshes
osg::ref_ptr<osg::AlphaFunc> alpha = new osg::AlphaFunc(osg::AlphaFunc::GEQUAL, 128.f / 255.f);
mStateset->setAttributeAndModes(alpha.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
mStateset->setAttributeAndModes(new osg::BlendFunc, osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE);
mStateset->setRenderBinDetails(0, "RenderBin", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
mStateset->setAttribute(new osg::VertexAttribDivisor(6, 1));
mStateset->setAttribute(new osg::VertexAttribDivisor(7, 1));
} }
void Groundcover::collectInstances(InstanceMap& instances, float size, const osg::Vec2f& center) void Groundcover::collectInstances(InstanceMap& instances, float size, const osg::Vec2f& center)
@ -255,27 +235,23 @@ namespace MWRender
for (auto& pair : instances) for (auto& pair : instances)
{ {
const osg::Node* temp = mSceneManager->getTemplate(pair.first); const osg::Node* temp = mSceneManager->getTemplate(pair.first);
osg::ref_ptr<osg::Node> node = static_cast<osg::Node*>(temp->clone(osg::CopyOp::DEEP_COPY_ALL&(~osg::CopyOp::DEEP_COPY_TEXTURES))); osg::ref_ptr<osg::Node> node = static_cast<osg::Node*>(temp->clone(osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES|osg::CopyOp::DEEP_COPY_USERDATA|osg::CopyOp::DEEP_COPY_ARRAYS|osg::CopyOp::DEEP_COPY_PRIMITIVES));
// Keep link to original mesh to keep it in cache // Keep link to original mesh to keep it in cache
group->getOrCreateUserDataContainer()->addUserObject(new Resource::TemplateRef(temp)); group->getOrCreateUserDataContainer()->addUserObject(new Resource::TemplateRef(temp));
mSceneManager->reinstateRemovedState(node);
InstancingVisitor visitor(pair.second, worldCenter); InstancingVisitor visitor(pair.second, worldCenter);
node->accept(visitor); node->accept(visitor);
group->addChild(node); group->addChild(node);
} }
// Force a unified alpha handling instead of data from meshes group->setStateSet(mStateset);
osg::ref_ptr<osg::AlphaFunc> alpha = new osg::AlphaFunc(osg::AlphaFunc::GEQUAL, 128.f / 255.f);
group->getOrCreateStateSet()->setAttributeAndModes(alpha.get(), osg::StateAttribute::ON);
group->getBound();
group->setNodeMask(Mask_Groundcover); group->setNodeMask(Mask_Groundcover);
if (mSceneManager->getLightingMethod() != SceneUtil::LightingMethod::FFP) if (mSceneManager->getLightingMethod() != SceneUtil::LightingMethod::FFP)
group->setCullCallback(new SceneUtil::LightListCallback); group->setCullCallback(new SceneUtil::LightListCallback);
mSceneManager->recreateShaders(group, "groundcover", false, true); mSceneManager->recreateShaders(group, "groundcover", false, true);
mSceneManager->shareState(group);
group->getBound();
return group; return group;
} }

@ -56,6 +56,7 @@ namespace MWRender
private: private:
Resource::SceneManager* mSceneManager; Resource::SceneManager* mSceneManager;
float mDensity; float mDensity;
osg::ref_ptr<osg::StateSet> mStateset;
typedef std::map<std::string, std::vector<GroundcoverEntry>> InstanceMap; typedef std::map<std::string, std::vector<GroundcoverEntry>> InstanceMap;
osg::ref_ptr<osg::Node> createChunk(InstanceMap& instances, const osg::Vec2f& center); osg::ref_ptr<osg::Node> createChunk(InstanceMap& instances, const osg::Vec2f& center);

Loading…
Cancel
Save