перекрывающиеся примитивы Metal Point и смешивание

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

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

Другими словами, точечные примитивы с более высоким идентификатором вершины очищают ранее заштрихованные фрагменты точечных примитивов с более низким идентификатором вершины.

Примитивы точек кодируются следующим образом:

command_encoder.drawPrimitives(.Point, vertexStart: 0, vertexCount: stroke.count) 

И вершинные и фрагментные шейдеры выглядят так:

vertex OutVertex vertex_func(constant InVertex* vertex_array [[buffer(0)]],
                          constant Uniforms& uniforms [[buffer(1)]],
                          uint vid [[vertex_id]]) {

    OutVertex out;
    InVertex in = vertex_array[vid];

    // transform vertex into NDC space
    out.position = uniforms.projection * float4(in.position.x, in.position.y, 0, 1);

    out.pointSize = 60;

    return out;
}

fragment float4 fragment_func(OutVertex vert [[stage_in]], float2 uv[[point_coord]]) {
    float2 uvPos = uv;

    uvPos.x -= 0.5f;
    uvPos.y -= 0.5f;

    uvPos *= 2.0f;

    float dist = sqrt(uvPos.x*uvPos.x + uvPos.y*uvPos.y);
    float circleAlpha = 1.0f-dist;

    half4 color = half4(0.0f, 0.0f, 1.0f, 1.0f);
    color *= circleAlpha;

    return float4(color.r, color.g, color.b, circleAlpha);
}

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

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

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

Спасибо.

Обновление от 25 мая 2016 г.:

Я смог включить фиксированное смешивание функций с этими дополнениями к моему дескриптору конвейера рендеринга:

    rpld.colorAttachments[0].blendingEnabled = true
    rpld.colorAttachments[0].rgbBlendOperation = .Add;
    rpld.colorAttachments[0].alphaBlendOperation = .Add;
    rpld.colorAttachments[0].sourceRGBBlendFactor = .One;
    rpld.colorAttachments[0].sourceAlphaBlendFactor = .One;
    rpld.colorAttachments[0].destinationRGBBlendFactor = .OneMinusSourceAlpha;
    rpld.colorAttachments[0].destinationAlphaBlendFactor = .OneMinusSourceAlpha;

И теперь все выглядит так, как ожидалось:

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


person Rene Limberger    schedule 24.05.2016    source источник
comment
Как вы настраиваете свой объект состояния трафарета глубины? Похоже, у вас включена глубинная запись, но на самом деле вы хотите, чтобы она была отключена. Кроме того, в зависимости от вашей функции смешивания вам может потребоваться отсортировать точки от дальних к ближним, чтобы получить желаемый эффект (например, если вы используете неассоциативную функцию смешивания, такую ​​как SrcAlpha, 1-SrcAlpha).   -  person warrenm    schedule 25.05.2016
comment
Спасибо, warrenm, за ответ. Поскольку я абсолютный новичок в Metal, я не знаю, что вы подразумеваете под включенной глубиной записи. Как я могу отключить его? Кроме того, я не устанавливаю никаких функций смешивания, поэтому я думаю, что получаю то, что по умолчанию. В этом случае меня не волнует глубина, потому что все примитивы Point находятся на одной и той же глубине Z от камеры. Это попытка перенести систему рисования мазков кистью с OpenGL на Metal.   -  person Rene Limberger    schedule 25.05.2016
comment
Интересно, я не ожидал такого эффекта при отключенном смешивании, но я рад, что вы нашли то, что вам подходит.   -  person warrenm    schedule 25.05.2016