From 4324ffccf4bdcf34f8f8bd2f03d408fb6c958ed0 Mon Sep 17 00:00:00 2001 From: timoore Date: Fri, 21 Dec 2007 06:24:53 +0000 Subject: [PATCH] Fix cloud layer - point lights visibility issue 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 | 46 ++++++++------------ simgear/scene/tgdb/pt_lights.cxx | 17 +++++--- simgear/scene/util/Makefile.am | 4 +- simgear/scene/util/RenderConstants.hxx | 21 +++++++++ simgear/scene/util/StateAttributeFactory.cxx | 40 +++++++++++++++++ simgear/scene/util/StateAttributeFactory.hxx | 36 +++++++++++++++ 6 files changed, 127 insertions(+), 37 deletions(-) create mode 100644 simgear/scene/util/StateAttributeFactory.cxx create mode 100644 simgear/scene/util/StateAttributeFactory.hxx diff --git a/simgear/scene/sky/cloud.cxx b/simgear/scene/sky/cloud.cxx index 34361cd9..0b532fd0 100644 --- a/simgear/scene/sky/cloud.cxx +++ b/simgear/scene/sky/cloud.cxx @@ -45,6 +45,8 @@ #include #include #include +#include +#include #include #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 ) { diff --git a/simgear/scene/tgdb/pt_lights.cxx b/simgear/scene/tgdb/pt_lights.cxx index 8963b3be..e5c9a19c 100644 --- a/simgear/scene/tgdb/pt_lights.cxx +++ b/simgear/scene/tgdb/pt_lights.cxx @@ -54,10 +54,13 @@ #include #include #include +#include #include #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; diff --git a/simgear/scene/util/Makefile.am b/simgear/scene/util/Makefile.am index b223228c..0bdba87f 100644 --- a/simgear/scene/util/Makefile.am +++ b/simgear/scene/util/Makefile.am @@ -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) diff --git a/simgear/scene/util/RenderConstants.hxx b/simgear/scene/util/RenderConstants.hxx index 2cbd1d5b..54e4f075 100644 --- a/simgear/scene/util/RenderConstants.hxx +++ b/simgear/scene/util/RenderConstants.hxx @@ -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 index 00000000..3071ef3e --- /dev/null +++ b/simgear/scene/util/StateAttributeFactory.cxx @@ -0,0 +1,40 @@ +#include + +#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::_theInstance; +OpenThreads::Mutex StateAttributeFactory::_instanceMutex; + +StateAttributeFactory* StateAttributeFactory::instance() +{ + OpenThreads::ScopedLock 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 index 00000000..f8192df9 --- /dev/null +++ b/simgear/scene/util/StateAttributeFactory.hxx @@ -0,0 +1,36 @@ +#ifndef SIMGEAR_STATEATTRIBUTEFACTORY_HXX +#define SIMGEAR_STATEATTRIBUTEFACTORY_HXX 1 + +#include +#include +#include +#include +#include +#include + +// 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 _standardAlphaFunc; + osg::ref_ptr _smooth; + osg::ref_ptr _flat; + osg::ref_ptr _standardBlendFunc; + osg::ref_ptr _standardTexEnv; + static osg::ref_ptr _theInstance; + static OpenThreads::Mutex _instanceMutex; +}; +} +#endif -- 2.39.5