写在前面
最近对OpenGL编程又双叒产生了浓厚的兴趣,决定把学习OpenGL过程中学到的知识都整理到博客中来,一来方便日后查看,而来也是为了和诸位大佬共勉。有不当的地方还望诸位批评指正,谢谢。
本系列博客将使用freeglut3.0.0和glew2.1.0和vs2017,在win10平台上开发。
配置freeglut
之前我们编译好了freeglut,在创建项目后需要引入。右键项目->属性->VC++目录,在右边窗口的包含目录中引入include下的文件(当前为F:\OpenGL\freeglut3.0.0\include),库目录中引入lib文件(当前为F:\OpenGL\freeglut3.0.0\lib),点击确定就可以了。
创建第一个窗口
先来段代码压压惊:
#include "stdafx.h"
#include <freeglut.h>
void init()
{
glClearColor(0.0,0.0,0.0,0.0);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glutSolidSphere(1.0, 50, 6);
glFlush();
}
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowSize(600, 600);
glutInitWindowPosition(0, 0);
glutCreateWindow("第一个窗口");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
这段代码用来绘制一个白色的球体(但由于没有任何视角变换,我们看到的只是一个圆,这一点后面再说)。
点击调试,会报一条错:
错误 LNK1104 无法打开文件“freeglutd.lib” OpenGL2 E : \Visual Studio\OpenGL2\OpenGL2\LINK 1
因为之前的freeglut是release版本的,所以我们需要对预处理器进行定义,在属性->C/C++->与处理器->预处理器定义里加上一行NDEBUG:
或者选择解决方案配置为Release,再点调试,OK,具体效果如下:
这样,一个圆就画出来了,虽然是一个丑的要死的圆哈哈哈。
代码详解
接下来我们分析下代码:
首先,毋庸置疑,这段代码入口是main函数。他收到控制台的一系列参数放在argv中。这儿就会有同学困惑,我们不是建立了窗口吗,怎么又和丑丑的控制台建立了联系呢?可以这样理解,我们是通过控制台来建立窗口的。所以在窗口建立之前会先弹出一个控制台。怎么办呢?只需要在包含头文件之后加一行代码:
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
这样就可以了。
接着来看main函数里面的方法:
glutInit(&argc, argv);
这段代码表示对glut进行初始化,并处理控制台参数。
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
指定显示模式,如果要指定多个,需要用按位或符号“|”隔开。此处可以选择:
/*
* GLUT API macro definitions -- the display mode definitions
*/
#define GLUT_RGB 0x0000
#define GLUT_RGBA 0x0000
#define GLUT_INDEX 0x0001
#define GLUT_SINGLE 0x0000
#define GLUT_DOUBLE 0x0002
#define GLUT_ACCUM 0x0004
#define GLUT_ALPHA 0x0008
#define GLUT_DEPTH 0x0010
#define GLUT_STENCIL 0x0020
#define GLUT_MULTISAMPLE 0x0080
#define GLUT_STEREO 0x0100
#define GLUT_LUMINANCE 0x0200
这里我们用到了GLUT_RGBA,表示RGBA而非颜色索引,还有GLUT_SINGLE表示使用单缓冲而非双缓冲,具体的区别和用处到后面我们再说。
glutInitWindowSize(600, 600);
设定窗口的宽度和高度,以像素为单位。
glutInitWindowPosition(0, 0);
指定窗口左上角的位置。(0, 0)表示左上角。
glutCreateWindow("第一个窗口");
生成窗口,参数为窗口title,并返回一个int值用来标识改窗口。
init();
自定义方法,在窗口创建之后调用且在应用程序生命周期中只调用一次,用于自定义初始化。
glutDisplayFunc(display);
指定渲染回调函数,在每帧渲染时都会调用display函数。
glutMainLoop();
表示启动循环,所有创建的窗口会在这时显示,事件循环开始启动,渲染回调函数触发,渲染开始并进入循环。
再看display()方法,当开始渲染后opengl就会每隔固定时间(每帧)调用display()方法进行实时渲染:
glClear(GL_COLOR_BUFFER_BIT);
清除颜色缓冲区。颜色缓冲区存储着屏幕上每个像素对应的颜色。在init()中我们调用glClearColor()设定清除色为黑色,所以每次调用glClear(GL_COLOR_BUFFER_BIT)都会把颜色缓冲区全部设置为黑色。
glClear()还可以清除其他缓冲区,具体用到时我们再说。
glColor3f(1.0, 1.0, 1.0);
设置画笔颜色。在这里我们使用白色,也就是说接下来绘制的点、线、多边形都会设置为白色。
glutSolidSphere(1.0, 50, 6);
绘制一个球体,半径为1。以地球为例,以地轴为z轴,50表示要绘制的经线条数,6表示要绘制的纬线条数。这两个变量值越大,会出来的图形越像球形,如果越小会看到一个有棱角的球体。
glFlush();