簡體   English   中英

如何使用 OpenGL 繪制 OpenMesh

[英]How to Draw OpenMesh using OpenGL

我正在使用OpenMesh讀取stlobj文件並使用openGL在屏幕上繪制它們的項目。 我一直在做以下事情,

#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/IO/MeshIO.hh>

OpenMesh::TriMesh_ArrayKernelT<> mesh;

std::vector<point> vertices;
std::vector<point> normals;

void readMesh(std::string file)
{
    OpenMesh::IO::read_mesh(mesh, file);

    mesh.requestFaceNormals();
    mesh.request_vertex_normals();
    mesh.updateNormals();

    vertices.clear();
    normals.clear();

    for (auto face : mesh.faces())
    {
        for (auto vertex : mesh.fv_range(face))
        {
            auto point = mesh.point(vertex);
            auto normal = mesh.normal(face);

            vertices.push_back(point);
            normals.push_back(normal);
        }
    }

    mesh.releaseFaceNormals();
    mesh.releaseVertexNormals();
}

並且在繪制時我只是像這樣將verticesnormals向量傳遞給頂點着色器

void paint()
{
    glSetAttributeArray(0, vertices.data());
    glSetAttributeArray(1, normals.data());
    glDrawArrays(GL_TRIANGLES, 0, vertices.length());
}

頂點着色器如下所示:

attribute vec3 position;
attribute vec3 normal;

uniform mat4 modelViewMatrix;

void main(void)
{
    vec4 color = vec4(0.25, 0.25, 0.25, 0.0);

    vec4 P = vec4(position, 0);
    vec4 N = vec4(normal, 0);

    vec3 L = vec3(20, 20, 20) - position;
    vec3 V = -position;
    N = normalize(N);
    L = normalize(L);
    V = normalize(V);
    vec3 R = reflect(-L, vec3(N));
    vec3 diffuse = max(dot(vec3(N), L), 0.0) * color.rgb;
    vec3 specular = pow(max(dot(R, V), 0.0), 0.2) * vec3(0.1, 0.1, 0.1);
    color = vec4(color.a * (ambient + diffuse + specular), color.a);
    color = clamp(color, 0.0, 1.0);

    gl_Color = color;
    gl_Position = modelViewMatrix * P;
}

片段着色器是:

void main(void)
{
    gl_FragColor = gl_Color;
}

這會產生非常好的結果,但是將頂點和法線的另一個副本存儲在另一個位置( normalsvertices )以便能夠繪制網格的想法看起來非常違反直覺。

我想知道我是否可以使用openGL緩沖區和openMesh來優化它。 我一直在搜索有關此主題的任何內容,但一無所獲。

請參閱頂點規范 您可以為頂點坐標和正常頂點創建 2 個頂點緩沖區Object:

GLuint vbos[2];
glGenBuffers(2, vbos);
glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vertices[0]), vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(normals[0]), normals.data(), GL_STATIC_DRAW);

如果您使用 OpenGL 3.0 或更高版本,則可以指定頂點數組 Object和 state 頂點規范:

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

當你想繪制網格時,綁定 VAO 就足夠了:

glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, vertices.length());

如果使用 OpenGL 2.0,則無法創建 VAO,因此必須在繪制網格之前指定通用頂點屬性數據的 arrays:

glBindBuffer(GL_ARRAY_BUFFER, vbos[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, vertices.length());

此外請注意,屬性索引不保證為 0 和 1。屬性索引可以是任意數字。

如果您使用 GLSL 3.30 版,則可以通過Layout Qualifier在着色器代碼中設置屬性索引。
無論如何,您可以在鏈接程序之前通過glBindAttribLocation定義屬性索引,或者在鏈接程序之后通過glGetAttribLocation檢索屬性索引。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM