W jaki sposób renderujesz prymitywy jako wireframes w OpenGL?W jaki sposób renderujesz prymitywy jako wireframe w OpenGL?
Odpowiedz
Od 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);
wykonywanie dwóch połączeń jest zbędne. use GL_FRONT_AND_BACK – shoosh
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 wyżej.Teraz możesz nadal używać ich przez rozszerzenie kompatybilności, ale jeśli masz wybór między kompatybilnym do przodu i wstecznym, polecam pójście do pierwszego. – fouric
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
włączyć,
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
wrócić do normy.
Należy pamiętać, że rzeczy takie jak odwzorowanie tekstury i oświetlenie będą nadal stosowane do linii krawędziowych, jeśli są włączone, co może wyglądać dziwnie.
Lubię cię. Jeszcze 4 inne. –
Najprostszym sposobem jest narysowanie prymitywów jako GL_LINE_STRIP
.
glBegin(GL_LINE_STRIP);
/* Draw vertices here */
glEnd();
nie, jeśli jest to wiązka GL_TRIANGLES: otrzymasz linie między nimi. W OpenGL 1.x lub starszych używasz glPolygonMode. W najnowszym OpenGL grasz z modułem cieniującym geometrii. –
Zakładając naprzód zgodnego kontekst OpenGL 3 iw górę, można użyć glPolygonMode
Jak wspomniano wcześniej, ale należy pamiętać, że linie o grubości większej niż 1px są obecnie przestarzałe. Podczas gdy możesz rysować trójkąty jako ramkę z drutu, muszą być bardzo cienkie. W OpenGL ES można używać GL_LINES
z tym samym ograniczeniem.
W OpenGL możliwe jest użycie shaderów geometrii do odbierania trójkątów, rozbierania ich i wysyłania do rasteryzacji jako quady (naprawdę pary trójkątów) naśladujące grube linie. Całkiem proste, z wyjątkiem tego, że shadery geometrii są znane ze złego skalowania wydajności.
Co można zamiast tego zrobić, a także, co będzie działać również w OpenGL ES, należy użyć modułu cieniującego fragment. Pomyśl o zastosowaniu tekstury trójkąta z drutu do trójkąta. Poza tym, że nie jest potrzebna żadna tekstura, można ją wygenerować proceduralnie. Ale wystarczy rozmowa, zróbmy kod. Fragment shader:
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);
}
A vertex shader:
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)
i (0, 0, 1)
dla trzech wierzchołkach trójkąta (kolejność nie ma znaczenia, co sprawia, pakowanie w paski trójkątne potencjalnie łatwiejsze).
Oczywistą wadą tego podejścia jest fakt, że zjada on pewne współrzędne tekstury i trzeba zmodyfikować macierz wierzchołków. Może być rozwiązany za pomocą bardzo prostego modułu cieniującego geometrii, ale nadal podejrzewam, że będzie wolniejszy, niż tylko dostarczanie GPU z większą ilością danych.
Pomyślałem, że to wygląda obiecująco, ale wydaje się, że nie działa to w żadnym wypadku z OpenGL 3.2 (bez ES). Chociaż jest to możliwe, coś pomieszałem, grałem z tym całkiem sporo i nie jestem do końca pewien, w jaki sposób jest to przeznaczone do użycia. Przydałoby się więcej informacji o tym, co zamierzasz renderować za pomocą tych shaderów; Nie widzę, aby coś innego niż wypełnienie mogło przynieść coś użytecznego, ale to nawet nie działa, ponieważ wartość alpha gl_FragColor wydawała się całkowicie ignorowana w OpenGL 3.2 ... – user1167662
Oczywiście, że tak. Możesz odwołać się do czyjejś implementacji tego samego pomysłu na http://stackoverflow.com/questions/7361582/opengl-debugging-single-pass-wireframe-rendering. –
Czy jest w stanie wytworzyć linie grubsze niż 1 piksel? – user1167662
Można użyć biblioteki GLUT tak:
na kuli:
glutWireSphere(radius,20,20);
dla cylindra:
GLUquadric *quadratic = gluNewQuadric(); gluQuadricDrawStyle(quadratic,GLU_LINE); gluCylinder(quadratic,1,1,1,12,1);
dla Cube:
glutWireCube(1.5);
W Nowoczesnej OpenGL (OpenGL 3.2 i wyżej), można użyć Geometry Shader na to:
#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:
- o punkty, zmienić
layout (line_strip, max_vertices=3) out;
dolayout (points, max_vertices=3) out;
- Read more about Geometry Shaders
Jeśli to OpenGL ES 2.0 masz do czynienia, można wybrać jeden z ciągnących stałych trybu z
GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,
do rysowania linii,
GL_POINTS
(jeśli trzeba wyciągnąć tylko wierzchołki) lub
GL_TRIANGLE_STRIP
, GL_TRIANGLE_FAN
i GL_TRIANGLES
rysować wypełnione trójkąty
jako pierwszy argument do swojej
glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices)
lub
glDrawArrays(GLenum mode, GLint first, GLsizei count)
połączeń.
Jeśli używasz stałym rurociągiem (OpenGL < 3.3) lub profil kompatybilności można 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 tym przypadku można zmienić szerokość linii poprzez wywołanie glLineWidth
W przeciwnym razie trzeba zmień tryb wielokąta w twojej metodzie rysowania (glDrawElements, glDrawArrays, itp.), a możesz otrzymać niektóre zgrubne wyniki, ponieważ twoje dane wierzchołków dotyczą trójkątów i wyprowadzasz linie. Aby uzyskać najlepsze wyniki, należy rozważyć użycie Geometry shader lub utworzenie nowych danych dla modelu krawędziowego.
Bardziej szczegółowe informacje na temat używanej wersji OpenGL. – Vertexwahn
W [ModernGL] (https://github.com/cprogrammer1994/ModernGL) możesz użyć prostownika [wireframe] (http://moderngl.readthedocs.io/en/latest/Context.html#ModernGL.Context.wireframe) atrybut [Kontekst] (http://moderngl.readthedocs.io/en/latest/Context.html#ModernGL.Context) klasa –