介绍
游戏角色的顶点,法线和UV坐标等数据被加载到称为Buffer对象的OpenGL对象中。有很多方法来加载这些数据。在本节中,你将了解可以加载这些数据所有可能的方式。
泰课在线

简单数据加载
首先,让我们加载一个简单的数组表示角色顶点位置。我们将创建一个单一的OpenGL缓冲区,将其绑定到GL_ARRAY_BUFFER并将顶点数据放入其中。一旦数据被加载,我们将它链接到着色器属性位置。
代码1:简单数据加载

//Vertex data of character
float vertexData[250]={1.0,0.4,0.9,1.0,....};
 
//1. Create a buffer
GLuint myBuffer;
 
glGenBuffers(1,&myBuffer);
 
//2. Bind a buffer
glBindBuffer(GL_ARRAY_BUFFER,myBuffer);
 
//3. Load data in the buffer
glBufferData(GL_ARRAY_BUFFER,sizeof(vertexData),vertexData,GL_STATIC_DRAW);
 
//4. Get the location of the shader attribute called "position"
 
GLuint positionLocation=glGetAttribLocation(programObject, "position");
 
//5. Get Location of uniforms called "modelViewProjectionMatrix"
 
modelViewProjectionUniformLocation = glGetUniformLocation(programObject,"modelViewProjectionMatrix");
 
//6. Enable the attribute location
glEnableVertexAttribArray(positionLocation);
 
//7. Link the buffer data to the shader attribute locations.
glVertexAttribPointer(positionLocation,3, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)0);

我们在加载数据之前所做的第一件事是创建一个缓冲区myBuffer,如第1行所示。缓冲区绑定到绑定点GL_ARRAY_BUFFER(第2行)。一旦绑定完成,我们能够将数据加载到myBuffer。这是通过使用OpenGL函数glBufferData来完成的,如第3行所示。
OpenGL函数glBufferData需要myBuffer的绑定点,需要加载的数据的大小和指向数据vertexData的指针。参数GL_STATIC_DRAW表示数据不会改变。
为了正确地在着色器中使用数据,我们需要获取在着色器中引用的属性位置的存储位置(第4行)。然后启用此位置,如第6行所示。启用后,我们可以将属性位置与vertexData数组中的数据链接。链接是通过使用函数glVertexAttribPointer建立的,如第7行所示。这个函数需要属性的位置,每个顶点的组成(在我们的例子中是3。即x,y和z),数据类型,是否normalization,stride的大小 和指向数据的第一个组成部分的指针。

 
加载交错数据

上面示例显示如何加载表示3D模型位置的简单数据数组。然而,很可能你还需要加载代表法线和uv坐标的数据。这些数据可以如下所示在characterData数组中交错。数组的前两个分量表示uv坐标。接下来的三个表示法线坐标,最后三个表示顶点位置。
代码2:加载交错数据

GLfloat characterData[192] =
    {
        // Data layout for each line below is:
        // UV1,UV2, Normal1, Normal2, Normal3, positionX, positionY, positionZ
        0.00000, 1.00000, 0.00000, 0.00000, 1.00000, -0.50000, -0.50000, 0.50000,
        0.00000, 0.00000, 0.00000, 0.00000, 1.00000, -0.50000, 0.50000, 0.50000...};
 
//1. Create a Vertex Buffer Object
 
GLuint myBuffer;
 
glGenBuffers(1, &myBuffer);
 
//2. Bind the Vertex Buffer Object
 
glBindBuffer(GL_ARRAY_BUFFER, myBuffer);
 
//3. Dump the data into the Buffer
 
glBufferData(GL_ARRAY_BUFFER, sizeof(characterData), characterData, GL_STATIC_DRAW);
 
//4. Get the location of the shader attribute called "position"
 
GLuint positionLocation=glGetAttribLocation(shaderProgram, "position");
 
//5. Get the location of the shader attribute called "normal"
 
GLuint normalLocation=glGetAttribLocation(shaderProgram, "normal");
 
//6. Get the location of the shader attribute called "texCoord"
 
GLuint textureLocation=glGetAttribLocation(shaderProgram, "texCoord");
 
//7. Get Location of the uniforms
modelViewProjectionUniformLocation = glGetUniformLocation(programObject,"modelViewProjectionMatrix");
 
//8. Enable attribute locations
 
glEnableVertexAttribArray(positionLocation);
 
glEnableVertexAttribArray(normalLocation);
 
glEnableVertexAttribArray(textureLocation);
 
//9. Link the buffer data to the shader attribute locations
 
glVertexAttribPointer(textureLocation, 2, GL_FLOAT, GL_FALSE, 32, BUFFER_OFFSET(0));
 
glVertexAttribPointer(normalLocation, 3, GL_FLOAT, GL_FALSE, 32, BUFFER_OFFSET(8));
 
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 32, BUFFER_OFFSET(20));

该过程基本上与代码1中所示的相同。第1-3行简单地创建一个OpenGL缓冲区并将数据加载到缓冲区中。第4,5和6行分别查询属性位置position,normal和textCoord。第8行启用这些属性位置。
第9行将characterData数组中的数据与属性位置相链接。函数glVertexAttribPointer的最后一个参数要求指向数组中组件的指针偏移量。
例如,uv坐标具有0的偏移,因为它是数组中的第一个组件。表示法线坐标的偏移量是sizeof(float)*(elementPosition)= sizeof(float)* 2 =8。顶点位置指针设置为20。因为 sizeof(float)*(elementPosition)= sizeof(float)* 5 =20。stride设置为32,因为32是属性在数组中重复的时候。

源代码
源代码 "Loading Interleaved data"。

使用glBufferSubData加载
你也可以在不同的数组中存储顶点,法线和uv数据。这些数据仍然可以通过使用函数glBufferSubData加载到同一个OpenGL缓冲区中。
过程是一样的。我们创建一个OpenGL缓冲区并绑定它,如代码3,第1和2行所示。但是,glBufferData中的参数不同,如第3行所示。缓冲区的大小是所有三个数组的大小之和,数据的参数指针设置为NULL(第3行)。
代码3:使用glBufferSubData加载

float position[250]={1.0,0.0,1.0,
                   0.0,1.0,0.0,
                   0.5,0.5,1.0,
                   0.5,0.0,0.4,....};
 
float normal[250]={1.0,0.0,1.0,
                   0.0,1.0,0.0,
                   0.5,0.5,1.0,
                   0.5,0.0,0.4,....};
 
float uv[250]={1.0,0.0,
               1.0,0.0,
               1.0,0.0,
                标签: OpenGL
0