opengl es和opengl,opengl和opengl es的区别

  opengl es和opengl,opengl和opengl es的区别

  前言主要介绍什么是VBO/VAO,为什么需要使用它,以及如何使用VBO和VAO。

  VBO VBO是什么

  o(顶点缓冲对象):顶点缓冲对象。它是在显卡的存储空间中开辟的一个区域,在显卡的存储空间中开辟的一个区域用来存储顶点的各种属性信息。如顶点坐标、纹理坐标、顶点颜色等数据。渲染时,直接从显式VBO获取数据,无需与CPU交换数据。

  为什么你需要用VBO?

  将顶点数据保存在内存中。在调用glDrawArrays或glDrawElements等绘图方法之前,需要调用相应的方法将数据送入显存,导致I/O开销大,性能差。如果使用顶点缓冲对象来存储顶点数据,就不需要在每次绘制之前将顶点数据复制到显存中,而是在初始化顶点缓冲对象时将顶点数据发送到显存中一次,每次绘制都直接使用显存中的数据,这样可以大大提高绘制性能。

  如何使用VBO

  使用函数glGenBuffers和一个缓冲区ID生成一个VBO对象:unsigned int VBO;

  glGenBuffers(1,VBO);函数glBindBuffer用于绑定顶点缓冲对象,缓冲类型为GL_ARRAY_BUFFER。OpenGL有很多类型的缓冲对象,顶点缓冲对象的缓冲类型是GL _ array _ buffer。

  glBindBuffer(GL_ARRAY_BUFFER,VBO);使用函数glBufferData将定义的顶点数据复制到缓冲内存://vertices表示顶点数组。

  glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL _ STATIC _ DRAW);GlBufferData是一个专门用于将用户定义的数据复制到当前绑定缓冲区的函数。它的第一个参数是目标缓冲区的类型,其中VBO代表yes GL_ARRAY_BUFFER。第二个参数指定传输数据的大小(以字节为单位)。只需用一个简单的sizeof计算顶点数据大小。第三个参数是我们想要发送的实际数据。第四个参数指定我们希望图形卡如何管理给定的数据。它有三种形式:

  GL_STATIC_DRAW:数据不会或几乎不会改变。

  GL_DYNAMIC_DRAW:数据会有很大变化。

  GL_STREAM_DRAW:每次绘制时数据都会发生变化。

  位置数据一般不会改变,每次调用渲染都会保持不变,所以它的使用类型一般是GL_STATIC_DRAW。如果一个缓冲区中的数据会经常变化,那么使用的类型就是GL_DYNAMIC_DRAW或者GL_STREAM_DRAW,保证显卡把数据放在可以高速写入的内存部分。

  使用glDeleteBuffers函数后,删除缓冲区。今天我们以之前画四边形的练习为例,用VBO画四边形:在Opengl ES中画四边形。

  我们的目标是灵活运用Opengl绘制一个蓝色的四边形。

  这里就不多说普通画图了。可以看看后续的代码,或者回顾一下之前的四边形绘制的文章。在这里,我主要介绍一下VBO的两种绘画方法:

  首先,它们使用相同的顶点着色器和片段着色器,两者都是:

  //顶点着色器

  静态常量char *ver=#version 300 es\n

  在vec4 aColor中;\n

  在vec4位置;\n

  out vec4 vColor\n

  void main() {\n

  vColor=aColor\n

  gl _ Position=aPosition\n

  };

  //片段着色器

  静态常量char *fragment=#version 300 es\n

  精密中间浮动;\n

  在vec4 vColor中;\n

  out vec4 fragColor\n

  void main() {\n

  fragColor=vColor\n

  };顶点坐标和颜色值坐标是分开的(数组结构)。首先看顶点数据和颜色数据:

  //用画两个三角形的形式组成一个矩形(三角带)

  //第一、二、三点构成三角形,第二、三、四点构成三角形。

  const static GLfloat顶点[]={

  0.5f,-0.5f,//右下方

  0.5f,0.5f,//右上

  -0.5f,-0.5f,//左下方

  -0.5f,0.5f,//左上

  };

  //vbo颜色

  const static GL float COLOR _ ICES[]={

  0.0f,0.0f,1.0f,1.0f

  0.0f,0.0f,1.0f,1.0f

  0.0f,0.0f,1.0f,1.0f

  0.0f,0.0f,1.0f,1.0f

  };O vb数据和绑定:

  //vbo

  glGenBuffers(3,vbo);

  glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);

  glBufferData(GL_ARRAY_BUFFER,sizeof(VERTICES),VERTICES,GL _ STATIC _ DRAW);

  //颜色

  glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);

  glBufferData(GL_ARRAY_BUFFER,sizeof(COLOR_ICES),COLOR_ICES,GL _ STATIC _ DRAW);主要图纸代码:

  //使用VBO绘制,顶点与颜色分开

  //glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);

  //glvertexattributepointer(position handle,2,GL_FLOAT,GL_FALSE,0,(void *)0);

  ////启用顶点数据

  //glEnableVertexAttribArray(position handle);

  //

  //glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);

  //glvertexattributepointer(color handle,4,GL_FLOAT,GL_FALSE,0,(void *)0);

  ////启用颜色顶点数据

  //glEnableVertexAttribArray(color handle);

  ////取消绑定

  //glBindBuffer(GL_ARRAY_BUFFER,0);顶点的坐标和颜色值的坐标结合的方式(结构数组)顶点数据和颜色数据混合混淆;

  const static GL float VERTICES _ AND _ COLOR[]={

  0.5f,-0.5f,//右下方

  //颜色

  0.0f,0.0f,1.0f,1.0f

  0.5f,0.5f,//右上

  //颜色

  0.0f,0.0f,1.0f,1.0f

  -0.5f,-0.5f,//左下方

  //颜色

  0.0f,0.0f,1.0f,1.0f

  -0.5f,0.5f,//左上

  //颜色

  0.0f,0.0f,1.0f,1.0f

  };O vbdata绑定:

  //vbo

  glGenBuffers(3,vbo);

  glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);

  glBufferData(GL_ARRAY_BUFFER,sizeof(VERTICES),VERTICES,GL _ STATIC _ DRAW);

  //颜色

  glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);

  glBufferData(GL_ARRAY_BUFFER,sizeof(COLOR_ICES),COLOR_ICES,GL _ STATIC _ DRAW);

  //顶点混色,先顶点坐标,再颜色坐标。

  glBindBuffer(GL_ARRAY_BUFFER,vbo[2]);

  glBufferData(GL_ARRAY_BUFFER,sizeof(VERTICES_AND_COLOR),VERTICES_AND_COLOR

  ,GL _ STATIC _ DRAW);主要图纸代码:

  //VBO绘制顶点坐标和颜色坐标

  //glBindBuffer(GL_ARRAY_BUFFER,vbo[2]);

  ////跨步,每个顶点坐标由6个数据点分隔,数据类型为float。

  //glvertexattributepointer(position handle,2,GL_FLOAT,GL_FALSE,6 * sizeof(float),(void *)0);

  ////启用顶点数据

  //glEnableVertexAttribArray(position handle);

  ////步幅步长每个颜色坐标由6个数据点分隔。数据类型为float,颜色坐标索引从2开始。

  //glvertexattributepointer(color handle,4,GL_FLOAT,GL_FALSE,6 * sizeof(float),(void *)(2 * sizeof(FLOAT)));

  ////启用颜色顶点数据

  //glEnableVertexAttribArray(color handle);

  ////取消绑定

  //glBindBuffer(GL_ARRAY_BUFFER,0);他们的运行结果都是成功的画出了一个蓝色的四边形:

  在性能方面,我们使用了多种不同的组合来绘制四边形,包括将顶点坐标和颜色坐标分别写在两个不同的数组中,或者将顶点坐标和颜色坐标写在同一个数组中,然后通过控制stride和offset (*pointer)的参数进行绘制。这两种方法哪个性能更好?

  其中,将不同数组中的各种顶点坐标分开的写入方法成为数组结构,而将各种顶点坐标组合成一个数组的写入方法也称为结构化数组。在《OPENGL ES 3.0编程指南》这本书里,作者指出结构化数组的写性能更好。

  大多数情况下,答案是结构数组。

  原因是可以顺序读取每个顶点的属性数据,这最有可能造成高效的内存访问模式。

  VAO VAO是什么

  o(顶点数组对象):顶点数组对象。

  注意:VAO是OpenGL ES 3.0之后推出的新功能,所以在使用VAO之前需要确定OpenGL ES的版本是否在3.0之后。

  顶点数组对象可以像顶点缓冲区对象一样绑定,任何后续的顶点属性调用都将存储在这个VAO中。这样做的好处是,在配置顶点属性指针时,只需要执行那些调用一次,然后在绘制对象时只需要绑定相应的VAO。这使得在不同的顶点数据和属性配置之间切换非常简单,只需绑定不同的vao。刚刚设置的所有状态都将存储在VAO中。

  顶点数组对象存储以下内容:

  对GlenVertexattribarray和glEnableVertexAttribArray的调用。配置由glVertexAttribPointer设置的顶点属性。通过glVertexAttribPointer调用与顶点属性关联的顶点缓冲区对象。在上面VBO的介绍中,我们知道每次绘制都需要频繁绑定和解除绑定VBO,并且每次绘制都需要在渲染前拿出VBO的数据进行赋值。当数据量很大时,重复这些操作会很繁琐。这个过程可以被VAO简化,所以VAO可以简单理解为VBO的管理者,避免了画框时对VBO的人工操纵,VAO也不能单独使用。

  它需要和VBO一起使用。

  对于GPU来说,VBO就是一堆数据,但是如何解析和使用这堆数据,需要glEnableVertexAttribArray等相关函数在每次绘制的时候告诉GPU,所以VAO的作用就是简化这个过程。只需要在初始化时将这些解析逻辑与VAO绑定一次。

  然后每次画图只需要绑定对应的VAO,而不是每次都绑定VBO,然后告诉GPU如何解析相关数据。可以说是一次性能优化。

  如何使用VAO

  首先,调用函数glGenVertexArrays来生成无符号int VAO;

  glGenVertexArrays(1,VAO);调用函数glBindVertexArray绑定vaogbindvertexarray(VAO);

  //管理VBO,让VAO记住VBO的数据是如何解析和使用的。

  glBindBuffer(GL_ARRAY_BUFFER,VBO);

  glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL _ STATIC _ DRAW);

  //3.设置顶点属性指针

  glvertexattributepointer(0,3,GL_FLOAT,GL_FALSE,3 * sizeof(float),(void *)0);

  glEnableVertexAttribArray(0);

  glBindVertexArray(0);然后在绘图时使用函数glBindVertexArray(VAO)。

  退出时,通过函数glDeleteVertexArrays删除VAOglDeleteVertexArrays的主绑定代码:

  //VAO

  glGenVertexArrays(1,vao);

  glBindVertexArray(vao);

  //VAO与VBO联系在一起

  glBindBuffer(GL_ARRAY_BUFFER,vbo[2]);

  //跨步,每个顶点坐标用6个数据点隔开,数据类型为float。

  glvertexattributepointer(position handle,2,GL_FLOAT,GL_FALSE,6 * sizeof(float),(void *)0);

  //启用顶点数据

  glEnableVertexAttribArray(position handle);

  //步幅步长每个颜色坐标由6个数据点分隔,数据类型为float,颜色坐标索引从2开始。

  glvertexattributepointer(color handle,4,GL_FLOAT,GL_FALSE,6 * sizeof(float),(void *)(2 * sizeof(FLOAT)));

  //启用颜色顶点数据

  glEnableVertexAttribArray(color handle);

  //解除绑定

  glBindBuffer(GL_ARRAY_BUFFER,0);

  glBindVertexArray(0);使用的主要图纸代码:

  //VBO和VAO被画在一起。

  //使用vao

  glBindVertexArray(vao);

  //4个顶点绘制两个三角形形成一个矩形

  glDrawArrays(GL_TRIANGLE_STRIP,0,4);

  glUseProgram(0);

  //vao解除绑定

  glBindVertexArray(vao);以下是完整的代码:

  VBOVAOOpengl.h

  静态常数int NUM _ VBO=3;

  VBOVAOOpengl类:public BaseOpengl{

  公共:

  VBOVAOOpengl();

  virtual ~ VBOVAOOpengl();

  虚拟void onDraw();

  私人:

  闪烁位置句柄{-1 };

  闪烁color handle {-1 };

  Glu int vbo[NUM _ VBO];

  Glu int vao { 0 };

  };VBOVAOOpengl.cpp

  //顶点着色器

  静态常量char *ver=#version 300 es\n

  在vec4 aColor中;\n

  在vec4位置;\n

  out vec4 vColor\n

  void main() {\n

  vColor=aColor\n

  gl _ Position=aPosition\n

  };

  //片段着色器

  静态常量char *fragment=#version 300 es\n

  精密中间浮动;\n

  在vec4 vColor中;\n

  out vec4 fragColor\n

  void main() {\n

  fragColor=vColor\n

  };

  //用画两个三角形的形式组成一个矩形(三角带)

  //第一、二、三点构成三角形,第二、三、四点构成三角形。

  const static GLfloat顶点[]={

  0.5f,-0.5f,//右下方

  0.5f,0.5f,//右上

  -0.5f,-0.5f,//左下方

  -0.5f,0.5f,//左上

  };

  const static GL float VERTICES _ AND _ COLOR[]={

  0.5f,-0.5f,//右下方

  //颜色

  0.0f,0.0f,1.0f,1.0f

  0.5f,0.5f,//右上

  //颜色

  0.0f,0.0f,1.0f,1.0f

  -0.5f,-0.5f,//左下方

  //颜色

  0.0f,0.0f,1.0f,1.0f

  -0.5f,0.5f,//左上

  //颜色

  0.0f,0.0f,1.0f,1.0f

  };

  //rgba

  //const static GL float COLOR _ ICES[]={

  //0.0f,0.0f,1.0f,1.0f

  //};

  //vbo颜色

  const static GL float COLOR _ ICES[]={

  0.0f,0.0f,1.0f,1.0f

  0.0f,0.0f,1.0f,1.0f

  0.0f,0.0f,1.0f,1.0f

  0.0f,0.0f,1.0f,1.0f

  };

  VBOVAOOpengl:VBOVAOOpengl() {

  initGlProgram(ver,fragment);

  position handle=glgetattributelocation(程序,一个位置);

  color handle=glgetattributelocation(program, aColor );

  //vbo

  glGenBuffers(3,vbo);

  glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);

  glBufferData(GL_ARRAY_BUFFER,sizeof(VERTICES),VERTICES,GL _ STATIC _ DRAW);

  //颜色

  glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);

  glBufferData(GL_ARRAY_BUFFER,sizeof(COLOR_ICES),COLOR_ICES,GL _ STATIC _ DRAW);

  //顶点与颜色混合,先顶点坐标,再颜色坐标

  glBindBuffer(GL_ARRAY_BUFFER,vbo[2]);

  glBufferData(GL_ARRAY_BUFFER,sizeof(VERTICES_AND_COLOR),VERTICES_AND_COLOR

  ,GL _ STATIC _ DRAW);

  glBindBuffer(GL_ARRAY_BUFFER,0);

  //VAO

  glGenVertexArrays(1,vao);

  glBindVertexArray(vao);

  //VAO与电压关联

  glBindBuffer(GL_ARRAY_BUFFER,vbo[2]);

  //步幅步长每个顶点坐标之间相隔6个数据点,数据类型是漂浮物

  glvertexattributepointer(位置句柄,2,GL_FLOAT,GL_FALSE,6 * sizeof(float),(void *)0);

  //启用顶点数据

  glEnableVertexAttribArray(位置句柄);

  //步幅步长每个颜色坐标之间相隔6个数据点,数据类型是浮动,颜色坐标索引从2开始

  glvertexattributepointer(颜色句柄,4,GL_FLOAT,GL_FALSE,6 * sizeof(float),(void *)(2 * sizeof(FLOAT)));

  //启用颜色顶点数据

  glEnableVertexAttribArray(彩色手柄);

  //解除绑定

  glBindBuffer(GL_ARRAY_BUFFER,0);

  glBindVertexArray(0);

  LOGD(’程序:%d ,程序);

  LOGD(’位置句柄:%d ,位置句柄);

  LOGD(colorHandle:%d ,颜色句柄);

  }

  void VBOVAOOpengl:onDraw() {

  //清屏

  glClearColor(0.0f,1.0f,0.0f,1.0f);

  GL清零(GL _ COLOR _ BUFFER _ BIT);

  葡萄糖程序(程序);

  //普通方式绘制

  ///**

  //*大小几个数字表示一个点,显示是两个数字表示一个点

  //*正常化是否需要归一化,不用,这里已经归一化了

  //*步幅步长,连续顶点之间的间隔,如果顶点直接是连续的,也可填0

  //*/

  //glvertexattributepointer(位置句柄,2,GL_FLOAT,GL_FALSE,0,顶点);

  ////启用顶点数据

  //glEnableVertexAttribArray(位置句柄);

  //

  ////这个不需要glEnableVertexAttribArray

  //glvertexattrib 4 Fv(颜色句柄,COLOR _ ICES);

  //############################################# 分割线#################################

  //使用电压的方式绘制,顶点与颜色分开

  ///**

  //glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);

  //glvertexattributepointer(位置句柄,2,GL_FLOAT,GL_FALSE,0,(void *)0);

  ////启用顶点数据

  //glEnableVertexAttribArray(位置句柄);

  //

  //glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);

  //glvertexattributepointer(颜色句柄,4,GL_FLOAT,GL_FALSE,0,(void *)0);

  ////启用颜色顶点数据

  //glEnableVertexAttribArray(颜色句柄);

  ////解除绑定

  //glBindBuffer(GL_ARRAY_BUFFER,0);

  //############################################# 分割线#################################

  //VBO绘制顶点坐标与颜色坐标一起

  //glBindBuffer(GL_ARRAY_BUFFER,vbo[2]);

  ////步幅步长每个顶点坐标之间相隔6个数据点,数据类型是漂浮物

  //glvertexattributepointer(位置句柄,2,GL_FLOAT,GL_FALSE,6 * sizeof(float),(void *)0);

  ////启用顶点数据

  //glEnableVertexAttribArray(位置句柄);

  ////步幅步长每个颜色坐标之间相隔6个数据点,数据类型是浮动,颜色坐标索引从2开始

  //glvertexattributepointer(颜色句柄,4,GL_FLOAT,GL_FALSE,6 * sizeof(float),(void *)(2 * sizeof(FLOAT)));

  ////启用颜色顶点数据

  //glEnableVertexAttribArray(颜色句柄);

  ////解除绑定

  //glBindBuffer(GL_ARRAY_BUFFER,0);

  //############################################# 分割线#################################

  //VBO与顶点数组对象配合绘制

  //使用顶点数组对象

  glBindVertexArray(vao);

  //4个顶点绘制两个三角形形成一个矩形

  glDrawArrays(GL_TRIANGLE_STRIP,0,4);

  glUseProgram(0);

  //vao解除绑定

  glBindVertexArray(vao);

  //禁用顶点

  glDisableVertexAttribArray(position handle);

  if(nullptr!=eglHelper){

  egl helper-swap buffers();

  }

  }

  VBOVAOOpengl:~ VBOVAOOpengl()no except {

  glDeleteBuffers(NUM_VBO,vbo);

  glDeleteVertexArrays(1,vao);

  }之前的注释Opengl ES的EGL环境Opengl ES的构建着色器

  Opengl ES的三角形绘制

  Opengl ES的四边形绘制

  Opengl ES的纹理映射

  关注我,共同进步,生活不止编码!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: