2017-05-30 127 views
0

我创建了一个使用OpenGL的网格查看器,现在我正尝试实现带有重心坐标的线框着色器,该指南找到here带重心坐标的线框着色器显示黑色三角形

问题是我的网格有很多黑色三角形,我不明白错误在哪里。它可能在我的重心向量中吗?

我的最终渲染看起来是这样的:

BoneWrongWireframe

在代码中,我创建的重心矢量以这样的方式

MatrixXi barycentric(3, faceCount*3); 
for(int i=0; i<faceCount*3; i+=9){ 
    barycentric.col(i) << 1,0,0,0,1,0,0,0,1; 
} 

这是我的顶点着色器:

#version 330 

in vec3 vertices; 
in vec3 barycentric; 

uniform mat4 proj; 
uniform mat4 model; 
uniform mat4 view; 

out vec4 frag_color; 
varying vec3 vBC; 
void main(void) { 
    mat4 mvp = proj * view * model; 

    frag_color = vec4(0.0, 1.0, 0.0, 1.0); 
    vBC = barycentric; 
    gl_Position = mvp * vec4(vertices, 1.0); 
} 

而我的片段着色器:

#version 330 

varying vec3 vBC; 
in vec4 frag_color; 

out vec4 color; 
float edgeFactor(){ 
     vec3 d = fwidth(vBC); 
     vec3 a3 = smoothstep(vec3(0.0), d*1.5, vBC); 
     return min(min(a3.x, a3.y), a3.z); 
} 

void main(void) { 
     if(gl_FrontFacing){ 
      gl_FragColor = vec4(0.0, 0.0, 0.0, (1.0-edgeFactor())*0.95); 
     } 
     else{ 
      gl_FragColor = vec4(0.0, 0.0, 0.0, (1.0-edgeFactor())*0.7); 
     } 
} 
+0

看起来你的三角形有三个顶点的重心值。这可能意味着你使用索引网格。您应该以某种方式重新排列几何图形。顺便说一句,为什么你不只是使用'glPolygonMode(GL_FRONT_AND_BACK,GL_LINE)'? –

+0

@KirillDmitrenko谢谢你的回答。我想你可能是对的......我该如何解决它?我不知道如何创建矢量。顺便说一句,我不使用glPolygonMode(),因为我使用的是nanogui,而且该函数也作用于GUI。此外,我想选择透明线框和填充线框 – lilcaesar

+0

我已经发布了一些想法作为anwser –

回答

0

问题,正如我在问题的评论中提到的那样,网格的某些三角形具有相同的barycentric属性。因为,据我所知,你使用索引网格,重新排序你的数据来解决这个问题可能会很棘手,并且很大程度上取决于你的模型的拓扑结构。但是有这样做防弹方式,它只是有点不理想:刚刚摆脱指数(代码是C++ - 十岁上下,但可能需要一些返工):

// Here're buffers with vertices and indices of the mesh. 
std::vector<Vertex> vertexBuffer; 
std::vector<int> indexBuffer; 

std::vector<VertexWithBarycentricCoord> outputVertexBuffer; 

const std::array<BarycentricCoord> COORDS({{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}); 

for (int i : indexBuffer) { 
    outputVertexBuffer.push_back({vertexBuffer, COORDS[i % 3]}); 
} 

关于glPolygonMode。你在评论中指出它可能会破坏GUI。不过,这并不有:可以切换模式,仅GL_LINE您的绘图,然后再切换回GL_FILL

glPolygonMode(GL_FRONT_AND_BACK, GL_LINES); 
// draw your mesh 
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
// draw GUI 

而且你所提到的,你可能会想“混”的网格线框填充网格,这可能会妨碍使用glPolygonMode,但它不应该。你可以画两次网格:

glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
// draw your filled mesh 
glDepthFunc(GL_LEQUAL) // to make sure that not all wireframe's fragments are culled in depth test. 
glPolygonMode(GL_FRONT_AND_BACK, GL_LINES); 
// draw your mesh again 
+0

非常感谢,它完美的工作! – lilcaesar