Як ви відображаєте примітиви як каркасні рамки у OpenGL?


220

Як ви відображаєте примітиви як каркасні рамки у OpenGL?

opengl 

2
Будьте більш конкретними щодо версії OpenGL, яку ви використовуєте.
Vertexwahn

За допомогою ModernGL ви можете спростити використання атрибута каркасної рамки класу « Контекст»
Szabolcs Dombi

використовуйте GL_LINES для малювання каркасів
oxine

Відповіді:


367
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

увімкнути,

glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

щоб повернутися до нормального.

Зауважте, що такі речі, як картографування текстур та освітлення, все ще застосовуватимуться до ліній каркасних рам, якщо вони включені, що може виглядати дивно.


2
Ти мені подобаєшся. Ще 4.
Jo So

37

Від 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);

75
здійснення двох дзвінків зайве. використовувати GL_FRONT_AND_BACK
shoosh

6
Як доповнення до коментаря @ shoosh, Червона книга зазначає, що GL_FRONT та GL_BACK застаріли та вилучені з OpenGL 3.1 та новіших версій. Тепер ви все ще можете використовувати їх за допомогою розширення сумісності, але якщо у вас є вибір між сумісними вперед та назад, я рекомендую перейти до першого.
fouric

1
Посилання у цій відповіді повертає 404.
Ondrej Slinták

1
@ OndrejSlinták Це виправлено зараз.
MaxiMouse

24

Припускаючи контекст, сумісний з прямим пересуванням у 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) для трьох вершин трикутника (порядок насправді не має значення, що робить упаковку в трикутникові смужки потенційно простішою).

Очевидним недоліком такого підходу є те, що він буде мати деякі координати текстури і вам потрібно змінити вершину масиву. Можна вирішити дуже простий шейдер для геометрії, але я все-таки підозрюю, що це буде повільніше, ніж просто подавати GPU з більшою кількістю даних.


Я вважав, що це виглядає багатообіцяюче, однак це, здається, не працює ні з якою функцією з OpenGL 3.2 (не-ES). Хоча можливо, я щось зіпсував, я пограв з цим зовсім небагато, і не дуже впевнений, як це взагалі призначено використовувати. Будь-яка додаткова інформація про те, що ви насправді маєте зробити за допомогою цих шейдерів, була б корисною; Я не бачу, як щось, окрім заливки, призвело б до корисного, але це навіть не спрацювало, враховуючи, що значення альфа gl_FragColor виявилося повністю ігнорованим у OpenGL 3.2 ...
користувач1167662,

2
Звичайно, так і є. Ви можете посилатися на реалізацію тієї самої ідеї чиїсь у stackoverflow.com/questions/7361582/… .
свиня

1
Проблема, з якою я стикаюся, намагаючись використати запропоновану вами реалізацію, полягає в тому, що шейдер ніколи не буде малювати поза об'єктом, який слід окреслити. Отже, це накреслить контур над об'єктом, який окреслюється? Іншими словами, контур буде чисто міститися в оригінальному об'єкті, який потрібно намалювати?
користувач1167662

1
@BrunoLevy ви можете отримати додаткову координацію в webGL, ні? Якщо вам пощастить, ви можете отримати ці координати з текстових рядків, якщо у вас дуже прості моделі, але в іншому випадку потрібно просто додати нові координати. Було б дуже приємно, якби це працювало без нього :). Все, що вам потрібно, це пропустити один скаляр по вершині (а потім розгорнути його до 3-го вектора в вершинній шейдері).
свиня

2
Ах, тепер я бачу ... f_width () - мій друг у цьому відношенні. Спасибі
Ніл Гатенбі

5

Якщо ви використовуєте фіксований конвеєр (OpenGL <3.3) або профіль сумісності, який ви можете використовувати

//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 або створення нових даних для каркасного каркаса.


3

Найпростіший спосіб - намалювати примітиви як GL_LINE_STRIP.

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

ні, якщо це купа GL_TRIANGLES: ви отримаєте лінії між ними. У OpenGL 1.x або спадщині ви використовуєте glPolygonMode. В останній OpenGL ви граєте з шейдером геометрії.
Fabrice NEYRET

Це давній спосіб робити речі, які потрібно залишити позаду.
Бенні Макні

2

У Modern OpenGL (OpenGL 3.2 та новіших версіях) ви можете використовувати для цього шейдер геометрії:

#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

Ви можете використовувати такі бібліотеки, як це:

  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

Хороший і простий спосіб малювання анти-псевдонімічних ліній на цілі візуалізації, що не має псевдоніму, - це намалювати прямокутники шириною 4 пікселі з текстурою 1x4, зі значеннями альфа-каналів {0., 1., 1., 0.} та використовувати лінійну фільтрацію з відключенням mip-відображення. Це зробить лінії на 2 пікселі товстими, але ви можете змінити текстуру для різної товщини. Це швидше і простіше, ніж бариметричні розрахунки.


0

використовувати цю функцію: недійсний glPolygonMode (обличчя GLenum, режим GLenum);

face: Вказує багатокутники, до яких застосовується режим. може бути GL_FRONT для передньої сторони багатокутника та GL_BACK для його спини та GL_FRONT_AND_BACK для обох.

режим: Визначено три режими, які можна вказати в режимі:

GL_POINT: Вершини багатокутника, які позначені як початок граничного краю, малюються як точки.

GL_LINE: Прикордонні краї багатокутника намальовані у вигляді відрізків ліній. (ваша ціль)

GL_FILL: Внутрішня частина полігону заповнена.

PS: glPolygonMode контролює інтерпретацію полігонів для растерізації в графічному конвеєрі.

Для отримання додаткової інформації дивіться довідкові сторінки OpenGL у групі khronos: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonMode.xhtml


-1

Якщо ви працюєте з 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) дзвінки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.