Sign in to follow this  
Bakura

Mipmapping not working with FBO ? Why ?

Recommended Posts

Hi ! My problem is that it seems that I can't get working mipmapping with textures generated on an offscreen buffer (FBO). What I want is a texture base level, and each pixel of sublevels textures being the average value of the four pixels of the previous level. I tried to generate them by myself on the GPU, but it's much more slower than automatic mipmap generation. If I remember well, what I want is defined by GL_LINEAR_MIPMAP_NEAREST for MIN_FILTERING (bilinear). Here is how I do :
[source code="cpp"]
glGenFramebuffersEXT (1, &lightPyramidsCreationFBO);
	
	glGenTextures (1, &lightPyramidsCreationPosition);
	glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationPosition);
	glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, 512, 512, 0, GL_RGBA, GL_FLOAT, NULL);
	glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
        glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
	
	glGenTextures (1, &lightPyramidsCreationNormal);
	glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationNormal);
	glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, 512, 512, 0, GL_RGBA, GL_FLOAT, NULL);
	glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
        glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
		
	glGenTextures (1, &lightPyramidsCreationIntensity);
	glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationIntensity);
	glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, 512, 512, 0, GL_RGBA, GL_FLOAT, NULL);
	glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
        glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

	glBindTexture (GL_TEXTURE_2D, 0);
	
	glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, lightPyramidsCreationFBO);
	glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, lightPyramidsCreationPosition, 0);
	glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, lightPyramidsCreationNormal, 0);
	glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, lightPyramidsCreationIntensity, 0);

	GLenum status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
	if (status == GL_FRAMEBUFFER_COMPLETE_EXT)
		std::cerr << "No problem" << std::endl;

Then my shader writes to the 3 textures (with gl_FragData[0-1-2]). I precise that glGenerateMipmapsEXT doesn't seem to work on ATi cards (I've got a 3870HD). Next, I draw some quads in order to see if mipmapping has worked : if I set GL_NEAREST or GL_LINEAR for MIN_FILTERING, all the textures work but each subtextures is the same than the others (no average values as I want). If I set GL_*_MIPMAP_*, only the base level works, all of the sublevels textures are entirely black, but don't know why ! In the same time, the textures have been generated because if I call those lines : GLfloat data1, data2; glGetTexLevelParameterfv (GL_TEXTURE_2D, 1, GL_TEXTURE_WIDTH, &data1); glGetTexLevelParameterfv (GL_TEXTURE_2D, 1, GL_TEXTURE_HEIGHT, &data2); std::cout << data1 << '*' << data2 << std::endl; I get 256*256... Thanks for your help :)

Share this post


Link to post
Share on other sites
glGenerateMipmapsEXT should work with ATI cards... You need to create all the mipmap levels first though. I am not sure if RGBA16 is a supported format on ATI cards for mipmapping with FBOs... I use Nvidia so I can't comment on this. I do know you can use glGenerateMipmapsEXT and that it was created for FBOs. So create all your mipmap levels manually and call glGenerateMipmapsEXT. Also what errors are you getting back from GL if any for the FBO...

Share this post


Link to post
Share on other sites
Hi,

I've already tried that. I don't know exactly where do I have to put glGenerateMipmapEXT, so I tried at various places (during creation of textures, after binding the framebuffer, before binding the framebuffer)... The base level still work, but all sublevels are black. As the previous methods, if I set GL_LINEAR or GL_NEAREST for min filter, it works, but with GL_*_MIPMAP_*, black screen :/.

[source code="cpp"]
glGenTextures (1, &lightPyramidsCreationPosition);
glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationPosition);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, 512, 512, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 1, GL_RGBA16F_ARB, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 2, GL_RGBA16F_ARB, 128, 128, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 3, GL_RGBA16F_ARB, 64, 64, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 4, GL_RGBA16F_ARB, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 5, GL_RGBA16F_ARB, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 6, GL_RGBA16F_ARB, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 7, GL_RGBA16F_ARB, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 8, GL_RGBA16F_ARB, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 9, GL_RGBA16F_ARB, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glGenerateMipmapEXT (GL_TEXTURE_2D);
//glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

glGenTextures (1, &lightPyramidsCreationNormal);
glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationNormal);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, 512, 512, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 1, GL_RGBA16F_ARB, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 2, GL_RGBA16F_ARB, 128, 128, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 3, GL_RGBA16F_ARB, 64, 64, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 4, GL_RGBA16F_ARB, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 5, GL_RGBA16F_ARB, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 6, GL_RGBA16F_ARB, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 7, GL_RGBA16F_ARB, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 8, GL_RGBA16F_ARB, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 9, GL_RGBA16F_ARB, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glGenerateMipmapEXT (GL_TEXTURE_2D);
//glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

glGenTextures (1, &lightPyramidsCreationIntensity);
glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationIntensity);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, 512, 512, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 1, GL_RGBA16F_ARB, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 2, GL_RGBA16F_ARB, 128, 128, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 3, GL_RGBA16F_ARB, 64, 64, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 4, GL_RGBA16F_ARB, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 5, GL_RGBA16F_ARB, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 6, GL_RGBA16F_ARB, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 7, GL_RGBA16F_ARB, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 8, GL_RGBA16F_ARB, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 9, GL_RGBA16F_ARB, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glGenerateMipmapEXT (GL_TEXTURE_2D);
//glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);




About the compatibility with ATi cards, I've read that on OpenGL officiel forum (http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=237975) see second post.

Share this post


Link to post
Share on other sites
The normal method of doing this is;

@ Init
- create FBO
- create target texture with GL_LINEAR and GL_NEAREST filters
- (optionally) bind texture to FBO

@ Render
- bind FBO as target
- (optionally) bind texture to FBO
- render as normal
- unbind FBO
- bind texture (glBindTexture(GL_TEXTURE_2D,textureid);)
- call glGenerateMipmapsEXT
- set texture filter to mipmap'd filter
- use

glGenerateMipmapsEXT should work fine on ATI cards, at least up to the X1900 series I last had, I'd even used it. I can't speak for anything newer.

My only pondering would be what V-man brought up; does the hardware support mipmap'd floating point textures; I think everything does but don't quote me on that.

Share this post


Link to post
Share on other sites
Quote:
Original post by MARS_999
I am not sure if RGBA16 is a supported format on ATI cards for mipmapping with FBOs...


Not to be a stick in the mud, but I stated that a long time ago. This is one reason ATI support sucks as they don't have documentation that is easy to find.

Anyway from their docs...

They may only be sampled as NEAREST or NEAREST_MIPMAP_NEAREST since floating point texture filtering is not supported.

So if you want to use mipmapping with some other format then you will need to do it in the fragment shader. Sorry.

Share this post


Link to post
Share on other sites
Hi ! First of all thank you for having answering me.

It doesn't work either. Here is how I do :

Init time :

[source code="cpp"]

glGenFramebuffersEXT (1, &lightPyramidsCreationFBO);

glGenTextures (1, &lightPyramidsCreationPosition);
glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationPosition);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, 512, 512, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 1, GL_RGBA16F_ARB, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 2, GL_RGBA16F_ARB, 128, 128, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 3, GL_RGBA16F_ARB, 64, 64, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 4, GL_RGBA16F_ARB, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 5, GL_RGBA16F_ARB, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 6, GL_RGBA16F_ARB, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 7, GL_RGBA16F_ARB, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 8, GL_RGBA16F_ARB, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 9, GL_RGBA16F_ARB, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

glGenTextures (1, &lightPyramidsCreationNormal);
glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationNormal);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, 512, 512, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 1, GL_RGBA16F_ARB, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 2, GL_RGBA16F_ARB, 128, 128, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 3, GL_RGBA16F_ARB, 64, 64, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 4, GL_RGBA16F_ARB, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 5, GL_RGBA16F_ARB, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 6, GL_RGBA16F_ARB, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 7, GL_RGBA16F_ARB, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 8, GL_RGBA16F_ARB, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 9, GL_RGBA16F_ARB, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

glGenTextures (1, &lightPyramidsCreationIntensity);
glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationIntensity);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, 512, 512, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 1, GL_RGBA16F_ARB, 256, 256, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 2, GL_RGBA16F_ARB, 128, 128, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 3, GL_RGBA16F_ARB, 64, 64, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 4, GL_RGBA16F_ARB, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 5, GL_RGBA16F_ARB, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 6, GL_RGBA16F_ARB, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 7, GL_RGBA16F_ARB, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 8, GL_RGBA16F_ARB, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
glTexImage2D (GL_TEXTURE_2D, 9, GL_RGBA16F_ARB, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);





Render time :

[source="cpp"]
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();

gluLookAt (0.0f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glTranslatef (0.0, -5.0, 0.0);
//glRotatef (25.0f, 1.0f, 0.0f, 0.0f);

// On rend la scène dans le framebuffer
glUseProgram (lightPyramidsCreationProg);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, lightPyramidsCreationFBO);

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

GLenum buffers[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT};

glDrawBuffers (3, buffers);
RenderScene();

glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);

glUseProgram (0);

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// On rend les textures à l'écran
glEnable (GL_TEXTURE_2D);
glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationPosition);
glGenerateMipmapEXT (GL_TEXTURE_2D);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);

GLfloat data1, data2;
glGetTexLevelParameterfv (GL_TEXTURE_2D, 1, GL_TEXTURE_WIDTH, &data1);
glGetTexLevelParameterfv (GL_TEXTURE_2D, 1, GL_TEXTURE_HEIGHT, &data2);
std::cout << data1 << '*' << data2 << std::endl;

DrawQuad (256.0, 256.0);
glBindTexture (GL_TEXTURE_2D, 0);
glDisable (GL_TEXTURE_2D);





I tried with RGBA8 textures (unsigned byte), but it doesn't work either, but instead of being all black, the texture is all white (not much better ^_^).

Please, could somebody with a 3870HD give me some details ?

EDIT > MARS_99 : Oh, this is not a good news :|... I've tried to generate them on the GPU, but it's quite expensive (lot of texture lookups :/), and not practical, and with larger textures, it'll be more and more expensive !! But the whole algorithm relieves on those mipmaps textures, so I have no solution :/. Fuck you ATi. I decided to buy again an ATi card because I was quite happy with their old stuff (9800 Pro) and I wanted to encourage them, but that's not great !! (NB : GL_NEAREST and GL_NEAREST_MIPMAP_NEAREST doesn't work either, black texture...)

EDIT : I found the ATI doc that you quoted... But it was a documentation of the R300 (9700 and 9800), I'm sure it has changed now... :(

[Edited by - Bakura on May 8, 2008 2:13:05 PM]

Share this post


Link to post
Share on other sites
I know this can be frustrating, but hang in there.

I see with the init code you call
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

then with the rendering you call

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);

I am guessing you need to call the min filter with a mipmapping type. Maybe the driver isn't using mipmapping due to the GL_NEAREST call...

Also have you tried RGBA32F...

I don't see a call to glGenerateMipmapEXT(GL_TEXTURE_2D); after each set of Bound texture objects. IIRC you need to do this to establish a mipmap chain...

Share this post


Link to post
Share on other sites
Hi,

I just apply what phantom said (look at his message). At me too it doesn't look really logical to set some filters at init time and other filters at render time, but he said it was the right way (if I understood well his message).

GL_RGBA32F doesn't work either.

Again, I did what phatnom said : call glGenerateMipmapEXT after binding the texture for rendering. And this I what I did. But if I call glGenerateMipmapEXT after binding each texture at init time, it doesn't work either.

Really frustrating... It's sure that all developers doesn't use OpenGL anymore if the support isn't good...

Share this post


Link to post
Share on other sites
Hi again !

I contacted Humus because I think he works at ATi in order to know :). Secondly, I've tried with UNSIGNED_BYTE textures RGBA, so there is no reason not to work... but it doesn't.

This framebuffer extension has managed to make me angry and want to break everything, which is a miracle !

Share this post


Link to post
Share on other sites
OpenGL works like a charm for me and quite a few others I know. Can you do this without mipmapping first to see if that works... Try that first, and then move onto mipmapping. If you can't get the code to work without mipmapping something is seriously wrong.

BTW Humus doesn't work for ATI anymore, but he should know what to do.

Share this post


Link to post
Share on other sites
Hi,

Without mipmapping it works well, even for GL_RGBA32F textures, with GL_NEAREST or GL_LINEAR. The problem is when I generate mipmap and try to render them... If my texture is 512*512 and all mipmaps generated, normally it should draw me the 256*256 texture if I draw a 256*256 quad (this is how it works when I generated them by myself in the fragment shader, but it's way too slow when you have several textures to generate...).

I think the best way to solve this problem is that I give you a minimal program that doesn't work, and then person who have ATi cards can test. I'm doing that... There I tried with GL_GENERATE_MIPMAP extension, but you can easily try with glGenerateMipmapEXT. Morever, as it uses SFML you may have to change the main (by using SDL or GLUT). The fragment shader just writes to the three textures (gl_FragData[0], gl_FragData[1], gl_FragData[2].

[source="cpp"]
#include <iostream>
#include <cstdlib>
#include <GL/glew.h>
#include <cmath>
#include <SFML/Window.hpp>


// Identifiant des vertex & fragment shaders, et des framebuffers
GLuint lightPyramidsCreationVert;
GLuint lightPyramidsCreationFrag;
GLuint lightPyramidsCreationProg;

GLuint lightPyramidsCreationFBO;
GLuint lightPyramidsCreationPosition;
GLuint lightPyramidsCreationNormal;
GLuint lightPyramidsCreationIntensity;

// Chargement d'un fichier texture
char* LoadSource(const char *filename)
{
char *src = NULL; // code source de notre shader
FILE *fp = NULL; // fichier
long size; // taille du fichier
long i; // compteur


// on ouvre le fichier
fp = fopen(filename, "r");
// on verifie si l'ouverture a echoue
if(fp == NULL)
{
fprintf(stderr, "impossible d'ouvrir le fichier '%s'\n", filename);
return NULL;
}

// on recupere la longueur du fichier
fseek(fp, 0, SEEK_END);
size = ftell(fp);

// on se replace au debut du fichier
rewind(fp);

// on alloue de la memoire pour y placer notre code source
src = (char*)malloc(size+1); // +1 pour le caractere de fin de chaine '\0'
if(src == NULL)
{
fclose(fp);
fprintf(stderr, "erreur d'allocation de memoire!\n");
return NULL;
}

// lecture du fichier
for(i=0; i<size; i++)
src[i] = fgetc(fp);

// on place le dernier caractere a '\0'
src[size] = '\0';

fclose(fp);

return src;
}

void InitOGL ()
{
glewInit ();

// Set color and depth clear value
glClearDepth(1.f);
glClearColor(0.f, 0.f, 0.3f, 1.f);

// Enable Z-buffer read and write
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);

// Setup a perspective projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glViewport (0, 0, 512, 512); // On règle le Viewport

glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (60.0, 512.0 / 512.0, 1.0, 400.0);

glMatrixMode (GL_MODELVIEW);
glLoadIdentity (); // On rétablit la matrice identité

// On charche, dans un premier temps, les shaders
lightPyramidsCreationVert = glCreateShader (GL_VERTEX_SHADER);
lightPyramidsCreationFrag = glCreateShader (GL_FRAGMENT_SHADER);

char * source3 = LoadSource ("LightPyramidsCreation.vert");
char * source4 = LoadSource ("LightPyramidsCreation.frag");
glShaderSource (lightPyramidsCreationVert, 1, (const GLchar **)&source3, NULL);
glShaderSource (lightPyramidsCreationFrag, 1, (const GLchar **)&source4, NULL);

glCompileShader (lightPyramidsCreationVert);
glCompileShader (lightPyramidsCreationFrag);

lightPyramidsCreationProg = glCreateProgram ();

glAttachShader (lightPyramidsCreationProg, lightPyramidsCreationVert);
glAttachShader (lightPyramidsCreationProg, lightPyramidsCreationFrag);

glLinkProgram (lightPyramidsCreationProg);


// On créé à présent le framebuffer, ainsi que les deux textures destinées à recevoir le tout
glGenFramebuffersEXT (1, &lightPyramidsCreationFBO);

glGenTextures (1, &lightPyramidsCreationPosition);
glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationPosition);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

glGenTextures (1, &lightPyramidsCreationNormal);
glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationNormal);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

glGenTextures (1, &lightPyramidsCreationIntensity);
glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationIntensity);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

glBindTexture (GL_TEXTURE_2D, 0);

glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, lightPyramidsCreationFBO);
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, lightPyramidsCreationPosition, 0);
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, lightPyramidsCreationNormal, 0);
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, lightPyramidsCreationIntensity, 0);

GLenum status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
if (status == GL_FRAMEBUFFER_COMPLETE_EXT)
std::cerr << "Creation du framebuffer parfaite" << std::endl;

glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
}

void Destroy ()
{
glDeleteShader (lightPyramidsCreationVert);
glDeleteShader (lightPyramidsCreationFrag);
glDeleteProgram (lightPyramidsCreationProg);

glDeleteTextures (1, &lightPyramidsCreationPosition);
glDeleteTextures (1, &lightPyramidsCreationNormal);
glDeleteTextures (1, &lightPyramidsCreationIntensity);
glDeleteFramebuffersEXT (1, &lightPyramidsCreationFBO);
}

void RenderScene ()
{
// On dessine un sol
GLfloat gris[] = {0.8f, 0.8f, 0.8f};
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, gris);
glBegin (GL_QUADS);
glNormal3f (0.0f, 1.0f, 0.0f);
glVertex3f (-5.0f, 0.0f, 5.0f);
glVertex3f (-5.0f, 0.0f, -5.0f);
glVertex3f (5.0f, 0.0f, -5.0f);
glVertex3f (5.0f, 0.0f, 5.0f);
glEnd ();

glBegin (GL_QUADS);
glNormal3f (0.0f, -1.0f, 0.0f);
glVertex3f (-5.0f, 10.0f, 5.0f);
glVertex3f (-5.0f, 10.0f, -5.0f);
glVertex3f (5.0f, 10.0f, -5.0f);
glVertex3f (5.0f, 10.0f, 5.0f);
glEnd ();

glBegin (GL_QUADS);
glNormal3f (0.0f, 1.0f, 1.0f);
glVertex3f (-5.0f, 0.0f, -5.0f);
glVertex3f (5.0f, 0.0f, -5.0f);
glVertex3f (5.0f, 10.0f, -5.0f);
glVertex3f (-5.0f, 10.0f, -5.0f);
glEnd ();

GLfloat rouge[] = {1.0f, 0.0f, 0.0f};
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, rouge);
glBegin (GL_QUADS);
glNormal3f (1.0f, 0.0f, 0.0f);
glVertex3f (-5.0f, 0.0f, 5.0f);
glVertex3f (-5.0f, 0.0f, -5.0f);
glVertex3f (-5.0f, 10.0f, -5.0f);
glVertex3f (-5.0f, 10.0f, 5.0f);
glEnd ();

GLfloat vert[] = {0.0f, 1.0f, 0.0f};
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, vert);
glBegin (GL_QUADS);
glNormal3f (-1.0f, 0.0f, 0.0f);
glVertex3f (5.0f, 0.0f, 5.0f);
glVertex3f (5.0f, 0.0f, -5.0f);
glVertex3f (5.0f, 10.0f, -5.0f);
glVertex3f (5.0f, 10.0f, 5.0f);
glEnd ();
}

void DrawQuad (float w, float h)
{
// On utilise une perception 2D
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
gluOrtho2D (0.0, 512.0, 0.0, 512.0);

glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();

glBegin (GL_QUADS);
glTexCoord2f (0.0f, 0.0f);
glVertex2f (0.0f, 0.0f);
glTexCoord2f (1.0f, 0.0f);
glVertex2f (w, 0.0f);
glTexCoord2f (1.0f, 1.0f);
glVertex2f (w, h);
glTexCoord2f (0.0f, 1.0f);
glVertex2f (0.0f, h);
glEnd ();

glMatrixMode (GL_PROJECTION);
glPopMatrix ();
}

void Render ()
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();

gluLookAt (0.0f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glTranslatef (0.0, -5.0, 0.0);

// ------------------------------------ PASSE 1 --------------------------------------
// On rend la scène dans le framebuffer
glUseProgram (lightPyramidsCreationProg);
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, lightPyramidsCreationFBO);

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

GLenum buffers[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT};

glDrawBuffers (3, buffers);
RenderScene();

glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);

glUseProgram (0);

// On rend les textures à l'écran
glEnable (GL_TEXTURE_2D);
glBindTexture (GL_TEXTURE_2D, lightPyramidsCreationPosition);
DrawQuad (256.0, 256.0);
glBindTexture (GL_TEXTURE_2D, 0);
glDisable (GL_TEXTURE_2D);
}

int main()
{
// Create the main window
sf::Window App(sf::VideoMode(512, 512, 32), "SFML OpenGL");

// Create a clock for measuring time elapsed
sf::Clock Clock;

InitOGL ();

// Start game loop
bool Running = true;
while (Running)
{
// Process events
sf::Event Event;
while (App.GetEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
Running = false;

// Escape key : exit
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
Running = false;

// Resize event : adjust viewport
if (Event.Type == sf::Event::Resized)
glViewport(0, 0, Event.Size.Width, Event.Size.Height);
}

// Set the active window before using OpenGL commands
// It's useless here because active window is always the same,
// but don't forget it if you use multiple windows or controls
App.SetCurrent();

Render ();

// Finally, display rendered frame on screen
App.Display();
}

Destroy ();

return EXIT_SUCCESS;
}

Share this post


Link to post
Share on other sites
YES !! I finally get it working !! After long hours of testing... As you'll see, the solution I've found is... awkward and completely unlogical, but since it works, I'll use it until I found better.

Here is how I have to do :

At Init time :

Create all the textures and the first level (set all the levels also work, but I don't think there is any difference). Set GL_LINEAR or GL_NEAREST to both GL_MIN or GL_MAX filtering mode. Setting a mipmap setting make it a black texture. SET GL_GENERATE_MIPMAP TO GL_TRUE.

At draw time :

Draw into the framebuffer, unbind the framebuffer. For each texture that was generated by the FBO, bind it, set the desired filtering mode (here I set GL_LINEAR_MIPMAP_NEAREST), AND CALL glGenerateMipmapEXT. Here, it works.


So yes, I have to use both extensions (GL_SGIS_GENERATE_MIPMAP) and the glGenerateMipmapEXT. And yes, I have to set a non mipmap filtering mode at setup, and I really don't know why, as after binding the texture, I set GL_LINEAR_MIPMAP_NEAREST, and never reset GL_LINEAR, so after the first frame the FBO will use textures with GL_LINEAR_MIPMAP_NEAREST as filtering...

Moreover, I don't know why I have to use both extensions, but it works, I now know it is supported by ATI cards. Finally, I don't know why I have to bind eeach texture and call glGenerateMipmap... I thought it was possible to generate each of them with one call. And here the result :

http://tof.canardplus.com/show/47aa57ed-9d8a-4c27-b618-535221c7cbf5.html (click here)

Share this post


Link to post
Share on other sites
glGenerateMipmapEXT should work, makes me think that either its a driver issue, or you don't have a complete mipmap chain setup, that is why the glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); works. The glGenerateMipmapEXT() doesn't create the mipmaps for you it only updates the chain you have created, IIRC. Either way glad its working for you.

Share this post


Link to post
Share on other sites
Hi,

I'm glad too, but when I create the whole chain by myself and call glGenerateMipmap, it doesn't work. I'll wait three or four drivers and try again the normal way ;).

Share this post


Link to post
Share on other sites
Hi,

Some news from here. Everything got working well, except that I found a subtle bug. In fact, the sublevels were correctly generated, but they were never updated. That is to say that although the base level is updated, all the other sublevels aren't. The only solution I found to update the subbuffers was to reset the texture data of one of the levels (each level work, but deleting the last level - 1*1 texture - is much more faster than deleting the second level).

So, here is how it works well :

1) Create texture (base level), and set GL_LINEAR or GL_NEAREST filters
2) Set GL_GENERATE_MIPMAP to GL_TRUE at init time
3) Draw to the texture via the framebuffer, as usual
4) Bind the texture, call glTexImage2D (GL_TEXTURE_2D, 9, GL_RGBA16F_ARB, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL) for exemple, set GL_LINEAR_MIPMAP_NEAREST filter, and call glGenerateMipmapEXT (GL_TEXTURE_2D), and we're done ! It works

The strange things is that according to the GL_GENERATE_MIPMAP extension spec, only the sublevels are updated, so if I update level 8, only level 9 should be updated, but here, if I update level 9 (1*1 texture), all the levels are updated.

Quite strange :D.

Share this post


Link to post
Share on other sites
According to the GL 2.1 specification, when you make a change to the base level, a complete set of mipmaps are generated. It does not say what should happen when you update a mipmap. This is on p178 Automatic Mipmap Generation.

In principle, you shouldn't use this along with FBO. You should only use glGenerateMipmapsEXT although it doesn't say it anywhere in the spec. I'm just basing this on the fact that glGenerateMipmapsEXT when FBOs were introduced.

Share this post


Link to post
Share on other sites
I would love to only use glGenerateMipmap, as my implementation is really strange, but the problem is that it doesn't work... If somebody could make it working on a ATi card (I've got a 3870 HD) with a minimal code, I would be glad to have to whole source, but I assure you, I've tried everything possible, but I HAVE TO use glGenerateMipmap AND GL_GENERATE_MIPMAP AND reset one of the level. For sure, this is not normal (and certainly not optimal), but this is the only solution that works so far.

I really hope that OGL3.0 will have better support on ATi cards...

Share this post


Link to post
Share on other sites
Just wanted to add that I have also been messing around with this and have not been able to get it work on any ATI card. Nvidia works fine. This makes me think driver bug... did you contact ATI about this?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this