On Mar 24, 11:21 pm, Gary Herron <[email protected]> wrote:
> Jonathan Hartley wrote:
> > I'm wondering whether it's possible to compensate for non-square pixels.
>
> > Using vector graphics drawn from OpenGL, in some resolutions my
> > circles are wider than they are tall, and in other resolutions they
> > are taller than they are wide. At my LCD's max, native resolution, the
> > circles are perfect, and to confirm this, the aspect of this max
> > screen resolution matches the physical measurements of the screen.
> > Other resolutions vary in aspect ratio from 1.25 up to 1.7, with a
> > corresponding distortion to the graphics onscreen.
>
> > I started out trying to compensate for non-square pixels when running
> > in lower resolutions , by setting my gluOrtho2D params. I assume that
> > the max available resolution on a display comprises square pixels, and
> > then compare the current resolution's aspect ratio to this. This works
> > great, in both fullscreen and windowed mode.
>
> > However, then I switched from Linux to Windows, and on the same
> > hardware, this time the drivers provide modes which have 'black bars'
> > down the sides. So the reported resolution does not use the whole
> > screen real estate. This throws off my 'compenation' calculation, and
> > in fact pretty much makes it redundant, so I'd like to stop performing
> > this pixel aspect correction in this case. But I've no idea how to
> > detect this circumstance from software.
>
> > I guess I could have a manual tweak for pixel aspect ratio, that the
> > user could set. Meh.
>
> > I assume automating this can't reliably be done, unless someone has
> > information to the contrary. Ideas, thoughts, etc, welcome.
>
> >     Jonathan
>
> Yes, easily done...  not with a call for that specific purpose, but
> OpenGL provides the building blocks necessary to achieve the desired
> result for any size/shape/number of pixels.
>
> With a call to glViewport, you set the range of pixels you are using,
> and with a call to one of glFrustum, gluPerspective, glOrtho or
> gluOrtho2D, you set the range of world space coordinates you wish to use.
>
> In a normal square-pixel situation, the viewport's height/width ratio
> should equal the frustum's height/width ratio.   In non-square-pixel
> situations, those two ratios will differ.
>
> Equations can be provided if anyone cares to see the specifics ...
>
> Gary Herron


Hey Gary,

Thanks, yes I did get non-square pixel correction working by changing
the params to glOrtho2D, as described above. :-)

My only outstanding problem is detecting when the graphics driver is
providing a less-than native resolution with 'black bars' down the
sides of the screen. In this instance I want to turn off my non-square
pixel detection. If I can't figure this out, I'll grudgingly settle
for providing the user with a manual 'my screen as black bars down the
sides' switch to turn non-square-pixel correction off. But I'm curious
why I've never seen this anywhere else. Does no-one else do non-square
pixel correction? This is really the reason I posted all this, in case
there's something else going on that I've entirely overlooked.

Specifically, just in case it helps any future googlers, my code to
set projection and initial modelview matrices to correct future
rendering for any screen resolution, aspect ratio, fullscreen or
bizarrely-shaped windows, and non-square pixels, looks like this
(forgive the use of a couple of pygame-isms):

Class Camera(object):

    def __init__(self, window):
        self.window = window
        self.x, self.y = (0, 0) # world location camera is centered on
        self.angle = 0.0  # camera can tilt
        self.zoom = 1.0   # distance from centre of screen to nearest
edge
                          # in world co-ords. ie. user can always see
at
                          # least this much of the world in every
direction.

    def set_world_projection(self):
        '''
        Call this to set projection matrix before
        drawing all the in-world game entities
        '''
        width, height = self.window.size
        aspect = width / height

        # account for non-square pixels
        aspect *= self.window.getPixelAspect()

        def getOrtho2DBounds():
            left = bottom = -self.zoom
            right = top = self.zoom
            if width > height: # widescreen
                left *= aspect
                right *= aspect
            elif width < height: # tallscreen
                bottom /= aspect
                top /= aspect
            return left, right, bottom, top

        GL.glMatrixMode(GL.GL_PROJECTION)
        GL.glLoadIdentity()
        GLU.gluOrtho2D(*getOrtho2DBounds())

    def look_at(self):
        '''
        Call this to set initial modelview matrix,
        just before drawing all in-world game entities
        '''
        GL.glMatrixMode(GL.GL_MODELVIEW)
        GL.glLoadIdentity()
        GLU.gluLookAt(
            self.x, self.y, +1.0,
            self.x, self.y, -1.0,
            sin(self.angle), cos(self.angle), 0.0)


Where my window.getPixelAspect() looks like:


    def getPixelAspect(self):
        '''
        Return the pixel aspect ratio for the current resolution. This
        is the ratio of width to height of a single pixel. So:
            <1.0 represents tall skinny pixels
            =1.0 represents square pixels,
            >1.0 represents short wide pixels
        '''

        # Assumption 1: The highest available resolution uses square
pixels
        # Seems to be true for the native resolutions of my LCD. Use
this
        # resolution to determine the aspect of the physical screen
        # measurements

        physWidth, physHeight = self.modes[0] # pygame for 'get
highest available screen resolution'
        physAspect = physWidth / physHeight

        # Assumtions 2: The current resolution is using all available
screen
        # real-estate. So comparing the current resolution aspect with
the
        # phyAspect will give current pixel aspect ratio.

        # However, my Windows ATI drivers offer a mode which provides
        # lower-than-native resolutions with black bars around them,
violating
        # assumtion 2. In this case, this calculation will give the
wrong
        # answers, and likely is not needed at all.

        info = display.Info() # pygame for 'get current screen
resolution'
        pixWidth = info.current_w
        pixHeight = info.current_h
        pixAspect = pixWidth / pixHeight

        return physAspect / pixAspect

-- 
You received this message because you are subscribed to the Google Groups 
"pyglet-users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/pyglet-users?hl=en.

Reply via email to