如何在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库:
-
对于一个球体:
glutWireSphere(radius,20,20);
-
对于一个气缸:
GLUquadric *quadratic = gluNewQuadric(); gluQuadricDrawStyle(quadratic,GLU_LINE); gluCylinder(quadratic,1,1,1,12,1);
-
对于立方体:
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_STRIP
, GL_TRIANGLE_FAN
和GL_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新数据。