Como você processa primitivas como wireframes no OpenGL?

220

Como você processa primitivas como wireframes no OpenGL?


fonte
2
Seja mais específico na versão do OpenGL que você está usando.
precisa
Com ModernGL você simpli pode usar o wireframe atributo do Contexto classe
Szabolcs Dombi
usar GL_LINES para desenhar wireframes
oxina

Respostas:

367
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

para ligar,

glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

para voltar ao normal.

Observe que coisas como mapeamento de textura e iluminação ainda serão aplicadas às linhas de estrutura de arame se estiverem ativadas, o que pode parecer estranho.


fonte
2
Eu gosto de você. Mais 4 para ir.
Jo #
37

Em 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);
John Millikin
fonte
75
fazer duas chamadas é redundante. use GL_FRONT_AND_BACK
shoosh 30/09/08
6
Como um adendo ao comentário do @ shoosh, o Red Book declara que GL_FRONT e GL_BACK foram preteridos e removidos do OpenGL 3.1 e superior. Agora, você ainda pode usá-los através da extensão de compatibilidade, mas se tiver uma escolha entre compatibilidade com versões anteriores e versões anteriores, eu recomendaria a opção anterior.
fouric
1
O link nesta resposta retorna 404.
Ondrej Slinták
1
@ OndrejSlinták Está consertado agora.
MaxiMouse 17/04
24

Assumindo um contexto compatível com a frente no OpenGL 3 e superior, você pode usar glPolygonModecomo mencionado anteriormente, mas observe que as linhas com espessura superior a 1px agora estão obsoletas. Portanto, embora você possa desenhar triângulos como uma armação de arame, eles precisam ser muito finos. No OpenGL ES, você pode usar GL_LINEScom a mesma limitação.

No OpenGL, é possível usar sombreadores de geometria para pegar triângulos, desmontá-los e enviá-los para rasterização como quads (pares de triângulos realmente) emulando linhas grossas. Bem simples, na verdade, exceto que os shaders de geometria são notórios por uma escala de desempenho ruim.

O que você pode fazer e o que também funcionará no OpenGL ES é empregar o shader de fragmentos . Pense em aplicar uma textura de triângulo de arame ao triângulo. Exceto que nenhuma textura é necessária, ela pode ser gerada proceduralmente. Mas chega de conversa, vamos codificar. Shader de fragmento:

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

E shader de vértice:

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
}

Aqui, as coordenadas baricêntricas são simples (1, 0, 0), (0, 1, 0)e (0, 0, 1)para os três vértices do triângulo (a ordem realmente não importa, o que torna o empacotamento em tiras de triângulo potencialmente mais fácil).

A desvantagem óbvia dessa abordagem é que ela comerá algumas coordenadas de textura e você precisará modificar sua matriz de vértices. Poderia ser resolvido com um shader de geometria muito simples, mas eu ainda suspeitaria que será mais lento do que apenas alimentar a GPU com mais dados.

os porcos
fonte
Eu pensei que isso parecia promissor, no entanto, isso não parece funcionar de forma alguma com o OpenGL 3.2 (não-ES). Embora seja possível que eu tenha estragado alguma coisa, brinquei com isso por um tempo e não tenho muita certeza de como isso deve ser usado. Mais informações sobre o que você pretende render com esses shaders seriam úteis; Eu não vejo como outra coisa que não um preenchimento iria produzir nada de útil, mas que nem sequer funciona dado que o valor alfa de gl_FragColor apareceu a ser totalmente ignorado em OpenGL 3.2 ...
user1167662
2
Claro que sim. Você pode consultar a implementação de alguém da mesma ideia em stackoverflow.com/questions/7361582/… .
the suine
1
Acho que o problema ao tentar usar a implementação sugerida é que o sombreador nunca será desenhado fora do objeto a ser descrito. Isso, portanto, desenhará o contorno do objeto que está sendo delineado? Em outras palavras, o contorno será puramente contido no objeto original a ser desenhado?
precisa saber é o seguinte
1
@BrunoLevy, você pode obter coordenadas adicionais no webGL, não? Se você tiver sorte, poderá obter essas coordenadas dos cabos de texto se tiver modelos muito simples, mas, caso contrário, precisará adicionar novas coordenadas. Seria muito bom se funcionasse sem ele :). Tudo o que você precisa é passar um único escalar por vértice (e depois expandi-lo para um vetor de 3 no sombreador de vértices).
the suine
2
Ah, agora eu vejo ... f_width () é meu amigo, a esse respeito. Graças
Neil Gatenby
5

Se você estiver usando o pipeline fixo (OpenGL <3.3) ou o perfil de compatibilidade, poderá usar

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

Nesse caso, você pode alterar a largura da linha chamando glLineWidth

Caso contrário, você precisará alterar o modo de polígono dentro do seu método de desenho (glDrawElements, glDrawArrays, etc) e poderá obter alguns resultados aproximados, porque seus dados de vértice são para triângulos e você está produzindo linhas. Para obter melhores resultados, considere usar um sombreador Geometry ou criar novos dados para o wireframe.

Zaphyk
fonte
3

A maneira mais fácil é desenhar as primitivas como GL_LINE_STRIP .

glBegin(GL_LINE_STRIP);
/* Draw vertices here */
glEnd();
Hochester
fonte
não se for um monte de GL_TRIANGLES: você obteria linhas entre eles. No OpenGL 1.x ou legado, você usa glPolygonMode. No OpenGL recente, você brinca com o sombreador de geometria.
Fabrice NEYRET
Esta é uma maneira antiga de fazer coisas que precisam ser deixadas para trás.
Benny Mackney 22/07/19
2

No Modern OpenGL (OpenGL 3.2 e superior), você poderia usar um Geometry Shader para isso:

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

Avisos:

LMD
fonte
1

Você pode usar bibliotecas de excesso como esta:

  1. para uma esfera:

    glutWireSphere(radius,20,20);
    
  2. para um cilindro:

    GLUquadric *quadratic = gluNewQuadric();
    gluQuadricDrawStyle(quadratic,GLU_LINE);
    gluCylinder(quadratic,1,1,1,12,1);
    
  3. para um cubo:

    glutWireCube(1.5);
    
H.Mohcen
fonte
0

Uma maneira boa e simples de desenhar linhas com suavização de borda em um destino de renderização sem suavização de borda é desenhar retângulos de 4 pixels de largura com uma textura 1x4, com valores de canal alfa de {0., 1., 1., 0.} e use a filtragem linear com o mip-mapping desativado. Isso tornará as linhas com 2 pixels de espessura, mas você pode alterar a textura para diferentes espessuras. Isso é mais rápido e fácil do que os cálculos bariátricos.

Peter Soltesz
fonte
0

use esta função: void glPolygonMode (face GLenum, modo GLenum);

face: especifica os polígonos aos quais o modo se aplica. pode ser GL_FRONT para a frente do polígono e GL_BACK para as costas e GL_FRONT_AND_BACK para ambos.

mode: Três modos são definidos e podem ser especificados no modo:

GL_POINT: os vértices do polígono marcados como o início de uma aresta do limite são desenhados como pontos.

GL_LINE: As arestas de limite do polígono são desenhadas como segmentos de linha. (seu objetivo)

GL_FILL: O interior do polígono é preenchido.

PS: glPolygonMode controla a interpretação de polígonos para rasterização no pipeline de gráficos.

para obter mais informações, consulte as páginas de referência do OpenGL no grupo khronos: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonMode.xhtml

omar ghannou
fonte
-1

Se você estiver lidando com o OpenGL ES 2.0 , poderá escolher uma das constantes do modo de desenho em

GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, desenhar linhas,

GL_POINTS (se você precisar desenhar apenas vértices) ou

GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, E GL_TRIANGLESpara desenhar triângulos a cheio

como primeiro argumento para o seu

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

ou

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

Vencedor
fonte