Как объединить круги выбора юнитов?

16

Я хотел бы знать, как сделать этот эффект выделения объединенного круга. Вот изображения для иллюстрации:

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

В основном я ищу этот эффект:

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

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

По возможности я ищу чисто шейдерное решение.

Мат
источник
Не могли бы вы объяснить, что вы подразумеваете под «эффектом слияния»?
Wondra
Конечно, если вы посмотрите на верхние правые символы на скриншоте, эти наклейки не пересекаются, а два слева пересекают синий круг и объединяются. Я добавил новый скриншот, чтобы показать эффект.
МАТ
Вы настаиваете на шейдерном решении? Если нет, то вы просто решили это в своей последней картине.
Wondra
Последний скриншот показывает только тот эффект, на который я нацеливаюсь. Окончательный результат должен выглядеть как предыдущие скриншоты.
МАТ
1
Да, я согласен, я думаю, что они динамически строят круг сетки с текстурой, а затем обрезают сетку, чтобы объединить их. Это также хорошее решение, но я думаю, что оно более ограничено с точки зрения эффекта, который вы можете сделать.
Мат

Ответы:

8

Есть несколько трюков, которые вы можете сделать:

Z-буфер

После того, как вы отрендерили все остальные объекты, для каждого блока визуализируйте прозрачный круг меньшего размера с максимальным значением Z. Затем визуализируем круги выбора надписей на земле. Так как они находятся ниже в Z-порядке, они будут отброшены, когда находятся под юнитами.

Быть полностью прозрачным означает, что круг записывается только в Z-буфер (максимальное значение Z). Теперь, когда вы отрисовываете декали, они проверяются по значениям буфера Z, и если они проходят тест, они визуализируются (что происходит только за пределами кругов)

трафарет

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

Кромстер говорит, что поддерживает Монику
источник
Техника Z-буфера интересна, но я не понимаю, как первый прозрачный круг может обрезать наземные наклейки.
МАТ
0

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

JarkkoL
источник
1
Я предполагаю, что вы пропустили часть из своего ответа - чтобы передать все круги и радиусы шейдерам.
Кромстер говорит, что поддерживает Монику
@Krom Если OP проявит какой-либо интерес к решению, я с удовольствием предоставлю более подробную информацию.
JarkkoL
0

Вы имеете в виду эти синие круги на земле?

Возможно, есть более разумный способ сделать это, но рассмотрим мое решение в качестве примера того, как это можно сделать. Рендеринг ваших кругов в отдельную пустую текстуру размером с экран. На данный момент вы можете смешать их вместе, как вы хотите. В зависимости от ваших потребностей вы можете написать полный цвет или просто информацию о том, что круг присутствует в данном пикселе. Однако вам обязательно понадобится информация о глубине для каждого пикселя, который вы пишете, если вы хотите получить эффект Z-теста.

Когда вы визуализируете ландшафт после предыдущего шага, вы можете отобрать ранее созданную текстуру, используя координаты экрана в пиксельном шейдере, в качестве UV. Теперь вы знаете, что круг должен или не должен проецироваться на заданный пиксель местности. Однако в этом случае он будет работать так, как если бы Z-тест был отключен, поэтому местность не может скрыть ни одного круга. Если вы хотите, чтобы местность скрывала окружности за ней, выполните проверку глубины, прежде чем смешивать окружность с текстурой местности. Вы можете использовать небольшой уклон, чтобы включить рендеринг кругов, которые находятся чуть-чуть под землей, но вы все равно хотели бы, чтобы они отображались.


Редактировать: теперь, чтобы получить эффект объединенных кругов, вам нужно сделать следующее: при рендеринге на отдельную текстуру, вам нужно проверить, есть ли уже отрисованный круг, где вы пытаетесь создать новый. (Проверьте, есть ли у текстуры значение), если это так, сотрите этот пиксель. Это должно дать эффект «контура», когда два или более кругов перекрываются. Чтобы это работало правильно, вам нужно будет выполнить этот тест только для внутренней части круга, а не для границы. Таким образом, при рендеринге кругов записывайте в выходную текстуру какое-то конкретное значение, которое указывает, что внутри находится круг. Тогда вам просто не нужно ничего рендерить на круг внутри, и вы должны быть хорошими.

Edit2: для вашего простого красного / зеленого примера: перед рендерингом какого-либо пикселя проверьте, не является ли этот пиксель уже зеленым. Если это так, не визуализируйте. Это сделает свое дело. Фактически, при записи в текстуру вы можете даже использовать красный / зеленый снаружи / внутри круга, а затем при рендеринге ландшафта читать эти значения и преобразовывать их в желаемый цвет.

Если мой ответ окажется слишком абстрактным, дайте мне знать.

Elvithari
источник
Я понимаю общую идею, но, как вы говорите, мне нужно немного абстрагироваться от слитых кругов :)
МАТ
0

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

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

Единственное предостережение в том, что вы должны быть осторожны с глубокой борьбой. Вы можете использовать небольшое смещение, чтобы удостовериться, что контуры на самом деле находятся за внутренней частью, и будут устранены с помощью теста глубины. Альтернативой было бы использоватьglPolygonOffset() .

Допустим, у вас есть две окружности, параллельные плоскости xy, с центрами в точках (x1, y1, z) и (x2, y2, z). И у вас есть эти функции рисования:

// Draw interior part of circle, shown in green in the schematic in the question.
drawInterior(x, y, z);

// Draw outline of circle, shown in red in the schematic in the question.
drawOutline(x, y, z);

Последовательность рисования выглядит следующим образом с deltaнебольшим смещением:

glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
drawInterior(x1, y1, z + delta);
drawInterior(x2, y2, z + delta);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
drawOutline(x1, y1, z);
drawOutline(x2, y2, z);

источник
0

Вне моей головы, если эти надписи нарисованы как диски, я бы проверял каждый круг на предмет пересечения с каждым другим кругом и помещал точки пересечения в массив. Затем нарисуйте дуги, которые не находятся внутри пересечения. Это не шейдерное решение.

melfar
источник
Да, я тоже об этом думал :) но, как вы сказали, это не шейдерное решение и не очень общее решение. Но спасибо !
МАТ
Это довольно расплывчатое описание
Кромстер говорит, что поддерживает Монику
0

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

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

Draco18s больше не доверяет SE
источник
Благодарность! Поэтому вместо того, чтобы сначала рисовать видимые части, я должен начать с рендеринга прозрачных кругов в трафарет. Но как мне сделать круглые прозрачные круги? Я не могу ограничить части изображения, которые будут отображаться в трафарете. Когда я отрисовываю трафарет, все идет туда, я прав?
Doodlemeat
Да, именно поэтому второй проход (видимая часть) масштабируется больше: поэтому его границы больше, чем буфер трафарета. Вам просто нужно применить вершинный скаляр во втором проходе (ищите контурные шейдеры, большинство из них используют более простой скаляр, о котором я говорю). Вы также не можете изменить трафаретный буфер, если цвет прозрачный. В этом случае вам, вероятно, понадобится вторая текстурная маска, или вы можете использовать некоторую дистанционную математику, чтобы определить круг. Мне понадобится пара часов и доступ к Unity, чтобы предоставить любой код.
Draco18s больше не доверяет SE
Хм, а как насчет черно-белого изображения только для записи в буфер трафарета при первом проходе, чтобы черный стал 0, а белый - 1 в трафарете? Это вообще возможно?
Doodlemeat
Вот что я имел в виду под второй текстурной маской. Я уверен, что это сработает, но я просто не могу проверить, не имея Unity передо мной, чего у меня не будет более 24 часов.
Draco18s больше не доверяет SE