Как смешать цвет двух спрайтов с постоянной альфа в DirectX? - PullRequest
2 голосов
/ 20 августа 2009

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

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

Вот скриншот того, что на самом деле происходит со стандартным смешиванием (лучшее, что я могу получить): http://arcengames.com/share/FFActual.png Вот скриншот с макетом того, как бы я хотел, чтобы смешивание получилось (силовые поля были добавлены в тот же слой в Photoshop, а затем получили общее альфа-значение): http://arcengames.com/share/FFMockup.png

Вот как я это сделал в Photoshop: 1. Возьмите два изображения и удалите всю прозрачность (за исключением полностью прозрачных пикселей). 2. Объедините их в один слой, который смешивает цвет, но не имеет никакой частичной альфа. 3. Теперь установите глобальную прозрачность для этого слоя, скажем, 40%.

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

ОБНОВЛЕНИЕ: Хорошо, большое спасибо Гозу ниже, который предложил использовать Z-Buffer. Это работает! Смешивание, по большому счету, идеально и именно то, что я хотел бы. Единственная оставшаяся проблема? Используя этот новый метод, вокруг края изображения силового поля появляется огромный артефакт, который отображается последним. Смотрите это: http://www.arcengames.com/share/FFZBuffer.png

ОБНОВЛЕНИЕ: Ниже приведено окончательное решение в C # (SlimDX)

  1. Очистка ZBuffer до черного, прозрачного или белого цвета один раз за кадр имеет одинаковый эффект (это происходит перед вызовом BeginScene)

Direct3DWrapper.ClearDevice (SlimDX.Direct3D9.ClearFlags.ZBuffer, Color.Transparent, 0);

  1. Все остальные спрайты отрисовываются с Z = 1, для них ZBuffer отключен:

device.SetRenderState (RenderState.ZEnable, ZBufferType.DontUseZBuffer);

  1. Спрайты силового поля рисуются при Z = 2, с включенным ZBuffer, включенным ZWrite и ZFunc как Less:

device.SetRenderState (RenderState.ZEnable, ZBufferType.UseZBuffer); device.SetRenderState (RenderState.ZWriteEnable, true); device.SetRenderState (RenderState.ZFunc, Compare.Less);

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

device.SetRenderState (RenderState.AlphaTestEnable, true); device.SetRenderState (RenderState.AlphaFunc, Compare.GreaterEqual); device.SetRenderState (RenderState.AlphaRef, 55);

Обратите внимание, что AlphaRef находится на 55 из-за альфа-уровней, установленных в конкретном исходном изображении, которое я использовал. Если бы мое исходное изображение имело более высокое альфа-значение, то AlphaRef также должен был бы быть выше.

Ответы [ 3 ]

1 голос
/ 26 августа 2009

Трудно точно сказать, что вы пытаетесь достичь с помощью макета, поскольку оба силовых поля одного цвета; Вы хотите смешать цвета и ограничить альфа? Просто взять один из цветов?

Исходя из вышеприведенного обсуждения, не ясно, устанавливаете ли вы все соответствующие состояния визуализации:

D3DRS_ALPHABLENDENABLE = TRUE (по умолчанию: FALSE)

D3DRS_BLENDOP = D3DBLENDOP_MAX (по умолчанию: D3DBLENDOP_ADD)

D3DRS_SRCBLEND = D3DBLEND_ONE (по умолчанию: D3DBLEND_ONE)

D3DRS_DESTBLEND = D3DBLEND_ONE (по умолчанию: D3DBLEND_ZERO)

Звучит так, будто вы устанавливаете первые два, но как насчет последних двух?

1 голос
/ 26 августа 2009

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

то есть не смешанные настройки, это ваша проблема.

Редактировать: Можете ли вы использовать рендеринг в текстуру тогда? Если так, вы можете легко сделать то, что вы сделали в фотошопе. Поместите их все вместе в текстуру, а затем снова смешайте текстуру по экрану.

Edit2: как насчет

ALPHATESTENABLE  = TRUE;
ALPHAFUNC = LESS

ALPHABLENDENABLE = TRUE;
SRCBLEND = SRCALPHA;
DESTBLEND = INVSRCALPHA;

SEPERATEALPHABLENDENABLE = TRUE;
SRCBLENDALPHA = ONE;
DESTBLENDALPHA = ZERO;

Необходимо убедиться, что альфа очищена до 0xff в буфере кадров каждого кадра. Затем вы делаете стандартную альфа-смесь. при передаче значения альфа прямо в буфер. Это, однако, то, где вступает альфа-тест. Вы проверяете окончательное альфа-значение по сравнению с тем в заднем буфере. Если он меньше, чем в буферном буфере, этот пиксель еще не смешан и будет помещен в буфер кадра. Если оно равно (или больше), то оно уже смешано, и значение альфа будет отброшено.

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

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

В любом случае ... надеюсь, что один из этих методов поможет.

Edit3: вы визуализируете силовое поле с некоторой формой растушевки по краю? Скорее всего, этот край вызван тем фактом, что альфа-канал немного гаснет, а затем «слегка альфа-пиксели» записываются в z-буфер и, следовательно, любое последующее рисование не перезаписывает их.

Попробуйте следующие настройки

ALPHATESTENABLE = TRUE
ALPHAFUNC = GREATEREQUAL // if this doesn't work try less .. i may be being a retard
ALPHAREF = 255

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

1 голос
/ 20 августа 2009

Можно указать D3DBLENDOP , используемый при смешивании двух изображений вместе для альфа-канала. Похоже, вы используете D3DBLENDOP_ADD в настоящее время - попробуйте переключить его на D3DBLENDOP_MAX, так как при этом будет использоваться только непрозрачность "самого непрозрачного" изображения.

...