J-S (and others),

You could look at doing this is the same way the depth partition node does
it, which is what I do:

I use a class based on an OSG camera with an overriden traverse method, that
forces the projection matrix to a particular z near and z far. Oh, and the
camera has setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
in its constructor. The skydome is then a child of this camera.

You then set the z near and z far to be whatever you want (i.e. enveloping
your skydome radius). I typically have a skydome with a radius of 1

void CExtentsCamera::traverse(osg::NodeVisitor &nv)
{
    // If the scene hasn't been defined (i.e. we have no children at all)
then don't do anything
    if(_children.size() == 0) return;

    // If the visitor is not a cull visitor, then we are not interested in
intercepting it, so pass it directly onto the scene.
    osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
    if(!cv)
    {
        Camera::traverse(nv);
        return;
    }

    // Get a reference to the Cull Visitor's projection matrix
    osg::Matrix* projection = cv->getProjectionMatrix();

    // NB : This might be possible to simplify and hence optimise (haven't
yet checked)
    double a = (*projection)(2,2);
    double b = (*projection)(3,2);
    double c = (*projection)(2,3);
     double d = (*projection)(3,3);
    double trans_near = (-_zNear*a + b) / (-_zNear*c + d);
    double trans_far  = ( -_zFar*a + b) / ( -_zFar*c + d);
    double ratio = fabs(2.0/(trans_near - trans_far));
    double center = -0.5*(trans_near + trans_far);

    // Set the projection matrix
    projection->postMult(osg::Matrixd(    1.0, 0.0, 0.0,            0.0,
                                        0.0, 1.0, 0.0,            0.0,
                                        0.0, 0.0, ratio,        0.0,
                                        0.0, 0.0, center*ratio, 1.0));

    Camera::traverse(nv);
}

Probably a better way of doing it, but it works fine for me.

I also do this on the "camera"'s stateset

    {
        osg::Depth* depth = new osg::Depth;
        depth->setFunction(osg::Depth::LEQUAL);
        depth->setRange(1.0,1.0);
        stateSet->setAttributeAndModes(depth,osg::StateAttribute::ON );
    }

so that you can render the sky last, and any expensive pixel shaders don't
get unnecessarily run.

Hope that helps,

David
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to