PDA

View Full Version : FBO and TEXTURE_RECTANGLE_ARB



devdept
10-21-2008, 12:46 AM
Hi Guys,


RenderToBitamp (target bitmap is not square and not power of two): we are switching to the slower glReadPixel in the case GL_TEXTURE_RECTANGLE extension is not present but it is really necessary? FBO cares about NPOTS or not?

Below the code we use ONLY when *both* FBO and GL_TEXTURE_RECTANGLE are available.


Thanks,

Alberto


glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);

DrawScene(...);

glBindTexture(GL_TEXTURE_RECTANGLE_ARB, color_tex);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGR, GL_UNSIGNED_BYTE, bitmapData);

Ilian Dinev
10-21-2008, 01:10 AM
FBO with texture-rectangle is not slower than tex2D, in my experience.

devdept
10-21-2008, 01:17 AM
Hi Ilian,

My question is: if I use GL_TEXTURE2D and target a rectangular texture will it work on all OpenGL implementations? On my ATI FIRE GL it works.

Thanks,

Alberto

Ilian Dinev
10-21-2008, 01:39 AM
You can safely create an 888x333 GL_TEXTURE_2D if the NPOT extension-string is available. And you can use that texture as a render-target.
Just think about it: all current-gen games do render-to-texture and then do post-processing on that texture :). In DX9/10, there's no texRECT, it's all tex2D.

But if you mean creation of a GL_TEXTURE_RECTANGLE, and then binding that same texture to a GL_TEXTURE_2D target, then I don't know. Your question is ambiguous imho. (also "a rectangular texture" can mean both a 888x333 GL_TEXTURE_2D and an 888x333 GL_TEXTURE_RECTANGLE, so it can be confusing)

Korval
10-21-2008, 01:49 AM
if I use GL_TEXTURE2D and target a rectangular texture will it work on all OpenGL implementations?

No. Not if it is a real rectangle textures.

Rectangle Textures (created with the type GL_TEXTURE_RECTANGLE) are a fundamentally different type from 2D textures. You cannot interchange them with 2D textures.

I suspect ATi works because they use a regular 2D texture for Rectangle Textures internally. nVidia hardware has special handling for rectangle textures.

Please note that rectangle textures are different from NPOT textures (which are not new texture types; they're just a modification for the size rules on textures), which is what Ilian is talking about.

devdept
10-21-2008, 01:51 AM
Ilian,


I thought that when you check for existance of the GL_ARB_TEXTURE_RECTANGLE extension you need to target it as GL_TEXTURE_RECTANGLE_ARB.

By the way here: http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt you find:


3) How is the image of a rectangular texture specified?

Using the standard OpenGL API for specifying a 2D texture
image: glTexImage2D, glSubTexImage2D, glCopyTexImage2D,
and glCopySubTexImage2D. The target for these commands is
GL_TEXTURE_RECTANGLE_ARB though.

This is similar to how the texture cube map functionality uses the 2D
texture image specification API though with its own texture target.

The texture target GL_TEXTURE_RECTANGLE_ARB should also
be used for glGetTexImage, glGetTexLevelParameteriv, and
glGetTexLevelParameterfv.

But your observation is right. It works also specifying GL_TEXTURE2D.

This is the source of my doubts.


Thanks,

Alberto

devdept
10-21-2008, 02:11 AM
Korval,


We are talking about getting a bitmap from a OpenGL viewport, docked inside a variable size Windows form: dimension can be all the possible combinations.

My question is: should I discard the FBO approach if OpenGL extension GL_ARB_texture_rectangle is not available?


Thanks,

Alberto

Ilian Dinev
10-21-2008, 02:33 AM
So, in conclusion:


CFBO* g_FBO;
...
int texWid=111,texHei=444;

if(extensionFBO){
int realTexWid,realTexHei;
if(extensionNPOT){
realTexWid=texWid;
realTexHid=texHid;
}else{
realTexWid = 128; // = fixupSize(texWid);
realTexHei = 512; // = fixupSize(texHei);
}
g_FBO = createFBO(realTexWid,realTexHei,texWid,texHei); // this uses only GL_TEXTURE_2D
}else{
#if OK_TO_USE_glCopyTexImage2D
g_FBO = null;
#else
msgbox("Sorry, but Radeon9550 or even more ancient silicon is not supported");
ExitProcess(0);
#endif
}

devdept
10-21-2008, 02:38 AM
Ilian,

Yes, more or less like you coded but glCopyTexImage2D would need to handle NPOT dimensions, that's why we use glReadPixels.

Alberto

dletozeun
10-21-2008, 06:06 AM
Your wording is quite confusing for me. o

There may be only a "problem" if the ARB_texture_non_power_of_two is not supported and ARB_texture_rectangle is (you say the opposite IMO).

if ARB_texture_non_power_of_two is supported, you do anything you want.

Actually, what do you practically need to do? Retrieve image data in a texture or in system memory? glReadPixels and glCopyTexImage2D is not for the same purpose...

devdept
10-21-2008, 06:37 AM
dletozeun,

We need to get the OpenGL viewport contents in a bitmap. AFAIK the fastest method is FBO and FBO requires to pass through a texture, right?

Supposing that the viewport can have any dimension combination, do I need the ARB_texture_rectangle or I need only the ARB_texture_non_power_of_two?

Thanks,

Alberto

glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);

DrawScene(...);

glBindTexture(GL_TEXTURE_RECTANGLE_ARB, color_tex);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGR, GL_UNSIGNED_BYTE, bitmapData);

V-man
10-21-2008, 07:31 AM
dletozeun,
We need to get the OpenGL viewport contents in a bitmap. AFAIK the fastest method is FBO and FBO requires to pass through a texture, right?


No, you can make a RenderBuffer instead.



glGenFramebuffersEXT(1, &fboID2);
glBindFramebufferEXT(GL_FRAMEBUFFER, fboID2);
glGenRenderbuffersEXT(1, &ColorBufferID2);
glBindRenderbufferEXT(GL_RENDERBUFFER, ColorBufferID2);
glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_RGBA8, width, height);
glGenRenderbuffersEXT(1, &DepthBufferID2);
glBindRenderbufferEXT(GL_RENDERBUFFER, DepthBufferID2);
glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ColorBufferID2);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, DepthBufferID2);

ReturnVal=glExtCheckFramebufferStatus();


and use glReadPixels

devdept
10-21-2008, 07:36 AM
Is it fast like the one I shown above?

glReadPixel isn't always slow?

Thanks,

Alberto

devdept
10-21-2008, 07:40 AM
By the way, what is the real difference between GL_ARB_texture_rectangle and ARB_texture_non_power_of_two and NV_texture_rectangle?

Thanks,

Alberto

Brolingstanz
10-21-2008, 09:17 AM
Frankly, in these modern times, I don't see the point in da texture rect.

Put it this way: what can you do with a rect that you can't do with a NPOT? (without getting nasty).

dletozeun
10-21-2008, 10:34 AM
Is it fast like the one I shown above?

glReadPixel isn't always slow?


I don't know how glGetTexImage and glReadPixels work internally, but I seeing their prototype I want to say that they do the same thing (I mean, for 2D texture) if you omit the thing that the 1st operate on a texture and the 2nd on the framebuffer.
So IMO none of them is faster than the other.



By the way, what is the real difference between GL_ARB_texture_rectangle and ARB_texture_non_power_of_two and NV_texture_rectangle?


You need to take a look to these extension spec (just the description). It is helpful.

Very quickly. GL_ARB_texture_rectangle allow you to use NPOT 2D and only 2D texture but all native wrap mode are not supported and texture coordinates are not normalized. You need to use in addition, a special texture target : TEXTURE_RECTANGLE_ARB

When ARB_texture_non_power_of_two is supported, it is like, you hardware support 1D, 2D, 3D and cube map NPOT texture natively. You don't need any special target, you keep the current ones. So you have litterally nothing much to do and you don't have to care of texture dimension whatsoever the texture nature.
In addition, all wrapping mode, mipmapping, normalized texture coordinates are supported.

Now, hoping that you understand this, you will see that you actually don't have any problem to copy the data in system memory.

Korval
10-21-2008, 10:51 AM
Supposing that the viewport can have any dimension combination, do I need the ARB_texture_rectangle or I need only the ARB_texture_non_power_of_two?

Either one. NPOT requires higher-end hardware, but texture_rectangle isn't going to go into the standard (and there are limits in glslang as to the use of it).


By the way, what is the real difference between GL_ARB_texture_rectangle and ARB_texture_non_power_of_two and NV_texture_rectangle?

A GL_TEXTURE_RECTANGLE is not a GL_TEXTURE_2D. That's probably the #1 most important take home point. If you create a texture rectangle, it is as different from a GL_TEXTURE_2D as a GL_TEXTURE_2D is from a GL_TEXTURE_CUBE. You cannot interchange them.

NPOT isn't a new texture type; it is merely a change to the wording in the spec. It removes the restriction for all texture types that the sizes be 2^n.

Also, GL_TEXTURE_RECTANGLE textures are access in pixel units, not normalized texture coordinates [0.0, 1.0].

devdept
10-21-2008, 02:40 PM
Either one. NPOT requires higher-end hardware, but texture_rectangle isn't going to go into the standard (and there are limits in glslang as to the use of it).


Mmm... so what would you use to display a 333x888 bitmap into a 333x888 viewport?

I start to be a little confused.

Thanks,

Alberto

Korval
10-21-2008, 02:50 PM
Mmm... so what would you use to display a 333x888 bitmap into a 333x888 viewport?

What part of "Either one" is confusing to you? Check the extensions; if one of them is available, use it. If it isn't, check the other. If neither, punt or some fallback.

devdept
10-21-2008, 02:59 PM
You are right, differences a well explained in the specification.

I will opt for the non_poer_of_two and stretch the bitmap to the closest POT dimension if it is missing.

Thanks,

Alberto


+ In ARB_texture_non_power_of_two:
* mipmapping is allowed, default filter remains unchanged.
* all wrap modes are allowed, default wrap mode remains unchanged.
* borders are supported.
* paletted textures are not unsupported.
* texture coordinates are addressed parametrically [0..1],[0..1]
+ In EXT_texture_rectangle:
* mipmapping is not allowed, default filter is changed to LINEAR.
* only CLAMP* wrap modes are allowed, default is CLAMP_TO_EDGE.
* borders are not supported.
* paletted textures are unsupported.
* texture coordinates are addressed non-parametrically [0..w],[0..h].

devdept
10-21-2008, 03:14 PM
I don't know how glGetTexImage and glReadPixels work internally, but I seeing their prototype I want to say that they do the same thing (I mean, for 2D texture) if you omit the thing that the 1st operate on a texture and the 2nd on the framebuffer.
So IMO none of them is faster than the other.

Any other opinion on this?

Thanks,

Alberto

V-man
10-21-2008, 10:53 PM
Theoretically, glGetTexImage should be slower since some or on all GPUs, the texture is stored in a certain swizzled format for better cache performance. I imagine that render buffers are stored in a linear fashion and should yeild better performance with glReadPixels.

Korval
10-22-2008, 12:31 AM
I imagine that render buffers are stored in a linear fashion and should yeild better performance with glReadPixels.

Of course, this is moot if you're reading from a texture rather than a renderbuffer.

devdept
10-22-2008, 12:38 AM
Thanks to you all guys !!!