欲以此分类来记录opengl的学习历程,此为第一篇,所以先来一个固定管线的例子,以及对双缓存的测试。

一、配置环境

写之前,先进行配置,然后再讲内容。

注:第一部分涉及的代码均忽略。

【环境配置传送门】

二、所需知识

1. opengl程序结构

main函数结构大体上由如下几个步骤:

) glutInit(&argc, argv);
读取命令行参数,初始化glut ) glutInitDisplayMode(unsigned int mode);
设置显示模式(或窗口类型) (本节涉及参数如下)
GLUT_RGB GLUT_RGBA GLUT_DOUBLE ) glutInitWindowSize(int, int);
设置窗口规格 ) glutInitWindowPosition(int, int);
设置窗口初始位置 ) glutCreateWindow(char*); ) if(glewInit()) ....
判断glew是否初始化成功 ) init()
初始化数据 ,函数体自己写 ) glutDisplayFunc(函数指针);
系统自带的显示回调宏,在glut每次更新窗口内容的时候自动调用。 ) glutMainLoop();
无限循环,一直处理窗口消息,如:判断是否需要进行重绘,然后自动调用glutDisplayFunc()中注册的函数(即参数)。

2. 初始化数据

glGen*  系列函数,用于OpenGL 分配不同类型的对象名称。

glBind*  系列函数,将已分配的对象名称进行绑定,设定为当前活动对象。

以VBO(Vertex Buffer Object  顶点缓冲对象)为例,来理解上面两个函数的理念,其中VBO是一个GLuint对象,即无符号整型。

我们程序员想要操控缓冲区,怎么办呢,缓冲区位于系统硬件中,对编程人员是不可见的。所以,opengl建立了一个映射机制,以一个GLuint的数据对象来代表某一缓存区。

其中,缓存区为映射的一端,VBO为另一端,我们首先要创建所需的VBO对象,然后通过glGenBuffers(VBO数量,VBO取址);来激活VBO对象作为某一映射的映射端。

因为程序员创建的GLuint对象,系统默认为一个普通的对象,只有通过glGenBuffers(),才能使系统将其认定为缓存区映射的对象。

而glBindBuffer(分配缓冲区类型,已激活的VBO对象);用于建立此映射,将VBO绑定到一个缓冲区,将当前VBO代表的缓冲区作为当前活动对象。尔后的所有关于缓冲区的操作均对当前VBO对象代表的缓冲区进行操作。

glBufferData(缓冲区类型,大小,数据,数据的读写方式);

刚刚说到VBO映射到一块缓冲区,但是里面并没有信息数据,所以要将数据传到缓冲区中,就是上述函数的作用。

我们可以通过glBufferData将一组顶点位置坐标信息传入到VBO1代表的缓冲区中,然后将顶点的颜色信息传入到VBO2代表的缓冲区中,当我们渲染的时候,需要颜色信息对颜色信息进行处理加工的时候,我们就通过GLBindBuffer,将VBO2绑定为当前活动对象,反之,同理。

上述,以VBO为例讲述了相关的一些概念,其他类似的函数同理。

3. 渲染

glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer)

参数解析表
参数名 数值 解释
index GLuint     如:0 顶点着色器中输入变量的location值,就是属性的索引
size GLint       如:2 每个顶点的属性数量,如:x、y
type GLenum  如:GL_FLOAT 顶点属性变量的数值类型
normalized GLboolean  如:GL_FALSE 设定了顶点数据存储前是否进行归一化
stride GLsizei     如:0 相邻属性变量之间间隔的比特长度
pointer GLvoid*    如:BUFFER_OFFSET(0) 数据读取时,开始位置的偏移量

通过该函数告诉管线怎样解析buffer中的数据

glDrawArrays(绘制方式,第一个顶点的索引,顶点数量);

void glFlush(void);

强制所有进行中的OpenGL命令立即完成并传输到OpenGL服务端处理。这样就可以保证它们在一定时间内全部完成。

但是,该函数只是强制所有运行中的命令送入服务端而已,它会立即返回,它并不会等待所有的命令完成,而等待确实我们需要做的。。。

glFinish();

它会一直等待所有当前的OpenGL命令立即执行,等待他们全部完成。但是可想而知,它会拖累程序整体性能。

三、代码

 //配置代码
#if _MSC_VER>=1900
#include "stdio.h"
_ACRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned);
#ifdef __cplusplus
extern "C"
#endif
FILE* __cdecl __iob_func(unsigned i) {
return __acrt_iob_func(i);
}
#endif /* _MSC_VER>=1900 */ #include <iostream>
using namespace std; //我们需要包含 "val.h" 和 "LoadShaders.h"
//如果你按照之前配置环境那样做了,需要:
//#include "vgl.h" //我这里是自己将两个文件放到VS库目录里面了,总之,只要正确引用两个文件即可
#include <vgl.h> //顶点缓冲对象初始下标、缓冲对象数量、顶点属性数量、顶点数量
enum {Arraybuffers, Numbuffers, AttriNum = , VerNum}; GLuint buffers[Numbuffers]; //顶点缓冲对象数组 the array of VBOs void init();
void Display(); int main(int argc, char** argv)
{
//命令行初始化glut
glutInit(&argc, argv); //初始化显示模式
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); //初始化windows
glutInitWindowSize(, );
glutInitWindowPosition(, );
glutCreateWindow("my work 1"); //检查glew是否就绪
if (glewInit())
{
cout << "glew didn't go work!" << glewGetErrorString(glewInit()) << endl;
exit(EXIT_FAILURE);
} //初始化数据
init(); //渲染
glutDisplayFunc(Display); glutMainLoop(); return ;
} void init()
{
//顶点数据
GLfloat vertices[VerNum][AttriNum]
{
{ 0.8,0.8, },
{ -0.1,,},
{0.8,-0.8,},
{-0.8,,},
}; //创建缓冲器
glGenBuffers(Numbuffers, buffers);
//绑定缓冲器
glBindBuffer(GL_ARRAY_BUFFER, buffers[Arraybuffers]);
//向缓冲区传递数据
glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW); //设置清除颜色
glClearColor(, , , );
} void Display()
{
//清空颜色缓存
glClear(GL_COLOR_BUFFER_BIT); //开启顶点属性数组
glEnableVertexAttribArray(); glBindBuffer(GL_ARRAY_BUFFER, buffers[Arraybuffers]); glVertexAttribPointer(, AttriNum, GL_FLOAT, GL_FALSE, , BUFFER_OFFSET()); //绘制 两个三角形
glColor4f(, , , 0.3); //设置颜色
glDrawArrays(GL_TRIANGLES, , VerNum);
glColor4f(, , , 0.8);
glDrawArrays(GL_TRIANGLES, , VerNum);
//1. 将绘制好的两个三角形放到屏幕前面
glutSwapBuffers(); //在后面的帧缓存中继续绘制 一个四边形 边框
glColor4f(, 0.1, 0.8, 0.0);
glDrawArrays(GL_LINE_LOOP, , VerNum); //2. 将后面的四边形边框帧缓存放到屏幕前面
glutSwapBuffers(); //此时,理论上讲,后台的帧缓存应该为原来绘制的两个三角形
glColor4f(, 0.1, 0.8, 0.0);
//我们在其基础上,加上边框
glDrawArrays(GL_LINE_LOOP, , VerNum); //3. 显示的是两个三角形+边框
glutSwapBuffers(); //禁用顶点属性数组 这个要最后禁用
glDisableVertexAttribArray(); glFlush();
}

四、效果

标号为1.处得到的效果:(将107-122注释掉)

标号2.处得到的效果(将114-122注释)

标号3.处的效果,即将后面帧缓存中的效果添加到原来帧缓存的图形中得到的效果

通过这一节的测试,我们真正的看到了双缓存的工作过程,以及内部数据信息。

感谢您的阅读,生活愉快~

OpenGL 笔记<1> 固定管线实例 + 双缓存测试实例的更多相关文章

  1. web自动化测试-模块驱动测试实例和数据驱动测试实例

    一.模块驱动测试实例 把登录和退出统一封装在login类中,若把login类单独放在一个文件中,就可以给任一测试脚本调用,这里就跟测试脚本放一起 from selenium import webdri ...

  2. Confluence 6 从生产环境中恢复一个测试实例

    请参考 Restoring a Test Instance from Production 页面中的内容获得更多完整的说明. 很多 Confluence 的管理员将会使用生产实例运行完整数据和服务的 ...

  3. OpenGL 笔记 <2> Compiling and Linking a shader program

    Preface 这一节所有的主要内容都在一个OpenGL库文件中<LoadShaders.h> ,只需要用LoadShader()函数进行加载即可.但是由于老是出错,所以自己实现了一下,也 ...

  4. OpenGL笔记<第一章> 构建 GLSL class

    恭喜,我们终于很扎实地完成了第一章——glsl 入门 不幸的是,it's not the basic of GLSL shader ,我们下一节开篇,basic of GLSL shader 在下一章 ...

  5. 7_DoubleBuffer 游戏编程中的双缓存模式

    ### double buffer 双缓存 简单说: 当一个缓存被读取的时候,往另一个缓存里写入, 如此交替 #### the pattern 有两个缓存实例,一个是 current buffer, ...

  6. Android 框架修炼-自己封装双缓存管理框架库

    一.概述 Android开发中,网络请求是很重要的一部分,而缓存网络请求来的图片或者响应结果字符串或者结果流,既可以省流量,同时也可以帮助我们 解决无网或弱网情况下加载情况,当然也可以提升程序性能效率 ...

  7. [图形学] Chp8 使用双缓存创建帧动画

    第八章的习题有动画的要求,之前并没有讲解动画如何制作,网上搜到一篇文章SCARA——OpenGL入门学习五六(三维变换.动画),按照里面的方法,使用双缓存和空闲回调函数实现了一个简单的帧动画. #in ...

  8. GPU的历史:从固定管线到可编程管线再到通用计算平台

    开始的时候GPU不能编程,也叫固定管线的,就是把数据按照固定的通路走完. 和CPU同样作为计算处理器,顺理成章就出来了可编程的GPU,但是那时候想在GPU上编程可不是容易的事,你只能使用GPU汇编来写 ...

  9. 《Linux就该这么学》培训笔记_ch16_使用Squid部署代理缓存服务

    <Linux就该这么学>培训笔记_ch16_使用Squid部署代理缓存服务 文章最后会post上书本的笔记照片. 文章主要内容: 代理缓存服务 配置Squid服务程序 正向代理 标准正向代 ...

随机推荐

  1. 寒假短期学习计划 - C++

    寒假短期学习计划 - C++ 一.所选课程 && 相关 0.选以下课的理由: 选课理由0: 只是短期的计划,先选些短视频感受:之后再视情况选其他课: 选课理由1: 难度低,以前自学过一 ...

  2. Maven实战(九)Maven仓库简介

    目录 一.作用 Maven仓库分为本地仓库和远程仓库,集中存放项目引用的jar包,无需将jar包放在程序中,结合Maven项目的pom.xml,使得项目管理jar包更容易,有以下几个优点: 对于项目来 ...

  3. 4-2 R语言函数 apply

    #apply函数,沿着数组的某一维度处理数据 #例如将函数用于矩阵的行或列 #与for/while循环的效率相似,但只用一句话可以完成 #apply(参数):apply(数组,维度,函数/函数名) & ...

  4. Spring-IOC BeanFactory运行时动态注册bean

    在spring运行时,动态的添加bean,dapeng框架在解析xml的字段时,使用到了动态注册,注册了一个实现了FactoryBean类! 定义一个没有被Spring管理的Controller pu ...

  5. 2049. [SDOI2008]Cave 洞穴勘测【LCT】

    Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好 ...

  6. virtualbox+vagrant学习-3-Vagrant Share-1-简介

    Vagrant Share 通过 ngrok 内网穿透功能实现让全世界人可以访问虚拟机的服务 Vagrant Share允许你与世界上的任何人共享您的Vagrant环境,几乎支持你在任何网络环境中使用 ...

  7. SSM框架之批量增加示例(同步请求jsp视图解析)

    准备环境:SSM框架+JDK8/JDK7+MySQL5.7+MAVEN3以上+Tomcat8/7应用服务器 示例说明: 分发给用户优惠券,通过checkbox选中批量分发,对应也就是批量增加. 对于公 ...

  8. Python自动化之django model验证(很弱,感觉应用场景不多)

    django model的数据验证 使用full_clean进行验证 obj = models.UserInfo(name="alex",email="tiantian& ...

  9. [NOIp2009] $Hankson$の趣味题

    \(23333\)这是最近第二份在时间上吊打\(yjk\)的代码--啊哈哈哈哈哈哈哈 嗯,其实遇到这种单纯的\(gcd \ \ or \ \ lcm\)的题,我们都可以用一种比较简单的方法分析:唯一分 ...

  10. C语言程序设计I—第九周教学

    第九周教学总结(28/10-03/11) 教学内容 第三章 分支结构 3.3 查询自动售货机中商品的价格 课前准备 在蓝墨云班课发布资源: PTA:2018秋第九周作业1 3.3 分享码:530571 ...