I'm working on a software rasterizer to use in my project. I have implemented one that works well, however, often my rasterizer under or overestimates triangle coverage. I need perfect emulation of the hardware rasterizer. I'm using the exact same rasterization rules from MSDN (including the top-left rule).

How does the Direct3D rasterizer determine which pixels are covered by a triangle? What's the algorithm being employed? Does it rasterizer use the pixel center coordinate or the pixel's top-left coordinate when determining triangle coverage?

When I use the pixel's top-left coordinate I get better results. I've also been determining the planes perpendicular to the triangle's edges, then admitting pixels if their coordinate is "behind" each plane.

  • 1
    \$\begingroup\$ Why do you need perfect emulation, exactly? \$\endgroup\$ – user1430 Dec 11 '13 at 1:29
  • \$\begingroup\$ I need perfect emulation because i must add color to a texture( render target ) already written to by the hardware rasterizer...if i underestimate or overestimate coverage it will show on the final image... \$\endgroup\$ – P. Avery Dec 11 '13 at 1:47
  • \$\begingroup\$ And why does that need to be perfect? In any case, screenshots of your anomalies would be useful, but you are going to have a hard time achieving 100% general-case matching for non-reference devices (are you testing with a reference D3D device, for example? I mean explicitly created as the "REF" device type?) because hardware introduces differences in rasterization rule implementation. \$\endgroup\$ – user1430 Dec 11 '13 at 1:49
  • \$\begingroup\$ @P.Avery I guess the obvious question here is why can't you use the hardware rasterizer for this second stage (adding color to a render target) as well? Even if you need to calculate pixel values on the CPU for some reason, you could still use the HW to determine pixel coverage, e.g. by drawing the triangles in white on a black background, reading that RT back to the CPU, and evaluating your algorithm on the white pixels. \$\endgroup\$ – Nathan Reed Dec 11 '13 at 3:33
  • \$\begingroup\$ @NathanReed I had this idea also but I thought it would take too long...i'm working on the same radiosity processor...i am rendering from the pov of individual pixels... \$\endgroup\$ – P. Avery Dec 12 '13 at 3:36

If you pretend a pixel is a square (see A Pixel is Not a Little Square), then the center of that square is the pixel coordinate. This is documented in Direct3D 9's rasterization rules (emphasis mine):

Direct3D uses a top-left filling convention for filling geometry. This is the same convention that is used for rectangles in GDI and OpenGL. In Direct3D, the center of the pixel is the decisive point. If the center is inside a triangle, the pixel is part of the triangle. Pixel centers are at integer coordinates.

For pixels that are part of the triangle, pixels on the top edge and the left edge are filled. Pixels on the bottom and right edge are not. A top edge is completely horizontal, otherwise it does not exist.

You may want also peruse the documentation on mapping pixel coordinates to texel coordinates in D3D9 and, should you ever consider moving to D3D10+, take a look at the modern rasterization rules.

It's also worth noting that you will see variation in this behavior from hardware to hardware (although usually that variation is minimal). It could be that that explains your discrepancies, and it also means it will be extremely difficult for you to achieve a 100% match to a hardware-based rasterizer from D3D; consider using the reference device when doing your testing.

  • \$\begingroup\$ i've read all that documentation and have tried putting those rules to use...there are always discrepancies which is why i want to know what method is used by D3D9 to determine pixel coverage by a triangle. using the reference device is a good idea. When drawing an individual pixel using that pixels uv coordinate, should I use the pixel's top-left or center coordinate? \$\endgroup\$ – P. Avery Dec 11 '13 at 1:56
  • \$\begingroup\$ That is the method, though. Or did you mean how it determines which pixels are in the top edge or left edge (top should be obvious, left edges are the pixels on the start of each horizontal span). \$\endgroup\$ – user1430 Dec 11 '13 at 1:58
  • 1
    \$\begingroup\$ @P.Avery Are you snapping vertices before evaluating edge equations? The hardware rasterizer operates in fixed point, so it effectively snaps vertices to a subpixel grid. For D3D11 it's specified to have at least 8 subpixel bits and it's a good bet that most/all HW use exactly 8 subpixel bits. You'll need to take account of this to rasterize exactly. \$\endgroup\$ – Nathan Reed Dec 11 '13 at 3:31
  • 1
    \$\begingroup\$ @P.Avery Here is a presentation that describes subpixel rasterization a bit more; see page 9. \$\endgroup\$ – Nathan Reed Dec 12 '13 at 5:15
  • 1
    \$\begingroup\$ @P.Avery The presentation shows only a few subpixels to avoid being visually overwhelming. Like I said, D3D11 requires 8 bits of subpixel precision, so there are 2^8 = 256 increments along x and y in each pixel. BTW, I found another article on it, here. \$\endgroup\$ – Nathan Reed Dec 12 '13 at 6:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.