C++ 使用并发c+解决问题+;窗户
我是第一次学习opengl,我正在尝试制作一个简单的程序。我的程序运行在两个线程中,一个线程在屏幕上呈现程序,而另一个线程更新程序的数据。然而,有时当我试图关闭我的程序时,我会收到一条令人讨厌的错误消息。我不明白为什么,尽管我觉得这是一个并发错误。这是我的密码 Main.cppC++ 使用并发c+解决问题+;窗户,c++,windows,multithreading,opengl,C++,Windows,Multithreading,Opengl,我是第一次学习opengl,我正在尝试制作一个简单的程序。我的程序运行在两个线程中,一个线程在屏幕上呈现程序,而另一个线程更新程序的数据。然而,有时当我试图关闭我的程序时,我会收到一条令人讨厌的错误消息。我不明白为什么,尽管我觉得这是一个并发错误。这是我的密码 Main.cpp #define WIN32_LEAN_AND_MEAN #define WIN32_EXTRA_LEAN #define GLX_GLXEXT_LEGACY #include <windows.h> #in
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#define GLX_GLXEXT_LEGACY
#include <windows.h>
#include "glwindow.h"
#include "example.h"
#include "util.h"
void updateThread(Example* example);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
{
const int windowWidth = 1024;
const int windowHeight = 768;
const int windowBPP = 16;
const int windowFullscreen = false;
GLWindow programWindow(hInstance);
Example example;
programWindow.attachExample(&example);
if (!programWindow.create(windowWidth, windowHeight, windowBPP, windowFullscreen))
{
MessageBox(NULL, "Unable to create the OpenGL Window", "An error occurred", MB_ICONERROR | MB_OK);
programWindow.destroy();
return 1;
}
if (!example.init())
{
MessageBox(NULL, "Could not initialize the application", "An error occurred", MB_ICONERROR | MB_OK);
programWindow.destroy();
return 1;
}
HANDLE thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) updateThread, &example, 0, 0);
example.setThread(&thread);
while(programWindow.isRunning())
{
programWindow.processEvents();
example.render();
programWindow.swapBuffers();
}
example.shutdown();
programWindow.destroy();
return 0;
}
void updateThread(Example* example)
{
setFPS(2000);
while(true)
{
example->update();
sync();
}
}
glwindow.cpp
#include <ctime>
#include <iostream>
#include <windows.h>
#include <GL/gl.h>
#include "wglext.h"
#include "glwindow.h"
#include "example.h"
typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*);
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
GLWindow::GLWindow(HINSTANCE hInstance):
m_isRunning(false),
m_example(NULL),
m_hinstance(hInstance),
m_lastTime(0)
{
}
bool GLWindow::create(int width, int height, int bpp, bool fullscreen)
{
DWORD dwExStyle;
DWORD dwStyle;
m_isFullscreen = fullscreen;
m_windowRect.left = (long)0;
m_windowRect.right = (long)width;
m_windowRect.top = (long)0;
m_windowRect.bottom = (long)height;
m_windowClass.cbSize = sizeof(WNDCLASSEX);
m_windowClass.style = CS_HREDRAW | CS_VREDRAW;
m_windowClass.lpfnWndProc = GLWindow::StaticWndProc;
m_windowClass.cbClsExtra = 0;
m_windowClass.cbWndExtra = 0;
m_windowClass.hInstance = m_hinstance;
m_windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
m_windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
m_windowClass.hbrBackground = NULL;
m_windowClass.lpszMenuName = NULL;
m_windowClass.lpszClassName = "GLClass";
m_windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
if(!RegisterClassEx(&m_windowClass))
{
return false;
}
if(m_isFullscreen)
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width;
dmScreenSettings.dmPelsHeight = height;
dmScreenSettings.dmBitsPerPel = bpp;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
MessageBox(NULL, "Display mode failed", NULL, MB_OK);
m_isFullscreen = false;
}
}
if (m_isFullscreen)
{
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
ShowCursor(false);
}
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
}
AdjustWindowRectEx(&m_windowRect, dwStyle, false, dwExStyle);
m_hwnd = CreateWindowEx(NULL, "GLClass", "BOGLGP - Chapter 2 - Simple OpenGL Application", dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, m_windowRect.right - m_windowRect.left, m_windowRect.bottom - m_windowRect.top, NULL, NULL, m_hinstance, this);
if (!m_hwnd)
{
MessageBox(NULL, "Window Creation Failed", NULL, MB_OK);
return 1;
}
m_hdc = GetDC(m_hwnd);
ShowWindow(m_hwnd, SW_SHOW);
UpdateWindow(m_hwnd);
m_lastTime = GetTickCount() / 1000.0f;
return true;
}
void GLWindow::destroy()
{
if (m_isFullscreen)
{
ChangeDisplaySettings(NULL, 0);
ShowCursor(true);
}
}
void GLWindow::attachExample(Example* example)
{
m_example = example;
}
bool GLWindow::isRunning()
{
return m_isRunning;
}
void GLWindow::processEvents()
{
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
void GLWindow::setupPixelFormat(void)
{
int pixelFormat;
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0,
};
pixelFormat = ChoosePixelFormat(m_hdc, &pfd);
SetPixelFormat(m_hdc, pixelFormat, &pfd);
}
LRESULT GLWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
{
m_hdc = GetDC(hWnd);
setupPixelFormat();
int attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 0,
0};
HGLRC tmpContext = wglCreateContext(m_hdc);
wglMakeCurrent(m_hdc, tmpContext);
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");
if (!wglCreateContextAttribsARB)
{
MessageBox(NULL, "Open GL 3.0 Is Not Supported", NULL, MB_OK);
m_hglrc = tmpContext;
DestroyWindow(hWnd);
return 0;
}
else
{
m_hglrc = wglCreateContextAttribsARB(m_hdc, 0, attribs);
wglDeleteContext(tmpContext);
}
wglMakeCurrent(m_hdc, m_hglrc);
m_isRunning = true;
}
break;
case WM_DESTROY:
case WM_CLOSE:
wglMakeCurrent(m_hdc, NULL);
wglDeleteContext(m_hglrc);
m_isRunning = false;
PostQuitMessage(0);
return 0;
break;
case WM_SIZE:
{
int height = HIWORD(lParam);
int width = LOWORD(lParam);
getAttachedExample()->onResize(width, height);
}
break;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
DestroyWindow(m_hwnd);
}
break;
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK GLWindow::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
GLWindow* window = NULL;
if(uMsg == WM_CREATE)
{
window = (GLWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)window);
}
else
{
window = (GLWindow*)GetWindowLongPtr(hWnd, GWL_USERDATA);
if(!window)
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
return window->WndProc(hWnd, uMsg, wParam, lParam);
}
float GLWindow::getElapsedSeconds()
{
float currentTime = float(GetTickCount()) / 1000.0f;
float seconds = float(currentTime - m_lastTime);
m_lastTime = currentTime;
return seconds;
}
#包括
#包括
#包括
#包括
#包括“wglext.h”
#包括“glwindow.h”
#包括“example.h”
typedef HGLRC(apientrypfwnwglcreatecontextattribsarbproc)(HDC、HGLRC、const int*);
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB=NULL;
GLWindow::GLWindow(HINSTANCE HINSTANCE):
m_正在运行(错误),
m_示例(空),
m_hinstance(hinstance),
m_上次(0)
{
}
bool GLWindow::create(int-width、int-height、int-bpp、bool-fullscreen)
{
德沃德·德韦克斯风格;
德沃德风格;
m_isFullscreen=全屏;
m_windowRect.left=(长)0;
m_windowRect.right=(长)宽度;
m_windowRect.top=(长)0;
m_windowRect.bottom=(长)高度;
m_windowClass.cbSize=sizeof(WNDCLASSEX);
m_windowClass.style=CS_HREDRAW | CS_VREDRAW;
m_windowClass.lpfnWndProc=GLWindow::StaticWndProc;
m_windowClass.cbClsExtra=0;
m_windowClass.cbWndExtra=0;
m_windowClass.hInstance=m_hInstance;
m_windowClass.hIcon=加载图标(NULL,IDI_应用程序);
m_windowClass.hCursor=LoadCursor(空,IDC_箭头);
m_windowClass.hbrBackground=NULL;
m_windowClass.lpszMenuName=NULL;
m_windowClass.lpszClassName=“GLClass”;
m_windowClass.hIconSm=LoadIcon(NULL,IDI_WINLOGO);
if(!RegisterClass(&m_windowClass))
{
返回false;
}
如果(m_为全屏)
{
DEVMODE DMS筛选设置;
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth=宽度;
dmScreenSettings.dmPelsHeight=高度;
dmScreenSettings.dmBitsPerPel=bpp;
dmScreenSettings.dmFields=DM|u BITSPERPEL | DM|u PELSWIDTH | DM|PELSHEIGHT;
if(更改显示设置(&dmScreenSettings,CD\u全屏)!=显示更改成功)
{
消息框(NULL,“显示模式失败”,NULL,MB_OK);
m_isFullscreen=false;
}
}
如果(m_为全屏)
{
dwExStyle=WS_EX_APPWINDOW;
dwStyle=WS_弹出窗口;
ShowCursor(假);
}
其他的
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle=WS_重叠窗口;
}
AdjustWindowRectEx(&m_windowRect,dwStyle,false,dwExStyle);
m|u hwnd=CreateWindowEx(NULL,“GLClass”,“BOGLGP-第2章-简单OpenGL应用程序”,dwStyle | WS|u CLIPCHILDREN | WS|CLIPSIBLINGS,
0,0,m_windowRect.right-m_windowRect.left,m_windowRect.bottom-m_windowRect.top,NULL,NULL,m_hinstance,this);
如果(!m_hwnd)
{
MessageBox(空,“窗口创建失败”,空,MB_OK);
返回1;
}
m_hdc=GetDC(m_hwnd);
显示窗口(m_hwnd,SW_SHOW);
更新域(m_hwnd);
m_lastTime=GetTickCount()/1000.0f;
返回true;
}
void GLWindow::destroy()
{
如果(m_为全屏)
{
ChangeDisplaySettings(空,0);
ShowCursor(true);
}
}
void GLWindow::attachExample(示例*示例)
{
m_示例=示例;
}
bool GLWindow::isRunning()
{
返回m_正在运行;
}
void GLWindow::processEvents()
{
味精;
while(peek消息(&msg,NULL,0,0,PM_-REMOVE))
{
翻译信息(&msg);
发送消息(&msg);
}
}
void GLWindow::setupPixelFormat(void)
{
整数像素格式;
像素描述符pfd=
{
sizeof(像素格式描述符),
1.
PFD_支持_OPENGL|
PFD_绘图_至_窗口|
PFD_双缓冲器,
PFD_类型_RGBA,
32,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_主飞机,
0,
0, 0, 0,
};
像素格式=选择像素格式(m_hdc和pfd);
SetPixelFormat(m_hdc、pixelFormat和pfd);
}
LRESULT GLWindow::WndProc(HWND HWND、UINT uMsg、WPARAM WPARAM、LPARAM LPARAM)
{
开关(uMsg)
{
案例WM_创建:
{
m_hdc=GetDC(hWnd);
设置像素格式();
int attribs[]={
WGL\U上下文\U主要\U版本\U ARB,3,
WGL_上下文_次要_版本_ARB,0,
0};
HGLRC tmpContext=wglCreateContext(m_hdc);
wglMakeCurrent(m_hdc,tmpContext);
wglCreateContextAttribsARB=(PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress(“wglCreateContextAttribsARB”);
如果(!wglCreateContextAttribsARB)
{
MessageBox(空,“不支持OpenGL 3.0”,空,MB_OK);
m_hglrc=tmpContext;
窗口(hWnd);
返回0;
}
其他的
{
m_hglrc=wglCreateContextAttribsARB(m_hdc,0,attribs);
wglDeleteContext(tmpContext);
}
wglMakeCurrent(m_hdc,m_hglrc);
m_isRunning=真;
}
打破
案例WM_销毁:
案例WM_结束:
wglMakeCurrent(m_hdc,空);
wglDeleteContext(m_hglrc);
m_isRunning=假;
PostQuitMessage(0);
返回0;
打破
案例WM_大小:
{
int height=HIWORD(lParam);
int width=LOWORD(LPRAM);
getAttachedExample()->onResize(宽度、高度);
}
打破
案例WM_键控:
if(wParam==VK_转义)
{
破坏窗口(m_hwnd);
}
打破
违约:
打破
}
返回DefWindowProc(hWnd、uMsg、wParam、lParam);
}
爱尔兰
#include <ctime>
#include <iostream>
#include <windows.h>
#include <GL/gl.h>
#include "wglext.h"
#include "glwindow.h"
#include "example.h"
typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*);
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
GLWindow::GLWindow(HINSTANCE hInstance):
m_isRunning(false),
m_example(NULL),
m_hinstance(hInstance),
m_lastTime(0)
{
}
bool GLWindow::create(int width, int height, int bpp, bool fullscreen)
{
DWORD dwExStyle;
DWORD dwStyle;
m_isFullscreen = fullscreen;
m_windowRect.left = (long)0;
m_windowRect.right = (long)width;
m_windowRect.top = (long)0;
m_windowRect.bottom = (long)height;
m_windowClass.cbSize = sizeof(WNDCLASSEX);
m_windowClass.style = CS_HREDRAW | CS_VREDRAW;
m_windowClass.lpfnWndProc = GLWindow::StaticWndProc;
m_windowClass.cbClsExtra = 0;
m_windowClass.cbWndExtra = 0;
m_windowClass.hInstance = m_hinstance;
m_windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
m_windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
m_windowClass.hbrBackground = NULL;
m_windowClass.lpszMenuName = NULL;
m_windowClass.lpszClassName = "GLClass";
m_windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
if(!RegisterClassEx(&m_windowClass))
{
return false;
}
if(m_isFullscreen)
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width;
dmScreenSettings.dmPelsHeight = height;
dmScreenSettings.dmBitsPerPel = bpp;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
MessageBox(NULL, "Display mode failed", NULL, MB_OK);
m_isFullscreen = false;
}
}
if (m_isFullscreen)
{
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
ShowCursor(false);
}
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
}
AdjustWindowRectEx(&m_windowRect, dwStyle, false, dwExStyle);
m_hwnd = CreateWindowEx(NULL, "GLClass", "BOGLGP - Chapter 2 - Simple OpenGL Application", dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, m_windowRect.right - m_windowRect.left, m_windowRect.bottom - m_windowRect.top, NULL, NULL, m_hinstance, this);
if (!m_hwnd)
{
MessageBox(NULL, "Window Creation Failed", NULL, MB_OK);
return 1;
}
m_hdc = GetDC(m_hwnd);
ShowWindow(m_hwnd, SW_SHOW);
UpdateWindow(m_hwnd);
m_lastTime = GetTickCount() / 1000.0f;
return true;
}
void GLWindow::destroy()
{
if (m_isFullscreen)
{
ChangeDisplaySettings(NULL, 0);
ShowCursor(true);
}
}
void GLWindow::attachExample(Example* example)
{
m_example = example;
}
bool GLWindow::isRunning()
{
return m_isRunning;
}
void GLWindow::processEvents()
{
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
void GLWindow::setupPixelFormat(void)
{
int pixelFormat;
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0,
};
pixelFormat = ChoosePixelFormat(m_hdc, &pfd);
SetPixelFormat(m_hdc, pixelFormat, &pfd);
}
LRESULT GLWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
{
m_hdc = GetDC(hWnd);
setupPixelFormat();
int attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 0,
0};
HGLRC tmpContext = wglCreateContext(m_hdc);
wglMakeCurrent(m_hdc, tmpContext);
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");
if (!wglCreateContextAttribsARB)
{
MessageBox(NULL, "Open GL 3.0 Is Not Supported", NULL, MB_OK);
m_hglrc = tmpContext;
DestroyWindow(hWnd);
return 0;
}
else
{
m_hglrc = wglCreateContextAttribsARB(m_hdc, 0, attribs);
wglDeleteContext(tmpContext);
}
wglMakeCurrent(m_hdc, m_hglrc);
m_isRunning = true;
}
break;
case WM_DESTROY:
case WM_CLOSE:
wglMakeCurrent(m_hdc, NULL);
wglDeleteContext(m_hglrc);
m_isRunning = false;
PostQuitMessage(0);
return 0;
break;
case WM_SIZE:
{
int height = HIWORD(lParam);
int width = LOWORD(lParam);
getAttachedExample()->onResize(width, height);
}
break;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
{
DestroyWindow(m_hwnd);
}
break;
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK GLWindow::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
GLWindow* window = NULL;
if(uMsg == WM_CREATE)
{
window = (GLWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)window);
}
else
{
window = (GLWindow*)GetWindowLongPtr(hWnd, GWL_USERDATA);
if(!window)
{
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
return window->WndProc(hWnd, uMsg, wParam, lParam);
}
float GLWindow::getElapsedSeconds()
{
float currentTime = float(GetTickCount()) / 1000.0f;
float seconds = float(currentTime - m_lastTime);
m_lastTime = currentTime;
return seconds;
}
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "example.h"
Example::Example()
{
m_rotationAngle = 0.0f;
}
bool Example::init()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
return true;
}
void Example::update()
{
const float SPEED = 15.0f;
m_rotationAngle += SPEED;
if (m_rotationAngle > 360.0f)
{
m_rotationAngle -= 360.0f;
}
}
void Example::render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(m_rotationAngle, 0, 0, 1);
glBegin(GL_TRIANGLES);
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glVertex3f(-1.0f, -0.5f, -4.0f);
glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, -0.5f, -4.0f);
glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
glVertex3f(0.0f, 0.5f, -4.0f);
glEnd();
}
void Example::shutdown()
{
TerminateThread(thread, 0);
}
void Example::onResize(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, float(width) / float(height), 1.0f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
while (true) {
...
if (IShouldExit()) break;
}