chapter4.cpp
来自「一本关于OPenGL的很好的电子书」· C++ 代码 · 共 886 行 · 第 1/2 页
CPP
886 行
g_hInstance, // application instance
NULL); // no extra params
// see if our window handle is valid
if (!g_hwnd)
{
// reset the display
KillWindow();
MessageBox(NULL, "Unable to create window", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
// get a device context
if (!(g_hdc = GetDC(g_hwnd)))
{
// reset the display
KillWindow();
MessageBox(NULL,"Unable to create device context", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
// set the pixel format we want
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of structure
1, // default version
PFD_DRAW_TO_WINDOW | // window drawing support
PFD_SUPPORT_OPENGL | // OpenGL support
PFD_DOUBLEBUFFER, // double buffering support
PFD_TYPE_RGBA, // RGBA color mode
bits, // 32 bit color mode
0, 0, 0, 0, 0, 0, // ignore color bits, non-palettized mode
0, // no alpha buffer
0, // ignore shift bit
0, // no accumulation buffer
0, 0, 0, 0, // ignore accumulation bits
16, // 16 bit z-buffer size
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main drawing plane
0, // reserved
0, 0, 0 }; // layer masks ignored
GLuint pixelFormat;
// choose best matching pixel format
if (!(pixelFormat = ChoosePixelFormat(g_hdc, &pfd)))
{
// reset the display
KillWindow();
MessageBox(NULL, "Can't find an appropriate pixel format", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
// set pixel format to device context
if(!SetPixelFormat(g_hdc, pixelFormat,&pfd))
{
// reset the display
KillWindow();
MessageBox(NULL, "Unable to set pixel format", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
// create the OpenGL rendering context
if (!(g_hrc = wglCreateContext(g_hdc)))
{
// reset the display
KillWindow();
MessageBox(NULL, "Unable to create OpenGL rendering context", "Error",MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
// now make the rendering context the active one
if(!wglMakeCurrent(g_hdc, g_hrc))
{
// reset the display
KillWindow();
MessageBox(NULL,"Unable to activate OpenGL rendering context", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
// show the window in the forground, and set the keyboard focus to it
ShowWindow(g_hwnd, SW_SHOW);
SetForegroundWindow(g_hwnd);
SetFocus(g_hwnd);
// set up the perspective for the current screen size
ResizeScene(width, height);
// do one-time initialization
if (!InitializeScene())
{
// reset the display
KillWindow();
MessageBox(NULL, "Initialization failed", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
return TRUE;
} // end SetupWindow()
/****************************************************************************
InitializeScene()
Sets up everything for our scene that only needs to be done once.
*****************************************************************************/
BOOL InitializeScene()
{
// use Gouraud shading
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// tell OpenGL to use the nicest built-in antialiasing possible
glHint(GL_POINT_SMOOTH, GL_NICEST);
glHint(GL_LINE_SMOOTH, GL_NICEST);
glHint(GL_POLYGON_SMOOTH, GL_NICEST);
// get the min and max point sizes and the step size
glGetFloatv(GL_POINT_SIZE_RANGE, g_pointSizeMinMax);
glGetFloatv(GL_POINT_SIZE_GRANULARITY, &g_pointSizeStep);
// get the min and max line widths and the step size
glGetFloatv(GL_LINE_WIDTH_RANGE, g_lineWidthMinMax);
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &g_lineWidthStep);
// set a line stipple pattern, setting each bit to repeat 3 times
GLushort lineStipple = 0xEB32;
glLineStipple(3, lineStipple);
// specify a polygon mask for stippling. This is a rough copy of the
// OpenGL logo
GLubyte mask[] = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x7, 0xFF, 0xF0, 0x0,
0x1F, 0xE0, 0x1E, 0x0,
0x7E, 0x20, 0x01, 0x0,
0x7F, 0x39, 0xAB, 0x6F,
0xFC, 0xA6, 0xAB, 0x6F,
0xF8, 0x66, 0x6E, 0xEC,
0xF8, 0x6A, 0x2A, 0x6C,
0xFC, 0x80, 0x02, 0x2C,
0x7F, 0x0, 0x1, 0xC8,
0x7F, 0x0, 0x1, 0xC8,
0x1F, 0xC0, 0x0C, 0x0,
0x07, 0xFF, 0xF0, 0x0,
0x03, 0xFF, 0xE0, 0x0,
0x0, 0x1C, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0
};
// tell OpenGL to use this mask for stippling
glPolygonStipple(mask);
return TRUE;
} // end InitializeScene()
/****************************************************************************
Resize()
Sets up the correct perspective based on the current screen size.
*****************************************************************************/
GLvoid ResizeScene(GLsizei width, GLsizei height)
{
// reset the viewport to the new dimensions
glViewport(100, 100, width-100, height-100);
// set our globals to match the (possibly new) values
g_width = width;
g_height = height;
// select the projection matrix and clear it out
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// set the perspective
gluOrtho2D(0, width, 0, height);
// select modelview matrix and clear it out
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
} // end ResizeScene()
/****************************************************************************
DisplayScene()
Actually draw our scene. This will be called every frame.
*****************************************************************************/
BOOL DisplayScene()
{
// clear the screen
glClear(GL_COLOR_BUFFER_BIT);
// we're using random numbers for most of the colors and primitive
// positions. Because we want to have the random numbers chosen every frame,
// we need to seed the random number generator with the same number every
// frame. Try commenting this line out to see what happens.
srand(g_currentPrimitive);
// only draw the currently selected primitive
switch(g_currentPrimitive)
{
case PT_POINT:
{
// draw 40 random points. Note that we're only making a single call to
// glBegin().
glBegin(GL_POINTS);
for (int n = 0; n < 40; n++)
{
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(rand() % g_width, rand() % g_height);
}
glEnd();
} break;
case PT_LINE:
{
// draw 10 random lines. Each pair of vertices specifies a new line
glBegin(GL_LINES);
for (int n = 0; n < 10; n++)
{
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(rand() % g_width, rand() % g_height);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(rand() % g_width, rand() % g_height);
}
glEnd();
} break;
case PT_TRIANGLE:
{
// draw 3 random triangles
glBegin(GL_TRIANGLES);
for (int n = 0; n < 3; n++)
{
glColor3ub(255, rand() % 256, rand() % 256);
glVertex2i(rand() % g_width, rand() % g_height);
glColor3ub(rand() % 256, 255, rand() % 256);
glVertex2i(rand() % g_width, rand() % g_height);
glColor3ub(rand() % 256, rand() % 256, 255);
glVertex2i(rand() % g_width, rand() % g_height);
}
glEnd();
} break;
case PT_TRIANGLE_STRIP:
{
// draw a single triangle strip
glBegin(GL_TRIANGLE_STRIP);
glColor3ub(255, 0, 0);
glVertex2i(10, 10);
glColor3ub(0, 255, 0);
glVertex2i(100, 50);
glColor3ub(0, 0, 255);
glVertex2i(75, 120);
glColor3ub(255, 0, 0);
glVertex2i(150, 110);
glColor3ub(0, 255, 0);
glVertex2i(200, 180);
glColor3ub(0, 0, 255);
glVertex2i(400, 300);
glColor3ub(255, 0, 0);
glVertex2i(350, 400);
glColor3ub(0, 255, 0);
glVertex2i(470, 275);
glColor3ub(0, 0, 255);
glVertex2i(600, 480);
glEnd();
} break;
case PT_TRIANGLE_FAN:
{
// draw a single triangle fan. Notice that this one is closed
// (the last vertex is the same as the second) but it doesn't
// have to be
glBegin(GL_TRIANGLE_FAN);
glColor3ub(255, 255, 255);
glVertex2i(400, 300);
glColor3ub(255, 0, 0);
glVertex2i(320, 310);
glColor3ub(0, 255, 0);
glVertex2i(300, 250);
glColor3ub(0, 0, 255);
glVertex2i(330, 220);
glColor3ub(255, 0, 0);
glVertex2i(340, 190);
glColor3ub(0, 255, 0);
glVertex2i(390, 180);
glColor3ub(0, 0, 255);
glVertex2i(430, 200);
glColor3ub(255, 0, 0);
glVertex2i(475, 285);
glColor3ub(0, 255, 0);
glVertex2i(510, 330);
glColor3ub(0, 0, 255);
glVertex2i(460, 380);
glColor3ub(255, 0, 0);
glVertex2i(405, 415);
glColor3ub(0, 255, 0);
glVertex2i(375, 375);
glColor3ub(0, 0, 255);
glVertex2i(350, 365);
glColor3ub(255, 0, 0);
glVertex2i(320, 310);
glEnd();
} break;
case PT_QUAD:
{
// draw 3 quads. I'm not doing these randomly because it'd be
// difficult to ensure that the polygons are convex and that
// edges don't cross
glBegin(GL_QUADS);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(60, 60);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(200, 80);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(210, 190);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(70, 200);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(500, 420);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(630, 450);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(635, 460);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(495, 500);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(190, 180);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(500, 190);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(400, 350);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(300, 300);
glEnd();
} break;
case PT_POLYGON:
{
// draw a single polygon. I'm not doing this randomly for
// the same reason quads aren't done randomly.
glBegin(GL_POLYGON);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(390, 420);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(300, 400);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(240, 300);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(250, 250);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(370, 200);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(480, 220);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(500, 290);
glColor3ub(rand() % 256, rand() % 256, rand() % 256);
glVertex2i(520, 400);
glEnd();
} break;
}
return TRUE;
} // end DisplayScene()
/****************************************************************************
KillWindow()
Restore the original display and dispose of the window, device context, and
rendering context properly.
*****************************************************************************/
BOOL KillWindow()
{
// restore the original display if we're in fullscreen mode
if (g_isFullscreen)
{
ChangeDisplaySettings(NULL, 0);
ShowCursor(TRUE);
}
// if we have an RC, release it
if (g_hrc)
{
// release the RC
if (!wglMakeCurrent(NULL,NULL))
{
MessageBox(NULL, "Unable to release rendering context", "Error", MB_OK | MB_ICONINFORMATION);
}
// delete the RC
if (!wglDeleteContext(g_hrc))
{
MessageBox(NULL, "Unable to delete rendering context", "Error", MB_OK | MB_ICONINFORMATION);
}
g_hrc = NULL;
}
// release the DC if we have one
if (g_hdc && !ReleaseDC(g_hwnd, g_hdc))
{
MessageBox(NULL, "Unable to release device context", "Error", MB_OK | MB_ICONINFORMATION);
g_hdc = NULL;
}
// destroy the window if we have a valid handle
if (g_hwnd && !DestroyWindow(g_hwnd))
{
MessageBox(NULL, "Unable to destroy window", "Error", MB_OK | MB_ICONINFORMATION);
g_hwnd = NULL;
}
// unregister our class so we can create a new one if we need to
if (!UnregisterClass(WND_CLASS_NAME, g_hInstance))
{
MessageBox(NULL, "Unable to unregister window class", "Error", MB_OK | MB_ICONINFORMATION);
g_hInstance = NULL;
}
return TRUE;
} // end KillWindow()
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?