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.
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 linesvoid main(){float f_closest_edge = min(v_barycentric.x,
min(v_barycentric.y, v_barycentric.z));// see to which edge this pixel is the closestfloat 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 matrixvoid 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 ...
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.
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:
para puntos, cambie 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.
Respuestas:
encender,
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.
fuente
De http://cone3d.gamedev.net/cgi-bin/index.pl?page=tutorials/ogladv/tut5
fuente
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:
Y sombreador de vértices:
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.
fuente
Si está usando la tubería fija (OpenGL <3.3) o el perfil de compatibilidad, puede usar
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.
fuente
La forma más fácil es dibujar las primitivas como
GL_LINE_STRIP
.fuente
En Modern OpenGL (OpenGL 3.2 y superior), puede usar un sombreador de geometría para esto:
Avisos:
layout (line_strip, max_vertices=3) out;
alayout (points, max_vertices=3) out;
fuente
Puede usar bibliotecas de glut como esta:
para una esfera:
para un cilindro:
para un cubo:
fuente
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.
fuente
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
fuente
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íneasGL_POINTS
(si necesita dibujar solo vértices), oGL_TRIANGLE_STRIP
,GL_TRIANGLE_FAN
YGL_TRIANGLES
dibujar triángulos rellenoscomo primer argumento para tu
o
glDrawArrays(GLenum mode, GLint first, GLsizei count)
llamadas.fuente