diff --git a/simgear/scene/material/Effect.cxx b/simgear/scene/material/Effect.cxx index 9ca2acee..3cd6a93b 100644 --- a/simgear/scene/material/Effect.cxx +++ b/simgear/scene/material/Effect.cxx @@ -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()); - 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); } }; diff --git a/simgear/scene/material/EffectBuilder.hxx b/simgear/scene/material/EffectBuilder.hxx index a464071f..a7c35ea1 100644 --- a/simgear/scene/material/EffectBuilder.hxx +++ b/simgear/scene/material/EffectBuilder.hxx @@ -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; } diff --git a/simgear/scene/material/EffectCullVisitor.cxx b/simgear/scene/material/EffectCullVisitor.cxx index e2d19920..36f85eb4 100644 --- a/simgear/scene/material/EffectCullVisitor.cxx +++ b/simgear/scene/material/EffectCullVisitor.cxx @@ -19,6 +19,7 @@ #endif #include +#include #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]; +} + } diff --git a/simgear/scene/material/EffectCullVisitor.hxx b/simgear/scene/material/EffectCullVisitor.hxx index fa752c8f..4f0054dd 100644 --- a/simgear/scene/material/EffectCullVisitor.hxx +++ b/simgear/scene/material/EffectCullVisitor.hxx @@ -19,9 +19,12 @@ #include +#include + 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 > _bufferList; }; } #endif diff --git a/simgear/scene/material/Pass.hxx b/simgear/scene/material/Pass.hxx index 869dabd9..a2c901dd 100644 --- a/simgear/scene/material/Pass.hxx +++ b/simgear/scene/material/Pass.hxx @@ -26,10 +26,23 @@ namespace simgear class Pass : public osg::StateSet { public: + typedef std::list > BufferUnitList; + typedef std::map 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; }; } diff --git a/simgear/scene/material/Technique.cxx b/simgear/scene/material/Technique.cxx index a540fb2f..3a09dfea 100644 --- a/simgear/scene/material/Technique.cxx +++ b/simgear/scene/material/Technique.cxx @@ -5,6 +5,7 @@ #include "Technique.hxx" #include "Pass.hxx" +#include "EffectCullVisitor.hxx" #include @@ -15,6 +16,8 @@ #include #include #include +#include +#include #include #include @@ -159,10 +162,37 @@ Technique::processDrawables(const EffectGeode::DrawablesIterator& begin, if (isNaN(depth[i])) depth[i] = FLT_MAX; } + EffectCullVisitor* ecv = dynamic_cast( cv ); EffectGeode::DrawablesIterator drawablesEnd = itr; BOOST_FOREACH(ref_ptr& pass, passes) { - cv->pushStateSet(pass.get()); + osg::ref_ptr ss = pass; + if (ecv && ( pass->getBufferUnitList().size() != 0 || pass->getPositionedUniformMap().size() != 0 ) ) { + ss = static_cast( + 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) diff --git a/simgear/scene/material/TextureBuilder.cxx b/simgear/scene/material/TextureBuilder.cxx index d191ef33..f4523c9b 100644 --- a/simgear/scene/material/TextureBuilder.cxx +++ b/simgear/scene/material/TextureBuilder.cxx @@ -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::buildFromType(effect, type, props, options); + return EffectBuilder::buildFromType(effect, pass, type, props, options); } typedef boost::tuplegetStringValue(); 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 > TexMap; @@ -287,7 +287,7 @@ protected: }; template -Texture* TexBuilder::build(Effect* effect, const SGPropertyNode* props, +Texture* TexBuilder::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("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 > 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 > 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 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(); + } else { + const SGPropertyNode* pName = prop->getChild("name"); + if (pName) + try { + unit = boost::lexical_cast(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)); +} + } diff --git a/simgear/scene/material/TextureBuilder.hxx b/simgear/scene/material/TextureBuilder.hxx index c8105e75..c4225a21 100644 --- a/simgear/scene/material/TextureBuilder.hxx +++ b/simgear/scene/material/TextureBuilder.hxx @@ -27,7 +27,7 @@ class TextureBuilder : public EffectBuilder { 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); };