¿Cómo se representan primitivas como wireframes en OpenGL?


220

¿Cómo se representan primitivas como wireframes en OpenGL?

opengl 

2
Sea más específico sobre la versión de OpenGL que está utilizando.
Vertexwahn

Con ModernGL puede simplificar el uso del atributo wireframe de la clase Context
Szabolcs Dombi

use GL_LINES para dibujar wireframes
oxine

Respuestas:


367
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.


2
Me gustas. 4 más para ir.
Jo So

37

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);

75
Hacer dos llamadas es redundante. use GL_FRONT_AND_BACK
shoosh

66
Como una adición al comentario de @ shoosh, el Libro Rojo afirma que GL_FRONT y GL_BACK han sido desaprobados y eliminados de OpenGL 3.1 y posteriores. Ahora, todavía puede usarlos a través de la extensión de compatibilidad, pero si puede elegir entre compatible con versiones anteriores y compatibles con versiones anteriores, recomendaría optar por el primero.
Fouric

1
El enlace en esta respuesta devuelve 404.
Ondrej Slinták

1
@ OndrejSlinták Ya está arreglado.
MaxiMouse

24

Suponiendo un contexto compatible con reenvío en OpenGL 3 y versiones posteriores, puede usarlo glPolygonModecomo 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.


Pensé que esto parecía prometedor, sin embargo, esto no parece funcionar de ninguna manera con OpenGL 3.2 (no ES). Aunque es posible que haya estropeado algo, jugué un poco con esto y no estoy realmente seguro de cómo se pretende usarlo. Sería útil obtener más información sobre lo que pretende renderizar realmente con estos sombreadores; No veo la forma en que no sea un relleno nada produciría nada útil, pero que ni siquiera servir, ya que el valor alfa del gl_FragColor parecía ser ignorado por completo en OpenGL 3.2 ...
user1167662

2
Claro que lo hace. Puede consultar la implementación de alguien de la misma idea en stackoverflow.com/questions/7361582/… .
los cerdos

1
Creo que el problema con el que intento utilizar la implementación sugerida es que el sombreador nunca se dibujará fuera del objeto que se va a delinear. Por lo tanto, esto dibujará el contorno sobre el objeto que se está esbozando? En otras palabras, ¿el contorno estará puramente contenido dentro del objeto original a dibujar?
user1167662

1
@BrunoLevy puedes obtener coordinación adicional en webGL, ¿no? Si tiene suerte, puede obtener esas coordenadas de texcoords si tiene modelos muy simples, pero de lo contrario solo necesita agregar nuevas coordenadas. Sería demasiado agradable si funcionara sin él :). Todo lo que necesita es pasar un solo escalar por vértice (y luego expandirlo a un vector 3 en el sombreador de vértices).
los cerdos

2
Ah, ahora veo ... f_width () es mi amigo, a este respecto. Gracias
Neil Gatenby el

5

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.


3

La forma más fácil es dibujar las primitivas como GL_LINE_STRIP.

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

no si es un montón de GL_TRIANGLES: obtendrías líneas entre ellos. En OpenGL 1.xo legacy, usa glPolygonMode. En OpenGL reciente juegas con el sombreador de geometría.
Fabrice NEYRET

Esta es una forma antigua de hacer cosas que hay que dejar atrás.
Benny Mackney

2

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:


1

Puede usar bibliotecas de glut como esta:

  1. para una esfera:

    glutWireSphere(radius,20,20);
    
  2. para un cilindro:

    GLUquadric *quadratic = gluNewQuadric();
    gluQuadricDrawStyle(quadratic,GLU_LINE);
    gluCylinder(quadratic,1,1,1,12,1);
    
  3. para un cubo:

    glutWireCube(1.5);
    

0

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.


0

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


-1

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_FANY GL_TRIANGLESdibujar 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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.