Hi,

I have a decent solution to this problem that doesn't require modifications to 
the shader and can work with any number of ships in the scene.  The stencil 
buffer can be set up to mark the fragments on the inside of the boat as 
ineligible for rendering upon by the ocean.  Then when the ocean renders, it 
can fail the stencil test and not draw on those areas.  My process for this is:

1) Export the geometry in separate subgraphs so that all exterior boat geometry 
is under one branch and all interior geometry is under another.

2) Load the file and find interior and exterior graph root nodes.

3) Apply a stencil to the interior to always mark that fragment with an ID like 
this:


Code:
// The inner stencil should mark it
osg::Stencil* innerStencil = new osg::Stencil;
innerStencil->setFunction(osg::Stencil::ALWAYS);
innerStencil->setFunctionRef(STENCIL_VALUE);
innerStencil->setStencilPassAndDepthPassOperation(osg::Stencil::REPLACE);

interiorGroupState->setAttributeAndModes(innerStencil, osg::StateAttribute::ON);



4) Apply a stencil to the exterior to always unmark anything that might've been 
marked by a previous draw of the interior that is underneath (depth-wise) like 
this:


Code:
// The outer stencil should un-mark it so that if part of this mesh
// draws on top of the mNodeToStencil, it doesn't count as 'marked'
osg::Stencil* outerStencil = new osg::Stencil;
outerStencil->setFunction(osg::Stencil::ALWAYS);
outerStencil->setFunctionRef(0);
outerStencil->setStencilPassAndDepthPassOperation(osg::Stencil::REPLACE);

exteriorGroupState->setAttributeAndModes(outerStencil, osg::StateAttribute::ON);



5) Apply a stencil to the ocean geometry so that it tests to see if each 
fragment has already been drawn on with an interior boat pixel and if so, it 
fails the stencil test and doesn't draw like this:


Code:
// Tell the ocean tiles that they should not render on
// pixels that are occupied by surface vessels.
osg::Stencil* oceanStencil = new osg::Stencil;
oceanStencil->setFunction(osg::Stencil::NOTEQUAL);
oceanStencil->setFunctionRef(StencilActorComponent::STENCIL_VALUE);
oceanStencil->setStencilPassAndDepthPassOperation(osg::Stencil::KEEP);




6) Ensure that the ocean is drawn AFTER the boats so that the boats could have 
the stencil buffer already marked and the ocean can properly test before 
drawing.  I didn't have a great way to do this but this sufficed:


Code:
// This needs to be drawn after the surface vessels (this works, for now)
GetMatrixNode()->getOrCreateStateSet()->setRenderBinDetails(5, "RenderBin");




The above worked wonderfully for me when I was just using a simple quad for my 
ocean and not using dtOcean.  However, after bring dtOcean into my application, 
either the stenciling no longer work or I'm not able to make the boats draw 
before the ocean using the method from above.

So all that said, my main questions are:

  How do I apply a stencil to my osgOcean::FFTOceanSurface?
  How do I control the render order of dtOcean?

Thank you!

Cheers,
Michael

PS Make sure you are using a stencil buffer or this won't work :P
I do this before creating my window:

Code:
osg::DisplaySettings* display = osg::DisplaySettings::instance();
display->setMinimumNumStencilBits(8);

[/code]

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=42773#42773





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

Reply via email to