How to rasterize an OpenGL triangle on half-integer pixel centers

OpenGL pixels / fragments conceptually 1x1 squares centered on half-integer pixels. The OpenGL 4.5 specification states:

The fragment is located at its lower left corner, which lies on the integer coordinate of the grid. Rasterization operations also relate to fragments of the center, which is offset (1 / 2,1 / 2) from its lower left corner (and therefore lies on half-integer coordinates).

Rasterizers typically assume that the centers of the pixels lie on an integer grid. Since I am trying to implement the correct triangle of an OpenGL triangle, I want to know if the following procedures sound.

Take the simple case of a triangle with clip coordinates (-1, -1), (+ 1, -1), (0, + 1), as shown to the left of the figure below (suppose the spelling projection and r = 0). Suppose we have (a small buffer of 5 Γ— 5 frames) that we map to our triangle using glViewport(0,0,5,5) , as shown on the right, which gives a triangle in the coordinates of the device with the vertices (0,0), (5.0), (2.5.5).

pixels centered at half integers

As you can see, 13 fragments (shaded pixels in the image) with centers inside the triangle should be generated by the rasterizer. Note that the centers of the fragments are in half-integer coordinates. To implement the OpenGL specification, this must be the result.

The polygonal fill of the scan line will determine the intervals x where the scan lines intersect the triangle, but the scan lines have values ​​with half an integer y, as shown in the following figure:

triangle fill OpenGL

The hardware / firmware rasterizer assumes that the pixel centers are on an integer grid, as this is the most efficient way to perform padding. In the figure below, I switched the coordinates of the triangle devices to (-0.5, -0.5) to place the centers in the whole grid:

enter image description here

Note that the centers of the pixels are now really in the integer grid. This rasterizer simply added back (0.5,0.5) to each center of the fragment before transferring it to the shader of the fragment. At least that's my plan.

Processing texture coordinates seems straightforward. Imagine that I assigned the texture coordinates (0,0), (1,0), (0,5,1), as shown below. The image on the left uses half-integer pixel centers (OpenGL path), and the image on the right uses integer pixel centers (hardware method). The texture coordinates (any attributes of the attached fragments in this regard) ultimately have the same values ​​in any case - i.e. Nothing special is required.

enter image description here

How does my approach seem right?

  • Add (-0.5, -0.5) to each fragment coordinate,
  • use hardware efficient fill,
  • add (0.5, 0.5) back when creating fragment centers and
  • do not sweat other fragment attributes (they just work).
+5
source share

Source: https://habr.com/ru/post/1200964/


All Articles