这是我的第一篇学习OpenGL的笔记,也是博主的第一篇博客,希望能够在这里和大家一起成长。

下面的代码是《OpenGL超级宝典(第五版)》中的示例代码,基本程序如下:

 #include <GLtools.h>  //OpenGL toolkit:工具箱库——包含一个用于操作矩阵和向量的3D数学库,并依靠GLEW获得OpenGL 3.3中用来产生和渲染一些简单3D对象的函数,以及对平截头体、相机类和变换矩阵进行管理的函数的充分支持。
#include <GLShaderManager.h> //Shader Manager Class:
//GLEW:自动初始化所有新函数指针并包含所需类型定义、常量和枚举值的扩展加载库。
//#include <GL/glut.h>
#define FREEGLUT_STATIC //因为我们使用的是freeglut的静态库版本,所以需要在它前面添加FREEGLUT_STATIC处理器宏
#include <GL/glut.h> //Windows FreeGlut equivalent:一种实用工具箱 GLBatch triangleBatch; //声明一个简单的GLTool封装类,用于将三角形顶点批次进行封装
GLShaderManager shaderManager; //简单的存储着色器实例 ////////////////////////////////////////////////////////////////////////////////////////////
//62 CHAPTER 2 Getting Started
//04_0321712617_ch02.qxd 6/21/10 11:35 AM Page 62
//Windows has changed size, or has just been created. In either case, we need to use the
//windows dimensions to set the viewport and the projection matrix.
void ChangeSize(int w,int h) //在窗口大小改变时接受新的宽度和高度
{
glViewport(,,w,h); //修改从目的坐标系到屏幕坐标系上的映射,x,y参数代表窗口中视口的左下角坐标,而宽度和高度参数实用像素表示的。
}
///////////////////////////////////////////////////////////////////////////////////////////
//this fuction does any needed initialization on the rendering context.
//This is the first opportunity to do any OpenGL related tasks.
void SetupRC()
{
//Blue background
glClearColor(0.0f,0.0f,1.0f,1.0f); //这个函数设置用来进行窗口清除的颜色
shaderManager.InitializeStockShaders(); //由于着色器管理器需要编译和链接它自己的着色器,所以我们必须在OpenGL开始的时候调用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 }; //创建三角形图元,三角形图元就是组成三角形的一系列点或者顶点;值得一提的是,所有这些点的Z坐标均设置为0
//下面代码建立了一个三角形的批次,仅包含3个顶点。
triangleBatch.Begin(GL_TRIANGLES,); //批次容器的初始化,告诉这个类它代表哪种图元,其中包括顶点数,以及(可选)一组或两组纹理坐标。
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函数清除一个或一组特定的缓冲区。颜色缓冲区、深度缓冲区、模板缓冲区。深度缓冲区用于进行深度测试,其中存储了屏幕上每个像素的深度值。 //下面的代码设置一组浮点数来表示红色(其alpha值设为1.0),并将它传递到存储着色器,即GLT_SHADER_IDENTITY着色器。这个着色器是使用指定颜色以默认笛卡尔坐标系在屏幕上渲染几何图形。
GLfloat vRed[]={1.0f,0.0f,0.0f,1.0f};
shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed); //UseStockShader函数会选择一个存储着色器并提供这个着色器的Uniform值。
triangleBatch.Draw(); //指示将几何图形提交到着色器,绘制批次容器所描述的内容。 //Perform the buffer swap to display the back buffer
//当设置OpenGL时,我们指定要一个双缓冲渲染环境。这就意味着将在后台缓冲区进行渲染,然后在结束时交换到前台。这种形式能够防止观察者看到可能伴随着动画帧与动画帧之间闪烁的渲染过程。
//缓冲区交换将以平台特定的方式进行,但是GLUT有一个单独的函数调用可以完成这项工作,即glutSwapBuffers()。
glutSwapBuffers();
}
///////////////////////////////////////////////////////////////////////////////////////////
//Main entry point for GLUT based programs
int main(int argc,char* argv[])
{
gltSetWorkingDirectory(argv[]); //设置当前工作目录 //接下来,进行一些基于GLUT的标准设置
glutInit(&argc,argv); //传输命令行参数,并初始化GLUT库
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL); //告诉GLUT库,在创建窗口时要使用哪种显示模式。GLUT_DOUBLE:双缓冲窗口 GLUT_RGBA:RGBA颜色模式 GLUT_DEPTH:将一个深度缓冲区分配为显示的一部分 GLUT_STENCIL:确保我们也会有一个可用的模板缓冲区。
//其中深度缓冲区可用于进行深度测试,存储了屏幕上每个像素的深度值。
glutInitWindowSize(,); //设置窗口的大小
glutCreateWindow("Triangle"); //创建以“Triangle”为标题的窗口
//回调函数
glutReshapeFunc(ChangeSize); //为窗口改变大小而设置一个回调函数,以便能够设置视点
glutDisplayFunc(RenderScene); //注册一个函数以包含OpenGL渲染代码 //在开始运行主消息循环之前,还要解决两个问题
GLenum err=glewInit(); //初始化GLEW库。重新调用GLEW库初始化OpenGL驱动程序中所有丢失的入口点,以确保OpenGL API对我们来说完全可用。
if(GLEW_OK!=err) //在试图做任何渲染之前,还要检查确定驱动程序的初始化过程中没有出现任何问题。
{
fprintf(stderr,"GLEW Error:%s\n",glewGetErrorString(err));
return ;
}
SetupRC(); //调用SetupRC。这里RC代表渲染环境(Rendering Context),这是一个运行中的OpenGL状态机的句柄。在任何OpenGL函数起作用之前必须创建一个渲染环境。 //开始主消息循环并结束main函数
glutMainLoop();
return ;
}

头文件分析

 #include <GLtools.h>  //OpenGL toolkit:工具箱库——包含一个用于操作矩阵和向量的3D数学库,并依靠GLEW获得OpenGL 3.3中用来产生和渲染一些简单3D对象的函数,以及对平截头体、相机类和变换矩阵进行管理的函数的充分支持。
#include <GLShaderManager.h> //Shader Manager Class
#define FREEGLUT_STATIC //因为我们使用的是freeglut的静态库版本,所以需要在它前面添加FREEGLUT_STATIC处理器宏
#include <GL/glut.h> //Windows FreeGlut equivalent:一种实用工具箱

这里插入了三个库函数:

1.GLtools.h:这个库是随着《OpenGL超级宝典》出现的,是一个工具箱库函数。GLTools中包含了一个用于操作矩阵和向量和3D数学库,并依靠GLEW获得OpenGL3.3中用来产生和渲染一些简单3D对象的函数,以及对视觉平截头体、相机类和变换矩阵进行管理的函数的充分支持。

2.GLShaderManager.h:这个也是《OpenGL超级宝典》中的头文件,其中包含了着色器管理器。没有着色器我们就不能再OpenGL(核心框架)中进行着色。着色器管理器不仅允许我们创建并管理着色器,还提供一组“存储着色器”(Stock Shader),它们能够进行一些初步和基本的渲染操作。

3.GL/glut.h:这是一个静态库,首先在前面添加FREEGLUT_STATI处理器宏。GLUT是OpenGL的实用工具箱,目的是帮助人们学习和编写OpenGL程序,而不必为任何平台特定环境的细枝末节而分神。

主函数分析

 int main(int argc,char* argv[])
{
gltSetWorkingDirectory(argv[]); //设置当前工作目录 //接下来,进行一些基于GLUT的标准设置
glutInit(&argc,argv); //传输命令行参数,并初始化GLUT库
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL); //告诉GLUT库,在创建窗口时要使用哪种显示模式。GLUT_DOUBLE:双缓冲窗口 GLUT_RGBA:RGBA颜色模式 GLUT_DEPTH:将一个深度缓冲区分配为显示的一部分 GLUT_STENCIL:确保我们也会有一个可用的模板缓冲区。
//其中深度缓冲区可用于进行深度测试,存储了屏幕上每个像素的深度值。
glutInitWindowSize(,); //设置窗口的大小
glutCreateWindow("Triangle"); //创建以“Triangle”为标题的窗口
//回调函数
glutReshapeFunc(ChangeSize); //为窗口改变大小而设置一个回调函数,以便能够设置视点
glutDisplayFunc(RenderScene); //注册一个函数以包含OpenGL渲染代码 //在开始运行主消息循环之前,还要解决两个问题
GLenum err=glewInit(); //初始化GLEW库。重新调用GLEW库初始化OpenGL驱动程序中所有丢失的入口点,以确保OpenGL API对我们来说完全可用。
if(GLEW_OK!=err) //在试图做任何渲染之前,还要检查确定驱动程序的初始化过程中没有出现任何问题。
{
fprintf(stderr,"GLEW Error:%s\n",glewGetErrorString(err));
return ;
}
SetupRC(); //调用SetupRC。这里RC代表渲染环境(Rendering Context),这是一个运行中的OpenGL状态机的句柄。在任何OpenGL函数起作用之前必须创建一个渲染环境。 //开始主消息循环并结束main函数
glutMainLoop();
return ;
}

和基本的win32程序一样,OpenGL的程序是从main函数开始运行的。

1.设置程序的默认工作目录

首先设置程序默认的工作目录,在Windows当中,默认的工作目录实际上就是与程序的可执行执行程序相同的目录。

2.GLUT的标准设置

    GLUT的初始化操作

向GLUT传递命令行参数,并初始化GLUT库:glutInit(&argc,argv);

显示模式设置  

告诉GLUT库,在创建窗口时要使用哪种类型的显示模式:glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);

创建窗口 

首先调用glutInitWindowSize(800,600);函数初始化一个大小为800*600的显示窗体;

然后调用glutCreateWindow("Triangle");来创建一个名为Triangle的显示窗体。

定义不同事件的回调函数

GLUT内部运行着一个本地消息循环,拦截适当的消息,然后调用我们为不同事件注册的回调函数。与使用真正的系统特定框架相比有一定的局限性,但是大大简化了组织并运行一个程序的过程,并且支持一个演示框架的最低限度的事件。

在这里,我们必须为窗体改变大小而设置一个回调函数,以便能够设置视点:glutReshapeRunc(ChangeSize);

此后,我们再为渲染窗体设置一个回调函数:glut(RenderScene);

3.初始化GLEW库

重新调用OpenGL库初始化OpenGL驱动程序中所有丢失的入口点,以确保OpenGL API对我们来说完全可用。调用glewInit一次就能完成这一步,在试图做任何渲染之前,还要检查确定驱动程序的初始化过程中没有出现任何问题。

这一步在调用主消息循环之前必须完成。

 GLenum err=glewInit();   //初始化GLEW库。重新调用GLEW库初始化OpenGL驱动程序中所有丢失的入口点,以确保OpenGL API对我们来说完全可用。
if(GLEW_OK!=err) //在试图做任何渲染之前,还要检查确定驱动程序的初始化过程中没有出现任何问题。
{
fprintf(stderr,"GLEW Error:%s\n",glewGetErrorString(err));
return ;
}

4.OpenGL渲染环境的初始化   

最后一项准备工作就是调用SetupRC,在实际开始渲染之前,我们在这里进行任何OpenGL初始化都非常方便。这里的RC代表渲染环境(Rendering Context),这是一个运行中的OpenGL状态机的句柄。在任何OpenGL函数起作用之前必须创建一个渲染环境,而GLUT在我们第一次创建窗口时完成了这项工作。我们实际上在这里进行预加载纹理,建立几何图形、渲染器等工作。

5.开启主消息循环   

调用glutMainLoop()函数,开启主消息循环。

GlutMainLoop函数被调用之后,在主窗口被关闭之前都不会返回,并且一个应用程序中只需调用一次。这个函数负责处理所有操作系统特定的消息、按键动作等,直到我们关闭程序为止。它还能确保我们注册的这些函数被正确地调用。

子函数分析

1. 全局变量

这里声明了两个全局变量,一个用于构建三角形顶点的批次,一个用于存储着色器。

GLBatch triangleBatch; //声明一个简单的GLTool封装类,用于将三角形顶点批次进行封装

2 GLShaderManager shaderManager; //简单的存储着色器实例

2. ChangeSize函数

该函数在窗口大小改变的同时,修改坐标系间的映射关系。

ChangeSize函数在窗口大小改变时接受新的宽度和高度。我们可以使用这个信息,在OpenGL函数glViewport的帮助下修改从目的坐标系到屏幕坐标系上的映射。

3. RenderScene函数

当窗口发生变化时,该函数用以重绘窗口。

首先glClear清除一个或一组特定的缓冲区。颜色缓冲区、深度缓冲区、模板缓冲区。glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

然后设置着色器。

这里使用着色器管理器申请了一个单位(Identity)着色器。使用红色背景来填充这个单位着色器。

 GLfloat vRed[]={1.0f,0.0f,0.0f,1.0f};
shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed); //UseStockShader函数会选择一个存储着色器并提供这个着色器的Uniform值。
triangleBatch.Draw(); //指示将几何图形提交到着色器,绘制批次容器所描述的内容。

单位着色器只是简单地使用默认的笛卡尔坐标系(在所有坐标轴的坐标范围都是-1.0~1.0)。所有片段都应用同一颜色,几何图形为实心和未渲染的。这种着色器只能使用一个GLT_ATTRIBUTE_VERTEX属性。vColor参数包含了要求的颜色。

最后,调用glutSwapBuffers函数指定双缓冲渲染环境。这就意味着将在后台缓冲区进行渲染,然后在结束时交换到前台。这种形式能够防止观察者看到可能伴随着动画帧与动画帧之间闪烁的渲染过程。缓冲区交换将以平台特定的方式进行,但是GLUT的这个函数可以完成这项工作。

glutSwapBuffers();

4. SetupRC函数

首先设置用来进行窗口清除的颜色,即几何图形的颜色。glClearColor(0.0f,0.0f,1.0f,1.0f);

然后绘制顶点三角形,首先是顶点数组GLfloat[]。

紧接着使用批次管理器来构建三角形批次,

 //下面代码建立了一个三角形的批次,仅包含3个顶点。
triangleBatch.Begin(GL_TRIANGLES,); //批次容器的初始化,告诉这个类它代表哪种图元,其中包括顶点数,以及(可选)一组或两组纹理坐标。
triangleBatch.CopyVertexData3f(vVerts); //然后至少复制一个由三分量顶点组成的数组。
triangleBatch.End(); //表示已经完成了数据复制工作,并且将设置内部标记,以通知这个类包含哪些属性。

Start from here: <<OpenGL的基本程序解析>>的更多相关文章

  1. osg 示例程序解析之osgdelaunay

    osg 示例程序解析之osgdelaunay 转自:http://lzchenheng.blog.163.com/blog/static/838335362010821103038928/ 本示例程序 ...

  2. 学习基于OpenGL的CAD程序的开发计划(一)

    本人目前从事的工作面对的客户中很多来自高端制造业,他们对CAD/CAE/CAM软件的应用比较多.公司现有的软件产品主要是用于渲染展示及交互,但面对诸如CAD方面的应用(比如基于约束的装配.制造工艺的流 ...

  3. 开源免费跨平台opengl opencv webgl gtk blender, opengl贴图程序

    三维图形的这是opengl的强项,大型3D游戏都会把它作为首选.图像处理,是opencv的锁定的目标,大多都是C的api,也有少部分是C++的,工业图像表现,图像识别,都会考虑opencv的.webg ...

  4. 【mybatis深度历险系列】mybatis的框架原理+入门程序解析

    在前面的博文中,小编介绍了springmvc的相关知识点,在今天这篇博文中,小编将介绍一下mybatis的框架原理,以及mybatis的入门程序,实现用户的增删改查,她有什么优缺点以及mybatis和 ...

  5. python调用openstack的api,create_instance的程序解析

    python调用openstack的api,create_instance的程序解析 2017年10月17日 15:27:24 CloudXli 阅读数:848   版权声明:本文为博主原创文章,未经 ...

  6. opengl 无法定位程序输入点_glutInitWithExit于动态链接库glut32.dll上

    1.问题:opengl 无法定位程序输入点_glutInitWithExit于动态链接库glut32.dll上 2.环境:vc6.0  win7,64位,opengl. 3.解决:将glut32.dl ...

  7. Java 实现《编译原理》中间代码生成 -逆波兰式生成与计算 - 程序解析

    Java 实现<编译原理>中间代码生成 -逆波兰式生成与计算 - 程序解析 编译原理学习笔记 (一)逆波兰式是什么? 逆波兰式(Reverse Polish notation,RPN,或逆 ...

  8. Java 实现《编译原理》简单-语法分析功能-LL(1)文法 - 程序解析

    Java 实现<编译原理>简单-语法分析功能-LL(1)文法 - 程序解析 编译原理学习,语法分析程序设计 (一)要求及功能 已知 LL(1) 文法为: G'[E]: E→TE' E'→+ ...

  9. Java 实现《编译原理》简单词法分析功能 - 程序解析

    Java 实现<编译原理>简单词法分析功能 - 程序解析 简易词法分析功能 要求及功能 (1)读取一个 txt 程序文件(最后的 # 作为结束标志,不可省去) { int a, b; a ...

随机推荐

  1. Codeforces Round #599 (Div. 2) B1. Character Swap (Easy Version)

    This problem is different from the hard version. In this version Ujan makes exactly one exchange. Yo ...

  2. 3.CRUD(增删改查)

    Select 选择,查询语句 id:就是对应的namespace中的方法名: resultType:Sql语句执行的返回值: parameterType:参数类型 我们想使用查询语句首先要在UserM ...

  3. 设置textarea不可拉伸

    默认情况下,我们将鼠标移动到textarea的右下角时发现文本域是可以通过拖动的方式改变其大小的,这会影响我们原本的页面布局.若想设置其不可拖动,可为其添加如下属性: style="resi ...

  4. itest(爱测试) 4.3.0 发布,开源BUG 跟踪管理 & 敏捷测试管理软件

    itest 简介:查看简介 test 开源敏捷测试管理,testOps 践行者.可按测试包分配测试用例执行,也可建测试迭代(含任务,测试包,BUG)来组织测试工作,也有测试环境管理,还有很常用的测试度 ...

  5. Uva 136 丑数

    n^2暴力就完事,但是上限要高,不然就算不到对应的1500,刘汝佳的写法更好. #include <bits/stdc++.h> using namespace std; const in ...

  6. Cygwin不能编译及解决办法

    最近不知道什么原因,以前使用cygwin编译Android动态库,现在不能使用了,报下面的错误. Android NDK: Host 'awk' tool is outdated. Please de ...

  7. ztree-编辑节点(树节点添加,删除,修改)

    <!DOCTYPE html> <HTML> <HEAD> <TITLE> ZTREE DEMO - addNodes / editName / rem ...

  8. FFmpeg + php 视屏转换

    什么是FFmpeg? FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频的完整解决方案.它包含了非常先进 ...

  9. 【JavaScript基础#1】

    "   目录 #. 概述 1. ECMAScript与JavaScript的关系 2. ECMAScript版本历史 3. 简单总结 #. 用法 1. 引入方式 2. 规范 3. 变量声明 ...

  10. 洛谷 P1843 奶牛晒衣服(二分答案)

    嗯... 题目链接:https://www.luogu.com.cn/problem/P1843 我们二分枚举时间,看看那些衣服在蒸发后还要用烘干机,则用cnt记录它的时间. 注意w数组在操作中不能变 ...