3

部分的に重なるポイント プリミティブをレンダリングしています。フラグメント シェーダーは、各 Point プリミティブの四角形の一部を透明にシェーディングします (中心が塗りつぶされた円)。他のどのポイント プリミティブとも重ならないポイント プリミティブは、期待どおりにシェーディングされます (正方形の透明な領域は背景を示します)。

このようなポイント プリミティブが別のポイント プリミティブとオーバーラップすると、予期しない動作になります。具体的には、透明な領域は、元のポイントプリミティブの不透明な色を表示しませんが、代わりにそれをクリアして背景色を表示します。

つまり、頂点 ID 番号が大きいポイント プリミティブは、頂点 ID 番号が小さいポイント プリミティブの以前にシェーディングされたフラグメントをクリアします。

ポイント プリミティブは次のようにエンコードされます。

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);
}

結果は次のようになります。

ここに画像の説明を入力 ここに画像の説明を入力

重なり合う透明領域のクリアを防ぎながら、背景に対する透明性を維持する方法を見つけたいと思います。

ありがとうございました。

2016 年 5 月 25 日更新:

レンダー パイプライン記述子への次の追加により、固定関数のブレンドを有効にすることができました。

    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;

そして今、物事は期待どおりに見えます:

ここに画像の説明を入力

4

0 に答える 0