【发布时间】:2010-09-13 08:25:16
【问题描述】:
如何在 OpenGL 中将图元渲染为线框?
【问题讨论】:
-
更具体地说明您使用的 OpenGL 版本。
-
使用 GL_LINES 绘制线框
-
这将对大多数读者有所帮助,因为它解释了如何实现它learnopengl.com/Getting-started/Hello-Triangle
标签: opengl
如何在 OpenGL 中将图元渲染为线框?
【问题讨论】:
标签: opengl
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
开启,
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
恢复正常。
请注意,如果启用了纹理映射和光照等内容,它们仍将应用于线框线,这可能看起来很奇怪。
【讨论】:
来自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);
【讨论】:
假设在 OpenGL 3 及更高版本中具有向前兼容的上下文,您可以使用前面提到的glPolygonMode,但请注意,现在不推荐使用粗细超过 1px 的线条。因此,虽然您可以将三角形绘制为线框,但它们需要非常薄。在 OpenGL ES 中,您可以使用 GL_LINES,但有同样的限制。
在 OpenGL 中,可以使用几何着色器来获取传入的三角形,将它们分解并将它们发送为模拟粗线的四边形(实际上是三角形对)进行光栅化。真的很简单,只是几何着色器因性能缩放而臭名昭著。
您可以做的,以及在 OpenGL ES 中也可以使用的方法是使用 fragment 着色器。考虑将线框三角形的纹理应用于三角形。除了不需要纹理外,它可以通过程序生成。但是说够了,让我们来编码吧。片段着色器:
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);
}
和顶点着色器:
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
}
在这里,三个三角形顶点的重心坐标只是(1, 0, 0)、(0, 1, 0) 和(0, 0, 1)(顺序并不重要,这使得打包成三角形条可能更容易)。
这种方法的明显缺点是它会吃掉一些纹理坐标并且你需要修改你的顶点数组。可以用一个非常简单的几何着色器来解决,但我仍然怀疑它会比仅仅向 GPU 提供更多数据要慢。
【讨论】:
如果您使用的是固定管道 (OpenGL
//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);
在这种情况下,您可以通过调用glLineWidth来更改线宽
否则,您需要在绘图方法(glDrawElements、glDrawArrays 等)中更改多边形模式,最终可能会得到一些粗略的结果,因为您的顶点数据是针对三角形的并且您正在输出线。为获得最佳效果,请考虑使用Geometry shader 或为线框创建新数据。
【讨论】:
在现代 OpenGL(OpenGL 3.2 及更高版本)中,您可以为此使用几何着色器:
#version 330
layout (triangles) in;
layout (line_strip /*for lines, use "points" for points*/, 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();
}
注意事项:
layout (line_strip, max_vertices=3) out; 更改为 layout (points, max_vertices=3) out;
【讨论】:
最简单的方法是将基元绘制为GL_LINE_STRIP。
glBegin(GL_LINE_STRIP);
/* Draw vertices here */
glEnd();
【讨论】:
你可以像这样使用 glut 库:
对于一个球体:
glutWireSphere(radius,20,20);
对于圆柱体:
GLUquadric *quadratic = gluNewQuadric();
gluQuadricDrawStyle(quadratic,GLU_LINE);
gluCylinder(quadratic,1,1,1,12,1);
对于多维数据集:
glutWireCube(1.5);
【讨论】:
使用这个功能: void glPolygonMode(GLenum face, GLenum 模式);
face :指定模式适用的多边形。多边形的正面可以是 GL_FRONT,他的背面可以是 GL_BACK,两者都可以是 GL_FRONT_AND_BACK。
mode:定义了三种模式,可以在mode中指定:
GL_POINT :标记为边界边缘起点的多边形顶点被绘制为点。
GL_LINE :多边形的边界边缘被绘制为线段。 (你的目标)
GL_FILL : 多边形内部被填充。
P.S : glPolygonMode 控制图形管道中光栅化多边形的解释。
有关更多信息,请查看 khronos 组中的 OpenGL 参考页面: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonMode.xhtml
【讨论】:
在非抗锯齿渲染目标上绘制抗锯齿线的一种简单而简单的方法是使用 1x4 纹理绘制 4 像素宽度的矩形,Alpha 通道值为 {0.,1.,1., 0.},并使用关闭 mip-mapping 的线性过滤。这将使线条厚 2 个像素,但您可以更改不同厚度的纹理。 这比气压计算更快更容易。
【讨论】:
如果您正在处理的是 OpenGL ES 2.0,您可以从中选择一种绘制模式常量
GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,画线,
GL_POINTS(如果您只需要绘制顶点),或者
GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN 和 GL_TRIANGLES 绘制实心三角形
作为你的第一个参数
glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices)
或
glDrawArrays(GLenum mode, GLint first, GLsizei count) 来电。
【讨论】: