OpenGL - c++, zużycie procesora 100%

0
 #include <windows.h>
#include <stdio.h>
#include <gl\gl.h>
#include <gl\glu.h>

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"glu32.lib")

#include "ExampleProject.h"

HINSTANCE hInst;

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{
	if (height == 0)
		height = 1;

	glViewport(0, 0, width, height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 1000.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  HWND hWndButton;
  HWND hWndAbout;
  switch (message) 
  { 
  case WM_SIZE:
	  ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));
	  break;
  case WM_DESTROY:

    PostQuitMessage(0);
    break;
  }

  return DefWindowProc (hwnd, message, wParam, lParam);
}

int DrawGLScene(GLvoid)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glLoadIdentity();
	glTranslatef(0, 0, -10);

	glBegin(GL_LINE_STRIP);

	glColor3d(1, 0, 0);

	glVertex3d(0, 0, 0);
	glVertex3d(1, 1, 0);

	glVertex3d(0, 1, 0);
	glVertex3d(1, 0, 0);


	glEnd();
	return 1;
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
  hInst = hInstance;

  WNDCLASS wc;
  wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
  wc.lpfnWndProc = (WNDPROC)WndProc; 
  wc.cbClsExtra = 0; 
  wc.cbWndExtra = 0; 
  wc.hInstance = hInstance; 
  wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(FIRSTAPP_ICON_MAIN)); 
  wc.hCursor = LoadCursor(NULL, IDC_HAND); 
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 
  wc.lpszMenuName = MAKEINTRESOURCE(FIRSTAPP_MENU_MAIN); 
  wc.lpszClassName = TEXT("ExampleProjectWindowClass"); 

  if ( !RegisterClass( &wc ) ) return( FALSE );

  HWND hWnd = CreateWindow( TEXT("ExampleProjectWindowClass"),
                            TEXT("ExampleProjectWindow"),
                            WS_OVERLAPPEDWINDOW,
                            0,
                            0,
                            600,
                            800,
                            NULL,
                            NULL,
                            hInstance, 
                            NULL);

  if ( hWnd == NULL ) return( FALSE );

  static PIXELFORMATDESCRIPTOR pfd =
  {
	  sizeof(PIXELFORMATDESCRIPTOR),
	  1,
	  PFD_DRAW_TO_WINDOW |
	  PFD_SUPPORT_OPENGL |
	  PFD_DOUBLEBUFFER,
	  PFD_TYPE_RGBA,
	  16,
	  0,0,0,0,0,0,
	  0,
	  0,
	  0,
	  0,0,0,0,
	  16,
	  0,
	  0,
	  PFD_MAIN_PLANE,
	  0,
	  0,0,0
  };

  HDC hDC = NULL;
  HGLRC hRC = NULL;
  GLuint PixelFormat;

  if (!(hDC = GetDC(hWnd))) return 0;
  if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) return 0;

  if (!SetPixelFormat(hDC, PixelFormat, &pfd)) return 0;
  if (!(hRC = wglCreateContext(hDC))) return 0;
  if (!wglMakeCurrent(hDC, hRC)) return 0;

  ShowWindow(hWnd,iCmdShow);
  SetForegroundWindow(hWnd);
  SetFocus(hWnd);

  MSG msg;

  BOOL done = false;
  while (!done)
  {
	  if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	  {
		  if (msg.message == WM_QUIT) { done = TRUE; }
		  else
		  {
			  TranslateMessage(&msg);
			  DispatchMessage(&msg);

		  }
	  }
	  else
	  {
		  DrawGLScene();
		  SwapBuffers(hDC);
	  }
  }

  if (hRC)
  {
	  !wglMakeCurrent(NULL, NULL);
	  !wglDeleteContext(hRC);
	  hRC = NULL;
  }
  if (hDC && !ReleaseDC(hWnd, hDC)) { hDC = NULL; }
  if (hWnd && !DestroyWindow(hWnd)) { hWnd = NULL; }


  return 0;
}

Jestem jak na razie kompletnie zielony w OpenGL i piszę prosty program do rysowanie czegokolwiek jak na razie (linii, punktów, wielokątów). Dlaczego przy tak prostym programie pokazuje mi się zużycie CPU 100%? Jak temu zaradzić bo nie za bardzo mi się to podoba.

2

Dlaczego przy tak prostym programie pokazuje mi się zużycie CPU 100%? Jak temu zaradzić bo nie za bardzo mi się to podoba.

A dlaczego nie miałoby?

while (!done)
  {
      if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
      {
          if (msg.message == WM_QUIT) { done = TRUE; }
          else
          {
              TranslateMessage(&msg);
              DispatchMessage(&msg);
 
          }
      }
      else
      {
          DrawGLScene();
          SwapBuffers(hDC);
      }
  }

PeekMessage prawie zawsze zwraca FALSE (brak komunikatu). Pętla więc w praktyce wygląda tak:

  while (!done)
  {
          DrawGLScene();
          SwapBuffers(hDC);
  }

Czyli bez przerwy rysujesz na nowo, tak szybko jak komputer wydoli.

W przypadku statycznego obrazka wystarczy narysować raz. Najlepiej w WM_PAINT. Tylko pamiętaj żeby zrobić ValidateRect po narysowaniu.

W przypadku animacji wypadałoby spowolnić pętlę do częstotliwości odświeżania monitora. Da się to pod OpenGL zrobić, chwilowo nie mam przykładu. Może później (wieczorem) wrzucę.

  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 

Tutaj daj NULL. I tak czyścisz okno za pomocą glClear, nie potrzebujesz dwukrotnego czyszczenia.

0
#include <windows.h>
#include <stdio.h>
#include <gl\gl.h>
#include <gl\glu.h>

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"glu32.lib")

#include "ExampleProject.h"

HINSTANCE hInst;

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{
	if (height == 0)
		height = 1;

	glViewport(0, 0, width, height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 1000.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

int DrawGLScene(GLvoid)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glLoadIdentity();
	glTranslatef(0, 0, -10);

	glBegin(GL_LINE_LOOP);

	glColor3d(1, 0, 0);

	glVertex3d(0, 0, 0);
	glVertex3d(1, 1, 0);

	glVertex3d(0, 1, 0);
	glVertex3d(1, 0, 0);


	glEnd();

	glBegin(GL_LINES);

	glColor3d(0, 1, 0);

	glVertex3d(2, 0, 0);
	glVertex3d(2, 2, 0);

	glEnd();

	glBegin(GL_TRIANGLES);

	glColor3d(0, 0, 1);

	glVertex3d(-1, 0, 0);
	glVertex3d(-3, 0, 0);
	glVertex3d(-2, 2, 0);

	glEnd();

	glBegin(GL_QUADS);

	glColor3d(1, 1, 0);

	glVertex3d(-1, -1, 0);
	glVertex3d(0, -1, 0);
	glVertex3d(0, -3, 0);
	glVertex3d(-1, -2, 0);

	glEnd();

	return 1;
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  HWND hWndButton;
  HWND hWndAbout;
  switch (message) 
  { 
  case WM_PAINT:
	  DrawGLScene();
	  SwapBuffers(GetDC(hwnd));
	  break;
  case WM_SIZE:
	  ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));
	  break;
  case WM_DESTROY:

    PostQuitMessage(0);
    break;
  }

  return DefWindowProc (hwnd, message, wParam, lParam);
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
  hInst = hInstance;

  WNDCLASS wc;
  wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
  wc.lpfnWndProc = (WNDPROC)WndProc; 
  wc.cbClsExtra = 0; 
  wc.cbWndExtra = 0; 
  wc.hInstance = hInstance; 
  wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(FIRSTAPP_ICON_MAIN)); 
  wc.hCursor = LoadCursor(NULL, IDC_HAND); 
  wc.hbrBackground = NULL;
  wc.lpszMenuName = MAKEINTRESOURCE(FIRSTAPP_MENU_MAIN); 
  wc.lpszClassName = TEXT("ExampleProjectWindowClass"); 

  if ( !RegisterClass( &wc ) ) return( FALSE );

  HWND hWnd = CreateWindow( TEXT("ExampleProjectWindowClass"),
                            TEXT("ExampleProjectWindow"),
                            WS_OVERLAPPEDWINDOW,
                            0,
                            0,
                            600,
                            800,
                            NULL,
                            NULL,
                            hInstance, 
                            NULL);

  if ( hWnd == NULL ) return( FALSE );

  static PIXELFORMATDESCRIPTOR pfd =
  {
	  sizeof(PIXELFORMATDESCRIPTOR),
	  1,
	  PFD_DRAW_TO_WINDOW |
	  PFD_SUPPORT_OPENGL |
	  PFD_DOUBLEBUFFER,
	  PFD_TYPE_RGBA,
	  16,
	  0,0,0,0,0,0,
	  0,
	  0,
	  0,
	  0,0,0,0,
	  16,
	  0,
	  0,
	  PFD_MAIN_PLANE,
	  0,
	  0,0,0
  };

  HDC hDC = NULL;
  HGLRC hRC = NULL;
  GLuint PixelFormat;

  if (!(hDC = GetDC(hWnd))) return 0;
  if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) return 0;

  if (!SetPixelFormat(hDC, PixelFormat, &pfd)) return 0;
  if (!(hRC = wglCreateContext(hDC))) return 0;
  if (!wglMakeCurrent(hDC, hRC)) return 0;

  ShowWindow(hWnd,iCmdShow);
  SetForegroundWindow(hWnd);
  SetFocus(hWnd);

  MSG msg;

  BOOL done = false;
  while (!done)
  {
	  if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
	  {
		  if (msg.message == WM_QUIT) { done = TRUE; }
		  else
		  {
			  TranslateMessage(&msg);
			  DispatchMessage(&msg);
		  }
	  }
	  else
	  {
		  //DrawGLScene();
		  //SwapBuffers(hDC);
	  }
  }

  if (hRC)
  {
	  !wglMakeCurrent(NULL, NULL);
	  !wglDeleteContext(hRC);
	  hRC = NULL;
  }
  if (hDC && !ReleaseDC(hWnd, hDC)) { hDC = NULL; }
  if (hWnd && !DestroyWindow(hWnd)) { hWnd = NULL; }


  return 0;
}
 

@Azarien: Dzięki. Teraz mi się udało zbić obciążenie procesora do 45%.

0
#include <windows.h>
#include <stdio.h>
#include <gl\gl.h>
#include <gl\glu.h>

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"glu32.lib")

#include "ExampleProject.h"

HINSTANCE hInst;

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{
	if (height == 0)
		height = 1;

	glViewport(0, 0, width, height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 1000.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

int DrawGLScene(GLvoid)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glLoadIdentity();
	glTranslatef(0, 0, -10);
	glRotatef(0,0, 0, 0);

	glBegin(GL_POLYGON);

	glColor3d(1, 0, 0);

	glVertex3d(2, 0, 0);
	glVertex3d(0, 2, 0);
	glVertex3d(0, 0, 2);

	glEnd();

	return 1;
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  HWND hWndButton;
  HWND hWndAbout;
  switch (message) 
  { 
  case WM_PAINT:
	  DrawGLScene();
	  SwapBuffers(GetDC(hwnd));
	  RECT rect;
	  GetClientRect(hwnd, &rect);
	  ValidateRect(hwnd, &rect);
	  break;
  case WM_SIZE:
	  ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));
	  break;
  case WM_DESTROY:
    PostQuitMessage(0);
    break;
  }

  return DefWindowProc (hwnd, message, wParam, lParam);
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
  hInst = hInstance;

  WNDCLASS wc;
  wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
  wc.lpfnWndProc = (WNDPROC)WndProc; 
  wc.cbClsExtra = 0; 
  wc.cbWndExtra = 0; 
  wc.hInstance = hInstance; 
  wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(FIRSTAPP_ICON_MAIN)); 
  wc.hCursor = LoadCursor(NULL, IDC_HAND); 
  wc.hbrBackground = NULL;
  wc.lpszMenuName = MAKEINTRESOURCE(FIRSTAPP_MENU_MAIN); 
  wc.lpszClassName = TEXT("ExampleProjectWindowClass"); 

  if ( !RegisterClass( &wc ) ) return( FALSE );

  HWND hWnd = CreateWindow( TEXT("ExampleProjectWindowClass"),
                            TEXT("ExampleProjectWindow"),
                            WS_OVERLAPPEDWINDOW,
                            0,
                            0,
                            600,
                            800,
                            NULL,
                            NULL,
                            hInstance, 
                            NULL);

  if ( hWnd == NULL ) return( FALSE );

  static PIXELFORMATDESCRIPTOR pfd =
  {
	  sizeof(PIXELFORMATDESCRIPTOR),
	  1,
	  PFD_DRAW_TO_WINDOW |
	  PFD_SUPPORT_OPENGL |
	  PFD_DOUBLEBUFFER,
	  PFD_TYPE_RGBA,
	  16,
	  0,0,0,0,0,0,
	  0,
	  0,
	  0,
	  0,0,0,0,
	  16,
	  0,
	  0,
	  PFD_MAIN_PLANE,
	  0,
	  0,0,0
  };

  HDC hDC = NULL;
  HGLRC hRC = NULL;
  GLuint PixelFormat;

  if (!(hDC = GetDC(hWnd))) return 0;
  if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) return 0;

  if (!SetPixelFormat(hDC, PixelFormat, &pfd)) return 0;
  if (!(hRC = wglCreateContext(hDC))) return 0;
  if (!wglMakeCurrent(hDC, hRC)) return 0;

  ShowWindow(hWnd,iCmdShow);
  SetForegroundWindow(hWnd);
  SetFocus(hWnd);

  MSG msg;

  BOOL done = false;
  while (!done)
  {
	  if (GetMessage(&msg, NULL, 0, 0))
	  {
		  if (msg.message == WM_QUIT) { done = TRUE; }
		  else
		  {
			  TranslateMessage(&msg);
			  DispatchMessage(&msg);
		  }
	  }
	  else
	  {
		  //DrawGLScene();
		  //SwapBuffers(hDC);
	  }
  }

  if (hRC)
  {
	  !wglMakeCurrent(NULL, NULL);
	  !wglDeleteContext(hRC);
	  hRC = NULL;
  }
  if (hDC && !ReleaseDC(hWnd, hDC)) { hDC = NULL; }
  if (hWnd && !DestroyWindow(hWnd)) { hWnd = NULL; }


  return 0;
}
 

Teraz obciążenie procka zeszło do maks 10%, więc jest git. Nie wiem czemu ale nie mogę teraz aplikacji zamknąć, nawet po naduszeniu x w prawym górnym rogu. Trzeba zawsze robić "Stop debugging".

1 użytkowników online, w tym zalogowanych: 0, gości: 1