Skip to main content
gamedev.net
🔒 Locked

Sub-pixel accuracy

Started by Lodis 10 replies 9.2k views
Original Post
Lodis
Lodis
Hello, I have tried to obtain an ultra smooth scrolling into a 2D opengl application but the polygon I created seems to "jump" rather than slide. It does use double-buffering and the screen renders as much as possible. I got told to use sub-pixel accuracy as it lets you translate to a value inferior to 1 pixel. I have defined my polygon to move at a speed of 0.25 pixel/second, so every 4 seconds, I see it jump 1 pixel.. are sub-pixel movements really possible? Anyway, I could not find a lot of theory about it on google and even less samples of applications using that. Could you guys hint me as to how sub-pixel accuracy can be illustrated in a 2D opengl application? Thanks a lot.
sinoth
sinoth
Good ol' Wikipedia has a pretty good article on subpixel rendering:
http://en.wikipedia.org/wiki/Subpixel_rendering

It probably isn't going to do what you want. The only reason to consider using subpixel rendering is if you're coding for one target device and you know the display will ALWAYS be the same. For example, many homebrew Nintendo DS games use subpixel fonts because you know the screen is constant. Also, this type of rendering is only useful on LCDs.

Are you using time constant movement, as opposed to movement based on FPS? Also, you might try enabling VSync to see if you like how that looks better. If you still don't like the movement, you might have to resort to some kind of blurring.
Lodis
Lodis
Quote:
Original post by sinoth
Are you using time constant movement, as opposed to movement based on FPS?


My game logic function is called at a constant speed of 20 times per second. Rendering, on the other hand, is done as much as possible.

Quote:
Original post by sinoth
Also, you might try enabling VSync to see if you like how that looks better. If you still don't like the movement, you might have to resort to some kind of blurring.


Ok, but how can I enable Vsync?
sinoth
sinoth
Quote:
Original post by Lodis
Ok, but how can I enable Vsync?


What OpenGL framework are you using? (SDL, GLFW, etc)
Lodis
Lodis
Quote:
Original post by sinoth
Quote:
Original post by Lodis
Ok, but how can I enable Vsync?


What OpenGL framework are you using? (SDL, GLFW, etc)


I use SDL.
OrangyTang
OrangyTang
Unless you've got a really good reason then I think you really should be running your logic at a much higher frequency. Since pretty much everyone is running on an LCD these days I find it best to run your logic at 60Hz (and as already mentioned, run your framerate locked to vsync (which will probably end up being 60Hz as well)).

20Hz is really far too low for smooth movement in a 2d game IMHO.
Lodis
Lodis
Quote:
Original post by OrangyTang
Unless you've got a really good reason then I think you really should be running your logic at a much higher frequency. Since pretty much everyone is running on an LCD these days I find it best to run your logic at 60Hz (and as already mentioned, run your framerate locked to vsync (which will probably end up being 60Hz as well)).

20Hz is really far too low for smooth movement in a 2d game IMHO.


Ok gotcha.
Also, I found this really interesting article earlier today on Vsync and how it effects FPS: http://www.hardforum.com/showthread.php?t=928593

Although, I could not find how to enable it on opengl.
Graz
Graz
Are you seeing the edge of the polygon jump from pixel to pixel? If so, then it's nothing to do with vsync or game logic - all of that is probably working fine. It's because you need good quality antialiasing to be able to draw the edge of a polygon at a sub-pixel location. This is not something that is supported in a standard way, and can generally only be turned on by driver extensions or the vendor's control panel application.
If you draw a texture across your polygon, you will see that the texture moves smoothly across the screen, effectively jumping relative to the polygon.
Don't worry about it. Once you have a screen full of fast moving objects and a bunch of colorful textures, you wont notice the edge of the polygon jumping. If you do, just use your quad SLI rig to render 16x FSAA or something and I'm sure it will be fine.
swiftcoder
swiftcoder
Quote:
Original post by Lodis
Although, I could not find how to enable it on opengl.
Unfortunately, there is no portable way to enable vsync in SDL. I would advocate moving to GLFW or SFML instead.
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
idinev
idinev
Why toy with the output hardware to get ugly 0.5px subpixels?

Do it yourself, with regular OpenGL code, blending, 1px-wider/higher quads, some simple math and textures with borders (or sprites in the textures, that have a transparent border, thus do not touch another sprite).

To get the idea how to use all above, imagine you need to draw a 16x16 sprite at position 10:10, from tu:tv=100:100 (expressed as integer tex-coords). Now, move the sprite 0.1px to the left. At 10:10 you get the texture coords tu:tv=101:100, but your eyes expect tu:tv=100.1:100 . And you expect pixels to be set at the vertical line starting from 25:10. (thus we draw the sprite with extra 1px horizontally and vertically, space which should be transparent).
idinev
idinev
Here's an example of 1px-wide lines being drawn at subpixel positions. (right side of the image). The 8px-wide lines are at position 8*k1, 8*k2-1, 8*k3-2, ...



Free Image Hosting at www.ImageShack.us
Lodis
Lodis
Quote:
Original post by swiftcoder
Quote:
Original post by Lodis
Although, I could not find how to enable it on opengl.
Unfortunately, there is no portable way to enable vsync in SDL. I would advocate moving to GLFW or SFML instead.


Ok noted, that's what I will do :)

Quote:
Original post by idinev
Why toy with the output hardware to get ugly 0.5px subpixels?

Do it yourself, with regular OpenGL code, blending, 1px-wider/higher quads, some simple math and textures with borders (or sprites in the textures, that have a transparent border, thus do not touch another sprite).

To get the idea how to use all above, imagine you need to draw a 16x16 sprite at position 10:10, from tu:tv=100:100 (expressed as integer tex-coords). Now, move the sprite 0.1px to the left. At 10:10 you get the texture coords tu:tv=101:100, but your eyes expect tu:tv=100.1:100 . And you expect pixels to be set at the vertical line starting from 25:10. (thus we draw the sprite with extra 1px horizontally and vertically, space which should be transparent).


That is really interesting, thanks.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.