基于Qt的OpenGL编程(3.x以上GLSL可编程管线版)---(二十三)高级数据储存方法

Vries的教程是我看过的最好的可编程管线OpenGL教程,没有之一其原地址如下,https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/07%20Advanced%20Data/关于高级数据储存格式的详细知识了解请看原教程,本篇旨在对Vires基于visual studio平台的编程思想与c++代码做纯Qt平台的移植,代码移植顺序基本按照原教程顺序,并附加一些学习心得,重在记录自身学习之用

Tip1:这章内容很少,主要讲数据在缓存中的另一种储存与拷贝方法。

Tip2:Vries的分批顶点属性在实际应用中还比较常用,复制换冲真的是不好用。

程序源代码链接:https://pan.baidu.com/s/1vPQZvAyjqoqMhRZYI8VbrQ 提取码:28jg 

编译环境:Qt5.9.4

编译器:Desktop Qt5.9.4 MSVC2017 64bit

IDE:QtCreator

一. 分批顶点属性

    以往在传输数据时,我们总是使用glBufferData()函数将数据一次传进缓冲中,然后再绘制时,分批绑定至着色器的顶点属性中。如下所示。

  float vertices[] = {
    // positions        // textures        // normals
    //Back Face
    -0.5f, -0.5f, -0.5f,  0.0f,  0.0f,  0.0f,  0.0f, -1.0f, //bottom-left
     0.5f,  0.5f, -0.5f,  1.0f,  1.0f,  0.0f,  0.0f, -1.0f, //top-right
     0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f, -1.0f,
     0.5f,  0.5f, -0.5f,  1.0f,  1.0f,  0.0f,  0.0f, -1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f,  0.0f,  0.0f,  0.0f, -1.0f,
    -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, -1.0f,

            .......................... 
  } 

  core->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);



  /************ draw绘制 ****************/
  core->glBindBuffer(GL_ARRAY_BUFFER, VBO);
  core->glEnableVertexAttribArray(0);
  core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
  core->glEnableVertexAttribArray(1);
  core->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3*sizeof(float)));
  core->glEnableVertexAttribArray(2);
  core->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(5*sizeof(float)));
  core->glDrawArrays(GL_TRIANGLES, 0, 6);

  但这样的缓冲传输方式在特定条件下有弊端,比如只知道物体各个顶点的几何坐标,而不清楚面的法线坐标。在这种条件下,用vertices的数组传输方式会显得很笨重。所有有一个新的数据缓冲传输函数:

glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data)

    这个函数需要一个缓冲目标、一个偏移量、数据的大小和数据本身作为它的参数。这个函数不同的地方在于,我们可以提供一个偏移量,指定从何处开始填充这个缓冲。

    简单来说,上面的glBufferData()函数传输可以写成以下这种形式。

  float positions[] = {
//Back Face
  -0.5f, -0.5f, -0.5f,  //bottom-left
   0.5f,  0.5f, -0.5f,  //top-right
   0.5f, -0.5f, -0.5f,
   0.5f,  0.5f, -0.5f,
  -0.5f, -0.5f, -0.5f,
  -0.5f,  0.5f, -0.5f,

  .............  

  core->glGenBuffers(1, &VBO);

  core->glBindBuffer(GL_ARRAY_BUFFER, VBO);
  core->glBufferData(GL_ARRAY_BUFFER, sizeof(positions)+sizeof(textures)+sizeof(normals), NULL, GL_STATIC_DRAW);
  core->glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), positions);
  core->glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions), sizeof(textures), textures);
  core->glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions)+sizeof(textures), sizeof(normals), normals);
  core->glBindBuffer(GL_ARRAY_BUFFER, 0);




/************ draw绘制函数 *************/
  core->glBindBuffer(GL_ARRAY_BUFFER, VBO);
  core->glEnableVertexAttribArray(0);
  core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
  core->glEnableVertexAttribArray(1);
  core->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3*sizeof(float)));
  core->glEnableVertexAttribArray(2);
  core->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(5*sizeof(float)));

  core->glDrawArrays(GL_TRIANGLES, 0, 6);

  这样就很方便了。我可以轻松地将几何体的顶点坐标先传进缓冲,待计算法线后,再将法线传进缓冲。

  这里要注意:再使用glBufferSubData()函数之前,必须使用glBufferData()函数提前开辟内存!!!!!。

  程序仍然是这个程序,只是内部立方体的数据缓冲传输方式产生了变化。

猜你喜欢

转载自blog.csdn.net/z136411501/article/details/84349664