Dynamic cube map generation and rendering

hi,
I succefully obtained a cube map at runtime
but in 6 GL_TEXTURE_2D only.
it looks correct on a textured cube.

I’m trying to use them with GL_TEXTURE_CUBE_MAP_ARB.
found some examples but i don’t know where i am wrong.
if you seen any error, notify me please ^^
any comment is welcome.

/* UpdateCubeMap()*/

for (i=0;i<6;i++)
  { 
    glLoadIdentity();
    /* appropriate call to glulookat(); */
    glPushMatrix();
    glViewport(0,0,256,256);

    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );

    RenderScene();

    glEnable(GL_TEXTURE_CUBE_MAP_ARB);
    glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, WP->textures[52] /*cube map texture*/);

    glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, 0, 0, 0, 0, 256, 256);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i,GL_TEXTURE_WRAP_T,GL_CLAMP);
    glDisable(GL_TEXTURE_CUBE_MAP_ARB);
  }
 

/* rendering */

 
glPushMatrix();

   glEnable(GL_TEXTURE_CUBE_MAP_ARB);
   glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, WP->textures[52] /*cube map texture*/);

   glTranslatef(...);
   glRotatef(...);
   glScalef(...);

   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
   glEnable(GL_TEXTURE_GEN_S);
   glEnable(GL_TEXTURE_GEN_T);
   glEnable(GL_TEXTURE_GEN_R);

     glutSolidTeapot(1.0);

   glDisable(GL_TEXTURE_GEN_S);
   glDisable(GL_TEXTURE_GEN_T);
   glDisable(GL_TEXTURE_GEN_R);
   glDisable(GL_TEXTURE_CUBE_MAP_ARB);

glPopMatrix();
 

thx


brucemangy

it might help if you state what the problem is, rather than have us guess, or dig around in your code for a syntax/semantic error. what is the problem, exactly?

btw, these tired eyes didn’t see anything wrong with the snippet you posted, fwiw @_@ .

i only have a white texture
my renderering is correct but not the copy in
the GL_TEXTURE_CUBE_MAP_ARB.
that is so weird to copy 6 textures in one GLuint.
BTW, is there any way to check if the texture is correctly copied ?
with a GL_TEXTURE_2D it is easy … you juste render a quad with the texture.

ok, just spotted a nasty. you need to submit the texture using glTexImage2D()/glCopyTexImage2D() before using the sub versions. use glCopyTexImage2D() on first bind, then glCopyTexSubImage2D() thereafter.

BTW, is there any way to check if the texture is correctly copied ?
with a GL_TEXTURE_2D it is easy … you juste render a quad with the texture.
affirmative, same as for 2d, except that you need 6 quads instead of 1.

ok,
so something like that would work :

  glEnable(GL_TEXTURE_CUBE_MAP_ARB);
  glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, WP->textures[52] /*cube map*/);
  if (i==0)
  glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, 0, 0, 0, 0, 256, 256);
  else 
  glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, 0, 0, 0, 0, 256, 256);
  

but there must be another problem if what i have written is correct …
it’s still white.
i’m really not good at allocating memory.
i’m juste copying over a simple 256x256 texture…
the problem may be there.
i’m not quite sure how to allocate the memory for such a texture.
size 6256256*3 bytes (if in GL_RGB) ?
i have seen 2 or 3 sources of example of cube mapping and the memory allocation were not simple to understand.
you may be able to do if you think memory allocation can be the problem.

void glCopyTexImage2D(
GLenum target,
GLint level,
GLenum internalFormat,
GLint x,
GLint y,
GLsizei width,
GLsizei height,
GLint border
);

you only need to call this function once, the very first time the cubemap is ever bound.

then use

void glCopyTexSubImage2D(
GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLint x,
GLint y,
GLsizei width,
GLsizei height
);

thereafter.

why are you fooling with memory? gl does all that for you on copy.

but fyi:

for 2D:
mem = num_components * 8 * width * height

for 3D:
mem = num_components * 8 * width * height * depth

for RGB, num_components = 3
for RGBA, num_components = 4
and so on…

you need to tack on mip level storage to this, but you get the idea.

oh, tack on borders too (if used)…

you can get the poop here (a must read)
http://www.opengl.org/documentation/spec.html

ok i already have a texture before any rendering of the cube map so it cannot be the problem thx

i have questions about a few line of code :

  glEnable(GL_TEXTURE_CUBE_MAP_ARB);
  glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, WP->textures[52] /*cube map*/);
  glCopyTex(Sub)Image2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, 0, 0, 0, 0, 256, 256);

you see i always bind the same gluint in the glBindTexture
this is correct ?
i only have to bind this WP->texture[52] in this example to render the cubemap ?

gl makes the distinction between the different faces with the first parameter of glCopyTex(Sub)Image2D?
for each face i give a different parameter.
(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i)
for what i have seen, it seems still correct.

i really can’t see where the problem can be …

you see i always bind the same gluint in the glBindTexture
this is correct ?
i only have to bind this WP->texture[52] in this example to render the cubemap ?
yes, that’s correct. gl understands that the bind has a cubemap target.

gl makes the distinction between the different faces with the first parameter of glCopyTex(Sub)Image2D?
look carefully at the prototypes, they have the same number of arguments, but they don’t have the same meaning. that’s why i posted them to begin with :stuck_out_tongue: .

if (i==0)
glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, GL_RGB, 0, 0, 256, 256, 0);
else
glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, 0, 0, 0, 0, 256, 256);

seems better,
my parameters were wrong thx
but i still have a white teapot :stuck_out_tongue:

(i can provide you the code of my project if you want to have a look.)

i tried a lot of things but there seems to be many errors (even if you didn’t noticed them all) so i can’t really know if i corrected one :stuck_out_tongue:

thank you for your help

bruce, i would build a tiny, stripped down test app that simply reads and draws a cubemap to the screen. actually, just draw a cubemap to the screen, so you know it works (a cube of smiley faces or whatever). try that, and if you can’t get that working, post it here, and we’ll all go from there. cool? i could go for some hot java…gotta get my head outa my arse.

i’m tired it’s 07:30 here and i didn’t slept
not really a “stripped down test app”
but the project is so big …

http://gorre.nerim.net/cube_map_fail.rar
(you will need glut glui and gl
in Visual C++)

the interesting code is in glut_fcts.cpp
line 590 for the render to texture
line 811 for the rendering of the teapot

i rendered directly on the screen the six textures.

if you have an IRC client, you can find me on quakenet.org #brucemangy
we are just making a huge thread for nothing ^^

bruce, sorry buddy, it hurts my head to look at a lot of code, especially after looking at my own mess all day. it would be for your benefit as well to create a very simple little glut app. that way you can isolate the problem, and hack away at it. i always have a little skeleton app on the side for quick tests. it sure helps. in fact, i created a little debug framework for just that purpose, just because i use it so much. if a new extension comes out, i can plug it in, and try it on for size, without having to hack it into a much larger project (very nasty). i wouldn’t leave home without it…

if (i==0)
glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, GL_RGB, 0, 0, 256, 256, 0);
else 
glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, 0, 0, 0, 0, 256, 256);

This won’t help much.
You have to allocate the texture space for all faces.

The easiest way :

glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, GL_RGB, 0, 0, 256, 256, 0);
// without testing (i==0)

The most efficient way :

glCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, 0, 0, 0, 0, 256, 256);

and pre-allocate your texture memory (when you get the texture names for instance) somewhere in your initialization sequence :

glGenTextures(52, WP->textures);
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, WP->textures[52]);
for (int i=0;i<6;++i)
  glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

Also, make sure you have disabled mipmapping otherwise you will have to fill all mipmap levels (filling them can be simplified/accelerated thanks to the GL_SGIS_generate_mipmap extension but for textures changing very often I always recommend disabling mipmapping).

// Use GL_LINEAR instead of GL_LINEAR_MIPMAP_LINEAR, for instance
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

White textures are usually a symptom of bad texture filtering state … urm …

Originally posted by brucemangy:
[b]/* UpdateCubeMap()*/

for (i=0;i<6;i++)
  { 
/* stuff */
glTexParameteri(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i,GL_TEXTURE_WRAP_T,GL_CLAMP);
    glDisable(GL_TEXTURE_CUBE_MAP_ARB);
  }
 

[/b]
Aren’t clamp/filter modes supposed to be per target, not per face?
Try

glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,GL_TEXTURE_WRAP_T,GL_CLAMP);

And you only need this once, btw.
Hope this helps, don’t slap me if it doesn’t.

Aren’t clamp/filter modes supposed to be per target, not per face?
Yes it is per target.

ok,
started from a the Lesson 33 of nehe.
(it has TGA loading)
rendered an explicit “skybox”
a teapot with the parameters for cubemap

the only part missing is the loading of the cubemap.

http://gorre.nerim.net/cubemap.rar
(1.2 MB)

would you please have a look ?
i can’t do anything simpler ^^


brucemangy

ok thx vincoof
you were all right
besides i would never slap someone helping me ^^

ok no more white texture ^^
a few bugs but it can be fixed quickly

UPDATE
http://gorre.nerim.net/screenshot1.jpg
only a prob with texturing…
thank you very much guys.

UPDATE2
http://gorre.nerim.net/cubemap2.jpg
this looks quite good ^^

i think you guys nailed in 3 minutes what i couldn’t see in 3 hours. alas, fresher heads prevail. thanks to vincoof and zeckensack for their astute observations.

i would still strongly recommend building a separate test app for each new extension, so that you can rigorously test it. i further suggest reading the extension spec at least a dozen times (if you’ve got swiss-cheese memory like mine).