带有重心坐标的线框着色器显示黑色三角形

时间:2017-05-30 17:29:25

标签: glsl shader wireframe

我使用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);
        }
}

1 个答案:

答案 0 :(得分:1)

正如我在问题评论中提到的那样,问题在于网格的某些三角形具有相同的barycentric属性。据我所知,您使用索引网格,重新排序数据以解决此问题可能会非常棘手,并且很大程度上取决于模型的拓扑结构。然而,有一种防弹的方法,它只是有点不理想:只是摆脱索引(代码是C ++ - ish,但可能需要一些重做):

// 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