Modified Files:

simgear/scene/model/animation.hxx
	simgear/scene/model/shadanim.cxx: Tim Moore: the crom shader.
This commit is contained in:
frohlich 2007-05-03 19:46:13 +00:00
parent d645fd6327
commit 2dc8de295d
2 changed files with 102 additions and 1 deletions

View File

@ -359,6 +359,7 @@ public:
virtual osg::Group* createAnimationGroup(osg::Group& parent);
private:
class UpdateCallback;
osg::ref_ptr<osg::Texture2D> _effect_texture;
};

View File

@ -24,6 +24,8 @@
# include <simgear_config.h>
#endif
#include <map>
#include <osg/Group>
#include <osg/Program>
#include <osg/Shader>
@ -179,6 +181,102 @@ SGShaderAnimation::SGShaderAnimation(const SGPropertyNode* configNode,
SGPropertyNode* modelRoot) :
SGAnimation(configNode, modelRoot)
{
const SGPropertyNode* node = configNode->getChild("texture");
if (node)
_effect_texture = SGLoadTexture2D(node->getStringValue());
}
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 = (updateVisitor->getAmbientLight().osg() * .4f
+ updateVisitor->getDiffuseLight().osg());
globalColor.a() = 1.0f;
combine->setConstantColor(globalColor);
}
};
typedef map<osg::ref_ptr<osg::Texture2D>, osg::ref_ptr<osg::StateSet> >
StateSetMap;
}
// 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)
{
static SGMutex mutex;
SGGuard<SGMutex> locker(mutex);
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*
@ -195,8 +293,10 @@ SGShaderAnimation::createAnimationGroup(osg::Group& parent)
// _shader_type = 2;
// else
if( shader_name == "chrome")
#if 0
create_specular_highlights(group);
#endif
create_chrome(group, _effect_texture.get());
return group;
}