简体   繁体   English

GLSL将指示的法线传递给着色器

[英]GLSL passing indiced normals to shader

I generated model (Suzie) in blender and exported it to .obj file with normals. 我在Blender中生成了模型(Suzie),并使用法线将其导出到.obj文件。 During loading mode to my app i noticed that numbers of vertices and normals are diffrent (2012 and 1967). 在加载到我的应用程序的过程中,我注意到顶点和法线的数量不同(2012年和1967年)。

型号详情

I try to implement simple cell shading. 我尝试实现简单的单元格阴影。 The problem is in passing normals to shader. 问题在于将法线传递给着色器。 For storing vertex data i use vectors from glm. 为了存储顶点数据,我使用glm中的向量。

std::vector<unsigned int> face_indices;
std::vector<unsigned int> normal_indices;
std::vector<glm::vec3> geometry;
std::vector<glm::vec3> normals;

Result i've got so far 结果我到目前为止

法线错误

Buffers Layout 缓冲区布局

    glBindVertexArray(VAO);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
    glBufferData(GL_ARRAY_BUFFER, geometry.size() * sizeof(glm::vec3), &geometry[0], GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, NormalVBOID);
    glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_DYNAMIC_DRAW);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VIndexVBOID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, face_indices.size() * sizeof(unsigned int), &face_indices[0], GL_DYNAMIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

Rendering fragment 渲染片段

    glBindVertexArray(VAO);

    glPolygonMode(GL_FRONT_AND_BACK, GL_QUADS);
    glDrawElements(GL_QUADS, face_indices.size(), GL_UNSIGNED_INT, (void*)0);

    glBindVertexArray(0);

The reason that had such wierd problem was that some normals were used more than once to preserve disk space so i had to rearrange them in a proper order. 出现这种问题的原因是,一些法线被多次使用以保留磁盘空间,因此我不得不以适当的顺序重新排列它们。 So the solution is pretty trival. 因此,解决方案非常简单。

geometry.clear();
normals.clear();

geometry.resize(vv.size());
normals.resize(vv.size());

for (unsigned int i = 0; i < face_indices.size(); i++)
{
    int vi = face_indices[i];
    int ni = normal_indices[i];
    glm::vec3 v = vv [vi];
    glm::vec3 n = vn [ni];
    geometry[vi] = v ;
    normals[vi]  = n ;
    indices.push_back(vi);
}

You should also keep in mind that using the smooth modifier in Blender before export will in some cases help ensure that you have 1 normal per vertex (you may or may not need to also set per-vert normal view instead of face-normal view...can't rem so you'll have to test). 您还应该记住,在导出之前在Blender中使用smooth修改器在某些情况下将有助于确保每个顶点有1个法线(您可能也可能不需要设置每个顶点法线视图而不是面法线视图。 ..无法rem,因此您必须进行测试)。 This is because by default, blender uses per-face normals. 这是因为默认情况下,Blender使用按面法线。 The smooth modifier ("w" hotkey menu) will switch it to per-vertex norms. 平滑修饰符(“ w”热键菜单)会将其切换为基于顶点的规范。 Then when you export, you export verts and norms as usual, and the number should match. 然后,在导出时,您将照常导出verts和norm,并且数字应该匹配。 It doesn't always, but this has worked for me in the past. 并非总是如此,但这在过去对我有用。 This could possibly mean less unnecessary juggling of your data during import. 这可能意味着在导入期间减少不必要的数据摆弄。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM