using glCopyTexImage2D

I’ve done alot of searching and trial/error, can’t seem to figure this out, so here it goes…

What I am trying to be able to do is to take whatever was last on the screen (currently showing on the screen) and save it as a texture so I can do whatever I want with it. All my attempts to copy it to a texture have failed so far.

Here is a code snippet that I am using to try and create the texture:


        glGenTextures(1, &screenTexture);
        glEnable(GL_TEXTURE_2D);  
        glBindTexture(GL_TEXTURE_2D, screenTexture);      
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);       
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 256, 256, 0);

That is initiated by a button press. Then what I do is render it to one side of a cube. The other 3 sides has textures that I have loaded from a file, and I use the same code to try and render this texture as I do with the other textures. Here is the code I call to render each side of the cube


void DrawQuad(float x1, float y1, float x2, float y2, float z1, float z2, float fWrapCount, GLuint uiTexture)
{


	// Use the given texture
	glBindTexture(GL_TEXTURE_2D, uiTexture);


	// Pass the vertex data
	VERTTYPE afVertices[] = {f2vt(x1),f2vt(y1),f2vt(z1), f2vt(x2),f2vt(y1),f2vt(z2), f2vt(x1),f2vt(y2),f2vt(z1), f2vt(x2),f2vt(y2),f2vt(z2)};
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3,VERTTYPEENUM,0,afVertices);

	// Pass the texture coordinates data
	VERTTYPE afTexCoord[] = {f2vt(0),f2vt(0), f2vt(fWrapCount),f2vt(0), f2vt(0),f2vt(fWrapCount), f2vt(fWrapCount),f2vt(fWrapCount)};
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glTexCoordPointer(2,VERTTYPEENUM,0,afTexCoord);

	// Draws an indexed triangle list
	unsigned short aIndices[] = {0,1,2, 2,1,3};
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, aIndices);
}

Like I said, the textures that I load from a file work fine, but the screenshot texture…not so much. It creates some garbage on the screen so I know it is doing something, but definitely not what I want it to.

Any ideas on where I am going wrong?

as a follow up to this, it appears that all that is copied is the clear color of the scene. So if I change the clearColor to red or blue, etc. I end up with one side of the cube being that color, that isn’t what I want obviously but maybe it will help understand my problem.

At what point are you calling glCopyTexImage2D? Note that it reads from the back buffer of the current context read surface, not the front buffer buffer (which is currently displayed on the screen).

That makes more sense now, if I call it at the end of my rendering instead of the middle I do get something recognizable. Thanks a lot for pointing that out.

However, my end goal is to be able to take whatever was on the screen before my application began running and do a transition of some sort. How is it possible to get whatever is currently on the screen (even if your application did not render it) and turn it into a texture?

That depends on the platform, OS, and window system you’re targeting. Some might grant you access to the framebuffer, others don’t.

Currently experimenting on a device with Windows Mobile 6 Standard

I am investigating this exact same issue. I read in a tutorial that OpenGL can’t grab/put anything outside its rendering area. If you get the screen pixel data using GDI:

HDC hScreenDC = CreateDC(NULL, NULL, NULL, NULL);
HDC hMemoryDC = CreateCompatibleDC(NULL);

int Width = GetSystemMetrics(SM_CXSCREEN) ;
int Height = GetSystemMetrics(SM_CYSCREEN) ;

//Not sure if we need all the info, This will tell the system what format we want the pixels to be in
BITMAPINFO bmi;
ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = Width;
bmi.bmiHeader.biHeight = Height;
bmi.bmiHeader.biSizeImage = (Width * Height) * 3;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 24;

//All we are really interested in
DWORD* pBitmapBits;

BITMAPFILEHEADER	hdr;
////create bitmap from buffer...
int nColors = 0;

//// Fill in the fields of the file header 
hdr.bfType			= ((WORD) ('M' << 8 ) | 'B');	// is always "BM" for bitmap
hdr.bfSize			= 0;//GlobalSize (hDIB) + sizeof( hdr );
hdr.bfReserved1 	= 0;
hdr.bfReserved2 	= 0;
hdr.bfOffBits		= (DWORD) (sizeof( hdr ) + sizeof(BITMAPINFOHEADER) + nColors * sizeof(RGBQUAD));

//sloppy bad way of grabbing the bits. You could probably use a format specific bitmap here
HBITMAP hNewBitmap = CreateDIBSection( hMemoryDC,
&bmi,
DIB_RGB_COLORS,
(void**)&pBitmapBits,
NULL,
0
);

HBITMAP hOldBitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hNewBitmap));

//copy the on screen bitmap to our DC
BOOL bitBltSuccess = BitBlt(hMemoryDC, 0, 0, Width, Height, hScreenDC, X1, Y1, SRCCOPY);

then pass the pointer pBitmapBits to glTexImage2D() which will “render this texture on all enabled surfaces” (http://opengles.net/opengles/sdk/1.1/do … mage2D.xml)

I am really newbie to opengl(today) so this might not make sense. But I would also like to accomplish the same goal. If this helps or you can help me, please let me in on the final product :slight_smile: