sprites rounding vertices to nearest int

19 views
Skip to first unread message

Michael Halle

unread,
Apr 10, 2008, 4:39:42 PM4/10/08
to pyglet...@groups.l.google.com
In looking through the sprite code, I saw that computed vertices get
rounded off to ints, and then passed in integer form to OpenGL. This
process happens even when the sprite is scaled and rotated, where
vertices would in general not fall on pixel boundaries.

Seems like for small sprites, noticeable distortion or bad packing could
happen.

As far as I know, graphics cards usually use floats internally anyway --
are there real performance hits in removing the rounding and just
passing the floats down to OpenGL?

Thanks.

--Mike

Richard Jones

unread,
Apr 10, 2008, 5:49:14 PM4/10/08
to pyglet...@googlegroups.com
On Fri, 11 Apr 2008, Michael Halle wrote:
> In looking through the sprite code, I saw that computed vertices get
> rounded off to ints, and then passed in integer form to OpenGL. This
> process happens even when the sprite is scaled and rotated, where
> vertices would in general not fall on pixel boundaries.
>
> Seems like for small sprites, noticeable distortion or bad packing could
> happen.

So this is something you've not actually observed?


> As far as I know, graphics cards usually use floats internally anyway --
> are there real performance hits in removing the rounding and just
> passing the floats down to OpenGL?

The rounding is not done for performance.

More often than not you'll get artifacts and fuzziness on raster graphics if
they're not pixel-aligned. The most common artifact is flickering border
where pixels bleed in from adjacent images (in the same texture).


Richard

Alex Holkner

unread,
Apr 10, 2008, 7:42:57 PM4/10/08
to pyglet...@googlegroups.com

Even without adjacent images, you'll get this flicker as any high
frequency parts of the texture (lines, for example) pass in and out of
pixel alignment.

I've been thinking about providing a SubpixelSprite class, which would
use v2f instead of v2i for coordinates. The onus on deciding which is
appropriate (e.g. for scaled/rotated sprites it really isn't a
problem) is on the developer.

Alex.

Simon Wittber

unread,
Apr 10, 2008, 10:09:13 PM4/10/08
to pyglet-users
On Apr 11, 7:42 am, "Alex Holkner" <alex.holk...@gmail.com> wrote:
> On 4/11/08, Richard Jones <r1chardj0...@gmail.com> wrote:
> > On Fri, 11 Apr 2008, Michael Halle wrote:
> > > In looking through the sprite code, I saw that computed vertices get
> > > rounded off to ints, and then passed in integer form to OpenGL. This
> > > process happens even when the sprite is scaled and rotated, where
> > > vertices would in general not fall on pixel boundaries.
>
> > > Seems like for small sprites, noticeable distortion or bad packing could
> > > happen.
>
> > So this is something you've not actually observed?

I've observed this when rotating a pyglet.Sprite.

This code demonstrates the problem. The image on the left seems to
pulse in and out.

import pyglet
from pyglet.gl import *
from itertools import *

window = pyglet.window.Window()
image = pyglet.resource.image('simon.jpg')
image.anchor_x, image.anchor_y = image.width*0.5, image.height*0.5
sprite = pyglet.sprite.Sprite(image, x=100, y=100)

def update(T):
sprite.rotation += 1.0

pyglet.clock.schedule_interval(update, 1.0/30)

x,y = image.anchor_x, image.anchor_y
vertices = (-x, -y, 0), (-x, +y, 0), (+x, +y, 0), (+x, -y, 0)
texcoords = [i for i in izip(*[chain(image.texture.tex_coords, )]*3)]

@window.event
def on_draw():
window.clear()
glLoadIdentity()
sprite.draw()
glLoadIdentity()
glTranslatef(200,100,0)
glRotatef(sprite.rotation, 0, 0, 1)
glEnable(image.texture.target)
glBindTexture(image.texture.target, image.texture.id)

glBegin(GL_QUADS)
for v, t in izip(vertices, texcoords):
glTexCoord3f(*t)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glVertex3f(*v)
glEnd()

pyglet.app.run()

>
> > > As far as I know, graphics cards usually use floats internally anyway --
> > > are there real performance hits in removing the rounding and just
> > > passing the floats down to OpenGL?
>
> > The rounding is not done for performance.
>
> > More often than not you'll get artifacts and fuzziness on raster graphics if
> > they're not pixel-aligned. The most common artifact is flickering border
> > where pixels bleed in from adjacent images (in the same texture).
>
> Even without adjacent images, you'll get this flicker as any high
> frequency parts of the texture (lines, for example) pass in and out of
> pixel alignment.

I've got a hunch (I could be wrong) that this problem can be mitigated
by using a filter on the textures. Something like:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

Simon Wittber

unread,
Apr 10, 2008, 10:16:33 PM4/10/08
to pyglet-users
On Apr 11, 10:09 am, Simon Wittber <simonwitt...@gmail.com> wrote:
> glBegin(GL_QUADS)
> for v, t in izip(vertices, texcoords):
> glTexCoord3f(*t)
> glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
> glVertex3f(*v)
> glEnd()

Argh. Remove:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

from the above code to make it work. My mouse has gotten paste happy.

Eric Burgess

unread,
Apr 10, 2008, 10:24:33 PM4/10/08
to pyglet-users
Those functions are for scaling, and they do make images look nicer
when scaled up or down than a straight nearest-neighbor method.

Fuzziness from sub-pixel positioning is a totally separate problem.
Images with hard, narrow lines just won't look right at a half-pixel
position, since it's physically impossible to draw a one-pixel-wide
line between pixels. UI widgets and text strings (especially at small
font sizes) are examples of things you really want to have pixel-
aligned. A photograph or anti-aliased cartoon-type image, on the
other hand, looks just fine at sub-pixel positions, and moving them
around at sub-pixel speeds really looks beautiful.

I'm glad Alex is thinking about making both options available.

Michael Halle

unread,
Apr 11, 2008, 7:16:31 AM4/11/08
to pyglet-users


On Apr 10, 7:42 pm, "Alex Holkner" <alex.holk...@gmail.com> wrote:
Might this be better done as a mode for the existing sprite class? I
could see advantages either way.

Thanks.

--Mike

Reply all
Reply to author
Forward
0 new messages