C++ Vbo如何绘制图元
嗨,我正在尝试使用本教程学习OpenGl 我想说的是,本教程不适合刚开始学习的人。他们展示了许多适用于1个三角形的代码,但没有更多的示例。我正在写一个函数来画。直线或矩形,我有问题,因为这是很难为我的困难。 我想写一个可重用的函数。但我不懂VBO:/我想写函数绘图,它将从主循环执行C++ Vbo如何绘制图元,c++,opengl,C++,Opengl,嗨,我正在尝试使用本教程学习OpenGl 我想说的是,本教程不适合刚开始学习的人。他们展示了许多适用于1个三角形的代码,但没有更多的示例。我正在写一个函数来画。直线或矩形,我有问题,因为这是很难为我的困难。 我想写一个可重用的函数。但我不懂VBO:/我想写函数绘图,它将从主循环执行 class lines{ public: lines(){ } static void draw(GLuint ve){ float vertices[] = {-0.5f,
class lines{
public: lines(){
}
static void draw(GLuint ve){
float vertices[] = {-0.5f, -0.5f, 0.5f, 0.5f};
unsigned int indices[] = {0, 1};
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, indices);
}
};
// Ensure we can capture the escape key being pressed below
glfwEnable( GLFW_STICKY_KEYS );
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );
static const GLfloat g_vertex_buffer_data[] = {
-0.8f, -1.0f,0.0f,
0.8f, -1.0f, 0.0f,
-0.8f, 1.0f, 0.0f,
-0.8f, 1.0f, 0.0f,
0.8f, 1.0f, 0.0f,
0.8, -1.0f, 0.0f,
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
do{
// Clear the screen
glClear( GL_COLOR_BUFFER_BIT );
// Use our shader
glUseProgram(programID);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
lines::draw(vertexbuffer);
// Swap buffers
glfwSwapBuffers();
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey( GLFW_KEY_ESC ) != GLFW_PRESS &&
glfwGetWindowParam( GLFW_OPENED ) );
要绘制基本体,请向OpenGL提供顶点列表以及连接它们的模式(例如形成直线、三角形等)。最简单的方法是立即模式(
glBegin
/glVertex3f
/glEnd
)。即时模式非常慢,通过“顶点数组”(不是顶点数组对象(VAO),它们是不同的)一次传递所有顶点的速度要快得多,它们在一维数组中按顺序排列,就像您的g_vertex_buffer_data
一样。顶点数组是指将指向主内存中数组的指针传递到glvertexinter
。这会更快,但每次绘制时都会将整个阵列发送到GPU。顶点缓冲区对象(VBO)允许您在GPU内存中发送和存储阵列。使用VBO,只需发送一个draw调用,并且数据已经在GPU上,因此无需传输,速度更快。VAOs将glVertexPointer
参数分组以加快绑定速度,并且glDraw*Indirect
允许使用GPU内存中已有的参数进行绘图,但我将这些留到以后
大多数教程从硬编码顶点开始,但对于最终应用程序来说,这当然不实用。您希望存储任意几何体的许多位。与行类似的网格类非常常见。关键点是网格有一个顶点列表。可以添加索引数组以重新引用现有顶点以形成基本体,从而节省重复顶点的内存和计算
但我现在要从即时模式渲染开始,这样可以减少出错的情况
首先
struct vec3f {
float x, y, z;
vec3f(float nx, float ny, float nz) : x(nx), y(ny), z(nz) {}
};
class Mesh {
std::vector<vec3f> vertices;
public:
void add(float x, float y, float z)
{
vertices.push_back(vec3f(x, y, z));
}
void draw()
{
glBegin(GL_LINE_STRIP);
for (size_t i = 0; i < vertices.size(); ++i)
glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
glEnd();
}
};
这个想法允许你有一个全局的std::列表行代码>例如。您可以在初始化时、从文件中或在运行时向其添加一次行。然后,绘图代码只需对每个元素调用draw。稍后,您可以扩展此想法,以支持三角形(例如,使GL\u LINE\u STRIP
aprimitive
member)。稍后,您可以添加索引、法线(这里您需要使用gl*Pointer
函数的stride
参数查找交错顶点/法线数据)、颜色/材质等
关于使用VBOs的问题glGenBuffers
将为您提供一个引用VBO的唯一句柄-简单地说是一个整数。当您修改或使用VBO时,您需要绑定它
glBufferData(GL\u ARRAY\u BUFFER…
对当前绑定的GL\u ARRAY\u BUFFER
(如果尚未)进行实际初始化/调整大小,并在数据参数非空时传输数据
glVertexAttribPointer
将假定您在主存中为上面提到的“顶点数组”传递一个数组,除非您glBindBuffer(GL\u array\u BUFFER,vbo)
,在这种情况下,最后一个参数成为该vbo的偏移量。调用glVertexAttribPointer
后
所以
这就搞定了。继续画画
3. glVertexAttribPointer (while the buffer is bound)
然后
或
因此,要扩展mesh类,您至少需要一个GLuint vertexBuffer;
。可以添加一个函数upload()
,以生成句柄并缓冲当前数据。然后可以调用Vertex.clear()
(实际上,用于std::vector使用)假设您不再需要主存中的顶点数据。然后更改draw函数以绑定vbo,调用glVertexPoint
,取消绑定并glDrawArrays
(从numVertices
成员中,将vertex.size()
设为零)
以下是一些相关帖子:
- 从你的教程中
要绘制基本体,您需要给OpenGL一个顶点列表以及连接它们的模式(例如形成直线、三角形等)。最简单的方法是立即模式(glBegin
/glVertex3f
/
)。立即模式非常慢,通过“顶点数组”一次传递所有顶点要快得多(不是顶点数组对象(VAO),它们是不同的),它们在一维数组中按顺序排列,就像您的g_vertex\u buffer\u data
一样。当您将指向主内存中数组的指针传递到glvertexpointinter
时,顶点数组就出现了。这样速度更快,但每次绘制时都会将整个数组发送到GPU。顶点缓冲区对象(VBO)允许您发送数组并将其存储在GPU内存中。使用VBO,只需发送一个绘图调用,并且数据已经在GPU上,因此无需传输,而且速度更快。VAOs将glvertexinter
参数分组以加快绑定速度,并glDraw*Indirect
允许使用GPU内存中已有的参数进行绘图,但我会把这些留到以后
大多数教程从硬编码顶点开始,但对于最终应用程序来说,这当然不实用。您需要存储许多任意几何体。类似于线的网格类非常常见。关键点是网格有一个顶点列表。您可以添加一组索引来重新引用现有顶点形成基本体,节省重复顶点的内存和计算
但我现在要从即时模式渲染开始,这样可以减少出错的情况
首先
struct vec3f {
float x, y, z;
vec3f(float nx, float ny, float nz) : x(nx), y(ny), z(nz) {}
};
class Mesh {
std::vector<vec3f> vertices;
public:
void add(float x, float y, float z)
{
vertices.push_back(vec3f(x, y, z));
}
void draw()
{
glBegin(GL_LINE_STRIP);
for (size_t i = 0; i < vertices.size(); ++i)
glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
glEnd();
}
};
例如,这个想法允许您拥有一个全局的std::list lines;
。您可以在初始化时、从文件中或在运行时向其中添加一次行。然后,您的绘图代码只需调用e
3. glVertexAttribPointer (while the buffer is bound)
4. glDrawArrays
4. glDrawElements (while an element array buffer is bound, containing the order in which to draw the vertices)