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

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

glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 

打开,

 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); 

恢复正常。

请注意,纹理映射和照明等function仍将应用于线框线条,如果它们已启用,可能看起来很奇怪。

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提到的glPolygonMode ,但是请注意厚度大于1px的行现在已经被弃用了。 所以,虽然你可以画三angular形的线框,但他们需要非常薄。 在OpenGL ES中,您可以使用具有相同限制的GL_LINES

在OpenGL中,可以使用几何着色器对进入的三angular形进行拆分,并将它们作为四边形(实际上是三angular形对)模拟粗线发送光栅化。 真的很简单,除了几何着色器因恶劣的性能缩放而臭名昭着。

你可以做什么,而在OpenGL ES中也可以使用片段着色器。 想想在三angular形上应用线框三angular形的纹理。 除了不需要纹理之外,它可以通过程序生成。 但足够的话,让我们编码。 片段着色器:

 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 } 

在这里,三angular形顶点的重心坐标简单地(1, 0, 0) 1,0,0 (1, 0, 0)(0, 1, 0)(0, 0, 1) 0,0,1)(顺序实际上并不重要,这使得潜在地包装成三angular形带更轻松)。

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

最简单的方法是GL_LINE_STRIP语绘制为GL_LINE_STRIP

 glBegin(GL_LINE_STRIP); /* Draw vertices here */ glEnd(); 

你可以使用这样的glut库:

  1. 对于一个球体:

     glutWireSphere(radius,20,20); 
  2. 对于一个气缸:

     GLUquadric *quadratic = gluNewQuadric(); gluQuadricDrawStyle(quadratic,GLU_LINE); gluCylinder(quadratic,1,1,1,12,1); 
  3. 对于立方体:

     glutWireCube(1.5); 

在现代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;
  • 阅读关于几何着色器的更多信息

如果你正在处理OpenGL ES 2.0 ,你可以从中select一个绘制模式常量

GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,来绘制线条,

GL_POINTS (如果您只需要绘制顶点)或

GL_TRIANGLE_STRIPGL_TRIANGLE_FANGL_TRIANGLES绘制实心三angular形

作为你的第一个参数

 glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices) 

要么

glDrawArrays(GLenum mode, GLint first, GLsizei count)调用。

如果您正在使用固定pipe线(OpenGL <3.3)或您可以使用的兼容性configuration文件

 //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等)内的多边形模式,你可能会得到一些粗糙的结果,因为你的顶点数据是三angular形的,而你正在输出线。 为了获得最佳效果,请考虑使用几何着色器或为线框创build新数据。