If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Canvas/Translate

Hey there, me again.

I have been playing around with Canvas - drawing 2d cubes out of square textures - and got troubled with positioning objects at decimal points.
It happens that when I draw a cube at position 0.0f and another one at position 100.0f I got well aligned objects, but when I draw one at 0.1f and the other at 100.1f, they just get misaligned. I don't understand the reason that is happening, but my solution so far is keeping decimal positions for the game objects, and drawing them at truncated positions.

Is that supposed to be this way? I've attached two examples of my problem.
Thanks.

To obtain exact two-dimensional rasterization, carefully specify both the orthographic projection and the vertices of the primitives that are to be rasterized. Specify the orthographic projection with integer coordinates, as shown in the following example.

Code:

gluOrtho2D(0, width, 0, height);

The parameters width and height are the dimensions of the viewport. Given this projection matrix, place polygon vertices and pixel image positions at integer coordinates to rasterize predictably. For example, glRecti( 0, 0, 1, 1 ) reliably fills the lower-left pixel of the viewport, and glRasterPos2i( 0, 0 ) reliably positions an unzoomed image at the lower-left pixel of the viewport. However, point vertices, line vertices, and bitmap positions should be placed at half-integer locations. For example, a line drawn from (x (1) , 0.5) to (x (2) , 0.5) will be reliably rendered along the bottom row of pixels in the viewport, and a point drawn at (0.5, 0.5) will reliably fill the same pixel as glRecti( 0, 0, 1, 1 ).

An optimum compromise that allows all primitives to be specified at integer positions, while still ensuring predictable rasterization, is to translate x and y by 0.375, as shown in the following code sample. Such a translation keeps polygon and pixel image edges safely away from the centers of pixels, while moving line vertices close enough to the pixel centers.

Always be very careful with OpenGL documentation since way too much of it points at obsolete OpenGL 1.x fixed-function information. The infamous 0.375 constant is indeed not used by ClanLib anymore and really shouldn't be used by anyone. It generates blurred images and suboptimal line drawing. As Rombust found out at the of the other forum thread, the constant is a hack intended for a time and age when doing a matrix multiplication was expensive, when shaders did not exist and enabling linear filtering was something for only the most powerful machines!

The factor that decides whether a pixel is 'lit' by a polygon is whether the pixel center is covered by the polygon or not. Since both 100.0f and 100.1f are very far from the pixel centers, there is no chance some kind of rounding error could cause this issue. Additionally to this OpenGL guarantees all pixels are filled when 100.1f is used as the vertex for the neighbouring polygon. Mathmatically this is obtained by using a x >= 0.5 rule for the left edge and a x < 0.5 rule for the right edge.

Lines have a width and also need to cover a pixel to lit it. They therefore have to be offset by 0.5 or the line isn't going through the center of a pixel. The 0.375 hack is about preventing lines from starting at exactly 0,0 because then the edge of the line ends up at exactly 0.5 - the slightest rounding error would then cause the line to move one pixel. Likewise if you fill a polygon with a vertex exactly at 0.5 the edge again ends up at the pixel center and a slight rounding error could move your polygon by a pixel. 0.375 places both incorrectly but at a place where neither suffers from rounding errors. However the texture coordinates and pixel coverage is now always wrong with visual bluring problems when texture sampling and poor anti-aliasing. Do not use this hack. Place your lines correctly instead.

I am not sure why you are seeing the error in that screenshot, but one possibility could be that the texture image lacks a proper border. You can test this theory by switching the filtering to nearest and see if the effect disappears.