Hi J S,

Comments at the bottom.

Jean-Sébastien Guay wrote:
Hi Roger,

I would like to render a scene that has some nodes in it that should not receive a shadow, and also some nodes that should neither cast nor receive a shadow but still be rendered.

Not that I want to curb your enthusiasm to fix a percieved problem, but there are ways to achieve what you want without changing the shadow technique code.

(Note that I will only speak from experience with osgShadow::ShadowMap and the new ViewDependentShadow techniques - the others I know less about but it might be similar)

First of all, ShadowMap and the new ViewDependentShadow classes (LightSpacePerspectiveShadowMap being the one you probably want) will honor the castsShadow traversal mask. So if you flag a node like so:

unsigned int castsShadow = shadowedScene->getCastsShadowTraversalMask();
node->setNodeMask(node->getNodeMask() & ~castsShadow);

it will not cast shadows (and its volume will not be considered when calculating the shadow casting volume, which is good for reducing shadow aliasing in the case of ShadowMap).

Second, no shadow technique right now honors the receivesShadow traversal mask. But you can work around this by putting the node you don't want to receive shadows outside the shadowedScene in your scene graph. So for example, your actual scene root would be an ordinary osg::Group, which would have as children all the nodes you don't want to receive shadows, and also the ShadowedScene under which all nodes will receive shadows.

You can also add control for receiving shadows in your shadow shader. Both ShadowMap and LightSpacePerspectiveShadowMap allow you to replace the shaders by ones you would write yourself. In my case, I have a single shader pair (vertex + fragment) for the whole scene, where I have a uniform that controls if the object is shadowed (so if this uniform is false, no shadow map lookup will be performed for the current vertex/fragment). Then I just set that uniform to the desired value on the nodes. This might slow down your rendering a bit, but it gives you better control over shadow application in your scene.

So with those suggestions I think you can get the result you want. If not, perhaps I've misunderstood what you were trying to accomplish.

Hope this helps,

J-S
Thanks for the suggestions. They may well be my only option, but I am a bit limited in what I can do as I am adding shadowing into an existing application, which also limits me to the OSG 2.6 branch for production code.

I realise that taking nodes out of the tree could do what I want, but that would be a bit messy as most of them are under LOD nodes, and the user needs to be able to switch shadows on and off on various objects.

I have managed to avoid fragment shaders so far. Experiments using ShadowMap gave me between a 30 and 50 percent raw framerate (non vsynced) hit, and I am up against it performance wise in many cases already. I already have a version which runs my own shader but as far as I can see the ShadowMap does not allow me to specify my own uniforms via a public interface, and more importantly unilaterally turns off ambient lighting in the main scene.

I am happy to invest some time in finding a solution that may be of more general use. Please forgive me now for dumping some general observations into this message.

I notice from some earlier correspondence that you also made the same assumption that I did about control of shadow reception using the receivesShadow mask. I wonder if the fact that none of the implementors of shadow techniques have found a way of using this mask/bit to control the application of  a shadowed state during the scene rendering pass calls its place in the design into question.

At the heart of OSGs scene traversal algorithm is the osg::Node::validNodeMask code

inline bool validNodeMask(const osg::Node& node) const
{
    return (getTraversalMask() & (getNodeMaskOverride() | node.getNodeMask()))!=0;
}

In normal usage the fundamental result of this is that any bit that is set in the NodeMask (which to my way of thinking is not really a mask but a set of flag bits :-) ) and not masked by the travesal mask will cause the node and its children to be included in the processing, but in reverse no unmasked bit can be set if the node is to be excluded. Also as far as the general purpose osgUtill::CullVisitor is concerned this only controls whether a node is included in its cull processing not any conditional processing within the internal cull processing of a node.

It seems to me that most efficient way to ensure that a node is correctly shadowed would be to not unconditionally push a shadowing state onto the stateSet stack at the start of the ShadowTechnique cull method, but to find a way to conditionally add it on a node by node basis during the main cull traversal. One way to do this would be by adding a cull callback to every node in every child subgraph, but I can foresee major difficulties with doing this in way which does not interfere with exisitng cull callbacks in the subgraph and does not require intervention by the scene graph constructor (i.e. he can just add and remove his graph as a child and the callbacks should  appear and dissappear).

Maybe others can comment on this.

Roger

_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to