• OpenGL VAO, VBO 使用简介


    参照代码样例:

     1 // This function takes in a vertex, color, index and type array 
     2 // And does the initialization for an object.  
     3 // The partner function below it draws the object 
     4 void initobject(GLuint object, GLfloat * vert, GLint sizevert, GLfloat * col, GLint sizecol, GLubyte * inds, GLint sizeind, GLenum type){
     5     int offset = object * numperobj;
     6     // make the new GL_ARRAY_BUFFER active
     7     // 将VAO绑定到当前的context上
     8     glBindVertexArray(VAOs[object]);
     9 
    10 
    11     // 将颜色数据绑定到VBO上
    12     glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors+offset]) ; 
    13     glBufferData(GL_ARRAY_BUFFER, sizecol, col,GL_STATIC_DRAW);
    14     // 用于关联 shader (location = 1) color
    15     glEnableVertexAttribArray(1);
    16     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
    17 
    18 
    19     // 将顶点数据绑定到VBO上20     // 将这个buffer关联到 GL_ARRAY_BUFFER
    21     glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices+offset]);
    22     // 将数据传送到这个buffer 
    23     glBufferData(GL_ARRAY_BUFFER, sizevert, vert,GL_STATIC_DRAW);
    24     // 用于关联 shader (location = 0) vertex
    25     glEnableVertexAttribArray(0);
    27     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
    28 
    29    // 将三角形序列绑定到VBO上
    30     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[Elements+offset]) ; 
    31     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeind, inds,GL_STATIC_DRAW);
    32     PrimType[object] = type;
    33     NumElems[object] = sizeind;
    34     // Prevent further modification of this VAO by unbinding it
    35     glBindVertexArray(0);
    36 }
    37 
    38 void drawobject(GLuint object) {
    39     glBindVertexArray(VAOs[object]);
    40     glDrawElements(PrimType[object], NumElems[object], GL_UNSIGNED_BYTE, 0); 
    41     glBindVertexArray(0);
    42 }

    程序的部分相关初始化代码:

     1 // Now create the buffer objects to be used in the scene later
     2 // Remember to delete all the VAOs and VBOs when the program terminates!
     3 glGenVertexArrays(numobjects, VAOs);
     4 glGenBuffers(numperobj*numobjects, buffers);
     5 
     6 // Initialize the floors
     7 initobject(FLOOR, (GLfloat *) floorverts, sizeof(floorverts), (GLfloat *) floorcol, sizeof (floorcol), (GLubyte *) floorinds, sizeof (floorinds), GL_TRIANGLES) ; 
     8 initobject(FLOOR2, (GLfloat *) floorverts2, sizeof(floorverts2), (GLfloat *) floorcol2, sizeof (floorcol2), (GLubyte *) floorinds2, sizeof (floorinds2), GL_TRIANGLES) ;
     9 

    vertex shader

     1 # version 330 core
     2 // Do not modify the above version directive to anything older than 330, as
     3 // modern OpenGL will not work properly due to it not being core at the time.
     4 
     5 // Shader inputs
     6 layout (location = 0) in vec3 position;
     7 layout (location = 1) in vec3 color;
     8 
     9 // Shader outputs, if any
    10 out vec3 Color;
    11 
    12 // Uniform variables
    13 uniform mat4 modelview;
    14 uniform mat4 projection;
    15 
    16 void main() {
    17     gl_Position = projection * modelview * vec4(position, 1.0f);
    18     Color = color; // Just forward this color to the fragment shader
    19 }

    OpenGL有着许多令人捉摸不着的概念,其中比较重要的便是Vertex Array Object 以及 Vertex Buffer Object。为了理解这两个概念,还需要注意另一个叫做context(上下文)的概念,因为OpenGL用C写的,没有C++那种面向对象的特性,因此在遇到涉及状态保存的时候(比如为当前物体(而不是其他什么物体)赋值),就需要用context来储存临时状态(比如“我现在编辑的对象是物体1,而不是物体2”)。

    牢记context这个概念的存在,让我们看看如何使用代码创建一个物体并显示。

    1. 创建物体

    先看initobject函数(见上文),可以看到函数内部代码大致分成了4块,我们分别解释。

    代码就不重复复制了。

    offset那个变量不用管,那个是用于区分当前初始化的是第一个物体还是第二个物体的,你们可以默认这个程序只有一个物体然后忽视掉代码中的所有offset。

    (1). 将VAO绑定到context

    可以简单的将VAO理解为一个我们将要显示的物体。这个物体有许多属性,比如所有顶点,颜色,三角形的顶点序列。而这些属性都又由VBO来表示。

    将其绑定到context这一动作表示:我接下来操作的对象都是1号物体了。

    (2). 将颜色绑定到VBO上

    glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors+offset]) ; 
    glBufferData(GL_ARRAY_BUFFER, sizecol, col, GL_STATIC_DRAW);

    这两行代码应该一起使用,可以将其作用理解为:将col这个数组的数据绑定到buffers[colors] (此处忽略了offset)

    也就是说,我们将颜色数据连接到一个VBO上,这样以后OpenGL便可以通过这个VBO读取这个颜色数据。

    由于我们需要在shader中访问颜色数据,因此我们还需要将其暴露给shader,通过以下代码。

    // 用于关联 shader (location = 1) color
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);

    以上代码说明shader中的 1 号(可以是任何未使用过的数字) location 处的数据将是我们刚刚绑定的颜色信息

    (3). 将顶点绑定到VBO上

    这一步与绑定颜色的做法重复,先是将我们的顶点数据绑定到一个VBO,然后将其暴露给shader的0号位置。

    (4). 将三角形序列绑定到VBO

    这里就不解释三角形序列是什么了,这个名字我可能叫错了。。。总之这个数据定义了那些顶点用来组成三角形。

    绑定的过程与上面一样,不过由于shader中并不需要这个数据,因此我们不用将其暴露给shader


    2. 显示物体

    创建完物体,我们可以显示出来了

    在丢给glutDisplayFunc的那个display函数中加上以下代码

    1 glBindVertexArray(VAOs[object]);
    2 glDrawElements(PrimType[object], NumElems[object], GL_UNSIGNED_BYTE, 0); 
    3 glBindVertexArray(0);

    第一行说明我们现在开始操作物体1

    第二行让OpenGL画出物体1(为什么不是物体2?因为我们上一步已经说明了现在的context是物体1)

    第三行解绑物体1

  • 相关阅读:
    关于STM32的bxcan模块中的Error management中的TEC和REC的值
    不同MCU的大小端(endian)分类
    vmware中虚拟机的网络连接设置
    ST的STM32系列单片机
    使用diskgenius进行分区的备份和恢复
    VMware虚拟机设置中的网络适配器设置
    js图片随鼠标移动,旋转,拉伸
    JDK1.8的Lambda、Stream和日期的使用详解
    MySQL Explain详解
    为什么我使用了索引,查询还是慢?
  • 原文地址:https://www.cnblogs.com/makejeffer/p/7820930.html
Copyright © 2020-2023  润新知