2017-09-02 148 views
2

假设我有我的几何体并创建了包含三角形邻接信息的索引缓冲区。然后,将绘图模式从GL_TRIANGLES更改为GL_TRIANGLE_ADJACENCY。 问题是,我可以使用几何着色器将三角形邻接中的几何转换为三角形带吗?opengl - 与三角形带相邻的三角形

是这样的:

layout(triangles_adjacency) in; 
layout(triangle_strip, max_vertices = 3) out; 

in Vertex 
{ 
    vec3 normal; 
} vertex[]; 

out FragmentVertexData 
{ 
    vec3 normal; 
    vec3 fragpos; 
} VertexOut; 


void main() 
{ 
    for(int i = 0 ; i < gl_in.length(); i+=2) 
    { 
     gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * gl_in[i].gl_Position; 
     VertexOut.normal = vertex[i].normal; 
     VertexOut.fragpos = vec3(ModelMatrix * gl_in[i].gl_Position); 
     VertexOut.fragpos = gl_Position; 
     EmitVertex(); 
    } 
    EndPrimitive(); 
} 

我已经尝试过,事实上它吸引到几何,但事情是错误的法线。我也必须索引它们吗?我错过了一步?

enter image description here

,这是我如何使用fragpos正常,在片段着色器

vec3 normal = normalize(VertexOut.normal); 
    vec3 lightDir = normalize(light.position - VertexOut.fragpos); 

这是我的算法写的三角形邻接索引缓存:

void Loader::FindAdjacencies(const aiMesh * paiMesh, vector<int>& indices) 
{ 
    // Step 1 - find the two triangles that share every edge 
    for (uint i = 0; i < paiMesh->mNumFaces; i++) 
    { 
     const aiFace& face = paiMesh->mFaces[i]; 

     Face Unique; 

     // If a position vector is duplicated in the VB we fetch the 
     // index of the first occurrence. 
     for (uint j = 0; j < 3; j++) 
     { 
      uint Index = face.mIndices[j]; 
      aiVector3D& v = paiMesh->mVertices[Index]; 

      if (m_posMap.find(v) == m_posMap.end()) 
      { 
       m_posMap[v] = Index; 
      } 
      else 
      { 
       Index = m_posMap[v]; 
      } 

      Unique.Indices[j] = Index; 
     } 

     m_uniqueFaces.push_back(Unique); 

     Edge e1(Unique.Indices[0], Unique.Indices[1]); 
     Edge e2(Unique.Indices[1], Unique.Indices[2]); 
     Edge e3(Unique.Indices[2], Unique.Indices[0]); 

     m_indexMap[e1].AddNeigbor(i); 
     m_indexMap[e2].AddNeigbor(i); 
     m_indexMap[e3].AddNeigbor(i); 

    } 

    // Step 2 - build the index buffer with the adjacency info 
    for (uint i = 0; i < paiMesh->mNumFaces; i++) 
    { 
     const Face& face = m_uniqueFaces[i]; 

     for (uint j = 0; j < 3; j++) 
     { 
      Edge e(face.Indices[j], face.Indices[(j + 1) % 3]); 
      assert(m_indexMap.find(e) != m_indexMap.end()); 
      Neighbors n = m_indexMap[e]; 
      uint OtherTri = n.GetOther(i); 
      uint minus1 = (uint)-1; 
      bool comp = (OtherTri != minus1); 
      assert(comp); 

      const Face& OtherFace = m_uniqueFaces[OtherTri]; 
      uint OppositeIndex = OtherFace.GetOppositeIndex(e); 

      indices.push_back(face.Indices[j]); 
      indices.push_back(OppositeIndex); 
     } 
    } 

} 

不幸的是,只适用于紧密的几何形状。这就是我用立方体测试它的原因。我试着用bunny.ply,但模型的一部分有漏洞,我将不得不在搅拌机中进行编辑。

,这是OBJ文件:

# Blender v2.76 (sub 0) OBJ File: '' 
# www.blender.org 
v 1.000000 -1.000000 -1.000000 
v 1.000000 -1.000000 1.000000 
v -1.000000 -1.000000 1.000000 
v -1.000000 -1.000000 -1.000000 
v 1.000000 1.000000 -0.999999 
v 0.999999 1.000000 1.000001 
v -1.000000 1.000000 1.000000 
v -1.000000 1.000000 -1.000000 
vt 0.333333 0.666667 
vt 0.333333 1.000000 
vt 0.000000 1.000000 
vt 0.000000 0.666667 
vt 0.000000 0.333333 
vt 0.333333 0.333333 
vt 0.333333 0.000000 
vt 0.666667 0.000000 
vt 0.000000 0.000000 
vt 1.000000 0.333333 
vt 0.666667 0.333333 
vt 0.666667 0.666667 
vt 1.000000 0.000000 
vn 0.000000 -1.000000 0.000000 
vn 0.000000 1.000000 0.000000 
vn 1.000000 0.000000 0.000000 
vn -0.000000 0.000000 1.000000 
vn -1.000000 -0.000000 -0.000000 
vn 0.000000 0.000000 -1.000000 
f 2/1/1 3/2/1 4/3/1 
f 8/1/2 7/4/2 6/5/2 
f 5/6/3 6/7/3 2/8/3 
f 6/9/4 7/7/4 3/6/4 
f 3/10/5 7/11/5 8/8/5 
f 1/11/6 4/12/6 8/1/6 
f 1/4/1 2/1/1 4/3/1 
f 5/6/2 8/1/2 6/5/2 
f 1/11/3 5/6/3 2/8/3 
f 2/5/4 6/9/4 3/6/4 
f 4/13/5 3/10/5 8/8/5 
f 5/6/6 1/11/6 8/1/6 

非常感谢您!

这是我的顶点着色器:

#version 430 core 
layout(location = 0) in vec3 vertexPosition; 
layout(location = 1) in vec2 texCoord; 
layout(location = 2) in vec3 normal; 

out VertexData 
{ 
    vec3 normal; 
    vec2 textCoord; 
} vertex; 

// Values that stay constant for the whole mesh. 

void main(){ 
    gl_Position = vec4(vertexPosition,1.0f); 
    vertex.textCoord = texCoord; 
    vertex.normal = normal; 
} 

和我的片段着色器:

#version 430 core 

struct Material { 
    vec3 ambient; 
    vec3 diffuse; 
    vec3 specular; 
    float shininess; 
}; 

struct Light { 
    vec3 position; 
    vec3 ambient; 
    vec3 diffuse; 
    vec3 specular; 
}; 

uniform Material material; 
uniform Light light; 

out vec4 color; 

uniform float LightIntensity; 
uniform vec3 LightPos; 
uniform vec3 ViewPos; 

in FragmentVertexData 
{ 
    vec3 normal; 
    vec3 fragpos; 
    vec2 texCoord; 
} VertexOut; 


void main(){ 


    // color of the object 
    vec3 objectColor = vec3(1.0f, 0.5f, 0.31f); 


    // Ambient 

    vec3 ambient = light.ambient * material.ambient ; 

    vec3 normal = normalize(VertexOut.normal); 
    vec3 lightDir = normalize(light.position - VertexOut.fragpos); 

    float diff = max(dot(lightDir,normal), 0.0); 
    vec3 diffuse = light.diffuse * diff * material.diffuse ; 

    vec3 viewDir = normalize(ViewPos - VertexOut.fragpos); 
    vec3 reflectDir = reflect(-lightDir, normal); 

    vec3 halfwayDir = normalize(lightDir + viewDir); 

    float spec = pow(max(dot(normal, halfwayDir), 0.0), material.shininess); 


    vec3 specular = light.specular * spec * material.specular ; 

    color = vec4((ambient + diffuse + specular) * objectColor, 1); 

} 

回答

4

三角形邻接,包含三角形邻接数据,使得相邻的三角形可以被访问。 Geometry Shader阶段可以访问6个顶点和属性,形成4个三角形。 3个顶点形成当前呈现的三角形。其他3个顶点形成相邻(相邻)三角形,并结合当前呈现的三角形的3个侧边。 (见GL_ARB_geometry_shader4Primitive)。

trianglesa djacency

如果Geometry Shader应该通过呈现三角形到下一个着色器级,那么它仅处理的三个点,形成的三角形,而不是它的邻接关系。

另外的问题:该模型的

  • 世界空间中的位置是由VertexOut.fragpos = gl_Position;
  • 法线向量重写必须被转换到世界空间:
    VertexOut.normal = mat3(ModelMatrix) * vertex[i].normal;

几何着色器应看起来像这样:

layout(triangles_adjacency) in; 
layout(triangle_strip, max_vertices = 3) out; 

in Vertex 
{ 
    vec3 normal; 
} vertex[]; 

out FragmentVertexData 
{ 
    vec3 normal; 
    vec3 fragpos; 
} VertexOut; 

uniform mat4 ModelMatrix; 
uniform mat4 ViewMatrix; 
uniform mat4 ProjectionMatrix; 

void main() 
{ 
    for (int i = 0; i < 6; i += 2) 
    { 
     vec4 fragPos  = ModelMatrix * gl_in[i].gl_Position; 
     VertexOut.normal = mat3(ModelMatrix) * vertex[i].normal; 
     VertexOut.fragpos = fragPos.xyz; 
     gl_Position  = ProjectionMatrix * ViewMatrix * fragPos; 
     EmitVertex(); 
    } 
    EndPrimitive(); 
} 


如果正常矢量是每个面,你的邻接算法将失败:

产生邻接指数不考虑,即面部的每个点是由一对的顶点位置和所述的算法法线矢量。不同的人脸可能具有相同的角落位置,但它们总是具有不同的法向矢量。由于您将所有顶点位置放置在地图m_pos Map中,其中位置是关键点,因此法线向量的区别会丢失。当你有一个立方体时,对于每个面的法向量,每个顶点位置在顶点缓冲区中必须是3次,因为它由立方体的3边共享并具有3个不同的法向量。
如果您有一个网格,其法向量是每个顶点(例如球体),那么您的算法将会正常工作。但是,如果法向量是每个面,则算法会失败,就像立方体的情况一样。


,保持面孔和只添加邻接的脸看起来像这样的算法:

#include <array> 
#include <vector> 
#include <map> 

using TIndices = std::vector<int>; 
using TFace  = std::array<int, 3>; 
using TFaces = std::vector<TFace>; 
using TVertex = std::array<float, 3>; 
using TVertices = std::vector<TVertex>; 

void GenerateAdjacencies(const TVertices &vertices, const TFaces &faces, TIndices &adj) 
{ 
    // associate each geometric vertex position with an unique ID 
    std::vector<int>  uniqueMap; 
    std::map<TVertex,int> tempUniqueVertices; 
    int uniqueIndex = 0; 
    for (size_t vI = 0; vI < vertices.size(); ++ vI) 
    { 
     auto vIt = tempUniqueVertices.find(vertices[vI]); 
     if (vIt == tempUniqueVertices.end()) 
     { 
      tempUniqueVertices[ vertices[vI] ] = uniqueIndex; 
      uniqueMap.push_back(uniqueIndex); 
      uniqueIndex ++; 
     } 
     else 
      uniqueMap.push_back(vIt->second); 
    } 
    tempUniqueVertices.clear(); 

    // find all edges and associate the edge with all the points, which form a triangle with it. 
    std::map< std::tuple<int, int>, std::vector<int> > edges; 
    for (auto & f : faces) 
    { 
     for (int pI = 0; pI < 3; ++ pI) 
     { 
     int edgeU[2]{ uniqueMap[f[pI]], uniqueMap[f[(pI+1) % 3]] }; 
     int i0 = edgeU[0] < edgeU[1] ? 0 : 1; 
     edges[{ edgeU[i0], edgeU[1-i0] }].push_back(f[(pI+2) % 3]); 
     } 
    } 

    // create the adjacencies 
    for (auto & f : faces) 
    { 
     for (int pI = 0; pI < 3; ++ pI) 
     { 
      int edgeU[2]{ uniqueMap[f[pI]], uniqueMap[f[(pI+1) % 3]] }; 
      int i0 = edgeU[0] < edgeU[1] ? 0 : 1; 
      auto &adjs = edges[{ edgeU[i0], edgeU[1 - i0] }]; 
      int adjI = adjs.size() > 1 && adjs[0] == f[(pI+2) % 3] ? 1 : 0; 
      adj.push_back(f[pI]); 
      adj.push_back(adjs[adjI]); 
     } 
    } 
} 

example

+1

嗨,是啊,这就是我在循环正在做(int i = 0,i Camilo

+0

你的意思是光的位置?世界空间。在将它们从GL_TRIANGLE_ADJACENCY转换为三角形条(现在它只是一个普通立方体)后,我附加了顶点法线的图像。 在那张照片中,光线在立方体上方,但它的一些边看起来像是光线在它们的前方。这就是为什么我认为法线方面也必须做些什么。 – Camilo

+0

这是我如何计算片段着色器中的法线和光线方向。 vec3 normal = normalize(VertexOut.normal); vec3 lightDir = normalize(light.position - VertexOut.fragpos); 我认为搅拌机输出每个顶点的法线。立方体面的法线使用另一个几何着色器绘制 – Camilo