在 OpenGL 中创建网格
我需要使用 OpenGL 在 xy 平面中生成 NxN 分辨率网格.最终的网格需要由三角形 (GL_TRIANGLES
) 构成,因此应该类似于以下示例:
I need to generate a NxN resolution grid in the xy-plane with OpenGL. The final grid needs to be made by triangles (GL_TRIANGLES
), so it should seem like the following example:
^
* | ----------
* | | | | |
* | | | | |
* | ----------
* | | | | |
* y | | | | |
* | ----------
* | | | | |
* | | | | |
* | ----------
* |
* |-------------->
* x
请注意,我需要以顶点索引形式存储网格(通过参数给定结构).
Note that I need to store the grid in vertex-index form (given the structures by parameters).
此时我的代码:
void generate_grid(
std::uint32_t N,
std::vector<glm::vec3>* vertices,
std::vector<glm::uvec3>* indices)
{
for (int i = 0; i < N; i++) {
glBegin(GL_TRIANGLES);
for (int j = 0; j < N; j++) {
int vertexNum = indices; // Index for vertex j of face i.
double[] vertexCoords = vertices[vertexNum]; // The vertex itself.
glVertex3f(vertexCoords, 0);
}
glEnd();
}
有什么建议吗?问候.
推荐答案
由于语言是 C++ 并且您使用的是 std::vector
您应该更改函数签名并通过引用而不是指针传递参数.
Since the language is C++ and you are using a std::vector
you should change the function signature and pass the parameters by reference instead of by pointer.
void generate_grid(int N, std::vector<glm::vec3> &vertices, std::vector<glm::uvec3> &indices);
首先你必须填充顶点数组.请注意,对于 N*N
字段,您需要 (N+1)*(N+1)
个顶点.其次,您必须生成三角形索引,对于每个字段,您必须生成 2 个三角形:
First you have to fill the vertex array. Note, for a N*N
field you need (N+1)*(N+1)
vertices. Second you have to generate the triangle indices, for each field you have to generate 2 triangles:
float f(float x, float y)
{
// use any curve function you want
return sin(x*2.0f*3.141526f) * sin(y*2.0f*3.141526f) * 0.1f;
}
void generate_grid(int N, std::vector<glm::vec3> &vertices, std::vector<glm::uvec3> &indices)
{
for (int j=0; j<=N; ++j)
{
for (int i=0; i<=N; ++i)
{
float x = (float)i/(float)N;
float y = (float)j/(float)N;
float z = f(x, y);
vertices.push_back(glm::vec3(x, y, z));
}
}
for (int j=0; j<N; ++j)
{
for (int i=0; i<N; ++i)
{
int row1 = j * (N+1);
int row2 = (j+1) * (N+1);
// triangle 1
indices.push_back(glm::uvec3(row1+i, row1+i+1, row2+i+1));
// triangle 2
indices.push_back(glm::uvec3(row1+i, row2+i+1, row2+i));
}
}
}
老派和过时的画法是这样的:
The old school and deprecated way to draw this, would be like this:
void draw_grid(const std::vector<glm::vec3> &vertices, const std::vector<glm::uvec3> &indices)
{
glBegin(GL_TRIANGLES);
for ( auto i : indices )
{
glVertex3fv(glm::value_ptr(vertices[i.x]));
glVertex3fv(glm::value_ptr(vertices[i.y]));
glVertex3fv(glm::value_ptr(vertices[i.z]));
}
glEnd();
}
绘制几何图形的常用方法是创建一个顶点数组对象:
The common way to draw geometry is to create a Vertex Array Object:
GLuint generate_vao(const std::vector<glm::vec3> &vertices, const std::vector<glm::uvec3> &indices)
{
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, vertices.size()*sizeof(glm::vec3), glm::value_ptr(vertices[0]), GL_STATIC_DRAW );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, nullptr );
GLuint ibo;
glGenBuffers( 1, &ibo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(glm::uvec3), glm::value_ptr(indices[0]), GL_STATIC_DRAW );
glBindVertexArray( 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
return vao;
}
void draw_vao( GLuint vao, GLsizei n )
{
glBindVertexArray( vao );
glDrawElements( GL_TRIANGLES, (GLsizei)n, GL_UNSIGNED_INT, NULL );
glBindVertexArray( 0 );
}
std::vector<glm::vec3> vertices;
std::vector<glm::uvec3> indices;
GLuint vao = generate_vao( vertices, indices );
.....
draw_vao( vao, (GLsizei)indices.size()*3 );
相关文章