]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/material/Technique.cxx
Random buildings - initial commit.
[simgear.git] / simgear / scene / material / Technique.cxx
index b8ceaa59ddfa6f641e6196a8c5922334004df65b..3a09dfead0b64bfb43b27b1013f4fbbe5994f475 100644 (file)
@@ -5,8 +5,8 @@
 
 #include "Technique.hxx"
 #include "Pass.hxx"
+#include "EffectCullVisitor.hxx"
 
-#include <boost/bind.hpp>
 #include <boost/foreach.hpp>
 
 #include <iterator>
 #include <string>
 
 #include <osg/GLExtensions>
+#include <osg/GL2Extensions>
 #include <osg/Math>
+#include <osg/Texture2D>
+#include <osg/CopyOp>
 #include <osgUtil/CullVisitor>
 
 #include <osgDB/Registry>
@@ -58,17 +61,17 @@ Technique::Technique(bool alwaysValid)
 }
 
 Technique::Technique(const Technique& rhs, const osg::CopyOp& copyop) :
+    osg::Object(rhs,copyop),
     _contextMap(rhs._contextMap), _alwaysValid(rhs._alwaysValid),
-    _shadowingStateSet(rhs._shadowingStateSet),
+    _shadowingStateSet(copyop(rhs._shadowingStateSet.get())),
     _validExpression(rhs._validExpression),
     _contextIdLocation(rhs._contextIdLocation)
 {
-    using namespace std;
-    using namespace boost;
-    transform(rhs.passes.begin(), rhs.passes.end(),
-              back_inserter(passes),
-              bind(simgear::clone_ref<Pass>, _1, copyop));
-
+    for (std::vector<ref_ptr<Pass> >::const_iterator itr = rhs.passes.begin(),
+             end = rhs.passes.end();
+         itr != end;
+         ++itr)
+        passes.push_back(static_cast<Pass*>(copyop(itr->get())));
 }
 
 Technique::~Technique()
@@ -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)
@@ -192,7 +222,7 @@ void Technique::releaseGLObjects(osg::State* state) const
         pass->releaseGLObjects(state);
     }
     if (state == 0) {
-        for (int i = 0; i < _contextMap.size(); ++i) {
+        for (int i = 0; i < (int)_contextMap.size(); ++i) {
             ContextInfo& info = _contextMap[i];
             Status oldVal = info.valid();
             info.valid.compareAndSwap(oldVal, UNKNOWN);
@@ -276,6 +306,38 @@ Expression* extensionSupportedParser(const SGPropertyNode* exp,
 expression::ExpParserRegistrar
 extensionSupportedRegistrar("extension-supported", extensionSupportedParser);
 
+class GLShaderLanguageExpression : public GeneralNaryExpression<float, int>
+{
+public:
+    void eval(float& value, const expression::Binding* b) const
+    {
+        value = 0.0f;
+        int contextId = getOperand(0)->getValue(b);
+        GL2Extensions* extensions
+            = GL2Extensions::Get(static_cast<unsigned>(contextId), true);
+        if (!extensions)
+            return;
+        if (!extensions->isGlslSupported())
+            return;
+        value = extensions->getLanguageVersion();
+    }
+};
+
+Expression* shaderLanguageParser(const SGPropertyNode* exp,
+                                 expression::Parser* parser)
+{
+    GLShaderLanguageExpression* slexp = new GLShaderLanguageExpression;
+    int location = parser->getBindingLayout().addBinding("__contextId",
+                                                         expression::INT);
+    VariableExpression<int>* contextExp = new VariableExpression<int>(location);
+    slexp->addOperand(contextExp);
+    return slexp;
+}
+
+expression::ExpParserRegistrar shaderLanguageRegistrar("shader-language",
+                                                       glVersionParser);
+
+    
 void Technique::setGLExtensionsPred(float glVersion,
                                     const std::vector<std::string>& extensions)
 {
@@ -314,7 +376,7 @@ void Technique::setGLExtensionsPred(float glVersion,
 
 void Technique::refreshValidity()
 {
-    for (int i = 0; i < _contextMap.size(); ++i) {
+    for (int i = 0; i < (int)_contextMap.size(); ++i) {
         ContextInfo& info = _contextMap[i];
         Status oldVal = info.valid();
         // What happens if we lose the race here?