Jitter in object movement when using subpixel positions

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

User avatar
Bregalad
Posts: 7890
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Re: Jitter in object movement when using subpixel positions

Post by Bregalad » Fri May 22, 2015 12:05 am

Is it possible to fix this problem without taking the subpixel position into account when calculating O_c?
No offence, but I see really no reason for not doing it. That is just the logical way to do thing, make all calculations in 16-bit and clip only when you're about to draw the sprite.

User avatar
thefox
Posts: 3141
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Re: Jitter in object movement when using subpixel positions

Post by thefox » Fri May 22, 2015 1:11 am

Thanks for bringing up the other method for doing subpixel(ish) movement. I had never heard about it before.
Bregalad wrote:
Is it possible to fix this problem without taking the subpixel position into account when calculating O_c?
No offence, but I see really no reason for not doing it. That is just the logical way to do thing, make all calculations in 16-bit and clip only when you're about to draw the sprite.
No offense taken. :) I actually thought of it more as an academic exercise.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi

User avatar
Bregalad
Posts: 7890
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Re: Jitter in object movement when using subpixel positions

Post by Bregalad » Fri May 22, 2015 1:35 am

Oh and I forgot to give you the answer I wanted to give.

One way would be to make sure the scenario you describe is avoided. For example, whenever the camera stops, the less significant bits of its positions are reset to zero, and when it starts to move again, the less significant bits of all objects are reset to zero. Of course this can lead to other bugs, and if your camera is slowly accelerating it will still not work.

User avatar
tokumaru
Posts: 11756
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Jitter in object movement when using subpixel positions

Post by tokumaru » Fri May 22, 2015 5:01 am

Bregalad wrote:That is just the logical way to do thing, make all calculations in 16-bit and clip only when you're about to draw the sprite.
But even if clipping the values is the last thing you do, the pixel positions of objects moving at the same fractional speed (including the camera) will change on different frames, resulting in the problem described in the first post.

I can't think of a way to solve this problem that wouldn't be a hack, except for the fake subpixel method that has been brought up, where the pixel positions of all objects moving at the same speed will change in the same frame.

Sik
Posts: 1589
Joined: Thu Aug 12, 2010 3:43 am

Re: Jitter in object movement when using subpixel positions

Post by Sik » Fri May 22, 2015 8:15 am

thefox wrote:Sorry, but I don't understand what is the difference between "faked" and a "non-faked" subpixel precision? As far as I see, it's always "faked", because we have to align the graphics to the pixel grid
It's about whether you actually store subpixel position in RAM or not (i.e. you keep track of subpixels), not about the final position of the graphic on screen (which has to be pixel-aligned).

User avatar
tokumaru
Posts: 11756
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Jitter in object movement when using subpixel positions

Post by tokumaru » Sat May 23, 2015 6:19 pm

You know what console would benefit a lot from this subpixel faking thing? The Atari 2600, where RAM is really tight. I don't know if the reduced horizontal resolution (160 pixels) would make the slightly more uneven movement more apparent, but still...

User avatar
thefox
Posts: 3141
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Re: Jitter in object movement when using subpixel positions

Post by thefox » Mon May 25, 2015 12:40 am

tokumaru wrote:
Bregalad wrote:That is just the logical way to do thing, make all calculations in 16-bit and clip only when you're about to draw the sprite.
But even if clipping the values is the last thing you do, the pixel positions of objects moving at the same fractional speed (including the camera) will change on different frames, resulting in the problem described in the first post.
Can you come up with an example of what you mean? The "pixel positions" in world space certainly change on different frames, but after the transformation to camera space the coordinate of the object should always stay constant (since it's moving at the same speed as the camera). In the first post the error was solely introduced by the false assumption that floor(a)-floor(b) = floor(a-b).
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi

User avatar
rainwarrior
Posts: 7824
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Jitter in object movement when using subpixel positions

Post by rainwarrior » Mon May 25, 2015 1:31 am

Following up on the question of why bit reversal. I've made some images to demonstrate the properties of the two proposed functions for testing a "fake" subpixel velocity for whether to increment this frame. The Y axis represents the velocity value, and the X axis represents a sequence of 256 frames. A white pixel means this frame (X) will increment for this velocity (Y).

Optimal spacing would be as even as possible. The ideal function would make all intervals between increment frames almost the same length, varying by at most 1 frame.

You could create optimal spacing with a division function of X and Y together, but here we are only considering functions which operate on X.
Dither test of bit reverse
Dither test of bit reverse
bitreverse.png (1.57 KiB) Viewed 2346 times
Function 1: reversing the bits.

This appears to be optimally (evenly) spaced for values that align to power-of-two divisions, e.g. 16, 32, 196 etc. In between these divisions, however, the extra increments are added at anti-optimal positions in between. For example, Y=3 has 2 short intervals (64 frames each) and one long interval (128 frames), giving you a 64 frame disparity! It's kind of an interesting tradeoff between the best possible situation at power-of-two points, and the worst possible situation confined to the intervals between them.
Dither test of +157 mod 256
Dither test of +157 mod 256
golden.png (1.57 KiB) Viewed 2346 times
Function 2: adding 157 each frame, mod 256.

This works on the principle that adding a number that is relatively prime to a modulus will cycle through all values in sequence, creating an effective pseudorandom number generator. Here the prime 157 is chosen because it approximates the Golden Ratio, which has the strange property that it tends to produce even spacing in the general case. For example, Y=3 has 2 short intervals (75 each) and one lone (106), so for this case the jitter is only 31 frames.


The golden ratio function is better than bit reversal in some cases, and worse in others. I think the distribution of error is a little more even, whereas with bit reversal error is concentrated into cases that are close to but not on power-of-two nodes. Overall they are both fairly good, and the best results in both are found in the middle region (Y approaches 128). Bit reversal is probably the better choice if you think you're going to be using power-of-two aligned values often. The golden ratio function is faster to compute, but an 8-bit reversal once per frame is pretty fast already.

Could probably spend a bunch of time creating various functions (e.g. you could survey all prime values instead of just 157) and write evaluators to rank them by overall jitter, but I just wanted to know how optimal bit-reversal was.



Edit: Python scripts were later disallowed on this forum. Uploading a ZIP with what I think was the original script.
Attachments
dither_test.py.zip
(453 Bytes) Downloaded 37 times

[The extension py has been deactivated and can no longer be displayed.]

Last edited by rainwarrior on Tue Jun 12, 2018 12:49 pm, edited 1 time in total.

User avatar
tokumaru
Posts: 11756
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Jitter in object movement when using subpixel positions

Post by tokumaru » Mon May 25, 2015 4:17 am

thefox wrote:Can you come up with an example of what you mean?
Oh, never mind me, I was probably drunk when I wrote that. Obviously, if you take into account the fractional part of the coordinates in convertions to screen space the relative distance between the camera and an object moving at the same speed will remain constant, causing no jitter. Sorry about that.
In the first post the error was solely introduced by the false assumption that floor(a)-floor(b) = floor(a-b).
You're right, I see it now. It sucks though, having to do 24-bit operations to find the screen positions of the objects.

User avatar
Drew Sebastino
Formerly Espozo
Posts: 3503
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: Jitter in object movement when using subpixel positions

Post by Drew Sebastino » Mon May 25, 2015 6:01 am

tokumaru wrote:I was probably drunk when I wrote that.
Cool. :beer:

Sik
Posts: 1589
Joined: Thu Aug 12, 2010 3:43 am

Re: Jitter in object movement when using subpixel positions

Post by Sik » Mon May 25, 2015 10:29 am

thefox wrote:
tokumaru wrote:
Bregalad wrote:That is just the logical way to do thing, make all calculations in 16-bit and clip only when you're about to draw the sprite.
But even if clipping the values is the last thing you do, the pixel positions of objects moving at the same fractional speed (including the camera) will change on different frames, resulting in the problem described in the first post.
Can you come up with an example of what you mean? The "pixel positions" in world space certainly change on different frames, but after the transformation to camera space the coordinate of the object should always stay constant (since it's moving at the same speed as the camera). In the first post the error was solely introduced by the false assumption that floor(a)-floor(b) = floor(a-b).
Two words: rounding errors (since this is the direct result of approximating non-integer values to integers).

Post Reply