mirror of
https://github.com/OpenMW/openmw.git
synced 2025-12-09 13:34:34 +00:00
Groundcover optimisation (#3101)
* groundcover.cpp share state * groundcover.hpp share state
This commit is contained in:
parent
0ab8a7ddd7
commit
b6f572578e
2 changed files with 16 additions and 39 deletions
|
|
@ -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…
Reference in a new issue