Just when you thought it was safe to draw trapezoids...

I've been experimenting with 'sharp' polygons, those with aliased edges. 
This is effected by generating a 1-bit mask instead of an 8-bit mask.

It shows off-by-one errors quite easily.

Here's one:


          +--/--------+
          |A/         |
          |/   B      |
          /           |
         /|           |
        ------------------ 0.5
         \|           |
          \    C      |
          |\          |
          |D\         |
          +--\--------+

Ok, so let's enumerate the "primitive" alphas, those computed
directly from the area:

        A, AB, D, ABCD

And composite alphas:

        B = AB - A
        CD = ABCD - AB
        C = CD - D

Now, try a few rounding modes:

                Round   Ceil    Floor
        A       0       1       0       <-
        AB      1       1       0
        D       0       1       0       <-
        ABCD    1       1       1
        B       1       0       0
        CD      0       0       1
        C       0       -1      1
        A+B+C+D 1       2       1


This example has a problem when using 'Ceil' rounding; the pixel
will be drawn by both trapezoid 'A' and 'D'.

Here's another one:

                 L
        +---------\---+------------+
        |          \  |            |
        |      A    \B|      C     |
        |            \|            |
        |             \            |
        ---------------\-------------  N
        |      D      |E\    F     |
        +-------------+--\---------+

B and C belong to trap Q
A D E belong to trap R
F belongs to trap S

Trap R is rendered without knowledge of boundary N

When drawing trap Q:

        Aq: primitive
        ABq: primitive
        ADq: primitive
        Bq = ABq - Aq

When drawing trap R:

        ADr: primitive

Trap S doesn't intersect the left pixel at all, it's alpha is not
evaluated.

Now, try a few rounding modes:

                Round   Ceil    Floor
        Aq:     1       1       0
        ABq:    1       1       0
        ADq:    1       1       0
        ADr:    1       1       0       <-
        Bq:     0       0       0       <-

This example has a problem when using 'Floor' rounding; the pixel
is never drawn. Curiously, if you blindly evaluate the alpha for trap S,
it turns out to be one.  Pretend there is a zero-sized trapezoid 'G'
between the line 'L' and the right edge of the left pixel

        As:     primitive
        ADs:    primitive
        ABs:    primitive
        ABDGs:  primitive
        Ds      = ADs - As
        DGs     = ABDGs - ABs
        Gs      = DGs - Ds

                Round   Ceil    Floor
        As      1       1       0
        ADs     1       1       0
        ABs     1       1       0
        ABDGs   1       1       1
        Ds      0       0       0
        DGs     0       0       1
        Gs      0       0       1

We've just approximated an empty pixel with an alpha of 1.  Move left and 
perform the same hat trick and you get another 'full' pixel.

Now we've eliminated 'floor' and 'ceil' as accurate rounding modes, here's
my final example:

          +----------/
          |         /|
          |        / |
          |       /  |
          |  A   /   |
          |     /    |
          |    /   B |
          |   /      |
        -----/----------  N
          |C/        |
          |/      D  |
          +----------+

        Trap R:         AC (no knowledge of N)
        Trap S:         B
        Trap T:         D

        ACr/ACt:        primitive
        ABs/ABt:        primitive
        At/As:          primitive
        ABCD:           primitive
        Bs:             ABs - As
        CDt:            ABCD - ABt
        Ct:             ACt - At
        Dt:             CDt - Ct

                        Round   Ceil    Floor

        At/As:          0       1       0
        ACr/ACt:        1       1       0       <-
        ABs/ABt:        1       1       0
        ABCD:           1       1       1
        Bs:             1       0       0       <-
        CDt:            0       0       1
        Ct:             1       0       0
        Dt:             -1      0       1       <-

Our old negative alpha friend has reappeared, resulting in a pixel getting
rendered twice.

I have two suggestions here -- it's clear that the 'Round' mode generates 
the most "reasonable" results, except for negative alpha.  Given that
these computations reflect sub-pixel accumulated error in coverage 
involving deeper alpha values, it seems that 'Round' is our mode of 
choice; it limits the error to cases where some portion of the pixel is 
smaller than 1/max_alpha, and then errors occur only in the upper left
corner of the trapezoid.

However, when depth is 1, we obviously need a different spec -- it's 
rather hard to generate trapezoids whose pixel coverage is always
>= 1/max_alpha when max_alpha is 1.  For this case, I suggest that we 
ignore area and look only at whether the desired region contains a 
particular point within the pixel -- to match our AA trapezoids, that 
should probably be the center.  I think all this requires is a change in 
how the primitive alpha values are computed; alpha is '1' if the primitive 
area contains the line from the center of the pixel to the origin, else 
'0'.  I'll give this a try and see what happens.

Keith Packard        XFree86 Core Team        HP Cambridge Research Lab


_______________________________________________
Render mailing list
[EMAIL PROTECTED]
http://XFree86.Org/mailman/listinfo/render

Reply via email to