PDA

View Full Version : draw after swapbuffer



cyrfer
03-30-2009, 12:14 PM
Hi,
I'm trying to add a new feature to an older application, basically a HUD drawn last. I can recompile the basic application, but I'm not having good luck recompiling the graphics dependency, which is a wrapper around a opengl-based render library in which there is no support since this company went belly-up a while ago.

I have added some draw code (which should basically clear the background, and render a square in viewport space) in the app-loop, after the application does its normal "gfxUpdate" call, and no part of my draw code is showing. I'm guessing the reason nothing is showing is because the frame buffer is being swapped before my draw code runs. I've tried sharing the HGLRC created by the dependency DLL instead of creating a new one, but that didn't fix it.

Any ideas about how to draw after one part of the code has drawn and you can't change its code? Thanks!

Ilian Dinev
03-30-2009, 06:49 PM
SwapBuffers(hdc); // effectively goes back to the backbuffer.
DrawMyExtraStuff();
SwapBuffers(hdc);
//Sleep(16); // optional

Make sure vsync is disabled.



Another way, which is very easy imho, is to hook SwapBuffers(). Microsoft made all API in Windows hookable on purpose. You modify the first 5 bytes of the code of SwapBuffers (those should be 0x8B55FF8B, 0xEC). (modification only done in RAM, no harm to the OS is done :) ) I'll provide info/code if you want (but in PM, we don't want script-kiddies doing nasties easily).

cyrfer
04-07-2009, 09:56 AM
I have confirmed that your code works as expected. However, even while disabling vsync (using wglSwapIntervalEXT(0) ), there is a nasty vertical trace that cuts through the "DrawMyExtraStuff" and shows the "DrawFirstStuff" behind it. Using wglSwapIntervalEXT(1) I see a ton of flicker.

The only satisfactory result I've found is to remove the first call to SwapBuffers. Unfortunately I don't have this option. Maybe this is a bug?...that NVidia (8800 GTX) would fix?

Ilian Dinev
04-07-2009, 10:22 AM
The flicker and tearing are expected.

Hooking code sent :)

cyrfer
04-07-2009, 01:48 PM
So the hooking code is quite impressive. However, I'm not able to get the effect I want. It's probably my fault, and I was wondering if you could take a look.

I'm using the hooking code like this:
BOOL result_inject = InjectCode("GDI32.dll", "SwapBuffers", MyCustom_SwapBuffers, &Previous_SwapBuffers );


And those functions are defined like:
/*WINGDIAPI*/ BOOL (WINAPI *Previous_SwapBuffers)(HDC);

BOOL WINAPI MyCustom_SwapBuffers(HDC hDC)
{
static unsigned int hits = 0;
unsigned int odd = hits % 2;
++hits;
if( odd )
{
return Previous_SwapBuffers(hDC);
}

return TRUE;
}


I've attempted to write a function that basically disregards the first call to SwapBuffers and actually does the swap the second time it gets hit. I'm really frustrated because I feel so close to the right solution, but when stepping through the debugger, I see that it works exactly as I think it should, but only for the first frame. The draw code draws a triangle with the legacy engine, and a rectangle with my new engine. The legacy engine uses glClear( col_buf_bit ) and renders first, then my new engine uses glClear(0) and renders. In the first frame, the rectangle (my new engine) successfully writes over part of the triangle (legacy engine)- BUT ONLY ON THE FIRST FRAME. Every frame after, I only see geometry from the new engine (which updates last). It might be interesting to note that the clear color from the legacy engine still works. How can I make geometry from the legacy engine remain?

Ilian Dinev
04-07-2009, 03:24 PM
You probably change OpenGL renderstates, while the old engine depends on them staying intact.

Why use glClear() ? I thought you'd be displaying alpha-blended stuff over the already-drawn color; and have depth-test disabled meanwhile.

Use glGet**() to retrieve states that you'll be changing, and then restore those states after you've done drawing the extra HUD stuff.

cyrfer
04-13-2009, 10:16 AM
why use glClear: The framework I was setting up seemed to make sense if I used glClear. I thought passing zero would be just as good as not calling it. You're right that I basically want alpha blended stuff showing which doesn't require depth testing.

I've been able to see some results. I think I was drawing in a window area that had dimensions of 0x0. Oops. Now I'm able to clear the whole screen if I choose, which is a good sign for now. So, because of the brilliant hooking code, I am eliminating all calls to SwapWindows until the final call to it is needed and this is giving me nice results, no tearing or flicker. My issue with SwapBuffer seems to be solved, but I have another (related) problem...

Now that I'm drawing after the other engine is drawing, the content of what the other engine is drawing is affected. Some sections of the terrain (its a flight sim) are transparent, and the skydome has similar problems. I am making an attempt to return any state changes back to their original values after I render, but I have made sure only a small number of states have changed and I'm drawing only vertex positions in immediate mode in my engine. I'm using a very small number of calls, glClearColor, glClear, glScissor, glViewport, glMatrixMode, glLoadIdentity, gluPerspective, gluLookAt, glPushMatrix, glTranslatef, glBegin, glVertex3f, glEnd, glPopMatrix.

I also tried using the OGRE engine instead of my engine as the engine to render after the flight sim. The same sections of the terrain that are missing from the flight sim are actually not missing when using OGRE, but they are much brighter in color, almost white. I'm pretty sure the dis-coloration is not from lighting, I'm pretty sure there are no lights in the flight sim, and I know there are no light states managed by the 2nd engine rendering over the flight sim. I guess I should check to see if Ogre enabled GL_LIGHTING, but I know my custom engine is not doing that (which has the missing polygons effect).

Why might some polygons have brighter colored textures or be completely missing when trying to draw over the results of another engine? Many thanks!

Ilian Dinev
04-13-2009, 10:58 AM
Debug the engine with glslDevil, while the hooking and your extra code are disabled. To see what API that engine uses, it should shed some light on what states cause that brightness.