OpenGL实例教程02:使用GLEW绘制点
什么是GLEW?
GLEW(OpenGL Extension Wrangler Library)是一个跨平台的开源C/C++扩展加载库。GLEW提供了高效的运行时机制,用于确定目标平台支持哪些OpenGL扩展。OpenGL核心和扩展功能声明在同一个头文件中。GLEW已经在多种操作系统上进行了测试,包括Windows、Linux、Mac OS X、FreeBSD、Irix和Solaris。
简单来说,GLEW就是在运行时(动态的),帮助我们将头文件中声明的函数指针,绑定到显卡驱动上的具体内存地址,也就时具体的opengl函数实现。
和glad有什么不同?
本教程采用freegult、glew分别实现窗口和绘制,另一套教程我们采用的是glfw和glad。使用起来大同小异。不必纠结这些细节,在QT中编写OpenGL我们甚至不需要使用这些,对我们来说都是透明的。库的选择和使用本来就是为了让我们更专心于实际业务,还是集中精力在OpenGL本身上。
GLEW编译
可以下载源码进行编译,或是直接下载编译好的运行库(windows)。
更过详细介绍可以参阅官网:https://glew.sourceforge.net/
代码展示:
前面我们已经使用freegult创建了支持OpenGL的窗口,有了GLEW的帮助我们就可以很方便的使用OpenGL函数在窗口上进行绘制了。
#include <stdio.h>//C风格的打印
#include "../include/glew-2.1.0/glew.h"//为了初始化OpenGL核心库和扩展库函数
//必须加载到其他OpenGL头文件的上面
#include "../include/freeglut3.4/freeglut.h"
#include "../include/ogldev_math_3d.h"//数学库
GLuint VBO;//unsigned int;句柄; vertex buffer object(顶点缓冲对象)
//VBO是将顶点加载到GPU最有效的方法。
static void RenderSceneCB()
{
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(0); //激活索引0表示的顶点属性,默认开启
glBindBuffer(GL_ARRAY_BUFFER, VBO);//再次绑定,在本例中多余,但是个好习惯
/*这个调用告诉管道如何解释缓冲区内的数据。
参数1:指定顶点属性的索引。
参数2:属性中的元素的数量(X、Y和Z)。
参数3:属性中的元素的类型
参数4:是否需要标准化(映射到-1到1之间)
参数5:属性之间的步长,目前只有一种属性且连续存放所以可以用0表示
参数6:属性的偏移量(第几个属性,从0开始),目前只有一种属性所以为0*/
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0/*sizeof(int)*3*/, 0);
glDrawArrays(GL_POINTS, 0, 1);//这就是GPU真正开始工作的地方。
//按照当前的所有状态,解析参数,并绘制出来
//glDrawArrays表示按顶点顺序绘制
//本例:从第0个数据开始,拿出一个,绘制点形状
glDrawArrays(GL_POINTS, 1, 1);//从第1个数据开始,拿出一个,绘制点形状
glDisableVertexAttribArray(0);
glutSwapBuffers();
}
static void InitializeGlutCallbacks()
{
glutDisplayFunc(RenderSceneCB);//注册回调函数
}
static void CreateVertexBuffer()//tutorial2新增
{
Vector3f Vertices[2]; //创建一个顶点数组
Vertices[0] = Vector3f(-0.5f, 0.0f, 0.0f);//也就是在屏幕中间左边的一个点
Vertices[1] = Vector3f(0.5f, 0.0f, 0.0f); //也就是在屏幕中间右边的一个点
glGenBuffers(1, &VBO);//创建1个缓冲,使用VBO作为ID(或句柄)
//注意:这时候我们并没有明确该缓冲是用来干什么的
glBindBuffer(GL_ARRAY_BUFFER, VBO);//将GL_ARRAY_BUFFER的状态绑定到VBO
//注意:在这里明确了VBO这块缓冲的用途
/*现在开始填充数据
参数1:目标名称,这里是我们刚刚绑定的目标
参数2:填充的数据大小(单位:字节)
参数3:数据地址
参数4:指示此数据的使用模式的标志,GL_STATIC_DRAW表示我们不打算改变缓冲区内容。
驱动程序可以依据它进行优化(例如内存中存储缓冲区的最佳位置)。*/
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(1024, 768);
glutInitWindowPosition(100, 100);
glutCreateWindow("Tutorial 02");
InitializeGlutCallbacks();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLenum res = glewInit();//初始化GLEW,必须在GLUT初始化之后。
if (res != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return 1;
}
CreateVertexBuffer();
glutMainLoop();
return 0;
}
显示效果:
一共绘制两个小点,分别是(-0.5,0,0)和(0.5,0,0),默认只是一个像素太小(下图中用红色圆圈标出),看不大清楚,以后我们将可以在shader中设置点的大小。
