Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL behavior in a 2D tile-based engine: pixel "snapping" when in motion, approximation errors?

Let me see if I can ask this question legibly:

I'm writing a 2D tile-based engine in OpenGL ES, with the intent of making it look like an old-school raster engine. My art assets are all at native resolution (that is to say, 1:1 pixel art) and mapped onto rectangular polygons, and my OpenGL view is orthogonal and spans the rectangle (0.0, 0.0) to (screen.width, screen.height). I did this hoping that each pixel on the display would correspond to a "virtual" pixel square in the XY coordinate plane, which would in turn correspond to a pixel on one of my tiles. (The tiles are 16.0 x 16.0, and the origin of my world is obviously [0.0,0.0].)

I was certain that my engine would look "fake" because of approximation errors. For example, I thought that since the tile pixels weren't being written directly to the display, an incorrect pixel might occasionally be fetched. I was also sure that camera motion would cause OpenGL to interpolate whenever the tiles weren't aligned with the actual display pixels.

As it turns out, OpenGL behaves almost exactly as a raster engine would. When the camera is still, each virtual pixel corresponds perfectly to a pixel on the display. When the camera is in motion, the tiles "snap" one pixel row/column at a time rather than moving smoothly via interpolation. (This happens even if the motion is very slow.) Out of curiosity, I tried scaling my tiles to 1.1x, and as I expected, they started to look muddy and the snapping behavior ceased. Is it true, then, that OpenGL behaves differently depending on whether the stuff it's rendering can be perfectly aligned to the display?

Where in the spec can I find information about these issues, and how can I ensure that OpenGL continues behaving this way? I feel uncomfortable using a default that I don't quite understand, since the behavior could theoretically change at any time.

Thank you!

like image 591
Archagon Avatar asked Oct 26 '22 00:10

Archagon


1 Answers

Where in the spec can I find information about this behavior, and how can I ensure that OpenGL continues behaving this way?

You need to read the whole "Rasterization" chapter in the specification. It describes exactly what is guaranteed and how OpenGL implementation supposed to work;

I feel uncomfortable using a default that I don't quite understand, since the behavior could theoretically change at any time.

Right. As far as I understand in your situation the behavior is well defined. However, take in mind that the specification gives some freedom to the implementations so the results may vary from one implementation to the other. For example in the x1.1 scaling or 20deg rotation of the grid, the exact raterization of the edges is already implementation defined.

Note that the "snap" behavior is expected. You don't have AA enabled, so OpenGL can't make the movement any smoother.

like image 70
Yakov Galka Avatar answered Dec 10 '22 08:12

Yakov Galka