Sign in to follow this  
AverageJoeSSU

OpenGL Pros/Cons of using WM_PAINT for rendering

Recommended Posts

szecs    2990
IMHO:
WM_PAINT for rendering ONLY when you don't have to update continuously: only when events (window messages) occur. Most games have to be updated repeatedly, so you have to render "outside" the message handling loop. So not in WM_PAINT.

Share this post


Link to post
Share on other sites
mhagain    13430
The problem with Windows messaging functions is that there is no guarantee of when the message will arrive at your application. So there will definitely be some latency between the time when your window needs to be redrawn and the time when your app gets the WM_PAINT and is actually redrawn. How long that is depends on a variety of factors, many of which are completely outside of the control of your app (some AV software might be hooking and examining all Windows messages for all apps as part of it's heuristics, for example). So what runs fast on one machine might be unacceptably slow on another.

You're better off writing a proper game loop (using PeekMessage instead of GetMessage) and doing your rendering in that.

Share this post


Link to post
Share on other sites
AverageJoeSSU    564
Yeah... i agree... so i currently have a peek message loop implemented, but am not sure how the device context lives through the application.

For some reason my device context gets lost (even with using OWN_DC).

I am running out of ideas as to why this is happening.

When using the WM_PAINT, you get difference DC's throughout your application.

Share this post


Link to post
Share on other sites
szecs    2990
Post code. Do you store all the handlers during the lifespan of the program (window, device, rendering context) and use them? Do you create the window/device/rendering context in the appropriate order?
RegisterClass(...)
MainWindow.hWnd=CreateWindowEx(...);
ShowWindow(...);

MainWindow.hDC = GetDC(MainWindow.hWnd);

PixelFormat = ChoosePixelFormat(MainWindow.hDC,&pfd);
SetPixelFormat(MainWindow.hDC,PixelFormat,&pfd);
MainWindow.hRC = wglCreateContext(MainWindow.hDC);
wglMakeCurrent(MainWindow.hDC,MainWindow.hRC);

OpenGLInitStuff();

Share this post


Link to post
Share on other sites
AverageJoeSSU    564
Ha... your code is unbelievably simplified.

I will refactor mine before i post my mess of code.

EDIT: It's actually not that bad... most of it is from the tuts.


GLuint PixelFormat; // Holds The Results After Searching For A Match
WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height

fullscreen=fullscreenflag; // Set The Global Fullscreen Flag

this->m_hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_GLOBALCLASS; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndPDummy;// WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = this->m_hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = _T("OpenGL"); // Set The Class Name

if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,_T("Failed To Register The Window Class."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (fullscreen) // Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox(NULL,_T("The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?"),_T("NeHe GL"),MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,_T("Program Will Now Close."),_T("ERROR"),MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE
}
}
}

if (fullscreen) // Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(FALSE); // Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
}

AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size

// Create The Window
if (!(m_hDevWindow=CreateWindowEx( dwExStyle, // Extended Style For The Window
_T("OpenGL"), // Class Name
title, // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
m_hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
// Retrieve the system error message for the last-error code
this->Shutdown(); // Reset The Display
MessageBox(NULL,_T("Window Creation Error."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

hookWindow(m_hDevWindow);

static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
32, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};

if (!(hDC=GetDC(m_hDevWindow))) // Did We Get A Device Context?
{
this->Shutdown(); // Reset The Display
MessageBox(NULL,_T("Can't Create A GL Device Context."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{
this->Shutdown(); // Reset The Display
MessageBox(NULL,_T("Can't Find A Suitable PixelFormat."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
this->Shutdown(); // Reset The Display
MessageBox(NULL,_T("Can't Set The PixelFormat."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
this->Shutdown(); // Reset The Display
MessageBox(NULL,_T("Can't Create A GL Rendering Context."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{
this->Shutdown(); // Reset The Display
MessageBox(NULL,_T("Can't Activate The GL Rendering Context."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

ShowWindow(m_hDevWindow,SW_SHOW); // Show The Window
SetForegroundWindow(m_hDevWindow); // Slightly Higher Priority
SetFocus(m_hDevWindow); // Sets Keyboard Focus To The Window
this->ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen


if (!this->OnInit()) // Initialize Our Newly Created GL Window
{
this->Shutdown(); // Reset The Display
MessageBox(NULL,_T("Initialization Failed."),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

this->soundMan.Init();
// load stolen windows sound for now
//this->soundMan.Load("..\\Content\\Sounds\\type.wav", false);
this->AssetMgr->GetSound("..\\Content\\Sounds\\type.wav", false, &this->soundMan);

this->lastTime = timeGetTime();
return TRUE;





and on shutdown, you can see where i get the 1425 error code

if (fullscreen) // Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
}

if (hRC) // Do We Have A Rendering Context?
{
if (!wglMakeCurrent(hDC,NULL)) // Are We Able To Release The DC And RC Contexts?
{
MessageBox(NULL,_T("Release Of DC And RC Failed."),_T("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION);
}

if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{
MessageBox(NULL,_T("Release Rendering Context Failed."),_T("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Set RC To NULL
}

bool Released = ReleaseDC(m_hDevWindow,hDC);
DWORD errr = GetLastError();
if (hDC && !Released) // Are We Able To Release The DC
{
MessageBox(NULL,_T("Release Device Context Failed."),_T("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
}
bool R = DestroyWindow(m_hDevWindow);
DWORD errrr = GetLastError();
if (m_hDevWindow && !DestroyWindow(m_hDevWindow)) // Are We Able To Destroy The Window?
{
MessageBox(NULL,_T("Could Not Release hWnd."),_T("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION);
m_hDevWindow=NULL; // Set hWnd To NULL
}

if (!UnregisterClass(_T("OpenGL"),m_hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL,_T("Could Not Unregister Class."),_T("SHUTDOWN ERROR"),MB_OK | MB_ICONINFORMATION);
m_hInstance=NULL; // Set hInstance To NULL
}




return S_OK;




[Edited by - AverageJoeSSU on October 18, 2010 12:05:40 AM]

Share this post


Link to post
Share on other sites
szecs    2990
Nope. Pay attention to the order that I posted!

You have to ShowWindow before you get the device. When I did it just like you do, I got very strange and seemingly unrelated bugs. With fonts for example. My code is simplified but that should be just enough.

The order is very important!!

Share this post


Link to post
Share on other sites
AverageJoeSSU    564
So,

I removed my "doOpenGLInit" function and went straight to shutdown, and it works correctly.

I am doing some weirdness for hooking in my WndProc which allows me to intialize my engine from a hwnd parameter.

http://msdn.microsoft.com/en-us/library/ms633591(VS.85).aspx

I think i am doing this incorrectly. (at least not correct enough to release).

I'll post some code when i am home.

Share this post


Link to post
Share on other sites
mhagain    13430
You might try running a PeekMessage loop, then sleeping for a bit (about 20 to 100 ms should be enough), after your CreateWindow - just to give everything a chance to settle down before you proceed with getting the DC. CreateWindow(Ex) sends a WM_CREATE message to your Window procedure before returning, but - like I indicated above - there is no guarantee that the message has actually arrived yet.

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  

  • Partner Spotlight

  • Similar Content

    • By pseudomarvin
      I assumed that if a shader is computationally expensive then the execution is just slower. But running the following GLSL FS instead just crashes
      void main() { float x = 0; float y = 0; int sum = 0; for (float x = 0; x < 10; x += 0.00005) { for (float y = 0; y < 10; y += 0.00005) { sum++; } } fragColor = vec4(1, 1, 1 , 1.0); } with unhandled exception in nvoglv32.dll. Are there any hard limits on the number of steps/time that a shader can take before it is shut down? I was thinking about implementing some time intensive computation in shaders where it would take on the order of seconds to compute a frame, is that possible? Thanks.
    • By Arulbabu Donbosco
      There are studios selling applications which is just copying any 3Dgraphic content and regenerating into another new window. especially for CAVE Virtual reality experience. so that the user opens REvite or CAD or any other 3D applications and opens a model. then when the user selects the rendered window the VR application copies the 3D model information from the OpenGL window. 
      I got the clue that the VR application replaces the windows opengl32.dll file. how this is possible ... how can we copy the 3d content from the current OpenGL window.
      anyone, please help me .. how to go further... to create an application like VR CAVE. 
       
      Thanks
    • By cebugdev
      hi all,

      i am trying to build an OpenGL 2D GUI system, (yeah yeah, i know i should not be re inventing the wheel, but this is for educational and some other purpose only),
      i have built GUI system before using 2D systems such as that of HTML/JS canvas, but in 2D system, i can directly match a mouse coordinates to the actual graphic coordinates with additional computation for screen size/ratio/scale ofcourse.
      now i want to port it to OpenGL, i know that to render a 2D object in OpenGL we specify coordiantes in Clip space or use the orthographic projection, now heres what i need help about.
      1. what is the right way of rendering the GUI? is it thru drawing in clip space or switching to ortho projection?
      2. from screen coordinates (top left is 0,0 nd bottom right is width height), how can i map the mouse coordinates to OpenGL 2D so that mouse events such as button click works? In consideration ofcourse to the current screen/size dimension.
      3. when let say if the screen size/dimension is different, how to handle this? in my previous javascript 2D engine using canvas, i just have my working coordinates and then just perform the bitblk or copying my working canvas to screen canvas and scale the mouse coordinates from there, in OpenGL how to work on a multiple screen sizes (more like an OpenGL ES question).
      lastly, if you guys know any books, resources, links or tutorials that handle or discuss this, i found one with marekknows opengl game engine website but its not free,
      Just let me know. Did not have any luck finding resource in google for writing our own OpenGL GUI framework.
      IF there are no any available online, just let me know, what things do i need to look into for OpenGL and i will study them one by one to make it work.
      thank you, and looking forward to positive replies.
    • By fllwr0491
      I have a few beginner questions about tesselation that I really have no clue.
      The opengl wiki doesn't seem to talk anything about the details.
       
      What is the relationship between TCS layout out and TES layout in?
      How does the tesselator know how control points are organized?
          e.g. If TES input requests triangles, but TCS can output N vertices.
             What happens in this case?
      In this article,
      http://www.informit.com/articles/article.aspx?p=2120983
      the isoline example TCS out=4, but TES in=isoline.
      And gl_TessCoord is only a single one.
      So which ones are the control points?
      How are tesselator building primitives?
    • By Orella
      I've been developing a 2D Engine using SFML + ImGui.
      Here you can see an image
      The editor is rendered using ImGui and the scene window is a sf::RenderTexture where I draw the GameObjects and then is converted to ImGui::Image to render it in the editor.
      Now I need to create a 3D Engine during this year in my Bachelor Degree but using SDL2 + ImGui and I want to recreate what I did with the 2D Engine. 
      I've managed to render the editor like I did in the 2D Engine using this example that comes with ImGui. 
      3D Editor preview
      But I don't know how to create an equivalent of sf::RenderTexture in SDL2, so I can draw the 3D scene there and convert it to ImGui::Image to show it in the editor.
      If you can provide code will be better. And if you want me to provide any specific code tell me.
      Thanks!
  • Popular Now