enter image description here

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

К сожалению, я использую неизвестный игровой движок, где разработчики либо неактивны, либо им просто все равно, поэтому я надеюсь, что кто-то здесь может помочь, но суть такова:

start batch drawing
draw small tree at location: x, y, 1  // 1 to make it appear in front
draw big tree at location: x, y, 0
end batch drawing

Что вообще нужно делать в приложении OpenGL / glsl, чтобы что-то вроде этого работало?

Я уже пробовал эквивалент

glEnable( GL_BLEND );
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2
tea 1 Янв 2018 в 14:31

2 ответа

Лучший ответ

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

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

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

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

2
Yunnosch 1 Янв 2018 в 14:35

Думаю, мой второй комментарий непонятен. Я уже нашел проблему и ее решение.

Проблема: альфа не отбрасывается во фрагментном шейдере

Решение:

if(gl_FragColor.a < 0.5)
        discard;

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

Спасибо всем за ваше время.

0
tea 1 Янв 2018 в 14:48