¿Cómo se representan primitivas como wireframes en OpenGL?
¿Cómo se representan primitivas como wireframes en OpenGL?
Respuestas:
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
encender,
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
para volver a la normalidad
Tenga en cuenta que cosas como el mapeo de texturas y la iluminación aún se aplicarán a las líneas de estructura metálica si están habilitadas, lo que puede parecer extraño.
De 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);
Suponiendo un contexto compatible con reenvío en OpenGL 3 y versiones posteriores, puede usarlo glPolygonMode
como se mencionó anteriormente, pero tenga en cuenta que las líneas con un grosor de más de 1px ahora están en desuso. Entonces, si bien puede dibujar triángulos como marco de alambre, deben ser muy delgados. En OpenGL ES, puede usarGL_LINES
con la misma limitación.
En OpenGL es posible usar sombreadores de geometría para tomar triángulos entrantes, desarmarlos y enviarlos a rasterización como quads (pares de triángulos realmente) emulando líneas gruesas. Bastante simple, en realidad, excepto que los sombreadores de geometría son conocidos por el escalado de bajo rendimiento.
Lo que puede hacer en su lugar, y lo que también funcionará en OpenGL ES es emplear sombreador de fragmentos . Piense en aplicar una textura de triángulo de marco de alambre al triángulo. Excepto que no se necesita textura, se puede generar de manera procesal. Pero basta de hablar, codifiquemos. Sombreador de fragmentos:
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);
}
Y sombreador de vértices:
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
}
Aquí, las coordenadas barcéntricas son simples (1, 0, 0)
, (0, 1, 0)
y(0, 0, 1)
para los tres vértices triangulares (el orden en realidad no importa, lo que hace que empacar en tiras triangulares sea potencialmente más fácil).
La desventaja obvia de este enfoque es que comerá algunas coordenadas de textura y deberá modificar su matriz de vértices. Podría resolverse con un sombreador de geometría muy simple, pero aún sospecharía que será más lento que solo alimentar la GPU con más datos.
Si está usando la tubería fija (OpenGL <3.3) o el perfil de compatibilidad, puede usar
//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);
En este caso, puede cambiar el ancho de línea llamando glLineWidth
De lo contrario, debe cambiar el modo de polígono dentro de su método de dibujo (glDrawElements, glDrawArrays, etc.) y puede terminar con algunos resultados aproximados porque sus datos de vértice son para triángulos y está generando líneas. Para obtener los mejores resultados, considere usar un sombreador de Geometría o crear nuevos datos para la estructura alámbrica.
La forma más fácil es dibujar las primitivas como GL_LINE_STRIP
.
glBegin(GL_LINE_STRIP);
/* Draw vertices here */
glEnd();
En Modern OpenGL (OpenGL 3.2 y superior), puede usar un sombreador de geometría para esto:
#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();
}
Avisos:
layout (line_strip, max_vertices=3) out;
alayout (points, max_vertices=3) out;
Una buena y sencilla forma de dibujar líneas suavizadas en un objetivo de renderizado suavizado es dibujar rectángulos de 4 píxeles de ancho con una textura 1x4, con valores de canal alfa de {0., 1., 1., 0.} , y utilice el filtrado lineal con mip-mapping desactivado. Esto hará que las líneas tengan un grosor de 2 píxeles, pero puede cambiar la textura para diferentes grosores. Esto es más rápido y más fácil que los cálculos barimétricos.
use esta función: void glPolygonMode (cara GLenum, modo GLenum);
face: especifica los polígonos a los que se aplica el modo. puede ser GL_FRONT para la parte frontal del polígono y GL_BACK para su espalda y GL_FRONT_AND_BACK para ambos.
modo: se definen tres modos y se pueden especificar en modo:
GL_POINT: los vértices poligonales que están marcados como el inicio de un borde límite se dibujan como puntos.
GL_LINE: los bordes del límite del polígono se dibujan como segmentos de línea. (tu objetivo)
GL_FILL: se rellena el interior del polígono.
PD: glPolygonMode controla la interpretación de los polígonos para la rasterización en la tubería de gráficos.
Para obtener más información, consulte las páginas de referencia de OpenGL en el grupo khronos: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonMode.xhtml
Si está tratando con OpenGL ES 2.0 , puede elegir una de las constantes del modo de dibujo de
GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,
dibujar líneas
GL_POINTS
(si necesita dibujar solo vértices), o
GL_TRIANGLE_STRIP
, GL_TRIANGLE_FAN
Y GL_TRIANGLES
dibujar triángulos rellenos
como primer argumento para tu
glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices)
o
glDrawArrays(GLenum mode, GLint first, GLsizei count)
llamadas.