本次实践是绘制两个三角形,重点理解顶点数组对象和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来输入数据,示例如下:

         glGenBuffers(NumBuffers,Buffers);
glBindBuffer(GL_ARRAY_BUFFER,Buffers[ArrayBuffer]);
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);基于索引绘制(即所有的顶点在一个数组中,使用索引来引用顶点数据)

具体的示例代码如下:

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdio.h>
#include "ShaderHelper.h" #define BUFFER_OFFSET(n) ((GLvoid*)n)
enum VAO_IDs { Triangles,NumVAOs};
enum Buffers_IDs { ArrayBuffer, NumBuffers }; enum Attrib_IDs { vPosition=0 }; GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers]; const GLuint NumVertices=6; void init();
void display(); int main(int argc,char* argv[])
{
glutInit(&argc,argv);
glutInitContextVersion(3,3);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(0,0);
glutInitWindowSize(300,300);
glutCreateWindow("Frame Buffer"); /* const GLubyte* name = glGetString(GL_VENDOR); //返回负责当前OpenGL实现厂商的名字
const GLubyte* biaoshifu = glGetString(GL_RENDERER); //返回一个渲染器标识符,通常是个硬>
件平台
const GLubyte* OpenGLVersion =glGetString(GL_VERSION); //返回当前OpenGL实现的版本号
const GLubyte* gluVersion= gluGetString(GLU_VERSION); //返回当前GLU工具库版本
printf("OpenGL实现厂商的名字:%s\n", name);
printf("渲染器标识符:%s\n", biaoshifu);
printf("OOpenGL实现的版本号:%s\n",OpenGLVersion );
printf("OGLU工具库版本:%s\n", gluVersion);*/
glewExperimental=GL_TRUE;
glewInit();
init();
glutDisplayFunc(display); glutMainLoop();
return 0;
} void init()
{
glClearColor(0.0,0.0,0.0,1.0);
glMatrixMode(GL_PROJECTION);
glOrtho(-5,5,-5,5,5,15);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0,0,10,0,0,0,0,1,0); glGenVertexArrays(NumVAOs,VAOs);
glBindVertexArray(VAOs[Triangles]); GLfloat vertices[NumVertices][2]={
{-0.90,-0.90},
{0.85, -0.90},
{ -0.90, 0.85 },
{ 0.90, -0.85 },
{ 0.90, 0.90 },
{-0.85, 0.90 },
}; glGenBuffers(NumBuffers,Buffers);
glBindBuffer(GL_ARRAY_BUFFER,Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW); ShaderInfo shaders[] = {
{GL_VERTEX_SHADER,"triangles.vert"},
{GL_FRAGMENT_SHADER,"triangles.frag"},
{GL_NONE,NULL},
}; GLuint program = LoadShaders(shaders);
glUseProgram(program); glVertexAttribPointer(vPosition,2,GL_FLOAT,GL_FALSE,0,BUFFER_OFFSET(0)); glEnableVertexAttribArray(vPosition);
} void display()
{
glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES,0,NumVertices); glFlush();
}

注意:代码根据红宝书编写,一些辅助性代码(如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. Redis 中的数据类型及基本操作

    Redis 内置的数据类型有 5种:字符串String.哈希Hash.列表List.集合Set.有序集合ZSet 字符串类型 String 是 Redis 中最基本的类型,一个 key 对应着一个 v ...

  2. 【treeview】 基于jQuery的简单树形插件

    [treeview] 效果图: 前几天想把后台的目录结构通过树形插件的方法反映到前端来,在网上搜了半天只找到了这个treeview,虽然不是很好看,不过还是够用的..用treeview的前提是要有jq ...

  3. 【Flask】 网站的用户管理

    网站用户管理 不知道为什么很多学习Flask的人都是从搭博客开始的(大概是因为那本书的案例是博客,同时对bootstrap支持良好,bootstrap又是twitter开发的吧..)既然是搭建博客,就 ...

  4. 大数据 --> 安装Hadoop-单机模式(1)

    安装Hadoop-单机模式(1) 一.在Ubuntu下创建hadoop组和hadoop用户 1)创建hadoop用户组 sudo addgroup hadoop //添加用户组 2)创建hadoop用 ...

  5. java各种概念 Core Java总结

    Base: OOA是什么?OOD是什么?OOP是什么?{ oo(object-oriented):基于对象概念,以对象为中心,以类和继承为构造机制,来认识,理解,刻画客观世界和设计,构建相应的软件系统 ...

  6. robotframework环境搭建问题

    启动的时候报错,应该是环境变量没有配置好 错误: command: pybot.bat --argumentfile c:\users\keikei\appdata\local\temp\RIDEam ...

  7. JS获得一个对象的所有属性和方法

    function displayProp(obj){ var names=""; for(var name in obj){ names+=name+": "+ ...

  8. Dom属性方法

    一.javascript的三大核心 1.ECMAScript js的语法标准 2.DOM Document object Model 文档对象模型,提供的方法可以让js操作html标签 3.BOM B ...

  9. C语言-学生博客汇总

    一.学生个人博客汇总 五班 学号 姓名 博客地址 4079 马天琦 http://www.cnblogs.com/simalang/ 4080 马宇欣 http://www.cnblogs.com/m ...

  10. edittext实现自动查询,刷新listview

    mEdittextqueryvalue.addTextChangedListener(new TextWatcher() {             @Override             pub ...