mirror of https://github.com/OpenMW/openmw.git
terrain: use a custom drawable for multi-pass render instead of osgFX::Effect
osgFX::Effect is awkward to use because of the lazy-definition of passes, no support for compileGLObjects, useless 'Technique' abstraction and having to define silly methods like 'effectAuthor()' Handling the multi-pass rendering inside the Drawable also avoids redundant culling tests against the same bounding box for each pass.pull/1225/head
parent
34130fc5cc
commit
eef63a880a
@ -0,0 +1,85 @@
|
||||
#include "terraindrawable.hpp"
|
||||
|
||||
#include <osgUtil/CullVisitor>
|
||||
|
||||
#include <components/sceneutil/lightmanager.hpp>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
|
||||
TerrainDrawable::TerrainDrawable()
|
||||
{
|
||||
mLightListCallback = new SceneUtil::LightListCallback;
|
||||
}
|
||||
|
||||
TerrainDrawable::TerrainDrawable(const TerrainDrawable ©, const osg::CopyOp ©op)
|
||||
: osg::Geometry(copy, copyop)
|
||||
, mPasses(copy.mPasses)
|
||||
, mLightListCallback(copy.mLightListCallback)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TerrainDrawable::accept(osg::NodeVisitor &nv)
|
||||
{
|
||||
if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)
|
||||
{
|
||||
osg::Geometry::accept(nv);
|
||||
}
|
||||
else if (nv.validNodeMask(*this))
|
||||
{
|
||||
nv.pushOntoNodePath(this);
|
||||
cull(static_cast<osgUtil::CullVisitor*>(&nv));
|
||||
nv.popFromNodePath();
|
||||
}
|
||||
}
|
||||
|
||||
inline float distance(const osg::Vec3& coord,const osg::Matrix& matrix)
|
||||
{
|
||||
return -((float)coord[0]*(float)matrix(0,2)+(float)coord[1]*(float)matrix(1,2)+(float)coord[2]*(float)matrix(2,2)+matrix(3,2));
|
||||
}
|
||||
|
||||
void TerrainDrawable::cull(osgUtil::CullVisitor *cv)
|
||||
{
|
||||
const osg::BoundingBox& bb = getBoundingBox();
|
||||
|
||||
if (cv->isCulled(getBoundingBox()))
|
||||
return;
|
||||
|
||||
osg::RefMatrix& matrix = *cv->getModelViewMatrix();
|
||||
|
||||
float depth = bb.valid() ? distance(bb.center(),matrix) : 0.0f;
|
||||
if (osg::isNaN(depth))
|
||||
return;
|
||||
|
||||
bool pushedLight = mLightListCallback->pushLightState(this, cv);
|
||||
|
||||
for (PassVector::const_iterator it = mPasses.begin(); it != mPasses.end(); ++it)
|
||||
{
|
||||
cv->pushStateSet(*it);
|
||||
cv->addDrawableAndDepth(this, &matrix, depth);
|
||||
cv->popStateSet();
|
||||
}
|
||||
|
||||
if (pushedLight)
|
||||
cv->popStateSet();
|
||||
}
|
||||
|
||||
void TerrainDrawable::setPasses(const TerrainDrawable::PassVector &passes)
|
||||
{
|
||||
mPasses = passes;
|
||||
}
|
||||
|
||||
void TerrainDrawable::compileGLObjects(osg::RenderInfo &renderInfo) const
|
||||
{
|
||||
for (PassVector::const_iterator it = mPasses.begin(); it != mPasses.end(); ++it)
|
||||
{
|
||||
osg::StateSet* stateset = *it;
|
||||
stateset->compileGLObjects(*renderInfo.getState());
|
||||
}
|
||||
|
||||
osg::Geometry::compileGLObjects(renderInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
#ifndef OPENMW_COMPONENTS_TERRAIN_DRAWABLE_H
|
||||
#define OPENMW_COMPONENTS_TERRAIN_DRAWABLE_H
|
||||
|
||||
#include <osg/Geometry>
|
||||
|
||||
namespace osgUtil
|
||||
{
|
||||
class CullVisitor;
|
||||
}
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
class LightListCallback;
|
||||
}
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
|
||||
/**
|
||||
* Subclass of Geometry that supports built in multi-pass rendering and built in LightListCallback.
|
||||
*/
|
||||
class TerrainDrawable : public osg::Geometry
|
||||
{
|
||||
public:
|
||||
virtual osg::Object* cloneType() const { return new TerrainDrawable (); }
|
||||
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new TerrainDrawable (*this,copyop); }
|
||||
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const TerrainDrawable *>(obj)!=NULL; }
|
||||
virtual const char* className() const { return "TerrainDrawable"; }
|
||||
virtual const char* libraryName() const { return "Terrain"; }
|
||||
|
||||
TerrainDrawable();
|
||||
TerrainDrawable(const TerrainDrawable& copy, const osg::CopyOp& copyop);
|
||||
|
||||
virtual void accept(osg::NodeVisitor &nv);
|
||||
void cull(osgUtil::CullVisitor* cv);
|
||||
|
||||
typedef std::vector<osg::ref_ptr<osg::StateSet> > PassVector;
|
||||
void setPasses (const PassVector& passes);
|
||||
|
||||
virtual void compileGLObjects(osg::RenderInfo& renderInfo) const;
|
||||
|
||||
private:
|
||||
PassVector mPasses;
|
||||
|
||||
osg::ref_ptr<SceneUtil::LightListCallback> mLightListCallback;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue