]> git.mxchange.org Git - simgear.git/commitdiff
Fix cloud layer - point lights visibility issue
authortimoore <timoore>
Fri, 21 Dec 2007 06:24:53 +0000 (06:24 +0000)
committertimoore <timoore>
Fri, 21 Dec 2007 06:24:53 +0000 (06:24 +0000)
Move point lights to render bin 8, clouds to render bin 9. Turn on
AlphaFunc for cloud layers.

Create a StateAttributeFactory object to create and share common state
objects.

simgear/scene/sky/cloud.cxx
simgear/scene/tgdb/pt_lights.cxx
simgear/scene/util/Makefile.am
simgear/scene/util/RenderConstants.hxx
simgear/scene/util/StateAttributeFactory.cxx [new file with mode: 0644]
simgear/scene/util/StateAttributeFactory.hxx [new file with mode: 0644]

index 34361cd9294435706f44ec745afc383405cec88b..0b532fd03f37df98ab499e9a0505a26298664b96 100644 (file)
@@ -45,6 +45,8 @@
 #include <simgear/misc/PathOptions.hxx>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/scene/model/model.hxx>
+#include <simgear/scene/util/RenderConstants.hxx>
+#include <simgear/scene/util/StateAttributeFactory.hxx>
 #include <simgear/math/polar3d.hxx>
 
 #include "newcloud.hxx"
@@ -88,31 +90,13 @@ SGMakeState(const SGPath &path, const char* colorTexture,
     stateSet->setTextureAttribute(0, SGLoadTexture2D(colorTexture,
                                                      options.get()));
     stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
-
-    osg::TexEnv* texEnv = new osg::TexEnv;
-    texEnv->setMode(osg::TexEnv::MODULATE);
-    stateSet->setTextureAttribute(0, texEnv);
-    osg::ShadeModel* shadeModel = new osg::ShadeModel;
-    // FIXME: TRUE??
-    shadeModel->setMode(osg::ShadeModel::SMOOTH);
-    stateSet->setAttributeAndModes(shadeModel);
-
+    StateAttributeFactory* attribFactory = StateAttributeFactory::instance();
+    stateSet->setTextureAttribute(0, attribFactory->getStandardTexEnv());
+    stateSet->setAttributeAndModes(attribFactory->getSmoothShadeModel());
     stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
     stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
-
-//     osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
-//     alphaFunc->setFunction(osg::AlphaFunc::GREATER);
-//     alphaFunc->setReferenceValue(0.01);
-//     stateSet->setAttribute(alphaFunc);
-//     stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
-    stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
-
-    osg::BlendFunc* blendFunc = new osg::BlendFunc;
-    blendFunc->setSource(osg::BlendFunc::SRC_ALPHA);
-    blendFunc->setDestination(osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
-    stateSet->setAttribute(blendFunc);
-    stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+    stateSet->setAttributeAndModes(attribFactory->getStandardAlphaFunc());
+    stateSet->setAttributeAndModes(attribFactory->getStandardBlendFunc());
 
 //     osg::Material* material = new osg::Material;
 //     material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
@@ -160,11 +144,15 @@ SGCloudLayer::SGCloudLayer( const string &tex_path ) :
     last_lon(0.0),
     last_lat(0.0)
 {
+    // XXX
+    // Render bottoms before the rest of transparent objects (rendered
+    // in bin 10), tops after. The negative numbers on the bottoms
+    // RenderBins and the positive numbers on the tops enforce this
+    // order.
   layer_root->addChild(group_bottom.get());
   layer_root->addChild(group_top.get());
-  // Force the cloud layers into recursive bins of bin 4.
   osg::StateSet *rootSet = layer_root->getOrCreateStateSet();
-  rootSet->setRenderBinDetails(4, "RenderBin");
+  rootSet->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
   rootSet->setTextureAttribute(0, new osg::TexMat());
   base = osg::Vec2(sg_random(), sg_random());
 
@@ -869,10 +857,10 @@ bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
     // bottom polys should be drawn from high altitude to low, and the
     // top polygons from low to high. The altitude can be used
     // directly to order the polygons!
-    layer_root->getChild(0)->getStateSet()->setRenderBinDetails(-(int)layer_asl,
-                                                                "RenderBin");
-    layer_root->getChild(1)->getStateSet()->setRenderBinDetails((int)layer_asl,
-                                                                "RenderBin");
+    group_bottom->getStateSet()->setRenderBinDetails(-(int)layer_asl,
+                                                     "RenderBin");
+    group_top->getStateSet()->setRenderBinDetails((int)layer_asl,
+                                                  "RenderBin");
     if ( alt <= layer_asl ) {
       layer_root->setSingleChildOn(0);
     } else if ( alt >= layer_asl + layer_thickness ) {
index 8963b3be582b7fe083e7af099588f35e1074b1da..e5c9a19cd6504daa2d404c6f4b983efa9728efa0 100644 (file)
 #include <simgear/debug/logstream.hxx>
 #include <simgear/threads/SGThread.hxx>
 #include <simgear/threads/SGGuard.hxx>
+#include <simgear/scene/util/RenderConstants.hxx>
 #include <simgear/scene/util/SGEnlargeBoundingBox.hxx>
 
 #include "SGVasiDrawable.hxx"
 
+using namespace simgear;
+
 static void
 setPointSpriteImage(unsigned char* data, unsigned log2resolution,
                     unsigned charsPerPixel)
@@ -238,7 +241,7 @@ SGLightFactory::getLight(const SGLightBin::Light& light)
   geometry->addPrimitiveSet(drawArrays);
   
   osg::StateSet* stateSet = geometry->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(9, "DepthSortedBin");
+  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
   stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
   
   osg::BlendFunc* blendFunc = new osg::BlendFunc;
@@ -291,7 +294,7 @@ SGLightFactory::getLight(const SGDirectionalLightBin::Light& light)
   geometry->addPrimitiveSet(drawArrays);
   
   osg::StateSet* stateSet = geometry->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(9, "DepthSortedBin");
+  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
 
   osg::Material* material = new osg::Material;
   material->setColorMode(osg::Material::OFF);
@@ -352,7 +355,7 @@ SGLightFactory::getLights(const SGLightBin& lights, unsigned inc, float alphaOff
   geometry->addPrimitiveSet(drawArrays);
   
   osg::StateSet* stateSet = geometry->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(9, "DepthSortedBin");
+  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
 
   stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
   
@@ -407,7 +410,7 @@ SGLightFactory::getLights(const SGDirectionalLightBin& lights)
   geometry->addPrimitiveSet(drawArrays);
   
   osg::StateSet* stateSet = geometry->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(9, "DepthSortedBin");
+  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
 
   osg::Material* material = new osg::Material;
   material->setColorMode(osg::Material::OFF);
@@ -489,7 +492,7 @@ SGLightFactory::getVasi(const SGVec3f& up, const SGDirectionalLightBin& lights,
     return 0;
 
   osg::StateSet* stateSet = drawable->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(9, "DepthSortedBin");
+  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
   stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
 
   osg::BlendFunc* blendFunc = new osg::BlendFunc;
@@ -525,7 +528,7 @@ SGLightFactory::getSequenced(const SGDirectionalLightBin& lights)
   sequence->setSync(true);
 
   osg::StateSet* stateSet = sequence->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(9, "DepthSortedBin");
+  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
   stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
 
   osg::BlendFunc* blendFunc = new osg::BlendFunc;
@@ -577,7 +580,7 @@ SGLightFactory::getOdal(const SGLightBin& lights)
   sequence->setSync(true);
 
   osg::StateSet* stateSet = sequence->getOrCreateStateSet();
-  stateSet->setRenderBinDetails(9, "DepthSortedBin");
+  stateSet->setRenderBinDetails(POINT_LIGHTS_BIN, "DepthSortedBin");
   stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
 
   osg::BlendFunc* blendFunc = new osg::BlendFunc;
index b223228c52ecdafbd7bde692e8a8abfec9cc5a64..0bdba87f30867cbb44a39d045af2afc413a86893 100644 (file)
@@ -15,6 +15,7 @@ include_HEADERS = \
        SGStateAttributeVisitor.hxx \
        SGTextureStateAttributeVisitor.hxx \
        RenderConstants.hxx \
+       StateAttributeFactory.hxx \
        VectorArrayAdapter.hxx
 
 
@@ -23,6 +24,7 @@ libsgutil_a_SOURCES = \
        SGSceneFeatures.cxx \
        SGSceneUserData.cxx \
        SGStateAttributeVisitor.cxx \
-       SGTextureStateAttributeVisitor.cxx
+       SGTextureStateAttributeVisitor.cxx \
+       StateAttributeFactory.cxx
 
 INCLUDES = -I$(top_srcdir)
index 2cbd1d5bd39efa1fc41ec2c1c1fe25f698750282..54e4f0756d9cbd763dd94144fec8366478f251a6 100644 (file)
@@ -40,5 +40,26 @@ enum NodeMask {
     LIGHTS_BITS = (GROUNDLIGHTS0_BIT | GROUNDLIGHTS1_BIT | GROUNDLIGHTS2_BIT
                    | RUNWAYLIGHTS_BIT)
 };
+
+// Theory of bin numbering:
+//
+// Normal opaque objects are assigned bin 0.
+//
+// Point lights blend with the terrain to simulate attenuation but
+// should completely obscure any transparent geometry behind
+// them. Also, they should be visible through semi-transparent cloud
+// layers, so they are rendered before the cloud layers.
+//
+// Clouds layers can't be depth sorted because they are too big, so
+// they are rendered before other transparent objects. The layer
+// partial ordering is handled in the clouds code.
+//
+// OSG and its file loaders throw all transparent objects into bin 10.
+
+enum RenderBin {
+    POINT_LIGHTS_BIN = 8,
+    CLOUDS_BIN = 9,
+    TRANSPARENT_BIN = 10        // assigned by OSG
+};
 }
 #endif
diff --git a/simgear/scene/util/StateAttributeFactory.cxx b/simgear/scene/util/StateAttributeFactory.cxx
new file mode 100644 (file)
index 0000000..3071ef3
--- /dev/null
@@ -0,0 +1,40 @@
+#include <OpenThreads/ScopedLock>
+
+#include "StateAttributeFactory.hxx"
+
+using namespace osg;
+
+namespace simgear
+{
+StateAttributeFactory::StateAttributeFactory()
+{
+    _standardAlphaFunc = new AlphaFunc;
+    _standardAlphaFunc->setFunction(osg::AlphaFunc::GREATER);
+    _standardAlphaFunc->setReferenceValue(0.01);
+    _standardAlphaFunc->setDataVariance(Object::STATIC);
+    _smooth = new ShadeModel;
+    _smooth->setMode(ShadeModel::SMOOTH);
+    _smooth->setDataVariance(Object::STATIC);
+    _flat = new ShadeModel(ShadeModel::FLAT);
+    _flat->setDataVariance(Object::STATIC);
+    _standardBlendFunc = new BlendFunc;
+    _standardBlendFunc->setSource(BlendFunc::SRC_ALPHA);
+    _standardBlendFunc->setDestination(BlendFunc::ONE_MINUS_SRC_ALPHA);
+    _standardBlendFunc->setDataVariance(Object::STATIC);
+    _standardTexEnv = new TexEnv;
+    _standardTexEnv->setMode(TexEnv::MODULATE);
+    _standardTexEnv->setDataVariance(Object::STATIC);
+}
+
+osg::ref_ptr<StateAttributeFactory> StateAttributeFactory::_theInstance;
+OpenThreads::Mutex StateAttributeFactory::_instanceMutex;
+
+StateAttributeFactory* StateAttributeFactory::instance()
+{
+    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_instanceMutex);
+    if (!_theInstance.valid()) {
+        _theInstance = new StateAttributeFactory;
+    }
+    return _theInstance.get();
+}
+}
diff --git a/simgear/scene/util/StateAttributeFactory.hxx b/simgear/scene/util/StateAttributeFactory.hxx
new file mode 100644 (file)
index 0000000..f8192df
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef SIMGEAR_STATEATTRIBUTEFACTORY_HXX
+#define SIMGEAR_STATEATTRIBUTEFACTORY_HXX 1
+
+#include <OpenThreads/Mutex>
+#include <osg/ref_ptr>
+#include <osg/AlphaFunc>
+#include <osg/BlendFunc>
+#include <osg/ShadeModel>
+#include <osg/TexEnv>
+
+// Return read-only instances of common OSG state attributes.
+namespace simgear
+{
+class StateAttributeFactory : public osg::Referenced {
+public:
+    // Alpha test > .01
+    osg::AlphaFunc* getStandardAlphaFunc() { return _standardAlphaFunc.get(); }
+    // alpha source, 1 - alpha destination
+    osg::BlendFunc* getStandardBlendFunc() { return _standardBlendFunc.get(); }
+    // modulate
+    osg::TexEnv* getStandardTexEnv() { return _standardTexEnv.get(); }
+    osg::ShadeModel* getSmoothShadeModel() { return _smooth.get(); }
+    osg::ShadeModel* getFlatShadeModel() { return _flat.get(); }
+    static StateAttributeFactory* instance();
+protected:
+    StateAttributeFactory();
+    osg::ref_ptr<osg::AlphaFunc> _standardAlphaFunc;
+    osg::ref_ptr<osg::ShadeModel> _smooth;
+    osg::ref_ptr<osg::ShadeModel> _flat;
+    osg::ref_ptr<osg::BlendFunc> _standardBlendFunc;
+    osg::ref_ptr<osg::TexEnv> _standardTexEnv;
+    static osg::ref_ptr<StateAttributeFactory> _theInstance;
+    static OpenThreads::Mutex _instanceMutex;
+};
+}
+#endif