Jonathan Hartley wrote:
On Mar 25, 3:37 pm, Gary Herron <[email protected]> wrote:Jonathan Hartley wrote: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 mycircles 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 runningin 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 samehardware, 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 theuser could set. Meh.I assume automating this can't reliably be done, unless someone hasinformation to the contrary. Ideas, thoughts, etc, welcome.JonathanYes, 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 ratioshould 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 HerronHey Gary,Thanks, yes I did get non-square pixel correction working by changingthe params to glOrtho2D, as described above. :-)My only outstanding problem is detecting when the graphics driver isproviding 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.What you *really* want here -- which you may or may not be able to get from the driver -- is two bits of information: * the resolution in each direction, i.e. the number of pixels in each direction * the physical dimensions of the display area occupied by those pixelsWith that information, you need not "detect" anything about the shape of the pixels. Just set your perspective/frustum/ortho height/width ratio to match the physical dimension height/width ratio, and set your viewport to match the stated pixel resolution, and you're done. No need to "detect" or compensate for pixel shapes. As a (small inadequate) example of getting the physical dimensions, GLUT offers these two calls: glutGet(GLUT_SCREEN_WIDTH_MM) Width of the screen in millimeters. Zero indicates the width is unknown or not available. glutGet(GLUT_SCREEN_HEIGHT_MM) Height of the screen in millimeters. Zero indicates the height is unknown or not available. Other window systems should be able to provide such information, but I con't recall how at the moment. Gary HerronAhar, thanks Gary! I had no idea such information as physical dimensions might even possibly be available. I'll do a quick straw poll on various hardware and drivers within reach, see if these seem reliable. Thanks!
Here's a bit more info: On XWindows (Linux/Unix and perhaps Macs) the appropriate calls areDisplayWidthMM and DisplayHeightMM, and it looks like pyglet exposes those calls.
On Windows the appropriate call seems to be GetDeviceCaps, but I've not found any evidence that pyglet exposes that function.
Anybody know anything more about this? Gary Herron
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 pixelsaspect *= 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, topGL.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 squarepixels # Seems to be true for the native resolutions of my LCD. Use this # resolution to determine the aspect of the physical screen # measurementsphysWidth, physHeight = self.modes[0] # pygame for 'gethighest available screen resolution' physAspect = physWidth / physHeight# Assumtions 2: The current resolution is using all availablescreen # 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 screenresolution' pixWidth = info.current_w pixHeight = info.current_h pixAspect = pixWidth / pixHeightreturn 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.
