本章内容:
》OpenGL的发展历程和未来趋势
》扩展机制(Extension Mechanism)如何工作,以及它为什么很重要
》核心框架和“不鼓励使用的功能”
》如何检测OpenGL编程错误
》如何向OpenGL传递性能提示(Hint)
》如何获得一个基本项目并进入Visual C++或Xcode
》如何使用在一个基本编程框架中使用GLUT
2.1 什么是OpenGL?
使用OpenGL的最大优点是它的速度远远快于光线追踪器或软件渲染引擎
OpenGL规范包含GLSL(OpenGL着色语言)
2.1.1 标准的演化
IRSI GL(SGI)–>2D–>3D
OpenGL ARB(OpenGL Architecture Reiview Board)OpenGL 体系结构审核委员会
1992.7.1 OpenGL 1.0
ARB–>Khronos–>OpenGL ES
OpenGL的两种形式:OpenGL规范和OpenGL实现
OpenGL扩展机制
添加新函数、标记枚举
这是谁的扩展
许可和一致
OpenGL可以是软件库,也可以是一个完成三维图像渲染任务的硬件设备的驱动程序包
2.1.2 OpenGL的未来
OpenGL 2.0 –OpenGL着色语言(GLSL)
OpenGL 与Direct3D
OpenGL是跨平台的和可移植的,是一个开放的标准,拥有扩展机制
不鼓励使用的功能
OpenGL3.0将一些老旧的功能标记为不鼓励使用
OpenGL3.x:
OpenGL3.1–>所有不鼓励使用的功能都从OpenGL核心规范中移除了,引入GL_ARB_compatibility
OpenGL3.2–>核心框架和完整框架
只有核心
2.2 使用OpenGL
OpenGL是一种过程性而不是描述性的API:程序员不需要描述场景和它的外观,而是事先确定一些操作步骤,实现一定的外观和效果。
OpenGL并不包含任何负责窗口管理、用户交互或文件IO的函数。
2.2.1 支持阵容
GLUT
AUX–缺乏基本的GUI特性,不是编写最终代码
GLUT(OpenGL utility toolkit)OpenGL实用工具箱
GLU(OpenGL utility library)OpenGL实用库
GLUT—>freeglut
GLEW
GLTools–>基于GLEW
下载地址:https://github.com/HazimGazov/GLTools
2.2.2 OpenGL API 特性
数据类型:都以GLxxx
2.2.3 OpenGL错误
偶然健全性检查
GLenum glGetError(void)
GL_INVALID_ENUM 枚举参数超出范围
GL_INVALID_VALUE 数值参数超出范围
GL_INVALID_OPERATION 在当前的状态中操作非法
GL_OUT_OF_MEMERY 没有足够的内存来执行这条命令
GL_NO_ERROR 没有错误出现
如果一个错误是由于对OpenGL的非法调用所致,那么这条命令或函数调用将会被忽略
2.2.4 确认版本
const GLubyte *glGetString(GLenum name);
2.2.5 使用glHint获取线索
glHint函数允许我们指定偏重于视觉质量还是速度
void glHint(GLenum target, GLenum mode);
2.2.6 OpenGL状态机
对象是不是与背景混合,要不要进行正面或背面剔除,当前限制的是什么纹理,我们把这类变量的集合称为管线的状态。
状态机:表示一组状态变量的集合
打开状态变量glEnable(GLenum capability);
关闭状态变量glDisable(Glenum capability);
打开深度测试glEnable(GL_DEPTH_TEST);
关闭深度测试glDisable(GL_DEPTH_TEST);
判断是否打开glIsEnabled(GLenum capability);
查询变量的值:(布尔、整形、单精度浮点、双精度浮点)
void glGetBooleanv(GLenum pname,GLboolean *params);
void glGetDoublev(GLenum pname,GLboolean *params);
void glGetFloatv(GLenum pname,GLboolean *params);
void glGetIntegerv(GLenum pname,GLboolean *params);
2.3 建立Windows项目
2.4 建立Mac os X项目
2.5 第一个三角形
2.5.1 要包含什么
2.5.2 启动GLUT
源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
// Triangle.cpp // Our first OpenGL program that will just draw a triangle on the screen. //这两个是作者为了方便读者学习而提供的工具库 #include // OpenGL toolkit #include // Shader Manager Class #ifdef __APPLE__ #include <glut/glut.h> // OS X version of GLUT #else #define FREEGLUT_STATIC #include <GL/glut.h> // Windows FreeGlut equivalent #endif GLBatch triangleBatch; GLShaderManager shaderManager; /////////////////////////////////////////////////////////////////////////////// // Window has changed size, or has just been created. In either case, we need // to use the window dimensions to set the viewport and the projection matrix. void ChangeSize(int w, int h) { glViewport(0, 0, w, h); } /////////////////////////////////////////////////////////////////////////////// // This function does any needed initialization on the rendering context. // This is the first opportunity to do any OpenGL related tasks. // 在任何OpenGL函数起作用之前必须创建一个渲染环境,而GLUT在我们第一次创建窗口时就完成了这项工作 void SetupRC()// RC代表渲染环境(Rendering Context) { // Blue background glClearColor(0.0f, 0.0f, 1.0f, 1.0f );// 用来设置进行窗口清除的颜色,不会立即清除背景,而是设置在以后颜色缓冲区被清除(可能时重复的)时使用的颜色 shaderManager.InitializeStockShaders(); // Load up a triangle GLfloat vVerts[] = { -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f }; triangleBatch.Begin(GL_TRIANGLES, 3); triangleBatch.CopyVertexData3f(vVerts); triangleBatch.End(); } /////////////////////////////////////////////////////////////////////////////// // Called to draw scene void RenderScene(void) { // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);// glClear函数清除一个或一组特定的缓冲区 GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f }; shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed); triangleBatch.Draw(); // Perform the buffer swap to display back buffer glutSwapBuffers(); } /////////////////////////////////////////////////////////////////////////////// // Main entry point for GLUT based programs int main(int argc, char* argv[]) { gltSetWorkingDirectory(argv[0]);//工作目录,在载入纹理、模型数据时可能会用上 glutInit(&argc, argv);// 都支持哪些参数?以后有空看看 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);// 双缓冲窗口、RGBA颜色模式、深度缓冲区、模板缓冲区。后两个是?? glutInitWindowSize(800, 600);// 窗口大小 glutCreateWindow("Triangle");// 窗口标题 glutReshapeFunc(ChangeSize); glutDisplayFunc(RenderScene); GLenum err = glewInit();// 初始化OpenGL驱动程序中所有丢失的入口点,以确保OpenGL API对我们来说完全可用 if (GLEW_OK != err) { fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err)); return 1; } SetupRC(); glutMainLoop(); return 0; |
2.5.3 坐标系基础
开始讨论OpenGL中的视口和裁剪区域坐标(Clipping Volume Coordinate)
在某种程度上,设置坐标系是绘制对象并将他们显示到我们希望的屏幕位置的先决条件
定义视口
glutrReshapeFunc()—–如:void changeSize(GLsizei w, GLsizei h);// 在窗口创建或大小改变时调用
在changeSize函数中,我们可以通过调用
glViewport(GLint x, GLint y, GLsizei width, GLsizei height);// x,y时视口左下角坐标
当视口大小比实际窗口大小小时,相应的渲染区域就会变小
从笛卡尔坐标系到像素
我们要牢记一点,就是改变视口并不会改变基础坐标系
2.5.4 完成设置
RGB颜色空间
在OpenGL中,某种颜色是由红、绿、蓝和Alpha(透明度)分量混合而成的,每种分量的范围从0.0至1.0的浮点值,所以理论上可以产生的颜色数量时无限的。从现实角度,绝大多数设备中,颜色值的输出限制在24位
存储着色器
没有着色器,在OpenGL核心框架中就无法进行任何渲染
指定顶点
2.5.5 言归正传
缓冲区是一块存储图像信息的存储空间。红、绿、蓝、Alpha通常一起作为颜色缓冲区或像素缓冲区引用
颜色缓冲区是显示图像在内部存储的地方
通过glClear清除缓冲区会将屏幕上最后绘制的内容删除
“帧缓冲区”指的是所有这些缓冲区一起串联工作
2.6 加点儿活力!
2.6.1 特殊按键
glutSpecialFunc(SpecialKeys);—-void SpecialKeys(int key, int x, int y)// 按键编码,x、y坐标(像素形式)
2.6.2 刷新显示
glutPostRedisplay();
2.6.3 简单的动画片
将glutPostRedisplay放到RenderScene,就得到了一个持续自动刷新的程序
2.7 总结