Як ви відображаєте примітиви як каркасні рамки у OpenGL?
Як ви відображаєте примітиви як каркасні рамки у OpenGL?
Відповіді:
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
увімкнути,
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
щоб повернутися до нормального.
Зауважте, що такі речі, як картографування текстур та освітлення, все ще застосовуватимуться до ліній каркасних рам, якщо вони включені, що може виглядати дивно.
Від 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);
Припускаючи контекст, сумісний з прямим пересуванням у 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.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 або створення нових даних для каркасного каркаса.
Найпростіший спосіб - намалювати примітиви як GL_LINE_STRIP
.
glBegin(GL_LINE_STRIP);
/* Draw vertices here */
glEnd();
У 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();
}
Повідомлення:
layout (line_strip, max_vertices=3) out;
наlayout (points, max_vertices=3) out;
Хороший і простий спосіб малювання анти-псевдонімічних ліній на цілі візуалізації, що не має псевдоніму, - це намалювати прямокутники шириною 4 пікселі з текстурою 1x4, зі значеннями альфа-каналів {0., 1., 1., 0.} та використовувати лінійну фільтрацію з відключенням mip-відображення. Це зробить лінії на 2 пікселі товстими, але ви можете змінити текстуру для різної товщини. Це швидше і простіше, ніж бариметричні розрахунки.
використовувати цю функцію: недійсний 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
Якщо ви працюєте з 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)
дзвінки.