Sign in to follow this  
raptorstrike

Screen Capture texture generation in open GL

Recommended Posts

Well my goal right now is to read in the pixels from the screen buffer and bind them to an SDL_Surface (cleanest way that I can think of). And then use that to generate a texture on the fly and render it on a polygon. this is the code I have
      glPushMatrix();
      GLuint Reflection_Image;
      SDL_Surface* Image_Data = SDL_CreateRGBSurface(SDL_HWSURFACE, windowWidth, windowHeight, 32, 0xff000000,0x00ff0000,0x0000ff00,0x000000ff);
      glReadPixels(0,0,windowWidth, windowHeight, GL_RGBA, GL_UNSIGNED_BYTE, Image_Data->pixels);
      glGenTextures(1, &Reflection_Image);
      glBindTexture(GL_TEXTURE_2D, Reflection_Image);
      glTexImage2D(GL_TEXTURE_2D, 0, Image_Data->format->BytesPerPixel, Image_Data->w, Image_Data->h, 0, Image_Data->format->BytesPerPixel == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, Image_Data->pixels);
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);	
      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
      SDL_FreeSurface(Image_Data);
      Image_Data = NULL; 
      glBindTexture(GL_TEXTURE_2D, Reflection_Image); 
	  glBegin(GL_QUADS);
              glTexCoord2f(1,1);
	          glVertex3f(5,5,3);
              glTexCoord2f(1,0);
	          glVertex3f(5,-5,3);
              glTexCoord2f(0,0);
	          glVertex3f(-5,-5,3);
              glTexCoord2f(0,1);
	          glVertex3f(-5,5,3);
          glEnd();
      glPopMatrix();
Only problem is that nothing shows up, it seems like it should work but I don't really have any exerience doing this so anyone who has or might know what was wrong the help would be much appreciated. thanks [smile] yes I have GL_TEXTURE_2D enabled =) Ok well after some poking around I realized that the following line should most likely be included glTexImage2D(GL_TEXTURE_2D, 0, Image_Data->format->BytesPerPixel, Image_Data->w, Image_Data->h, 0, Image_Data->format->BytesPerPixel == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, Image_Data->pixels); I tried it and vola! it works, rather slow and understandably so but it works. =). Now time for some optomization [Edited by - raptorstrike on October 5, 2006 4:12:44 PM]

Share this post


Link to post
Share on other sites
You're not actually doing anything with the image_data (like transferring it to the GL) before you free it. You need a glTexImage2D or something.

In any case, using glReadPixels is a really bad idea. It's possible to copy directly from the framebuffer into a texture without going back and forth across the bus... Check out glCopyTexSubImage2D().

Share this post


Link to post
Share on other sites
Hmm it may just be my video card but rendering to texture is REALLY slow, im getting like 1fps... Any way that this can be made faster (I have changed my previous code around alot its not as bulky now but still very slow) I've seen this technique used in real time but perhaps those were just really good computers.

Share this post


Link to post
Share on other sites
The texture copy should be really fast (all happening on the video card), enough for real-time apps. One possibility is that your framebuffer bit depth is different than the bit depth of the texture you're copying into. This could cause GL to convert the data on the CPU, with associated slowness. I've seen drivers default to 16-bit framebuffers on some cards when you use GL_RGBA instead of GL_RGBA8.

Share this post


Link to post
Share on other sites
Well I remebered that my video card doesn't handle non power of 2 texture well at ALL (the frame rate really drops) and relized that my viewing window was not a power of 2. So I changed the window to be 1024 by 1024 and vola!... now I just have to figure out how to make that full screen.

Share this post


Link to post
Share on other sites
Now if you want speed :

You'll find many docs and samples on the sites of Nvidia or ATI. (Seek subjects like texture transfers, procedural, etc...)

With more recent gl technologies like CopyTexSubImage, Pixel Buffers or Pixel Buffer Objects, the trend is that procedural textures become more and more popular. Generate many things on the fly and use some cache to improve details/realism/complexity.

You will quickly see that ReadPixels is by far the less efficient method.

As Fingers said, the goal is to stay as much as possible on the server side (in video memory)

Share this post


Link to post
Share on other sites
O yes I definetly agree, I switched over to that method almost imediatly after the post was made, much faster. The think is. In windowed mode the effect doesn't work right because the bar at the top with a window title cuts off the window and causes a black band to be rendered on the polygon

Share this post


Link to post
Share on other sites
You can use a 1024x1024 texture with a window/fullscreen resolution of 1024x768, it merely wastes a little memory... When you copy the framebuffer into the texture it won't fill all of it (hence, the copy-tex-SUB-image), so when you're rendering it on a polygon you'll need to use the UV coordinates to make it only render the parts that have something in them. E.g. if you copy the 1024x768 screen to the "bottom" of the texture, then in the glTexCoord2f calls you'd use (0, 0.75) and (1, 0.75) instead of (0, 1) and (1,1) for the top vertices.

Framebuffer objects (FBO) are a more general solution for "off-screen" rendering with arbitrary resolution but I think you need to use extensions to use them in Windows.

Share this post


Link to post
Share on other sites
Yeah, FBOs will be faster and might actually be easier to do than what you're doing right now. Just get GLEW up and running to get OpenGL extensions (it's one include and a call to an initialize function) and you're set.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this