Как я могу визуализировать бесконечную 2D-сетку в GLSL?

В идеале я хотел бы нарисовать один четырехугольник, а создание реальных линий сетки сделать с помощью GLSL.

В моей попытке до сих пор вершинный шейдер:

#version 400

layout (location = 0) in vec4 in_position;
layout (location = 2) in vec3 in_UV;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

smooth out vec3 ex_UV;
smooth out vec3 ex_originalPosition;

void main()
{
    gl_Position = projection * view * model * in_position;

    ex_UV = in_UV;
    ex_originalPosition = vec3(in_position.xyz);
}

Матрица модели масштабирует четверку на какое-то большое число, например 10 000.

#version 400

layout (location = 0) out vec4 color;

smooth in vec3 ex_UV;
smooth in vec3 ex_originalPosition;

uniform vec4 lineColor;

void main(void)
{
    if(fract(ex_UV.x / 0.001f) < 0.01f || fract(ex_UV.y / 0.001f) < 0.01f)
        color = lineColor;
    else
        color = vec4(0);
}

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

введите здесь описание изображения

введите здесь описание изображения

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

Есть ли более простой способ сделать это?

РЕДАКТИРОВАТЬ

Скриншоты по запросу:

Линии VBO с мультисэмплированным кадровым буфером x8

введите здесь описание изображения

Линии VBO с мультисэмплированным кадровым буфером x8 и glEnable(GL_LINE_SMOOTH)

введите здесь описание изображения

я остановился на

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


person NeomerArcana    schedule 15.06.2015    source источник
comment
Мне было бы интересно увидеть результат с GL_LINES и мультисэмплингом. Не могли бы вы опубликовать скриншот в качестве обновления?   -  person jozxyqk    schedule 15.06.2015
comment
Результаты практически идентичны вашему вопросу. Однако, в конце концов, я обнаружил, что мне на самом деле не нужна бесконечная плоскость, поэтому вместо этого я использовал гораздо меньший четырехугольник с круговым градиентом от начала координат в качестве альфы. Это служит моим целям, хотя я признаю, что ваш ответ верен в отношении фактического вопроса, который я задал.   -  person NeomerArcana    schedule 16.06.2015


Ответы (2)


Простой случай псевдонима. Как и в случае с полигональным рендерингом, ваш фрагментный шейдер запускается один раз для каждого пикселя. Цвет вычисляется только для одной центральной координаты и не отражает истинный цвет.

введите здесь описание изображения

  1. Вы можете создать мультисемпловый FBO и включить суперсэмплинг. Но это дорого.
  2. Вы можете математически точно вычислить, сколько площади линии и пустой области сетки находится под каждым пикселем, а затем соответствующим образом раскрасить их во фрагментном шейдере. Учитывая, что это равномерная сетка, это может быть в пределах возможного, но математика все еще может быть довольно сложной.
  3. Mipmapping уже делает это для текстур. Создайте текстуру сетки всего несколькими линиями и наложите ее так, чтобы она повторялась для вашего действительно большого четырехугольника (не забудьте установить GL_REPEAT). Настройте правильные параметры фильтрации mipmap для текстуры и вызовите glGenerateMipmap. . Когда вы вызываете texture2D()/texture() во фрагментном шейдере, OpenGL автоматически вычисляет, какой уровень mipmap использовать, основываясь на разнице координат текстуры между соседними пикселями. Наконец, настройте анизотропную фильтрацию, чтобы сетка выглядела еще более потрясающе.

    введите здесь описание изображения

Если вы хотите, чтобы сетка была действительно «бесконечной», я видел, как некоторые средства визуализации океана соединяют края сетки с горизонтом с помощью вертикальной геометрии. Если у вас достаточно сетки перед ними, вы, возможно, сможете установить для них один плоский цвет — цвет на верхнем уровне вашего MIP-карты.


Примеры (относительно комментариев):

1024x2 GL_LINES, нарисованные из VBO
введите здесь описание изображения
45fps (нарисовано 100 раз для бенчмарка в разрешении HD)

См. комментарии относительно мультисэмплинга для устранения псевдонимов GL_LINES.

Текстура 32^2, наложенная на четырехугольник с помощью мипмаппинга
введите здесь описание изображения
< sup>954 кадра в секунду (нарисовано 100 раз для теста в разрешении HD)

Image img;
int w = 128;
int h = 128;
img.resize(w, h, 1);
for (int j = 0; j < h; ++j)
    for (int i = 0; i < w; ++i)
        img.data[j*w + i] = (i < w / 16 || j < h / 16 ? 255 : 0);

tex = img.upload();

glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);

...

//for the quick and dirty, immediate mode
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
glBegin(GL_QUADS);
glTexCoord2f(0,       0); glVertex3f(0, 0, 0);
glTexCoord2f(1024,    0); glVertex3f(1, 0, 0);
glTexCoord2f(1024, 1024); glVertex3f(1, 0, 1);
glTexCoord2f(0,    1024); glVertex3f(0, 0, 1);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
person jozxyqk    schedule 15.06.2015
comment
Текстуры вообще не гарантируют беззазорных линий. Кроме того, вы вводите много ненужной обработки фрагментов и сэмплирования, когда в линейном подходе будут запускаться только те фрагменты, которые действительно вносят вклад в строки. Целью было просто нарисовать 2D сетку, а для меня все ваши подходы - огромный перебор. - person Bartek Banachewicz; 15.06.2015
comment
Во-первых, он специально предоставляет методы применения текстур для получения сглаженных линий, после чего следует сравнение наивного текстурирования четырехугольника с тем, чтобы сделать это красиво. Для второго пункта нам все еще нужна цитата, для которой техника работает быстрее. - person Blarglenarf; 15.06.2015
comment
Интересные результаты работы. Теперь я могу с чистой совестью проголосовать за это :) - person Bartek Banachewicz; 15.06.2015

вы можете видеть, что даже эти строки отображаются с промежутками через них

О, конечно можем. И это потому, что вы оскорбили CG 101. (Без обид :))

Мы используем GL_LINES по причине; рисовать сплошные линии на экране компьютера нетривиально (хотя и решаемо). Я имею в виду что-то вроде этого. То, что вы сделали, выполняет вычисления с числами с плавающей запятой и будет означать отрисовку субпиксельных линий (т. Е. Пробелов).

Мое предложение состояло бы в том, чтобы отказаться от этого кода GLSL и сгенерировать линии как обычные вершины. Вероятно, это будет быстрее, и вы получите надлежащие результаты.

Вы также сможете получить желаемый эффект «исчезновения на расстоянии», используя обычные вычисления тумана.

person Bartek Banachewicz    schedule 15.06.2015
comment
... теперь я чувствую себя глупо. Навскидку знаете ли вы, может ли геометрический шейдер иметь треугольники в качестве входных данных и линии в качестве выходных данных? - person NeomerArcana; 15.06.2015
comment
@NeomerArcana Если вы действительно хотите сделать это в шейдерах (вы можете почувствовать это в воздухе: D), то я бы нарисовал четырехугольник и разбил его до желаемой плотности. Опять же, это потребует аппаратной поддержки, сделанной заранее, чтобы выдерживать такие нагрузки. Помимо этого, вы можете обрезать примитивы в шейдере геометрии, поэтому сокращение каждого треугольника до линии должно быть в порядке. Только 1_ - person Bartek Banachewicz; 15.06.2015
comment
Да, уже на нем в шейдере геометрии. Получил 2D-квадрат, теперь мне просто нужно его разделить. - person NeomerArcana; 15.06.2015
comment
@NeomerArcana Просто чтобы уточнить, я хотел использовать шейдер тесселяции; Вывод одной строки на один треугольник в GS — это нормально. Вывода тысяч строк на треугольник не будет! - person Bartek Banachewicz; 15.06.2015
comment
Рисование такого количества линий будет намного медленнее, чем один четырехугольник, и примитивы линий все равно должны быть сглажены. GL_LINE_SMOOTH может помочь, но он по-прежнему не работает на пересечениях линий. - person jozxyqk; 15.06.2015
comment
@jozxyqk [citation-needed] будет медленнее. Также я не вижу требования, чтобы линейные примитивы по-прежнему нуждались в сглаживании. Кроме того, существуют и другие алгоритмы и подходы к рисованию сглаженных линий. - person Bartek Banachewicz; 15.06.2015
comment
Справедливости ради, я не проверял его, поэтому я просто скажу, что подозреваю, что он будет немного медленнее. ОП хочет гладкую сетку. Примитивы линий рисования без какого-либо сглаживания, как в настоящее время описывает этот ответ, не дадут им желаемого результата. - person jozxyqk; 15.06.2015
comment
Да, в идеале они должны быть красивыми и сглаженными. - person NeomerArcana; 15.06.2015
comment
@NeomerArcana Тогда, возможно, этот GPU Gem может помочь. Но опять же, как я уже сказал, для рисования линий нужно многое, и я бы все равно придерживался, ну, рисования линий. Другой ответ от jozxyqk действительно только перемещает проблему, поскольку он все еще работает в пространстве фрагментов (даже если это выборка текстуры). - person Bartek Banachewicz; 15.06.2015
comment
Кажется, это не имеет большого значения, я использую мультисэмплерный буфер, и пока GL_LINES отлично рендерятся и сглаживаются. - person NeomerArcana; 15.06.2015
comment
Они будут сглажены, потому что вы используете мультисэмплинг, а не потому, что вы используете GL_LINES. - person Blarglenarf; 15.06.2015
comment
Да, я понимаю это. Просто говорю, что я получаю желаемый результат без ручного сглаживания линий. - person NeomerArcana; 15.06.2015