本次实践是绘制两个三角形,重点理解顶点数组对象和OpenGL缓存的使用。

顶点数组对象

  顶点数组对象负责管理一组顶点属性,顶点属性包括位置、法线、纹理坐标等。

OpenGL缓存

  OpenGL缓存实质上是OpenGL服务端的一块内存区域,用于存储数据。OpenGL的所有数据都是存储在缓存对象中的。

  在本次实践的思路是创建一个顶点数组对象来管理所绘制的三角性的顶点数据,数据存储在缓存对象中,然后使用绘制API绘制三角形。

  首先,创建顶点数组对象,函数原型:void genVertexArrays(GLsizei n, GLuint *arrays);其中n表示数量,结果保存在arrays中。

  然后使用glBindVertexArray绑定数组对象,那为什么需要绑定数组对象了?在使用OpenGL的过程中会生成的非常多的对象,每一种对象都会有许多的操作,如使用glVertexAttribPointer设置顶点数组对象的属性,在进行这些操作之前需要明确是对哪个对象进行操作,而绑定机制就是做这件事的。OpenGL绑定对象后,接下来的操作就表示作用于这个对象。示例如下:

    glGenVertexArrays(NumVAOs,VAOs);

    glBindVertexArray(VAOs[Triangles]);

  绑定好对象后我们就需要设置这个顶点数组对象所管理的顶点数据,这个时候就需要缓存了。创建和绑定类似顶点数组对象,但最后需要glBufferData来输入数据,示例如下:

  1. glGenBuffers(NumBuffers,Buffers);
  2. glBindBuffer(GL_ARRAY_BUFFER,Buffers[ArrayBuffer]);
  3. glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

创建缓存

  glGenBuffers(GLsizei n, GLuint* buffers);//创建n个缓存对象,保存在buffers数组中

向缓存中输入或输出数据

  glBindBuffer(GLenum target, GLuint buffer); //绑定缓存到target指定的缓存结合点

  glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); //为绑定到target的缓存对象分配size大小的存储空间,如果data不为NULL,则使用data初始化所为配的存储空间。usage指示缓存中的数据可能具备的一些特定的用途。

  glBufferSubData(GLenum target, GLsizeiptr offset, GLsizeiptr size, const GLvoid* data);//使用新数据替换缓存中的部分数据

清除数据

  glClearBufferData(GLenum target, GLenum internalformat, GLenum format, GLenum type, const GLvoid* data);  //使用data填充缓存存储空间,format和type指定data的数据格式和类型,填充前需要把data转化为internalformat

  glClearSubBufferData(GLenum target, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const GLvoid* data); //同上,区别是这个方法只填充offset和size指定的区域;

  

  接着我们需要设置顶点属性,使用glVertexAttribPointer.示例如下:

  glVertexAttribPointer(vPosition,2,GL_FLOAT,GL_FALSE,0,BUFFER_OFFSET(0));

设置顶点属性

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

  

  这些都做好了之后,我们就可以使用顶点数组对象来绘制我们的三角形了。

    glBindVertexArray(VAOs[Triangles]);

    glDrawArrays(GL_TRIANGLES,0,NumVertices);

  使用顶点数据之前需要先绑定,表示当前绘制使用该对象。

绘制命令

  glDrawArrays(GLenum mode, GLint first, GLsizei count);//直接读取顶点数据绘制

  glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);基于索引绘制(即所有的顶点在一个数组中,使用索引来引用顶点数据)

具体的示例代码如下:

  1. #include <GL/glew.h>
  2. #include <GL/freeglut.h>
  3. #include <stdio.h>
  4. #include "ShaderHelper.h"
  5.  
  6. #define BUFFER_OFFSET(n) ((GLvoid*)n)
  7. enum VAO_IDs { Triangles,NumVAOs};
  8. enum Buffers_IDs { ArrayBuffer, NumBuffers };
  9.  
  10. enum Attrib_IDs { vPosition=0 };
  11.  
  12. GLuint VAOs[NumVAOs];
  13. GLuint Buffers[NumBuffers];
  14.  
  15. const GLuint NumVertices=6;
  16.  
  17. void init();
  18. void display();
  19.  
  20. int main(int argc,char* argv[])
  21. {
  22. glutInit(&argc,argv);
  23. glutInitContextVersion(3,3);
  24. glutInitContextProfile(GLUT_CORE_PROFILE);
  25. glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
  26. glutInitWindowPosition(0,0);
  27. glutInitWindowSize(300,300);
  28. glutCreateWindow("Frame Buffer");
  29.  
  30. /* const GLubyte* name = glGetString(GL_VENDOR); //返回负责当前OpenGL实现厂商的名字
  31. const GLubyte* biaoshifu = glGetString(GL_RENDERER); //返回一个渲染器标识符,通常是个硬>
  32. 件平台
  33. const GLubyte* OpenGLVersion =glGetString(GL_VERSION); //返回当前OpenGL实现的版本号
  34. const GLubyte* gluVersion= gluGetString(GLU_VERSION); //返回当前GLU工具库版本
  35. printf("OpenGL实现厂商的名字:%s\n", name);
  36. printf("渲染器标识符:%s\n", biaoshifu);
  37. printf("OOpenGL实现的版本号:%s\n",OpenGLVersion );
  38. printf("OGLU工具库版本:%s\n", gluVersion);*/
  39. glewExperimental=GL_TRUE;
  40. glewInit();
  41. init();
  42. glutDisplayFunc(display);
  43.  
  44. glutMainLoop();
  45. return 0;
  46. }
  47.  
  48. void init()
  49. {
  50. glClearColor(0.0,0.0,0.0,1.0);
  51. glMatrixMode(GL_PROJECTION);
  52. glOrtho(-5,5,-5,5,5,15);
  53. glMatrixMode(GL_MODELVIEW);
  54. gluLookAt(0,0,10,0,0,0,0,1,0);
  55.  
  56. glGenVertexArrays(NumVAOs,VAOs);
  57. glBindVertexArray(VAOs[Triangles]);
  58.  
  59. GLfloat vertices[NumVertices][2]={
  60. {-0.90,-0.90},
  61. {0.85, -0.90},
  62. { -0.90, 0.85 },
  63. { 0.90, -0.85 },
  64. { 0.90, 0.90 },
  65. {-0.85, 0.90 },
  66. };
  67.  
  68. glGenBuffers(NumBuffers,Buffers);
  69. glBindBuffer(GL_ARRAY_BUFFER,Buffers[ArrayBuffer]);
  70. glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
  71.  
  72. ShaderInfo shaders[] = {
  73. {GL_VERTEX_SHADER,"triangles.vert"},
  74. {GL_FRAGMENT_SHADER,"triangles.frag"},
  75. {GL_NONE,NULL},
  76. };
  77.  
  78. GLuint program = LoadShaders(shaders);
  79. glUseProgram(program);
  80.  
  81. glVertexAttribPointer(vPosition,2,GL_FLOAT,GL_FALSE,0,BUFFER_OFFSET(0));
  82.  
  83. glEnableVertexAttribArray(vPosition);
  84. }
  85.  
  86. void display()
  87. {
  88. glClear(GL_COLOR_BUFFER_BIT);
  89.  
  90. glBindVertexArray(VAOs[Triangles]);
  91. glDrawArrays(GL_TRIANGLES,0,NumVertices);
  92.  
  93. glFlush();
  94. }

注意:代码根据红宝书编写,一些辅助性代码(如LoadShader)并未贴出,详情请参照www.opengl-readbook.com。

GLEW说明

  GLEW(OpenGL Extension Wrangler) 是OpenGL的另一个辅助库,主要封装了从OpenGL库中获取函数地址的过程,还包含了一些可以跨平台使用的OpenGL编程方法。

最终的效果如下:

Linux OpenGL 实践篇-3 绘制三角形的更多相关文章

  1. iOS OpenGL ES简单绘制三角形

    OpenGL 是用于2D/3D图形编程的一套基于C语言的统一接口. windows,Linux,Unix上均可兼容. OpenGL ES 是在OpenGL嵌入式设备上的版本, android/iOS ...

  2. Android OpenGL 入门示例----绘制三角形和正方形

    Android上对OpenGl的支持是无缝的,所以才有众多3D效果如此逼真的游戏,在Camera的一些流程中也有用到GLSurfaceView的情况.本文记录OpenGL在Android上的入门级示例 ...

  3. Linux OpenGL 实践篇-4 坐标系统

    OpenGL中顶点经过顶点着色器后会变为标准设备坐标系.标准设备坐标系的各坐标的取值范围是[-1,1],超过这个范围的点将会被剔除.而这个变换的过程可描述为顶点在几个坐标系统的变换,这几个坐标系统为: ...

  4. Linux OpenGL 实践篇-16 文本绘制

    文本绘制 本文主要射击Freetype的入门理解和在OpenGL中实现文字的渲染. freetype freetype的官网,本文大部分内容参考https://www.freetype.org/fre ...

  5. Linux OpenGL 实践篇-14-多实例渲染

    多实例渲染 OpenGL的多实例渲染是一种连续执行多条相同的渲染命令的方法,并且每条命令产生的结果都有轻微的差异,通常用于渲染大量的几何物体. 设想一个场景,比如太空,我们需要渲染数以万记的星球,如果 ...

  6. Linux OpenGL 实践篇-13-geometryshader

    几何着色器 几何着色器是位于图元装配和片元着色器之前的一个着色器阶段,是一个可选阶段.它的输入是一个图元的完整的顶点信息,通常来自于顶点着色器,但如果细分计算着色器启用的话,那输入则是细分计算着色器的 ...

  7. Linux OpenGL 实践篇-5 纹理

    纹理 在之前的实践中,我们所渲染的物体的表面颜色都是纯色或者根据顶点位置计算出的一个颜色,这种方式在表现物体细节方面是比较吃资源的,因为我们每增加一个细节,我们就需要定义更多的顶点及其属性.所以美术人 ...

  8. Linux OpenGL 实践篇-2 创建一个窗口

    OpenGL 作为一个图形接口,并没有包含窗口的相关内容,但OpenGL使用必须依赖窗口,即必须在窗口中绘制.这就要求我们必须了解一种窗口系统,但不同的操作系统提供的创建窗口的API都不相同,如果我们 ...

  9. Linux OpenGL 实践篇-11-shadow

    OpenGL 阴影 在三维场景中,为了使场景看起来更加的真实,通常需要为其添加阴影,OpenGL可以使用很多种技术实现阴影,其中有一种非常经典的实现是使用一种叫阴影贴图的实现,在本节中我们将使用阴影贴 ...

随机推荐

  1. 浅析Python多线程

    学习Python多线程的资料很多,吐槽Python多线程的博客也不少.本文主要介绍Python多线程实际应用,且假设读者已经了解多线程的基本概念.如果读者对进程线程概念不甚了解,可参见知名博主 阮一峰 ...

  2. Java的LockSupport工具,Condition接口和ConditionObject

    在之前我们文章(关于多线程编程基础和同步器),我们就接触到了LockSupport工具和Condition接口,之前使用LockSupport工具来唤醒阻塞的线程,使用Condition接口来实现线程 ...

  3. 多目标跟踪(MOT)评测标准

    MOT16是多目标跟踪领域非常有名的评测数据集,Ref 1详细阐述了这个数据集的组成以及评测标准(及其评测代码),Ref 2详细地解释了许多标准的由来和考虑,本部分主要介绍MOT任务中常用的评测标准. ...

  4. Beta第二天

    听说

  5. 201621123040《Java程序设计》第十四周学习总结

    1.本周学习总结 1.1以你喜欢的方式(思维导图或其他)归纳总结与数据库相关内容. 显示所有数据库: show databases; 创建数据库: create database test; 删除数据 ...

  6. 201621123043 《Java程序设计》第1周学习总结

    1. 本章学习总结 Jdk的安装: eclipse的基本使用方法 Java发展史 jdk.jre.jvm 关键词之间的联系:是整个java的核心,包括了一堆java.java基础的类库.java运行环 ...

  7. wpf研究之道——datagrid控件数据绑定

    前台: <DataGrid x:Name="TestCaseDataGrid" ItemsSource="{Binding}" > {binding ...

  8. django报错Manager isn't accessible via UserInfo instances

    出现这种错误是因为调用模型对象时使用了变量名,而不是对象名(模型类),例如: user = UserInfo()user_li = user.objects.filter(uname=username ...

  9. 验证码进阶(TensorFlow--基于卷积神经网络的验证码识别)

    本人的第一个深度学习实战项目,参考了网络上诸多牛人的代码,在此谢过,因时间久已,不记出处,就不一一列出,罪过罪过. 我的数据集是我用脚本在网页上扒的,标签是用之前写的验证码识别方法打的.大概用了400 ...

  10. 使用freemaker 导出word 含多张图片,若无图片则显示文本信息

    1.使用的Microsoft Office 2007,添加一个无边框的表格,并插入一张图片,最后另存为编码utf-8,一开始保存的word xml格式的,图片的base64编码位于文档最后,暂时没有找 ...