]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/material/Effect.cxx
Work around apparent OSG 3.2.0 normal binding bug.
[simgear.git] / simgear / scene / material / Effect.cxx
index a3064fdf1c95833d7a177195797b1f637f6381de..17b02a65a8e878e6d0d1cbb788cae66d860cf34c 100644 (file)
@@ -24,6 +24,7 @@
 #include "Technique.hxx"
 #include "Pass.hxx"
 #include "TextureBuilder.hxx"
+#include "parseBlendFunc.hxx"
 
 #include <algorithm>
 #include <functional>
@@ -74,7 +75,7 @@
 #include <simgear/scene/util/StateAttributeFactory.hxx>
 #include <simgear/structure/OSGUtils.hxx>
 #include <simgear/structure/SGExpression.hxx>
-
+#include <simgear/props/vectorPropTemplates.hxx>
 
 
 namespace simgear
@@ -453,58 +454,16 @@ struct BlendBuilder : public PassAttributeBuilder
             pass->setMode(GL_BLEND, StateAttribute::OFF);
             return;
         }
-        const SGPropertyNode* psource
-            = getEffectPropertyChild(effect, prop, "source");
-        const SGPropertyNode* pdestination
-            = getEffectPropertyChild(effect, prop, "destination");
-        const SGPropertyNode* psourceRGB
-            = getEffectPropertyChild(effect, prop, "source-rgb");
-        const SGPropertyNode* psourceAlpha
-            = getEffectPropertyChild(effect, prop, "source-alpha");
-        const SGPropertyNode* pdestRGB
-            = getEffectPropertyChild(effect, prop, "destination-rgb");
-        const SGPropertyNode* pdestAlpha
-            = getEffectPropertyChild(effect, prop, "destination-alpha");
-        BlendFunc::BlendFuncMode sourceMode = BlendFunc::ONE;
-        BlendFunc::BlendFuncMode destMode = BlendFunc::ZERO;
-        if (psource)
-            findAttr(blendFuncModes, psource, sourceMode);
-        if (pdestination)
-            findAttr(blendFuncModes, pdestination, destMode);
-        if (psource && pdestination
-            && !(psourceRGB || psourceAlpha || pdestRGB || pdestAlpha)
-            && sourceMode == BlendFunc::SRC_ALPHA
-            && destMode == BlendFunc::ONE_MINUS_SRC_ALPHA) {
-            pass->setAttributeAndModes(StateAttributeFactory::instance()
-                                       ->getStandardBlendFunc());
-            return;
-        }
-        BlendFunc* blendFunc = new BlendFunc;
-        if (psource)
-            blendFunc->setSource(sourceMode);
-        if (pdestination)
-            blendFunc->setDestination(destMode);
-        if (psourceRGB) {
-            BlendFunc::BlendFuncMode sourceRGBMode;
-            findAttr(blendFuncModes, psourceRGB, sourceRGBMode);
-            blendFunc->setSourceRGB(sourceRGBMode);
-        }
-        if (pdestRGB) {
-            BlendFunc::BlendFuncMode destRGBMode;
-            findAttr(blendFuncModes, pdestRGB, destRGBMode);
-            blendFunc->setDestinationRGB(destRGBMode);
-        }
-        if (psourceAlpha) {
-            BlendFunc::BlendFuncMode sourceAlphaMode;
-            findAttr(blendFuncModes, psourceAlpha, sourceAlphaMode);
-            blendFunc->setSourceAlpha(sourceAlphaMode);
-        }
-        if (pdestAlpha) {
-            BlendFunc::BlendFuncMode destAlphaMode;
-            findAttr(blendFuncModes, pdestAlpha, destAlphaMode);
-            blendFunc->setDestinationAlpha(destAlphaMode);
-        }
-        pass->setAttributeAndModes(blendFunc);
+
+        parseBlendFunc(
+          pass,
+          getEffectPropertyChild(effect, prop, "source"),
+          getEffectPropertyChild(effect, prop, "destination"),
+          getEffectPropertyChild(effect, prop, "source-rgb"),
+          getEffectPropertyChild(effect, prop, "destination-rgb"),
+          getEffectPropertyChild(effect, prop, "source-alpha"),
+          getEffectPropertyChild(effect, prop, "destination-alpha")
+        );
     }
 };
 
@@ -602,6 +561,28 @@ struct StencilBuilder : public PassAttributeBuilder
 
 InstallAttributeBuilder<StencilBuilder> installStencil("stencil");
 
+struct AlphaToCoverageBuilder : public PassAttributeBuilder
+{
+    void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
+                        const SGReaderWriterOptions* options);
+};
+
+#ifndef GL_SAMPLE_ALPHA_TO_COVERAGE_ARB
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#endif
+
+void AlphaToCoverageBuilder::buildAttribute(Effect* effect, Pass* pass,
+                                     const SGPropertyNode* prop,
+                                     const SGReaderWriterOptions* options)
+{
+    const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
+    if (!realProp)
+        return;
+    pass->setMode(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB, (realProp->getValue<bool>() ? 
+                                    StateAttribute::ON : StateAttribute::OFF));
+}
+
+InstallAttributeBuilder<AlphaToCoverageBuilder> installAlphaToCoverage("alpha-to-coverage");
 
 EffectNameValue<AlphaFunc::ComparisonFunction> alphaComparisonInit[] =
 {
@@ -648,6 +629,7 @@ struct AlphaTestBuilder : public PassAttributeBuilder
                                                              "comparison");
         const SGPropertyNode* pRef = getEffectPropertyChild(effect, prop,
                                                              "reference");
+
         AlphaFunc::ComparisonFunction func = AlphaFunc::ALWAYS;
         float refValue = 1.0f;
         if (pComp)
@@ -671,9 +653,9 @@ InstallAttributeBuilder<AlphaTestBuilder> installAlphaTest("alpha-test");
 InstallAttributeBuilder<TextureUnitBuilder> textureUnitBuilder("texture-unit");
 
 // Shader key, used both for shaders with relative and absolute names
-typedef pair<string, Shader::Type> ShaderKey;
+typedef pair<string, int> ShaderKey;
 
-inline ShaderKey makeShaderKey(SGPropertyNode_ptr& ptr, Shader::Type shaderType)
+inline ShaderKey makeShaderKey(SGPropertyNode_ptr& ptr, int shaderType)
 {
     return ShaderKey(ptr->getStringValue(), shaderType);
 }
@@ -815,7 +797,7 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
     BOOST_FOREACH(const ShaderKey& shaderKey, prgKey.shaders)
     {
         const string& shaderName = shaderKey.first;
-        Shader::Type stype = shaderKey.second;
+        Shader::Type stype = (Shader::Type)shaderKey.second;
         string fileName = SGModelLib::findDataFile(shaderName, options);
         if (fileName.empty())
             throw BuilderException(string("couldn't find shader ") +
@@ -833,12 +815,13 @@ void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
     BOOST_FOREACH(const ShaderKey& skey, resolvedKey.shaders)
     {
         const string& fileName = skey.first;
-        Shader::Type stype = skey.second;
+        Shader::Type stype = (Shader::Type)skey.second;
         ShaderMap::iterator sitr = shaderMap.find(skey);
         if (sitr != shaderMap.end()) {
             program->addShader(sitr->second.get());
         } else {
             ref_ptr<Shader> shader = new Shader(stype);
+                       shader->setName(fileName);
             if (shader->loadShaderSourceFromFile(fileName)) {
                 program->addShader(shader.get());
                 shaderMap.insert(ShaderMap::value_type(skey, shader));
@@ -998,8 +981,8 @@ struct UniformBuilder :public PassAttributeBuilder
         // optimize common uniforms
         if (uniformType == Uniform::SAMPLER_2D || uniformType == Uniform::INT)
         {
-            int val;
-            uniform->get(val);
+            int val = 0;
+            uniform->get(val); // 'val' remains unchanged in case of error (Uniform is a non-scalar)
             if (uniformType == Uniform::SAMPLER_2D && val == 0
                 && name == "texture") {
                 uniform = texture0;
@@ -1375,14 +1358,25 @@ template<typename T>
 class PropertyExpression : public SGExpression<T>
 {
 public:
-    PropertyExpression(SGPropertyNode* pnode) : _pnode(pnode) {}
+    PropertyExpression(SGPropertyNode* pnode) : _pnode(pnode), _listener(NULL) {}
+    
+    ~PropertyExpression()
+    {
+        delete _listener;
+    }
     
     void eval(T& value, const expression::Binding*) const
     {
         value = _pnode->getValue<T>();
     }
+    
+    void setListener(SGPropertyChangeListener* l)
+    {
+        _listener = l;
+    }
 protected:
     SGPropertyNode_ptr _pnode;
+    SGPropertyChangeListener* _listener;
 };
 
 class EffectPropertyListener : public SGPropertyChangeListener
@@ -1392,10 +1386,14 @@ public:
     
     void valueChanged(SGPropertyNode* node)
     {
-        _tniq->refreshValidity();
+        if (_tniq.valid())
+            _tniq->refreshValidity();
     }
+    
+    virtual ~EffectPropertyListener() { }
+    
 protected:
-    osg::ref_ptr<Technique> _tniq;
+    osg::observer_ptr<Technique> _tniq;
 };
 
 template<typename T>
@@ -1407,9 +1405,12 @@ Expression* propertyExpressionParser(const SGPropertyNode* exp,
     PropertyExpression<T>* pexp = new PropertyExpression<T>(pnode);
     TechniquePredParser* predParser
         = dynamic_cast<TechniquePredParser*>(parser);
-    if (predParser)
-        pnode->addChangeListener(new EffectPropertyListener(predParser
-                                                            ->getTechnique()));
+    if (predParser) {
+        EffectPropertyListener* l = new EffectPropertyListener(predParser
+                                                               ->getTechnique());
+        pexp->setListener(l);
+        pnode->addChangeListener(l);
+    }
     return pexp;
 }