Как вы представляете примитивы как каркасы в OpenGL? - PullRequest
199 голосов
/ 26 сентября 2008

Как вы отображаете примитивы как каркасы в OpenGL?

Ответы [ 8 ]

333 голосов
/ 26 сентября 2008
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

для включения,

glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

чтобы вернуться в нормальное состояние.

Обратите внимание, что такие вещи, как наложение текстуры и освещение, будут по-прежнему применяться к линиям каркаса, если они включены, что может выглядеть странно.

30 голосов
/ 26 сентября 2008

С 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);
18 голосов
/ 08 октября 2015

Если предположить, что в OpenGL 3 и выше поддерживается прямой совместимый контекст, вы можете использовать glPolygonMode, как уже упоминалось ранее, но учтите, что линии толщиной более 1 пикселя теперь не рекомендуется использовать. Поэтому, хотя вы можете рисовать треугольники в виде каркаса, они должны быть очень тонкими. В OpenGL ES вы можете использовать GL_LINES с тем же ограничением.

В OpenGL можно использовать геометрические шейдеры, чтобы брать входящие треугольники, разбирать их и отправлять их на растеризацию в виде квадратов (в действительности пар треугольников), эмулирующих толстые линии. Довольно просто, за исключением того, что геометрические шейдеры печально известны плохим масштабированием производительности.

Что вы можете сделать вместо этого, и что также будет работать в OpenGL ES, это использовать фрагмент шейдер. Подумайте о применении текстуры треугольника каркаса к треугольнику. За исключением того, что текстура не нужна, она может быть сгенерирована процедурно. Но хватит разговоров, давайте код. Фрагмент шейдера:

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

И вершинный шейдер:

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
}

Здесь барицентрические координаты - это просто (1, 0, 0), (0, 1, 0) и (0, 0, 1) для трех вершин треугольника (порядок на самом деле не имеет значения, что потенциально упрощает упаковку в треугольные полосы).

Очевидным недостатком этого подхода является то, что он съест некоторые текстурные координаты, и вам нужно изменить ваш массив вершин. Может быть решена с помощью очень простого геометрического шейдера, но я все еще подозреваю, что это будет медленнее, чем просто заполнение графического процессора большим количеством данных.

5 голосов
/ 19 марта 2014

Самый простой способ - нарисовать примитивы как GL_LINE_STRIP.

glBegin(GL_LINE_STRIP);
/* Draw vertices here */
glEnd();
4 голосов
/ 02 ноября 2017

Если вы используете фиксированный конвейер (OpenGL <3.3) или профиль совместимости, вы можете использовать </p>

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

В этом случае вы можете изменить ширину линии, вызвав glLineWidth

В противном случае вам нужно изменить режим многоугольника внутри вашего метода рисования (glDrawElements, glDrawArrays и т. Д.), И вы можете получить некоторые грубые результаты, потому что ваши данные вершин предназначены для треугольников и вы выводите линии. Для достижения наилучших результатов используйте шейдер Geometry или создайте новые данные для каркаса.

1 голос
/ 31 октября 2017

В Modern OpenGL (OpenGL 3.2 и выше) вы можете использовать для этого Geometry Shader:

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

Уведомления:

1 голос
/ 14 апреля 2017

Вы можете использовать библиотеки переизбытка, как это:

  1. для сферы:

    glutWireSphere(radius,20,20);
    
  2. для цилиндра:

    GLUquadric *quadratic = gluNewQuadric();
    gluQuadricDrawStyle(quadratic,GLU_LINE);
    gluCylinder(quadratic,1,1,1,12,1);
    
  3. для куба:

    glutWireCube(1.5);
    
0 голосов
/ 01 ноября 2017

Если это OpenGL ES 2.0 , с которым вы имеете дело, вы можете выбрать одну из констант режима рисования из

GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, для рисования линий,

GL_POINTS (если вам нужно рисовать только вершины) или

GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN и GL_TRIANGLES для рисования заполненных треугольников

в качестве первого аргумента для вашего

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

или

glDrawArrays(GLenum mode, GLint first, GLsizei count) звонки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...