Search code examples
graphicsvulkanvector-graphics

How to calculate if a triangle is back-facing or front facing in Vulkan


In this page: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFrontFace.html They give this equation: enter image description here

How would you apply that formula for example to a triangle with these coordinates?:

p0(-0.5, -0.5)

p1(0.5, -0.5)

p2(0.5, 0.5)

Does it expand to something like this?

(-1/2) ( ((p0.x)(p1.y) - (p1.x)(p0.y)) + ((p1.x)(p2.y) - (p2.x)(p1.y)) + ((p2.x)(p0.y) - (p0.x)(p2.y)) )

(-1/2) ( ((-0.5)(-0.5) - (0.5)(-0.5)) + ((0.5)(0.5) - (0.5)(-0.5)) + ((0.5)(-0.5) - (-0.5)(0.5)) )

(-1/2) ( (0.5) + (0.5) + (0.0) )

-0.5

The sign being negative so that it is front-facing since "a triangle with negative area is considered front-facing."?

And if so, how does this coorespond to the normals calculation?


Solution

  • The triangle seems to be like this:

    triangle with winding

    The winding seems to be clockwise, so with the defaults (counter-clockwise) it would be backfacing.

    The formula is not something invented by Vulkan. It is basic formula for area of a triangle. The classic form is something like this: 0.5|AB×AC|. A, B, and C, are the vertices in this specified order, and so AB and AC are line segments\vectors:

    enter image description here

    For our purposes we don't need area exactly, we only need the direction of the normal. They just happen to be almost the same thing. We get a normal by calculating the cross product: AB×AC. That yields the vector
    (0, 0, AB.x⋅AC.y - AB.y⋅AC.x).

    Magnitude of a vector with only one component is the absolute value of that. We skip that absolute value operation, to get a signed "area". So we have just:
    AB.x⋅AC.y - AB.y⋅AC.x

    AB is simply B-A, and similarly AC = C-A, so substituting that and processing the multiplication, that yields:
    Ax⋅By-Bx⋅Ay + Bx⋅Cy-Cx⋅By + Cx⋅Ay-Ax⋅Cy
    This matches the Σ in the specification.

    With your numbers, that yields (-0.5⋅-0.5)-(0.5⋅-0.5) + (0.5⋅0.5)-(0.5⋅-0.5) + (0.5⋅-0.5)-(-0.5⋅0.5) = 1.

    The ½ multiplication obviously does not matter to us, since it is not sign-changing. But anyway, that makes it ½×1 = 0.5. That checks out: area of a 1x1 right-angled triangle is 0.5.

    The y coordinates poining down causes mirroring, therefore changes the perceived direction of winding:

    enter image description here

    Therefore we must swap the sign in the equation: -0.5(AB.x⋅AC.y - AB.y⋅AC.x). So we get -0.5.

    In case of VK_FRONT_FACE_COUNTER_CLOCKWISE, the frontface is the one with positive area, so we are indeed seeing the backface.