Set round shape for a point in Metal, Swift

Viewed 122

I'm creating animation using Metal.

Now it looks like this.

I want the shape of every point to be round like this

Here is my current shader code:

struct VertexOut {
  float4 position [[position]];
  float pointSize [[point_size]];
};

struct Uniforms {
  float4x4 ndcMatrix;
  float ptmRatio;
  float pointSize;
};

vertex VertexOut vertex_shader(const device packed_float2 * vertex_array [[buffer(0)]],
                               const device Uniforms& uniforms [[buffer(1)]],
                               unsigned int vid [[vertex_id]]) {
    VertexOut vertexOut;
    float2 position = vertex_array[vid];
    vertexOut.position = uniforms.ndcMatrix * float4(position.x * uniforms.ptmRatio, position.y * uniforms.ptmRatio * 1.5, 0, 1);
    vertexOut.pointSize = uniforms.pointSize * 1.5;
    return vertexOut;
}

fragment half4 fragment_shader(VertexOut fragData [[stage_in]],
                               float2 pointCoord [[point_coord]]) {
    return half4(0.3, 0.3, 0.1, 0.1);
}

Before, I've already achieved the desired effect using fragment shader. My code was:

fragment half4 fragment_shader(VertexOut fragData [[stage_in]],
                               float2 pointCoord [[point_coord]]) {
    float dist = length(pointCoord - float2(0.4));
    float4 color = fragData.color;
    // Marking particles round shaped
    color.a = 1.0 - smoothstep(0.4, 0.4, dist);
    // Setting yellow color
    color.b = (0.3, 0.3, 0.1, 0.1);
    return half4(color);
}

It worked fine with shape, but it didn't give the desired color effect. So I need to find another way to set both color and shape correctly.

I've tried setting two separate fragment functions, one for shape and one for color, and then passing them to PipelineState, but it didn't work.

Any help is appreciated!

1 Answers

I've solved it in one function:

fragment half4 fragment_shader(VertexOut fragData [[stage_in]],
                              float2 pointCoord  [[point_coord]]) {
    if (length(pointCoord - float2(0.5)) > 0.5) {
        discard_fragment();
    }
    return half4(0.3, 0.3, 0.1, 0.1);
}
Related