Как webgl рисует спрайты (И меши) и проблемы прозрачности


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


Rendering Pipeline
Какая-то типовая инфографика по запросу opengl pipeline

В самом начале у нас есть 6 точек, соединенных между собой в треугольники

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

После этого все для всех плоскостей (На самом деле точек, образующих эти плоскости), считается положение в пространстве - fragment shader

После этого наступает самое интересное - нужно решить кто перекрывает кого



Я опущу сам процесс рисования текстуры на плоскости, можно почитать об этом отдельно.
После этого fragment shaderом рисуются пиксели

Для отрисовки этой картинки есть два пути

Opt. 1:
Painter's algorithm.
Шаг 1: нарисовать первую плоскость целиком

Шаг 2: нарисовать вторую плоскость поверх первой

Проблема тут выходит аж несколько - во-первых надо знать порядок, в котором рисовать фигуры, что означает что его нужно пересчитывать каждый кадр для подвижных объектов, во-вторых не всегда вообще глубину возможно установить. Или объекты пересекаются, или находятся на неоднозначной глубине друг к другу
 
Opt. 2:

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

Сначала можем нарисовать передний план
теперь нарисовать задний, просто выкидывая все пиксели, которые итак будут не видны
Это работает отлично, пока речь не заходит о полупрозрачности - нельзя просто так нарисовать непрозрачную текстуру поверх прозрачной и как-то там ее обрезать.
Тяжелый случай полупрозрачности
Есть решение

Первая отрисовка, это, по сути, отрисовка геометрии - берутся только абсолютно непрозрачные пиксели, и они же пишутся в буфер глубины

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

Это работает только внутри одного draw call - если вызывать последовательно несколько операций отрисовки, то непрозрачные пиксели в итоге начнут перекрывать прозрачные.

Для спрайтов тоже необходимо разделять операции - сначала рисуется вся непрозрачная "геометрия", затем поверх нее выборочно, со своим depth buffer, рисуется всевозможная прозрачность

Comments

Popular posts from this blog

Доработка webpack template #2

Доработка webpack template #1