Обратите внимание, что такие вещи, как наложение текстур и освещение будут по-прежнему применяться к линиям каркаса, если они включены, что может выглядеть странно.
делать два звонка излишне. использовать GL_FRONT_AND_BACK
шош
6
В качестве дополнения к комментарию @ shoosh Красная книга гласит, что GL_FRONT и GL_BACK устарели и удалены из OpenGL 3.1 и выше. Теперь вы все равно можете использовать их через расширение совместимости, но если у вас есть выбор между прямой и обратной совместимостью, я бы рекомендовал перейти на первое.
четыре
1
Ссылка в этом ответе возвращает 404.
Ондрей Слинтак
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 linesvoid main(){float f_closest_edge = min(v_barycentric.x,
min(v_barycentric.y, v_barycentric.z));// see to which edge this pixel is the closestfloat 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 matrixvoid main(){
gl_Position = t_mvp * v_pos;
v_barycentric = v_bc;// just pass it on}
Здесь барицентрические координаты просто (1, 0, 0), (0, 1, 0)а (0, 0, 1)для трех вершин треугольника (порядок не имеет никакого значения, что делает упаковку в треугольные полосы потенциально легче).
Очевидным недостатком этого подхода является то, что он съест некоторые текстурные координаты, и вам нужно изменить ваш массив вершин. Может быть решен с помощью очень простого геометрического шейдера, но я все еще подозреваю, что это будет медленнее, чем просто заполнение графического процессора большим количеством данных.
Я думал, что это выглядело многообещающе, однако это не работает ни в каком качестве с OpenGL 3.2 (не-ES). Хотя, возможно, я что-то напутал, я немного поиграл с этим и не совсем уверен, как это вообще предполагается использовать. Любая дополнительная информация о том, что вы намереваетесь визуализировать с помощью этих шейдеров, будет полезна; Я не вижу, как что-то кроме заливки могло бы принести что-нибудь полезное, но это даже не работает, учитывая, что альфа-значение gl_FragColor, по-видимому, полностью игнорируется в OpenGL 3.2 ...
Проблема, с которой я сталкиваюсь, пытаясь использовать предложенную вами реализацию, я думаю, заключается в том, что шейдер никогда не будет рисовать вне объекта, который будет выделен. Это поэтому нарисует контур поверх обрисовываемого объекта? Другими словами, контур будет чисто содержаться в исходном объекте, который будет нарисован?
user1167662
1
@BrunoLevy вы можете получить дополнительные согласования в WebGL, нет? Если вам повезет, вы можете получить эти координаты от texcoords, если у вас очень простые модели, но в противном случае вам просто нужно добавить новые координаты. Было бы слишком хорошо, если бы это работало без него :). Все, что вам нужно, это передать один скаляр на вершину (а затем развернуть его до 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 или создания новых данных для каркаса.
нет, если это куча GL_TRIANGLES: между ними будут строки. В OpenGL 1.x или устаревшей версии вы используете glPolygonMode. В недавнем OpenGL вы играете с геометрическим шейдером.
Fabrice NEYRET
Это древний способ делать вещи, которые нужно оставить позади.
Бенни Макни
2
В 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();
}
Уведомления:
для очков, изменить layout (line_strip, max_vertices=3) out; наlayout (points, max_vertices=3) out;
Хороший и простой способ рисования линий с сглаживанием на цели рендеринга без сглаживания - рисовать прямоугольники шириной 4 пикселя с текстурой 1x4 со значениями альфа-канала {0., 1., 1., 0.} и использовать линейную фильтрацию с отключенным mip-отображением. Это сделает линии толщиной 2 пикселя, но вы можете изменить текстуру для различной толщины. Это быстрее и проще, чем бариметрические вычисления.
используйте эту функцию: void glPolygonMode (грань GLenum, режим GLenum);
face: указывает полигоны, к которым применяется режим. может быть GL_FRONT для лицевой стороны полигона и GL_BACK для его спины и GL_FRONT_AND_BACK для обоих.
режим: три режима определены и могут быть указаны в режиме:
GL_POINT: вершины многоугольника, помеченные как начало граничного ребра, отображаются в виде точек.
GL_LINE: Граничные ребра многоугольника отображаются в виде отрезков. (ваша цель)
GL_FILL: Внутренность многоугольника заполнена.
PS: glPolygonMode контролирует интерпретацию полигонов для растеризации в графическом конвейере.
Ответы:
включить,
чтобы вернуться к нормальной жизни.
Обратите внимание, что такие вещи, как наложение текстур и освещение будут по-прежнему применяться к линиям каркаса, если они включены, что может выглядеть странно.
источник
От http://cone3d.gamedev.net/cgi-bin/index.pl?page=tutorials/ogladv/tut5
источник
Если предположить, что в OpenGL 3 и более поздних версиях имеется совместимый с прямым контентом контекст, вы можете использовать его,
glPolygonMode
как упоминалось ранее, но учтите, что линии толщиной более 1 пикселя теперь не рекомендуются. Поэтому, хотя вы можете рисовать треугольники в виде каркаса, они должны быть очень тонкими. В OpenGL ES вы можете использоватьGL_LINES
с тем же ограничением.В OpenGL можно использовать геометрические шейдеры, чтобы брать входящие треугольники, разбирать их и отправлять их на растеризацию в виде квадратов (в действительности, пар треугольников), эмулирующих толстые линии. На самом деле довольно просто, за исключением того, что геометрические шейдеры печально известны плохим масштабированием производительности.
Вместо этого вы можете использовать в OpenGL ES использование шейдера фрагмента . Подумайте о применении текстуры треугольника каркаса к треугольнику. За исключением того, что текстура не нужна, она может быть сгенерирована процедурно. Но хватит разговоров, давайте закодируем. Фрагмент шейдера:
И вершинный шейдер:
Здесь барицентрические координаты просто
(1, 0, 0)
,(0, 1, 0)
а(0, 0, 1)
для трех вершин треугольника (порядок не имеет никакого значения, что делает упаковку в треугольные полосы потенциально легче).Очевидным недостатком этого подхода является то, что он съест некоторые текстурные координаты, и вам нужно изменить ваш массив вершин. Может быть решен с помощью очень простого геометрического шейдера, но я все еще подозреваю, что это будет медленнее, чем просто заполнение графического процессора большим количеством данных.
источник
Если вы используете фиксированный конвейер (OpenGL <3.3) или профиль совместимости, вы можете использовать
В этом случае вы можете изменить ширину линии, вызвав glLineWidth
В противном случае вам нужно изменить режим многоугольника внутри вашего метода рисования (glDrawElements, glDrawArrays и т. Д.), И вы можете получить некоторые грубые результаты, потому что ваши данные вершин предназначены для треугольников, а вы выводите линии. Для достижения наилучших результатов рассмотрите возможность использования шейдера Geometry или создания новых данных для каркаса.
источник
Самый простой способ - нарисовать примитивы как
GL_LINE_STRIP
.источник
В Modern OpenGL (OpenGL 3.2 и выше) вы можете использовать Geometry Shader для этого:
Уведомления:
layout (line_strip, max_vertices=3) out;
наlayout (points, max_vertices=3) out;
источник
Вы можете использовать библиотеки переизбытка, как это:
для сферы:
для цилиндра:
для куба:
источник
Хороший и простой способ рисования линий с сглаживанием на цели рендеринга без сглаживания - рисовать прямоугольники шириной 4 пикселя с текстурой 1x4 со значениями альфа-канала {0., 1., 1., 0.} и использовать линейную фильтрацию с отключенным mip-отображением. Это сделает линии толщиной 2 пикселя, но вы можете изменить текстуру для различной толщины. Это быстрее и проще, чем бариметрические вычисления.
источник
используйте эту функцию: void 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
рисовать заполненные треугольникив качестве первого аргумента к вашему
или
glDrawArrays(GLenum mode, GLint first, GLsizei count)
звонки.источник