写在前面
最近对OpenGL编程又双叒产生了浓厚的兴趣,决定把学习OpenGL过程中学到的知识都整理到博客中来,一来方便日后查看,而来也是为了和诸位大佬共勉。有不当的地方还望诸位批评指正,谢谢。
本系列博客将使用freeglut3.0.0和glew2.1.0和vs2017,在win10平台上开发。
包含glew
包含glew和包含freeglut一样,在属性里包含include文件和lib库,此处不再多说。此外,需要在项目右键->属性->链接器->输入->附加依赖项中添加glew32.lib:
绘制顶点
下面这段代码会在窗口中央绘制5个排在一行的顶点,需要注意的是(0,0,0)会被绘制到窗口中央:
// OpenGL3.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <GL\glew.h>
#include <GL\freeglut.h>
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
GLfloat vertex[] = { 0.0, 0.0, 0.0,
0.05, 0.0, 0.0,
0.1, 0.0, 0.0,
0.15, 0.0, 0.0,
0.2, 0.0, 0.0,
0.25, 0.0, 0.0,
};
void init()
{
glClearColor(1, 1, 1, 0.0);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT,GL_FALSE, 0, vertex);
glDrawArrays(GL_POINTS, 0, 5);
glDisableVertexAttribArray(0);
glFlush();
}
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(0, 0);
glutInitWindowSize(400, 300);
glutCreateWindow("顶点");
init();
glutDisplayFunc(display);
GLuint result = glewInit();
if (result != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(result));
return 1;
}
glutMainLoop();
return 0;
}
效果如下:
代码详解
在OpenGL中,所有模型都可以看成是由若干个顶点构成,每个顶点有自己的空间坐标、颜色坐标、法线坐标等。所以绘制图形可以通过绘制顶点来完成。我们可以通过glVertex*()制定单个顶点,但在绘制多个顶点时,使用顶点数据数组要快得多,也要方便得多。使用定点数组要经过如下流程:
此处我们使用glew来进行顶点数组操作。首先在main函数中初始化glew:
GLuint result = glewInit();
if (result != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(result));
return 1;
}
glewInit()会返回一个标识码用来判断初始化是否成功。如果失败,可以用glewGetErrorString(GLenum error)获取标识码对应的错误信息,用fprintf()将错误信息写入文件。
之后,启用顶点数组:
glEnableVertexAttribArray(GLuint index);
OpenGL支持多个顶点数组,index表示顶点数组对应的下标。
之后制定顶点数组数据和解引用格式:
glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer)
- index:顶点数组下标。
- size:顶点维度,比如二维、三维、四维,只能是2、3、4。
- type:顶点数据类型,比如整数、浮点数等。
- normalized:是否对顶点进行单位化。
- stride:跨距,指两个顶点数据之间隔着多少个byte。比如我们在一个顶点数组中既保存了位置坐标(x, y, z),也保存了颜色坐标(r, g, b):GLfloat vertex[] = {x1, y1,z1, r1, g1, b1, x2, y2, z2, c2, r2, g2, b2},这种情况下跨距指x1与x2之间的间隔,也就是sizeof(x1) * 6。
- pointer:顶点数据数组,保存着顶点数据。
接着解引用顶点数组:
glDrawArrays(GLenum mode, GLint first, GLsizei count);
- mode:解引用模式,即最后生成图形的模式,有顶点、点化线、线段、多边形等。
- first:数组中要被绘制的第一个元素,我们可以选择从数组中第一个元素开始绘制,也可以选择以后的元素作为开始解引用的首元素。
- count:要绘制的顶点个数。
当我们不用顶点数组时,可以选择关闭它:
glDisableVertexAttribArray(GLuint index)
index表示顶点数组下标。
结语
请了解本系列下一篇博文:OpenGL入门(四)顶点缓冲区