Opengl背景介绍

  • Post author:
  • Post category:其他




Opengl

Opengl即Open graphic library开源图形库,然后他本身并非是一个函数库,而仅仅是一个接口规范,各家厂商由于并不愿意公开自己的源码,但是又有开发需求(游戏工作室要进行开发),所以依照这个规范进行设计,方便开发人员的调用。

作为开发人员,Opengl提供了一些命令,让我们调用这些命令就可以完成我们对应想要完成的操作。例如,使用这个命令,我们就可以画出一个光源,就可以设置颜色,但是具体的实现是由各个厂商设计完成的。

在使用Opengl前,还需要简单了解三个部分的知识,Cmake,GLFW库,以及GLAD库。



Cmake

cmake是一个开源的跨平台工具集合,通过cmake我们可以根据自己所在的平台,编译环境控制软件的编译过程。具体介绍可以看

cmake官网:https://cmake.org/

cmake指导手册:https://cmake.org/cmake/help/latest/module/FetchContent.html

这里我们只需要了解一个部分,我们下载下来的软件包,里面包含了一个CmakeList.txt文件,该文件告诉Cmake该如何构建这个软件包,例如我们“输入”这是VS平台,那他就会按照VS进行软件构建。可以简单的使用图形化界面操作。



GLFW

由于Opengl作为一个接口规范,肯定要在各个平台上有相同的作用效果,那么就不能涉及到图形化界面,用户输入输出这些交互处理部分,因为这些操作在不同平台,不同系统是不统一的,需要程序员自己在所在平台上编写交互命令。但是这无疑增加了负担,对于一般学习Opengl,又想要通过界面更好的观察运行效果,其实没有必要单独编写,使用GLFW库,就可以帮我们很好的解决这个问题。允许我们绑定Opengl上下文,进行窗口创建,处理用户的输入输出等。

GLFW下载地址:www.glfw.org/download.html

下载之后使用cmake进行特定平台的构建,就可以使用了。



GLAD

Opengl作为一个接口规范,具体的实现是由厂商编写保存在某个地方,这个函数的地址我们是不知道的。那么该如何调用我们需要的函数呢。使用函数指针的方法:

// define the function’s prototype
typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*);
// find the function and assign it to a function pointer
GL_GENBUFFERS glGenBuffers =
(GL_GENBUFFERS)wglGetProcAddress("glGenBuffers");
// function can now be called as normal
unsigned int buffer;
glGenBuffers(1, &buffer);

Windows平台提供了wglGetProcAddress(string name);通过传入我们想要调用的函数名字,就会返回该函数的地址,通过该函数指针就可以使用该函数功能。但是如果每一个函数都需要用以上代码调用的化,一行调用代码变为了三行,非常浪费时间。但是我们在编译期间不知道具体函数的地址的,GLAD就是解决这个问题,他会在编译期间得到所有的函数指针,我们就可以直接使用。在https://glad.dav1d.de/,可以根据我们需要的Opengl版本号和平台自动生成GLAD库,下载即可。

Glad的使用很简单:

if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}

这一步骤加载函数会根据你的Opengl版本号(在你生成的时候已经选择好了),加载所有支持的Opengl函数,以加载Opengl3.3版本的函数为例。

static void load_GL_VERSION_3_3(GLADloadproc load) {
	if(!GLAD_GL_VERSION_3_3) return;
	glad_glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)load("glBindFragDataLocationIndexed");
	glad_glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC)load("glGetFragDataIndex");
	glad_glGenSamplers = (PFNGLGENSAMPLERSPROC)load("glGenSamplers");
	glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC)load("glDeleteSamplers");
	glad_glIsSampler = (PFNGLISSAMPLERPROC)load("glIsSampler");
	glad_glBindSampler = (PFNGLBINDSAMPLERPROC)load("glBindSampler");
	glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC)load("glSamplerParameteri");
	glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC)load("glSamplerParameteriv");
	glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC)load("glSamplerParameterf");
	glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC)load("glSamplerParameterfv");
	glad_glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC)load("glSamplerParameterIiv");
	glad_glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC)load("glSamplerParameterIuiv");
	glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC)load("glGetSamplerParameteriv");
	glad_glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC)load("glGetSamplerParameterIiv");
	glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC)load("glGetSamplerParameterfv");
	glad_glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC)load("glGetSamplerParameterIuiv");
	glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC)load("glQueryCounter");
	glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC)load("glGetQueryObjecti64v");
	glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC)load("glGetQueryObjectui64v");
	glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)load("glVertexAttribDivisor");
	glad_glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC)load("glVertexAttribP1ui");
	glad_glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC)load("glVertexAttribP1uiv");
	glad_glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC)load("glVertexAttribP2ui");
	glad_glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC)load("glVertexAttribP2uiv");
	glad_glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC)load("glVertexAttribP3ui");
	glad_glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC)load("glVertexAttribP3uiv");
	glad_glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC)load("glVertexAttribP4ui");
	glad_glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC)load("glVertexAttribP4uiv");
	glad_glVertexP2ui = (PFNGLVERTEXP2UIPROC)load("glVertexP2ui");
	glad_glVertexP2uiv = (PFNGLVERTEXP2UIVPROC)load("glVertexP2uiv");
	glad_glVertexP3ui = (PFNGLVERTEXP3UIPROC)load("glVertexP3ui");
	glad_glVertexP3uiv = (PFNGLVERTEXP3UIVPROC)load("glVertexP3uiv");
	glad_glVertexP4ui = (PFNGLVERTEXP4UIPROC)load("glVertexP4ui");
	glad_glVertexP4uiv = (PFNGLVERTEXP4UIVPROC)load("glVertexP4uiv");
	glad_glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC)load("glTexCoordP1ui");
	glad_glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC)load("glTexCoordP1uiv");
	glad_glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC)load("glTexCoordP2ui");
	glad_glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC)load("glTexCoordP2uiv");
	glad_glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC)load("glTexCoordP3ui");
	glad_glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC)load("glTexCoordP3uiv");
	glad_glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC)load("glTexCoordP4ui");
	glad_glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC)load("glTexCoordP4uiv");
	glad_glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC)load("glMultiTexCoordP1ui");
	glad_glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC)load("glMultiTexCoordP1uiv");
	glad_glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC)load("glMultiTexCoordP2ui");
	glad_glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC)load("glMultiTexCoordP2uiv");
	glad_glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC)load("glMultiTexCoordP3ui");
	glad_glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC)load("glMultiTexCoordP3uiv");
	glad_glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC)load("glMultiTexCoordP4ui");
	glad_glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC)load("glMultiTexCoordP4uiv");
	glad_glNormalP3ui = (PFNGLNORMALP3UIPROC)load("glNormalP3ui");
	glad_glNormalP3uiv = (PFNGLNORMALP3UIVPROC)load("glNormalP3uiv");
	glad_glColorP3ui = (PFNGLCOLORP3UIPROC)load("glColorP3ui");
	glad_glColorP3uiv = (PFNGLCOLORP3UIVPROC)load("glColorP3uiv");
	glad_glColorP4ui = (PFNGLCOLORP4UIPROC)load("glColorP4ui");
	glad_glColorP4uiv = (PFNGLCOLORP4UIVPROC)load("glColorP4uiv");
	glad_glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC)load("glSecondaryColorP3ui");
	glad_glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC)load("glSecondaryColorP3uiv");
}

可以看到GLAD将所有的函数地址预先获得保存下来(保存格式为原本函数名加上glad_前缀)。但是使用的时候是直接按照原名称来使用的,例如我们会用glColorP4uiv,而不是glad_glColorP4uiv。这是为什么呢,看glad.h可以发现,他做了非常多的宏定义:

#define glNormal3s glad_glNormal3s

所以我们使用的函数其实已经是glad的宏定义常量,本质上值还是加上了glad前缀。这样就可以在程序中直接使用我们想用的函数,而不需要繁琐的绑定了。



版权声明:本文为stevenjhjh原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。