原文地址:
http://www.rastertek.com/gl40tut03.html
Tutorial 3: Initializing OpenGL 4.0
第三章:初始化 OpenGL 4.0
This tutorial will be the first real introduction to working with OpenGL 4.0. We will address three main things which are initializing OpenGL 4.0, shutting it down, and basic rendering with it. This tutorial uses the same classes as the previous tutorial except that we will be adding more code to each to facilitate rendering with OpenGL 4.0.
这一章将正式介绍 OpenGL 4.0。我们将涉及3个部分,初始化 OpenGL 4.0、关闭、渲染。我们将在前面教程的基础上添加 OpenGL 4.0 渲染。
We will start the tutorial by looking at the filled out OpenGLClass:
本章从填充OpenGLClass开始:
Openglclass.h
// Filename: openglclass.h
#ifndef _OPENGLCLASS_H_
#define _OPENGLCLASS_H_
OpenGL 4.0 requires that you link in the opengl32.lib library. You can do this in the IDE or directly in the code. I have put the linking in the code as this is my preference.
OpenGL 4.0 需要链接opengl32.lib库文件。可以通过设置IDE或下面的代码来实现。原作者使用了他喜欢的代码方式。
/
// LINKING //
/
#pragma comment(lib, "opengl32.lib")
OpenGL 4.0 also requires the windows.h and gl.h header files. I have also included math.h since we will need to write some math functions to assist in rendering with OpenGL.
OpenGL 4.0 需要包含windows.h和gl.h头文件。这里也包含了math.h头文件以便实现一些数学方法来辅助OpenGL渲染。
//
// INCLUDES //
//
#include <windows.h>
#include <gl\gl.h>
#include <math.h>
In Windows the gl.h header only contains the defines, functions, and function pointers for OpenGL 1.0 and OpenGL 1.1. All newer OpenGL functionality is actually implemented in the display driver for your video card in the form of extensions. You can find the names of all the extensions in the OpenGL 4.0 spec that the Khronos Group maintains on their website in the OpenGL 4.0 documentation. You can also download files such as wglext.h and glext.h which contain a large number of them as well. For these tutorials we only need a subset of all the functions so I have included the defines, typedefs, and function pointers that we will use in this header file.
在Windows系统中gl.h头文件只包含了OpenGL 1.0 和 OpenGL 1.1 版本的定义、方法。全部的新的OpenGL实现都以扩展的方式实现在显示设备驱动里。你可以在Khronos组织提供的OpenGL 4.0 在线文档里查找全部OpenGL 4.0 扩展的名称。你也可以下载包含了大量扩展的wglext.h和glext.h文件。本教程只用到了部分扩展,所以我在下面的头文件里对它们进行了定义。
The following are the defines that we will be using:
下面是我们将要用到的定义:
/
// DEFINES //
/
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
#define WGL_ACCELERATION_ARB 0x2003
#define WGL_SWAP_METHOD_ARB 0x2007
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_PIXEL_TYPE_ARB 0x2013
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_FULL_ACCELERATION_ARB 0x2027
#define WGL_SWAP_EXCHANGE_ARB 0x2028
#define WGL_TYPE_RGBA_ARB 0x202B
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define GL_ARRAY_BUFFER 0x8892
#define GL_STATIC_DRAW 0x88E4
#define GL_FRAGMENT_SHADER 0x8B30
#define GL_VERTEX_SHADER 0x8B31
#define GL_COMPILE_STATUS 0x8B81
#define GL_LINK_STATUS 0x8B82
#define GL_INFO_LOG_LENGTH 0x8B84
#define GL_TEXTURE0 0x84C0
#define GL_BGRA 0x80E1
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
The following are the typedefs that we need to access the OpenGL 4.0 functionality:
下面是我们将在OpenGL 4.0 方法中使用的类型定义。
//
// TYPEDEFS //
//
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats,
int *piFormats, UINT *nNumFormats);
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
typedef void (APIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
typedef void (APIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRY * PFNGLBINDVERTEXARRAYPROC) (GLuint array);
typedef void (APIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, ptrdiff_t size, const GLvoid *data, GLenum usage);
typedef void (APIENTRY * PFNGLCOMPILESHADERPROC) (GLuint shader);
typedef GLuint (APIENTRY * PFNGLCREATEPROGRAMPROC) (void);
typedef GLuint (APIENTRY * PFNGLCREATESHADERPROC) (GLenum type);
typedef void (APIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program);
typedef void (APIENTRY * PFNGLDELETESHADERPROC) (GLuint shader);
typedef void (APIENTRY * PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
typedef void (APIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
typedef void (APIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
typedef void (APIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRY * PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
typedef GLint (APIENTRY * PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const char *name);
typedef void (APIENTRY * PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, char *infoLog);
typedef void (APIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
typedef void (APIENTRY * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, char *infoLog);
typedef void (APIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
typedef void (APIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program);
typedef void (APIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const char* *string, const GLint *length);
typedef void (APIENTRY * PFNGLUSEPROGRAMPROC) (GLuint program);
typedef void (APIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
const GLvoid *pointer);
typedef void (APIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const char *name);
typedef GLint (APIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const char *name);
typedef void (APIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
typedef void (APIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture);
typedef void (APIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
typedef void (APIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target);
typedef void (APIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
typedef void (APIENTRY * PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
typedef void (APIENTRY * PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
The class definition for the OpenGLClass is kept as simple as possible here. It has the regular constructor, copy constructor, and destructor. Then more importantly it has the InitializeExtensions, InitializeOpenGL, and Shutdown function. This will be what we are mainly focused on in this tutorial. Other than that I have a number of helper functions which aren't important to this tutorial and a number of private member variables that will be looked at when we examine the openglclass.cpp file. For now just realize the initialization and shutdown functions are what concern us.
OpenGLClass的定义尽量保持简洁。它包含规范的构造和析构函数。更重要的是它实现了InitializeExtensions、InitializeOpenGL、Shutdown方法。这是本章的重点。同时,类中也包含了一些不太重要的辅助方法和一些私有变量。目前我们只实现了初始化和关闭方法。
// Class name: OpenGLClass
class OpenGLClass
{
public:
OpenGLClass();
OpenGLClass(const OpenGLClass&);
~OpenGLClass();
bool InitializeExtensions(HWND);
bool InitializeOpenGL(HWND, int, int, float, float, bool);
void Shutdown(HWND);
void BeginScene(float, float, float, float);
void EndScene();
void GetWorldMatrix(float*);
void GetProjectionMatrix(float*);
void GetVideoCardInfo(char*);
void BuildIdentityMatrix(float*);
void BuildPerspectiveFovLHMatrix(float*, float, float, float, float);
void MatrixRotationY(float*, float);
void MatrixTranslation(float*, float, float, float);
void MatrixMultiply(float*, float*, float*);
private:
bool LoadExtensionList();
private:
HDC m_deviceContext;
HGLRC m_renderingContext;
The following three OpenGL function pointers are used for interfacing with windows:
下面3个窗口接口用的OpenGL函数指针:
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
float m_worldMatrix[16];
float m_projectionMatrix[16];
char m_videoCardDescription[128];
These are the remainder of the function pointers that will be used for interfacing with OpenGL. I have made them public so we can call them easily using just a pointer to this class:
余下的是OpenGL接口函数指针。为了方便调用,在此定义为公有的:
public:
PFNGLATTACHSHADERPROC glAttachShader;
PFNGLBINDBUFFERPROC glBindBuffer;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
PFNGLBUFFERDATAPROC glBufferData;
PFNGLCOMPILESHADERPROC glCompileShader;
PFNGLCREATEPROGRAMPROC glCreateProgram;
PFNGLCREATESHADERPROC glCreateShader;
PFNGLDELETEBUFFERSPROC glDeleteBuffers;
PFNGLDELETEPROGRAMPROC glDeleteProgram;
PFNGLDELETESHADERPROC glDeleteShader;
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
PFNGLDETACHSHADERPROC glDetachShader;
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
PFNGLGENBUFFERSPROC glGenBuffers;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
PFNGLGETPROGRAMIVPROC glGetProgramiv;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
PFNGLGETSHADERIVPROC glGetShaderiv;
PFNGLLINKPROGRAMPROC glLinkProgram;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLUSEPROGRAMPROC glUseProgram;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
PFNGLACTIVETEXTUREPROC glActiveTexture;
PFNGLUNIFORM1IPROC glUniform1i;
PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
PFNGLUNIFORM3FVPROC glUniform3fv;
PFNGLUNIFORM4FVPROC glUniform4fv;
};
#endif
For those familiar with OpenGL already you may notice I don't have a view matrix variable in this class. The reason being is that I will be putting it in a camera class that we will be looking at in future tutorials.
熟悉OpenGL的同学会发现这里没有定义视口矩阵。原因是我在后面的教程里将它放进摄像机类中。
Openglclass.cpp
// Filename: openglclass.cpp
#include "openglclass.h"
We begin by initializing the two member handles to null.
开始,将2个成员变量设置为null。
OpenGLClass::OpenGLClass()
{
m_deviceContext = 0;
m_renderingContext = 0;
}
OpenGLClass::OpenGLClass(const OpenGLClass& other)
{
}
OpenGLClass::~OpenGLClass()
{
}
The InitializeExtensions function is what allows us to get pointers to all the OpenGL functions that are available from the video card driver. Note that this function cannot be called unless there is a window already created, hence the reason in the SystemClass::InitializeWindows function for creating a temporary window, calling this function to get the extensions, and then destroying that temporary window and creating a new one.
InitializeExtensions方法允许我们从显卡驱动获取全部可用的OpenGL函数指针。注意,在窗口创建前不能调用此方法。这就是SystemClass::InitializeWindows方法创建临时窗口的原因,获取OpenGL扩展后销毁临时窗口,然后再新建一个窗口。
In this function we will setup a temporary device context, pixel format, and rendering context so that we can call the LoadExtensionList function which then gets us all the function pointers we need. Once that is complete we release the temporary contexts.
这个方法里我创建了一个临时设备上下文、像素格式和渲染上下文。然后我们可以通过调用LoadExtensionList方法获得我们需要的函数指针。最后释放他们。
bool OpenGLClass::InitializeExtensions(HWND hwnd)
{
HDC deviceContext;
PIXELFORMATDESCRIPTOR pixelFormat;
int error;
HGLRC renderContext;
bool result;
// Get the device context for this window.
// 获得窗口设备上下文。
deviceContext = GetDC(hwnd);
if(!deviceContext)
{
return false;
}
// Set a temporary default pixel format.
// 设置默认的临时像素格式。
error = SetPixelFormat(deviceContext, 1, &pixelFormat);
if(error != 1)
{
return false;
}
// Create a temporary rendering context.
// 创建临时渲染上下文。
renderContext = wglCreateContext(deviceContext);
if(!renderContext)
{
return false;
}
// Set the temporary rendering context as the current rendering context for this window.
// 为窗口设置临时渲染上下文。
error = wglMakeCurrent(deviceContext, renderContext);
if(error != 1)
{
return false;
}
// Initialize the OpenGL extensions needed for this application. Note that a temporary rendering context was needed to do so.
// 初始化程序需要的OpenGL扩展。
result = LoadExtensionList();
if(!result)
{
return false;
}
// Release the temporary rendering context now that the extensions have been loaded.
// 释放临时渲染上下文,现在扩展已经被加载。
wglMakeCurrent(NULL, NULL);
wglDeleteContext(renderContext);
renderContext = NULL;
// Release the device context for this window.
// 释放窗口设备上下文。
ReleaseDC(hwnd, deviceContext);
deviceContext = 0;
return true;
}
InitializeOpenGL sets up OpenGL 4.0. Before this function is called the extensions must be loaded from the InitializeExtensions function. Also and the correct window needs to be created which is done in the SystemClass::InitializeWindows. Once those two things are in place this function can then be called.
InitializeOpenGL方法设置OpenGL 4.0。扩展必须要在InitializeExtensions方法加载和SystemClass::InitializeWindows方法创建了正确的窗口后才能在此方法中调用。
This function then creates an OpenGL 4.0 rendering context and appropriate pixel format. Once that is in place this function then sets up some extra things such as back face culling, vertical sync, depth buffer, and some matrices that we will need for rendering.
然后此方法创建OpenGL 4.0渲染上下文和适当的像素格式。完成后,此方法将完成渲染需要的背面剔除、垂直同步、深度缓冲和矩阵变换等操作。
bool OpenGLClass::InitializeOpenGL(HWND hwnd, int screenWidth, int screenHeight, float screenDepth, float screenNear, bool vsync)
{
int attributeListInt[19];
int pixelFormat[1];
unsigned int formatCount;
int result;
PIXELFORMATDESCRIPTOR pixelFormatDescriptor;
int attributeList[5];
float fieldOfView, screenAspect;
char *vendorString, *rendererString;
// Get the device context for this window.
m_deviceContext = GetDC(hwnd);
if(!m_deviceContext)
{
return false;
}
// Support for OpenGL rendering.
attributeListInt[0] = WGL_SUPPORT_OPENGL_ARB;
attributeListInt[1] = TRUE;
// Support for rendering to a window.
attributeListInt[2] = WGL_DRAW_TO_WINDOW_ARB;
attributeListInt[3] = TRUE;
// Support for hardware acceleration.
attributeListInt[4] = WGL_ACCELERATION_ARB;
attributeListInt[5] = WGL_FULL_ACCELERATION_ARB;
// Support for 24bit color.
attributeListInt[6] = WGL_COLOR_BITS_ARB;
attributeListInt[7] = 24;
// Support for 24 bit depth buffer.
attributeListInt[8] = WGL_DEPTH_BITS_ARB;
attributeListInt[9] = 24;
// Support for double buffer.
attributeListInt[10] = WGL_DOUBLE_BUFFER_ARB;
attributeListInt[11] = TRUE;
// Support for swapping front and back buffer.
attributeListInt[12] = WGL_SWAP_METHOD_ARB;
attributeListInt[13] = WGL_SWAP_EXCHANGE_ARB;
// Support for the RGBA pixel type.
attributeListInt[14] = WGL_PIXEL_TYPE_ARB;
attributeListInt[15] = WGL_TYPE_RGBA_ARB;
// Support for a 8 bit stencil buffer.
attributeListInt[16] = WGL_STENCIL_BITS_ARB;
attributeListInt[17] = 8;
// Null terminate the attribute list.
attributeListInt[18] = 0;
// Query for a pixel format that fits the attributes we want.
result = wglChoosePixelFormatARB(m_deviceContext, attributeListInt, NULL, 1, pixelFormat, &formatCount);
if(result != 1)
{
return false;
}
// If the video card/display can handle our desired pixel format then we set it as the current one.
result = SetPixelFormat(m_deviceContext, pixelFormat[0], &pixelFormatDescriptor);
if(result != 1)
{
return false;
}
// Set the 4.0 version of OpenGL in the attribute list.
attributeList[0] = WGL_CONTEXT_MAJOR_VERSION_ARB;
attributeList[1] = 4;
attributeList[2] = WGL_CONTEXT_MINOR_VERSION_ARB;
attributeList[3] = 0;
// Null terminate the attribute list.
attributeList[4] = 0;
// Create a OpenGL 4.0 rendering context.
m_renderingContext = wglCreateContextAttribsARB(m_deviceContext, 0, attributeList);
if(m_renderingContext == NULL)
{
return false;
}
// Set the rendering context to active.
result = wglMakeCurrent(m_deviceContext, m_renderingContext);
if(result != 1)
{
return false;
}
// Set the depth buffer to be entirely cleared to 1.0 values.
glClearDepth(1.0f);
// Enable depth testing.
glEnable(GL_DEPTH_TEST);
// Set the polygon winding to front facing for the left handed system.
glFrontFace(GL_CW);
// Enable back face culling.
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// Initialize the world/model matrix to the identity matrix.
BuildIdentityMatrix(m_worldMatrix);
// Set the field of view and screen aspect ratio.
fieldOfView = 3.14159265358979323846f / 4.0f;
screenAspect = (float)screenWidth / (float)screenHeight;
// Build the perspective projection matrix.
BuildPerspectiveFovLHMatrix(m_projectionMatrix, fieldOfView, screenAspect, screenNear, screenDepth);
// Get the name of the video card.
vendorString = (char*)glGetString(GL_VENDOR);
rendererString = (char*)glGetString(GL_RENDERER);
// Store the video card name in a class member variable so it can be retrieved later.
strcpy_s(m_videoCardDescription, vendorString);
strcat_s(m_videoCardDescription, " - ");
strcat_s(m_videoCardDescription, rendererString);
// Turn on or off the vertical sync depending on the input bool value.
if(vsync)
{
result = wglSwapIntervalEXT(1);
}
else
{
result = wglSwapIntervalEXT(0);
}
// Check if vsync was set correctly.
if(result != 1)
{
return false;
}
return true;
}
The Shutdown function will release the two context handles that were used for rendering with OpenGL 4.0.
Shutdown方法用来释放OpenGL渲染用到的两个上下文句柄。
void OpenGLClass::Shutdown(HWND hwnd)
{
// Release the rendering context.
if(m_renderingContext)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(m_renderingContext);
m_renderingContext = 0;
}
// Release the device context.
if(m_deviceContext)
{
ReleaseDC(hwnd, m_deviceContext);
m_deviceContext = 0;
}
return;
}
The next two helper functions are named BeginScene and EndScene. BeginScene will be called whenever we are going to draw a new 3D scene at the beginning of each frame. All it does is initializes the buffers so they are blank and ready to be drawn to. The other function is Endscene, it swaps the back buffer to the front buffer which displays our 3D scene once all the drawing has completed at the end of each frame.
下面是两个辅助方法BeginScene和EndScene。BeginScene在每一帧开始绘制新的3D场景时被调用。EndScene在每一帧场景绘制完成后前后缓冲数据交换时被调用。
void OpenGLClass::BeginScene(float red, float green, float blue, float alpha)
{
// Set the color to clear the screen to.
glClearColor(red, green, blue, alpha);
// Clear the screen and depth buffer.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
return;
}
void OpenGLClass::EndScene()
{
// Present the back buffer to the screen since rendering is complete.
SwapBuffers(m_deviceContext);
return;
}
The LoadExtensionList function loads all the extensions we will be using for interfacing with OpenGL 4.0. Each function pointer gets the address to the function by calling the wglGetProcAddress function. If you wish to add even more OpenGL 4.0 support you can add your extra function pointer loading to this function.
LoadExtensionList方法加载了用来接口OpenGL 4.0的全部扩展。通过wglGetProcAddress 方法获取每个OpenGL方法指针。你也可以在此方法中添加其他的OpenGL 4.0支持的函数指针。
bool OpenGLClass::LoadExtensionList()
{
// Load the OpenGL extensions that this application will be using.
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
if(!wglChoosePixelFormatARB)
{
return false;
}
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
if(!wglCreateContextAttribsARB)
{
return false;
}
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
if(!wglSwapIntervalEXT)
{
return false;
}
glAttachShader = (PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
if(!glAttachShader)
{
return false;
}
glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
if(!glBindBuffer)
{
return false;
}
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)wglGetProcAddress("glBindVertexArray");
if(!glBindVertexArray)
{
return false;
}
glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
if(!glBufferData)
{
return false;
}
glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
if(!glCompileShader)
{
return false;
}
glCreateProgram = (PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram");
if(!glCreateProgram)
{
return false;
}
glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
if(!glCreateShader)
{
return false;
}
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers");
if(!glDeleteBuffers)
{
return false;
}
glDeleteProgram = (PFNGLDELETEPROGRAMPROC)wglGetProcAddress("glDeleteProgram");
if(!glDeleteProgram)
{
return false;
}
glDeleteShader = (PFNGLDELETESHADERPROC)wglGetProcAddress("glDeleteShader");
if(!glDeleteShader)
{
return false;
}
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)wglGetProcAddress("glDeleteVertexArrays");
if(!glDeleteVertexArrays)
{
return false;
}
glDetachShader = (PFNGLDETACHSHADERPROC)wglGetProcAddress("glDetachShader");
if(!glDetachShader)
{
return false;
}
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glEnableVertexAttribArray");
if(!glEnableVertexAttribArray)
{
return false;
}
glGenBuffers = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers");
if(!glGenBuffers)
{
return false;
}
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)wglGetProcAddress("glGenVertexArrays");
if(!glGenVertexArrays)
{
return false;
}
glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)wglGetProcAddress("glGetAttribLocation");
if(!glGetAttribLocation)
{
return false;
}
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)wglGetProcAddress("glGetProgramInfoLog");
if(!glGetProgramInfoLog)
{
return false;
}
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)wglGetProcAddress("glGetProgramiv");
if(!glGetProgramiv)
{
return false;
}
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog");
if(!glGetShaderInfoLog)
{
return false;
}
glGetShaderiv = (PFNGLGETSHADERIVPROC)wglGetProcAddress("glGetShaderiv");
if(!glGetShaderiv)
{
return false;
}
glLinkProgram = (PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram");
if(!glLinkProgram)
{
return false;
}
glShaderSource = (PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource");
if(!glShaderSource)
{
return false;
}
glUseProgram = (PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram");
if(!glUseProgram)
{
return false;
}
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer");
if(!glVertexAttribPointer)
{
return false;
}
glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)wglGetProcAddress("glBindAttribLocation");
if(!glBindAttribLocation)
{
return false;
}
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation");
if(!glGetUniformLocation)
{
return false;
}
glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)wglGetProcAddress("glUniformMatrix4fv");
if(!glUniformMatrix4fv)
{
return false;
}
glActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture");
if(!glActiveTexture)
{
return false;
}
glUniform1i = (PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i");
if(!glUniform1i)
{
return false;
}
glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)wglGetProcAddress("glGenerateMipmap");
if(!glGenerateMipmap)
{
return false;
}
glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glDisableVertexAttribArray");
if(!glDisableVertexAttribArray)
{
return false;
}
glUniform3fv = (PFNGLUNIFORM3FVPROC)wglGetProcAddress("glUniform3fv");
if(!glUniform3fv)
{
return false;
}
glUniform4fv = (PFNGLUNIFORM4FVPROC)wglGetProcAddress("glUniform4fv");
if(!glUniform4fv)
{
return false;
}
return true;
}
The following functions just return the matrices that this class has built to calling functions. These matrices are important to rendering.
下面几个方法用来处理本类用的矩阵。这些矩阵对渲染非常重要。
void OpenGLClass::GetWorldMatrix(float* matrix)
{
matrix[0] = m_worldMatrix[0];
matrix[1] = m_worldMatrix[1];
matrix[2] = m_worldMatrix[2];
matrix[3] = m_worldMatrix[3];
matrix[4] = m_worldMatrix[4];
matrix[5] = m_worldMatrix[5];
matrix[6] = m_worldMatrix[6];
matrix[7] = m_worldMatrix[7];
matrix[8] = m_worldMatrix[8];
matrix[9] = m_worldMatrix[9];
matrix[10] = m_worldMatrix[10];
matrix[11] = m_worldMatrix[11];
matrix[12] = m_worldMatrix[12];
matrix[13] = m_worldMatrix[13];
matrix[14] = m_worldMatrix[14];
matrix[15] = m_worldMatrix[15];
return;
}
void OpenGLClass::GetProjectionMatrix(float* matrix)
{
matrix[0] = m_projectionMatrix[0];
matrix[1] = m_projectionMatrix[1];
matrix[2] = m_projectionMatrix[2];
matrix[3] = m_projectionMatrix[3];
matrix[4] = m_projectionMatrix[4];
matrix[5] = m_projectionMatrix[5];
matrix[6] = m_projectionMatrix[6];
matrix[7] = m_projectionMatrix[7];
matrix[8] = m_projectionMatrix[8];
matrix[9] = m_projectionMatrix[9];
matrix[10] = m_projectionMatrix[10];
matrix[11] = m_projectionMatrix[11];
matrix[12] = m_projectionMatrix[12];
matrix[13] = m_projectionMatrix[13];
matrix[14] = m_projectionMatrix[14];
matrix[15] = m_projectionMatrix[15];
return;
}
The GetVideoCardInfo function returns the name and manufacturer of the video card in a string to the caller of this function.
GetVideoCardInfo 方法返回显卡的名字和生产厂商。
void OpenGLClass::GetVideoCardInfo(char* cardName)
{
strcpy_s(cardName, 128, m_videoCardDescription);
return;
}
This function builds a basic identity matrix.
下面方法构造基本单位矩阵。
void OpenGLClass::BuildIdentityMatrix(float* matrix)
{
matrix[0] = 1.0f;
matrix[1] = 0.0f;
matrix[2] = 0.0f;
matrix[3] = 0.0f;
matrix[4] = 0.0f;
matrix[5] = 1.0f;
matrix[6] = 0.0f;
matrix[7] = 0.0f;
matrix[8] = 0.0f;
matrix[9] = 0.0f;
matrix[10] = 1.0f;
matrix[11] = 0.0f;
matrix[12] = 0.0f;
matrix[13] = 0.0f;
matrix[14] = 0.0f;
matrix[15] = 1.0f;
return;
}
This function builds a left handed projection matrix.
下面方法构造基于左手坐标系的投影矩阵。
void OpenGLClass::BuildPerspectiveFovLHMatrix(float* matrix, float fieldOfView, float screenAspect, float screenNear, float screenDepth)
{
matrix[0] = 1.0f / (screenAspect * tan(fieldOfView * 0.5f));
matrix[1] = 0.0f;
matrix[2] = 0.0f;
matrix[3] = 0.0f;
matrix[4] = 0.0f;
matrix[5] = 1.0f / tan(fieldOfView * 0.5f);
matrix[6] = 0.0f;
matrix[7] = 0.0f;
matrix[8] = 0.0f;
matrix[9] = 0.0f;
matrix[10] = screenDepth / (screenDepth - screenNear);
matrix[11] = 1.0f;
matrix[12] = 0.0f;
matrix[13] = 0.0f;
matrix[14] = (-screenNear * screenDepth) / (screenDepth - screenNear);
matrix[15] = 0.0f;
return;
}
This function builds a rotation matrix based around the Y axis.
下面方法构造基于Y轴的旋转矩阵。
void OpenGLClass::MatrixRotationY(float* matrix, float angle)
{
matrix[0] = cosf(angle);
matrix[1] = 0.0f;
matrix[2] = -sinf(angle);
matrix[3] = 0.0f;
matrix[4] = 0.0f;
matrix[5] = 1.0f;
matrix[6] = 0.0f;
matrix[7] = 0.0f;
matrix[8] = sinf(angle);
matrix[9] = 0.0f;
matrix[10] = cosf(angle);
matrix[11] = 0.0f;
matrix[12] = 0.0f;
matrix[13] = 0.0f;
matrix[14] = 0.0f;
matrix[15] = 1.0f;
return;
}
This function builds a basic translation matrix.
下面方法构造了基本位移矩阵。
void OpenGLClass::MatrixTranslation(float* matrix, float x, float y, float z)
{
matrix[0] = 1.0f;
matrix[1] = 0.0f;
matrix[2] = 0.0f;
matrix[3] = 0.0f;
matrix[4] = 0.0f;
matrix[5] = 1.0f;
matrix[6] = 0.0f;
matrix[7] = 0.0f;
matrix[8] = 0.0f;
matrix[9] = 0.0f;
matrix[10] = 1.0f;
matrix[11] = 0.0f;
matrix[12] = x;
matrix[13] = y;
matrix[14] = z;
matrix[15] = 1.0f;
return;
}
This function multiplies two 4x4 matrices and returns the result.
下面方法返回两个4x4矩阵相乘的结果。
void OpenGLClass::MatrixMultiply(float* result, float* matrix1, float* matrix2)
{
result[0] = (matrix1[0] * matrix2[0]) + (matrix1[1] * matrix2[4]) + (matrix1[2] * matrix2[8]) + (matrix1[3] * matrix2[12]);
result[1] = (matrix1[0] * matrix2[1]) + (matrix1[1] * matrix2[5]) + (matrix1[2] * matrix2[9]) + (matrix1[3] * matrix2[13]);
result[2] = (matrix1[0] * matrix2[2]) + (matrix1[1] * matrix2[6]) + (matrix1[2] * matrix2[10]) + (matrix1[3] * matrix2[14]);
result[3] = (matrix1[0] * matrix2[3]) + (matrix1[1] * matrix2[7]) + (matrix1[2] * matrix2[11]) + (matrix1[3] * matrix2[15]);
result[4] = (matrix1[4] * matrix2[0]) + (matrix1[5] * matrix2[4]) + (matrix1[6] * matrix2[8]) + (matrix1[7] * matrix2[12]);
result[5] = (matrix1[4] * matrix2[1]) + (matrix1[5] * matrix2[5]) + (matrix1[6] * matrix2[9]) + (matrix1[7] * matrix2[13]);
result[6] = (matrix1[4] * matrix2[2]) + (matrix1[5] * matrix2[6]) + (matrix1[6] * matrix2[10]) + (matrix1[7] * matrix2[14]);
result[7] = (matrix1[4] * matrix2[3]) + (matrix1[5] * matrix2[7]) + (matrix1[6] * matrix2[11]) + (matrix1[7] * matrix2[15]);
result[8] = (matrix1[8] * matrix2[0]) + (matrix1[9] * matrix2[4]) + (matrix1[10] * matrix2[8]) + (matrix1[11] * matrix2[12]);
result[9] = (matrix1[8] * matrix2[1]) + (matrix1[9] * matrix2[5]) + (matrix1[10] * matrix2[9]) + (matrix1[11] * matrix2[13]);
result[10] = (matrix1[8] * matrix2[2]) + (matrix1[9] * matrix2[6]) + (matrix1[10] * matrix2[10]) + (matrix1[11] * matrix2[14]);
result[11] = (matrix1[8] * matrix2[3]) + (matrix1[9] * matrix2[7]) + (matrix1[10] * matrix2[11]) + (matrix1[11] * matrix2[15]);
result[12] = (matrix1[12] * matrix2[0]) + (matrix1[13] * matrix2[4]) + (matrix1[14] * matrix2[8]) + (matrix1[15] * matrix2[12]);
result[13] = (matrix1[12] * matrix2[1]) + (matrix1[13] * matrix2[5]) + (matrix1[14] * matrix2[9]) + (matrix1[15] * matrix2[13]);
result[14] = (matrix1[12] * matrix2[2]) + (matrix1[13] * matrix2[6]) + (matrix1[14] * matrix2[10]) + (matrix1[15] * matrix2[14]);
result[15] = (matrix1[12] * matrix2[3]) + (matrix1[13] * matrix2[7]) + (matrix1[14] * matrix2[11]) + (matrix1[15] * matrix2[15]);
return;
}
Systemclass.h
The SystemClass has been modified since the last tutorial to now include the OpenGL 4.0 initialization and shutdown. The header has not been modified but the source file has been.
SystemClass添加了OpenGL 4.0的初始化和关闭操作。
// Filename: systemclass.h
#ifndef _SYSTEMCLASS_H_
#define _SYSTEMCLASS_H_
///
// PRE-PROCESSING DIRECTIVES //
///
#define WIN32_LEAN_AND_MEAN
//
// INCLUDES //
//
#include <windows.h>
///
// MY CLASS INCLUDES //
///
#include "openglclass.h"
#include "inputclass.h"
#include "graphicsclass.h"
// Class name: SystemClass
class SystemClass
{
public:
SystemClass();
SystemClass(const SystemClass&);
~SystemClass();
bool Initialize();
void Shutdown();
void Run();
LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);
private:
bool Frame();
bool InitializeWindows(OpenGLClass*, int&, int&);
void ShutdownWindows();
private:
LPCWSTR m_applicationName;
HINSTANCE m_hinstance;
HWND m_hwnd;
OpenGLClass* m_OpenGL;
InputClass* m_Input;
GraphicsClass* m_Graphics;
};
/
// FUNCTION PROTOTYPES //
/
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
/
// GLOBALS //
/
static SystemClass* ApplicationHandle = 0;
#endif
Systemclass.cpp
// Filename: systemclass.cpp
#include "systemclass.h"
SystemClass::SystemClass()
{
m_OpenGL = 0;
m_Input = 0;
m_Graphics = 0;
}
SystemClass::SystemClass(const SystemClass& other)
{
}
SystemClass::~SystemClass()
{
}
bool SystemClass::Initialize()
{
int screenWidth, screenHeight;
bool result;
// Initialize the width and height of the screen to zero.
screenWidth = 0;
screenHeight = 0;
// Create the OpenGL object.
m_OpenGL = new OpenGLClass;
if(!m_OpenGL)
{
return false;
}
// Create the window the application will be using and also initialize OpenGL.
result = InitializeWindows(m_OpenGL, screenWidth, screenHeight);
if(!result)
{
MessageBox(m_hwnd, L"Could not initialize the window.", L"Error", MB_OK);
return false;
}
// Create the input object. This object will be used to handle reading the input from the user.
m_Input = new InputClass;
if(!m_Input)
{
return false;
}
// Initialize the input object.
m_Input->Initialize();
// Create the graphics object. This object will handle rendering all the graphics for this application.
m_Graphics = new GraphicsClass;
if(!m_Graphics)
{
return false;
}
// Initialize the graphics object.
result = m_Graphics->Initialize(m_OpenGL, m_hwnd);
if(!result)
{
return false;
}
return true;
}
void SystemClass::Shutdown()
{
// Release the graphics object.
if(m_Graphics)
{
m_Graphics->Shutdown();
delete m_Graphics;
m_Graphics = 0;
}
// Release the input object.
if(m_Input)
{
delete m_Input;
m_Input = 0;
}
We now call the shutdown function for the OpenGL object.
这里调用OpenGL对象的关闭方法。
// Release the OpenGL object.
if(m_OpenGL)
{
m_OpenGL->Shutdown(m_hwnd);
delete m_OpenGL;
m_OpenGL = 0;
}
// Shutdown the window.
ShutdownWindows();
return;
}
void SystemClass::Run()
{
MSG msg;
bool done, result;
// Initialize the message structure.
ZeroMemory(&msg, sizeof(MSG));
// Loop until there is a quit message from the window or the user.
done = false;
while(!done)
{
// Handle the windows messages.
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// If windows signals to end the application then exit out.
if(msg.message == WM_QUIT)
{
done = true;
}
else
{
// Otherwise do the frame processing.
result = Frame();
if(!result)
{
done = true;
}
}
}
return;
}
bool SystemClass::Frame()
{
bool result;
// Check if the user pressed escape and wants to exit the application.
if(m_Input->IsKeyDown(VK_ESCAPE))
{
return false;
}
// Do the frame processing for the graphics object.
result = m_Graphics->Frame();
if(!result)
{
return false;
}
return true;
}
LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
switch(umsg)
{
// Check if a key has been pressed on the keyboard.
case WM_KEYDOWN:
{
// If a key is pressed send it to the input object so it can record that state.
m_Input->KeyDown((unsigned int)wparam);
return 0;
}
// Check if a key has been released on the keyboard.
case WM_KEYUP:
{
// If a key is released then send it to the input object so it can unset the state for that key.
m_Input->KeyUp((unsigned int)wparam);
return 0;
}
// Any other messages send to the default message handler as our application won't make use of them.
default:
{
return DefWindowProc(hwnd, umsg, wparam, lparam);
}
}
}
bool SystemClass::InitializeWindows(OpenGLClass* OpenGL, int& screenWidth, int& screenHeight)
{
WNDCLASSEX wc;
DEVMODE dmScreenSettings;
int posX, posY;
bool result;
// Get an external pointer to this object.
ApplicationHandle = this;
// Get the instance of this application.
m_hinstance = GetModuleHandle(NULL);
// Give the application a name.
m_applicationName = L"Engine";
// Setup the windows class with default settings.
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = m_hinstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hIconSm = wc.hIcon;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = m_applicationName;
wc.cbSize = sizeof(WNDCLASSEX);
// Register the window class.
RegisterClassEx(&wc);
// Create a temporary window for the OpenGL extension setup.
m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName, WS_POPUP,
0, 0, 640, 480, NULL, NULL, m_hinstance, NULL);
if(m_hwnd == NULL)
{
return false;
}
// Don't show the window.
ShowWindow(m_hwnd, SW_HIDE);
We now load the extensions using the OpenGL object.
// Initialize a temporary OpenGL window and load the OpenGL extensions.
result = OpenGL->InitializeExtensions(m_hwnd);
if(!result)
{
MessageBox(m_hwnd, L"Could not initialize the OpenGL extensions.", L"Error", MB_OK);
return false;
}
// Release the temporary window now that the extensions have been initialized.
DestroyWindow(m_hwnd);
m_hwnd = NULL;
// Determine the resolution of the clients desktop screen.
screenWidth = GetSystemMetrics(SM_CXSCREEN);
screenHeight = GetSystemMetrics(SM_CYSCREEN);
// Setup the screen settings depending on whether it is running in full screen or in windowed mode.
if(FULL_SCREEN)
{
// If full screen set the screen to maximum size of the users desktop and 32bit.
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
// Change the display settings to full screen.
ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
// Set the position of the window to the top left corner.
posX = posY = 0;
}
else
{
// If windowed then set it to 800x600 resolution.
screenWidth = 800;
screenHeight = 600;
// Place the window in the middle of the screen.
posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth) / 2;
posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2;
}
// Create the window with the screen settings and get the handle to it.
m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName, WS_POPUP,
posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);
if(m_hwnd == NULL)
{
return false;
}
With the extensions in place we can now properly initialize an OpenGL 4.0 rendering context.
使用扩展初始化OpenGL 4.0渲染上下文。
// Initialize OpenGL now that the window has been created.
result = m_OpenGL->InitializeOpenGL(m_hwnd, screenWidth, screenHeight, SCREEN_DEPTH, SCREEN_NEAR, VSYNC_ENABLED);
if(!result)
{
MessageBox(m_hwnd, L"Could not initialize OpenGL, check if video card supports OpenGL 4.0.", L"Error", MB_OK);
return false;
}
// Bring the window up on the screen and set it as main focus.
ShowWindow(m_hwnd, SW_SHOW);
SetForegroundWindow(m_hwnd);
SetFocus(m_hwnd);
// Hide the mouse cursor.
ShowCursor(false);
return true;
}
void SystemClass::ShutdownWindows()
{
// Show the mouse cursor.
ShowCursor(true);
// Fix the display settings if leaving full screen mode.
if(FULL_SCREEN)
{
ChangeDisplaySettings(NULL, 0);
}
// Remove the window.
DestroyWindow(m_hwnd);
m_hwnd = NULL;
// Remove the application instance.
UnregisterClass(m_applicationName, m_hinstance);
m_hinstance = NULL;
// Release the pointer to this class.
ApplicationHandle = NULL;
return;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
switch(umessage)
{
// Check if the window is being closed.
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
// All other messages pass to the message handler in the system class.
default:
{
return ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
}
}
}
Graphicsclass.h
For this tutorial we have now also filled out the GraphicsClass so that it can perform some basic OpenGL rendering.
本章我们为GraphicsClass添加基本的OpenGL渲染。
// Filename: graphicsclass.h
#ifndef _GRAPHICSCLASS_H_
#define _GRAPHICSCLASS_H_
///
// MY CLASS INCLUDES //
///
#include "openglclass.h"
/
// GLOBALS //
/
const bool FULL_SCREEN = false;
const bool VSYNC_ENABLED = true;
const float SCREEN_DEPTH = 1000.0f;
const float SCREEN_NEAR = 0.1f;
// Class name: GraphicsClass
class GraphicsClass
{
public:
GraphicsClass();
GraphicsClass(const GraphicsClass&);
~GraphicsClass();
bool Initialize(OpenGLClass*, HWND);
void Shutdown();
bool Frame();
private:
bool Render();
private:
We now have an OpenGL class object.
OpenGLClass* m_OpenGL;
};
#endif
Graphicsclass.cpp
From the previous tutorial this class was entirely empty with no code in it at all. Now that we have a OpenGLClass member we will start to fill out some code inside the GraphicsClass to initialize and shutdown the OpenGLClass object. We will also add calls to BeginScene and EndScene in the Render function so that we are now drawing to the window using OpenGL.
本类在前面的教程没有任何代码。现在,我们有一个OpenGLClass成员,我们可以添加代码来初始化和关闭OpenGLClass对象。为了让OpenGL绘制窗口,在Render方法里我们添加了BeginScene和EndScene方法调用。
// Filename: graphicsclass.cpp
#include "graphicsclass.h"
So the very first change is in the class constructor. Here we initialize the OpenGLClass object pointer to null for safety reasons as we do with all class pointers.
此类的构造函数发生了变化。为了安全,在构造函数里将OpenGLClass对象指针设置为null。
GraphicsClass::GraphicsClass()
{
m_OpenGL = 0;
}
GraphicsClass::GraphicsClass(const GraphicsClass& other)
{
}
GraphicsClass::~GraphicsClass()
{
}
The second change is in the Initialize function inside the GraphicsClass Here we send in a pointer to the OpenGLClass object so that the GraphicsClass can make OpenGL system calls just using a single pointer.
在GraphicsClass的初始化方法里传入OpenGLClass对象指针,这样GraphicsClass使用同一个指针操作OpenGL系统。
bool GraphicsClass::Initialize(OpenGLClass* OpenGL, HWND hwnd)
{
// Store a pointer to the OpenGL class object.
m_OpenGL = OpenGL;
return true;
}
The next change is in the Shutdown function in the GraphicsClass. Here we release the pointer to the OpenGLClass object during shut down.
在Shutdown方法里释放OpenGLClass对象指针。
void GraphicsClass::Shutdown()
{
// Release the pointer to the OpenGL class object.
m_OpenGL = 0;
return;
}
The Frame function has been updated so that it now calls the Render function each frame.
Frame方法每一帧都调用Render方法。
bool GraphicsClass::Frame()
{
bool result;
// Render the graphics scene.
result = Render();
if(!result)
{
return false;
}
return true;
}
The final change to this class is in the Render function. We call the OpenGL object to clear the screen to a grey color. After that we call EndScene so that the grey color is presented to the window.
Render方法里,我们使用OpenGL对象清楚屏幕为灰色。然后调用EndScene将灰色显示到窗口中。
bool GraphicsClass::Render()
{
// Clear the buffers to begin the scene.
m_OpenGL->BeginScene(0.5f, 0.5f, 0.5f, 1.0f);
// Present the rendered scene to the screen.
m_OpenGL->EndScene();
return true;
}
Summary
总结
Now we are finally able to initialize and shut down OpenGL 4.0. Compiling and running the code will produce the same window as the last tutorial but OpenGL is initialized now and clear the window to grey for us. Compiling and running the code will also show if your video card driver can properly get all the OpenGL 4.0 extensions that we will be using.
本章讲述了初始化和关闭OpenGL 4.0的内容。编译并运行代码,将看到被OpenGL清理为灰色的窗口。同时也能知道你的显卡释放支持我们用到的OpenGL 4.0的扩展。
To Do Exercises
练习
1. Re-compile the code and run the program to ensure OpenGL works. Press the escape key to quit after the window displays.
1. 重新编译并运行代码确保OpenGL可以正常工作,窗口显示后按下ESC键退出。
2. Change the global in graphicsclass.h to full screen and re-compile/run.
2. 修改graphicsclass.h中全部变量的值为全屏,然后重新编译并运行。
3. Change the clear color in GraphicsClass::Render to yellow.
3. 修改GraphicsClass::Render方法里清除颜色为黄色。
4. Write the video card name out to a text file.
4. 将显卡名称输出到文本文件。
Source Code
源代码
http://www.rastertek.com/gl40src03.zip
Openglclass.cpp