这是我的第一篇学习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. UltraEdit设置打开的文件类型,怎么打开大文本文件

    点击高级,配置,选择文件处理下的临时文件,设置如图即可打开超大文本文件. 补充:视图——显示行号.

  2. Redis读写分离的简单配置

    Master进行写操作,可能只需要一台Master.进行写操作,关闭数据持久化. Slave进行读操作,可能需要多台Slave.进行读操作,打开数据持久化. 假设初始配置有Master服务器为A,sl ...

  3. 【译】PHP 内核 — zval 基础结构

    [译]PHP 内核 - zval 基础结构 原文地址:http://www.phpinternalsbook.com/php7/internal_types/zvals/basic_structure ...

  4. 实战【docker 镜像制作与使用】

    一.制作docker 镜像 使用spring boot 构建一个简单的web 项目,返回 “Hello,World ”字符串,使用 Maven 打成 jar 包,使用的Linux 环境是 Centos ...

  5. Bootstrap环境安装加使用---开启Bootstrap 之旅

    1.首先去Bootstrap官网https://getbootstrap.com/上下载Bootstrap 的最新版本 对应的中文页面如下: 下载自己所需要的版本(目前我自己下载的是编译的css和js ...

  6. python之 '随机'

    Q:想生成随机数,用哪个库? import random Q:想生成一个随机整数,范围在[0, 100]之内,怎么弄? >>> random.randint(0, 100) 7 Q: ...

  7. C语言实例——判断是否为闰年

    实例要求从键盘输入任意年份的整数 N,通过程序运行判断该年份是否为闰年. 算法思想 判断任意年份是否为闰年,需要满足以下条件中的任意一个:① 该年份能被 4 整除同时不能被 100 整除:② 该年份能 ...

  8. P&R 4

    Floorplan 要做好fp需要掌握哪些知识和技能? 通常遇到fp问题大致的debug步骤和方法有哪些? 如何衡量fp的QA? 通常FP是做PR 最关键也最具技术含量的一个环节.相对于后续的PR步骤 ...

  9. eosio 编译与部署

    1. 名词解释 创世节点(BIOS) 用于创建初始区块,加载基础合约,供其它节点同步连接. 矿工节点(BP) 主要用于生产同步区块,计算合约产生的费用归矿工账号所有. 查询节点 不产生区块,同步区块信 ...

  10. 安装Linux系统后配置的一般步骤

    安装linux后配置的一般步骤 最近在尝试不同的linux系统,记录一下安装完linux之后常用的软件的安装方法 1.源的更新 ubuntu 源的更新方法 参考(没有测试过,但是都大同小异,不行就换一 ...