Cubemaps and GL_RGB32F_ARB

Hello everyone,

I’ve been trying to load Paul Debevec’s light probes (actually the cross cube textures) into my program using GL_RGB32F_ARB internal format. To test my code, I have exactly similar code (but that’s my own opinion) for loading GL_RGB (GL_UNSIGNED_BYTE) internal format. Also, I have added functions that help me load individual faces to check my image loader.

To use this texture, right now, I am just using a simple shader program which does a textureCube using the current fragment’s normal(!).

The problem is, that this reflective shading works with the ubyte texture I am using, but shows up as black (indicating that no color is being read in from the texture) when I use the floating point format texture. I am really not sure what’s going on, may be I am missing a subtle detail I need to pay attention to, or something’s so obviously incorrect that I am overlooking.

Also, I tried using the same technique to load the image data into a GL_TEXTURE_2D just to check if my image loading is actually working. The textures show up fine.

Even if I am screwing up something really bad, at least something should show up. Below is the code I am using to load the textures.

Thanks,
verma


	glPushAttrib (GL_ENABLE_BIT); check_gl ();
	glEnable (GL_TEXTURE_CUBE_MAP); check_gl ();

	// I find it hard to get my head around image orienation and stuff, so most of the adjustments to flips and loads have been done
	// using hit and trial.  But if you sit and get the image orientation right in your head, it makes sense
	
	// generate our texture
	glGenTextures (1, &texId); check_gl();
	glBindTexture (GL_TEXTURE_CUBE_MAP, texId); check_gl ();
	
	if (imageType == IMAGE_TYPE_PFM) {
		fprintf (stderr, "... performing a floating point texture load.
");
		// left, -ve x
		fprintf (stderr, "... loading cube face 1
");
		__loadSubImage (img, face_img, face_width, face_height, 0, face_height, width, height);
		__imgFlipVertically (face_img, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB32F_ARB, face_width, face_height, 0, GL_RGB, GL_FLOAT, face_img); check_gl ();
	
		// front, -ve z
		fprintf (stderr, "... loading cube face 2
");
		__loadSubImage (img, face_img, face_width, face_height, face_width, face_height, width, height);
		__imgFlipVertically (face_img, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB32F_ARB, face_width, face_height, 0, GL_RGB, GL_FLOAT, face_img); check_gl ();
	
		// right, +ve x
		fprintf (stderr, "... loading cube face 3
");
		__loadSubImage (img, face_img, face_width, face_height, 2*face_width, face_height, width, height);
		__imgFlipVertically (face_img, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB32F_ARB, face_width, face_height, 0, GL_RGB, GL_FLOAT, face_img); check_gl ();
	
		//top, +ve y
		fprintf (stderr, "... loading cube face 4
");
		__loadSubImage (img, face_img, face_width, face_height, face_width, 2*face_height, width, height);
		__imgFlipHorizontally (face_img, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA32F_ARB, face_width, face_height, 0, GL_RGB, GL_FLOAT, face_img); check_gl ();
	
		// bottom, -ve y
		fprintf (stderr, "... loading cube face 5
");
		__loadSubImage (img, face_img, face_width, face_height, face_width, 0, width, height);
		__imgFlipHorizontally (face_img, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA32F_ARB, face_width, face_height, 0, GL_RGB, GL_FLOAT, face_img); check_gl ();
	
		// back, +ve z, its upside down in the image
		fprintf (stderr, "... loading cube face 6
");
		__loadSubImage (img, face_img, face_width, face_height, face_width, 3*face_height, width, height);
		__imgFlipHorizontally (face_img, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA32F_ARB, face_width, face_height, 0, GL_RGB, GL_FLOAT, face_img); check_gl ();
	
		free (img);
		free (face_img);
	}
	else {
		fprintf (stderr, "... performing a 8-bit per component load.
");
		
		// do a regular PPM loading
		// left, -ve x
		fprintf (stderr, "... loading cube face 1
");
		__loadSubImageC (img_c, face_img_c, face_width, face_height, 0, face_height, width, height);
		__imgFlipVerticallyC (face_img_c, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, face_width, face_height, 0, GL_RGB, GL_UNSIGNED_BYTE, face_img_c); check_gl ();
	
		// front, -ve z
		fprintf (stderr, "... loading cube face 2
");
		__loadSubImageC (img_c, face_img_c, face_width, face_height, face_width, face_height, width, height);
		__imgFlipVerticallyC (face_img_c, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, face_width, face_height, 0, GL_RGB, GL_UNSIGNED_BYTE, face_img_c); check_gl ();
	
		// right, +ve x
		fprintf (stderr, "... loading cube face 3
");
		__loadSubImageC (img_c, face_img_c, face_width, face_height, 2*face_width, face_height, width, height);
		__imgFlipVerticallyC (face_img_c, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, face_width, face_height, 0, GL_RGB, GL_UNSIGNED_BYTE, face_img_c); check_gl ();
	
		//top, +ve y
		fprintf (stderr, "... loading cube face 4
");
		__loadSubImageC (img_c, face_img_c, face_width, face_height, face_width, 0, width, height);
		__imgFlipHorizontallyC (face_img_c, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, face_width, face_height, 0, GL_RGB, GL_UNSIGNED_BYTE, face_img_c); check_gl ();
	
		// bottom, -ve y
		fprintf (stderr, "... loading cube face 5
");
		__loadSubImageC (img_c, face_img_c, face_width, face_height, face_width, 2*face_height, width, height);
		__imgFlipHorizontallyC (face_img_c, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, face_width, face_height, 0, GL_RGB, GL_UNSIGNED_BYTE, face_img_c); check_gl ();
	
		// back, +ve z, its upside down in the image
		fprintf (stderr, "... loading cube face 6
");
		__loadSubImageC (img_c, face_img_c, face_width, face_height, face_width, 3*face_height, width, height);
		__imgFlipHorizontallyC (face_img_c, face_width, face_height);
		glTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, face_width, face_height, 0, GL_RGB, GL_UNSIGNED_BYTE, face_img_c); check_gl ();

		free (img_c);
		free (face_img_c);		
	}

	// set some default properties
	glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); check_gl();
	glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); check_gl();
	glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); check_gl();
	glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); check_gl();

	unbindCubeMap ();

	glPopAttrib ();
	return texId;

Here are the shaders I am using:


// vertex shader
//
varying vec3 normal;		// normal in our eye space

void main () {
	normal = normalize (gl_NormalMatrix * gl_Normal);
	gl_Position = ftransform ();
}

// fragment shader
//
uniform samplerCube	cubemap;
varying vec3 		normal;

void main (void) {
	vec3 n = normalize (normal);
	gl_FragColor = textureCube (cubemap, n);
}

Sorry, forgot to mention, :smiley: … I am using a nVidia GeForce 8600 GTS 256 MB graphics card.

Seems like 16F is working.

Hmm, what is the size of your cube map textures (face_width, face_height)? Have you tried reducing these values when you supply the data for GL_RGB32F_ARB ?

256x256, the entire cube cross texture is 768x1024.

I believe GL_LINEAR filtering is not supported for 32 bit fp textures.

hmm … that could be the case, I cannot test it right now, but as soon as I am able to I will try using GL_NEAREST and see if it works. However if this limitation exists, it should only apply to GL_TEXTURE_CUBE_MAP because I have been able to specify upto GL_LINEAR_MIPMAP_LINEAR for GL_TEXTURE_2D.

That’s possible. I know that up till the GeForce 7 series linear fp32 filtering does work but it uses a slow software fallback implementation. Maybe it hasn’t been implemented for cubemaps.
I’m not 100% sure it’s not supported on GeForce 8 series but I recall reading that it’s one of the reasons that it’s a DX10 card and not a DX10.1 one.

I can confirm that fp32 filtering does indeed work with cubemaps on the 8800. :smiley:

If it helps, this is the code that worked for me:

void loadFloatCube(GLuint dest)
{
    glBindTexture(GL_TEXTURE_CUBE_MAP, dest);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

    GLfloat data[512 * 512 * 3];

    for (unsigned int i = 0; i < 512 * 512 * 3; i++)
    {
        data[i] = static_cast<GLfloat>(rand()) / (static_cast<GLfloat>(RAND_MAX) + 1.0f);
    }

    for (unsigned int i = 0; i < 6; i++)
    {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB32F_ARB, 512, 512, 0, GL_RGB, GL_FLOAT, data);
    }

    glGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP);
}

Maybe it has something to do with an 8600 limitation, although this would be strange.

hmmm … interesting. I am using cubemaps as part of a bigger project. May be I need to run some Cubemap and RGB32F_ARB exclusive tests to figure if the problem is because of a Hardware limitation or something stupid on my part.

Thanks though.