如何在OpenGL中将基元渲染为线框?

207 opengl

如何在OpenGL中将基元渲染为线框?

小智 349

glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
Run Code Online (Sandbox Code Playgroud)

打开,

glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
Run Code Online (Sandbox Code Playgroud)

恢复正常

请注意,纹理映射和光照等内容仍会应用于线框线,如果它们已启用,这看起来很奇怪.

  • 我喜欢你。还有4个。 (5认同)

Joh*_*kin 31

来自http://cone3d.gamedev.net/cgi-bin/index.pl?page=tutorials/ogladv/tut5

// Turn on wireframe mode
glPolygonMode(GL_FRONT, GL_LINE);
glPolygonMode(GL_BACK, GL_LINE);

// Draw the box
DrawBox();

// Turn off wireframe mode
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_FILL);
Run Code Online (Sandbox Code Playgroud)

  • 拨打两个电话是多余的.使用GL_FRONT_AND_BACK (72认同)
  • 作为@ shoosh评论的附录,红皮书指出GL_FRONT和GL_BACK已被弃用并从OpenGL 3.1及以上版本中删除.现在,您仍然可以通过兼容性扩展使用它们,但如果您可以选择前向兼容和后向兼容,我建议您选择前者. (6认同)

the*_*ine 22

假设在OpenGL 3及更高版本中具有向前兼容的上下文,您可以使用glPolygonMode前面提到的,但请注意,现在不推荐使用厚度超过1px的行.因此,虽然您可以将三角形绘制为线框,但它们需要非常薄.在OpenGL ES中,您可以使用GL_LINES相同的限制.

在OpenGL中,可以使用几何着色器来获取传入的三角形,对它们进行反汇编并将它们作为模拟粗线的四边形(真正的三角形对)进行光栅化.非常简单,实际上,除了几何着色器因性能不佳缩放而臭名昭着.

您可以做什么,以及在OpenGL ES中也可以使用的是使用片段着色器.考虑将线框三角形纹理应用于三角形.除了不需要纹理之外,它可以在程序上生成.但足够的话题,让我们的代码.片段着色器:

in vec3 v_barycentric; // barycentric coordinate inside the triangle
uniform float f_thickness; // thickness of the rendered lines

void main()
{
    float f_closest_edge = min(v_barycentric.x,
        min(v_barycentric.y, v_barycentric.z)); // see to which edge this pixel is the closest
    float f_width = fwidth(f_closest_edge); // calculate derivative (divide f_thickness by this to have the line width constant in screen-space)
    float f_alpha = smoothstep(f_thickness, f_thickness + f_width, f_closest_edge); // calculate alpha
    gl_FragColor = vec4(vec3(.0), f_alpha);
}
Run Code Online (Sandbox Code Playgroud)

和顶点着色器:

in vec4 v_pos; // position of the vertices
in vec3 v_bc; // barycentric coordinate inside the triangle

out vec3 v_barycentric; // barycentric coordinate inside the triangle

uniform mat4 t_mvp; // modeview-projection matrix

void main()
{
    gl_Position = t_mvp * v_pos;
    v_barycentric = v_bc; // just pass it on
}
Run Code Online (Sandbox Code Playgroud)

在这里,重心坐标是简单的(1, 0, 0),(0, 1, 0)(0, 0, 1)三个三角形顶点(顺序并不重要,这使得包装成三角形带可能更容易).

这种方法的明显缺点是它会吃掉一些纹理坐标,你需要修改你的顶点数组.可以通过一个非常简单的几何着色器来解决,但我仍然怀疑它会比为GPU提供更多数据更慢.

  • 当然可以.您可以在http://stackoverflow.com/questions/7361582/opengl-debugging-single-pass-wireframe-rendering中参考某人对同一想法的实现. (2认同)
  • 嗯,确定.这就是答案的重点. (2认同)
  • 啊,在这方面,我现在... f_width()是我的朋友。谢谢 (2认同)

LMD*_*LMD 9

在现代 OpenGL(OpenGL 3.2 及更高版本)中,您可以使用几何着色器来实现此目的:

#version 330

layout (triangles) in;
layout (line_strip, max_vertices=3) out;

in vec2 texcoords_pass[]; // texcoords from Vertex Shader
in vec3 normals_pass[]; // normals from Vertex Shader

out vec3 normals; // normals for Fragment Shader
out vec2 texcoords; // texcoords for Fragment Shader

void main(void)
{
    int i;
    for (i = 0; i < gl_in.length(); i++)
    {
        texcoords=texcoords_pass[i]; // pass through
        normals=normals_pass[i]; // pass through
        gl_Position = gl_in[i].gl_Position; // pass through
        EmitVertex();
    }
    EndPrimitive();
}
Run Code Online (Sandbox Code Playgroud)


小智 5

如果您使用的是固定管道(OpenGL < 3.3)或您可以使用的兼容性配置文件

//Turn on wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

//Draw the scene with polygons as lines (wireframe)
renderScene();

//Turn off wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以通过调用glLineWidth来更改线宽

否则,您需要在绘制方法(glDrawElements、glDrawArrays 等)中更改多边形模式,最终可能会得到一些粗略的结果,因为您的顶点数据用于三角形并且您正在输出线。为获得最佳结果,请考虑使用几何着色器或为线框创建新数据。