Способ остановить цветовую взаимосвязь на GL_EDGES? - PullRequest
1 голос
/ 27 апреля 2020

В настоящее время я пишу клейкий рендер в Python.

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

Я реализовал средство выбора, которое позволяет мне рисовать определенный c подграф.

У меня есть альфа-значение, хранящееся в буфере для каждой вершины. Когда я щелкаю, альфа-значения изменяются, так что альфа = 1 рисуются только точки выбранного подграфа. Шейдер вызывается дважды:

# Draw Points
self.program_points.draw(gl.GL_POINTS)

# Draw Lines
self.program_points.draw(gl.GL_LINES, self.edge_buffer)

Моя проблема: альфа-значения установлены правильно, также ребра с обеими точками alpha = 1 отображаются правильно, но ребра, имеющие одну точку с alpha = 1 и одну с alpha = 0, исчезают.

Я хочу вообще не красить угасающие края. Есть ли способ проверить оба узла ребра и всегда выбрать более низкое значение альфа или что-то одинаково полезное.

Мой вершинный шейдер:

uniform vec2 resolution;

attribute vec3 position;
attribute float radius;

attribute float  color;
attribute float color_alpha;
attribute float id;

// for AA
varying vec4 v_position;
varying float v_radius;
varying float v_color_alpha;


varying vec4  v_id;
varying float  v_color;

void main (void)
{
    // this is for the picker!
    v_id = vec4 (mod(floor(id / (256*256)), 256) / 255.0,
             mod(floor(id /     (256)), 256) / 255.0,
             mod(floor(id /       (1)), 256) / 255.0,
             1.0 );
    // values to the fragment shader
    v_color         = color;
    v_color_alpha   = color_alpha;
    v_radius        = radius;

    //two pixel for AA
    gl_PointSize = 2.0+ ceil(2.0*radius);

    // hook for the Cameramovement
    v_position = <transform(position)>;
    gl_Position = v_position;
} ```

1 Ответ

1 голос
/ 27 апреля 2020

Ну, в принципе, есть два варианта:

  • значение переменной интерполируется по всему примитиву
  • значение переменной постоянно для примитива, используя flat квалификатор интерполяции. Если примитив не просто точка, это означает, что данные должны поступать только из одной вершин, которая называется вызывающей вершиной. Для GL_LINES обычно это первая вершина каждой строки.

Ни один из двух режимов не решит вашу проблему в общем случае. Рассмотрим следующий случай двух соединенных ребер AB и BC с присоединенными альфа-значениями 1, 1 и 0 соответственно:

A      B      C 
|------+------|
1      1      0

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

A     B D     C 
|-----+++-----|
1     1 0     0

Теперь B и D имеют одинаковую позицию, но разные альфа-значения - и это что такое модель вершины в графическом процессоре: набор атрибутов, а не только положение, и если один атрибут отличается, технически это другая вершина.

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

Есть ли способ проверить оба узла ребра и всегда выбрать более низкое альфа-значение или что-то одинаково полезное.

Не напрямую. Существует несколько нестандартных расширений GL, которые предоставят вам доступ к связанным данным каждой вершины, например AMD_shader_explicit_vertex_parameter или NV_fragment_shader_barycentric, но ни одно из них обычно не поддерживается и не поддерживается. это также намного выше версии GL, которую вы, похоже, используете здесь.

Однако для вашего случая использования вы могли бы сделать несколько простых хакерских фрагментов, например:

gl_FragColor.a = step(0.99999, v_color_alpha);

, который в основном устанавливает альфа в 0.0, если он ниже 0.99999, поэтому он удалит большую часть перехода. Обратите внимание, что фрагменты с альфа = 0 могут по-прежнему записываться в буферы глубины и трафарета, поэтому вместо них может потребоваться условное discard.

...