webentwicklung-frage-antwort-db.com.de

Wie werden Grundelemente in OpenGL als Wireframes dargestellt?

Wie werden Grundelemente in OpenGL als Wireframes dargestellt?

194
Phineas
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

einschalten,

glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

um wieder normal zu sein.

Beachten Sie, dass Elemente wie Textur-Mapping und Beleuchtung immer noch auf die Drahtgitterlinien angewendet werden, wenn sie aktiviert sind. Dies kann seltsam aussehen.

327
Mike F

Von 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);
27
John Millikin

Unter der Annahme eines vorwärtskompatiblen Kontexts in OpenGL 3 und höher können Sie entweder glPolygonMode wie zuvor erwähnt verwenden, beachten Sie jedoch, dass Linien mit einer Dicke von mehr als 1px jetzt als veraltet gelten. Während Sie Dreiecke als Drahtrahmen zeichnen können, müssen sie sehr dünn sein. In OpenGL ES können Sie GL_LINES mit derselben Einschränkung verwenden.

In OpenGL ist es möglich, Geometrieshader zu verwenden, um eingehende Dreiecke zu nehmen, sie zu zerlegen und zur Rasterung als Quads (wirklich Dreieckspaare) zu senden, die dicke Linien emulieren. Eigentlich ziemlich einfach, mit der Ausnahme, dass Geometrieshader für schlechte Leistungsskalierung bekannt sind.

Was Sie dagegen tun können und was auch in OpenGL ES funktionieren wird, ist der Einsatz von fragment shader. Denken Sie daran, das Dreieck mit einer Textur aus einem Drahtrahmen zu versehen. Außer dass keine Textur benötigt wird, kann sie prozedural generiert werden. Aber genug reden, lass uns Code schreiben. 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);
}

Und 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
}

Hier sind die Schwerpunktskoordinaten einfach (1, 0, 0), (0, 1, 0) und (0, 0, 1) für die drei Dreieckscheitelpunkte (die Reihenfolge spielt keine Rolle, was das Packen in Dreieckstreifen möglicherweise einfacher macht).

Der offensichtliche Nachteil dieses Ansatzes ist, dass er einige Texturkoordinaten frisst und dass Sie Ihr Vertex-Array ändern müssen. Könnte mit einem sehr einfachen Geometrieshader gelöst werden, aber ich vermute immer noch, dass er langsamer ist, als nur der GPU mehr Daten zuzuführen.

18
the swine

Am einfachsten ist es, die Primitiven als GL_LINE_STRIP zu zeichnen.

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

Wenn Sie die feste Pipeline (OpenGL <3.3) oder das Kompatibilitätsprofil verwenden, können Sie verwenden

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

In diesem Fall können Sie die Linienbreite ändern, indem Sie glLineWidth aufrufen.

Andernfalls müssen Sie den Polygonmodus in Ihrer Zeichenmethode (glDrawElements, glDrawArrays usw.) ändern. Das Ergebnis kann zu groben Ergebnissen führen, da die Scheiteldaten für Dreiecke bestimmt sind und Sie Zeilen ausgeben. Für beste Ergebnisse sollten Sie einen Geometry-Shader verwenden oder neue Daten für das Drahtgitter erstellen.

3
Zaphyk

Sie können Glut-Bibliotheken wie folgt verwenden: 

  1. für eine Kugel:

    glutWireSphere(radius,20,20);
    
  2. für einen Zylinder: 

    GLUquadric *quadratic = gluNewQuadric();
    gluQuadricDrawStyle(quadratic,GLU_LINE);
    gluCylinder(quadratic,1,1,1,12,1);
    
  3. für einen Würfel:

    glutWireCube(1.5);
    
1
H.Mohcen

In Modern OpenGL (OpenGL 3.2 und höher) können Sie hierfür einen Geometry Shader verwenden: 

#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();
}

Hinweise: 

1
LMD

Wenn Sie sich mit OpenGL ES 2.0 beschäftigen, können Sie eine der Konstanten im Zeichenmodus auswählen

GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,, um Linien zu zeichnen,

GL_POINTS (wenn Sie nur Scheitelpunkte zeichnen müssen) oder

GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN und GL_TRIANGLES, um gefüllte Dreiecke zu zeichnen

als erstes Argument für deine 

glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices)

oder

glDrawArrays(GLenum mode, GLint first, GLsizei count) ruft auf. 

0
Victor