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