Add positioned uniforms and G-buffer textures to Effects

This commit is contained in:
Frederic Bouvier 2012-01-02 11:34:11 +01:00
parent 9700e46e47
commit d393e4a019
8 changed files with 139 additions and 19 deletions

View File

@ -916,6 +916,7 @@ struct UniformBuilder :public PassAttributeBuilder
return;
const SGPropertyNode* nameProp = prop->getChild("name");
const SGPropertyNode* typeProp = prop->getChild("type");
const SGPropertyNode* positionedProp = prop->getChild("positioned");
const SGPropertyNode* valProp = prop->getChild("value");
string name;
Uniform::Type uniformType = Uniform::FLOAT;
@ -1003,6 +1004,11 @@ struct UniformBuilder :public PassAttributeBuilder
}
}
pass->addUniform(uniform.get());
if (positionedProp && positionedProp->getBoolValue() && uniformType == Uniform::FLOAT_VEC4) {
osg::Vec4 offset;
uniform->get(offset);
pass->addPositionedUniform( name, offset );
}
}
};
@ -1163,7 +1169,10 @@ struct DepthBuilder : public PassAttributeBuilder
= getEffectPropertyChild(effect, prop, "write-mask");
if (pmask)
depth->setWriteMask(pmask->getValue<bool>());
pass->setAttribute(depth.get());
const SGPropertyNode* penabled
= getEffectPropertyChild(effect, prop, "enabled");
bool enabled = ( penabled == 0 || penabled->getBoolValue() );
pass->setAttributeAndModes(depth.get(), enabled ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
}
};

View File

@ -58,16 +58,16 @@ class EffectBuilder : public SGReferenced
{
public:
virtual ~EffectBuilder() {}
virtual T* build(Effect* effect, const SGPropertyNode*,
virtual T* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options) = 0;
static T* buildFromType(Effect* effect, const std::string& type,
static T* buildFromType(Effect* effect, Pass* pass, const std::string& type,
const SGPropertyNode*props,
const SGReaderWriterOptions* options)
{
BuilderMap& builderMap = getMap();
typename BuilderMap::iterator iter = builderMap.find(type);
if (iter != builderMap.end())
return iter->second->build(effect, props, options);
return iter->second->build(effect, pass, props, options);
else
return 0;
}

View File

@ -19,6 +19,7 @@
#endif
#include <osg/StateSet>
#include <osg/Texture2D>
#include "EffectCullVisitor.hxx"
@ -78,4 +79,20 @@ void EffectCullVisitor::apply(osg::Geode& node)
popStateSet();
}
void EffectCullVisitor::clearBufferList()
{
_bufferList.clear();
}
void EffectCullVisitor::addBuffer(int i, osg::Texture2D* tex)
{
_bufferList.insert(std::make_pair(i,tex));
}
osg::Texture2D* EffectCullVisitor::getBuffer(int i)
{
return _bufferList[i];
}
}

View File

@ -19,9 +19,12 @@
#include <osgUtil/CullVisitor>
#include <map>
namespace osg
{
class Geode;
class Texture2D;
}
namespace simgear
@ -34,6 +37,13 @@ public:
virtual osgUtil::CullVisitor* clone() const;
using osgUtil::CullVisitor::apply;
virtual void apply(osg::Geode& node);
void clearBufferList();
void addBuffer(int i, osg::Texture2D* tex);
osg::Texture2D* getBuffer(int i);
private:
std::map<int,osg::ref_ptr<osg::Texture2D> > _bufferList;
};
}
#endif

View File

@ -26,10 +26,23 @@ namespace simgear
class Pass : public osg::StateSet
{
public:
typedef std::list<std::pair<int,int> > BufferUnitList;
typedef std::map<std::string,osg::Vec4> PositionedUniformMap;
META_Object(simgear,Pass);
Pass() {}
Pass(const Pass& rhs,
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
void setBufferUnit( int unit, int buffer ) { _bufferUnitList.push_back( std::make_pair(unit,buffer) ); }
const BufferUnitList& getBufferUnitList() const { return _bufferUnitList; }
void addPositionedUniform( const std::string& name, const osg::Vec4& offset ) { _positionedUniforms[name] = offset; }
const PositionedUniformMap& getPositionedUniformMap() const { return _positionedUniforms; }
private:
BufferUnitList _bufferUnitList;
PositionedUniformMap _positionedUniforms;
};
}

View File

@ -5,6 +5,7 @@
#include "Technique.hxx"
#include "Pass.hxx"
#include "EffectCullVisitor.hxx"
#include <boost/foreach.hpp>
@ -15,6 +16,8 @@
#include <osg/GLExtensions>
#include <osg/GL2Extensions>
#include <osg/Math>
#include <osg/Texture2D>
#include <osg/CopyOp>
#include <osgUtil/CullVisitor>
#include <osgDB/Registry>
@ -159,10 +162,37 @@ Technique::processDrawables(const EffectGeode::DrawablesIterator& begin,
if (isNaN(depth[i]))
depth[i] = FLT_MAX;
}
EffectCullVisitor* ecv = dynamic_cast<EffectCullVisitor*>( cv );
EffectGeode::DrawablesIterator drawablesEnd = itr;
BOOST_FOREACH(ref_ptr<Pass>& pass, passes)
{
cv->pushStateSet(pass.get());
osg::ref_ptr<osg::StateSet> ss = pass;
if (ecv && ( pass->getBufferUnitList().size() != 0 || pass->getPositionedUniformMap().size() != 0 ) ) {
ss = static_cast<osg::StateSet*>(
pass->clone( osg::CopyOp( ( pass->getBufferUnitList().size() != 0 ?
osg::CopyOp::DEEP_COPY_TEXTURES :
osg::CopyOp::SHALLOW_COPY ) |
( pass->getPositionedUniformMap().size() != 0 ?
osg::CopyOp::DEEP_COPY_UNIFORMS :
osg::CopyOp::SHALLOW_COPY ) )
)
);
for (Pass::BufferUnitList::const_iterator ii = pass->getBufferUnitList().begin();
ii != pass->getBufferUnitList().end();
++ii) {
osg::Texture2D* tex = ecv->getBuffer(ii->second);
if (tex != 0)
ss->setTextureAttributeAndModes( ii->first, tex );
}
for (Pass::PositionedUniformMap::const_iterator ii = pass->getPositionedUniformMap().begin();
ii != pass->getPositionedUniformMap().end();
++ii) {
osg::RefMatrix* mv = cv->getModelViewMatrix();
osg::Vec4 v = ii->second * *mv;
ss->getUniform(ii->first)->set( v );
}
}
cv->pushStateSet(ss);
int i = 0;
for (itr = begin; itr != drawablesEnd; ++itr, ++i) {
if (depth[i] != FLT_MAX)

View File

@ -59,12 +59,12 @@ TexEnvCombine* buildTexEnvCombine(Effect* effect,
TexGen* buildTexGen(Effect* Effect, const SGPropertyNode* tgenProp);
// Hack to force inclusion of TextureBuilder.cxx in library
osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type,
osg::Texture* TextureBuilder::buildFromType(Effect* effect, Pass* pass, const string& type,
const SGPropertyNode*props,
const SGReaderWriterOptions*
options)
{
return EffectBuilder<Texture>::buildFromType(effect, type, props, options);
return EffectBuilder<Texture>::buildFromType(effect, pass, type, props, options);
}
typedef boost::tuple<string, Texture::FilterMode, Texture::FilterMode,
@ -130,7 +130,7 @@ void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
type = pType->getStringValue();
Texture* texture = 0;
try {
texture = TextureBuilder::buildFromType(effect, type, prop,
texture = TextureBuilder::buildFromType(effect, pass, type, prop,
options);
}
catch (BuilderException& e) {
@ -278,7 +278,7 @@ class TexBuilder : public TextureBuilder
{
public:
TexBuilder(const string& texType) : _type(texType) {}
Texture* build(Effect* effect, const SGPropertyNode*,
Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options);
protected:
typedef map<TexTuple, ref_ptr<T> > TexMap;
@ -287,7 +287,7 @@ protected:
};
template<typename T>
Texture* TexBuilder<T>::build(Effect* effect, const SGPropertyNode* props,
Texture* TexBuilder<T>::build(Effect* effect, Pass* pass, const SGPropertyNode* props,
const SGReaderWriterOptions* options)
{
TexTuple attrs = makeTexTuple(effect, props, options, _type);
@ -311,11 +311,11 @@ TextureBuilder::Registrar install3D("3d", new TexBuilder<Texture3D>("3d"));
class WhiteTextureBuilder : public TextureBuilder
{
public:
Texture* build(Effect* effect, const SGPropertyNode*,
Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options);
};
Texture* WhiteTextureBuilder::build(Effect* effect, const SGPropertyNode*,
Texture* WhiteTextureBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options)
{
return StateAttributeFactory::instance()->getWhiteTexture();
@ -329,11 +329,11 @@ TextureBuilder::Registrar installWhite("white", new WhiteTextureBuilder);
class TransparentTextureBuilder : public TextureBuilder
{
public:
Texture* build(Effect* effect, const SGPropertyNode*,
Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options);
};
Texture* TransparentTextureBuilder::build(Effect* effect, const SGPropertyNode*,
Texture* TransparentTextureBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options)
{
return StateAttributeFactory::instance()->getTransparentTexture();
@ -393,14 +393,14 @@ osg::Image* make3DNoiseImage(int texSize)
class NoiseBuilder : public TextureBuilder
{
public:
Texture* build(Effect* effect, const SGPropertyNode*,
Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options);
protected:
typedef map<int, ref_ptr<Texture3D> > NoiseMap;
NoiseMap _noises;
};
Texture* NoiseBuilder::build(Effect* effect, const SGPropertyNode* props,
Texture* NoiseBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode* props,
const SGReaderWriterOptions* options)
{
int texSize = 64;
@ -461,7 +461,7 @@ CubeMapTuple makeCubeMapTuple(Effect* effect, const SGPropertyNode* props)
class CubeMapBuilder : public TextureBuilder
{
public:
Texture* build(Effect* effect, const SGPropertyNode*,
Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options);
protected:
typedef map<CubeMapTuple, ref_ptr<TextureCubeMap> > CubeMap;
@ -484,7 +484,7 @@ void copySubImage(const osg::Image* srcImage, int src_s, int src_t, int width, i
}
Texture* CubeMapBuilder::build(Effect* effect, const SGPropertyNode* props,
Texture* CubeMapBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode* props,
const SGReaderWriterOptions* options)
{
// First check that there is a <images> tag
@ -876,4 +876,45 @@ bool makeTextureParameters(SGPropertyNode* paramRoot, const StateSet* ss)
return true;
}
class GBufferBuilder : public TextureBuilder
{
public:
GBufferBuilder(int b) : buffer(b) {}
Texture* build(Effect* effect, Pass* pass, const SGPropertyNode*,
const SGReaderWriterOptions* options);
private:
int buffer;
};
Texture* GBufferBuilder::build(Effect* effect, Pass* pass, const SGPropertyNode* prop,
const SGReaderWriterOptions* options)
{
int unit = 0;
const SGPropertyNode* pUnit = prop->getChild("unit");
if (pUnit) {
unit = pUnit->getValue<int>();
} else {
const SGPropertyNode* pName = prop->getChild("name");
if (pName)
try {
unit = boost::lexical_cast<int>(pName->getStringValue());
} catch (boost::bad_lexical_cast& lex) {
SG_LOG(SG_INPUT, SG_ALERT, "can't decode name as texture unit "
<< lex.what());
}
}
pass->setBufferUnit( unit, buffer );
// Return white for now. Would be overridden in Technique::ProcessDrawable
return StateAttributeFactory::instance()->getWhiteTexture();
}
namespace
{
TextureBuilder::Registrar installDepthBuffer("depth-buffer", new GBufferBuilder(0));
TextureBuilder::Registrar installNormalBuffer("normal-buffer", new GBufferBuilder(1));
TextureBuilder::Registrar installDiffuseBuffer("diffuse-buffer", new GBufferBuilder(2));
TextureBuilder::Registrar installSpecularBuffer("specular-buffer", new GBufferBuilder(3));
}
}

View File

@ -27,7 +27,7 @@ class TextureBuilder : public EffectBuilder<osg::Texture>
{
public:
// Hack to force inclusion of TextureBuilder.cxx in library
static osg::Texture* buildFromType(Effect* effect, const std::string& type,
static osg::Texture* buildFromType(Effect* effect, Pass* pass, const std::string& type,
const SGPropertyNode*props,
const SGReaderWriterOptions* options);
};