一、OpenGL简介
OpenGL(全写Open Graphics Library)是指定义了一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口。它用于三维图像(二维的亦可),是一个功能强大,调用方便的底层图形库。
OpenGL是个与硬件无关的软件接口,可以在不同的平台如Windows 95、Windows NT、Unix、Linux、MacOS、OS/2之间进行移植。因此,支持OpenGL的软件具有很好的移植性,可以获得非常广泛的应用。由于OpenGL是图形的底层图形库,没有提供几何实体图元,不能直接用以描述场景。但是,通过一些转换程序,可以很方便地将AutoCAD、3DS/3DSMAX等3D图形设计软件制作的DXF和3DS模型文件转换成OpenGL的顶点数组。
OpenGL中的大多数函数使用了一种基于状态的方法,大多数OpenGL对象都需要在使用前把该对象绑定到Context上。可把OpenGL对象理解成一个状态的集合,他负责管理他下属的所有状态。除了状态,OpenGL对象还会存储其他数据。只有在把一个OpenGL对象绑定到context上时,OpenGL对象的各种状态才会映射到context的状态。 OpenGL就是一个“状态机”。各种各样的API调用会改变这些状态,或者根据这些状态进行操作。
二、OpenGL配置和安装
1.配置glut(OpenGL Utility Tookit),为了使OpenGL应用程序结构能够真正独立于窗口系统的库。
glut下载地址:https://www.opengl.org/resources/libraries/glut/ (翻越大高墙)
可在此方便下载:
解压后得到文件:
(1)将glut.h放置在VC目录include下,即 【Microsoft Visual Studio安装路径\VC\include】,例如我的路径为:D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include
(2)将glut32.lib和glut.lib放置在VC目录lib下,即 【Microsoft Visual Studio安装路径\VC\lib】
(3)将glut.dll和glut32.dll这两个动态库文件放到操作系统目录下面的C:\Windows\system32文件夹内(32位系统)或C:\Windows\SysWOW64(64位系统)。为了兼容性考虑,最好在这两个目录下都复制相应的文件。
配置完成后,可运行测试代码:
#include
#include
#include
#include
static int year = 0, spin = 0, day = 0;
static GLint fogMode;
const int n = 100;
const GLfloat R = 1.0f;
const GLfloat Pi = 3.1415926536f;
void DrawCircle() {
int i;
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINE_LOOP);
for (i = 0; i < n; ++i)
{
glColor3f(1.0, 0.0, 0.0);
glVertex2f(R*cos(2 * Pi / n*i), R*sin(2 * Pi / n*i));
}
glEnd();
glFlush();
}
void init(void) {
GLfloat position[] = { 0.5, 0.5, 3.0, 0.0 };
glEnable(GL_DEPTH_TEST); //防止遮挡
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
{
GLfloat mat[3] = { 0.1745, 0.01175, 0.01175 };
glMaterialfv(GL_FRONT, GL_AMBIENT, mat);
mat[0] = 0.61424; mat[1] = 0.04136; mat[2] = 0.04136;
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat);
mat[0] = 0.727811; mat[1] = 0.626959; mat[2] = 0.626959;
glMaterialfv(GL_FRONT, GL_SPECULAR, mat);
glMaterialf(GL_FRONT, GL_SHININESS, 0.6*128.0);
}
glEnable(GL_FOG);
{
GLfloat fogColor[4] = { 0.5, 0.5, 0.5, 1.0 };
fogMode = GL_EXP;
glFogi(GL_FOG_MODE, fogMode);
glFogfv(GL_FOG_COLOR, fogColor);
glFogf(GL_FOG_DENSITY, 0.35);
glHint(GL_FOG_HINT, GL_DONT_CARE);
glFogf(GL_FOG_START, 1.0);
glFogf(GL_FOG_END, 5.0);
}
glClearColor(0.5, 0.9, 0.9, 1.0); /* fog color */
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.0, 1.0, 1.0);
glPushMatrix(); //记住自己的位置
glutSolidSphere(1.0, 20, 16); /* 画太阳半径、 20经度、16纬度*/
glRotatef(spin, 0.0, 1.0, 0.0); //自转,绕着一个向量以给定角度旋转(正的为逆时针)
glTranslatef(2.0, 1.0, 0.0);
glRotatef(spin, 1.0, 0.0, 0.0); //公转
glRectf(0.1, 0.1, 0.5, 0.5);
glColor3f(0.0, 0.0, 1.0);
glutWireSphere(0.2, 8, 8); /* 画第一颗小行星 */
glColor3f(1.0, 0.0, 0.0);
glTranslatef(2.0, 1.0, 0.0);
glRotatef(2 * spin, 0.0, 1.0, 0.0);
glutSolidSphere(0.5, 16, 8);
glPopMatrix();//回到原来的位置
glutSwapBuffers();
}
void spinDisplay(void) {
spin = spin + 2;
if (spin > 360)
spin = spin - 360;
glutPostRedisplay();
}
void mouse(int button, int state, int x, int y) {
switch (button)
{
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN)
glutIdleFunc(spinDisplay);
break;
case GLUT_MIDDLE_BUTTON:
if (state == GLUT_DOWN)
glutIdleFunc(NULL);
break;
default:
break;
}
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 0.5, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 10.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case 'd':
day = (day + 10) % 360;
glutPostRedisplay();
break;
case 'D':
day = (day - 10) % 360;
glutPostRedisplay();
break;
case 'y':
year = (year + 5) % 360;
glutPostRedisplay();
break;
case 'Y':
year = (year - 5) % 360;
glutPostRedisplay();
break;
case 27:
exit(0);
break;
default:
break;
}
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(400, 400);
glutInitWindowPosition(100, 100);
glutCreateWindow("OpengGL 程序设计");
init();
//glutDisplayFunc(DrawCircle);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
//glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMainLoop();
return 0;
}
2.配置GLEW
Windows(微软旗下产品)目前只支持OpenGL1.1的函数(DirectX),要使用OpenGL的高级特性,就必须下载最新的扩展GLEW,此为一个跨平台的C++扩展库,基于OpenGL图形接口。
下载地址:http://glew.sourceforge.net/
在此可方便下载:
最好是下载红框框中的Binaries,否则还需要手动编译。
加压缩后,文件目录如下:
配置过程:
(1)\bin\Release\Win32下glew32.dll放到操作系统目录下面的C:\Windows\system32文件夹内(32位系统)或C:\Windows\SysWOW64(64位系统)。
(2)\include下GL文件夹放置在VC目录include下,即 【Microsoft Visual Studio安装路径\VC\include】
(3) \lib\Release\Win32放置在VC目录lib下,即 【Microsoft Visual Studio安装路径\VC\lib】
(4)在链接器->输入->附加依赖项,添加glew32.lib
测试代码:
#include "GL/glew.h"
#include "glut.h"
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0); //窗口颜色(红:[0.0~1.0]R, 绿:[0.0~1.0]G,蓝:[0.0~1.0]B, 透明度:[0.0~1.0]A)
/*使用正投影将世界坐标系二位矩形区域的内容映射到屏幕上,区域的x坐标值从0.0到200.0,y坐标值从0.0到150.0*/
glMatrixMode(GL_PROGRAM);
gluOrtho2D(0.0, 200.0, 0.0, 150.0);
}
void lineSegment(void)
{
glClear(GL_COLOR_BUFFER_BIT);//GL_COLOR_BUFFER_BIT是一个OpenGL符号常量,用来指定它的颜色缓存(刷新缓存)中的位值,该缓存将使用 glClearColor函数中指定的值来设定。
glColor3f(1.0f, 0.0f, 0.0f);//设置线段颜色为红色
/*定义了一个从整数笛卡尔端点坐标(180,15)到(10, 145)的二维直线段*/
glBegin(GL_LINES);
glVertex2i(180, 15);
glVertex2i(10, 145);
glEnd();
glFlush(); //执行所有的OpenGL程序
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);//初始化GULT
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//设置显示模式
glutInitWindowPosition(50, 100);//设置左上角窗口显示位置
glutInitWindowSize(400, 300);//设置窗口显示的宽与高
glutCreateWindow("An Example OpenGL Program!");//创建一个窗口
init();//执行初始化程序
glutDisplayFunc(lineSegment);//把图形显示在窗口
glutMainLoop();//显示所有并进入等待状态
}
3.配置glfw
下载地址:http://www.glfw.org/download.html
配置:
将include中的GLFW文件夹拷贝到VS安装目录下的VC/include中
若使用VS2013,则将lib-vc2013中的lib文件拷贝到VS2013安装目录下的VC/lib中
然后将lib-vc2013中的dll文件拷贝到system32或system64中
写程序时,在工程的属性->链接器->输入->附加依赖项中添加glfw3.lib
或者在代码中加入:#pragma comment(lib , "glfw3.lib")
若运行时,出现无法启动的情况,那么将lib-vc2013中的dll文件拷贝到Debug/Release文件夹中
4.配置glad
打开GLAD的在线生成器http://glad.dav1d.de/,将语言(Language)设置为C/C++,在API选项中,选择3.3以上的OpenGL(gl)版本。之后将模式(Profile)设置为Core,并且保证生成加载器(Generate a loader)的选项是选中的。都选择完之后,点击生成(Generate)按钮来生成库文件。
GLAD现在应该提供给你了一个zip压缩文件,包含两个头文件目录,和一个glad.c文件。将两个头文件目录(glad和KHR)复制到Include文件夹中(路径"/usr/local/include"),并添加glad.c文件到工程中。
测试代码:
#include
#include
#include
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
//将窗口设置为关闭,跳出循环
glfwSetWindowShouldClose(window, true);
}
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
int main()
{
//glfw初始化
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfw创建窗口
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
printf("创建窗口失败");
//终止
glfwTerminate();
return -1;
}
//显示窗口
glfwMakeContextCurrent(window);
//设置回调,当窗口大小调整后将调用该回调函数
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// glad初始化
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
printf("加载失败");
return -1;
}
// 使用循环达到循环渲染效果
while (!glfwWindowShouldClose(window))
{
//自定义输入事件
processInput(window);
//交互缓冲区,否则显示空白
glfwSwapBuffers(window);
//输入输出事件,否则无法对窗口进行交互
glfwPollEvents();
}
//终止渲染 关闭并清理glfw本地资源
glfwTerminate();
return 0;
}
三、学习资料
1.外网:https://learnopengl.com/Introduction
2.内网:https://learnopengl-cn.github.io/
或者 http://learnopengl-cn.readthedocs.io/zh/latest/