graphicsrenderingmetal

Linear interpolation for vertices to achieve faceted appearance in Metal


I was trying to make an artistic look with Metal. The effect to achieve is to render a faceted teapot based on triangle primitives, instead of a smooth and mellow teapot. I am not sure how I can do this. I know I should tell Metal to calculate pixels inside a triangle as if the triangle is planar, instead of looking at nearby triangles and interpolate pixels. Should I do this in vertex function, or do some setting with rasterization process?

teapot

(Image: https://sketchfab.com/3d-models/art-reference-utah-teapot-4c02605ea63541b6aa053df167befe36)


Solution

  • The thing that controls how the faces will look is attribute interpolation.

    There are many different kinds of interpolation, and you can check them out in Metal Shading Language Specification (https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf, 5.4 Sampling and Interpolation Attributes ).

    If you want a flat look, there are two ways to do it: you will either want to use flat interpolation or change the initial model.

    You can set up interpolation in shader code. You will need to decorate your fragment shader inputs with attributes for interpolation.

    If you have directional lighting or any other lighting, to achieve this flat look your normals will need to be flat across the faces, to do that you want to mark fragment shader inputs somewhat like this

    struct FragmentInput
    {
        float3 position;
        float4 color;
        float3 normal [[flat]];
    };
    

    Flat interpolation will use data from the first vertex in a triangle and use it for the whole triangle.

    And result will also somewhat depend on the initial vertex data itself.

    Other way is to just have vertices that belong to one face (in your case one face is square consisting of two triangles) have the same value for normal. This way your model will have more vertices (some of the vertices will share the same position, but they will belong to different faces). You should be able to do it in any 3D editor.

    You can try and experiment with different kinds of interpolation for achieving different looks.

    Thanks to @warrenm for the comment about provoking vertex.