Problems copying screen with glCopyTexImage2D

well if you GL_RGBA the texture and glCopy with GL_RGB? not good.

Nothing wrong with your texture generation on the whole (although the use of 4 as the internal format should be GL_RGBA8). Does not make a difference though.

I now have a better picture of what you are trying to achive with your last description. much appreciated.

There really is no need to copy front buffer to back…

in your draw routine do the following: (using the standard back buffer)

  1. Bind copytexture
  2. draw full screen quad
  3. Draw all ‘dirty’ quads
  4. copy backbuffer to texture
  5. perform GL swapbuffer

Notes:

  1. Copytexture is the texture you use to ‘capture’ the back buffer as suggested before (step 4 below)
  2. No need to clear screen (depth buffer or color buffer) as the full screen quad will erase the contents of the back buffer anyway. I assume depth testing is disabled as your console emulator is 2D.
  3. Update screen with new contents
  4. Capture screen ready for the start of the new frame.

So you see, there is no need to use front buffer. As long as the texture has the same dimensions as the GL window (back buffer) then the subcopy will copy everything correctly to the currently bound texture. Try and ensure your code sets the main GL window and capture texture dimensions to the same value (eg 512*512).

Okay, so now I just ignore the front buffer and get the frame from the back buffer. That makes sense. However, I still can’t get it to display properly. Here’s my draw screen procedure:


   // Draw the last frame:
   glBindTexture(GL_TEXTURE_2D, ScreenTextureID[1, 1]);
   glBegin(GL_QUADS);
   glTexCoord2f(0, 0);
   glVertex3f(0, 0, 0.0);
   glTexCoord2f(1, 0);
   glVertex3f(512, 0, 0);
   glTexCoord2f(1, 1);
   glVertex3f(512, 512, 0);
   glTexCoord2f(0, 1);
   glVertex3f(0, 512, 0);
   glEnd();

   // Draw the quads that have changed:
   FOR X := 0 TO 79 DO BEGIN
      FOR Y := 0 TO 49 DO BEGIN
         IF (ScreenBuffer[X, Y].Color <> OldScreenBuffer[X, Y].Color)
         OR (ScreenBuffer[X, Y].Character <> OldScreenBuffer[X, Y].Character)
         THEN DrawDirectlyToScreen(X, Y, ScreenBuffer[X, Y].Color, ScreenBuffer[X, Y].Character);
      END;
   END;

   // Save the frame to texture:
   glViewPort(0, 0, 512, 512);
   glReadBuffer(GL_BACK);
   glBindTexture(GL_TEXTURE_2D, ScreenTextureID[1, 1]);
   glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 512, 512);
   glViewPort(0, 0, 960, 600);

   SDL_GL_SwapBuffers();

   // Update dirty rectangles info:
   FOR X := 0 TO 79 DO BEGIN
      FOR Y := 0 TO 49 DO BEGIN
         OldScreenBuffer[X, Y].Character := ScreenBuffer[X, Y].Character;
         OldScreenBuffer[X, Y].Color := ScreenBuffer[X, Y].Color;
      END;
   END;

This is the result:

If I clear the screen to get rid of the garbled stuff (as I’m only doing this on the (0,0,512,512) part of the screen), this is what I get:

It’s odd that the texture doesn’t seem to fill from the upper left corner… :confused:

EDIT: And why is part of it mirrored horizontally?

Don’t forget that GL uses lower left as the origin (0,0).

I have not seen the projection matrix when you use for rendering.

At the start of your draw routine, use this:

//draw the last frame
glviewport (0,0,900,600);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho(0,900,0,600,0,100);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();

Also, have you tried setting the capturetexture dimension to 900 * 600? That way both the texture and backbuffer have the same dimensions so there is no possiblity of wrapping horizontal lines.

Here’s how I set up GL in the initialization part of my program:


   glEnable(GL_TEXTURE_2D);
   glClearColor(0.0, 0.0, 0.0, 0.0);
   glViewport(0, 0, ResolutionWidth, ResolutionHeight);
   glClear(GL_COLOR_BUFFER_BIT);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(0.0, ResolutionWidth, ResolutionHeight, 0.0, -1.0, 1.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

For all other texture drawing, the origin is upper left and works fine.

And wouldn’t setting the texture to 960x600 possibly cause problems as it’s not a power of 2?

your projection seems fine. also it should go to upper-left if you use it like you do already, glOrtho(0.0, ResolutionWidth, ResolutionHeight, 0.0, -1.0, 1.0);
the flip, any change you use some glScalef(-1) before rendering the quad or you simply provide wrong texture coordinates.

“And wouldn’t setting the texture to 960x600 possibly cause problems as it’s not a power of 2?”
it should be your window dimension. i.e. 1024x768 to map 1:1.

No glScalef. All the code is there in my previous post.

My window dimension is 960x600 when not fullscreen, but shouldn’t what I’m doing work anyway: setting glviewport and copying the upper left 512x512 part of the screen into a 512x512 texture?

or you simply provide wrong texture coordinates.

“but shouldn’t what I’m doing work anyway”
viewport is the 2d area you will actually see. making it smaller will rasterize smaller image and vice versa. by setting it to your window size you will get 1:1 mapping otherwise a resize. i would recommend to stick to OpenGL default origin (lower-left) because many calls operate on that (glScissor, glCopy). should.

Like I said, I posted all the code in my previous post. Can you see if I am providing wrong texture coordinates there?

I’m not sure I understand. Are you telling me that I can’t copy part of the viewscreen to a texture because using glviewport will just “shrink” the viewport size instead of limiting it to the part I want to copy?

And changing to the default lower left origin means I’ll have to change all my other code. Can’t I just do something to the glCopyTexSubImage2D call to make it work with the upper left origin?

“Like I said, I posted all the code in my previous post. Can you see if I am providing wrong texture coordinates there?”
no, because projection setup is totally unrelated! where is your drawing code of the quads?

“I’m not sure I understand. Are you telling me that I can’t copy part of the viewscreen to a texture because using glviewport will just “shrink” the viewport size instead of limiting it to the part I want to copy?”
you can copy whatever is inside your backbuffer. when you draw it (glBegin() glEnd() / glDrawElemets / whatever) it will make a difference. either or just leave the parameters on glViewport and glOrtho to your screen size.

“And changing to the default lower left origin means I’ll have to change all my other code. Can’t I just do something to the glCopyTexSubImage2D call to make it work with the upper left origin?”
you can adjust the y coordinate. y - screenHeight to flip it.

What GL_Version are you using?
Specifying a null pointer at texture creation only works for version 1.1 and up.
I’m guessing, but the garbled texture would indicate something like this.

Does it help to pass a 512x512x4 byte array when setting up the textures?

It’s in post #259899, two posts above the one you’re looking at.

So I don’t need to alter glviewport? Why was I then previously told to set glviewport to the size of the texture to copy to and then reset it to the screen size after copying?

Okay, so if it would be glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 512, 512, 512) with lower left origin it will be glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 512 - 600, 512, 512) with upper left origin? Then I get a negative y value…?

i hope this helps:
http://www.lighthouse3d.com/opengl/glut/index.php?bmpfontortho

they use gluOrtho for orthographic projection, it is same as glOrtho(0.0,w,h,0.0,-1.0,+1.0); also they use glScalef(1,-1,1) to reflect the origin.

my bad on y - screenHeight;
say screenHeight = 800; y = 0;
y in lower left will be 800 - 0 = 800 in upper left copied what you need to copy (now y axis is pointing down).

I’m using “1.5.0 - Build 6.14.10.4814”.

The texture isn’t garbled when I clear the screen. The garbled stuff is just the part of the screen that doesn’t get drawn, since I’m only trying to get it to work on the upper left 512x512 part of the screen at the moment. And the texture gets filled with data the first time I run the update screen loop anyway, so that shouldn’t be a problem, should it?

Okay, using Height - y (which is 600 - 512 in my code) results in this:

It’s a bit better as it’s defintely filling the upper left 512x512 part now…

That sounds ancient!

What hardware/plattform/drivers are we talking about here anyway?

Have you tried a simple app with glCopyTexSubImage2D() ?

It still looks to me as if someone is poking around in texture memory…

I think I figured it out. I just had to pass the texture from bottom to top when drawing it as well. Seems to work now. :slight_smile:

Hmmm, that doesn’t explain mirroring, wrong colors and pixels, though…

No, it seems there was still some problem with the data in the textures when initialized with NULL. I just copied a completely black image to the textures.