Programming °æ (¾«»ªÇø)
×÷ ¼Ò: crystal (»¨) on board 'programming'
Ìâ Ä¿: VC 4.0ÖÐʹÓÃOpenGL
À´ Ô´: ¹þ¶û±õ×϶¡ÏãÕ¾
ÈÕ ÆÚ: Sun Aug 10 11:53:02 1997
³ö ´¦: crystal.bbs@bbs.net.tsinghua.edu.cn
·¢ÐÅÈË: midi (ÃÔµÑ), ÐÅÇø: Program
±ê Ìâ: VC 4.0ÖÐʹÓÃOpenGL
* 41 — The OpenGL Graphics Library
+ OpenGL Overview
+ Basic OpenGL Concepts
+ Initialization
+ Drawing with OpenGL
+ Additional Libraries
+ Writing OpenGL Windows Applications in C
+ OpenGL Initialization
+ The Window Procedure
+ Compiling and Running the Application
+ OpenGL in MFC Applications
+ OpenGL initialization
+ Drawing the Cube
+ Running the Application
+ Summary
41 — The OpenGL Graphics Library
OpenGL is a device- and operating system-independent library for
three-dimensional graphics and graphics rendering. OpenGL was originally
developed by Silicon Graphics Inc. (SGI) for use on their high-end graphics
workstations. Since then, OpenGL has become a widely accepted standard with
implementations on many operating system and hardware platforms, including
the Windows NT and Windows 95 operating systems.
---------------------------------------------------------------------------
[Image]Note: OpenGL support under Windows 95 has just become available
recently. The Windows 95 version of the OpenGL development system and
redistributable run-time files are available as part of the October, 1995
or later release of the Microsoft Developer Library, level 2. There is no
support for OpenGL under Win32s.
---------------------------------------------------------------------------
In addition to the standard OpenGL Library implementation, Windows also
provides a series of functions that integrate OpenGL with the operating
system. In particular, functions are provided that associate OpenGL
rendering contexts with GDI device contexts. These Windows extensions to
the OpenGL Library are identified by names that begin with wgl. In addition
to these OpenGL extensions, a series of new Win32 API functions has also
been defined to facilitate certain aspects of OpenGL programming.
The OpenGL Library is large and complex. If you wish to have access to a
comprehensive set of manuals, you should consider purchasing The OpenGL
Reference Manual from the OpenGL Architecture Review Board, or The OpenGL
Programming Guide by Jackie Neider, Tom Davis, and Mason Woo. Both books
are published by Addison-Wesley.
In this chapter, in addition to presenting a brief (and far from
comprehensive!) overview of the OpenGL Library, I place the focus on using
OpenGL from Windows and MFC applications.
OpenGL Overview
The purpose of the OpenGL Library is to render two- and three-dimensional
objects into a frame buffer, such as the pixel memory of your computer's
graphics hardware.
The OpenGL Library is fundamentally procedural. What this means is that in
your application, you don't describe what an object looks like; instead,
you specify how an object is to be drawn. Complex geometric objects are
described in terms of simple elements that your application defines.
The OpenGL Library implementation follows the client-server model. OpenGL
clients and servers need not even reside on the same machine.
Basic OpenGL Concepts
At the basic level, the OpenGL Library deals with vertices. A vertex is a
point, for example the end point of a line, or a corner of a polygon.
Vertices can be two- or three-dimensional.
At the next level are primitives. Primitives consist of a group of one or
more vertices. For example, a rectangle described as a set of four vertices
is a primitive.
How vertices are assembled into primitives and how primitives are drawn
into a frame buffer are controlled by a variety of settings. For example,
applications can specify a three-dimensional transformation matrix that
defines how the coordinates of an object are translated into coordinates on
the drawing surface.
In addition to its ability to draw points and lines, OpenGL can also draw
surfaces, apply lighting specifications, and use texture bitmaps.
Another set of features enables applications to selectively use or discard
pixels. For example, drawing a pixel can be made conditional upon
properties such as the pixel's depth or its opacity.
A greatly simplified view of how OpenGL works is presented in Figure 41.1.
Figure 41.1. Simplified overview of OpenGL operations.
Initialization
Before the OpenGL Library can be used, a number of initialization steps
must be executed.
Every Windows OpenGL application must associate a rendering context with a
device context. The device context must be a display device context or a
memory device context that is compatible with the display device context.
To set up a rendering context, applications must first use the
SetPixelFormat Win32 function to set up a pixel format for the device;
next, they must call wglCreateContext with the device context handle as its
parameter. If successful, wglCreateContext returns a rendering context
handle of type HGLRC.
---------------------------------------------------------------------------
[Image]Note: Windows does not support drawing into a printer device context
using the OpenGL Library. If you wish to print an image created with
OpenGL, one possible workaround is to draw into a memory device context
that is compatible with the display device and then transfer the resulting
bitmap to the printer device.
---------------------------------------------------------------------------
OpenGL under Windows recognizes two types of pixel data modes: RGBA formats
and color index-based modes. When the RGBA mode is selected, pixel colors
are specified in the form of RGB color values. When color index mode is
selected, pixel colors are selected from the system palette using an index
value. These two modes become relevant on palette-based 256-color devices
(many VGA-compatible display cards). When your application uses the RGBA
mode on such a device, it must manage its own palette, and respond to
Windows palette notification messages.
There are specific requirements that must be met by a window that is to be
used for OpenGL operations. Specifically, such windows cannot be created
using a window class that has the CS_PARENTDC style set. The window itself
must have the WS_CLIPCHILDREN and the WS_CLIPSIBLINGS styles in order to be
compatible with OpenGL.
Note that to increase your application's performance, you may wish to use a
window class that has a null background brush; the window background will
be erased through the OpenGL Library anyway.
Before a rendering context can be used, it must be set up as the current
context using the wglMakeCurrent function. This function takes two
parameters, one of which is a device-context handle. Interestingly, this
handle does not need to be identical to the handle used in
wglCreateContext—but it must refer to the same device). Thus it is
possible, for example, to set up an OpenGL rendering context using a
device-context handle returned by GetDC, but use wglMakeCurrent with a
device-context handle returned by BeginPaint.
Once a rendering context is ready to accept commands, you may wish to send
additional initialization commands; for example, you may wish to erase the
frame buffer before drawing, set up coordinate transformations, configure
light sources, or enable and disable other options.
One initialization step that cannot be omitted is the call to the
glViewport function. Through this function, you can set up or modify the
size of the rendering viewport. Typically, you should call this function
once when the rendering context is initialized, and subsequently every time
your application receives a WM_SIZE message indicating that its window size
has changed.
Drawing with OpenGL
Most OpenGL drawing consists of a series of vertex operations enclosed
between a pair of glBegin and glEnd calls. The glBegin call identifies the
type of primitive that subsequent vertex operations define; glEnd marks the
end of constructing the primitive. For example, the following series of
calls constructs a pentagon:
glBegin(GL_POLYGON);
glVertex2d(0.0, 1.0);
glVertex2d(-0.951057, 0.309017);
glVertex2d(-0.587785, -0.809017);
glVertex2d(0.587785, -0.809017);
glVertex2d(0.951057, 0.309017);
glEnd();
The glBegin function can be used to define a variety of primitives. Table
41.1 lists the allowable parameters for this function.
Table 41.1. Primitives constructed through glBegin.
glBegin ParameterDescription
GL_POINTS A series of points
GL_LINES A series of lines
GL_LINE_STRIP A connected group of line segments
GL_LINE_LOOP A connected, closed group of line segments
GL_TRIANGLES A set of triangles
GL_TRIANGLE_STRIPA set of connected triangles
GL_TRIANGLE_FAN A set of connected triangles
GL_QUADS A set of quadrilaterals
GL_QUAD_STRIP A set of connected quadrilaterals
GL_POLYGON A polygon
In the case when glBegin defines a set of connected primitives, specific
rules govern how vertices of a primitive are reused as vertices of the
subsequent primitive. For example, if GL_LINE_STRIP is specified, the
vertex representing the end point of a line segment also becomes the
starting point of the next line segment.
Additional Libraries
In addition to basic OpenGL functions, Microsoft's OpenGL implementation
provides two additional OpenGL libraries.
The OpenGL Utility Library (GLU) contains a series of functions that deal
with texture support; coordinate transformation; rendering of spheres,
disks, and cylinders; B-spline curves and surfaces; and error handling.
Additionally, the GLU Library provides polygon tessellation functions;
these functions can be used to break down complex or concave polygons into
simple convex polygons (the only kind that OpenGL can handle).
The OpenGL Programming Guide Auxiliary Library (GLAUX), in addition to
providing functions for handling several three-dimensional objects, also
provides functions to manage and run an OpenGL application. These functions
are most useful for quick porting OpenGL applications from other
environments. In particular, these functions provide basic window
management, implement a simple message loop, and provide a window procedure
for basic message handling. However, these library functions are not
intended for use in production applications.
Writing OpenGL Windows Applications in C
Now for a look at a very simple OpenGL application. This application, shown
in Listing 41.1, displays a cube. The cube is slightly rotated to show a
three-dimensional appearance, and is lit from the side. In its simplicity,
this application is the OpenGL version of a Windows Hello, World
application.
Listing 41.1. A simple OpenGL application.
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
HGLRC hglrc;
void DrawHello(HWND hwnd)
{
HDC hDC;
PAINTSTRUCT paintStruct;
RECT clientRect;
GLfloat lightPos[4] = {-1.0F, 2.0F, 0.2F, 0.0F};
hDC = BeginPaint(hwnd, &paintStruct);
if (hDC != NULL)
{
GetClientRect(hwnd, &clientRect);
wglMakeCurrent(hDC, hglrc);
glViewport(0, 0, clientRect.right, clientRect.bottom);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
glColor4d(1.0, 1.0, 1.0, 1.0);
glRotated(30.0, 0.0, 1.0, 0.0);
glRotated(15.0, 1.0, 0.0, 0.0);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glBegin(GL_QUADS);
glNormal3d(0.0, -1.0, 0.0);
glVertex3d(0.5, -0.5, 0.5);
glVertex3d(-0.5, -0.5, 0.5);
glVertex3d(-0.5, -0.5, -0.5);
glVertex3d(0.5, -0.5, -0.5);
glNormal3d(0.0, 0.0, -1.0);
glVertex3d(-0.5, -0.5, -0.5);
glVertex3d(-0.5, 0.5, -0.5);
glVertex3d(0.5, 0.5, -0.5);
glVertex3d(0.5, -0.5, -0.5);
glNormal3d(1.0, 0.0, 0.0);
glVertex3d(0.5, -0.5, -0.5);
glVertex3d(0.5, 0.5, -0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(0.5, -0.5, 0.5);
glNormal3d(0.0, 0.0, 1.0);
glVertex3d(-0.5, -0.5, 0.5);
glVertex3d(-0.5, 0.5, 0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(0.5, -0.5, 0.5);
glNormal3d(-1.0, 0.0, 0.0);
glVertex3d(-0.5, -0.5, 0.5);
glVertex3d(-0.5, 0.5, 0.5);
glVertex3d(-0.5, 0.5, -0.5);
glVertex3d(-0.5, -0.5, -0.5);
glNormal3d(0.0, 1.0, 0.0);
glVertex3d(-0.5, 0.5, 0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(0.5, 0.5, -0.5);
glVertex3d(-0.5, 0.5, -0.5);
glEnd();
glFlush();
wglMakeCurrent(NULL, NULL);
EndPaint(hwnd, &paintStruct);
}
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_PAINT:
DrawHello(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR d3, int nCmdShow)
{
MSG msg;
HWND hwnd;
WNDCLASS wndClass;
HDC hDC;
PIXELFORMATDESCRIPTOR pfd;
int iPixelFormat;
if (hPrevInstance == NULL)
{
memset(&wndClass, 0, sizeof(wndClass));
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.lpszClassName = "HELLO";
if (!RegisterClass(&wndClass)) return FALSE;
}
hwnd = CreateWindow("HELLO", "HELLO",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);
hDC = GetDC(hwnd);
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.cDepthBits = 16;
iPixelFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, iPixelFormat, &pfd);
hglrc = wglCreateContext(hDC);
ReleaseDC(hwnd, hDC);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
DispatchMessage(&msg);
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hglrc);
return msg.wParam;
}
The following sections explain this application's method of operation.
Note that for the sake of simplicity, I did not include any palette
initialization in this application. For this reason, the application may
not behave properly on systems configured for 16 or 256 colors.
OpenGL Initialization
The first series of OpenGL calls in this application begins in WinMain,
immediately after the application's window has been created. After
obtaining a device-context handle for the client area of this window, the
device context's pixel format is set to a pixel format obtained through
ChoosePixelFormat. The ChoosePixelFormat function can be used to identify
pixel formats for a specific device that best match a set of required
characteristics.
Note that although we are using the RGBA data mode, this application does
not handle palette notification messages. This is done in order to keep the
application as simple as possible; in a production application, you would
certainly not want to omit creating and managing a palette that is
appropriate for your application.
After the pixel format has been specified, a rendering context is created
by a call to wglCreateContext. The rendering context handle is saved in a
global variable that will be accessed from within other functions.
When all initializations have been completed, the application enters its
message loop. After the message loop terminates, cleanup is performed by
calling wglMakeCurrent and wglDeleteContext before the application
terminates.
The Window Procedure
The application's simple window procedure processes only two messages:
WM_PAINT and WM_DESTROY. When a WM_PAINT message is received, the window
procedure calls the DrawHello function; it is in this function where OpenGL
drawing operations take place.
The first step in DrawHello is to select the rendering context as the
current context and set the viewport size by calling glViewport. The
viewport size was obtained by a call to the Win32 GetClientRect function.
Next, the frame buffer is erased, and an identity transformation matrix is
loaded.
The transformation matrix is changed by two subsequent rotations, specified
by calls to glRotated. The first call rotates the view around the vertical
axis. The second call tips the view forward by rotating it around the
horizontal axis. As a result, we will see the cube from a viewpoint
somewhat above and to the left of the cube.
The rotations are followed by calls that enable lighting mode and specify a
light source. The code specifies a single light source that illuminates the
cube from the left and above.
With all this initialization work complete, actual drawing can begin. A
series of six quadrilaterals is drawn, representing the six sides of the
cube. For each of the quadrilaterals, the normal vector is defined by a
separate call to glNormal3d. When the construction of the six primitives is
complete, a call to glFlush is used to ensure that all OpenGL operations
are complete, and then the device context is released and the function
returns.
Compiling and Running the Application
This application can be compiled simply from the command line. I called the
source file cube.c; to compile this file, type the following:
cl cube.c user32.lib gdi32.lib opengl32.lib
Note that applications that use the GLU Library or the GLAUX Library must
also specify glaux.lib or glu32.lib on the command line. And because OpenGL
is computation-intensive, it might be a useful idea to compile with the
appropriate optimization flags set.
The application should display a window with a three-dimensional image of a
cube rendered in it, similar to that shown in Figure 41.2.
Figure 41.2. Running the cube.exe Windows application.
OpenGL in MFC Applications
The OpenGL Library can easily be utilized from MFC applications as well. To
enable the OpenGL libraries, add the appropriate library names to your
project settings (Figure 41.3).
Figure 41.3. Adding the OpenGL libraries to MFC project settings.
When initializing the OpenGL Library in an MFC application, it is important
to remember which window you wish to use for a rendering context. For
example, if it is a view window that will serve as the rendering context,
it is this window that should be used when the OpenGL rendering context is
created.
OpenGL initialization
The MFC OpenGL application I created is based on an AppWizard-generated
single document interface application skeleton.
In this application, we draw a cube identical to the cube drawn in the C
application discussed earlier. The cube is drawn into the application's
view window. Accordingly, the first task after creating the application's
skeleton is to modify the view class's PreCreateWindow member function, to
ensure that the view window is created with the appropriate flags.
The modified version of this function is shown in Listing 41.2.
Listing 41.2. Modified version of CCubeView::PreCreateWindow.
BOOL CCUBEView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
return CView::PreCreateWindow(cs);
}
As you can see, the change to this function is simple; it consists only of
adding the WS_CLIPSIBLINGS and WS_CLIPCHILDREN flags to the window style to
ensure proper operation of the OpenGL libraries.
Much more extensive initialization work is performed in the view class's
OnCreate member function. This member function must be added using
ClassWizard or the WizardBar, as a handler function for WM_CREATE messages.
The implementation of this function, shown in Listing 41.3, creates a
rendering context after setting a pixel format for the view window's device
context.
Listing 41.3. Implementation of CCubeView::OnCreate.
int CCUBEView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
PIXELFORMATDESCRIPTOR pfd;
int iPixelFormat;
CDC *pDC;
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
pDC = GetDC();
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.cDepthBits = 16;
iPixelFormat = ChoosePixelFormat(pDC->m_hDC, &pfd);
SetPixelFormat(pDC->m_hDC, iPixelFormat, &pfd);
m_hglrc = wglCreateContext(pDC->m_hDC);
ReleaseDC(pDC);
return 0;
}
The rendering context handle is stored in the member variable m_hglrc. This
member variable should be added to the declaration of the view class in the
Attributes section, as follows:
class CCUBEView : public CView
{
...
// Attributes
public:
CCUBEDoc* GetDocument();
HGLRC m_hglrc;
...
Drawing the Cube
The actual drawing of the cube is performed in the OnDraw member function
of the view class. This member function, shown in Listing 41.4, is very
similar to the DrawHello function of the C application presented earlier in
this chapter. After making the rendering context current, the function
performs a series of initializations, including setting the size of the
viewport, applying coordinate transformations, and setting up lighting.
Afterwards, four quadrilaterals that together comprise the cube are drawn.
Listing 41.4. Implementation of CCubeView::OnDraw.
void CCUBEView::OnDraw(CDC* pDC)
{
CRect clientRect;
GLfloat lightPos[4] = {-1.0F, 2.0F, 0.2F, 0.0F};
CCUBEDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
GetClientRect(&clientRect);
wglMakeCurrent(pDC->m_hDC, m_hglrc);
glViewport(0, 0, clientRect.right, clientRect.bottom);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
glColor4d(1.0, 1.0, 1.0, 1.0);
glRotated(30.0, 0.0, 1.0, 0.0);
glRotated(15.0, 1.0, 0.0, 0.0);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glBegin(GL_QUADS);
glNormal3d(0.0, -1.0, 0.0);
glVertex3d(0.5, -0.5, 0.5);
glVertex3d(-0.5, -0.5, 0.5);
glVertex3d(-0.5, -0.5, -0.5);
glVertex3d(0.5, -0.5, -0.5);
glNormal3d(0.0, 0.0, -1.0);
glVertex3d(-0.5, -0.5, -0.5);
glVertex3d(-0.5, 0.5, -0.5);
glVertex3d(0.5, 0.5, -0.5);
glVertex3d(0.5, -0.5, -0.5);
glNormal3d(1.0, 0.0, 0.0);
glVertex3d(0.5, -0.5, -0.5);
glVertex3d(0.5, 0.5, -0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(0.5, -0.5, 0.5);
glNormal3d(0.0, 0.0, 1.0);
glVertex3d(-0.5, -0.5, 0.5);
glVertex3d(-0.5, 0.5, 0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(0.5, -0.5, 0.5);
glNormal3d(-1.0, 0.0, 0.0);
glVertex3d(-0.5, -0.5, 0.5);
glVertex3d(-0.5, 0.5, 0.5);
glVertex3d(-0.5, 0.5, -0.5);
glVertex3d(-0.5, -0.5, -0.5);
glNormal3d(0.0, 1.0, 0.0);
glVertex3d(-0.5, 0.5, 0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(0.5, 0.5, -0.5);
glVertex3d(-0.5, 0.5, -0.5);
glEnd();
glFlush();
wglMakeCurrent(NULL, NULL);
}
Note that this implementation does not take into account the fact that the
MFC framework also calls the view class's OnDraw function when drawing into
a printer-device context. In its present state, attempts to use this
application for printing will fail.
Running the Application
To run the application, compile and execute it from the Build menu. The
application's window should appear similar to that shown in Figure 41.4.
Figure 41.4. Running the cube.exe MFC application.
Note that this application, as its non-MFC counterpart, includes no palette
initialization and may not work properly on systems configured with 16 or
256 colors.
Summary
OpenGL is a library of high-quality three-dimensional graphics and
rendering functions. The library's device- and platform-independence make
it a library of choice for developing portable graphical applications.
OpenGL drawings are constructed from primitives; primitives are simple
items such as lines or polygons, which in turn are composed of vertices.
The OpenGL Library assembles primitives from vertices while taking into
account a variety of settings, such as color, lighting, and texture.
Primitives are then processed in accordance with transformations, clipping
settings, and other parameters; at the end of the rasterization process is
pixel data deposited into a frame buffer.
The Windows implementation of the OpenGL Library consists of the core
library, utility functions (GLU), and auxiliary functions (GLAUX). The
auxiliary library can be used to easily create simple stand-alone OpenGL
applications, as it implements a message loop and a window procedure
internally. However, due to the simplicity of implementation, this library
should not be used in production applications.
Windows also provides a set of extension functions (WGL) that facilitate
the use of OpenGL functions in the context of the Windows GDI. Furthermore,
a set of new functions has been added to the Win32 API to support pixel
formats and OpenGL double buffering.
The main steps of creating a Windows OpenGL application are as follows:
1. Ensure that your window class is not created with the CS_PARENTDC
style. Ensure that your window is created with the styles
WM_CLIPCHILDREN and WM_CLIPSIBLINGS set.
2. Create an OpenGL rendering context; a good spot for doing so is in the
WM_CREATE handler function for the window that you intend to use with
OpenGL.
3. Add appropriate calls in your handler for WM_PAINT messages to draw
the OpenGL image.
4. Optionally, add a handler for WM_SIZE messages to reflect changes in
the viewport size. Use glViewport to set the viewport size.
If you plan to run your application on 256-color devices, add handling for
custom palettes.
--
¡ù À´Ô´:¡¤¹þ¶û±õ×϶¡ÏãÕ¾ bbs1.hit.edu.cn¡¤[FROM: crystal.bbs@bbs.net.]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
Ò³ÃæÖ´ÐÐʱ¼ä£º413.806ºÁÃë