博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
3D Computer Grapihcs Using OpenGL - 10 Color Buffer
阅读量:4557 次
发布时间:2019-06-08

本文共 4894 字,大约阅读时间需要 16 分钟。

本节我们将尝试利用三角形制作一个“走马灯”效果。

一个三角形如图示方式,从左向右依次移动。

先看一下代码:

MyGlWindow.cpp

1 #include 
2 #include "MyGlWindow.h" 3 #include
4 #include
5 6 float triangleWidth = 0.1f; 7 float bytesPerTriangle = sizeof(GLfloat) * 18; 8 uint triangleIndex = 0; 9 uint maxTriangleCount = 20;10 11 void MyGlWindow::sendDataToOpenGL()12 {13 //GLfloat verts[] =14 //{15 // -1.0f, -1.0f, +0.5f,//Vertex 016 // +1.0f, +0.0f, +0.0f,//Color 017 // +0.0f, +1.0f, -0.5f,//Vertex 118 // +0.0f, +1.0f, +0.0f,//Color 119 // +1.0f, -1.0f, +0.5f,//Vertex 220 // +0.0f, +0.0f, +1.0f,//Color 221 22 // -1.0f, +1.0f, +0.5f,//Vertex 323 // +0.5f, +0.3f, +0.1f,//Color 324 // +0.0f, -1.0f, -0.5f,//Vertex 425 // +0.1f, +0.4f, +0.2f,//Color 426 // +1.0f, +1.0f, +0.5f,//Vertex 527 // +1.0f, +0.5f, +0.2f,//Color 528 //};29 30 GLuint vertexBufferID;31 glGenBuffers(1, &vertexBufferID);32 glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);33 glBufferData(GL_ARRAY_BUFFER, maxTriangleCount * bytesPerTriangle, NULL, GL_STATIC_DRAW);34 35 //GLushort indices[] =36 //{37 // 0,1,2,38 // 3,4,5,39 //};40 //GLuint indexBufferID;41 //glGenBuffers(1, &indexBufferID);42 //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);43 //glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);44 45 glEnableVertexAttribArray(0);46 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0);47 48 glEnableVertexAttribArray(1);49 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (char*)(sizeof(GLfloat) * 3));50 }51 52 void MyGlWindow::installShaders()53 {54 //未修改,省略...55 }56 57 void MyGlWindow::initializeGL()58 {59 glewInit();60 glEnable(GL_DEPTH_TEST);61 sendDataToOpenGL();62 installShaders();63 }64 65 void MyGlWindow::paintGL()66 {67 glClear(GL_DEPTH_BUFFER_BIT);68 glViewport(0, 0, width(), height());69 //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);70 sendAnotherTriangle();71 glDrawArrays(GL_TRIANGLES, (triangleIndex-1)*3, triangleIndex * bytesPerTriangle);72 }73 74 void MyGlWindow::sendAnotherTriangle()75 {76 if (triangleIndex == maxTriangleCount)77 return;78 GLfloat xVal = -1 + triangleIndex * triangleWidth;79 GLfloat newTriangle[] = 80 {81 xVal, 1.0f, 0.0f,82 1.0f, 0.0f, 0.0f,83 84 xVal + triangleWidth, 1.0f, 0.0f,85 0.0f, 1.0f, 0.0f,86 87 xVal, 0.0f, 0.0f,88 0.0f, 0.0f, 1.0f,89 };90 91 glBufferSubData(GL_ARRAY_BUFFER, bytesPerTriangle * triangleIndex, bytesPerTriangle, newTriangle);92 93 triangleIndex++;94 }95 96 std::string MyGlWindow::ReadShaderCode(const char* fileName)97 {98 //未修改,省略...99 }

MyGlWindow.h

1 #pragma once 2 #include 
3 #include
4 class MyGlWindow :public QGLWidget 5 { 6 protected: 7 void sendDataToOpenGL(); 8 void installShaders(); 9 void initializeGL();10 void paintGL();11 std::string ReadShaderCode(const char* fileName);12 void sendAnotherTriangle();13 };

重点看cpp文件里的变化。

先定义了几个变量(其实也可以定义成常量),方便后面使用,他们分别是:

  • float triangleWidth = 0.1f 表示三角形的宽度
  • float bytesPerTriangle = sizeof(GLfloat) * 18 表示每个三角形包含的顶点信息数据字节数,一个三角形使用了3个顶点,每个顶点有6个GLfloat类型数据
  • uint triangleIndex = 0 表示当前绘制的三角形的索引
  • uint maxTriangleCount = 20 “走马灯”最多有多少个三角形

此前我们是在sendDataToOpenGL()函数中创建一个verts数组,把所有的数据一次性发送到OpenGL中进行绘制,本次我们需要动态改变绘制的内容,所以就不事先将数据一次性发送了。首先删除掉sendDataToOpenGL函数中的verts数组。(13-28行)

另外也不需要所以数组了,也把索引数组相关的内容删除掉。(35-43行以及69行)

33行也做了修改,首先我们要给VertexArrayBuffer分配足够的空间,所以第二个参数改成了maxTriangleCount * bytesPerTriangle,提供20个三角形需要的空间。而我们在这个阶段不需要提供任何数据(后面会讲如何提供),所以第三个参数直接给个空值NULL。

在71行绘制Array之前,我们调用了一个新添加的函数sendAnotherTriangle(),这个函数的前半部分(78-89行)是准备数据,准备每次走马灯要绘制的三角形的数据,由数据内容也能看出来,主要区别就是位置向右移动了。

重点是91行的函数

glBufferSubData(GL_ARRAY_BUFFER, bytesPerTriangle * triangleIndex, bytesPerTriangle, newTriangle);

glBufferSubData 这个OpenGL函数的作用是“部分填充” Array Buffer。可以对比观察33行的glBufferData(一次性全部填充), 名字只是多了一个Sub,但是两者的参数还是有些区别的。

  • 第一个参数和glBufferData是一样的,表示设置哪个绑定点的数据。
  • 第二个参数是一个绘制的起始位置,因为我们右了一个三角形的索引triangleIndex,所以起始值就是它乘以每个三角形的字节数。
  • 第三个参数表示每个元素的长度,正好使用我们一开始定义的每个三角形的字节数 bytesPerTriangle
  • 第四个参数是数据本身

71行绘制Array Buffer, 注意第二个参数是每个三角形的起始点。

 

完成后编译运行,发现画面并没有变化,主要原因是画面没有重绘,为了激活重绘,最简单的办法就是让窗口失去焦点和得到焦点,也就是可以在opengl窗口和其他任意窗口之间点击切换。

但是看到的效果仍然不是我们期望的。效果如下:

这是什么原因呢?

原因是OpenGL使用了双重缓存。一个Front Buffer, 一个Back Buffer。

绘制工作都是在Back Buffer上进行的,以免用户看到绘制的过程,绘制好以后,会和Front Buffer进行一次交换。这就是为什么我们看到了似乎有两副不同的图在反复切换。

另外,我们明确指定了每次只绘制一个三角形,但是为什么之前的三角形都保存下来了?

原因是我们没有进行一次“清理”。

找到MyGlWindow.cpp的67行,我们对它进行如下修改:

glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

既然要清理Depth Buffer,我们顺便使用一个"位或" 运算符把 Color Buffer也添加上。

这样修改以后,就可以实现"走马灯"效果了!(效果就不截图了,动图太难弄了)

 

转载于:https://www.cnblogs.com/AnKen/p/8343895.html

你可能感兴趣的文章
[转]微擎应用笔记3--manifest.xml文件使用说明
查看>>
Codeforces 1000C Covered Points Count 【前缀和优化】
查看>>
python高效读取文件、文件改写
查看>>
gulp
查看>>
pgsql查询优化之模糊查询
查看>>
不变模式
查看>>
matlab去云雾
查看>>
500lines项目简介
查看>>
Asp.net core logging 日志
查看>>
BOM浏览器对象模型
查看>>
Jq 遍历each()方法
查看>>
Android源码分析:Telephony部分–phone进程
查看>>
关于 redis.properties配置文件及rule
查看>>
WebService
查看>>
关于Java中重载的若干问题
查看>>
Java中start和run方法的区别
查看>>
23种设计模式中的命令模式
查看>>
[转载]年薪10w和年薪100w的人,差在哪里?
查看>>
shell 日期参数
查看>>
package的使用
查看>>