游戏开发/渲染与游戏引擎/OpenGL/绘制几何体
外观
这是将三角形的顶点数据传递给 OpenGL 的方法。
数据在一个数组中指定,每三个顶点表示一个新的三角形。在此格式中,需要按照连接的顺序指定数据。
#include <gl\glew.h>
#include <MyGLWindow.h>
void MyGLWindow::initializeGL(){
GLfloat verts[] =
{
//1st Triangle
+0.0f, +1.0f, +0.0f, //Vertex 1
-1.0f, -1.0f, -0.5f, //Vertex 2
+1.0f, -1.0f, +0.5f, //Vertex 3
//2nd Triangle
+0.0f, -1.0f, +0.0f, //Vertex 1
-1.0f, +1.0f, -0.5f, //Vertex 2
+1.0f, +1.0f, +0.5f, //Vertex 3
};
GLuint myBufferID;
glGenBuffers(1, &myBufferID); //Generate an identifier for the buffer ID
glBindBuffer(GL_ARRAY_BUFFER, myBufferID); //Bind it to the array buffer binding point
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); //Send the size of the data and the data to the buffer assigned to the array buffer binding point.
//Describing the data
glEnableVertexAttribArray(0); //The first attribute to send to openGL (later redirected through a vertex shader)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0); //There are 3 floats per vertex...
}
void MyGLWindow::paintGL(){
glViewport(0, 0, width(), height()); //Fixes the resizing to change ratio of triangle
glDrawArrays(GL_TRIANGLES, 0, 6); //Connect the 6 vertices into triangles (triangle=3, 6/3 = 2 triangles)
}
这段代码很容易修改为只传递 2D 数据,为此你需要更改两件事。
- 数组应该只包含 X 和 Y 坐标。
- glVertexAttribPointer 参数 2 需要从 3 更改为 2。
此程序的新版本传递顶点位置的 ID,以说明如何连接三角形。对于没有连接的基本三角形,这比之前效率低,但是对于大多数形状,三角形将共享顶点,这意味着你不需要指定 3 个数据(XYZ,如果添加颜色和光照法线则更多),只需要传递一个额外的短整型作为顶点索引。这样可以节省内存,因为需要更少的数据,并且对于动画几何体,这意味着需要发送到 OpenGL 及更远端的数据副本更少。
#include <gl\glew.h>
#include <MyGLWindow.h>
void MyGLWindow::initializeGL(){
GLfloat verts[] =
{
//1st Triangle
+0.0f, +1.0f, +0.0f, //Vertex 1
-1.0f, -1.0f, -0.5f, //Vertex 2
+1.0f, -1.0f, +0.5f, //Vertex 3
//2nd Triangle
+0.0f, -1.0f, +0.0f, //Vertex 1
-1.0f, +1.0f, -0.5f, //Vertex 2
+1.0f, +1.0f, +0.5f, //Vertex 3
};
GLuint myBufferID;
glGenBuffers(1, &myBufferID); //Num buffers, BufferID
glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
//Assigning the positions of the vertices into 2 triangle (triangle 1= {0,1,2}, triangle 2={3,4,5})
GLushort indices[] = {0,1,2, 3,4,5};
GLuint indexBufferID;
glGenBuffers(1, &indexBufferID); //Generate an identifier for the index buffer ID
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID); //Link the index buffer to the element array buffer binding point
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); //Send the size of the data and the data to the index buffer, linked to the element array buffer binding point.
//Describing the data
glEnableVertexAttribArray(0); //The first attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0); A vertex consists of 3 floats
}
void MyGLWindow::paintGL(){
glViewport(0, 0, width(), height()); //Fixes the resizing to change ratio of triangle
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0); //Notice this is different from above
}
注意:在设置片段着色器之前,颜色不会生效。但是,要设置片段着色器,你需要从顶点着色器发送颜色数据。
#include <gl\glew.h>
#include <MyGLWindow.h>
void MyGLWindow::initializeGL(){
GLfloat verts[] =
{
//One colourful triangle being drawn
+0.0f, +1.0f, +0.0f, //Vertex 1
+1.0f, +0.0f, +0.0f, //Vertex 1's Color (Red)
-1.0f, -1.0f, -0.5f, //Vertex 2
+0.0f, +1.0f, +0.0f, //Vertex 2's Color (Green)
+1.0f, -1.0f, +0.5f, //Vertex 3
+0.0f, +0.0f, +1.0f, //Vertex 3's Color (Blue)
};
GLuint myBufferID;
glGenBuffers(1, &myBufferID); //Num buffers, BufferID
glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
GLushort indices[] = {0,1,2};
GLuint indexBufferID;
glGenBuffers(1, &indexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//Describing the data
glEnableVertexAttribArray(0); //The first attribute (Vertex data)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) *6,0); //There are 6 floats worth of data from the start of one list of vertices and the next set of vertices
glEnableVertexAttribArray(1); //The second attribute (Color data)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) *6, (char*)(sizeof(float)*3)); //There are 6 floats worth of data from the start of one list of vertices and the next set of vertices. The first piece of data starts after 3 floats.
}
void MyGLWindow::paintGL(){
glViewport(0, 0, width(), height()); //Fixes the resizing to change ratio of triangle
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
}