OpenGL 4.0 Tutorials 第三章:初始化 OpenGL 4.0

原文地址:

 

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: OpenGLClassclass 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: SystemClassclass 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: GraphicsClassclass 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/432256.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

客户机和服务器在s7通信中各有什么作用,哪些通信口可以进行 Modbus TCP 通讯,作为 Modbus 服务器的 SIMATIC S7 CPU 可以...

以下通信端口可用于 Modbus/TCP 协议&#xff1a;在默认情况下&#xff0c;端口号 502 作为 Modbus 服务器的本地端口。可以在 Modbus 客户机中设置需要的本地端口&#xff0c;通常使用从 2000 开始的端口号。如果通信伙伴具有为服务器设置端口号的功能&#xff0c;那么也可以使…

移位操作符

移位操作符操作运算对象是 位(bit) 它处理的数据类型只能是 整数类型(int) 先大概看一下图,了解它是怎么移动的,下面会解释规则 移位的时候关注两点, 1.移动的方向 2.空缺位置的填补形式. "有符号"左移位操作符(<<) 将二进制数据左移(在低位补0). int i 124…

【OpenGL】详解第一个OpenGL程序

写在前面 OpenGL能做的事情太多了&#xff01;很多程序也看起来很复杂。很多人感觉OpenGL晦涩难懂&#xff0c;原因大多是被OpenGL里面各种语句搞得头大&#xff0c;一会gen一下&#xff0c;一会bind一下&#xff0c;一会又active一下。搞到最后都不知道自己在干嘛&#xff0c;…

基于 Editor.js 开发富文本编辑器库

开始 Editor.js 提供了简单而直观的用户界面&#xff0c;根据需求可以灵活添加自定义的编辑工具&#xff0c;通过插件扩展功能 Editorjs 使用 js 开发&#xff0c;脱离框架依赖&#xff0c;因此可以基于它封装富文本编辑器&#xff0c;用于 Vue 和 React 项目 editor-js-com…

dell服务器从硬盘引导,就是折腾 篇三:戴尔H710 mini(D1版本)阵列卡刷直通模式 附硬盘引导和还原IR模式办法...

就是折腾 篇三&#xff1a;戴尔H710 mini(D1版本)阵列卡刷直通模式 附硬盘引导和还原IR模式办法2021-07-24 10:00:201点赞13收藏12评论首先断开电池&#xff0c;确保阵列卡牢牢插入主板&#xff0c;没有松动。否则可能像我一样启动后识别不了raid卡。经实际测试&#xff0c;机器…

(转)你的团队需要一个领袖,而不是一个主管

作为这个社会的一员&#xff0c;你有你自己想要追随的领袖&#xff0c;他们是一种超人的存在&#xff0c;在各自的领域出类拔萃&#xff0c;拥有强大的人格力量。你不由自主的追随着精神领袖 Steve Jobs、王阳明、默罕默德&#xff1b;音乐领袖崔健、Bruce Springsteen、Michae…

硬件服务器采购指南,硬件组装_服务器采购指南_太平洋电脑网PConline

这个机箱不支持普通大光驱&#xff0c;要用超薄光驱&#xff0c;超薄光驱是不可以直接用IDE数据线连接&#xff0c;必须用一个很小光驱转接卡&#xff0c;当然电源接口是和软驱电源接口通用的。光驱转接板这次我们采用的电源&#xff0c;也比较突出。电源是一个不能马虎的东西&…

ExecuteScalar

ExecuteScalar运行查询&#xff0c;并返回查询所返回的结果集中第一行的第一列或空引用&#xff08;假设结果集为空).忽略其它列或行. 使用 ExecuteScalar 方法从数据库中检索单个值。 由于不用创建行集、查找值并关闭行集&#xff0c;所以产生的系统开销很小与使用 ExecuteRea…

计算机启动软件,计算机软件及应用启动会-20210703001237.pptx-原创力文档

晨操劲舞;业绩播报;昨天--今天--明天;昨天;遇到的困惑;有时我们感觉辛苦、累&#xff01;;入行的初衷;1、为了收入2、为了改变环境与现状3、为了找个事情做4、为了锻炼自己5、为了生存&#xff01; 试一试 ……;忆往昔&#xff0c;峥嵘岁月稠……;今 天;;先往 三只锅里倒入一些…

文件夹没有安全选项-文件上传下载-路径访问被拒绝

在文件的下载和上传中&#xff0c;有时候会出现“路径。。。访问被拒绝”&#xff0c;这是由于权限问题引起&#xff0c;只要给文件所在的文件夹设置权限为everyone就可以解决了&#xff0c;但是有时候文件夹属性没有“安全”选项卡&#xff0c;解决方法如下&#xff1a; 第一种…

css3 背景等比例,纯 CSS,不用背景,实现图片等比例展示

最简单的等比例&#xff1a;div img { max-width:100%; max-height:100%; }如上显示效果是&#xff1a;图片等比例缩放&#xff0c;不变形&#xff1b;图片所有区域都会显示。但是&#xff0c;如上代码有可能会造成横向、纵向白边&#xff0c;当我们在做图片列表时&#xff0c;…

emctl start dbconsole OC4J_dbconsole*** not found

C:\windows\system32>emctl start dbconsole OC4J Configuration issue. D:\app\product\11.1.0\db_1/oc4j/j2ee/OC4J_DBConsole_ghost1_orcl not found. 查看监听状态&#xff0c;环境变量 C:\windows\system32>echo %ORACLE_HOME% D:\app\product\11.1.0\db_1C:\window…

360剑灵洪门崛起服务器维护,剑灵洪门崛起————【维护】8月1日更新维护公告...

亲爱的玩家&#xff1a;大家好&#xff01;为了更新游戏内容&#xff0c;提升游戏体验&#xff0c;7k7k《剑灵洪门崛起》将于8月1日7:00-8:00对所有服务器进行更新维护&#xff0c;维护期间无法登陆游戏&#xff0c;维护时间预计1小时。如果在维护期间无法完成维护相关事宜&…

高德地图 android 调用 amap.clear()后定位蓝点消失 如何重新显示定位

您好&#xff01;AMap.clear()方法&#xff0c;将地图上全部的覆盖物都清除&#xff0c;包括定位的小蓝点。如果不想清除定位的图标&#xff0c;有两种方法&#xff1a;方法一&#xff1a;将自定以的marker存好&#xff0c;清除时&#xff0c;调用marker.remove()方法&#xff…

易票365显示连接服务器失败,易票365服务器地址参数

易票365服务器地址参数 内容精选换一换查看指定VPC通道的弹性云服务器列表。您可以在API Explorer中调试该接口。GET /v2/{project_id}/apic/instances/{instance_id}/vpc-channels/{vpc_channel_id}/members状态码&#xff1a; 200状态码&#xff1a; 400状态码&#xff1a; 4…

语言统计学中的几个定律,可作为设计检索的参考

30定律&#xff1a;出现频率最高的30个词占全文本总词数的30&#xff05;如果剔除150个最高频率的词&#xff08;由于df过大被认为是停用词&#xff09;&#xff1a;倒排表记录总个数会减少25&#xff0d;30&#xff05;Zipf定律&#xff1a; 在自然语料库中所有term的freq&…

so打包进APK

问题描述我本身有个现成的SO文件&#xff0c;想通过编译方式打包进APK里&#xff0c;不知道该怎么做&#xff1f; 解决方案1libs/armeabi/是在项目根目录中&#xff0c;应该可以 解决方案2大哥&#xff0c;so放到lib目录中&#xff0c;打包时&#xff0c;会自动编入APK&#xf…

保存hbitmap到文件

void SaveBitmapToFile(HBITMAP hBitmap, char* szfilename) {HDC hdc; //设备描述表int ibits;WORD wbitcount; //当前显示分辨率下每个像素所占字节数//位图中每个像素所占字节数&#xff0c;定义调色板大小&#xff0c;位图中像素字节大小&#xff0c;位图文件大小 &a…

linux rz批量上传

rz -be 转载于:https://www.cnblogs.com/hh6plus/p/5548082.html

Linux makefile 教程 很具体,且易懂

近期在学习Linux下的C编程&#xff0c;买了一本叫《Linux环境下的C编程指南》读到makefile就越看越迷糊&#xff0c;可能是我的理解能不行。 于是google到了下面这篇文章。通俗易懂。然后把它贴出来&#xff0c;方便学习。 后记&#xff0c;看完发现这篇文章和《Linux环境下的C…