[osg-users] [osgPPU] osgPPU and the stencil buffer

46 views
Skip to first unread message

Miguel Angel Exposito

unread,
May 28, 2011, 6:39:54 AM5/28/11
to osg-...@lists.openscenegraph.org
Hi,

I'm pretty new to osgPPU and I'm working on a port of Jimenez's MLAA full scene antialiasing algorithm.

It's a 3-pass post processing effect and I got it working on osgPPU.

- The first step detects the edges of the RTT'd scene and makes an 'edge texture'.
- The second step uses the previous texture and a precomputed one to calculate the area which pixels belonging to an edge would cover from an ideal trapeze.
- The final step blends each pixel in its 4-neighborhood according to the weights calculated in the previous step.

I got it fully working in osgPPU, however, an important optimization can be done by using the stencil buffer. The idea behind this is:

- Initially the stencil is cleared out to 0

- The first step of the post effect (edges detection) creates a stencil mask writing 1's to the stencil wherever there's an edge pixel. The pixels not belonging to an edge are discarded in the shader, so no writting to the stencil will occur in that case.

- In the subsequent steps the stencil test discards every pixel not covered by the mask, hence only the edge pixels are processed (weights calculation and final blend).

And this is how I tried to achieve it:

- I created two osg::Stencils, one for creating the mask and other for using the mask and discarding everything else.
- I attached the stencils to their corresponding osgPPU::Unit's.

(now, I need to clear the stencil at the beginning of the postFX chain, but not between each pass)
- I'm not sure about where glClear (with the clear mask of the camera the osgPPU::Processor is using) is called, but my guess is when rendering the scene to texture, not between units so I think that setting the clearMask in the camera is pointless.
- I tried to call glClear(GL_STENCIL_BUFFER_BIT) in a notify callback set in the first unit of my chain.


This has been driving me nuts for a couple of days now. It seems that the stencil buffer is not being written, or cleared prematurely between passes. And the stencil test only seems to be done if I enable it in the last unit's stateset.

What am I missing?

I can post the code if you want!

...


Thank a lot in advance!

Cheers,
Miguel

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

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

David Callu

unread,
May 29, 2011, 5:27:19 PM5/29/11
to osg-...@lists.openscenegraph.org
Hi Miguel,



2011/5/28 Miguel Angel Exposito <rad...@gmail.com>

Hi,

I'm pretty new to osgPPU and I'm working on a port of Jimenez's MLAA full scene antialiasing algorithm.

It's a 3-pass post processing effect and I got it working on osgPPU.

- The first step detects the edges of the RTT'd scene and makes an 'edge texture'.
- The second step uses the previous texture and a precomputed one to calculate the area which pixels belonging to an edge would cover from an ideal trapeze.
- The final step blends each pixel in its 4-neighborhood according to the weights calculated in the previous step.

I got it fully working in osgPPU, however, an important optimization can be done by using the stencil buffer. The idea behind this is:

- Initially the stencil is cleared out to 0

- The first step of the post effect (edges detection) creates a stencil mask writing 1's to the stencil wherever there's an edge pixel. The pixels not belonging to an edge are discarded in the shader, so no writting to the stencil will occur in that case.

- In the subsequent steps the stencil test discards every pixel not covered by the mask, hence only the edge pixels are processed (weights calculation and final blend).

And this is how I tried to achieve it:

- I created two osg::Stencils, one for creating the mask and other for using the mask and discarding everything else.
- I attached the stencils to their corresponding osgPPU::Unit's.

(now, I need to clear the stencil at the beginning of the postFX chain, but not between each pass)
- I'm not sure about where glClear (with the clear mask of the camera the osgPPU::Processor is using) is called, but my guess is when rendering the scene to texture, not between units so I think that setting the clearMask in the camera is pointless.
- I tried to call glClear(GL_STENCIL_BUFFER_BIT) in a notify callback set in the first unit of my chain.


This has been driving me nuts for a couple of days now. It seems that the stencil buffer is not being written, or cleared prematurely between passes. And the stencil test only seems to be done if I enable it in the last unit's stateset.

What am I missing?



- Have you create an opengl context with a stencil buffer ?
- Have you try to use osg:ClearNode to clear the stencil buffer ?
- Have you check opengl call order in a debugger like gDEBugger ?

no more ideas ... for now.



 
I can post the code if you want!

yes please, could be more simple to find the bug.

Cheers
David Callu

Miguel Angel Exposito

unread,
May 31, 2011, 2:43:33 PM5/31/11
to osg-...@lists.openscenegraph.org
Hi David,


> - Have you create an opengl context with a stencil buffer ?
> - Have you try to use osg:ClearNode to clear the stencil buffer ?
> - Have you check opengl call order in a debugger like gDEBugger ?


- Yes I the context that osgViewer creates when realizing has a working stencil (I tested it).
- No, I didn't know that one was allowed to put nodes such as osg::ClearNode inbetween osgPPU::Unit's
- No, but I was planning to use GLintercept as a last resort


> yes please, could be more simple to find the bug.


Sure!, here it is:

This function generates the whole pipeline and attaches its processor to an osg::Group which is returned


Code:


// This is a dirty workaround for not using an osg::ClearNode

struct CamClearMaskCallback : public osgPPU::Unit::NotifyCallback
{
osg::Camera * m_cam;
GLbitfield m_mask;
CamClearMaskCallback(osg::Camera *cam, GLbitfield mask) : osgPPU::Unit::NotifyCallback(), m_cam(cam), m_mask(mask) {}
virtual void operator()(osg::RenderInfo& ri, const osgPPU::Unit* u) const
{
m_cam->setClearMask(m_mask);
if(m_mask & GL_STENCIL_BUFFER_BIT)
{
glClear(GL_STENCIL_BUFFER_BIT);
// printf("CLEAR\n");
} else {
// printf("\n");
}
}
};


osg::Group* MLAARendering::createMLAAPipeline(osg::Camera* camera)
{

osg::Group* finalGroup = new osg::Group;

osg::ref_ptr<CamClearMaskCallback> clearStencilCallback = new CamClearMaskCallback(camera, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
osg::ref_ptr<CamClearMaskCallback> dontClearStencilCallback = new CamClearMaskCallback(camera, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

osg::ref_ptr<osgDB::ReaderWriter::Options> fragmentOptions = new osgDB::ReaderWriter::Options("fragment");
osg::ref_ptr<osgDB::ReaderWriter::Options> vertexOptions = new osgDB::ReaderWriter::Options("vertex");

// Setup the clear mask and the stencil clear value
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
camera->setClearStencil(0);
osg::Vec2f pixelSize(1.0/camera->getGraphicsContext()->getTraits()->width,
1.0/camera->getGraphicsContext()->getTraits()->height);


// This stencil is intended to create the mask by writting a 1 to the stencil wherever a fragment is not discarded in the shader of the unit it's
// attached to. However, the stencil test has to pass always and osgPPU disables the Z test, so I don't know if this is really working as I want!
osg::Stencil * createMaskStencil = new osg::Stencil;
{
createMaskStencil->setFunctionRef(1);
createMaskStencil->setFunction(osg::Stencil::ALWAYS);
createMaskStencil->setWriteMask(1);
createMaskStencil->setOperation(osg::Stencil::REPLACE, osg::Stencil::REPLACE, osg::Stencil::REPLACE);
}

// This one is intended to discard every fragment not masked by a 1 in the stencil
osg::Stencil * useMaskStencil = new osg::Stencil;
{
useMaskStencil->setFunctionRef(1);
useMaskStencil->setFunction(osg::Stencil::EQUAL); // TODO: TEMP!!, Should be osg::Stencil::EQUAL!
useMaskStencil->setWriteMask(1);
useMaskStencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);
}

// This is for testing purposes (it always passes and doesn't change the buffer)
osg::Stencil * testStencil = new osg::Stencil;
{
testStencil->setFunction(osg::Stencil::ALWAYS,1,~0u);
testStencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);
}

// Create a processor for this pipeline
m_processor = new osgPPU::Processor();
m_processor->setName("Processor");
m_processor->setCamera(camera);

osgPPU::UnitCameraAttachmentBypass* bypass = new osgPPU::UnitCameraAttachmentBypass();
{
bypass->setBufferComponent(osg::Camera::COLOR_BUFFER0);

bypass->setName("MLAA.mainCamOutputTex");

// I want the stencil to be cleared here, I don't really care if it's done before or after 'drawing'
bypass->setBeginDrawCallback(clearStencilCallback.get());
}

osgPPU::UnitCameraAttachmentBypass* bypassDepth = new osgPPU::UnitCameraAttachmentBypass();
{
bypassDepth->setBufferComponent(osg::Camera::DEPTH_BUFFER);

bypassDepth->setName("MLAA.mainCamOutputDepthTex");
}

// First step: Edges detection and stencil mask creation
edgeDetection = new osgPPU::UnitInOut();
edgeDetection->setName("MLAA.edgeDetectionUnit");
{


edgeDepthShader = new osgPPU::ShaderAttribute();
edgeDepthShader->addShader(osgDB::readShaderFile("Shaders\\edge_depth_frag.frag", fragmentOptions.get()));
edgeDepthShader->addShader(osgDB::readShaderFile("Shaders\\offset_vert.vert", vertexOptions.get()));
edgeDepthShader->setName("EdgeDetectionShader");

edgeDepthShader->add("threshold", osg::Uniform::FLOAT);
edgeDepthShader->set("threshold", edgeThreshold);
edgeDepthShader->add("pixelSize", osg::Uniform::FLOAT_VEC2);
edgeDepthShader->set("pixelSize", pixelSize);

edgeDepthShader->add("bias", osg::Uniform::FLOAT);
edgeDepthShader->set("bias", edgeThreshold);

edgeDepthShader->add("scale", osg::Uniform::FLOAT);
edgeDepthShader->set("scale", 0.1f);

edgeDetection->setInputToUniform(bypass, "colorMapG", true);
edgeDetection->setInputToUniform(bypassDepth, "depthMap", true);


edgeDetection->getOrCreateStateSet()->setAttributeAndModes(edgeDepthShader);

// Attach the 'createMask' stencil and enable the GL_STENCIL_TEST
edgeDetection->getOrCreateStateSet()->setAttributeAndModes(createMaskStencil, osg::StateAttribute::ON);
edgeDetection->getOrCreateStateSet()->setMode(GL_STENCIL_TEST, osg::StateAttribute::ON);
edgeDetection->setBeginDrawCallback(dontClearStencilCallback.get());

}

// This unit just loads up a texture which is needed by the next shader
osgPPU::UnitTexture* areaTexture = new osgPPU::UnitTexture();
areaTexture->setName("MLAA.areaTextureUnit");
{
osg::Image *areaImg = osgDB::readImageFile("Textures\\AreaMap65.dds");

// An extremely dirty error checking
if(!areaImg)
{
osg::notify(osg::FATAL) << "> Can't load the area map, aborting ...\n";
exit(-1);
}

osg::Texture2D *areaTex = new osg::Texture2D;
areaTex->setResizeNonPowerOfTwoHint(false);
areaTex->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
areaTex->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
areaTex->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
areaTex->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
areaTex->setImage(areaImg);
areaTex->setNumMipmapLevels(1);
areaTexture->setTexture(areaTex);
}

// Second step: Weights calculation only in the fragments masked by the stencil (whose values are == 1)
weightsCalculation = new osgPPU::UnitInOut();
weightsCalculation->setName("MLAA.weightsCalculationUnit");
{
weightsShader = new osgPPU::ShaderAttribute();
weightsShader->addShader(osgDB::readShaderFile("Shaders\\weights_frag.frag", fragmentOptions.get()));
weightsShader->addShader(osgDB::readShaderFile("Shaders\\offset_vert.vert", vertexOptions.get()));
weightsShader->setName("WeightsCalculationShader");

weightsCalculation->setInputToUniform(areaTexture, "areaMap", true);
weightsCalculation->setInputToUniform(edgeDetection, "edgesMapL", true);

weightsShader->add("maxSearchSteps", osg::Uniform::INT);
weightsShader->set("maxSearchSteps", 12);
weightsShader->add("pixelSize", osg::Uniform::FLOAT_VEC2);
weightsShader->set("pixelSize", pixelSize);

weightsCalculation->getOrCreateStateSet()->setAttributeAndModes(weightsShader);
weightsCalculation->setInputTextureIndexForViewportReference(1); // Choose to have an output the same size as edgesMap has

// Attach the 'usueMask' stencil here
weightsCalculation->getOrCreateStateSet()->setAttributeAndModes(useMaskStencil, osg::StateAttribute::ON);
weightsCalculation->getOrCreateStateSet()->setMode(GL_STENCIL_TEST, osg::StateAttribute::ON);
// Just to make sure that the stencil is not being cleared anymore
weightsCalculation->setBeginDrawCallback(dontClearStencilCallback.get());

}

// Last step: Blend the edge pixels with their 4-neighborhood according to the blending weights
// (again, only the masked pixels have to be processed)
osgPPU::UnitInOut* pixelBlend = new osgPPU::UnitInOut();
pixelBlend->setName("MLAA.pixelblendingUnit");
{
osgPPU::ShaderAttribute* blendShader = new osgPPU::ShaderAttribute();
blendShader->addShader(osgDB::readShaderFile("Shaders\\blend_frag.frag", fragmentOptions.get()));
blendShader->addShader(osgDB::readShaderFile("Shaders\\offset_vert.vert", vertexOptions.get()));
blendShader->setName("BlendShader");

pixelBlend->setInputToUniform(weightsCalculation, "blendMap", true);

blendShader->add("pixelSize", osg::Uniform::FLOAT_VEC2);
blendShader->set("pixelSize", pixelSize);


pixelBlend->setInputToUniform(bypass, "colorMapL", true);

pixelBlend->getOrCreateStateSet()->setAttributeAndModes(blendShader);

// Attach the 'useMask' stencil
pixelBlend->getOrCreateStateSet()->setAttributeAndModes(useMaskStencil, osg::StateAttribute::ON);
pixelBlend->getOrCreateStateSet()->setMode(GL_STENCIL_TEST, osg::StateAttribute::ON);

}


// This output unit just acts as a switch for displaying the original RTT, the final processed image or the textures inbetween (edges and weights)
unitOut= new osgPPU::UnitOut();
shaderAttributeOut= new osgPPU::ShaderAttribute();
{
osg::Shader* shader= new osg::Shader(osg::Shader::FRAGMENT);
const char* shaderSource=
"uniform sampler2D finalMap;\n"
"uniform sampler2D edgesMap;\n"
"uniform sampler2D weightsMap;\n"
"uniform sampler2D colorMap;\n"
"uniform int switchFlag;\n"
"void main()\n"
"{\n"
"if(switchFlag == 0)\n"
" gl_FragColor=texture2D(edgesMap,gl_TexCoord[0].st);\n"
"else if(switchFlag == 1)\n"
" gl_FragColor=texture2D(weightsMap,gl_TexCoord[0].st);\n"
"else if(switchFlag == 2)\n"
" gl_FragColor=texture2D(finalMap,gl_TexCoord[0].st);\n"
"else if(switchFlag == 3)\n"
" gl_FragColor=texture2D(colorMap,gl_TexCoord[0].st);\n"
"}";
shader->setShaderSource(shaderSource);
shaderAttributeOut->addShader(shader);
shaderAttributeOut->setName("nomShaderAttribute");

shaderAttributeOut->add("switchFlag", osg::Uniform::INT);
shaderAttributeOut->set("switchFlag", 2);


unitOut->setInputToUniform(pixelBlend, "finalMap", true);
unitOut->setInputToUniform(edgeDetection, "edgesMap", true);
unitOut->setInputToUniform(weightsCalculation, "weightsMap", true);
unitOut->setInputToUniform(bypass, "colorMap", true);
unitOut->setInputTextureIndexForViewportReference(1); // Choose to have an output the same size as edgesMap has


unitOut->setName("MLAA.finalOutputUnit");
unitOut->setViewport(new osg::Viewport(0,0, camera->getGraphicsContext()->getTraits()->width,
camera->getGraphicsContext()->getTraits()->height));

unitOut->getOrCreateStateSet()->setAttributeAndModes(shaderAttributeOut.get());

// It looks like for some reason no stencil testing is performed at all unless I enable the GL_STENCIL_TEST in this unit
// Let's recall that the testStencil does always pass
unitOut->getOrCreateStateSet()->setAttributeAndModes(testStencil, osg::StateAttribute::ON);
unitOut->getOrCreateStateSet()->setMode(GL_STENCIL_TEST, osg::StateAttribute::ON);

}

// Link the units

bypass->addChild(edgeDetection);
bypassDepth->addChild(edgeDetection);
edgeDetection->addChild(areaTexture);
edgeDetection->addChild(weightsCalculation);
areaTexture->addChild(weightsCalculation);
weightsCalculation->addChild(pixelBlend);
pixelBlend->addChild(unitOut);

m_processor->addChild(bypass);
m_processor->addChild(bypassDepth);
finalGroup->addChild(m_processor);

m_processor->dirtyUnitSubgraph();


// Set the edges texture properties
{
osg::Texture2D *outTex = static_cast<osg::Texture2D*>(edgeDetection->getOrCreateOutputTexture());
if(outTex)
{
outTex->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
outTex->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
outTex->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
outTex->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
}
}

// Set the weights texture properties
{
osg::Texture2D *outTex = static_cast<osg::Texture2D*>(weightsCalculation->getOrCreateOutputTexture());
if(outTex)
{
outTex->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
outTex->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
outTex->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
outTex->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
}
}

isInit = true;
return finalGroup;
}

... the first shader looks like this ...


Code:
/**
* Copyright (C) 2010 Jorge Jimenez ()
* Copyright (C) 2010 Belen Masia ()
* Copyright (C) 2010 Jose I. Echevarria ()
* Copyright (C) 2010 Fernando Navarro ()
* Copyright (C) 2010 Diego Gutierrez ()
* All rights reserved.
*
* Adaptated by Miguel Angel Exposito ()
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the following statement:
*
* "Uses Jimenez's MLAA. Copyright (C) 2010 by Jorge Jimenez, Belen Masia,
* Jose I. Echevarria, Fernando Navarro and Diego Gutierrez."
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the copyright holders.
*/

#version 120

varying vec4 offset[2];

uniform sampler2D depthMap;
uniform float threshold;


void main()
{

float D = texture2D(depthMap, gl_TexCoord[0].st).r;
float Dleft = texture2D(depthMap, offset[0].xy).r;
float Dtop = texture2D(depthMap, offset[0].zw).r;
float Dright = texture2D(depthMap, offset[1].xy).r;
float Dbottom = texture2D(depthMap, offset[1].zw).r;

vec4 delta = abs(vec4(D) - vec4(Dleft, Dtop, Dright, Dbottom));
vec4 edges = step(vec4(threshold) / 10.0, delta); // Dividing by 10 give us results similar to the color-based detection.

if (dot(edges, vec4(1.0)) == 0.0)
discard;

gl_FragData[0] = edges;
}

(Note that in order to make it work without the stencil test I have to comment the discard part in the sader).

... and the main program goes like this ...

Code:
void main(int argc, char **argv)
{
printHelp(); // Output some console text

osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

MLAA = new MLAARendering;

unsigned int screenWidth;
unsigned int screenHeight;
unsigned int windowWidth = 1280;
unsigned int windowHeight = 720;

// Init the stencil and disable the default MSAA
osg::DisplaySettings::instance()->setMinimumNumStencilBits(8);
osg::DisplaySettings::instance()->setNumMultiSamples(0);
osg::ref_ptr<KeyboardEventHandler> kbHandler;

// Get the screen resolution
osg::GraphicsContext::getWindowingSystemInterface()->
getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0),screenWidth,
screenHeight);

// Setup the view in a screen centered window
viewer->setUpViewInWindow((screenWidth-windowWidth)/2,
(screenHeight-windowHeight)/2, windowWidth, windowHeight);

// Set single-threading model
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);


// Setup the viewer camera and RTT
osg::Camera* camera = viewer->getCamera();
camera->setViewport(new osg::Viewport(0,0,windowWidth, windowHeight));
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);

osg::Texture* textureView = createRenderTextureWrks(windowWidth, windowHeight);
osg::Texture* textureDepth = createDepthTextureWrks(windowWidth, windowHeight);
camera->attach(osg::Camera::COLOR_BUFFER0, textureView);
camera->attach(osg::Camera::DEPTH_BUFFER, textureDepth);

osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;

traits->samples = 0; // No multisampling AA
traits->width = windowWidth;
traits->height = windowHeight;
traits->x = (screenWidth-windowWidth)/2;
traits->y = (screenHeight-windowHeight)/2;
traits->doubleBuffer = true;
traits->sharedContext = 0;
traits->stencil = 8;
traits->supportsResize = false;
traits->windowDecoration = true;

traits->windowName = "Jimenez's MLAA for OSG";

osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
camera->setGraphicsContext(gc);

// Load up the scene
osg::ref_ptr<osg::Node> scene;

if(argc > 1)
{
osg::notify(osg::NOTICE) << "> Loading requested model '" << argv[1] << "' ...\n";
scene = osgDB::readNodeFile(std::string(argv[1]));
} else {
osg::notify(osg::NOTICE) << "> No model specified, defaulting to 'Models\\cow.osg' ...\n";
scene = osgDB::readNodeFile("Models\\cow.osg");
}

if(!scene)
{
if(argc == 1)
osg::notify(osg::FATAL) << "> Can't load default model 'Models\\cow.osg', aborting...\n";
else
osg::notify(osg::FATAL) << "> Can't load requested model, '" << argv[1] << "' aborting...\n";

exit(-1);
}

osg::ref_ptr<osg::Group> group = new osg::Group();
group->setName("Antialiased Scene");


group = MLAA->createMLAAPipeline(camera);
group->addChild(scene);

osg::ref_ptr<osgViewer::StatsHandler> statsHandler = new osgViewer::StatsHandler();
statsHandler->setKeyEventPrintsOutStats('s'); // Map the statistics HUD to the 's' key
viewer->addEventHandler(statsHandler);
kbHandler = new KeyboardEventHandler(viewer, MLAA);

// Add the keyboard event handler
viewer->addEventHandler(kbHandler);

scene->getOrCreateStateSet()->setMode(GL_STENCIL_TEST, osg::StateAttribute::OFF);

viewer->realize();

viewer->setSceneData(group);

viewer->run();
}

...


Thank you!

Cheers,
Miguel

------------------
Read this topic online here:

http://forum.openscenegraph.org/viewtopic.php?p=39976#39976

Miguel Angel Exposito

unread,
Jun 3, 2011, 3:43:23 PM6/3/11
to osg-...@lists.openscenegraph.org
Come on, guys!!, a little help here.... :D

Sorry for bumping this but I couldn't figure out this yet :(

------------------
Read this topic online here:

http://forum.openscenegraph.org/viewtopic.php?p=40065#40065

David Callu

unread,
Jun 5, 2011, 7:54:53 AM6/5/11
to osg-...@lists.openscenegraph.org
Hi Miguel,

I'm too busy this week end to take a look on this problem.
Next week after Wednesday, my planning will be free and
you are the first on my todo list.

Cheers
David Callu

2011/6/3 Miguel Angel Exposito <rad...@gmail.com>

Miguel Angel Exposito

unread,
Jun 6, 2011, 11:32:47 AM6/6/11
to osg-...@lists.openscenegraph.org
Thanks David!

------------------
Read this topic online here:

http://forum.openscenegraph.org/viewtopic.php?p=40121#40121

David Callu

unread,
Jun 10, 2011, 10:03:38 AM6/10/11
to osg-...@lists.openscenegraph.org
Hi Miguel

Your code seem good.
I am not familiar with MLAA and its optimization.

Have you try gDEBugger, it allow you to see the StencilBuffer at anytime.

You're right, use of osg::ClearNode between osgPPU::Unit is probably not a good idea

If you could provide an simple example, I could play and search on my side.

Cheers
David Callu


2011/6/6 Miguel Angel Exposito <rad...@gmail.com>
Reply all
Reply to author
Forward
0 new messages