Moved the shadow creation code into a seperate CreateShadowedScene header and source,
and exposed just the basic createShadowedScene function in the header.
This commit is contained in:
@@ -1,95 +1,112 @@
|
||||
# Microsoft Developer Studio Project File - Name="Demo osgprerender" - Package Owner=<4>
|
||||
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
|
||||
|
||||
CFG=Demo osgprerender - Win32 Release
|
||||
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE NMAKE /f "osgprerender.mak".
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE NMAKE /f "osgprerender.mak" CFG="Demo osgprerender - Win32 Release"
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
|
||||
!MESSAGE
|
||||
|
||||
!MESSAGE "Demo osgprerender - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
|
||||
!MESSAGE "Demo osgprerender - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
|
||||
!MESSAGE
|
||||
|
||||
|
||||
|
||||
# Begin Project
|
||||
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
|
||||
# PROP Scc_ProjName ""
|
||||
|
||||
# PROP Scc_LocalPath ""
|
||||
|
||||
CPP=cl.exe
|
||||
|
||||
RSC=rc.exe
|
||||
|
||||
|
||||
|
||||
!IF "$(CFG)" == "Demo osgprerender - Win32 Release"
|
||||
|
||||
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
|
||||
# PROP BASE Output_Dir "Release"
|
||||
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
|
||||
# PROP BASE Target_Dir ""
|
||||
|
||||
# PROP Use_MFC 0
|
||||
|
||||
# PROP Use_Debug_Libraries 0
|
||||
|
||||
# PROP Output_Dir "Release"
|
||||
|
||||
# PROP Intermediate_Dir "Release"
|
||||
|
||||
# PROP Ignore_Export_Lib 0
|
||||
|
||||
# PROP Target_Dir ""
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
|
||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
|
||||
# ADD BASE RSC /l 0x809 /d "NDEBUG"
|
||||
|
||||
# ADD RSC /l 0x809 /d "NDEBUG"
|
||||
|
||||
BSC32=bscmake.exe
|
||||
# Microsoft Developer Studio Project File - Name="Demo osgshadowtexture" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=Demo osgshadowtexture - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "osgshadowtexture.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "osgshadowtexture.mak" CFG="Demo osgshadowtexture - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Demo osgshadowtexture - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Demo osgshadowtexture - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Demo osgshadowtexture - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x809 /d "NDEBUG"
|
||||
# ADD RSC /l 0x809 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgshadowtexture.exe" /libpath:"../../../lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "Demo osgshadowtexture - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /vd0 /GR /GX /Zi /Od /I "../../../include" /D "_CONSOLE" /D "_MBCS" /D "FL_DLL" /D "WIN32" /D "_DEBUG" /YX /FD /c
|
||||
# SUBTRACT CPP /Fr
|
||||
# ADD BASE RSC /l 0x809 /d "_DEBUG"
|
||||
# ADD RSC /l 0x809 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"../../../bin/osgshadowtextured.exe" /pdbtype:sept /libpath:"../../../lib"
|
||||
# SUBTRACT LINK32 /incremental:no
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Demo osgshadowtexture - Win32 Release"
|
||||
# Name "Demo osgshadowtexture - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\Demos\osgshadowtexture\osgshadowtexture.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\Demos\osgshadowtexture\CreateShadowedScene.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter ";h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Src\Demos\osgshadowtexture\CreateShadowedScene.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
|
||||
@@ -87,6 +87,13 @@ class SG_EXPORT Plane
|
||||
|
||||
inline bool valid() const { return _fv.valid(); }
|
||||
|
||||
inline bool operator == (const Plane& plane) const { return _fv==plane._fv; }
|
||||
inline bool operator != (const Plane& plane) const { return _fv!=plane._fv; }
|
||||
inline bool operator < (const Plane& plane) const { return _fv<plane._fv; }
|
||||
|
||||
inline float* ptr() { return _fv.ptr(); }
|
||||
inline const float* ptr() const { return _fv.ptr(); }
|
||||
|
||||
inline Vec4& asVec4() { return _fv; }
|
||||
|
||||
inline const Vec4& asVec4() const { return _fv; }
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#ifndef OSG_TEXGEN
|
||||
#define OSG_TEXGEN 1
|
||||
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Plane>
|
||||
#include <osg/StateAttribute>
|
||||
|
||||
namespace osg {
|
||||
@@ -92,9 +92,11 @@ class SG_EXPORT TexGen : public StateAttribute
|
||||
S, T, R, Q
|
||||
};
|
||||
|
||||
void setPlane(Coord which, const Vec4& plane);
|
||||
void setPlane(Coord which, const Plane& plane);
|
||||
|
||||
const Vec4& getPlane(Coord which) const;
|
||||
Plane& getPlane(Coord which);
|
||||
|
||||
const Plane& getPlane(Coord which) const;
|
||||
|
||||
protected :
|
||||
|
||||
@@ -103,7 +105,7 @@ class SG_EXPORT TexGen : public StateAttribute
|
||||
Mode _mode;
|
||||
|
||||
/// additional texgen coefficents for GL_OBJECT_PLANE or GL_EYE_PLANE,
|
||||
Vec4 _plane_s, _plane_t, _plane_r, _plane_q;
|
||||
Plane _plane_s, _plane_t, _plane_r, _plane_q;
|
||||
|
||||
};
|
||||
|
||||
|
||||
274
src/Demos/osgshadowtexture/CreateShadowedScene.cpp
Normal file
274
src/Demos/osgshadowtexture/CreateShadowedScene.cpp
Normal file
@@ -0,0 +1,274 @@
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TexGen>
|
||||
#include <osg/Material>
|
||||
#include <osg/LightSource>
|
||||
#include <osg/Geode>
|
||||
#include <osg/ShapeDrawable>
|
||||
|
||||
#include <osgUtil/CullVisitor>
|
||||
#include <osgUtil/RenderToTextureStage>
|
||||
|
||||
#include "CreateShadowedScene.h"
|
||||
|
||||
|
||||
|
||||
class CreateShadowTextureCullCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
|
||||
CreateShadowTextureCullCallback(osg::Node* shadower,const osg::Vec3& position, const osg::Vec4& ambientLightColor, unsigned int textureUnit):
|
||||
_shadower(shadower),
|
||||
_position(position),
|
||||
_ambientLightColor(ambientLightColor),
|
||||
_unit(textureUnit)
|
||||
{
|
||||
_texture = new osg::Texture2D;
|
||||
_texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
|
||||
_texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
|
||||
}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
|
||||
osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
|
||||
if (cullVisitor && (_texture.valid() && _shadower.valid()))
|
||||
{
|
||||
doPreRender(*node,*cullVisitor);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// must traverse the shadower
|
||||
traverse(node,nv);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv);
|
||||
|
||||
osg::ref_ptr<osg::Node> _shadower;
|
||||
osg::ref_ptr<osg::Texture2D> _texture;
|
||||
osg::Vec3 _position;
|
||||
osg::Vec4 _ambientLightColor;
|
||||
unsigned int _unit;
|
||||
|
||||
// we need this to get round the order dependance
|
||||
// of eye linear tex gen...
|
||||
class MyTexGen : public osg::TexGen
|
||||
{
|
||||
public:
|
||||
|
||||
void setMatrix(const osg::Matrix& matrix)
|
||||
{
|
||||
_matrix = matrix;
|
||||
}
|
||||
|
||||
virtual void apply(osg::State& state) const
|
||||
{
|
||||
glPushMatrix();
|
||||
glLoadMatrixf(_matrix.ptr());
|
||||
TexGen::apply(state);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
osg::Matrix _matrix;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
void CreateShadowTextureCullCallback::doPreRender(osg::Node& node, osgUtil::CullVisitor& cv)
|
||||
{
|
||||
|
||||
const osg::BoundingSphere& bs = _shadower->getBound();
|
||||
if (!bs.valid())
|
||||
{
|
||||
osg::notify(osg::WARN) << "bb invalid"<<_shadower.get()<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// create the render to texture stage.
|
||||
osg::ref_ptr<osgUtil::RenderToTextureStage> rtts = osgNew osgUtil::RenderToTextureStage;
|
||||
|
||||
// set up lighting.
|
||||
// currently ignore lights in the scene graph itself..
|
||||
// will do later.
|
||||
osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->_stage;
|
||||
|
||||
// set up the background color and clear mask.
|
||||
rtts->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,0.0f));
|
||||
rtts->setClearMask(previous_stage->getClearMask());
|
||||
|
||||
// set up to charge the same RenderStageLighting is the parent previous stage.
|
||||
rtts->setRenderStageLighting(previous_stage->getRenderStageLighting());
|
||||
|
||||
|
||||
// record the render bin, to be restored after creation
|
||||
// of the render to text
|
||||
osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin();
|
||||
|
||||
// set the current renderbin to be the newly created stage.
|
||||
cv.setCurrentRenderBin(rtts.get());
|
||||
|
||||
|
||||
float centerDistance = (_position-bs.center()).length();
|
||||
|
||||
float znear = centerDistance+bs.radius();
|
||||
float zfar = centerDistance-bs.radius();
|
||||
float zNearRatio = 0.001f;
|
||||
if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
|
||||
|
||||
|
||||
// 2:1 aspect ratio as per flag geomtry below.
|
||||
float top = (bs.radius()/centerDistance)*znear;
|
||||
float right = top;
|
||||
|
||||
// set up projection.
|
||||
osg::Matrix* projection = osgNew osg::Matrix;
|
||||
projection->makeFrustum(-right,right,-top,top,znear,zfar);
|
||||
|
||||
cv.pushProjectionMatrix(projection);
|
||||
|
||||
osg::Matrix* matrix = new osg::Matrix;
|
||||
matrix->makeLookAt(_position,bs.center(),osg::Vec3(0.0f,1.0f,0.0f));
|
||||
|
||||
|
||||
osg::Matrix MV = cv.getModelViewMatrix();
|
||||
|
||||
// compute the matrix which takes a vertex from local coords into tex coords
|
||||
// will use this later to specify osg::TexGen..
|
||||
osg::Matrix MVPT =
|
||||
*matrix *
|
||||
*projection *
|
||||
osg::Matrix::translate(1.0,1.0,1.0) *
|
||||
osg::Matrix::scale(0.5f,0.5f,0.5f);
|
||||
|
||||
cv.pushModelViewMatrix(matrix);
|
||||
|
||||
osg::ref_ptr<osg::StateSet> shadowState = osgNew osg::StateSet;
|
||||
|
||||
// make the material black for a shadow.
|
||||
osg::Material* material = new osg::Material;
|
||||
material->setAmbient(osg::Material::FRONT_AND_BACK,_ambientLightColor);
|
||||
material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
|
||||
material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
|
||||
material->setShininess(osg::Material::FRONT_AND_BACK,0.0f);
|
||||
shadowState->setAttribute(material,osg::StateAttribute::OVERRIDE);
|
||||
|
||||
cv.pushStateSet(shadowState.get());
|
||||
|
||||
{
|
||||
|
||||
// traverse the shadower
|
||||
_shadower->accept(cv);
|
||||
|
||||
}
|
||||
|
||||
cv.popStateSet();
|
||||
|
||||
// restore the previous model view matrix.
|
||||
cv.popModelViewMatrix();
|
||||
|
||||
|
||||
// restore the previous model view matrix.
|
||||
cv.popProjectionMatrix();
|
||||
|
||||
// restore the previous renderbin.
|
||||
cv.setCurrentRenderBin(previousRenderBin);
|
||||
|
||||
if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0)
|
||||
{
|
||||
// getting to this point means that all the shadower has been
|
||||
// culled by small feature culling or is beyond LOD ranges.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int height = 256;
|
||||
int width = 256;
|
||||
|
||||
|
||||
const osg::Viewport& viewport = *cv.getViewport();
|
||||
|
||||
// offset the impostor viewport from the center of the main window
|
||||
// viewport as often the edges of the viewport might be obscured by
|
||||
// other windows, which can cause image/reading writing problems.
|
||||
int center_x = viewport.x()+viewport.width()/2;
|
||||
int center_y = viewport.y()+viewport.height()/2;
|
||||
|
||||
osg::Viewport* new_viewport = new osg::Viewport;
|
||||
new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height);
|
||||
rtts->setViewport(new_viewport);
|
||||
|
||||
shadowState->setAttribute(new_viewport);
|
||||
|
||||
// and the render to texture stage to the current stages
|
||||
// dependancy list.
|
||||
cv.getCurrentRenderBin()->_stage->addToDependencyList(rtts.get());
|
||||
|
||||
// if one exist attach texture to the RenderToTextureStage.
|
||||
if (_texture.valid()) rtts->setTexture(_texture.get());
|
||||
|
||||
|
||||
// set up the stateset to decorate the shadower with the shadow texture
|
||||
// with the appropriate tex gen coords.
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
|
||||
|
||||
MyTexGen* texgen = new MyTexGen;
|
||||
texgen->setMatrix(MV);
|
||||
texgen->setMode(osg::TexGen::EYE_LINEAR);
|
||||
texgen->setPlane(osg::TexGen::S,osg::Plane(MVPT(0,0),MVPT(1,0),MVPT(2,0),MVPT(3,0)));
|
||||
texgen->setPlane(osg::TexGen::T,osg::Plane(MVPT(0,1),MVPT(1,1),MVPT(2,1),MVPT(3,1)));
|
||||
texgen->setPlane(osg::TexGen::R,osg::Plane(MVPT(0,2),MVPT(1,2),MVPT(2,2),MVPT(3,2)));
|
||||
texgen->setPlane(osg::TexGen::Q,osg::Plane(MVPT(0,3),MVPT(1,3),MVPT(2,3),MVPT(3,3)));
|
||||
|
||||
stateset->setTextureAttributeAndModes(_unit,_texture.get(),osg::StateAttribute::ON);
|
||||
stateset->setTextureAttribute(_unit,texgen);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
|
||||
|
||||
cv.pushStateSet(stateset);
|
||||
|
||||
// must traverse the shadower
|
||||
traverse(&node,&cv);
|
||||
|
||||
cv.popStateSet();
|
||||
|
||||
}
|
||||
|
||||
|
||||
// set up a light source with the shadower and shodower subgraphs below it
|
||||
// with the appropriate callbacks set up.
|
||||
osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const osg::Vec3& lightPosition,float radius,unsigned int textureUnit=1)
|
||||
{
|
||||
osg::LightSource* lightgroup = new osg::LightSource;
|
||||
|
||||
osg::Light* light = new osg::Light;
|
||||
light->setPosition(osg::Vec4(lightPosition,1.0f));
|
||||
light->setLightNum(0);
|
||||
|
||||
lightgroup->setLight(light);
|
||||
|
||||
osg::Vec4 ambientLightColor(0.1f,0.1f,0.1f,1.0f);
|
||||
|
||||
// add the shadower
|
||||
lightgroup->addChild(shadower);
|
||||
|
||||
// add the shadowed with the callback to generate the shadow texture.
|
||||
shadowed->setCullCallback(new CreateShadowTextureCullCallback(shadower,lightPosition,ambientLightColor,textureUnit));
|
||||
lightgroup->addChild(shadowed);
|
||||
|
||||
osg::Geode* lightgeode = new osg::Geode;
|
||||
lightgeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
lightgeode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(lightPosition,radius)));
|
||||
|
||||
lightgroup->addChild(lightgeode);
|
||||
|
||||
return lightgroup;
|
||||
}
|
||||
|
||||
12
src/Demos/osgshadowtexture/CreateShadowedScene.h
Normal file
12
src/Demos/osgshadowtexture/CreateShadowedScene.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef CREATESHADOWEDSCENE_H
|
||||
#define CREATESHADOWEDSCENE_H
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/Vec3>
|
||||
|
||||
// function to create a lightsource which contain a shadower and showed subgraph,
|
||||
// the showadowed subgrph has a cull callback to fire off a pre render to texture
|
||||
// of the shadowed subgraph.
|
||||
extern osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const osg::Vec3& lightPosition,float radius,unsigned int textureUnit=1);
|
||||
|
||||
#endif
|
||||
@@ -2,6 +2,7 @@ TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
CreateShadowedScene.cpp\
|
||||
osgshadowtexture.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
@@ -2,6 +2,7 @@ TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
CreateShadowedScene.cpp\
|
||||
osgshadowtexture.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS)
|
||||
|
||||
@@ -4,12 +4,8 @@
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/TexGen>
|
||||
#include <osg/Material>
|
||||
#include <osg/LightSource>
|
||||
|
||||
#include <osgUtil/Optimizer>
|
||||
#include <osgUtil/RenderToTextureStage>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
@@ -23,245 +19,15 @@
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
|
||||
// include the call which creates the shadowed subgraph.
|
||||
#include "CreateShadowedScene.h"
|
||||
|
||||
|
||||
// for the grid data..
|
||||
#include "../osghangglide/terrain_coords.h"
|
||||
|
||||
|
||||
|
||||
class CreateShadowTextureCullCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
|
||||
CreateShadowTextureCullCallback(osg::Node* shadower,const osg::Vec3& position, const osg::Vec4& ambientLightColor, unsigned int textureUnit):
|
||||
_shadower(shadower),
|
||||
_position(position),
|
||||
_ambientLightColor(ambientLightColor),
|
||||
_unit(textureUnit)
|
||||
{
|
||||
_texture = new osg::Texture2D;
|
||||
_texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
|
||||
_texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
|
||||
}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
|
||||
osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
|
||||
if (cullVisitor && (_texture.valid() && _shadower.valid()))
|
||||
{
|
||||
doPreRender(*node,*cullVisitor);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// must traverse the shadower
|
||||
traverse(node,nv);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv);
|
||||
|
||||
osg::ref_ptr<osg::Node> _shadower;
|
||||
osg::ref_ptr<osg::Texture2D> _texture;
|
||||
osg::Vec3 _position;
|
||||
osg::Vec4 _ambientLightColor;
|
||||
unsigned int _unit;
|
||||
|
||||
// we need this to get round the order dependance
|
||||
// of eye linear tex gen...
|
||||
class MyTexGen : public osg::TexGen
|
||||
{
|
||||
public:
|
||||
|
||||
void setMatrix(const osg::Matrix& matrix)
|
||||
{
|
||||
_matrix = matrix;
|
||||
}
|
||||
|
||||
virtual void apply(osg::State& state) const
|
||||
{
|
||||
glPushMatrix();
|
||||
glLoadMatrixf(_matrix.ptr());
|
||||
TexGen::apply(state);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
osg::Matrix _matrix;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
void CreateShadowTextureCullCallback::doPreRender(osg::Node& node, osgUtil::CullVisitor& cv)
|
||||
{
|
||||
|
||||
const osg::BoundingSphere& bs = _shadower->getBound();
|
||||
if (!bs.valid())
|
||||
{
|
||||
osg::notify(osg::WARN) << "bb invalid"<<_shadower.get()<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// create the render to texture stage.
|
||||
osg::ref_ptr<osgUtil::RenderToTextureStage> rtts = osgNew osgUtil::RenderToTextureStage;
|
||||
|
||||
// set up lighting.
|
||||
// currently ignore lights in the scene graph itself..
|
||||
// will do later.
|
||||
osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->_stage;
|
||||
|
||||
// set up the background color and clear mask.
|
||||
rtts->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,0.0f));
|
||||
rtts->setClearMask(previous_stage->getClearMask());
|
||||
|
||||
// set up to charge the same RenderStageLighting is the parent previous stage.
|
||||
rtts->setRenderStageLighting(previous_stage->getRenderStageLighting());
|
||||
|
||||
|
||||
// record the render bin, to be restored after creation
|
||||
// of the render to text
|
||||
osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin();
|
||||
|
||||
// set the current renderbin to be the newly created stage.
|
||||
cv.setCurrentRenderBin(rtts.get());
|
||||
|
||||
|
||||
float centerDistance = (_position-bs.center()).length();
|
||||
|
||||
float znear = centerDistance+bs.radius();
|
||||
float zfar = centerDistance-bs.radius();
|
||||
float zNearRatio = 0.001f;
|
||||
if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
|
||||
|
||||
|
||||
// 2:1 aspect ratio as per flag geomtry below.
|
||||
float top = (bs.radius()/centerDistance)*znear;
|
||||
float right = top;
|
||||
|
||||
// set up projection.
|
||||
osg::Matrix* projection = osgNew osg::Matrix;
|
||||
projection->makeFrustum(-right,right,-top,top,znear,zfar);
|
||||
|
||||
cv.pushProjectionMatrix(projection);
|
||||
|
||||
osg::Matrix* matrix = new osg::Matrix;
|
||||
matrix->makeLookAt(_position,bs.center(),osg::Vec3(0.0f,1.0f,0.0f));
|
||||
|
||||
|
||||
osg::Matrix MV = cv.getModelViewMatrix();
|
||||
|
||||
// compute the matrix which takes a vertex from local coords into tex coords
|
||||
// will use this later to specify osg::TexGen..
|
||||
osg::Matrix MVPT =
|
||||
*matrix *
|
||||
*projection *
|
||||
osg::Matrix::translate(1.0,1.0,1.0) *
|
||||
osg::Matrix::scale(0.5f,0.5f,0.5f);
|
||||
|
||||
cv.pushModelViewMatrix(matrix);
|
||||
|
||||
osg::ref_ptr<osg::StateSet> shadowState = osgNew osg::StateSet;
|
||||
|
||||
// make the material black for a shadow.
|
||||
osg::Material* material = new osg::Material;
|
||||
material->setAmbient(osg::Material::FRONT_AND_BACK,_ambientLightColor);
|
||||
material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
|
||||
material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f,0.0f,0.0f,1.0f));
|
||||
material->setShininess(osg::Material::FRONT_AND_BACK,0.0f);
|
||||
shadowState->setAttribute(material,osg::StateAttribute::OVERRIDE);
|
||||
|
||||
cv.pushStateSet(shadowState.get());
|
||||
|
||||
{
|
||||
|
||||
// traverse the shadower
|
||||
_shadower->accept(cv);
|
||||
|
||||
}
|
||||
|
||||
cv.popStateSet();
|
||||
|
||||
// restore the previous model view matrix.
|
||||
cv.popModelViewMatrix();
|
||||
|
||||
|
||||
// restore the previous model view matrix.
|
||||
cv.popProjectionMatrix();
|
||||
|
||||
// restore the previous renderbin.
|
||||
cv.setCurrentRenderBin(previousRenderBin);
|
||||
|
||||
if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0)
|
||||
{
|
||||
// getting to this point means that all the shadower has been
|
||||
// culled by small feature culling or is beyond LOD ranges.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int height = 256;
|
||||
int width = 256;
|
||||
|
||||
|
||||
const osg::Viewport& viewport = *cv.getViewport();
|
||||
|
||||
// offset the impostor viewport from the center of the main window
|
||||
// viewport as often the edges of the viewport might be obscured by
|
||||
// other windows, which can cause image/reading writing problems.
|
||||
int center_x = viewport.x()+viewport.width()/2;
|
||||
int center_y = viewport.y()+viewport.height()/2;
|
||||
|
||||
osg::Viewport* new_viewport = new osg::Viewport;
|
||||
new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height);
|
||||
rtts->setViewport(new_viewport);
|
||||
|
||||
shadowState->setAttribute(new_viewport);
|
||||
|
||||
// and the render to texture stage to the current stages
|
||||
// dependancy list.
|
||||
cv.getCurrentRenderBin()->_stage->addToDependencyList(rtts.get());
|
||||
|
||||
// if one exist attach texture to the RenderToTextureStage.
|
||||
if (_texture.valid()) rtts->setTexture(_texture.get());
|
||||
|
||||
|
||||
// set up the stateset to decorate the shadower with the shadow texture
|
||||
// with the appropriate tex gen coords.
|
||||
osg::StateSet* stateset = new osg::StateSet;
|
||||
|
||||
|
||||
MyTexGen* texgen = new MyTexGen;
|
||||
texgen->setMatrix(MV);
|
||||
texgen->setMode(osg::TexGen::EYE_LINEAR);
|
||||
texgen->setPlane(osg::TexGen::S,osg::Plane(MVPT(0,0),MVPT(1,0),MVPT(2,0),MVPT(3,0)));
|
||||
texgen->setPlane(osg::TexGen::T,osg::Plane(MVPT(0,1),MVPT(1,1),MVPT(2,1),MVPT(3,1)));
|
||||
texgen->setPlane(osg::TexGen::R,osg::Plane(MVPT(0,2),MVPT(1,2),MVPT(2,2),MVPT(3,2)));
|
||||
texgen->setPlane(osg::TexGen::Q,osg::Plane(MVPT(0,3),MVPT(1,3),MVPT(2,3),MVPT(3,3)));
|
||||
|
||||
stateset->setTextureAttributeAndModes(_unit,_texture.get(),osg::StateAttribute::ON);
|
||||
stateset->setTextureAttribute(_unit,texgen);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
|
||||
stateset->setTextureMode(_unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
|
||||
|
||||
cv.pushStateSet(stateset);
|
||||
|
||||
// must traverse the shadower
|
||||
traverse(&node,&cv);
|
||||
|
||||
cv.popStateSet();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
osg::AnimationPath* createAnimationPath(const osg::Vec3& center,float radius,double looptime)
|
||||
{
|
||||
// set up the animation path
|
||||
@@ -339,7 +105,6 @@ osg::Node* createBase(const osg::Vec3& center,float radius)
|
||||
grid->setHeight(c,r,(h+hieghtOffset)*hieghtScale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
geode->addDrawable(new osg::ShapeDrawable(grid));
|
||||
|
||||
@@ -357,27 +122,6 @@ osg::Node* createMovingModel(const osg::Vec3& center, float radius)
|
||||
osg::AnimationPath* animationPath = createAnimationPath(center,radius,animationLength);
|
||||
|
||||
osg::Group* model = new osg::Group;
|
||||
|
||||
// osg::Node* glider = osgDB::readNodeFile("glider.osg");
|
||||
// if (glider)
|
||||
// {
|
||||
// const osg::BoundingSphere& bs = glider->getBound();
|
||||
//
|
||||
// float size = radius/bs.radius()*0.3f;
|
||||
// osg::MatrixTransform* positioned = osgNew osg::MatrixTransform;
|
||||
// positioned->setDataVariance(osg::Object::STATIC);
|
||||
// positioned->setMatrix(osg::Matrix::translate(-bs.center())*
|
||||
// osg::Matrix::scale(size,size,size)*
|
||||
// osg::Matrix::rotate(osg::inDegrees(-90.0f),0.0f,0.0f,1.0f));
|
||||
//
|
||||
// positioned->addChild(glider);
|
||||
//
|
||||
// osg::PositionAttitudeTransform* xform = osgNew osg::PositionAttitudeTransform;
|
||||
// xform->setAppCallback(new osg::PositionAttitudeTransform::AnimationPathCallback(animationPath,0.0,1.0));
|
||||
// xform->addChild(positioned);
|
||||
//
|
||||
// model->addChild(xform);
|
||||
// }
|
||||
|
||||
osg::Node* cessna = osgDB::readNodeFile("cessna.osg");
|
||||
if (cessna)
|
||||
@@ -404,35 +148,6 @@ osg::Node* createMovingModel(const osg::Vec3& center, float radius)
|
||||
}
|
||||
|
||||
|
||||
// shadowed must be at least group right now as leaf nodes such as
|
||||
// osg::Geode don't get traversed so their cull callbacks don't get called.
|
||||
osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const osg::Vec3& lightPosition,float radius,unsigned int textureUnit=1)
|
||||
{
|
||||
osg::LightSource* lightgroup = new osg::LightSource;
|
||||
|
||||
osg::Light* light = new osg::Light;
|
||||
light->setPosition(osg::Vec4(lightPosition,1.0f));
|
||||
light->setLightNum(0);
|
||||
|
||||
lightgroup->setLight(light);
|
||||
|
||||
osg::Vec4 ambientLightColor(0.1f,0.1f,0.1f,1.0f);
|
||||
|
||||
// add the shadower
|
||||
lightgroup->addChild(shadower);
|
||||
|
||||
// add the shadowed with the callback to generate the shadow texture.
|
||||
shadowed->setCullCallback(new CreateShadowTextureCullCallback(shadower,lightPosition,ambientLightColor,textureUnit));
|
||||
lightgroup->addChild(shadowed);
|
||||
|
||||
osg::Geode* lightgeode = new osg::Geode;
|
||||
lightgeode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
||||
lightgeode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(lightPosition,radius)));
|
||||
|
||||
lightgroup->addChild(lightgeode);
|
||||
|
||||
return lightgroup;
|
||||
}
|
||||
|
||||
|
||||
osg::Node* createModel()
|
||||
@@ -484,17 +199,12 @@ int main( int argc, char **argv )
|
||||
return 1;
|
||||
}
|
||||
|
||||
// tilt the scene so the default eye position is looking down on the model.
|
||||
osg::MatrixTransform* rootnode = new osg::MatrixTransform;
|
||||
// rootnode->setMatrix(osg::Matrix::rotate(osg::inDegrees(30.0f),1.0f,0.0f,0.0f));
|
||||
rootnode->addChild(model);
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
// comment out optimization over the scene graph right now as it optimizers away the shadow... will look into this..
|
||||
//osgUtil::Optimizer optimzer;
|
||||
//optimzer.optimize(rootnode);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
viewer.addViewport( model );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgGA::TrackballManipulator);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <osg/Math>
|
||||
|
||||
// for the grid data..
|
||||
#include "../osghangglide/terrain_coords.h"
|
||||
|
||||
osg::Geode* createShapes()
|
||||
@@ -19,11 +20,10 @@ osg::Geode* createShapes()
|
||||
osg::Geode* geode = osgNew osg::Geode();
|
||||
|
||||
// ---------------------------------------
|
||||
// Set up a StateSet to make the cube red
|
||||
// Set up a StateSet to texture the objects
|
||||
// ---------------------------------------
|
||||
osg::StateSet* stateset = osgNew osg::StateSet();
|
||||
|
||||
|
||||
osg::Image* image = osgDB::readImageFile("Images/lz.rgb");
|
||||
if (image)
|
||||
{
|
||||
|
||||
@@ -111,7 +111,7 @@ class ConstructStateCallback : public osg::NodeCallback
|
||||
osg::TexGen* texgen = dynamic_cast<osg::TexGen*>(attribute);
|
||||
if (texgen)
|
||||
{
|
||||
texgen->setPlane(osg::TexGen::R, texgen->getPlane(osg::TexGen::R)+osg::Vec4(0.0f,0.0f,0.0f,0.001f));
|
||||
texgen->getPlane(osg::TexGen::R)[3] += 0.001f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ TexGen::~TexGen()
|
||||
}
|
||||
|
||||
|
||||
void TexGen::setPlane(Coord which, const Vec4& plane)
|
||||
void TexGen::setPlane(Coord which, const Plane& plane)
|
||||
{
|
||||
switch( which )
|
||||
{
|
||||
@@ -30,8 +30,19 @@ void TexGen::setPlane(Coord which, const Vec4& plane)
|
||||
}
|
||||
}
|
||||
|
||||
const Plane& TexGen::getPlane(Coord which) const
|
||||
{
|
||||
switch( which )
|
||||
{
|
||||
case S : return _plane_s;
|
||||
case T : return _plane_t;
|
||||
case R : return _plane_r;
|
||||
case Q : return _plane_q;
|
||||
default : notify(WARN)<<"Error: invalid 'which' passed TexGen::getPlane(which)"<<std::endl; return _plane_r;
|
||||
}
|
||||
}
|
||||
|
||||
const Vec4& TexGen::getPlane(Coord which) const
|
||||
Plane& TexGen::getPlane(Coord which)
|
||||
{
|
||||
switch( which )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user