首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用OpenMesh绘制OpenGL

如何使用OpenMesh绘制OpenGL
EN

Stack Overflow用户
提问于 2020-07-22 11:34:03
回答 1查看 754关注 0票数 1

我正在进行一个项目,在这个项目中,我使用OpenMesh读取stl和obj文件,并使用openGL在屏幕上绘制它们。我一直在做以下事情,

代码语言:javascript
复制
#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向量传递给顶点着色器,如下所示

代码语言:javascript
复制
void paint()
{
    glSetAttributeArray(0, vertices.data());
    glSetAttributeArray(1, normals.data());
    glDrawArrays(GL_TRIANGLES, 0, vertices.length());
}

顶点着色器看起来如下:

代码语言:javascript
复制
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;
}

碎片着色器是:

代码语言:javascript
复制
void main(void)
{
    gl_FragColor = gl_Color;
}

这产生了相当好的结果,但是将另一个顶点和法线的副本存储在另一个位置(normalsvertices)来绘制网格的想法看起来非常违背直觉。

我想知道是否可以使用openGL缓冲区和openMesh来优化这一点。有一段时间,我一直在寻找关于这个话题的任何东西,但什么也没有发现。

EN

回答 1

Stack Overflow用户

发布于 2020-07-22 14:13:17

顶点规范。您可以为垂直坐标和正常变送器创建2个顶点缓冲对象

代码语言:javascript
复制
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或更高版本,则可以指定顶点阵列对象并声明顶点规范:

代码语言:javascript
复制
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:

代码语言:javascript
复制
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, vertices.length());

如果使用OpenGL 2.0,则无法创建VAO,因此必须在绘制网格之前指定泛型顶点属性数据的数组:

代码语言:javascript
复制
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,则可以通过布局限定符在着色器代码中设置属性索引。

无论如何,您可以在链接程序之前通过glBindAttribLocation定义属性索引,或者在链接程序之后通过glGetAttribLocation检索属性索引。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63033237

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档