Comment rendre les primitives comme fil de fer dans OpenGL?

Comment rendre les primitives comme fil de fer dans OpenGL?

glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 

allumer,

 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); 

pour revenir à la normale.

Notez que des choses comme le mappage de texture et l’éclairage seront toujours appliquées aux lignes filaires si elles sont activées, ce qui peut sembler étrange.

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

En supposant un contexte compatible avec Forward dans OpenGL 3 et plus, vous pouvez soit utiliser glPolygonMode comme mentionné précédemment, mais notez que les lignes avec une épaisseur supérieure à 1px sont maintenant obsolètes. Donc, bien que vous puissiez dessiner des sortingangles en fil de fer, ils doivent être très fins. Dans OpenGL ES, vous pouvez utiliser GL_LINES avec la même limitation.

Dans OpenGL, il est possible d’utiliser des shaders de géomésortinge pour prendre des sortingangles entrants, les désassembler et les envoyer pour les rasteriser sous forme de quads (paires de sortingangles réellement) émulant des lignes épaisses. Assez simple, vraiment, sauf que les shaders de géomésortinge sont notoires pour la réduction des performances.

Ce que vous pouvez faire à la place, et ce qui fonctionnera également dans OpenGL ES, est d’utiliser un fragment shader. Pensez à appliquer une texture de sortingangle filaire au sortingangle. Sauf qu’aucune texture n’est nécessaire, elle peut être générée de manière procédurale. Mais assez parlé, codons. Fragment shader:

 in vec3 v_barycensortingc; // barycensortingc coordinate inside the sortingangle uniform float f_thickness; // thickness of the rendered lines void main() { float f_closest_edge = min(v_barycensortingc.x, min(v_barycensortingc.y, v_barycensortingc.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); } 

Et vertex shader:

 in vec4 v_pos; // position of the vertices in vec3 v_bc; // barycensortingc coordinate inside the sortingangle out vec3 v_barycensortingc; // barycensortingc coordinate inside the sortingangle uniform mat4 t_mvp; // modeview-projection masortingx void main() { gl_Position = t_mvp * v_pos; v_barycensortingc = v_bc; // just pass it on } 

Ici, les coordonnées barycensortingques sont simplement (1, 0, 0) , (0, 1, 0) et (0, 0, 1) pour les trois sumts du sortingangle (l’ordre n’a pas vraiment d’importance, ce qui Plus facile).

L’inconvénient évident de cette approche est qu’elle va manger des coordonnées de texture et que vous devez modifier votre tableau de sumts. Pourrait être résolu avec un shader de géomésortinge très simple mais je soupçonnerais toujours qu’il sera plus lent que de simplement alimenter le GPU avec plus de données.

Le moyen le plus simple consiste à dessiner les primitives sous la forme GL_LINE_STRIP .

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

Si vous utilisez le pipeline fixe (OpenGL <3.3) ou le profil de compatibilité que vous pouvez utiliser

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

Dans ce cas, vous pouvez modifier la largeur de la ligne en appelant glLineWidth

Sinon, vous devez changer le mode polygone dans votre méthode de dessin (glDrawElements, glDrawArrays, etc.) et vous pouvez vous retrouver avec des résultats approximatifs car vos données de sumt sont destinées aux sortingangles et vous êtes en train de générer des lignes. Pour de meilleurs résultats, utilisez un shader Geometry ou créez de nouvelles données pour le wireframe.

Vous pouvez utiliser les bibliothèques de glut comme ceci:

  1. pour une sphère:

     glutWireSphere(radius,20,20); 
  2. pour un cylindre:

     GLUquadric *quadratic = gluNewQuadric(); gluQuadricDrawStyle(quadratic,GLU_LINE); gluCylinder(quadratic,1,1,1,12,1); 
  3. pour un cube:

     glutWireCube(1.5); 

Dans OpenGL moderne (OpenGL 3.2 et versions ultérieures), vous pouvez utiliser un Geometry Shader pour cela:

 #version 330 layout (sortingangles) in; layout (line_ssortingp /*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(); } 

Avis:

  • pour les points, changez la layout (line_ssortingp, max_vertices=3) out; à la layout (points, max_vertices=3) out; en layout (points, max_vertices=3) out;
  • En savoir plus sur les géomésortinges Shaders

Si vous avez affaire à OpenGL ES 2.0 , vous pouvez choisir l’une des constantes du mode de dessin à partir de

GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, pour tracer des lignes,

GL_POINTS (si vous avez besoin de ne dessiner que des sumts), ou

GL_TRIANGLE_STRIP , GL_TRIANGLE_FAN et GL_TRIANGLES pour dessiner des sortingangles remplis

comme premier argument à votre

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

ou

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