PDA

View Full Version : Some framebuffer access rules questions



Nowhere-01
07-05-2011, 09:43 AM
There are some basic questions(i just couldnt come up with right search keywords). So i'm trying to replace separate rendering pass(simplified) for gathering refraction map with just saving image before rendering refractive objects. The problem is i'm not really sure about what is a legal method. And what's traditional/fastest way.

Abstract rendering function:


Render()
{
BindFBO(2);
RenderReflectionMap();
UnbindFBO();

BindFBO(1);
RenderShadowMap();
UnbindFBO();

BindFBO(0);
RenderNonRefractiveStuff();

glBindTexture(GL_TEXTURE_2D, &RefractionMap);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, screenw, screenh, 0);

RenderRefractiveStuff();//Use RefractionMap;
UnbindFBO();

RenderQuad();//Fullscreen Quad With Post-processing
SwapBuffers();
}

And it works. But i'm afraid it can fail on some hardware. Also, glCopyTexImage2D is too expensive. So is it safe to just save image during rendering pass? Is there a better way to do that, keeping structure untouched?

ZbuffeR
07-05-2011, 11:46 AM
glCopyTexImage2D is only needed to create the texture.
When updating data each frame, you can use glCopyTexSubImage2D, it can be much faster on some GL implementations (and make no difference on others).

Nowhere-01
07-06-2011, 09:23 PM
Thanks for the reply. So i assume it is ok to do so? But i doubt this is the best way. And not shure how do i avoid glCopyTexSubImage2D call without creating another fbo(this will suck too because i'll need to deal with depth somehow).

ZbuffeR
07-06-2011, 11:11 PM
Sorry, what do you mean ?
Did you test with *Sub* and did that made any difference on the performance side ?

EDIT: by the way I skipped that, but you can try to reorder the passes, to avoid using RefractionMap right after copy. Currently the card must wait for the copy to finish, whereas if you render refractonMap then copy, then do something else (while copy is happening, do not use either src or dst), then use the copied map.

_arts_
07-07-2011, 12:25 AM
Why not rendering all in fbo since you need to copy your framebuffer into a texture ? You can make an fbo with both color and depth attachment without problem.

Also as ZbuffeR said, use glCopyTexSubImage instead of glCopyTexImage, it is generally faster.

Nowhere-01
07-07-2011, 09:39 AM
ZBuffer, any idea how reorder? In real code, i make TextureCopy only every 2nd frame. And i don't know what can i do to use it without makin my card to wait.

Yes i did test *Sub* yesterday. I have currently installed GTS250(main card is in service) and it didn't make noticeable difference.

_arts_, Because if you'll render refracting objects into refraction map, you will get artifacts(self-refraction, looks intresting, but wrong). But biggest problem if you decide to use FBO texture as a refraction map, how? If you render all objects in a final scene to 1 FBO like i do - how you're going to use texture from the same FBO? There's no back buffer(maybe it's my lack of knowledge? if you know, please tell me)? Make another FBO and use it for non-refractive objects? In that case performance is highly questionable(Additional FBO and also you'll need to combine them to 1 scene somehow).

I'm sorry in advance if i wrote something stupid or missed something. I don't feel really good now.

_arts_
07-07-2011, 10:26 AM
This makes sense. However you could also try with a second renderbuffer or a second texture attachment to the same fbo. Not sure if you could manage all like this however...

Nowhere-01
07-07-2011, 11:25 AM
I did some tests now, with 512 FPS limit and a simple scene i get 512 FPS without saving refraction map and about 490-493 with saving refraction map every 2nd frame enabled. So really... ~4% maybe i should leave it alone? Yes, updating it every frame is too noticeable performance hit, but now it feels ok. I also can disable it then there are no refractors visible. And thought a bit about attachment method, and it looks like it can work if you can bind multiple attachments and unbind them then rendering, like that:


BindAttachment(COLOR_ATTACHMENT_0);

if(Frame % 2 == 0)
BindAttachment(COLOR_ATTACHMENT_1);
else
BindAttachment(COLOR_ATTACHMENT_2);

RenderNonRefractiveStuff();

if(Frame % 2 == 0)
UnbindAttachment(COLOR_ATTACHMENT_1);
else
UnbindAttachment(COLOR_ATTACHMENT_2);

RenderRefractiveStuff();

I'm just not sure about how attachment mechanics works. But if i can't do something like that, i don't think attachments will help here. Also, i'm not sure having 3 attachments is cheap in terms of performance.

BionicBytes
07-07-2011, 02:03 PM
I don't see that there would be a performance hit as you are not rendering to multiple attachments simultaneously.
Also instead if binding different attachments you could use glDrawBuffer to select which attachment you wish to draw to. In my testing this has a lower overhead than switching between targets with a bind.

Nowhere-01
07-08-2011, 02:36 AM
BionicBytes, if you look on my last example more closely, you'll see that it does render to multiple attachments simultaneously. And i don't think it's possible inside one FBO begin render to 2 attachments and then disable one of them. I found that (http://www.gamedev.net/page/resources/_/reference/programming/opengl/opengl-frame-buffer-object-201-r2333) article about multiple attachments and it looks like i don't need to disable one of them, before rendering refractive objects, i can just make it ignore refractors using gl_FragData[1]. But it also seems not so reliable and seems a bit messy.

And some explanation about example: It uses attachment0 for main texture that will be post-processed and shown on screen and attachments1 and 2 are for refraction map and they supposed to imitate double-buffering because RenderRefractiveStuff() uses one of them. And i'm forced to disable them before rendering refractive stuff to avoid self-refraction. And yes, i kinda doubt myself it will work like that.

_arts_
07-08-2011, 06:57 AM
I _think_ you can achieve this with multiple render targets (MRT). The link you shew talks a bit about this. And I _think_ it will be faster than doing it without fbo and/or with doing several consecutive passes.

BionicBytes
07-08-2011, 07:59 AM
And i don't think it's possible inside one FBO begin render to 2 attachments and then disable one of them

You don't need to. You can use glDrawBuffers to select which attachments should be written to by the shader output.


BindAttachment(COLOR_ATTACHMENT_0);

if(Frame % 2 == 0)
BindAttachment(COLOR_ATTACHMENT_1);
else
BindAttachment(COLOR_ATTACHMENT_2);

RenderNonRefractiveStuff();

if(Frame % 2 == 0)
UnbindAttachment(COLOR_ATTACHMENT_1);
else
UnbindAttachment(COLOR_ATTACHMENT_2);

RenderRefractiveStuff();

becomes... (PSEUDO CODE)

if(Frame % 2 == 0)
glDrawBuffers (COLOR_ATTACHMENT_0,COLOR_ATTACHMENT_1);
else
glDrawBuffers (COLOR_ATTACHMENT_0,COLOR_ATTACHMENT_2);

RenderNonRefractiveStuff();

glDrawBuffers (COLOR_ATTACHMENT_0);

RenderRefractiveStuff();

Nowhere-01
07-08-2011, 08:30 AM
That's nice, thank you. I had no idea i can render like that.