Screenshot to texture

I know I’ve already posted a question about this but I’m still having trouble. What I want to do is capture the screen, dump it into a texture, and then texture a sphere with it. I’ve tried using glReadPixels, FBOs, glGenerateMipmap, and the glCoprTex* functions. Nothing seems to work properly. Is there anybody who can tell me how I might accomplish doing what I’m trying to do?

Actually you don’t need a FBO for this, but it is a fast and practical way. What in this page isn’t working?

http://www.songho.ca/opengl/gl_fbo.html

Theres also an example of how to texture an object.

Cool! Its working! Thanks man. However its a little slow. I know how I can speed it up but I need to know where the vertex coordinates stop on the x and y axes. Would anybody out there know how to find out? I know, its lame that I don’t already know how to do this.

Nevermind the previous question. I figued it out. Now I have another question. Why can’t I take that texture that has my screen shot and slap it back to the screen with one big quad? I don’t know where I’m going wrong. It textures the sphere no problem but I can’t get it to map to the entire screen. I’m trying to speed things up here.

Let’s see some code. Show us how you’re binding the texture, and building the batch (draw call) for that GL QUAD.

void genFBOtexture(void)
{
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
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_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);

// create a renderbuffer object to store depth info
GLuint rboId;
glGenRenderbuffersEXT(1, &rboId);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboId);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 512, 512);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

// create a framebuffer object
GLuint fboId;
glGenFramebuffersEXT(1, &fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);

// attach the texture to FBO color attachment point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0);

// attach the renderbuffer to depth attachment point
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId);

/this is where I draw all of my scene with the exception of the sphere. too much code right here to post/

// unbind FBO
glDeleteRenderbuffersEXT(1, &rboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

}

void drawSphere(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glBindTexture(GL_TEXTURE_2D, tex);
glGenerateMipmapEXT(GL_TEXTURE_2D);

glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);    

glEnable(GL_TEXTURE_2D); 

glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);

//glLoadIdentity();
glTranslatef(0.0f, 5.0f, -25.0f);

glNormal3f(0.0f, 0.0f, 1.0f);
glutSolidSphere(5.0f, 25, 25);

glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);

glDisable(GL_TEXTURE_2D);
glColor3f(1.0f, 1.0f, 1.0f);

glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);

}

void drawScene() {

genFBOtexture();

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glEnable(GL_DEPTH_TEST);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glBegin(GL_QUADS);

glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(2.5f, -2.5f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-2.5f, -2.5f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-2.5f, 2.5f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(2.5f, 2.5f, 0.0f);

glEnd();

glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);

drawSphere();  

glutSwapBuffers();

}

//I hope this is all you need. Thanks for the help.

Well I don’t see a glGenTextures( 1, &tex ), but I assume you’ve got it elsewhere.

First thing that jumps out at me is that, while you are loading an Identity MODELVIEW, you’re not loading a projection matrix before drawing that quad. You probably want something like:


glMatrixMode( GL_PROJECTION );
glOrtho( -2.5, 2.5, -2.5, 2.5, -1, 1 );

Also, you probably want to disable DEPTH_TEST before you draw it, because the depth buffer will be nonsensical for rendering the quad in a different projection.

Yeah, I’ve got the glGenTextures function above everything else in another function; initRendering(). Anyhow, I’ll implement the changes you suggest and get back to you guys.

Ok, tried it. Now my screen is just black. Like nothing is getting drawn.

The strange thing is if I take all the code used in between the creation and release of the FBO and replace the code that is drawing that big quad with it then it seems to work. Its just a little slow.

// unbind FBO
glDeleteRenderbuffersEXT(1, &rboId);

Are you deleting your depth render buffer when you unbind the FBO?
Really??!

Oh, sorry. I thought once you have the texture made you get rid of the stuff used to make it or you might end up with a memory leak or something. Cut me some slack man. I’m new to opengl and graphics programming in general. And when I say new I mean by a couple of weeks. That means I have yet to understand the way all of this works and that includes the workings of my graphics card. However, I took that line out of the code and its still not working. But I thank you for your help.

Ok, I don’t mean to overwhelm anyone bt here it is. My code. All 966 lines of it:

#include <iostream>
#include <stdlib.h>
#include <assert.h>
#include <fstream>
#include <math.h>

#ifdef APPLE
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/GLee.h>
#include <GL/GLU.h>
#include <GL/glut.h>
//#include <GL/gl.h>
//#include <GL/glext.h>

#endif

using namespace std;

float _yangle = -70.0f;
float _xangle = -70.0f;
float _zangle = -70.0f;

GLuint _textureId; //The id of the texture
GLuint _textureId1;
GLuint tex;

void drawSphere(void);

class Image {
public:
Image(char* ps, int w, int h);
~Image();

	/* An array of the form (R1, G1, B1, R2, G2, B2, ...) indicating the
	 * color of each pixel in image.  Color components range from 0 to 255.
	 * The array starts the bottom-left pixel, then moves right to the end
	 * of the row, then moves up to the next column, and so on.  This is the
	 * format in which OpenGL likes images.
	 */
	char* pixels;
	int width;
	int height;

};

//Reads a bitmap image from file.
Image* loadBMP(const char* filename);

Image::Image(char* ps, int w, int h) : pixels(ps), width(w), height(h) {

}

Image::~Image() {
delete[] pixels;
}

namespace {
//Converts a four-character array to an integer, using little-endian form
int toInt(const char* bytes) {
return (int)(((unsigned char)bytes[3] << 24) |
((unsigned char)bytes[2] << 16) |
((unsigned char)bytes[1] << 8) |
(unsigned char)bytes[0]);
}

//Converts a two-character array to a short, using little-endian form
short toShort(const char* bytes) {
	return (short)(((unsigned char)bytes[1] &lt;&lt; 8) |
				   (unsigned char)bytes[0]);
}

//Reads the next four bytes as an integer, using little-endian form
int readInt(ifstream &input) {
	char buffer[4];
	input.read(buffer, 4);
	return toInt(buffer);
}

//Reads the next two bytes as a short, using little-endian form
short readShort(ifstream &input) {
	char buffer[2];
	input.read(buffer, 2);
	return toShort(buffer);
}

//Just like auto_ptr, but for arrays
template&lt;class T&gt;
class auto_array {
	private:
		T* array;
		mutable bool isReleased;
	public:
		explicit auto_array(T* array_ = NULL) :
			array(array_), isReleased(false) {
		}
		
		auto_array(const auto_array&lt;T&gt; &aarray) {
			array = aarray.array;
			isReleased = aarray.isReleased;
			aarray.isReleased = true;
		}
		
		~auto_array() {
			if (!isReleased && array != NULL) {
				delete[] array;
			}
		}
		
		T* get() const {
			return array;
		}
		
		T &operator*() const {
			return *array;
		}
		
		void operator=(const auto_array&lt;T&gt; &aarray) {
			if (!isReleased && array != NULL) {
				delete[] array;
			}
			array = aarray.array;
			isReleased = aarray.isReleased;
			aarray.isReleased = true;
		}
		
		T* operator-&gt;() const {
			return array;
		}
		
		T* release() {
			isReleased = true;
			return array;
		}
		
		void reset(T* array_ = NULL) {
			if (!isReleased && array != NULL) {
				delete[] array;
			}
			array = array_;
		}
		
		T* operator+(int i) {
			return array + i;
		}
		
		T &operator[](int i) {
			return array[i];
		}
};

}

Image* loadBMP(const char* filename) {
ifstream input;
input.open(filename, ifstream::binary);
assert(!input.fail() || !“Could not find file”);
char buffer[2];
input.read(buffer, 2);
assert(buffer[0] == ‘B’ && buffer[1] == ‘M’ || !“Not a bitmap file”);
input.ignore(8);
int dataOffset = readInt(input);

//Read the header
int headerSize = readInt(input);
int width;
int height;
switch(headerSize) {
	case 40:
		//V3
		width = readInt(input);
		height = readInt(input);
		input.ignore(2);
		assert(readShort(input) == 24 || !"Image is not 24 bits per pixel");
		assert(readShort(input) == 0 || !"Image is compressed");
		break;
	case 12:
		//OS/2 V1
		width = readShort(input);
		height = readShort(input);
		input.ignore(2);
		assert(readShort(input) == 24 || !"Image is not 24 bits per pixel");
		break;
	case 64:
		//OS/2 V2
		assert(!"Can't load OS/2 V2 bitmaps");
		break;
	case 108:
		//Windows V4
		assert(!"Can't load Windows V4 bitmaps");
		break;
	case 124:
		//Windows V5
		assert(!"Can't load Windows V5 bitmaps");
		break;
	default:
		assert(!"Unknown bitmap format");
}

//Read the data
int bytesPerRow = ((width * 3 + 3) / 4) * 4 - (width * 3 % 4);
int size = bytesPerRow * height;
auto_array&lt;char&gt; pixels(new char[size]);
input.seekg(dataOffset, ios_base::beg);
input.read(pixels.get(), size);

//Get the data into the right format
auto_array&lt;char&gt; pixels2(new char[width * height * 3]);
for(int y = 0; y &lt; height; y++) {
	for(int x = 0; x &lt; width; x++) {
		for(int c = 0; c &lt; 3; c++) {
			pixels2[3 * (width * y + x) + c] =
				pixels[bytesPerRow * y + 3 * x + (2 - c)];
		}
	}
}

input.close();
return new Image(pixels2.release(), width, height);

}

//Makes the image into a texture, and returns the id of the texture
GLuint loadTexture(Image* image) {
GLuint textureId;
glGenTextures(1, &textureId); //Make room for our texture
glBindTexture(GL_TEXTURE_2D, textureId); //Tell OpenGL which texture to edit
//Map the image to the texture
glTexImage2D(GL_TEXTURE_2D, //Always GL_TEXTURE_2D
0, //0 for now
GL_RGB, //Format OpenGL uses for image
image->width, image->height, //Width and height
0, //The border of the image
GL_RGB, //GL_RGB, because pixels are stored in RGB format
GL_UNSIGNED_BYTE, //GL_UNSIGNED_BYTE, because pixels are stored
//as unsigned numbers
image->pixels); //The actual pixel data
return textureId; //Returns the id of the texture
}

void calcNormal(float v[3][3], float out[3])
{
float v1[3], v2[3], length;
static const int x = 0, y = 1, z = 2;

v1[x] = v[0][x] - v[1][x];
v1[y] = v[0][y] - v[1][y];
v1[z] = v[0][z] - v[1][z];

v2[x] = v[1][x] - v[2][x];
v2[y] = v[1][y] - v[2][y];
v2[z] = v[1][z] - v[2][z];

out[x] = (v1[y] * v2[z]) - (v1[z] * v2[y]);
out[y] = (v1[z] * v2[x]) - (v1[x] * v2[z]);
out[z] = (v1[x] * v2[y]) - (v1[y] * v2[x]);

length = (float)sqrt( (out[x] * out[x]) + (out[y] * out[y]) + (out[z] * out[z]) );

out[x] = out[x] / length;
out[y] = out[y] / length;
out[z] = out[z] / length;
}

void MakeShadowMatrix(GLfloat points[3][3], GLfloat lightPos[4], GLfloat destMat[4][4])
{
GLfloat planeCoeff[4];
GLfloat dot;

calcNormal(points, planeCoeff);

planeCoeff[3] = - ( (planeCoeff[0] * points[2][0]) + (planeCoeff[1] * points[2][1]) + (planeCoeff[2] * points[2][2]) );

dot = (planeCoeff[0] * lightPos[0]) + (planeCoeff[1] * lightPos[1]) + (planeCoeff[2] * lightPos[2]) + (planeCoeff[3] * lightPos[3]);

destMat[0][0] = dot - (lightPos[0] * planeCoeff[0]);
destMat[1][0] = 0.0f - (lightPos[0] * planeCoeff[1]);
destMat[2][0] = 0.0f - (lightPos[0] * planeCoeff[2]);
destMat[3][0] = 0.0f - (lightPos[0] * planeCoeff[3]);

destMat[0][1] = 0.0f - (lightPos[1] * planeCoeff[0]);
destMat[1][1] = dot - (lightPos[1] * planeCoeff[1]);
destMat[2][1] = 0.0f - (lightPos[1] * planeCoeff[2]);
destMat[3][1] = 0.0f - (lightPos[1] * planeCoeff[3]);

destMat[0][2] = 0.0f - (lightPos[2] * planeCoeff[0]);
destMat[1][2] = 0.0f - (lightPos[2] * planeCoeff[1]);
destMat[2][2] = dot - (lightPos[2] * planeCoeff[2]);
destMat[3][2] = 0.0f - (lightPos[2] * planeCoeff[3]);

destMat[0][3] = 0.0f - (lightPos[3] * planeCoeff[0]);
destMat[1][3] = 0.0f - (lightPos[3] * planeCoeff[1]);
destMat[2][3] = 0.0f - (lightPos[3] * planeCoeff[2]);
destMat[3][3] = dot - (lightPos[3] * planeCoeff[3]);
}

void checkGLErrors( const char *s )
{
while ( 1 )
{
int x = glGetError() ;

if ( x == GL_NO_ERROR )
  return;

fprintf( stderr, "%s: OpenGL error: %s", 
         s ? s : "", gluErrorString ( x ) ) ;

}
}

void keybd ( unsigned char, int, int )
{
exit ( 0 ) ;
}

void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
}

void showGLerror ()
{
GLenum err ;

while ( (err = glGetError()) != GL_NO_ERROR )
fprintf ( stderr, "OpenGL Error: %s
", gluErrorString ( err ) ) ;
}

void initRendering() {
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING); //Enable lighting
glEnable(GL_LIGHT0); //Enable light #0
glEnable(GL_LIGHT1);
glEnable(GL_LIGHT2);
glEnable(GL_LIGHT3);
glEnable(GL_LIGHT4);
glEnable(GL_LIGHT5);
glEnable(GL_NORMALIZE); //Automatically normalize normals
//glShadeModel(GL_SMOOTH); //Enable smooth shading

Image* image = loadBMP("georgia.bmp");
  _textureId = loadTexture(image);

Image* image1 = loadBMP("checker.bmp");
_textureId1 = loadTexture(image1);

glGenTextures(1, &tex);

delete image;
delete image1;

}

void genFBOtexture(void)
{
GLfloat shadowMat[4][4];
GLfloat points[3][3] = {{5.0f, -3.5f, -17.0f}, {-5.0f, -3.5f, -17.0f}, {-5.0f, -3.5f, -7.0f}};

glBindTexture(GL_TEXTURE_2D, tex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
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_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);

// create a renderbuffer object to store depth info
GLuint rboId;
glGenRenderbuffersEXT(1, &rboId);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboId);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 512, 512);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

// create a framebuffer object
GLuint fboId;
glGenFramebuffersEXT(1, &fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);

// attach the texture to FBO color attachment point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0);

// attach the renderbuffer to depth attachment point
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glTranslatef(-3.0f, -3.5f, -21.0f);

GLfloat lightColor4[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightPos4[] = {8.0f, 5.0f, -18.0f, 1.0f};
glLightfv(GL_LIGHT4, GL_DIFFUSE, lightColor4);
glLightfv(GL_LIGHT4, GL_POSITION, lightPos4);

glPushMatrix();
glTranslatef(5.0f, 3.0f, 3.0f);

glEnable(GL_DEPTH_TEST); 

glRotatef(_yangle, 0.0f, 1.0f, 0.0f);
glRotatef(_xangle, 1.0f, 0.0f, 0.0f);
glRotatef(_zangle, 0.0f, 0.0f, 1.0f);

glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, _textureId);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glBegin(GL_QUADS);

//Top
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.5f, 1.5f, -1.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.5f, 1.5f, -1.5f);

//Bottom
glNormal3f(0.0f, -1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.5f, -1.5f, -1.5f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);

  //Front
  glNormal3f(0.0f, 1.0f, 1.0f);
  //glNormal3f(-1.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 0.0f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 1.0f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 1.0f); 
  //glNormal3f(-1.0f, 0.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, 1.5f);

  //Right
  glNormal3f(1.0f, 0.0f, 0.0f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, 1.5f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);

  //Back
  glNormal3f(0.0f, 0.0f, -1.0f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, -1.5f);

  //Left
  glNormal3f(-1.0f, 0.0f, 0.0f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);
  //glNormal3f(-1.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, 1.5f);
  //glNormal3f(-1.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, 1.5f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, -1.5f);

glEnd();

glDisable(GL_TEXTURE_2D);

glPopMatrix();

glEnable(GL_STENCIL_TEST); //Enable using the stencil buffer
glClearStencil(0);
glColorMask(0, 0, 0, 0); //Disable drawing colors to the screen
glDisable(GL_DEPTH_TEST); //Disable depth testing
glStencilFunc(GL_ALWAYS, 1, 1); //Make the stencil test always pass
//Make pixels in the stencil buffer be set to 1 when the stencil test passes
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
//Set all of the pixels covered by the floor to be 1 in the stencil buffer

glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, _textureId1);

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

glBegin(GL_QUADS);

glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(20.0f, 0.0f, 20.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-20.0f, 0.0f, 20.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-20.0f, 0.0f, -20.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(20.0f, 0.0f, -20.0f);

glEnd();

glDisable(GL_TEXTURE_2D);

glColorMask(1, 1, 1, 1); //Enable drawing colors to the screen
glEnable(GL_DEPTH_TEST); //Enable depth testing
//Make the stencil test pass only when the pixel is 1 in the stencil buffer
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); //Make the stencil buffer not change

//Draw the cube, reflected vertically, at all pixels where the stencil
//buffer is 1
glPushMatrix();
glScalef(1, -1, 1);
glTranslatef(5.0f, 3.0f, 3.0f);

glRotatef(_yangle, 0.0f, 1.0f, 0.0f);
  glRotatef(_xangle, 1.0f, 0.0f, 0.0f);
glRotatef(_zangle, 0.0f, 0.0f, 1.0f);

glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, _textureId);

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

glBegin(GL_QUADS);

//Top
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.5f, 1.5f, -1.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.5f, 1.5f, -1.5f);

//Bottom
glNormal3f(0.0f, -1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.5f, -1.5f, -1.5f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);

  //Front
  glNormal3f(0.0f, 1.0f, 1.0f);
  //glNormal3f(-1.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 0.0f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 1.0f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 1.0f); 
  //glNormal3f(-1.0f, 0.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, 1.5f);

  //Right
  glNormal3f(1.0f, 0.0f, 0.0f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, 1.5f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);

  //Back
  glNormal3f(0.0f, 0.0f, -1.0f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, -1.5f);

  //Left
  glNormal3f(-1.0f, 0.0f, 0.0f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);
  //glNormal3f(-1.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, 1.5f);
  //glNormal3f(-1.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, 1.5f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, -1.5f);

glEnd();

glDisable(GL_TEXTURE_2D);

glPopMatrix();

glDisable(GL_STENCIL_TEST); //Disable using the stencil buffer

//Blend the floor onto the screen
glEnable(GL_BLEND);
glColor4f(1, 1, 1, 0.7f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, _textureId1);

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

glBegin(GL_QUADS);

glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(20.0f, 0.0f, 20.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-20.0f, 0.0f, 20.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-20.0f, 0.0f, -20.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(20.0f, 0.0f, -20.0f);

glEnd();

glDisable(GL_TEXTURE_2D);

glDisable(GL_BLEND); 
	
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

glEnable(GL_LIGHTING);

glTranslatef(-3.0f, 0.0f, -16.0f);

GLfloat lightColor0[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightPos0[] = {0.0f, 12.0f, 0.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);

GLfloat lightColor1[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightPos1[] = {-4.0f, 0.0f, 0.0f, 1.0f};
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);

GLfloat lightColor2[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightPos2[] = {4.0f, 0.0f, 0.0f, 1.0f};
glLightfv(GL_LIGHT2, GL_DIFFUSE, lightColor2);
glLightfv(GL_LIGHT2, GL_POSITION, lightPos2);

GLfloat lightColor3[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightPos3[] = {0.0f, 0.0f, 4.0f, 1.0f};
glLightfv(GL_LIGHT3, GL_DIFFUSE, lightColor3);
glLightfv(GL_LIGHT3, GL_POSITION, lightPos3);

//Add ambient light
  //GLfloat ambientColor[] = {0.2f, 0.2f, 0.2f, 1.0f}; //Color (0.2, 0.2, 0.2)
  //glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);

glPushMatrix();

glRotatef(_yangle, 0.0f, 1.0f, 0.0f);
  glRotatef(_xangle, 1.0f, 0.0f, 0.0f);
glRotatef(_zangle, 0.0f, 0.0f, 1.0f);

glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, _textureId);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glBegin(GL_QUADS);

//Top
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.5f, 1.5f, -1.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.5f, 1.5f, -1.5f);

//Bottom
glNormal3f(0.0f, -1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.5f, -1.5f, -1.5f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);

  //Front
  glNormal3f(0.0f, 1.0f, 1.0f);
  //glNormal3f(-1.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 0.0f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 1.0f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 1.0f); 
  //glNormal3f(-1.0f, 0.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, 1.5f);

  //Right
  glNormal3f(1.0f, 0.0f, 0.0f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, 1.5f);
  //glNormal3f(1.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);

  //Back
  glNormal3f(0.0f, 0.0f, -1.0f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, -1.5f);
  //glNormal3f(1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, -1.5f);

  //Left
  glNormal3f(-1.0f, 0.0f, 0.0f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);
  //glNormal3f(-1.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, 1.5f);
  //glNormal3f(-1.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, 1.5f);
  //glNormal3f(-1.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, -1.5f);

glEnd();

glDisable(GL_TEXTURE_2D);

glPopMatrix();

glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);

MakeShadowMatrix(points, lightPos0, shadowMat);

glPushMatrix();

glMultMatrixf((GLfloat *)shadowMat);

glRotatef(_yangle, 0.0f, 1.0f, 0.0f);
  glRotatef(_xangle, 1.0f, 0.0f, 0.0f);
glRotatef(_zangle, 0.0f, 0.0f, 1.0f);

glColor3f(0.0f, 0.0f, 0.0f);

glBegin(GL_QUADS);

//Top
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.5f, 1.5f, 1.5f);
glVertex3f(-1.5f, 1.5f, 1.5f);
glVertex3f(-1.5f, 1.5f, -1.5f);
glVertex3f(1.5f, 1.5f, -1.5f);

//Bottom
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(-1.5f, -1.5f, 1.5f);
glVertex3f(1.5f, -1.5f, 1.5f);
glVertex3f(1.5f, -1.5f, -1.5f);
glVertex3f(-1.5f, -1.5f, -1.5f);

  //Front
  glNormal3f(0.0f, 0.0f, 1.0f);
  glVertex3f(-1.5f, -1.5f, 1.5f);
glVertex3f(1.5f, -1.5f, 1.5f);
glVertex3f(1.5f, 1.5f, 1.5f);
glVertex3f(-1.5f, 1.5f, 1.5f);

  //Right
  glNormal3f(1.0f, 0.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, -1.5f);
  glVertex3f(1.5f, 1.5f, -1.5f);
  glVertex3f(1.5f, 1.5f, 1.5f);
  glVertex3f(1.5f, -1.5f, 1.5f);

  //Back
  glNormal3f(0.0f, 0.0f, -1.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);
  glVertex3f(-1.5f, 1.5f, -1.5f);
  glVertex3f(1.5f, 1.5f, -1.5f);
  glVertex3f(1.5f, -1.5f, -1.5f);

  //Left
  glNormal3f(-1.0f, 0.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);
  glVertex3f(-1.5f, -1.5f, 1.5f);
  glVertex3f(-1.5f, 1.5f, 1.5f);
  glVertex3f(-1.5f, 1.5f, -1.5f);

glEnd();

glColor3f(1.0f, 1.0f, 1.0f);

glPopMatrix();

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

}

void drawScene(){

genFBOtexture();

glMatrixMode(GL_MODELVIEW);
//glMatrixMode( GL_PROJECTION );
//glOrtho( -2.5, 2.5, -2.5, 2.5, -1, 1 );
glLoadIdentity();

glEnable(GL_DEPTH_TEST);

glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, tex);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glBegin(GL_QUADS);

glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(2.5f, -2.5f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-2.5f, -2.5f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-2.5f, 2.5f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(2.5f, 2.5f, 0.0f);

glEnd();

glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);

glutSwapBuffers();

}

void update(int value) {
_yangle += 1.5f;
_xangle += 1.5f;
_zangle += 1.5f;

if (_yangle &gt; 360) {
	_yangle -= 360;
}

if (_xangle &gt; 360) {
	_xangle -= 360;
}

if (_zangle &gt; 360) {
	_zangle -= 360;
} 

glutPostRedisplay();
glutTimerFunc(25, update, 0);

}

int main ( int argc, char **argv )
{
// Init GL context
glutInit ( &argc, argv ) ;
glutInitDisplayMode ( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE ) ;
glutInitWindowSize ( 512, 512 ) ;

initRendering();

glutCreateWindow ( “GL Test” ) ;
glutDisplayFunc ( drawScene ) ;
glutKeyboardFunc ( keybd ) ;
glutReshapeFunc ( reshape ) ;

// Put create/setup code here

checkGLErrors ( “end of setup” ) ;

glutTimerFunc(25, update, 0); //Add a timer

// Draw with shader
glutMainLoop () ;
return 0 ;
}

Actually I did leave out my drawSphere function but I’m quite sure the problem doesn’t lie there.

Alright guys, sorry about the huge blob of code I posted the other night. After taking something of a textual beat down from someone else on this board (who will remain nameless), and being made to feel like crap for having the nerve to ask him for help, I’ve decided to break up my code into functions and comment it so its a little easier to follow. Despite how I was made to feel the guy did have a point. Anyhow, the code will be posted right after this post. Any advice as to what may be going wrong would be greatly appreciated.

<div class=“ubbcode-block”><div class=“ubbcode-header”>Click to reveal… <input type=“button” class=“form-button” value=“Show me!” onclick=“toggle_spoiler(this, ‘Yikes, my eyes!’, ‘Show me!’)” />]<div style=“display: none;”>
void drawFloor(GLuint texture)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textureId1);

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

glBegin(GL_QUADS);

glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(20.0f, 0.0f, 20.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-20.0f, 0.0f, 20.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-20.0f, 0.0f, -20.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(20.0f, 0.0f, -20.0f);

glEnd();

glDisable(GL_TEXTURE_2D);

}

void drawCube(GLuint texture, char c)
{
//apply rotation
glRotatef(_yangle, 0.0f, 1.0f, 0.0f);
glRotatef(_xangle, 1.0f, 0.0f, 0.0f);
glRotatef(_zangle, 0.0f, 0.0f, 1.0f);

if(c == 'n' || c == 'l')
{ 
  //set up texture for cube
  glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture);

  //set up parameters for the texture 
  if(c == 'n')
  {
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  }
  else
  {
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  }
}  

//now draw the cube
glBegin(GL_QUADS);

//Top
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.5f, 1.5f, -1.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.5f, 1.5f, -1.5f);

//Bottom
glNormal3f(0.0f, -1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.5f, -1.5f, -1.5f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);

  //Front
  glNormal3f(0.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 1.0f); 
  glVertex3f(-1.5f, 1.5f, 1.5f);

  //Right
  glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, -1.5f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, -1.5f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, 1.5f);

  //Back
  glNormal3f(0.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, -1.5f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(1.5f, 1.5f, -1.5f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(1.5f, -1.5f, -1.5f);

  //Left
  glNormal3f(-1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, -1.5f);
glTexCoord2f(1.0f, 0.0f);
  glVertex3f(-1.5f, -1.5f, 1.5f);
glTexCoord2f(1.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, 1.5f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(-1.5f, 1.5f, -1.5f);

glEnd();

if(c == 'n' || c == 'l')
  glDisable(GL_TEXTURE_2D);    

}

void drawShadow(GLfloat *lightPos0)
{
GLfloat shadowMat[4][4];
GLfloat points[3][3] = {{5.0f, -3.5f, -17.0f}, {-5.0f, -3.5f, -17.0f}, {-5.0f, -3.5f, -7.0f}};

glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);

MakeShadowMatrix(points, lightPos0, shadowMat);

glMultMatrixf((GLfloat *)shadowMat);

glColor3f(0.0f, 0.0f, 0.0f);

drawCube((GLuint)0, 's');

glColor3f(1.0f, 1.0f, 1.0f);

glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);

}

void genFBOtexture(void)
{
//set up mipmap
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
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_GENERATE_MIPMAP, GL_TRUE); // automatic mipmap
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);

// create a renderbuffer object to store depth info
GLuint rboId;
glGenRenderbuffersEXT(1, &rboId);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboId);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 512, 512);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

// create a framebuffer object
GLuint fboId;
glGenFramebuffersEXT(1, &fboId);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);

// attach the texture to FBO color attachment point
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0);

// attach the renderbuffer to depth attachment point
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId);

//clear and load identity
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

//move left, down, and back
glTranslatef(-3.0f, -3.5f, -21.0f);

//set up a light source
GLfloat lightColor4[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightPos4[] = {8.0f, 5.0f, -18.0f, 1.0f};
glLightfv(GL_LIGHT4, GL_DIFFUSE, lightColor4);
glLightfv(GL_LIGHT4, GL_POSITION, lightPos4);

//draw cude on the right
glPushMatrix();
glTranslatef(5.0f, 3.0f, 3.0f);
glEnable(GL_DEPTH_TEST); 
drawCube(_textureId, 'n');
glPopMatrix();

//set up stencil for simple reflection of cude on the floor
glEnable(GL_STENCIL_TEST); //Enable using the stencil buffer
glClearStencil(0);
glColorMask(0, 0, 0, 0); //Disable drawing colors to the screen
glDisable(GL_DEPTH_TEST); //Disable depth testing
glStencilFunc(GL_ALWAYS, 1, 1); //Make the stencil test always pass
//Make pixels in the stencil buffer be set to 1 when the stencil test passes
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
//Set all of the pixels covered by the floor to be 1 in the stencil buffer

drawFloor(_textureId1); 

glColorMask(1, 1, 1, 1); //Enable drawing colors to the screen
glEnable(GL_DEPTH_TEST); //Enable depth testing
//Make the stencil test pass only when the pixel is 1 in the stencil buffer
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); //Make the stencil buffer not change

//Draw the cube, reflected vertically, at all pixels where the stencil
//buffer is 1
glPushMatrix();
glScalef(1, -1, 1);
glTranslatef(5.0f, 3.0f, 3.0f);

drawCube(_textureId, 'l'); 

glPopMatrix();

glDisable(GL_STENCIL_TEST); //Disable using the stencil buffer

//Blend the floor onto the screen
glEnable(GL_BLEND);
glColor4f(1, 1, 1, 0.7f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

drawFloor(_textureId1);

glDisable(GL_BLEND); 
	
  //reset identity
glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

glEnable(GL_LIGHTING);

//move left and to the back
glTranslatef(-3.0f, 0.0f, -16.0f);

//place 4 lights in scene
GLfloat lightColor0[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightPos0[] = {0.0f, 12.0f, 0.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);

GLfloat lightColor1[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightPos1[] = {-4.0f, 0.0f, 0.0f, 1.0f};
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);

GLfloat lightColor2[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightPos2[] = {4.0f, 0.0f, 0.0f, 1.0f};
glLightfv(GL_LIGHT2, GL_DIFFUSE, lightColor2);
glLightfv(GL_LIGHT2, GL_POSITION, lightPos2);

GLfloat lightColor3[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightPos3[] = {0.0f, 0.0f, 4.0f, 1.0f};
glLightfv(GL_LIGHT3, GL_DIFFUSE, lightColor3);
glLightfv(GL_LIGHT3, GL_POSITION, lightPos3);

//draw cube on left
glPushMatrix();
drawCube(_textureId, 'n');
glPopMatrix();

//draw its shadow
glPushMatrix();
drawShadow(lightPos0);
glPopMatrix();

// unbind FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

}

void drawScene()
{
//get out screenshot and put it in a texture called tex
genFBOtexture();

//reset everything
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

//enable depth testing and bind our newly made texture
glEnable(GL_DEPTH_TEST);
glBindTexture(GL_TEXTURE_2D, tex);
glEnable(GL_TEXTURE_2D);

//set parameters for the texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

//Now take our large texture and slap it to the whole screen in one big quad
glBegin(GL_QUADS);

glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(2.5f, -2.5f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
  glVertex3f(-2.5f, -2.5f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-2.5f, 2.5f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(2.5f, 2.5f, 0.0f);

glEnd();

glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);

//now draw a sphere covered with our texture
drawSphere();

glutSwapBuffers();

}
[/QUOTE]</div>

Hmmm, well, its still a lot of code, but it is actually a third of what I posted the other night.

Ok, I think you’re gonna need to do a little work here narrowing down the problem. The 2nd source code snippet doesn’t compile. The first one does, with a little hacking, but then expects some BMP textures. If I toss one its way, it comes up with a black screen. And I have no idea if that’s right, wrong, or what exactly is supposed to happen.

Spend some time narrowing down the problem, scalping off big hunks of stuff you know “do” work, replacing complex drawing with a single triangle or quad, and post a test program that focuses “directly” on the specific thing you have a question about.

Sure thing Photon! I really am grateful for all the help you’ve given me thus far. I’ve been working on it all day and I think I’m getting close. I should be able to have the problem narrowed down in a couple of days. Thanks a bunch! :slight_smile: