Можно ли нарисовать толщину линии в фрагментном шейдере? - программирование
Подтвердить что ты не робот

Можно ли нарисовать толщину линии в фрагментном шейдере?

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

4b9b3361

Ответ 1

Довольно много возможно с помощью флеш-шейдеров. Просто посмотрите то, что делают некоторые парни. Я далек от этого уровня, но этот код может дать вам идею:

#define resolution vec2(500.0, 500.0)
#define Thickness 0.003

float drawLine(vec2 p1, vec2 p2) {
  vec2 uv = gl_FragCoord.xy / resolution.xy;

  float a = abs(distance(p1, uv));
  float b = abs(distance(p2, uv));
  float c = abs(distance(p1, p2));

  if ( a >= c || b >=  c ) return 0.0;

  float p = (a + b + c) * 0.5;

  // median to (p1, p2) vector
  float h = 2 / c * sqrt( p * ( p - a) * ( p - b) * ( p - c));

  return mix(1.0, 0.0, smoothstep(0.5 * Thickness, 1.5 * Thickness, h));
}

void main()
{
  gl_FragColor = vec4(
      max(
        max(
          drawLine(vec2(0.1, 0.1), vec2(0.1, 0.9)),
          drawLine(vec2(0.1, 0.9), vec2(0.7, 0.5))),
        drawLine(vec2(0.1, 0.1), vec2(0.7, 0.5))));
}

enter image description here

Другой альтернативой является проверка с помощью texture2D для цвета соседнего пикселя - таким образом, вы можете сделать изображение сияющим или утолщенным (например, если какой-либо пиксель регулировки белого цвета - сделать текущий пиксель белым, если рядом с соседним пикселем белый - сделать текущий пиксель серым).

Ответ 2

Вот мой подход. Пусть p1 и p2 - две точки, определяющие прямую, и пусть точка - это точка, расстояние до которой вы хотите измерить. Точка, скорее всего, gl_FragCoord.xy/resolution;

Здесь функция.

float distanceToLine(vec2 p1, vec2 p2, vec2 point) {
    float a = p1.y-p2.y;
    float b = p2.x-p1.x;
    return abs(a*point.x+b*point.y+p1.x*p2.y-p2.x*p1.y) / sqrt(a*a+b*b);
}

Затем используйте это в ваших функциях mix и smoothstep.

Также проверьте этот ответ: fooobar.com/questions/376784/...

Ответ 3

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

Вот приятное обсуждение этой темы (с образцами кода).

Ответ 4

Простой способ - просто добавить джиттер в вершинный шейдер: gl_Position + = vec4 (дельта, дельта, дельта, 0,0); где delta - размер пикселя, то есть 1,0/viewsize

Выполните прохождение рисования линии дважды, используя ноль, а затем дельту как джиттер (передайте как униформу).