Environment Cube Mapping

I’m trying to get a cube map working for my environment around a teapot. The image only comes up as the teapot, correctly lit, with no background, just white space. Help?

Here’s my code for init() and display():



static GLuint texname;
GLubyte* env;

void init(void)
{
	int width;
	int height;
	env = readPPM("uffizi_cross.ppm",&width,&height);

	glClearColor(0.3,0.3,0.3,1.0);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	glGenTextures(1, &texname);
	glBindTexture(GL_TEXTURE_CUBE_MAP, texname);

	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_WRAP_R, 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);

	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env);

	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
	glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	GLfloat lpos[] = {0.0,-10.0,-15.0,1.0};
	GLfloat La[] = {1.0,1.0,1.0,1.0};
	GLfloat Lid[] = {1.0,1.0,1.0,1.0};
	GLfloat Lis[] = {1.0,1.0,1.0,1.0};
	GLfloat ka[] = {0.005,0.1,0.01,1.0};
	GLfloat kd[] = {0.015,0.3,0.03,1.0};
	GLfloat ks[] = {0.5,0.5,0.5,1.0};

	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ka);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, kd);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ks);
	glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0);

	glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

	glLightfv(GL_LIGHT0, GL_POSITION, lpos);
	glLightfv(GL_LIGHT0, GL_AMBIENT, La);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, Lid);
	glLightfv(GL_LIGHT0, GL_SPECULAR, Lis);

}


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

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	gluLookAt(-3.f,5.f,5.f,0.f,0.f,0.f,0.f,1.f,0.f);

	glEnable(GL_TEXTURE_CUBE_MAP);
	glEnable(GL_TEXTURE_GEN_S);
	glEnable(GL_TEXTURE_GEN_T);
	glEnable(GL_TEXTURE_GEN_R);

	glBindTexture(GL_TEXTURE_CUBE_MAP_POSITIVE_X, texname);
	glBegin(GL_QUADS);
		glNormal3f(-0.5f, 0.0f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(10.0f, -10.0f,  10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(10.0f,  10.0f,  10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(10.0f,  10.0f, -10.0f);
	glEnd();
	glBindTexture(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, texname);
	glBegin(GL_QUADS);
		glNormal3f( 0.5f, 0.0f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-10.0f, -10.0f,  10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-10.0f,  10.0f, -10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-10.0f,  10.0f,  10.0f);
	glEnd();
	glBindTexture(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, texname);
	glBegin(GL_QUADS);
		glNormal3f( 0.0f, 0.5f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 10.0f,  10.0f,  10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-10.0f,  10.0f,  10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-10.0f,  10.0f, -10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 10.0f,  10.0f, -10.0f);
	glEnd();
	glBindTexture(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, texname);
	glBegin(GL_QUADS);
		glNormal3f( 0.0f, -0.5f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-10.0f, -10.0f,  10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 10.0f, -10.0f,  10.0f);
	glEnd();
	glBindTexture(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, texname);
	glBegin(GL_QUADS);
		glNormal3f( 0.0f, 0.0f, -0.5f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 10.0f, -10.0f,  10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-10.0f, -10.0f,  10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-10.0f,  10.0f,  10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 10.0f,  10.0f,  10.0f);
	glEnd();
	glBindTexture(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, texname);	
	glBegin(GL_QUADS);
		glNormal3f( 0.0f, 0.0f, 0.5f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 10.0f,  10.0f, -10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-10.0f,  10.0f, -10.0f);
	glEnd();


	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	glutSolidTeapot(1.3);

	glDisable(GL_LIGHTING);
	glDisable(GL_LIGHT0);

        glDisable(GL_TEXTURE_GEN_S);
        glDisable(GL_TEXTURE_GEN_T);
        glDisable(GL_TEXTURE_GEN_R);
	glDisable(GL_TEXTURE_CUBE_MAP);
	
	glutSwapBuffers();
}

readPPM reads the .ppm file and stores the data as a char array of rgb data and stores the height and width of the image in the height and width parameters. Please help me fix this…

can anyone help me? just please give it a look and tell me if you find anything wrong with what i have here…

There are multiple mistakes.
It seems that you are trying to use a cube map to render a background - while this is possible - it is not how you are doing it and it is probably too complex for a beginner.

What you seem to be wanting to do is load 6 separate 2D textures and render a cube with each face.

Lines like:
glBindTexture(GL_TEXTURE_CUBE_MAP_POSITIVE_X, texname);

are not valid. Calling glGetError() occasionally should find this.

why isn’t that valid? I’ve seen that in a lot of places, including my class’s notes.

First, glBindTexture NEVER takes individual cube map faces as targets, if you use a glGetError function you will surely get an invalid parameters error. Use GL_TEXTURE_CUBE_MAP instead. You must first render each face with the correct view transform and then do a glCopyTexImage2D(Which copies the framebuffer to the texture, meaning you have to set your viewport to the cubemap size -don’t forget to reset it) with the corresponding cube map face(it’s OK to use individual cube map faces there). Don’t forget to have your cube map bound and clear your color buffer between passes! [edit]I see you load your cube map from a file instead…Well in that case what do you render all these quads for?[/edit]
When through, just render the object with the usual texture coordinates/coordinate generation function - usually reflection which you do use in your code. And before you post again asking why your reflection does not rotate with the view, I’ll warn you that you must use the rotation part of your view matrix as your texture matrix too.

And I think your class’s notes suck :p…OK, forget that!

And when in doubt, use this: http://www.opengl.org/sdk/docs/man/

P.S. You were warned, it’s complicated!

P.S.2 I have an old demo somewhere, if you still can’t make sense out of it, send me a pm or email and I’ll send you the source. It may take a while however, I have to find it first.

ok i got the textures to show up but for one each face has the same image, which i think has to do with how i’m binding the textures or something, and then these textures aren’t the images they should be, which i think is a problem with how i’m copying the char array into my GLubyte array. if anyone sees why this is now making every image the same, please tell me. i split the image into 6 separate files for each face.

also, Y-tension, the file only has the rgb colors of each pixel, so don’t i need to create the quads to apply the textures onto them?


static GLuint texname;
unsigned char* ppm;
GLubyte env[6][150][150][3];

void init(void)
{
	int width;
	int height;
	ppm = readPPM("uffizi_cross0.ppm",&width,&height);
	for(int i = 0; i < 150 ; i++){
		for(int k = 0; k < 150; k++){
			for(int j = 0; j < 3; j++)
				env[0][i][k][j] = ppm[450*i+3*k+j];
		}
	}
	ppm = readPPM("uffizi_cross1.ppm",&width,&height);
	for(int i = 0; i < 150 ; i++){
		for(int k = 0; k < 150; k++){
			for(int j = 0; j < 3; j++)
				env[1][i][k][j] = ppm[450*i+3*k+j];
		}
	}
	ppm = readPPM("uffizi_cross2.ppm",&width,&height);
	for(int i = 0; i < 150 ; i++){
		for(int k = 0; k < 150; k++){
			for(int j = 0; j < 3; j++)
				env[2][i][k][j] = ppm[450*i+3*k+j];
		}
	}
	ppm = readPPM("uffizi_cross3.ppm",&width,&height);
	for(int i = 0; i < 150 ; i++){
		for(int k = 0; k < 150; k++){
			for(int j = 0; j < 3; j++)
				env[3][i][k][j] = ppm[450*i+3*k+j];
		}
	}
	ppm = readPPM("uffizi_cross4.ppm",&width,&height);
	for(int i = 0; i < 150 ; i++){
		for(int k = 0; k < 150; k++){
			for(int j = 0; j < 3; j++)
				env[4][i][k][j] = ppm[450*i+3*k+j];
		}
	}
	ppm = readPPM("uffizi_cross5.ppm",&width,&height);
	for(int i = 0; i < 150 ; i++){
		for(int k = 0; k < 150; k++){
			for(int j = 0; j < 3; j++)
				env[5][i][k][j] = ppm[450*i+3*k+j];
		}
	}

	glClearColor(0.3,0.3,0.3,1.0);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

	glGenTextures(1, &texname);
	glBindTexture(GL_TEXTURE_CUBE_MAP, texname);

	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_WRAP_R, 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);

	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env[0]);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env[1]);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env[2]);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env[3]);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env[4]);
	glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, env[5]);

	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
	glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	GLfloat lpos[] = {0.0,-10.0,-15.0,1.0};
	GLfloat La[] = {1.0,1.0,1.0,1.0};
	GLfloat Lid[] = {1.0,1.0,1.0,1.0};
	GLfloat Lis[] = {1.0,1.0,1.0,1.0};
	GLfloat ka[] = {0.005,0.1,0.01,1.0};
	GLfloat kd[] = {0.015,0.3,0.03,1.0};
	GLfloat ks[] = {0.5,0.5,0.5,1.0};

	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ka);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, kd);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ks);
	glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0);

	glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

	glLightfv(GL_LIGHT0, GL_POSITION, lpos);
	glLightfv(GL_LIGHT0, GL_AMBIENT, La);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, Lid);
	glLightfv(GL_LIGHT0, GL_SPECULAR, Lis);

}

void display(void)
{

	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(0.f,5.f,5.f,0.f,0.f,0.f,0.f,1.f,0.f);

	glEnable(GL_TEXTURE_GEN_S);
	glEnable(GL_TEXTURE_GEN_T);
	glEnable(GL_TEXTURE_GEN_R);
	glEnable(GL_TEXTURE_CUBE_MAP);

	glBindTexture(GL_TEXTURE_CUBE_MAP, texname);
	glBegin(GL_QUADS);
		glNormal3f(-0.5f, 0.0f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(10.0f, -10.0f,  10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(10.0f,  10.0f,  10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(10.0f,  10.0f, -10.0f);
	glEnd();
	glBegin(GL_QUADS);
		glNormal3f( 0.5f, 0.0f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-10.0f, -10.0f,  10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-10.0f,  10.0f, -10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-10.0f,  10.0f,  10.0f);
	glEnd();
	glBegin(GL_QUADS);
		glNormal3f( 0.0f, 0.5f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 10.0f,  10.0f,  10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-10.0f,  10.0f,  10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-10.0f,  10.0f, -10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 10.0f,  10.0f, -10.0f);
	glEnd();
	glBegin(GL_QUADS);
		glNormal3f( 0.0f, -0.5f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-10.0f, -10.0f,  10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 10.0f, -10.0f,  10.0f);
	glEnd();
	glBegin(GL_QUADS);
		glNormal3f( 0.0f, 0.0f, -0.5f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 10.0f, -10.0f,  10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-10.0f, -10.0f,  10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-10.0f,  10.0f,  10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 10.0f,  10.0f,  10.0f);
	glEnd();
	glBegin(GL_QUADS);
		glNormal3f( 0.0f, 0.0f, 0.5f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 10.0f, -10.0f, -10.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 10.0f,  10.0f, -10.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-10.0f,  10.0f, -10.0f);
	glEnd();

	glDisable(GL_TEXTURE_CUBE_MAP);

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	glutSolidTeapot(1.3);

	glDisable(GL_LIGHTING);
	glDisable(GL_LIGHT0);

    glDisable(GL_TEXTURE_GEN_S);[quote][/QUOTE]
    glDisable(GL_TEXTURE_GEN_T);
    glDisable(GL_TEXTURE_GEN_R);

	
	glutSwapBuffers();
}

GAHHHHHH! ive almost got this, the images looked wrong because i was using GL_RGBA in my glTexImage2D instead of GL_RGB, which my ppm was using…all because i was reading out of the books i have and other things

lesson learned: pay attention to what im typing and dont just copy…

Ah! I realized why you render the quads! It’s a skybox…duh! However I think the texture coordinates you use for it are wrong because cube mapping does not use the same kind of coordinates as normal texturing. Try using the same coordinates as the world space vector coordinates, for example
glTexCoord3f(-10.0f, -10.0f, -10.0f); glVertex3f(-10.0f, -10.0f, -10.0f);
but disable texture coordinate generation prior to rendering the skybox and re-enable it later.
Hope it works!