# include <simgear_config.h>
#endif
+#include <map>
+
#include <osg/Group>
#include <osg/Program>
#include <osg/Shader>
#include <osg/Texture1D>
#include <osgUtil/HighlightMapGenerator>
+#include <OpenThreads/Mutex>
+#include <OpenThreads/ScopedLock>
+
#include <simgear/scene/util/SGUpdateVisitor.hxx>
-#include <simgear/threads/SGThread.hxx>
-#include <simgear/threads/SGGuard.hxx>
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx>
#include "animation.hxx"
#include "model.hxx"
+
+using OpenThreads::Mutex;
+using OpenThreads::ScopedLock;
+
/*
<animation>
<type>shader</type>
// FIXME: need an update or callback ...
// generate the six highlight map images (light direction = [1, 1, -1])
osg::ref_ptr<osgUtil::HighlightMapGenerator> mapgen;
- mapgen = new osgUtil::HighlightMapGenerator(_lastLightDirection.osg(),
- _lastLightColor.osg(), 5);
+ mapgen = new osgUtil::HighlightMapGenerator(toOsg(_lastLightDirection),
+ toOsg(_lastLightColor), 5);
mapgen->generateMap();
// assign the six images to the texture object
SGVec4f _lastLightColor;
};
+static Mutex cubeMutex;
+
+#if 0
static osg::TextureCubeMap*
getOrCreateTextureCubeMap()
{
- static osg::TextureCubeMap* textureCubeMap = 0;
- if (textureCubeMap)
- return textureCubeMap;
+ static osg::ref_ptr<osg::TextureCubeMap> textureCubeMap;
+ if (textureCubeMap.get())
+ return textureCubeMap.get();
- static SGMutex mutex;
- SGGuard<SGMutex> locker(mutex);
- if (textureCubeMap)
- return textureCubeMap;
+ ScopedLock<Mutex> lock(cubeMutex);
+ if (textureCubeMap.get())
+ return textureCubeMap.get();
// create and setup the texture object
textureCubeMap = new osg::TextureCubeMap;
textureCubeMap->setUpdateCallback(new SGMapGenCallback);
- return textureCubeMap;
+ return textureCubeMap.get();
}
static void create_specular_highlights(osg::Node *node)
te->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
ss->setTextureAttributeAndModes(0, te, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
}
+#endif
SGShaderAnimation::SGShaderAnimation(const SGPropertyNode* configNode,
- SGPropertyNode* modelRoot) :
+ SGPropertyNode* modelRoot,
+ const osgDB::ReaderWriter::Options*
+ options) :
SGAnimation(configNode, modelRoot)
{
+ const SGPropertyNode* node = configNode->getChild("texture");
+ if (node)
+ _effect_texture = SGLoadTexture2D(node->getStringValue(), options);
+}
+
+namespace {
+class ChromeLightingCallback :
+ public osg::StateAttribute::Callback {
+public:
+ virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
+ {
+ SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
+ if (!updateVisitor)
+ return;
+ osg::TexEnvCombine *combine = dynamic_cast<osg::TexEnvCombine *>(sa);
+ if (!combine)
+ return;
+ // An approximation for light reflected back by chrome.
+ osg::Vec4 globalColor = toOsg(updateVisitor->getAmbientLight() * .4f
+ + updateVisitor->getDiffuseLight());
+ globalColor.a() = 1.0f;
+ combine->setConstantColor(globalColor);
+ }
+};
+
+typedef std::map<osg::ref_ptr<osg::Texture2D>, osg::ref_ptr<osg::StateSet> >
+StateSetMap;
+}
+
+static Mutex chromeMutex;
+
+// The chrome effect is mixed by the alpha channel of the texture
+// on the model, which will be attached to a node lower in the scene
+// graph: 0 -> completely chrome, 1 -> completely model texture.
+static void create_chrome(osg::Group* group, osg::Texture2D* texture)
+{
+ ScopedLock<Mutex> lock(chromeMutex);
+ static StateSetMap chromeMap;
+ osg::StateSet *stateSet;
+ StateSetMap::iterator iterator = chromeMap.find(texture);
+ if (iterator != chromeMap.end()) {
+ stateSet = iterator->second.get();
+ } else {
+ stateSet = new osg::StateSet;
+ // If the model doesn't have any texture, we need to have one
+ // activated so that we don't need a seperate combiner
+ // attribute for the non-textured case. This texture will be
+ // shadowed by any attached to the model.
+ osg::Image *dummyImage = new osg::Image;
+ dummyImage->allocateImage(1, 1, 1, GL_LUMINANCE_ALPHA,
+ GL_UNSIGNED_BYTE);
+ unsigned char* imageBytes = dummyImage->data(0, 0);
+ imageBytes[0] = 255;
+ imageBytes[1] = 0;
+ osg::Texture2D* dummyTexture = new osg::Texture2D;
+ dummyTexture->setImage(dummyImage);
+ dummyTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
+ dummyTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
+ stateSet->setTextureAttributeAndModes(0, dummyTexture,
+ osg::StateAttribute::ON);
+ osg::TexEnvCombine* combine0 = new osg::TexEnvCombine;
+ osg::TexEnvCombine* combine1 = new osg::TexEnvCombine;
+ osg::TexGen* texGen = new osg::TexGen;
+ // Mix the environmental light color and the chrome map on texture
+ // unit 0
+ combine0->setCombine_RGB(osg::TexEnvCombine::MODULATE);
+ combine0->setSource0_RGB(osg::TexEnvCombine::CONSTANT);
+ combine0->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
+ combine0->setSource1_RGB(osg::TexEnvCombine::TEXTURE1);
+ combine0->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
+ combine0->setDataVariance(osg::Object::DYNAMIC);
+ combine0->setUpdateCallback(new ChromeLightingCallback);
+
+ // Interpolate the colored chrome map with the texture on the
+ // model, using the model texture's alpha.
+ combine1->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
+ combine1->setSource0_RGB(osg::TexEnvCombine::TEXTURE0);
+ combine1->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
+ combine1->setSource1_RGB(osg::TexEnvCombine::PREVIOUS);
+ combine1->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
+ combine1->setSource2_RGB(osg::TexEnvCombine::TEXTURE0);
+ combine1->setOperand2_RGB(osg::TexEnvCombine::SRC_ALPHA);
+ // Are these used for anything?
+ combine1->setCombine_Alpha(osg::TexEnvCombine::REPLACE);
+ combine1->setSource0_Alpha(osg::TexEnvCombine::TEXTURE1);
+ combine1->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);
+
+ texGen->setMode(osg::TexGen::SPHERE_MAP);
+ stateSet->setTextureAttribute(0, combine0);
+ stateSet->setTextureAttribute(1, combine1);
+ stateSet->setTextureAttributeAndModes(1, texture,
+ osg::StateAttribute::ON);
+ stateSet->setTextureAttributeAndModes(1, texGen,
+ osg::StateAttribute::ON);
+ chromeMap[texture] = stateSet;
+ }
+ group->setStateSet(stateSet);
}
osg::Group*
// _shader_type = 2;
// else
if( shader_name == "chrome")
+#if 0
create_specular_highlights(group);
-
+#endif
+ create_chrome(group, _effect_texture.get());
return group;
}