Hmmm... okay.. some additional info on this topic:
- I tried with a new StateAttribute "osg::DrawBuffer", but this doen'st work
:-( the situation is:
I have the top pre_render camera, I attach both texture2dArrays on slot 1
and slot 2 (slot 0 is already used by a needed sampler, also, those too
textures are attached on COLOR_BUFFER0 and COLOR_BUFFER1); then I add child
quads with the osg::DrawBuffer state attribute properly configured, and an
uniform properly configured to access the "source texture" (as opposed to
the texture being rendered on that quad, which is supposed to be determined
by the DrawBuffer state attribute...)
=> If I perform a "single pass" (rendering texture B from texture A) then
both texture A and B are properly rendered.
=> As soon as I try to render two passes (rendering texture B from texture A
then rendering texture A from Texture B) then texture B is still OK but
texture A is completely black :-(
- So I assumed the osg::DrawBuffer" stateAttribute was not working as
expected (but here I really don't understand why...) and started creating a
special PingPongDrawable.
The idea with this ping pong drawable is to place is just under the camera
previously defined (so I assume the FBO is applied, the textures are
applied, the shader program is applied and the color buffers are attached: I
attached the source of that "PingPongDrawable if someone wants to have a
look... it's main part is to render all the passes in one cycle just as in
the pure OpenGL code snipped I'm using as template:
So the main part of the code is:
// just call the OpenGL code.
for (int i = 0; i < _numPasses; ++i) { //
extensions->glUniform1f(passLoc, float(i + 0.5) /
_numPasses);
if (i%2 == 0) {
extensions->glUniform1i(imgLoc, 1); // use the first
texture.
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
} else {
extensions->glUniform1i(imgLoc, 2); // Use the second
texture.
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
}
drawQuad();
}
... but here again... everything is fine with a single pass but the texture
A becomes completely black as soon as I try with 2 passes...
I'm really starting to feel desperated so if somebody as a clue why my first
texture2D array gets cleared /destroyed/ sent into another dimension ? that
would be very helpful.
Buy the way, here is how the FBO camera is setup if you want to know that
(this is some lua code, but I guess everyone can understand the osg calls):
local PASSES = options.PASSES or 8;
local FFT_SIZE = options.FFT_SIZE or 256
-- Create a single camera holding the attachments:
local cam = osg.Camera();
cam:setRenderOrder(osg.Camera.RenderOrder.PRE_RENDER,11);
cam:setClearColor(osg.Vec4(1.0,0.0,0.0,1.0));
--cam:setClearMask(GL.Mode.GL_COLOR_BUFFER_BIT +
GL.Mode.GL_DEPTH_BUFFER_BIT)
cam:setClearMask(0)
cam:setViewport(osg.Viewport(0,0,FFT_SIZE,FFT_SIZE))
--cam:setReferenceFrame(osg.Transform.ReferenceFrame.ABSOLUTE_RF);
--cam:setGraphicsContext(context);
cam:setRenderTargetImplementation(osg.Camera.RenderTargetImplementation.FRAME_BUFFER_OBJECT)
-- attach the buffers to the init camera:
--cam:setReadBuffer(GLValues.GL_COLOR_ATTACHMENT0_EXT);
local ss = cam:getOrCreateStateSet()
ss:setMode(GL.Mode.GL_BLEND,osg.StateAttribute.Values.OFF+osg.StateAttribute.Values.OVERRIDE+osg.StateAttribute.Values.PROTECTED)
ss:setMode(GL.Mode.GL_DEPTH_TEST,osg.StateAttribute.Values.OFF+osg.StateAttribute.Values.OVERRIDE+osg.StateAttribute.Values.PROTECTED)
cam:attach(osg.Camera.BufferComponent.COLOR_BUFFER0,result.ffta,0)
--,0,true); -- last true here means: generate mipmaps (is it needed ??)
cam:attach(osg.Camera.BufferComponent.COLOR_BUFFER1,result.fftb,0)
--,0,true); -- last true here means: generate mipmaps (is it needed ??)
ss:setTextureAttribute(1,result.ffta,osg.StateAttribute.Values.ON);
ss:setTextureAttribute(2,result.fftb,osg.StateAttribute.Values.ON);
local ss = cam:getOrCreateStateSet();
cam:setReadBuffer(GLValues.GL_COLOR_ATTACHMENT0_EXT)
cam:setDrawBuffer(GLValues.GL_COLOR_ATTACHMENT0_EXT)
local proj = giProject.ProjectManager.getProject("ocean2");
assignTexture{ss=ss,name="butterfly",project=proj,slot=0}
release(proj)
--- Save uniform here:
giScene.SceneTools.setIntUniform(ss:getOrCreateUniform("nLayers",
osg.Uniform.Type.INT), options.choppy and 5 or 3)
local fftx_passes = osg.Group()
cam:addChild(fftx_passes)
local ss = fftx_passes:getOrCreateStateSet()
-- Add the program:
local proj = giProject.ProjectManager.getProject("ocean2");
local prog = createProgram(proj,"fftx")
ss:setAttributeAndModes(prog)
release(proj)
-- Add passes:
local pass = setupFFTPass(options,result,prog,8) -- this is where the
"pingPongDrawable" is created and added (taking the program and numPasses as
arguments)
fftx_passes:addChild(pass)
Thanks for your help guys!
cheers,
Manu.
2011/9/26 Emmanuel Roche <[email protected]>
> Hi Sergey and everyone,
>
> I've been trying to setup a "ping pong rendering" with multiple cameras as
> previously mentioned... unfortunately this is not really working :-) : I
> guess I just can't render to one texture / use it as input / re-render again
> as easily as I expected.
>
> So now I have to switch to another option. I have some experience with
> osgPPU already, but I only used it in a "regular" wait (with Texture2D,
> rendering a couple of gauss passes in X and Y...) : here the situation is
> much more tricky: I have to ping pong between texture2DArrays with Texture3D
> samplers and with much more passes : it might be possible with osgPPU, but I
> have the feeling I could spend a lot of time to get everything properly set
> up first... (I already spent a log of time trying to setup something with
> regular OSG cameras, so I would like to use that work if possible).
>
> So my idea is: how about if I create a simple new StateAttribute class to
> call glDrawBuffer() ?? This stateAttribute would be as simple as the
> AlphaFunc StateAttribute for instance...: Would this make sense ? Or do you
> think I would be waiting a few additional hours here ? :-)
>
> Then the plan would be to build a graph such as:
>
> Camera (PRE-Render, attachment color0=first Texture2DArray, attachment
> color1=second texture2D Array, rendering shader program)
> | -- Screen Quad 0 with stateset ( stateattribute
> glDrawBuffer=GL_COLOR_ATTACHMENT1_EXT)
> | -- Screen Quad 1 with stateset ( stateattribute
> glDrawBuffer=GL_COLOR_ATTACHMENT0_EXT)
> | -- Screen Quad 2 with stateset ( stateattribute
> glDrawBuffer=GL_COLOR_ATTACHMENT1_EXT)
> | -- etc
>
> ... I might have the ensure the quads are rendered in that exact order, but
> I think a simple bin number settings should be enough to do that no ?
>
>
> If this is really working as expected, this would also mean I would not
> have to use more that one camera to perform all the needed passes... So I
> really think this is the next option I should try, except is someone already
> knows why this won't work :-)
>
>
> Cheers,
> Manu.
>
>
>
>
>
> 2011/9/23 Sergey Polischuk <[email protected]>
>
>> Hi, Manu
>>
>> Cant comment on performance gain with pure gl, but you can write small
>> test to see possible gain. Osg dont share fbos with cameras and dont keep
>> track of vbo's binded so most of gain would be from reducing number of
>> glBindFramebuffer...(..) calls and geometry setup (vertex\index\texcoord
>> arrays\pointers).*
>> *
>>
>> It is possible to create whatever objects you need inside
>> renderImplementation, also you need to info osg::State about all gl state
>> that osg::State keep track of, that you change with opengl calls (look at
>> osg::State::haveApplied...(...) ), or use osg::State functionality instead
>> of opengl calls (look at applyMode(..)/applyAttribute(..)), though not all
>> gl calls can be done through osg::State interface. Instead you can use pure
>> gl and call osg::State::dirtyAll...() afterwards. Dont forget to restore fbo
>> used by osg if you change fbo binding inside drawImplementation(). Also
>> there could be issues with multiple opengl contexts handling if you use
>> multiple screens, so you may need to track current contextID and
>> create\store opengl handles for each contextID used, and pick right handles
>> for current contextID.
>>
>> Also with pure gl approach you can get rid of fbo and drawBuffers switch
>> if you can use NV_texture_barrier extension - you can create texture array
>> with two textures, reading from one layer and writing to another based on
>> uniform value or instanceID if you use instanced drawing for sqreen aligned
>> quads.
>>
>> Cheers,
>> Sergey.
>> 23.09.2011, 15:50, "Emmanuel Roche" <[email protected]>:
>>
>> Thanks Sergey,
>>
>> Right now I'm using multiple cameras rendered one after another... but I
>> have the feeling the performances are not too good (with 17 pre render
>> cameras...). Do you think I'm right to assume I could really improve the
>> performances by using pure GL code instead and create only one FBO ?
>>
>> as a matter of fact, my second idea would be to encapsulate all this using
>> approximately the code snippet of the previous mail in a special drawable.
>> But i'm wondering if this will not lead to other issues (I'm not that
>> familiar with pure GL code and creating special drawables): is it possible
>> to allocate by FBO and everything I could need from within the
>> renderImplementation of a drawable ? Could somebody predict a big issue
>> doing this ?
>>
>> Cheers,
>> Manu.
>>
>>
>> 2011/9/23 Sergey Polischuk <[email protected]>
>>
>> Hi, Manu
>>
>> There are no convenient support for renderbuffer ping-ponging. You can
>> either use pure gl, graph with lots of cameras setup with correct render
>> order and output textures, or osgppu graph with chain of units
>>
>> Cheers,
>> Sergey.
>> 22.09.2011, 16:28, "Emmanuel Roche" <[email protected]>:
>>
>>
>> Hi everyone,
>>
>> I have a question regarding FBO usage and Draw/Read buffer changes:
>>
>> - I have one pre render camera using FBO and with 2 textures attached (to
>> COLOR_BUFFER0 and COLOR_BUFFER1)
>> - Under that camera I would like to add multiple screen aligned quads that
>> would use the attached textures this way: (call them tex0 and tex1):
>> - quad0 would using the tex0 as input and draw on tex1
>> - quad1 would then use tex1 as input and draw on tex0
>> - quad2 would using the tex0 as input and draw on tex1
>> - quad3 would then use tex1 as input and draw on tex0
>> - etc.
>>
>> This is possible in pure OpenGL using something like that:
>>
>> * glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fftFbo2);
>> glUseProgram(fftx->program);
>> glUniform1i(glGetUniformLocation(fftx->program, "nLayers"), choppy ? 5
>> : 3);
>> for (int i = 0; i < PASSES; ++i) {
>> glUniform1f(glGetUniformLocation(fftx->program, "pass"), float(i +
>> 0.5) / PASSES);
>> if (i%2 == 0) {
>> glUniform1i(glGetUniformLocation(fftx->program, "imgSampler"),
>> FFT_A_UNIT);
>> glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
>> } else {
>> glUniform1i(glGetUniformLocation(fftx->program, "imgSampler"),
>> FFT_B_UNIT);
>> glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
>> }
>> drawQuad();
>> }
>> glUseProgram(ffty->program);
>> glUniform1i(glGetUniformLocation(ffty->program, "nLayers"), choppy ? 5
>> : 3);
>> for (int i = PASSES; i < 2 * PASSES; ++i) {
>> glUniform1f(glGetUniformLocation(ffty->program, "pass"), float(i -
>> PASSES + 0.5) / PASSES);
>> if (i%2 == 0) {
>> glUniform1i(glGetUniformLocation(ffty->program, "imgSampler"),
>> FFT_A_UNIT);
>> glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
>> } else {
>> glUniform1i(glGetUniformLocation(ffty->program, "imgSampler"),
>> FFT_B_UNIT);
>> glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
>> }
>> drawQuad();
>> }
>>
>> glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);*
>>
>> .. but I can't figure out how to do something equivalent to the internal
>> calls to glDrawBuffer in the previous snippet when I have a single camera.
>> (as calling setDrawBuffer() is done once and for all before rendering
>> anything... Any idea what could be worth trying here ?
>>
>> Cheers,
>> Manu.
>>
>> _______________________________________________
>> osg-users mailing list
>> [email protected]
>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>
>>
>> _______________________________________________
>> osg-users mailing list
>> [email protected]
>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>
>>
>> _______________________________________________
>> osg-users mailing list
>> [email protected]
>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>
>>
>> _______________________________________________
>> osg-users mailing list
>> [email protected]
>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>
>>
>
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#ifndef OSG_PINGPONGDRAWABLE
#define OSG_PINGPONGDRAWABLE 1
#include <osg/StateAttribute>
#include <osg/AlphaFunc>
#include <osg/Notify>
#include <osg/Drawable>
#include <osg/Program>
#include <osg/State>
#include <osg/ref_ptr>
#include <osg/GL>
#include <osg/GL2Extensions>
namespace osg {
// Now the OSG wrapper for the above OpenGL code, the most complicated bit is computing
// the bounding box for the above example, normally you'll find this the easy bit.
class PingPongDrawable : public osg::Drawable
{
protected:
osg::ref_ptr<osg::Program> _program;
int _numPasses;
public:
PingPongDrawable(): _numPasses(0) {}
PingPongDrawable(osg::Program* prog, int numPasses): _program(prog), _numPasses(numPasses) {}
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
PingPongDrawable(const PingPongDrawable& ppd,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
osg::Drawable(ppd,copyop),
_program(ppd._program) {}
void setNumPasses(int num) {
_numPasses = num;
};
int getNumPasses() {
return _numPasses;
};
void setProgram(osg::Program* prog) {
_program = prog;
};
osg::Program* getProgram() {
return _program.get();
};
META_Object(osg,PingPongDrawable)
void drawQuad() const
{
glBegin(GL_TRIANGLE_STRIP);
glVertex4f(-1.0, -1.0, 0.0, 0.0);
glVertex4f(+1.0, -1.0, 1.0, 0.0);
glVertex4f(-1.0, +1.0, 0.0, 1.0);
glVertex4f(+1.0, +1.0, 1.0, 1.0);
glEnd();
}
// the draw immediate mode method is where the OSG wraps up the drawing of
// of OpenGL primitives.
virtual void drawImplementation(osg::RenderInfo& info) const
{
// teapot(..) doens't use vertex arrays at all so we don't need to toggle their state
// if we did we'd need to something like following call
// state.disableAllVertexArrays(), see src/osg/Geometry.cpp for the low down.
if(!_program.valid()) {
wxLogError("Invalid Ping pong program!");
return;
}
osg::State* state = info.getState();
const unsigned int contextID = state->getContextID();
const GL2Extensions* extensions = GL2Extensions::Get(contextID,true);
if( ! extensions->isGlslSupported() ) {
wxLogError("GLSL not supported in PingPongDrawable.");
return;
}
osg::Program::PerContextProgram* pcp = _program->getPCP( contextID );
if(!pcp) {
wxLogError("Invalid Ping pong per context program for context %d",contextID);
return;
};
unsigned int progHandle = pcp->getHandle();
GLint passLoc = extensions->glGetUniformLocation( progHandle, "pass" );
GLint imgLoc = extensions->glGetUniformLocation( progHandle, "img_Sampler" );
// Retrieve the per context program handle:
// assuming here the program is allready applyed !
// just call the OpenGL code.
for (int i = 0; i < _numPasses; ++i) { //
extensions->glUniform1f(passLoc, float(i + 0.5) / _numPasses);
if (i%2 == 0) {
extensions->glUniform1i(imgLoc, 1); // use the first texture.
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
} else {
extensions->glUniform1i(imgLoc, 2); // Use the second texture.
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
}
drawQuad();
}
}
// Just return dummy bounding box.
virtual osg::BoundingBox computeBound() const
{
osg::BoundingBox bbox;
return bbox;
}
protected:
virtual ~PingPongDrawable() {}
};
}
#endif
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org