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.
wykonywanie dwóch połączeń jest zbędne. użyj GL_FRONT_AND_BACK
shoosh
6
Jako dodatek do komentarza @ shoosh, Czerwona Księga stwierdza, że GL_FRONT i GL_BACK zostały wycofane i usunięte z OpenGL 3.1 i nowszych. Teraz możesz nadal korzystać z nich za pomocą rozszerzenia kompatybilności, ale jeśli masz wybór między zgodnym w przód a wstecznym, zaleciłbym wybranie tego pierwszego.
fouric
1
Link w tej odpowiedzi zwraca 404.
Ondrej Slinták
1
@ OndrejSlinták Naprawiono teraz.
MaxiMouse
24
Zakładając kontekst zgodny z Open w OpenGL 3 i nowszych, możesz użyć albo glPolygonModejak 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_LINESz 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 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);}
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 matrixvoid 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.
Pomyślałem, że to wygląda obiecująco, jednak wydaje się, że nie działa to w żaden sposób z OpenGL 3.2 (nie ES). Chociaż możliwe, że coś pomieszałem, bawiłem się tym dość długo i nie jestem pewien, jak to w ogóle ma być wykorzystane. Pomocne będą wszelkie dodatkowe informacje na temat tego, co zamierzasz renderować za pomocą tych programów cieniujących; Nie rozumiem, jak coś innego niż wypełnienie dałoby coś użytecznego, ale to nawet nie działa, biorąc pod uwagę, że wartość alfa gl_FragColor wydaje się być całkowicie ignorowana w OpenGL 3.2 ...
Problem, na który napotykam, próbując użyć sugerowanej implementacji, jest, myślę, że moduł cieniujący nigdy nie będzie rysował poza obiektem, który ma zostać zarysowany. Spowoduje to zatem narysowanie konspektu na zarysowanym obiekcie? Innymi słowy, kontur będzie wyłącznie zawarty w oryginalnym obiekcie do narysowania?
user1167662,
1
@BrunoLevy możesz uzyskać dodatkową koordynację w webGL, nie? Jeśli masz szczęście, możesz uzyskać te współrzędne z texcoordów, jeśli masz bardzo proste modele, ale w przeciwnym razie musisz tylko dodać nowe współrzędne. Byłoby zbyt miło, gdyby działało bez niego :). Wystarczy przekazać jeden skalar na wierzchołek (a następnie rozwinąć go do 3-wektorowego modułu cieniującego wierzchołki).
świnie
2
Ach, teraz widzę ... f_width () jest pod tym względem moim przyjacielem. Dzięki
Neil Gatenby
5
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.
nie, jeśli jest to wiązka GL_TRIANGLES: dostaniesz linie między nimi. W OpenGL 1.x lub starszej wersji używasz glPolygonMode. W najnowszym OpenGL grasz z modułem cieniującym geometrię.
Fabrice NEYRET
Jest to starożytny sposób robienia rzeczy, które należy porzucić.
Benny Mackney
2
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:
dla punktów zmień 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.
Odpowiedzi:
włączyć,
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.
źródło
From http://cone3d.gamedev.net/cgi-bin/index.pl?page=tutorials/ogladv/tut5
źródło
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:
I moduł cieniujący wierzchołek:
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.
źródło
Jeśli używasz stałego potoku (OpenGL <3.3) lub profilu zgodności, którego możesz użyć
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.
źródło
Najprostszym sposobem jest narysowanie prymitywów jako
GL_LINE_STRIP
.źródło
W Modern OpenGL (OpenGL 3.2 i wyżej) możesz użyć Geometru Shadera w tym celu:
Uwagi:
layout (line_strip, max_vertices=3) out;
nalayout (points, max_vertices=3) out;
źródło
Możesz użyć takich bibliotek glut:
dla kuli:
dla cylindra:
dla kostki:
źródło
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.
źródło
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
źródło
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), lubGL_TRIANGLE_STRIP
,GL_TRIANGLE_FAN
iGL_TRIANGLES
narysować wypełnione trójkątyjako pierwszy argument do twojego
lub
glDrawArrays(GLenum mode, GLint first, GLsizei count)
połączenia.źródło