OpenGL4.0学习3.1--初始化OpenGL 4.0

本教程将是使用OpenGL 4.0的第一个真正的介绍。我们将解决三个主要问题,分别是初始化OpenGL 4.0,关闭它以及使用它进行基本渲染。本教程使用与上一教程相同的类,不同之处在于,我们将为每个类添加更多代码,以利于使用OpenGL 4.0进行渲染。

我们将通过查看填写好的OpenGLClass来开始本教程:

Openglclass

头文件中,OpenGL 4.0要求您在opengl32.lib库中进行链接。您可以在IDE中或直接在代码中执行此操作。我已将链接放入代码中,因为这是我的偏爱:
#pragma comment(lib,“ opengl32.lib”)

OpenGL 4.0还需要windows.h和gl.h头文件。我还包括了math.h,因为我们将需要编写一些数学函数来协助使用OpenGL进行渲染。

首先开始填充OpenGLClass来开始本教程:

OpenGL 4.0要求您在opengl32.lib库中进行链接。您可以在IDE中或直接在代码中执行此操作。我已将链接放入代码中,因为这是我的偏爱。

/
//链接//
/
#pragma comment(lib,“ opengl32.lib”)

如果找不到这些文件,就查看一下包含路径是否可靠:
在这里插入图片描述
我用的vs2019.

//
//包含//
//
#include <windows.h>
#include <gl \ gl.h>
#include <math.h>

在Windows中,gl.h标头仅包含OpenGL 1.0和OpenGL 1.1的定义,函数和函数指针。实际上,所有新的OpenGL功能都以扩展名的形式在您的显卡的显示驱动程序中实现。您可以在OpenGL 4.0文档中找到Khronos Group在其网站上维护的OpenGL 4.0规范中所有扩展的名称。您还可以下载wglext.h和glext.h之类的文件,其中也包含大量文件。对于这些教程,我们只需要所有函数的子集,因此我包括了将在此头文件中使用的定义,类型定义和函数指针。

以下是我们将使用的定义:


/
// 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

//
// 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);

OpenGLClass的类定义在此保持尽可能简单。它具有常规构造函数,复制构造函数和析构函数。然后更重要的是它具有InitializeExtensions,InitializeOpenGL和Shutdown函数。这将是我们在本教程中重点关注的内容。除此之外,我还有许多对本教程并不重要的帮助函数,以及许多私有成员变量,当我们检查openglclass.cpp文件时,它们会被查看。目前,我们只需要了解初始化和关闭功能即可。


// 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;
//以下三个OpenGL函数指针用于与Windows接口:
	PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
	PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
	PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;

	float m_worldMatrix[16];
	float m_projectionMatrix[16];
	char m_videoCardDescription[128];

	//这些是用于与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

Openglclass.cpp

我们首先将两个成员句柄初始化为null。

OpenGLClass :: OpenGLClass()
{
   
	m_deviceContext = 0;
	m_renderingContext = 0;
}

InitializeExtensions函数使我们能够获取视频卡驱动程序中可用的所有OpenGL函数的指针。请注意,除非已经创建了一个窗口,否则无法调用此函数,因此SystemClass :: InitializeWindows函数中创建临时窗口,调用此函数以获取扩展,然后销毁该临时窗口并创建一个新窗口的原因。

在此函数中,我们将设置临时设备上下文,像素格式和渲染上下文,以便我们可以调用LoadExtensionList函数,该函数然后为我们获取所需的所有函数指针。完成后,我们将释放临时上下文。

//获取显卡驱动程序中可用的所有的OpenGL函数的指针。前提是已经创建了一个窗口
//一般在InitializeWindows函数中创建临时窗口,调用此函数以获取扩展,然后销毁临时窗口并创建一个新窗口
//InitializeExtensions函数:设置临时设备上下文,像素格式和渲染上下文,
bool OpenGLClass::InitializeExtensions(HWND hwnd)
{
   
	HDC deviceContext;
	PIXELFORMATDESCRIPTOR pixelFormat;
	int error;
	HGLRC renderContext;
	bool result;


	// 获取此窗口的设备上下文
	deviceContext = GetDC(hwnd);
	if (!deviceContext)
	{
   
		return false;
	}

	// 设置临时的默认像素格式
	error = SetPixelFormat(deviceContext, 1, &pixelFormat);
	if (error != 1)
	{
   
		return false;
	}

	// 创建一个临时渲染上下文
	renderContext = wglCreateContext(deviceContext);
	if (!renderContext)
	{
   
		return false;
	}

	// 将临时渲染上下文设置为此窗口的当前渲染上下文
	error = wglMakeCurrent(deviceContext, renderContext);
	if (error != 1)
	{
   
		return false;
	}

	// 初始化此应用程序所需的OpenGL扩展。注意,需要一个临时的渲染上下文
	result = LoadExtensionList();
	if (!result)
	{
   
		return false;
	}

	// 既然已经加载了扩展,就释放临时渲染上下文
	wglMakeCurrent(NULL, NULL);
	wglDeleteContext(renderContext);
	renderContext = NULL;

	// 释放该窗口的设备上下文。
	ReleaseDC(hwnd, deviceContext);
	deviceContext = 0;

	return true;
}

InitializeOpenGL设置OpenGL 4.0。在调用此函数之前,必须从InitializeExtensions函数加载扩展。同样,需要创建正确的窗口,这是在SystemClass :: InitializeWindows中完成的。一旦这两件事到位,就可以调用此函数。

然后,此函数将创建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;


	//获取此窗口的设备上下文。
	m_deviceContext = GetDC(hwnd);
	if (!m_deviceContext)
	{
   
		return false;
	}

	// 支持OpenGL渲染。
	attributeListInt[0] = WGL_SUPPORT_OPENGL_ARB;
	attributeListInt[1] = TRUE;

	// 支持渲染到窗口。
	attributeListInt[2] =
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值