Ported all the render to texture examples across to using the new osg::CameraNode.

Added support for texture cube maps in FBO + CameraNode.
This commit is contained in:
Robert Osfield
2005-07-19 16:30:55 +00:00
parent 5c9bd792a3
commit 8dd013171c
23 changed files with 786 additions and 709 deletions

View File

@@ -8,7 +8,7 @@
#include <osg/ShapeDrawable>
#include <osg/PolygonOffset>
#include <osg/CullFace>
#include <osg/TexEnvCombine>
#include <osg/Texture2D>
#include <osg/MatrixTransform>
#include <osg/Light>
#include <osg/LightSource>
@@ -17,18 +17,12 @@
#include <osg/Material>
#include <osgUtil/TransformCallback>
#include <osgUtil/RenderToTextureStage>
#include <osg/CameraNode>
#include <osg/TexGenNode>
using namespace osg;
const int depth_texture_height = 512;
const int depth_texture_width = 512;
ref_ptr<RefMatrix> bias = new RefMatrix(0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f);
class LightTransformCallback: public osg::NodeCallback
{
@@ -91,152 +85,8 @@ LightTransformCallback::operator()(Node* node, NodeVisitor* nv)
}
class RenderToTextureCallback: public NodeCallback
{
public:
RenderToTextureCallback(Node* subgraph,
Texture2D* texture,
MatrixTransform* light_transform,
TexGen* tex_gen):
_subgraph(subgraph),
_texture(texture),
_local_stateset(new StateSet),
_viewport(new Viewport),
_light_projection(new RefMatrix),
_light_transform(light_transform),
_tex_gen(tex_gen)
{
_local_stateset->setAttribute(_viewport.get());
_local_stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
ref_ptr<PolygonOffset> polygon_offset = new PolygonOffset;
polygon_offset->setFactor(1.1f);
polygon_offset->setUnits(4.0f);
_local_stateset->setAttribute(polygon_offset.get(), StateAttribute::ON | StateAttribute::OVERRIDE);
_local_stateset->setMode(GL_POLYGON_OFFSET_FILL, StateAttribute::ON | StateAttribute::OVERRIDE);
ref_ptr<CullFace> cull_face = new CullFace;
cull_face->setMode(CullFace::FRONT);
_local_stateset->setAttribute(cull_face.get(), StateAttribute::ON | StateAttribute::OVERRIDE);
_local_stateset->setMode(GL_CULL_FACE, StateAttribute::ON | StateAttribute::OVERRIDE);
_viewport->setViewport(0, 0, depth_texture_width, depth_texture_height);
float znear = 1.0f * _subgraph->getBound().radius();
float zfar = 3.0f * _subgraph->getBound().radius();
float top = 0.5f * _subgraph->getBound().radius();
float right = 0.5f * _subgraph->getBound().radius();
znear *= 0.8f;
zfar *= 1.2f;
_light_projection->makeFrustum(-right, right, -top, top, znear, zfar);
}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
osgUtil::CullVisitor* cullVisitor = dynamic_cast<osgUtil::CullVisitor*>(nv);
if (cullVisitor && _texture.valid() && _subgraph.valid())
{
_request_render_to_depth_texture(*node, *cullVisitor);
}
// must traverse the subgraph
traverse(node,nv);
}
void _request_render_to_depth_texture(osg::Node& node, osgUtil::CullVisitor& cv);
ref_ptr<osg::Node> _subgraph;
ref_ptr<osg::Texture2D> _texture;
ref_ptr<osg::StateSet> _local_stateset;
ref_ptr<osg::Viewport> _viewport;
ref_ptr<RefMatrix> _light_projection;
ref_ptr<MatrixTransform> _light_transform;
ref_ptr<TexGen> _tex_gen;
};
void RenderToTextureCallback::_request_render_to_depth_texture(osg::Node&, osgUtil::CullVisitor& cv)
{
// create the render to texture stage.
osg::ref_ptr<osgUtil::RenderToTextureStage> rtts = new osgUtil::RenderToTextureStage;
// set up lighting.
// currently ignore lights in the scene graph itself..
// will do later.
osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->getStage();
// set up the background color and clear mask.
rtts->setClearMask(GL_DEPTH_BUFFER_BIT);
rtts->setColorMask(new ColorMask(false, false, false, false));
// 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();
osgUtil::CullVisitor::ComputeNearFarMode saved_compute_near_far_mode = cv.getComputeNearFarMode();
cv.setComputeNearFarMode(osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR);
// set the current renderbin to be the newly created stage.
cv.setCurrentRenderBin(rtts.get());
ref_ptr<RefMatrix> light_view = new RefMatrix;
light_view->makeLookAt(_light_transform->getMatrix().getTrans(), Vec3(0, 0, 0), Z_AXIS);
Matrix texture_matrix = (*light_view.get()) * (*_light_projection.get()) * (*bias.get());
_tex_gen->setPlane(TexGen::S, Vec4(texture_matrix(0, 0),
texture_matrix(1, 0),
texture_matrix(2, 0),
texture_matrix(3, 0)));
_tex_gen->setPlane(TexGen::T, Vec4(texture_matrix(0, 1),
texture_matrix(1, 1),
texture_matrix(2, 1),
texture_matrix(3, 1)));
_tex_gen->setPlane(TexGen::R, Vec4(texture_matrix(0, 2),
texture_matrix(1, 2),
texture_matrix(2, 2),
texture_matrix(3, 2)));
_tex_gen->setPlane(TexGen::Q, Vec4(texture_matrix(0, 3),
texture_matrix(1, 3),
texture_matrix(2, 3),
texture_matrix(3, 3)));
cv.pushProjectionMatrix(_light_projection.get());
cv.pushModelViewMatrix(light_view.get());
cv.pushStateSet(_local_stateset.get());
// traverse the subgraph
_subgraph->accept(cv);
cv.popStateSet();
cv.popModelViewMatrix();
cv.popProjectionMatrix();
cv.setComputeNearFarMode(saved_compute_near_far_mode);
// restore the previous renderbin.
cv.setCurrentRenderBin(previousRenderBin);
if (rtts->getRenderGraphList().size()==0 && rtts->getRenderBinList().size()==0)
{
// getting to this point means that all the subgraph has been
// culled by small feature culling or is beyond LOD ranges.
return;
}
rtts->setViewport(_viewport.get());
// and the render to texture stage to the current stages
// dependancy list.
cv.getCurrentRenderBin()->getStage()->addToDependencyList(rtts.get());
// if one exist attach texture to the RenderToTextureStage.
rtts->setTexture(_texture.get());
}
ref_ptr<MatrixTransform> _create_lights(ref_ptr<StateSet> root_stateset)
ref_ptr<MatrixTransform> _create_lights()
{
ref_ptr<MatrixTransform> transform_0 = new MatrixTransform;
@@ -256,6 +106,7 @@ ref_ptr<MatrixTransform> _create_lights(ref_ptr<StateSet> root_stateset)
transform_0->addChild(light_source_0.get());
ref_ptr<Geode> geode = new Geode;
ref_ptr<ShapeDrawable> shape;
ref_ptr<TessellationHints> hints = new TessellationHints;
hints->setDetailRatio(0.3f);
@@ -265,11 +116,11 @@ ref_ptr<MatrixTransform> _create_lights(ref_ptr<StateSet> root_stateset)
shape = new ShapeDrawable(new Cylinder(Vec3(0.0f, 0.0f, -0.4f), 0.05f, 0.8f), hints.get());
shape->setColor(Vec4(1.0f, 0.5f, 0.5f, 1.0f));
geode->addDrawable(shape.get());
geode->getOrCreateStateSet()->setMode(GL_LIGHTING, StateAttribute::OFF);
transform_0->addChild(geode.get());
light_source_0->setStateSetModes(*root_stateset.get(), StateAttribute::ON);
return transform_0;
}
@@ -336,72 +187,220 @@ ref_ptr<Group> _create_scene()
return scene;
}
class UpdateCameraAndTexGenCallback : public osg::NodeCallback
{
public:
UpdateCameraAndTexGenCallback(osg::MatrixTransform* light_transform, osg::CameraNode* cameraNode, osg::TexGenNode* texgenNode):
_light_transform(light_transform),
_cameraNode(cameraNode),
_texgenNode(texgenNode)
{
}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
// first update subgraph to make sure objects are all moved into postion
traverse(node,nv);
// now compute the camera's view and projection matrix to point at the shadower (the camera's children)
osg::BoundingSphere bs;
for(unsigned int i=0; i<_cameraNode->getNumChildren(); ++i)
{
bs.expandBy(_cameraNode->getChild(i)->getBound());
}
if (!bs.valid())
{
osg::notify(osg::WARN) << "bb invalid"<<_cameraNode.get()<<std::endl;
return;
}
osg::Vec3 position = _light_transform->getMatrix().getTrans();
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;
float top = (bs.radius()/centerDistance)*znear;
float right = top;
_cameraNode->setReferenceFrame(osg::CameraNode::ABSOLUTE_RF);
_cameraNode->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar);
_cameraNode->setViewMatrixAsLookAt(position,bs.center(),osg::Vec3(0.0f,1.0f,0.0f));
// compute the matrix which takes a vertex from local coords into tex coords
// will use this later to specify osg::TexGen..
osg::Matrix MVPT = _cameraNode->getViewMatrix() *
_cameraNode->getProjectionMatrix() *
osg::Matrix::translate(1.0,1.0,1.0) *
osg::Matrix::scale(0.5f,0.5f,0.5f);
_texgenNode->getTexGen()->setMode(osg::TexGen::EYE_LINEAR);
_texgenNode->getTexGen()->setPlanesFromMatrix(MVPT);
}
protected:
virtual ~UpdateCameraAndTexGenCallback() {}
osg::ref_ptr<osg::MatrixTransform> _light_transform;
osg::ref_ptr<osg::CameraNode> _cameraNode;
osg::ref_ptr<osg::TexGenNode> _texgenNode;
};
osg::Group* createShadowedScene(osg::Node* shadowed,osg::MatrixTransform* light_transform, unsigned int unit)
{
osg::Group* group = new osg::Group;
unsigned int tex_width = 1024;
unsigned int tex_height = 1024;
osg::Texture2D* texture = new osg::Texture2D;
texture->setTextureSize(tex_width, tex_height);
texture->setInternalFormat(GL_DEPTH_COMPONENT);
texture->setShadowComparison(true);
texture->setShadowTextureMode(Texture::LUMINANCE);
texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
// set up the render to texture camera.
{
// create the camera
osg::CameraNode* camera = new osg::CameraNode;
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
camera->setComputeNearFarMode(osg::CameraNode::DO_NOT_COMPUTE_NEAR_FAR);
// set viewport
camera->setViewport(0,0,tex_width,tex_height);
osg::StateSet* _local_stateset = camera->getOrCreateStateSet();
_local_stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
ref_ptr<PolygonOffset> polygon_offset = new PolygonOffset;
polygon_offset->setFactor(1.1f);
polygon_offset->setUnits(4.0f);
_local_stateset->setAttribute(polygon_offset.get(), StateAttribute::ON | StateAttribute::OVERRIDE);
_local_stateset->setMode(GL_POLYGON_OFFSET_FILL, StateAttribute::ON | StateAttribute::OVERRIDE);
ref_ptr<CullFace> cull_face = new CullFace;
cull_face->setMode(CullFace::FRONT);
_local_stateset->setAttribute(cull_face.get(), StateAttribute::ON | StateAttribute::OVERRIDE);
_local_stateset->setMode(GL_CULL_FACE, StateAttribute::ON | StateAttribute::OVERRIDE);
// set the camera to render before the main camera.
camera->setRenderOrder(osg::CameraNode::PRE_RENDER);
// tell the camera to use OpenGL frame buffer object where supported.
camera->setRenderTargetImplmentation(osg::CameraNode::FRAME_BUFFER_OBJECT);
// attach the texture and use it as the color buffer.
camera->attach(osg::CameraNode::DEPTH_BUFFER, texture);
// add subgraph to render
camera->addChild(shadowed);
group->addChild(camera);
// create the texgen node to project the tex coords onto the subgraph
osg::TexGenNode* texgenNode = new osg::TexGenNode;
texgenNode->setTextureUnit(unit);
group->addChild(texgenNode);
// set an update callback to keep moving the camera and tex gen in the right direction.
group->setUpdateCallback(new UpdateCameraAndTexGenCallback(light_transform, camera, texgenNode));
}
// set the shadowed subgraph so that it uses the texture and tex gen settings.
{
osg::Group* shadowedGroup = new osg::Group;
shadowedGroup->addChild(shadowed);
group->addChild(shadowedGroup);
osg::StateSet* stateset = shadowedGroup->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON);
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);
}
// add the shadower and shadowed.
group->addChild(light_transform);
return group;
}
int main(int argc, char** argv)
{
// use an ArgumentParser object to manage the program arguments.
ArgumentParser arguments(&argc, argv);
// use an ArgumentParser object to manage the program arguments.
ArgumentParser arguments(&argc, argv);
// set up the usage document, in case we need to print out how to use this program.
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates using of GL_ARB_shadow extension implemented in osg::Texture class");
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName());
arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information");
// construct the viewer.
osgProducer::Viewer viewer(arguments);
// set up the usage document, in case we need to print out how to use this program.
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates using of GL_ARB_shadow extension implemented in osg::Texture class");
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName());
arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information");
// set up the value with sensible default event handlers.
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
// get details on keyboard and mouse bindings used by the viewer.
viewer.getUsage(*arguments. getApplicationUsage());
// construct the viewer.
osgProducer::Viewer viewer(arguments);
// if user request help write it out to cout.
if (arguments.read("-h") || arguments.read("--help"))
// set up the value with sensible default event handlers.
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
// get details on keyboard and mouse bindings used by the viewer.
viewer.getUsage(*arguments. getApplicationUsage());
// if user request help write it out to cout.
if (arguments.read("-h") || arguments.read("--help"))
{
arguments.getApplicationUsage()->write(std::cout);
return 1;
arguments.getApplicationUsage()->write(std::cout);
return 1;
}
// any option left unread are converted into errors to write out later.
arguments.reportRemainingOptionsAsUnrecognized();
// any option left unread are converted into errors to write out later.
arguments.reportRemainingOptionsAsUnrecognized();
// report any errors if they have occured when parsing the program aguments.
if (arguments.errors())
// report any errors if they have occured when parsing the program aguments.
if (arguments.errors())
{
arguments.writeErrorMessages(std::cout);
return 1;
}
ref_ptr<MatrixTransform> scene = new MatrixTransform;
scene->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(125.0),1.0,0.0,0.0));
ref_ptr<Group> shadowed_scene = _create_scene();
if (!shadowed_scene.valid()) return 1;
scene->addChild(shadowed_scene.get());
ref_ptr<MatrixTransform> scene = new MatrixTransform;
scene->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(125.0),1.0,0.0,0.0));
ref_ptr<MatrixTransform> light_transform = _create_lights(scene->getOrCreateStateSet());
if (!scene.valid()) return 1;
scene->addChild(light_transform.get());
ref_ptr<Group> shadowed_scene = _create_scene();
if (!shadowed_scene.valid()) return 1;
ref_ptr<Texture2D> texture = new Texture2D;
texture->setInternalFormat(GL_DEPTH_COMPONENT);
texture->setShadowComparison(true);
texture->setShadowTextureMode(Texture::LUMINANCE);
ref_ptr<MatrixTransform> light_transform = _create_lights();
if (!light_transform.valid()) return 1;
ref_ptr<TexGen> tex_gen = new TexGen;
tex_gen->setMode(TexGen::EYE_LINEAR);
shadowed_scene->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture.get(), StateAttribute::ON);
shadowed_scene->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex_gen.get(), StateAttribute::ON);
ref_ptr<Group> shadowedScene = createShadowedScene(shadowed_scene.get(),light_transform.get(),0);
scene->setCullCallback(new RenderToTextureCallback(shadowed_scene.get(), texture.get(), light_transform.get(), tex_gen.get()));
scene->addChild(shadowedScene.get());
// add model to viewer.
viewer.setSceneData(scene.get());
viewer.setSceneData(scene.get());
// create the windows and run the threads.
viewer.realize();
// create the windows and run the threads.
viewer.realize();
while (!viewer.done())
while (!viewer.done())
{
// wait for all cull and draw threads to complete.
viewer.sync();
@@ -414,8 +413,8 @@ int main(int argc, char** argv)
viewer.frame();
}
// wait for all cull and draw threads to complete before exit.
viewer.sync();
// wait for all cull and draw threads to complete before exit.
viewer.sync();
return 0;
return 0;
}

View File

@@ -25,7 +25,7 @@
using namespace osg;
osg::Node* createDistortionSubgraph(osg::Node* subgraph)
osg::Node* createDistortionSubgraph(osg::Node* subgraph, const osg::Vec4& clearColour)
{
osg::Group* distortionNode = new osg::Group;
@@ -42,6 +42,10 @@ osg::Node* createDistortionSubgraph(osg::Node* subgraph)
{
osg::CameraNode* camera = new osg::CameraNode;
// set clear the color and depth buffer
camera->setClearColor(clearColour);
camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// just inherit the main cameras view
camera->setReferenceFrame(osg::Transform::RELATIVE_RF);
camera->setProjectionMatrix(osg::Matrixd::identity());
@@ -49,7 +53,6 @@ osg::Node* createDistortionSubgraph(osg::Node* subgraph)
// set viewport
camera->setViewport(0,0,tex_width,tex_height);
camera->getOrCreateStateSet()->setAttribute(camera->getViewport());
// set the camera to render before the main camera.
camera->setRenderOrder(osg::CameraNode::PRE_RENDER);
@@ -219,7 +222,7 @@ int main( int argc, char **argv )
return 1;
}
osg::Node* distortionNode = createDistortionSubgraph(loadedModel);
osg::Node* distortionNode = createDistortionSubgraph(loadedModel, viewer.getClearColor());
// add model to the viewer.
viewer.setSceneData( distortionNode );

View File

@@ -76,7 +76,6 @@ void build_world(osg::Group *root)
camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
camera->setViewport(0, 0, width, height);
camera->getOrCreateStateSet()->setAttribute(camera->getViewport());
// set the camera to render before the main camera.
camera->setRenderOrder(osg::CameraNode::PRE_RENDER);

View File

@@ -1028,8 +1028,8 @@ osg::Node* ForestTechniqueManager::createScene(unsigned int numTreesToCreates)
osg::Program* program = new osg::Program;
stateset->setAttribute(program);
osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource);
program->addShader(vertex_shader);
//osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource);
//program->addShader(vertex_shader);
osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource);
program->addShader(fragment_shader);

View File

@@ -23,38 +23,43 @@
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>
#include <osg/CameraNode>
#include <osg/FrontFace>
#include <osgText/Text>
osg::Node* createRearView(osg::Node* subgraph)
osg::Node* createRearView(osg::Node* subgraph, const osg::Vec4& clearColour)
{
osg::CameraNode* camera = new osg::CameraNode;
// set the projection matrix
camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
// set the viewport
camera->setViewport(420,800,400,200);
camera->getOrCreateStateSet()->setAttribute(camera->getViewport());
// set the view matrix
camera->setCullingActive(false);
camera->setReferenceFrame(osg::Transform::RELATIVE_RF);
camera->setTransformOrder(osg::CameraNode::POST_MULTIPLE);
camera->setProjectionMatrix(osg::Matrixd::identity());
camera->setProjectionMatrix(osg::Matrixd::scale(-1.0f,1.0f,1.0f));
camera->setViewMatrix(osg::Matrixd::rotate(osg::inDegrees(180.0f),0.0f,1.0f,0.0f));
// only clear the depth buffer
// set clear the color and depth buffer
camera->setClearColor(clearColour);
camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// draw subgraph after main camera view.
camera->setRenderOrder(osg::CameraNode::POST_RENDER);
// add the subgraph to draw.
camera->addChild(subgraph);
// switch of back face culling as we've swapped over the projection matrix making back faces become front faces.
#if 1
camera->getOrCreateStateSet()->setAttribute(new osg::FrontFace(osg::FrontFace::CLOCKWISE));
#else
camera->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
#endif
return camera;
}
@@ -103,7 +108,7 @@ int main( int argc, char **argv )
// add the HUD subgraph.
if (scene.valid()) group->addChild(scene.get());
group->addChild(createRearView(scene.get()));
group->addChild(createRearView(scene.get(), viewer.getClearColor()));
// set the scene to render
viewer.setSceneData(group.get());

View File

@@ -122,6 +122,9 @@ int main( int argc, char **argv )
// get details on keyboard and mouse bindings used by the viewer.
viewer.getUsage(*arguments.getApplicationUsage());
bool shader = false;
while (arguments.read("--shader")) shader = true;
// if user request help write it out to cout.
if (arguments.read("-h") || arguments.read("--help"))
{
@@ -196,6 +199,42 @@ int main( int argc, char **argv )
// register the handler for modifying the point size
viewer.getEventHandlerList().push_front(new KeyboardEventHandler(viewer.getGlobalStateSet()));
if (shader)
{
osg::StateSet* stateset = loadedModel->getOrCreateStateSet();
///////////////////////////////////////////////////////////////////
// vertex shader using just Vec4 coefficients
char vertexShaderSource[] =
"void main(void) \n"
"{ \n"
"\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
"}\n";
//////////////////////////////////////////////////////////////////
// fragment shader
//
char fragmentShaderSource[] =
"void main(void) \n"
"{ \n"
" gl_FragColor = gl_Color; \n"
"}\n";
osg::Program* program = new osg::Program;
stateset->setAttribute(program);
osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource);
program->addShader(vertex_shader);
//osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource);
//program->addShader(fragment_shader);
}
// create the windows and run the threads.
viewer.realize();

View File

@@ -213,13 +213,11 @@ osg::Node* createPreRenderSubGraph(osg::Node* subgraph)
// set view
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrixAsLookAt(bs.center()+osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f));
camera->setViewMatrixAsLookAt(bs.center()-osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f));
// set viewport
camera->setViewport(0,0,tex_width,tex_height);
camera->getOrCreateStateSet()->setAttribute(camera->getViewport());
// set the camera to render before the main camera.
camera->setRenderOrder(osg::CameraNode::PRE_RENDER);

View File

@@ -1,420 +1,282 @@
#include <osg/GLExtensions>
#include <osg/Group>
#include <osg/Geode>
#include <osg/Matrix>
#include <osg/Quat>
#include <osg/StateSet>
#include <osg/TextureCubeMap>
#include <osg/TexGen>
#include <osg/TexMat>
#include <osg/TexEnvCombine>
#include <osg/ShapeDrawable>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osgUtil/RenderToTextureStage>
#include <osgUtil/Optimizer>
#include <osgUtil/TransformCallback>
#include <osgDB/ReadFile>
#include <osgDB/Registry>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgProducer/Viewer>
#include <iostream>
#include <string>
#include <vector>
#include <osg/Projection>
#include <osg/Geometry>
#include <osg/Texture>
#include <osg/TexGen>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/PolygonOffset>
#include <osg/CullFace>
#include <osg/TextureCubeMap>
#include <osg/TexMat>
#include <osg/MatrixTransform>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/PolygonOffset>
#include <osg/CullFace>
#include <osg/Material>
#include <osg/RefNodePath>
#define UPDATE_ONE_IMAGE_PER_FRAME 1
#include <osgUtil/TransformCallback>
#include <osg/CameraNode>
#include <osg/TexGenNode>
using namespace osg;
class PrerenderAppCallback : public osg::NodeCallback
ref_ptr<Group> _create_scene()
{
ref_ptr<Group> scene = new Group;
ref_ptr<Geode> geode_1 = new Geode;
scene->addChild(geode_1.get());
ref_ptr<Geode> geode_2 = new Geode;
ref_ptr<MatrixTransform> transform_2 = new MatrixTransform;
transform_2->addChild(geode_2.get());
transform_2->setUpdateCallback(new osgUtil::TransformCallback(Vec3(0, 0, 0), Y_AXIS, inDegrees(45.0f)));
scene->addChild(transform_2.get());
ref_ptr<Geode> geode_3 = new Geode;
ref_ptr<MatrixTransform> transform_3 = new MatrixTransform;
transform_3->addChild(geode_3.get());
transform_3->setUpdateCallback(new osgUtil::TransformCallback(Vec3(0, 0, 0), Y_AXIS, inDegrees(-22.5f)));
scene->addChild(transform_3.get());
const float radius = 0.8f;
const float height = 1.0f;
ref_ptr<TessellationHints> hints = new TessellationHints;
hints->setDetailRatio(2.0f);
ref_ptr<ShapeDrawable> shape;
shape = new ShapeDrawable(new Box(Vec3(0.0f, -2.0f, 0.0f), 10, 0.1f, 10), hints.get());
shape->setColor(Vec4(0.5f, 0.5f, 0.7f, 1.0f));
geode_1->addDrawable(shape.get());
shape = new ShapeDrawable(new Sphere(Vec3(-3.0f, 0.0f, 0.0f), radius), hints.get());
shape->setColor(Vec4(0.6f, 0.8f, 0.8f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new ShapeDrawable(new Box(Vec3(3.0f, 0.0f, 0.0f), 2 * radius), hints.get());
shape->setColor(Vec4(0.4f, 0.9f, 0.3f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new ShapeDrawable(new Cone(Vec3(0.0f, 0.0f, -3.0f), radius, height), hints.get());
shape->setColor(Vec4(0.2f, 0.5f, 0.7f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new ShapeDrawable(new Cylinder(Vec3(0.0f, 0.0f, 3.0f), radius, height), hints.get());
shape->setColor(Vec4(1.0f, 0.3f, 0.3f, 1.0f));
geode_2->addDrawable(shape.get());
shape = new ShapeDrawable(new Box(Vec3(0.0f, 3.0f, 0.0f), 2, 0.1f, 2), hints.get());
shape->setColor(Vec4(0.8f, 0.8f, 0.4f, 1.0f));
geode_3->addDrawable(shape.get());
// material
ref_ptr<Material> matirial = new Material;
matirial->setColorMode(Material::DIFFUSE);
matirial->setAmbient(Material::FRONT_AND_BACK, Vec4(0, 0, 0, 1));
matirial->setSpecular(Material::FRONT_AND_BACK, Vec4(1, 1, 1, 1));
matirial->setShininess(Material::FRONT_AND_BACK, 64.0f);
scene->getOrCreateStateSet()->setAttributeAndModes(matirial.get(), StateAttribute::ON);
return scene;
}
osg::RefNodePath createReflector()
{
ref_ptr<Group> scene = new Group;
ref_ptr<Geode> geode_1 = new Geode;
scene->addChild(geode_1.get());
const float radius = 0.8f;
ref_ptr<TessellationHints> hints = new TessellationHints;
hints->setDetailRatio(2.0f);
ref_ptr<ShapeDrawable> shape = new ShapeDrawable(new Sphere(Vec3(0.0f, 0.0f, 0.0f), radius * 1.5f), hints.get());
shape->setColor(Vec4(0.8f, 0.8f, 0.8f, 1.0f));
geode_1->addDrawable(shape.get());
osg::RefNodePath refNodeList;
refNodeList.push_back(scene.get());
refNodeList.push_back(geode_1.get());
return refNodeList;
}
class UpdateCameraAndTexGenCallback : public osg::NodeCallback
{
public:
PrerenderAppCallback(osg::Node* subgraph):
_subgraph(subgraph) {}
typedef std::vector< osg::ref_ptr<osg::CameraNode> > CameraList;
UpdateCameraAndTexGenCallback(osg::RefNodePath& reflectorNodePath, CameraList& cameraNodes):
_reflectorNodePath(reflectorNodePath),
_cameraNodes(cameraNodes)
{
}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
// traverse the subgraph to update any nodes.
if (_subgraph.valid()) _subgraph->accept(*nv);
// must traverse the Node's subgraph
// first update subgraph to make sure objects are all moved into postion
traverse(node,nv);
// compute the position of the center of the reflector subgraph
osg::Matrixd matrix = osg::computeLocalToWorld(_reflectorNodePath);
osg::BoundingSphere bs = _reflectorNodePath.back()->getBound();
osg::Vec3 position = bs.center() * matrix;
typedef std::pair<osg::Vec3, osg::Vec3> ImageData;
const ImageData id[] =
{
ImageData( osg::Vec3( 1, 0, 0), osg::Vec3( 0, -1, 0) ), // +X
ImageData( osg::Vec3(-1, 0, 0), osg::Vec3( 0, -1, 0) ), // -X
ImageData( osg::Vec3( 0, 1, 0), osg::Vec3( 0, 0, 1) ), // +Y
ImageData( osg::Vec3( 0, -1, 0), osg::Vec3( 0, 0, -1) ), // -Y
ImageData( osg::Vec3( 0, 0, 1), osg::Vec3( 0, -1, 0) ), // +Z
ImageData( osg::Vec3( 0, 0, -1), osg::Vec3( 0, -1, 0) ) // -Z
};
for(unsigned int i=0;
i<6 && i<_cameraNodes.size();
++i)
{
_cameraNodes[i]->setReferenceFrame(osg::CameraNode::ABSOLUTE_RF);
_cameraNodes[i]->setProjectionMatrixAsFrustum(-1.0,1.0,-1.0,1.0,1.0,10000.0);
_cameraNodes[i]->setViewMatrixAsLookAt(position,position+id[i].first,id[i].second);
}
}
osg::ref_ptr<osg::Node> _subgraph;
protected:
virtual ~UpdateCameraAndTexGenCallback() {}
osg::RefNodePath _reflectorNodePath;
CameraList _cameraNodes;
};
class PrerenderCullCallback : public osg::NodeCallback
class TexMatCullCallback : public osg::NodeCallback
{
public:
PrerenderCullCallback(osg::Node* subgraph, osg::TextureCubeMap* cubemap, osg::TexMat* texmat):
_subgraph(subgraph),
_cubemap(cubemap),
TexMatCullCallback(osg::TexMat* texmat):
_texmat(texmat)
{
_updateCubemapFace = 0;
_clearColor = osg::Vec4(1,1,1,1);
_localState[0] = new osg::StateSet;
_localState[1] = new osg::StateSet;
_localState[2] = new osg::StateSet;
_localState[3] = new osg::StateSet;
_localState[4] = new osg::StateSet;
_localState[5] = new osg::StateSet;
}
{
}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
// Reset this counter to zero, otherwise it wont do the while loop down below.
// And the cubemap will never update the newer frames.
if (_updateCubemapFace > 5)
_updateCubemapFace = 0;
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
if (cv && _cubemap.valid() && _subgraph.valid())
{
const osg::Vec4 clearColArray[] =
{
osg::Vec4(0, 0, 1, 1), // +X
osg::Vec4(1, 0.7f, 0, 1), // -X
osg::Vec4(0, 1, 1, 1), // +Y
osg::Vec4(1, 1, 0, 1), // -Y
osg::Vec4(1, 0, 0, 1), // +Z
osg::Vec4(0, 1, 0, 1) // -Z
};
osg::Quat q;
cv->getModelViewMatrix().get(q);
const osg::Matrix C = osg::Matrix::rotate( q.inverse() );
_texmat->setMatrix(C);
#if UPDATE_ONE_IMAGE_PER_FRAME
if ((_updateCubemapFace >= 0) && (_updateCubemapFace <= 5))
{
_clearColor = clearColArray[_updateCubemapFace];
doPreRender(*node, *cv, _updateCubemapFace++);
}
#else
while (_updateCubemapFace<6)
{
_clearColor = clearColArray[_updateCubemapFace];
doPreRender(*node, *cv, _updateCubemapFace++);
}
#endif
}
// must traverse the subgraph
// first update subgraph to make sure objects are all moved into postion
traverse(node,nv);
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
if (cv)
{
osg::Quat quat;
cv->getModelViewMatrix().get(quat);
_texmat->setMatrix(osg::Matrix::rotate(quat.inverse()));
}
}
void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv, const int nFace);
struct ImageData
{
ImageData(const osg::Vec3& dir, const osg::Vec3& up) : _dir(dir), _up(up) {}
osg::Vec3 _dir;
osg::Vec3 _up;
};
osg::ref_ptr<osg::Node> _subgraph;
osg::ref_ptr<osg::TextureCubeMap> _cubemap;
osg::ref_ptr<osg::StateSet> _localState[6];
osg::ref_ptr<osg::TexMat> _texmat;
osg::Vec4 _clearColor;
int _updateCubemapFace;
protected:
osg::ref_ptr<TexMat> _texmat;
};
void PrerenderCullCallback::doPreRender(osg::Node& /*node*/, osgUtil::CullVisitor& cv, const int nFace)
osg::Group* createShadowedScene(osg::Node* reflectedSubgraph, osg::RefNodePath reflectorNodePath, unsigned int unit, const osg::Vec4& clearColor)
{
const ImageData id[] =
osg::Group* group = new osg::Group;
unsigned int tex_width = 512;
unsigned int tex_height = 512;
osg::TextureCubeMap* texture = new osg::TextureCubeMap;
texture->setTextureSize(tex_width, tex_height);
texture->setInternalFormat(GL_RGB);
texture->setFilter(osg::TextureCubeMap::MIN_FILTER,osg::TextureCubeMap::LINEAR);
texture->setFilter(osg::TextureCubeMap::MAG_FILTER,osg::TextureCubeMap::LINEAR);
// set up the render to texture cameras.
UpdateCameraAndTexGenCallback::CameraList cameraNodes;
for(unsigned int i=0; i<6; ++i)
{
ImageData( osg::Vec3( 1, 0, 0), osg::Vec3( 0, -1, 0) ), // +X
ImageData( osg::Vec3(-1, 0, 0), osg::Vec3( 0, -1, 0) ), // -X
ImageData( osg::Vec3( 0, 1, 0), osg::Vec3( 0, 0, 1) ), // +Y
ImageData( osg::Vec3( 0, -1, 0), osg::Vec3( 0, 0, -1) ), // -Y
ImageData( osg::Vec3( 0, 0, 1), osg::Vec3( 0, -1, 0) ), // +Z
ImageData( osg::Vec3( 0, 0, -1), osg::Vec3( 0, -1, 0) ) // -Z
};
osg::Image* image = _cubemap->getImage((osg::TextureCubeMap::Face)nFace);
osg::Vec3 dir = id[nFace]._dir;
osg::Vec3 up = id[nFace]._up;
// create the camera
osg::CameraNode* camera = new osg::CameraNode;
const osg::BoundingSphere& bs = _subgraph->getBound();
if (!bs.valid())
{
osg::notify(osg::WARN) << "bb invalid"<<_subgraph.get()<<std::endl;
return;
}
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
camera->setClearColor(clearColor);
// create the render to texture stage.
osg::ref_ptr<osgUtil::RenderToTextureStage> rtts = new osgUtil::RenderToTextureStage;
// set viewport
camera->setViewport(0,0,tex_width,tex_height);
// set up lighting.
// currently ignore lights in the scene graph itself..
// will do later.
osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->getStage();
// set the camera to render before the main camera.
camera->setRenderOrder(osg::CameraNode::PRE_RENDER);
// set up the background color and clear mask.
rtts->setClearColor(_clearColor);
// tell the camera to use OpenGL frame buffer object where supported.
camera->setRenderTargetImplmentation(osg::CameraNode::FRAME_BUFFER_OBJECT);
// ABJ: use default (color+depth)
rtts->setClearMask(previous_stage->getClearMask());
// attach the texture and use it as the color buffer.
camera->attach(osg::CameraNode::COLOR_BUFFER, texture, 0, i);
// 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 znear = 1.0f*bs.radius();
float zfar = 3.0f*bs.radius();
// add subgraph to render
camera->addChild(reflectedSubgraph);
znear *= 0.9f;
zfar *= 1.1f;
// set up projection.
const double fovy = 90.0;
const double aspectRatio = 1.0;
osg::RefMatrix* projection = new osg::RefMatrix;
projection->makePerspective(fovy, aspectRatio, znear, zfar);
cv.pushProjectionMatrix(projection);
osg::RefMatrix* matrix = new osg::RefMatrix;
osg::Vec3 eye = bs.center(); eye.z() = 0.0f;
osg::Vec3 center = eye + dir;
matrix->makeLookAt(eye, center, up);
cv.pushModelViewMatrix(matrix);
cv.pushStateSet(_localState[nFace].get());
{
// traverse the subgraph
_subgraph->accept(cv);
group->addChild(camera);
cameraNodes.push_back(camera);
}
// create the texgen node to project the tex coords onto the subgraph
osg::TexGenNode* texgenNode = new osg::TexGenNode;
texgenNode->getTexGen()->setMode(osg::TexGen::REFLECTION_MAP);
texgenNode->setTextureUnit(unit);
group->addChild(texgenNode);
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->getRenderGraphList().size()==0 && rtts->getRenderBinList().size()==0)
// set the reflected subgraph so that it uses the texture and tex gen settings.
{
// getting to this point means that all the subgraph has been
// culled by small feature culling or is beyond LOD ranges.
return;
osg::Node* reflectorNode = reflectorNodePath.front().get();
group->addChild(reflectorNode);
osg::StateSet* stateset = reflectorNode->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON);
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);
osg::TexMat* texmat = new osg::TexMat;
stateset->setTextureAttributeAndModes(unit,texmat,osg::StateAttribute::ON);
reflectorNode->setCullCallback(new TexMatCullCallback(texmat));
}
int height = 512;
int width = 512;
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);
_localState[nFace]->setAttribute(new_viewport);
// add the reflector scene to draw just as normal
group->addChild(reflectedSubgraph);
// set an update callback to keep moving the camera and tex gen in the right direction.
group->setUpdateCallback(new UpdateCameraAndTexGenCallback(reflectorNodePath, cameraNodes));
// and the render to texture stage to the current stages
// dependancy list.
cv.getCurrentRenderBin()->getStage()->addToDependencyList(rtts.get());
// if one exist attach image to the RenderToTextureStage.
// if (image.valid()) rtts->setImage(_image.get());
if (image) rtts->setImage(image);
return group;
}
osg::Drawable* makeGeometry()
{
const float radius = 20;
return new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius));
}
osg::Node* createPreRenderSubGraph(osg::Node* subgraph)
{
if (!subgraph) return 0;
// create the quad to visualize.
osg::Drawable* geom = makeGeometry();
geom->setSupportsDisplayList(false);
// new we need to add the texture to the Drawable, we do so by creating a
// StateSet to contain the Texture StateAttribute.
osg::StateSet* stateset = new osg::StateSet;
osg::TextureCubeMap* cubemap = new osg::TextureCubeMap;
// set up the textures
osg::Image* imagePosX = new osg::Image;
osg::Image* imageNegX = new osg::Image;
osg::Image* imagePosY = new osg::Image;
osg::Image* imageNegY = new osg::Image;
osg::Image* imagePosZ = new osg::Image;
osg::Image* imageNegZ = new osg::Image;
imagePosX->setInternalTextureFormat(GL_RGB);
imageNegX->setInternalTextureFormat(GL_RGB);
imagePosY->setInternalTextureFormat(GL_RGB);
imageNegY->setInternalTextureFormat(GL_RGB);
imagePosZ->setInternalTextureFormat(GL_RGB);
imageNegZ->setInternalTextureFormat(GL_RGB);
cubemap->setImage(osg::TextureCubeMap::POSITIVE_X, imagePosX);
cubemap->setImage(osg::TextureCubeMap::NEGATIVE_X, imageNegX);
cubemap->setImage(osg::TextureCubeMap::POSITIVE_Y, imagePosY);
cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Y, imageNegY);
cubemap->setImage(osg::TextureCubeMap::POSITIVE_Z, imagePosZ);
cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Z, imageNegZ);
cubemap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
cubemap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
cubemap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE);
cubemap->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
cubemap->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
stateset->setTextureAttributeAndModes(0, cubemap, osg::StateAttribute::ON);
osg::TexGen *texgen = new osg::TexGen;
texgen->setMode(osg::TexGen::REFLECTION_MAP);
stateset->setTextureAttributeAndModes(0, texgen, osg::StateAttribute::ON);
osg::TexMat* texmat = new osg::TexMat;
stateset->setTextureAttribute(0, texmat);
stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
geom->setStateSet(stateset);
osg::Geode* geode = new osg::Geode;
geode->addDrawable(geom);
// Geodes can't have cull callback so create extra Group to attach cullcallback.
osg::Group* parent = new osg::Group;
parent->setUpdateCallback(new PrerenderAppCallback(subgraph));
parent->setCullCallback(new PrerenderCullCallback(subgraph, cubemap, texmat));
parent->addChild(geode);
return parent;
}
struct DrawableCullCallback : public osg::Drawable::CullCallback
{
DrawableCullCallback(osg::TexMat* texmat) : _texmat(texmat)
{}
virtual bool cull(osg::NodeVisitor* nv, osg::Drawable* /*drawable*/, osg::State* /*state*/) const
{
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
if (cv)
{
osg::Quat q;
cv->getModelViewMatrix().get(q);
const osg::Matrix C = osg::Matrix::rotate( q.inverse() );
_texmat->setMatrix(C);
}
return false;
}
mutable osg::ref_ptr<osg::TexMat> _texmat;
};
osg::Node* createReferenceSphere()
{
const float radius = 10;
osg::Drawable* sphere = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius));
osg::StateSet* stateset = new osg::StateSet;
sphere->setStateSet(stateset);
osg::TextureCubeMap* cubemap = new osg::TextureCubeMap;
#define CUBEMAP_FILENAME(face) "Cubemap_axis/" #face ".png"
osg::Image* imagePosX = osgDB::readImageFile(CUBEMAP_FILENAME(posx));
osg::Image* imageNegX = osgDB::readImageFile(CUBEMAP_FILENAME(negx));
osg::Image* imagePosY = osgDB::readImageFile(CUBEMAP_FILENAME(posy));
osg::Image* imageNegY = osgDB::readImageFile(CUBEMAP_FILENAME(negy));
osg::Image* imagePosZ = osgDB::readImageFile(CUBEMAP_FILENAME(posz));
osg::Image* imageNegZ = osgDB::readImageFile(CUBEMAP_FILENAME(negz));
if (imagePosX && imageNegX && imagePosY && imageNegY && imagePosZ && imageNegZ)
{
cubemap->setImage(osg::TextureCubeMap::POSITIVE_X, imagePosX);
cubemap->setImage(osg::TextureCubeMap::NEGATIVE_X, imageNegX);
cubemap->setImage(osg::TextureCubeMap::POSITIVE_Y, imagePosY);
cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Y, imageNegY);
cubemap->setImage(osg::TextureCubeMap::POSITIVE_Z, imagePosZ);
cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Z, imageNegZ);
cubemap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
cubemap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
cubemap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE);
cubemap->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
cubemap->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
stateset->setTextureAttributeAndModes(0, cubemap, osg::StateAttribute::ON);
}
osg::TexGen *texgen = new osg::TexGen;
texgen->setMode(osg::TexGen::REFLECTION_MAP);
stateset->setTextureAttributeAndModes(0, texgen, osg::StateAttribute::ON);
osg::TexMat* texmat = new osg::TexMat;
stateset->setTextureAttribute(0, texmat);
stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
sphere->setCullCallback(new DrawableCullCallback(texmat));
osg::Geode* geode = new osg::Geode();
geode->addDrawable(sphere);
return geode;
}
int main( int argc, char **argv )
int main(int argc, char** argv)
{
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
ArgumentParser arguments(&argc, argv);
// set up the usage document, in case we need to print out how to use this program.
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates pre rendering of scene to a texture, and then apply this texture to geometry.");
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates using of GL_ARB_shadow extension implemented in osg::Texture class");
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName());
arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information");
// construct the viewer.
osgProducer::Viewer viewer(arguments);
@@ -422,7 +284,7 @@ int main( int argc, char **argv )
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
// get details on keyboard and mouse bindings used by the viewer.
viewer.getUsage(*arguments.getApplicationUsage());
viewer.getUsage(*arguments. getApplicationUsage());
// if user request help write it out to cout.
if (arguments.read("-h") || arguments.read("--help"))
@@ -437,72 +299,36 @@ int main( int argc, char **argv )
// report any errors if they have occured when parsing the program aguments.
if (arguments.errors())
{
arguments.writeErrorMessages(std::cout);
return 1;
arguments.writeErrorMessages(std::cout);
return 1;
}
/*
if (arguments.argc()<=1)
{
arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
return 1;
}
*/
osg::Group* rootNode = new osg::Group();
#if 1
osg::Node* sky = osgDB::readNodeFile("skydome.osg");
ref_ptr<MatrixTransform> scene = new MatrixTransform;
scene->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(125.0),1.0,0.0,0.0));
// Proof of concept to see if the skydome really rotates and that the cubemap gets updated.
// create a transform to spin the model.
osg::MatrixTransform* loadedModelTransform = new osg::MatrixTransform;
loadedModelTransform->addChild(sky);
ref_ptr<Group> reflectedSubgraph = _create_scene();
if (!reflectedSubgraph.valid()) return 1;
osg::NodeCallback* nc = new osgUtil::TransformCallback(loadedModelTransform->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(5.0f));
loadedModelTransform->setUpdateCallback(nc);
ref_ptr<Group> reflectedScene = createShadowedScene(reflectedSubgraph.get(),createReflector(),0, viewer.getClearColor());
// osg::Group* rootNode = new osg::Group();
// rootNode->addChild(loadedModelTransform);
// rootNode->addChild(createPreRenderSubGraph(loadedModelTransform));
scene->addChild(reflectedScene.get());
if (loadedModelTransform)
{
rootNode->addChild(createPreRenderSubGraph(loadedModelTransform));
}
#endif
#if 1
osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform;
pat->setPosition(osg::Vec3(0,0,50));
pat->addChild(createReferenceSphere());
rootNode->addChild(pat);
#endif
// load the nodes from the commandline arguments.
osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
if (loadedModel)
rootNode->addChild(loadedModel);
// add model to the viewer.
viewer.setSceneData( rootNode );
viewer.setSceneData(scene.get());
// create the windows and run the threads.
viewer.realize();
while( !viewer.done() )
while (!viewer.done())
{
// wait for all cull and draw threads to complete.
viewer.sync();
// wait for all cull and draw threads to complete.
viewer.sync();
// update the scene by traversing it with the the update visitor which will
// call all node update callbacks and animations.
viewer.update();
// update the scene by traversing it with the the update visitor which will
// call all node update callbacks and animations.
viewer.update();
// fire off the cull and draw traversals of the scene.
viewer.frame();
// fire off the cull and draw traversals of the scene.
viewer.frame();
}
// wait for all cull and draw threads to complete before exit.
@@ -510,4 +336,3 @@ int main( int argc, char **argv )
return 0;
}

View File

@@ -126,7 +126,6 @@ osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const os
// set viewport
camera->setViewport(0,0,tex_width,tex_height);
camera->getOrCreateStateSet()->setAttribute(camera->getViewport());
// set the camera to render before the main camera.
camera->setRenderOrder(osg::CameraNode::PRE_RENDER);
@@ -190,7 +189,6 @@ osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const os
camera->setViewMatrix(osg::Matrix::identity());
camera->setViewport(50,50,100,100);
camera->getOrCreateStateSet()->setAttribute(camera->getViewport());
// only clear the depth buffer
camera->setClearMask(GL_DEPTH_BUFFER_BIT);

View File

@@ -16,6 +16,7 @@
#include <osg/Transform>
#include <osg/Viewport>
#include <osg/ColorMask>
#include <osg/CullSettings>
#include <osg/Texture>
#include <osg/Image>
@@ -37,32 +38,45 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings
META_Node(osg, CameraNode);
/** Sets the clear color. */
inline void setClearColor(const Vec4& color) { _clearColor = color; }
/** Set the viewport of the scene view to use specified osg::Viewport. */
void setViewport(osg::Viewport* viewport)
{
_viewport = viewport;
}
/** Returns the clear color. */
inline const Vec4& getClearColor() const { return _clearColor; }
/** Set the clear mask used in glClear(..).
* Defaults to GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT. */
inline void setClearMask(GLbitfield mask) { _clearMask = mask; }
/** Set the viewport of the scene view to specified dimensions. */
void setViewport(int x,int y,int width,int height)
{
if (!_viewport) _viewport = new osg::Viewport;
_viewport->setViewport(x,y,width,height);
}
/** Get the clear mask.*/
inline GLbitfield getClearMask() const { return _clearMask; }
/** Set the color mask of the camera to use specified osg::ColorMask. */
void setColorMask(osg::ColorMask* colorMask);
/** Set the color mask of the camera to specified values. */
void setColorMask(bool red, bool green, bool blue, bool alpha);
/** Get the const ColorMask. */
const ColorMask* getColorMask() const { return _colorMask.get(); }
/** Get the ColorMask. */
ColorMask* getColorMask() { return _colorMask.get(); }
/** Set the viewport of the camera to use specified osg::Viewport. */
void setViewport(osg::Viewport* viewport);
/** Set the viewport of the camera to specified dimensions. */
void setViewport(int x,int y,int width,int height);
/** Get the const viewport. */
const Viewport* getViewport() const { return _viewport.get(); }
/** Get the viewport. */
Viewport* getViewport() { return _viewport.get(); }
/** Get the viewport of the scene view. */
void getViewport(int& x,int& y,int& width,int& height) const
{
if (_viewport.valid()) _viewport->getViewport(x,y,width,height);
}
enum TransformOrder
{
@@ -149,22 +163,6 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings
/** Get the inverse view matrix.*/
Matrixd getInverseViewMatrix() const;
/** Sets the clear color. */
inline void setClearColor(const Vec4& color) { _clearColor = color; }
/** Returns the clear color. */
inline const Vec4& getClearColor() const { return _clearColor; }
/** Set the clear mask used in glClear(..).
* Defaults to GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT. */
inline void setClearMask(GLbitfield mask) { _clearMask = mask; }
/** Get the clear mask.*/
inline GLbitfield getClearMask() const { return _clearMask; }
enum RenderOrder
{
@@ -276,6 +274,7 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings
Vec4 _clearColor;
GLbitfield _clearMask;
ref_ptr<ColorMask> _colorMask;
ref_ptr<Viewport> _viewport;
TransformOrder _transformOrder;

View File

@@ -19,6 +19,7 @@
#include <osg/GL>
#include <osg/Texture>
#include <osg/buffered_value>
#include <osg/CameraNode>
#ifndef GL_EXT_framebuffer_object
#define GL_EXT_framebuffer_object 1
@@ -256,6 +257,7 @@ namespace osg
explicit FrameBufferAttachment(Texture3D* target, int zoffset, int level = 0);
explicit FrameBufferAttachment(TextureCubeMap* target, int face, int level = 0);
explicit FrameBufferAttachment(TextureRectangle* target);
explicit FrameBufferAttachment(CameraNode::Attachment& attachment);
~FrameBufferAttachment();

View File

@@ -25,7 +25,12 @@ class OSG_EXPORT FrontFace : public StateAttribute
{
public :
FrontFace();
enum Mode {
CLOCKWISE = GL_CW,
COUNTER_CLOCKWISE = GL_CCW
};
FrontFace(Mode face=COUNTER_CLOCKWISE);
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
FrontFace(const FrontFace& ff,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
@@ -46,11 +51,6 @@ class OSG_EXPORT FrontFace : public StateAttribute
return 0; // passed all the above comparison macro's, must be equal.
}
enum Mode {
CLOCKWISE = GL_CW,
COUNTER_CLOCKWISE = GL_CCW
};
inline void setMode(Mode mode) { _mode = mode; }
inline Mode getMode() const { return _mode; }

View File

@@ -105,6 +105,12 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
/** Get the clear color.*/
int getClearStencil() const { return _clearStencil; }
void setInheritedRenderStageLightingMatrix(const osg::Matrix& matrix) { _inheritedRenderStageLightingMatrix = matrix; }
const osg::Matrix& getInheritedRenderStageLightingMatrix() const { return _inheritedRenderStageLightingMatrix; }
void setInheritedRenderStageLighting(RenderStageLighting* rsl) { _inheritedRenderStageLighting = rsl; }
RenderStageLighting* getInheritedRenderStageLighting() { return _inheritedRenderStageLighting.get(); }
void setRenderStageLighting(RenderStageLighting* rsl) { _renderStageLighting = rsl; }
RenderStageLighting* getRenderStageLighting() const
@@ -159,6 +165,8 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
double _clearDepth;
int _clearStencil;
mutable osg::Matrix _inheritedRenderStageLightingMatrix;
mutable osg::ref_ptr<RenderStageLighting> _inheritedRenderStageLighting;
mutable osg::ref_ptr<RenderStageLighting> _renderStageLighting;

View File

@@ -54,7 +54,7 @@ class OSGUTIL_EXPORT RenderStageLighting : public osg::Object
_texAttrListMap[textureUnit].push_back(AttrMatrixPair(attr,matrix));
}
virtual void draw(osg::State& state,RenderLeaf*& previous);
virtual void draw(osg::State& state,RenderLeaf*& previous, const osg::Matrix* postMultMatrix = 0);
public:

View File

@@ -23,6 +23,7 @@ CameraNode::CameraNode():
_renderOrder(POST_RENDER),
_renderTargetImplementation(FRAME_BUFFER)
{
setStateSet(new StateSet);
}
CameraNode::CameraNode(const CameraNode& camera,const CopyOp& copyop):
@@ -30,6 +31,7 @@ CameraNode::CameraNode(const CameraNode& camera,const CopyOp& copyop):
CullSettings(camera),
_clearColor(camera._clearColor),
_clearMask(camera._clearMask),
_colorMask(camera._colorMask),
_viewport(camera._viewport),
_transformOrder(camera._transformOrder),
_projectionMatrix(camera._projectionMatrix),
@@ -37,8 +39,7 @@ CameraNode::CameraNode(const CameraNode& camera,const CopyOp& copyop):
_renderOrder(camera._renderOrder),
_renderTargetImplementation(camera._renderTargetImplementation),
_bufferAttachmentMap(camera._bufferAttachmentMap)
{
{
}
@@ -46,6 +47,54 @@ CameraNode::~CameraNode()
{
}
void CameraNode::setColorMask(osg::ColorMask* colorMask)
{
if (_colorMask == colorMask) return;
osg::StateSet* stateset = getOrCreateStateSet();
if (_colorMask.valid() && stateset)
{
stateset->removeAttribute(_colorMask.get());
}
_colorMask = colorMask;
if (_colorMask.valid() && stateset)
{
stateset->setAttribute(_colorMask.get());
}
}
void CameraNode::setColorMask(bool red, bool green, bool blue, bool alpha)
{
if (!_colorMask) setColorMask(new osg::ColorMask);
if (_colorMask.valid()) _colorMask->setMask(red,green,blue,alpha);
}
void CameraNode::setViewport(osg::Viewport* viewport)
{
if (_viewport == viewport) return;
osg::StateSet* stateset = getOrCreateStateSet();
if (_viewport.valid() && stateset)
{
stateset->removeAttribute(_viewport.get());
}
_viewport = viewport;
if (_viewport.valid() && stateset)
{
stateset->setAttribute(_viewport.get());
}
}
void CameraNode::setViewport(int x,int y,int width,int height)
{
if (!_viewport) setViewport(new osg::Viewport);
if (_viewport.valid()) _viewport->setViewport(x,y,width,height);
}
Matrixd CameraNode::getInverseViewMatrix() const
{
Matrixd inverse;

View File

@@ -211,6 +211,55 @@ FrameBufferAttachment::FrameBufferAttachment(TextureRectangle* target)
_ximpl->textureTarget = target;
}
FrameBufferAttachment::FrameBufferAttachment(CameraNode::Attachment& attachment)
{
osg::Texture* texture = attachment._texture.get();
osg::Texture1D* texture1D = dynamic_cast<osg::Texture1D*>(texture);
if (texture1D)
{
_ximpl = new Pimpl(Pimpl::TEXTURE1D, attachment._level);
_ximpl->textureTarget = texture1D;
return;
}
osg::Texture2D* texture2D = dynamic_cast<osg::Texture2D*>(texture);
if (texture2D)
{
_ximpl = new Pimpl(Pimpl::TEXTURE2D, attachment._level);
_ximpl->textureTarget = texture2D;
return;
}
osg::Texture3D* texture3D = dynamic_cast<osg::Texture3D*>(texture);
if (texture3D)
{
_ximpl = new Pimpl(Pimpl::TEXTURE3D, attachment._level);
_ximpl->textureTarget = texture3D;
_ximpl->zoffset = attachment._face;
return;
}
osg::TextureCubeMap* textureCubeMap = dynamic_cast<osg::TextureCubeMap*>(texture);
if (textureCubeMap)
{
_ximpl = new Pimpl(Pimpl::TEXTURECUBE, attachment._level);
_ximpl->textureTarget = textureCubeMap;
_ximpl->cubeMapFace = attachment._face;
return;
}
osg::TextureRectangle* textureRectangle = dynamic_cast<osg::TextureRectangle*>(texture);
if (textureRectangle)
{
_ximpl = new Pimpl(Pimpl::TEXTURERECT);
_ximpl->textureTarget = textureRectangle;
return;
}
osg::notify(osg::WARN)<<"Error: FrameBufferAttachment::FrameBufferAttachment(CameraNode::Attachment&) passed an unrecognised Texture type."<<std::endl;
}
FrameBufferAttachment::~FrameBufferAttachment()
{
delete _ximpl;

View File

@@ -15,9 +15,9 @@
using namespace osg;
FrontFace::FrontFace()
FrontFace::FrontFace(Mode face)
{
_mode = COUNTER_CLOCKWISE;
_mode = face;
}

View File

@@ -90,9 +90,6 @@ void TexGen::apply(State&) const
glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, _mode );
// note, R & Q will be disabled so R&Q settings won't
// have an effect, see above comment in enable(). RO.
}
else if (_mode == EYE_LINEAR)
{
@@ -106,9 +103,6 @@ void TexGen::apply(State&) const
glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, _mode );
glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, _mode );
// note, R & Q will be disabled so R&Q settings won't
// have an effect, see above comment in enable(). RO.
}
else if (_mode == NORMAL_MAP)
{

View File

@@ -15,6 +15,7 @@
#include <osg/Image>
#include <osg/State>
#include <osg/TextureCubeMap>
#include <osg/Notify>
#include <osg/GLU>
@@ -302,6 +303,26 @@ void TextureCubeMap::apply(State& state) const
}
}
}
else if ( (_textureWidth!=0) && (_textureHeight!=0) && (_internalFormat!=0) )
{
_textureObjectBuffer[contextID] = textureObject = generateTextureObject(
contextID,GL_TEXTURE_CUBE_MAP,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);
textureObject->bind();
applyTexParameters(GL_TEXTURE_CUBE_MAP,state);
for (int n=0; n<6; n++)
{
// no image present, but dimensions at set so less create the texture
glTexImage2D( faceTarget[n], 0, _internalFormat,
_textureWidth, _textureHeight, _borderWidth,
_internalFormat,
GL_UNSIGNED_BYTE,
0);
}
}
else
{

View File

@@ -1036,6 +1036,7 @@ void CullVisitor::apply(osg::CameraNode& camera)
StateSet* node_state = camera.getStateSet();
if (node_state) pushStateSet(node_state);
osg::RefMatrix& originalModelView = getModelViewMatrix();
if (camera.getReferenceFrame()==osg::Transform::ABSOLUTE_RF)
{
@@ -1078,17 +1079,28 @@ void CullVisitor::apply(osg::CameraNode& camera)
// will do later.
osgUtil::RenderStage* previous_stage = getCurrentRenderBin()->getStage();
// set the compute near far mode.
ComputeNearFarMode saved_compute_near_far_mode = getComputeNearFarMode();
setComputeNearFarMode( camera.getComputeNearFarMode());
// set up the background color and clear mask.
rtts->setClearColor(camera.getClearColor());
rtts->setClearMask(camera.getClearMask());
osg::Viewport* viewport = camera.getViewport()!=0 ? camera.getViewport() : previous_stage->getViewport();
// set the color mask.
osg::ColorMask* colorMask = camera.getColorMask()!=0 ? camera.getColorMask() : previous_stage->getColorMask();
rtts->setColorMask(colorMask);
// set up the viewport.
osg::Viewport* viewport = camera.getViewport()!=0 ? camera.getViewport() : previous_stage->getViewport();
rtts->setViewport( viewport );
// set up to charge the same RenderStageLighting is the parent previous stage.
//rtts->setRenderStageLighting(previous_stage->getRenderStageLighting());
osg::Matrix inhertiedMVtolocalMV;
inhertiedMVtolocalMV.invert(originalModelView);
inhertiedMVtolocalMV.postMult(getModelViewMatrix());
rtts->setInheritedRenderStageLightingMatrix(inhertiedMVtolocalMV);
rtts->setInheritedRenderStageLighting(previous_stage->getRenderStageLighting());
// record the render bin, to be restored after creation
// of the render to text
@@ -1106,6 +1118,10 @@ void CullVisitor::apply(osg::CameraNode& camera)
// restore the previous renderbin.
setCurrentRenderBin(previousRenderBin);
// restore the previous compute near far mode
setComputeNearFarMode(saved_compute_near_far_mode);
if (rtts->getRenderGraphList().size()==0 && rtts->getRenderBinList().size()==0)
{
@@ -1156,9 +1172,49 @@ void CullVisitor::apply(osg::CameraNode& camera)
fbo = new osg::FrameBufferObject;
rtts->setFrameBufferObject(fbo.get());
fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FrameBufferAttachment(tex));
fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(viewport->width(), viewport->height(), GL_DEPTH_COMPONENT24)));
bool colorAttached = false;
bool depthAttached = false;
bool stencilAttached = false;
for(osg::CameraNode::BufferAttachmentMap::iterator itr = bufferAttachements.begin();
itr != bufferAttachements.end();
++itr)
{
osg::CameraNode::BufferComponent buffer = itr->first;
osg::CameraNode::Attachment& attachment = itr->second;
switch(buffer)
{
case(osg::CameraNode::DEPTH_BUFFER):
{
fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(attachment));
depthAttached = true;
break;
}
case(osg::CameraNode::STENCIL_BUFFER):
{
fbo->setAttachment(GL_STENCIL_ATTACHMENT_EXT, osg::FrameBufferAttachment(attachment));
stencilAttached = true;
break;
}
default:
{
fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FrameBufferAttachment(attachment));
colorAttached = true;
break;
}
}
}
if (!depthAttached)
{
fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(viewport->width(), viewport->height(), GL_DEPTH_COMPONENT24)));
}
if (!colorAttached)
{
fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(viewport->width(), viewport->height(), GL_RGB)));
}
}
}

View File

@@ -177,8 +177,17 @@ void RenderStage::drawImplementation(osg::State& state,RenderLeaf*& previous)
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// apply the lights.
if (_renderStageLighting.valid()) _renderStageLighting->draw(state,previous);
// apply the positional state.
if (_inheritedRenderStageLighting.valid())
{
_inheritedRenderStageLighting->draw(state, previous, &_inheritedRenderStageLightingMatrix);
}
// apply the positional state.
if (_renderStageLighting.valid())
{
_renderStageLighting->draw(state, previous, 0);
}
// draw the children and local.
RenderBin::drawImplementation(state,previous);

View File

@@ -32,7 +32,7 @@ void RenderStageLighting::reset()
_texAttrListMap.clear();
}
void RenderStageLighting::draw(osg::State& state,RenderLeaf*& previous)
void RenderStageLighting::draw(osg::State& state,RenderLeaf*& previous, const osg::Matrix* postMultMatrix)
{
if (previous)
@@ -47,7 +47,18 @@ void RenderStageLighting::draw(osg::State& state,RenderLeaf*& previous)
litr!=_attrList.end();
++litr)
{
state.applyModelViewMatrix((*litr).second.get());
if (postMultMatrix)
{
if ((*litr).second.valid())
state.applyModelViewMatrix(new osg::RefMatrix( (*((*litr).second)) * (*postMultMatrix)));
else
state.applyModelViewMatrix(new osg::RefMatrix( *postMultMatrix));
}
else
{
state.applyModelViewMatrix((*litr).second.get());
}
// apply the light source.
litr->first->apply(state);
@@ -71,7 +82,17 @@ void RenderStageLighting::draw(osg::State& state,RenderLeaf*& previous)
litr!=attrList.end();
++litr)
{
state.applyModelViewMatrix((*litr).second.get());
if (postMultMatrix)
{
if ((*litr).second.valid())
state.applyModelViewMatrix(new osg::RefMatrix( (*((*litr).second)) * (*postMultMatrix)));
else
state.applyModelViewMatrix(new osg::RefMatrix( *postMultMatrix));
}
else
{
state.applyModelViewMatrix((*litr).second.get());
}
// apply the light source.
litr->first->apply(state);

View File

@@ -60,8 +60,11 @@ void RenderToTextureStage::draw(osg::State& state,RenderLeaf*& previous)
}
if (_image.valid())
{
_image->readPixels(_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height(),_imageReadPixelFormat,_imageReadPixelDataType);
}
if (fbo_supported)
{
fbo_ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);