OpenGL 学习 02 - 第一个三角形
2018-04-15 本文已影响49人
执着丶执念
![](https://img.haomeiwen.com/i1795722/79dd104663991976.jpg)
学习书籍: OpenGL 超级宝典(中文第五版) 密码:fu4w
书籍源码:OpenGL 超级宝典第五版源代码 密码:oyb4
环境搭建:OpenGL 学习 01 - Mac 搭建 OpenGL 环境
基本概念
GLUT
全名 OpenGL utility toolkit,一种跨平台(Windows/Mac/Linux)的 GUI 编程框架,用于辅助 OpenGL 显示 GUI 界面
GLEW
一种维护最好的开源 OpenGL 扩展加载库(自动初始化所有函数指针并包含所需类型定义、常量和枚举值),GLEW 被预先封装在了 GLTools 库中。
GLTools
OpenGL 快捷开发工具,包含一个用于操作矩阵和向量的 3D 数学库,一些产生和渲染简单的 3D 对象的函数,以及对视觉平截头体、相机类和变换矩阵进行管理的函数的充分支持
OpenGL 数据类型
为了 OpenGL 的移植性,OpenGL 定义了各种数据类型,这些数据类型可以映射到所有平台上的特定最小格式。
![](https://img.haomeiwen.com/i1795722/3563e7ee8b3a0459.png)
源码解析
一、GLUT 构建窗口
要使用 GLUT 框架,需要导入头文件#include <glut/glut.h>
1. 设置当前目录(只针对 Mac)
// 程序入口
int main(int argc, char* argv[])
{
//设置当前工作目录,针对MAC OS X
gltSetWorkingDirectory(argv[0]);
2. 初始化 GLUT 库
glutInit(&argc, argv);
3. 初始化窗口渲染模式
/*
* 初始化渲染模式
* GLUT_DOUBLE - 双缓冲模式
* GLUT_RGBA - RGBA颜色模式
* GLUT_DEPTH - 深度测试模式
* GLUT_STENCIL - 模板缓存模式
*/
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
4.创建窗口并命名
//初始化窗口大小(width=800, height=600)
glutInitWindowSize(800, 600);
//创建窗口
glutCreateWindow("Triangle");
5. 注册不同的回调函数,拦截适当消息
//注册回调函数,拦截窗口大小变化消息,ChangeSize 是自定义方法名
glutReshapeFunc(ChangeSize);
//注册回调函数,拦截窗口渲染消息,RenderScene 是自定义方法名
glutDisplayFunc(RenderScene);
6. 初始化 GLEW 库
//确保驱动程序的初始化中没有出现任何问题。
GLenum err = glewInit();
if(GLEW_OK != err) {
return -1;
}
7. 初始化渲染环境
//自定义函数,方法名随意,这里用 SetupRC
SetupRC();
8. 主消息循环,类似 OC 中 RunLoop
glutMainLoop();
二、第一个三角形
1. 设置视口
//设置视口,(x, y, width, height),其中 (x, y) 代表窗口中视口的左下角坐标,
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
![](https://img.haomeiwen.com/i1795722/c6ee8764afb734d0.png)
2. 设置窗口背景颜色
//设置窗口背景颜色(RGBA),CGclampf 是浮点型,RGBA 每种分量在 0.0~1.0 之间
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
3. 着色器管理器初始化
//定义着色器管理器,OpenGL 没有着色器是无法渲染的
GLShaderManager shaderManager;
//初始化着色管理器
shaderManager.InitializeStockShaders();
4. 批次初始化
//构建三角形顶点数组,vVert包含3个顶点的(x, y, z)笛卡尔坐标
//窗口大小默认-1.0到1.0
GLfloat vVerts[] = {
-0.5f, 0.0f, 0.0f,
0.5f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f,
};
//创建批次,GLTools 容器类,方便我们保存数据和渲染图形
GLBatch triangleBatch;
//开始构建批次,GL_TRIANGLES 表示三角形,后面参数是顶点数
triangleBatch.Begin(GL_TRIANGLES, 3);
/*
* 批次增加存储属性
* CopyVertexData3f(XYZ顶点数据)
* CopyNormalDataf(表面法线)
* CopyColorData4f(RGBA颜色)
* CopyTexCoordData2f(纹理坐标)
*/
triangleBatch.CopyVertexData3f(vVerts);
//结束批次属性设置,表明完成数据复制操作,不能再添加新属性
triangleBatch.End();
5. 清除缓存区组
//清除一个或一组特定的缓冲区,对应前面设置的窗口渲染模式
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
6. 着色器设置颜色
//设置一组浮点数来表示红色(RGBA)
GLfloat vRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
//GLT_SHADER_IDENTITY 单位着色器,这个着色器只是使用指定颜色为顶点上色
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
7. 批次数据渲染
//根据批次里的顶点数据利用当前设置的着色器进行画图
triangleBatch.Draw();
8. 缓冲区交换(渲染模式包含 GLUT_DOUBLE,其他就可略过)
/*
* 当 glutInitDisplayMode 有传入双缓冲模式时,
* 将在后台缓冲区进行渲染,然后在结束时交换到前台
* 为了防止观察者看到可能随着动画帧和动画帧之间闪烁的渲染过程
*/
glutSwapBuffers();
三、全部源码如下:
#include <iostream>
#include <GLShaderManager.h>
#include <GLTools.h>
#include <glut/glut.h>
GLBatch triangleBatch;
GLShaderManager shaderManager;
//窗口大小改变时接受新的宽度和高度
void ChangeSize(int width, int height) {
// 设置视口,(x, y, width, height),其中 (x, y) 代表窗口中视口的左下角坐标
glViewport(0, 0, width, height);
}
//为程序作一次性的设置
void SetupRC() {
//设置背影颜色
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
//初始化着色管理器
shaderManager.InitializeStockShaders();
//构建三角形顶点数组,vVert包含3个顶点的(x, y, z)笛卡尔坐标
GLfloat vVerts[] = {
-0.5f, 0.0f, 0.0f,
0.5f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f,
};
//开始构建批次,GL_TRIANGLES 表示三角形,后面参数是顶点数
triangleBatch.Begin(GL_TRIANGLES, 3);
/*
* 批次增加存储属性
* CopyVertexData3f(XYZ顶点数据)
* CopyNormalDataf(表面法线)
* CopyColorData4f(RGBA颜色)
* CopyTexCoordData2f(纹理坐标)
*/
triangleBatch.CopyVertexData3f(vVerts);
//结束批次属性设置,表明完成数据复制操作,不能再添加新属性
triangleBatch.End();
}
//开始渲染
void RenderScene(void) {
//清除一个或一组特定的缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//设置一组浮点数来表示红色
GLfloat vRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
//传递到存储着色器,即GLT_SHADER_IDENTITY着色器,这个着色器只是使用指定颜色以默认笛卡尔坐标第在屏幕上渲染几何图形
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
//根据批次里的顶点数据利用当前设置的着色器进行画图
triangleBatch.Draw();
/*
* 当 glutInitDisplayMode 有传入双缓冲模式时,
* 将在后台缓冲区进行渲染,然后在结束时交换到前台
* 为了防止观察者看到可能随着动画帧和动画帧之间闪烁的渲染过程
*/
glutSwapBuffers();
}
//程序入口
int main(int argc, char* argv[]) {
//设置当前工作目录,针对MAC OS X
gltSetWorkingDirectory(argv[0]);
//初始化GLUT库
glutInit(&argc, argv);
/*初始化渲染模式,其中标志GLUT_DOUBLE、GLUT_RGBA、GLUT_DEPTH、GLUT_STENCIL分别指
双缓冲窗口、RGBA颜色模式、深度测试、模板缓冲区*/
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
//初始化窗口大小
glutInitWindowSize(800, 600);
//创建窗口
glutCreateWindow("Triangle");
//注册回调函数,拦截窗口大小变化消息,ChangeSize 是自定义方法名
glutReshapeFunc(ChangeSize);
//注册回调函数,拦截窗口渲染消息,RenderScene 是自定义方法名
glutDisplayFunc(RenderScene);
//确保驱动程序的初始化中没有出现任何问题。
GLenum err = glewInit();
if(GLEW_OK != err) {
fprintf(stderr, "glew error:%s\n", glewGetErrorString(err));
return 1;
}
//初始化设置
SetupRC();
//进入调用循环
glutMainLoop();
return 0;
}
![](https://img.haomeiwen.com/i1795722/c3736f09e4acf64a.png)
这里是 Demo 地址:github->openGLDemo->01-environment