Odpowiedzi:
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
włączyć,
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
wrócić do normalności.
Pamiętaj, że takie elementy jak mapowanie tekstur i oświetlenie będą nadal stosowane do linii szkieletowych, jeśli są włączone, co może wyglądać dziwnie.
From 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);
Zakładając kontekst zgodny z Open w OpenGL 3 i nowszych, możesz użyć albo glPolygonMode
jak wspomniano wcześniej, ale pamiętaj, że linie o grubości większej niż 1px są teraz przestarzałe. Tak więc, chociaż możesz rysować trójkąty jako ramkę drucianą, muszą one być bardzo cienkie. W OpenGL ES można używać GL_LINES
z tymi samymi ograniczeniami.
W OpenGL można używać shaderów geometrii do pobierania przychodzących trójkątów, demontowania ich i wysyłania do rasteryzacji jako quady (naprawdę pary trójkątów) emulujące grube linie. Całkiem proste, naprawdę, z wyjątkiem tego, że shadery geometrii są znane z powodu słabego skalowania wydajności.
Zamiast tego możesz także zastosować w OpenGL ES moduł cieniujący fragmenty . Pomyśl o zastosowaniu do niego tekstury trójkąta o konstrukcji drucianej. Tyle, że tekstura nie jest potrzebna, można ją wygenerować proceduralnie. Ale dość gadania, napiszmy kod. Moduł cieniujący fragmenty:
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);
}
I moduł cieniujący wierzchołek:
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
}
Tutaj barycentryczne współrzędne są po prostu (1, 0, 0)
, (0, 1, 0)
a (0, 0, 1)
za trzy wierzchołki trójkąta (kolejność nie ma znaczenia, co sprawia, że pakowanie w paski trójkąta potencjalnie łatwiej).
Oczywistą wadą tego podejścia jest to, że zje ono niektóre współrzędne tekstury i trzeba zmodyfikować tablicę wierzchołków. Można to rozwiązać za pomocą bardzo prostego modułu cieniującego geometrię, ale nadal podejrzewam, że będzie on wolniejszy niż tylko zasilanie GPU większą ilością danych.
Jeśli używasz stałego potoku (OpenGL <3.3) lub profilu zgodności, którego możesz użyć
//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);
W takim przypadku możesz zmienić szerokość linii, wywołując glLineWidth
W przeciwnym razie musisz zmienić tryb wielokąta w metodzie rysowania (glDrawElements, glDrawArrays itp.) I możesz skończyć z grubymi wynikami, ponieważ twoje dane wierzchołków dotyczą trójkątów i wyprowadzasz linie. Aby uzyskać najlepsze wyniki, rozważ użycie modułu cieniującego geometrię lub utworzenia nowych danych dla modelu szkieletowego.
Najprostszym sposobem jest narysowanie prymitywów jako GL_LINE_STRIP
.
glBegin(GL_LINE_STRIP);
/* Draw vertices here */
glEnd();
W Modern OpenGL (OpenGL 3.2 i wyżej) możesz użyć Geometru Shadera w tym celu:
#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();
}
Uwagi:
layout (line_strip, max_vertices=3) out;
nalayout (points, max_vertices=3) out;
Dobrym i prostym sposobem rysowania wygładzonych linii na nie-wygładzonym celu renderowania jest narysowanie prostokątów o szerokości 4 pikseli z teksturą 1x4, z wartościami kanału alfa {0., 1., 1., 0.} i użyj filtrowania liniowego przy wyłączonym mapowaniu mip. Spowoduje to, że linie będą miały grubość 2 pikseli, ale możesz zmienić teksturę dla różnych grubości. Jest to szybsze i łatwiejsze niż obliczenia barymetryczne.
użyj tej funkcji: void glPolygonMode (twarz GLenum, tryb GLenum);
twarz: określa wielokąty, których dotyczy tryb. może być GL_FRONT dla przedniej strony wielokąta i GL_BACK dla jego pleców oraz GL_FRONT_AND_BACK dla obu.
tryb: zdefiniowane są trzy tryby, które można określić w trybie:
GL_POINT: Wierzchołki wielokąta oznaczone jako początek krawędzi granicznej są rysowane jako punkty.
GL_LINE: Krawędzie granicy wielokąta są rysowane jako segmenty linii. (Twój cel)
GL_FILL: Wnętrze wielokąta jest wypełnione.
PS: glPolygonMode kontroluje interpretację wielokątów do rasteryzacji w potoku graficznym.
Aby uzyskać więcej informacji, zobacz strony referencyjne OpenGL w grupie Khronos: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonMode.xhtml
Jeśli jest to OpenGL ES 2.0 masz do czynienia z , możesz wybrać jedną ze stałych trybu rysowania
GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,
rysować linie,
GL_POINTS
(jeśli musisz rysować tylko wierzchołki), lub
GL_TRIANGLE_STRIP
, GL_TRIANGLE_FAN
iGL_TRIANGLES
narysować wypełnione trójkąty
jako pierwszy argument do twojego
glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices)
lub
glDrawArrays(GLenum mode, GLint first, GLsizei count)
połączenia.