2017-09-02 113 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