mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-03 17:54:06 +00:00
Groundcover optimisation (#3101)
* groundcover.cpp share state * groundcover.hpp share state
This commit is contained in:
parent
0ab8a7ddd7
commit
b6f572578e
@ -1,6 +1,7 @@
|
||||
#include "groundcover.hpp"
|
||||
|
||||
#include <osg/AlphaFunc>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Geometry>
|
||||
#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
|
||||
{
|
||||
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
|
||||
geom.setUseDisplayList(false);
|
||||
geom.setUseVertexBufferObjects(true);
|
||||
|
||||
geom.setVertexAttribArray(6, transforms.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:
|
||||
std::vector<Groundcover::GroundcoverEntry> mInstances;
|
||||
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
|
||||
@ -199,7 +170,16 @@ namespace MWRender
|
||||
: GenericResourceManager<GroundcoverChunkId>(nullptr)
|
||||
, mSceneManager(sceneManager)
|
||||
, 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)
|
||||
@ -255,27 +235,23 @@ namespace MWRender
|
||||
for (auto& pair : instances)
|
||||
{
|
||||
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
|
||||
group->getOrCreateUserDataContainer()->addUserObject(new Resource::TemplateRef(temp));
|
||||
|
||||
mSceneManager->reinstateRemovedState(node);
|
||||
|
||||
InstancingVisitor visitor(pair.second, worldCenter);
|
||||
node->accept(visitor);
|
||||
group->addChild(node);
|
||||
}
|
||||
|
||||
// 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);
|
||||
group->getOrCreateStateSet()->setAttributeAndModes(alpha.get(), osg::StateAttribute::ON);
|
||||
group->getBound();
|
||||
group->setStateSet(mStateset);
|
||||
group->setNodeMask(Mask_Groundcover);
|
||||
if (mSceneManager->getLightingMethod() != SceneUtil::LightingMethod::FFP)
|
||||
group->setCullCallback(new SceneUtil::LightListCallback);
|
||||
mSceneManager->recreateShaders(group, "groundcover", false, true);
|
||||
|
||||
mSceneManager->shareState(group);
|
||||
group->getBound();
|
||||
return group;
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,7 @@ namespace MWRender
|
||||
private:
|
||||
Resource::SceneManager* mSceneManager;
|
||||
float mDensity;
|
||||
osg::ref_ptr<osg::StateSet> mStateset;
|
||||
|
||||
typedef std::map<std::string, std::vector<GroundcoverEntry>> InstanceMap;
|
||||
osg::ref_ptr<osg::Node> createChunk(InstanceMap& instances, const osg::Vec2f& center);
|
||||
|
Loading…
x
Reference in New Issue
Block a user