0

I coded a game using pylet. It uses a static window with width 1600 and height 900 assuming users have a fullHD display so everything will be visible. However on some devices (with small displays) the window is way bigger as expected. I figured out that the pixel_ratio is set up (for example to 2.0) making each virtual pixel to be displayed double size (2x2) in physical pixel.

I want to prevent this behavior but can't figure out how, I know I can get the pixel ratio easily by get_pixel_ratio() but I actually don't know how to set them or prevent pyglet from automatically setting them.

I also tried to use glViewport which seemed to have an effect but it didn't worked the way I wanted.

So how can I change the pixel_ratio or prevent changing it automatically.

FinnK
  • 210
  • 4
  • 10

1 Answers1

1

Asked around in the official discord server for information, as I tried to reproduce the issue myself with some code, and this is what I used to test it:

import math
from pyglet import *
from pyglet.gl import *

key = pyglet.window.key

class main(pyglet.window.Window):
    def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
        super(main, self).__init__(width, height, *args, **kwargs)
        self.x, self.y = 0, 0

        self.keys = {}

        verts = []
        for i in range(30):
            angle = math.radians(float(i)/30 * 360.0)
            x = 100*math.cos(angle) + 300
            y = 100*math.sin(angle) + 200
            verts += [x,y]

        self.pixel_ratio = 100
        self.circle = pyglet.graphics.vertex_list(30, ('v2f', verts))

        self.alive = 1

    def on_draw(self):
        self.render()

    def on_close(self):
        self.alive = 0

    def on_key_release(self, symbol, modifiers):
        try:
            del self.keys[symbol]
        except:
            pass

    def on_key_press(self, symbol, modifiers):
        if symbol == key.ESCAPE: # [ESC]
            self.alive = 0

        self.keys[symbol] = True

    def render(self):
        self.clear()

        glClear(pyglet.gl.GL_COLOR_BUFFER_BIT)
        glColor3f(1,1,0)
        self.circle.draw(GL_LINE_LOOP)

        self.flip()

    def run(self):
        while self.alive == 1:
            self.render()

            # -----------> This is key <----------
            # This is what replaces pyglet.app.run()
            # but is required for the GUI to not freeze
            #
            event = self.dispatch_events()

if __name__ == '__main__':
    x = main()
    x.run()

Not that the code mattered heh, since the variable pixel_ratio is just, and I quote: "indicating that the actual number of pixels in the window is larger than the size of the Window created."

This is something OSX does to cope with the high DPI, using this information you should be able to scale your graphics accordingly. Window.get_framebuffer_size() will show you the difference in requested Window size and Framebuffer size, if any.

So your only way to actually scale up, would be to use glScale or if you're using sprites you can use Sprite.scale to scale the image-data. If you're using 2D graphics I'd go with the sprite option as it's pretty easy to work with.

Torxed
  • 22,866
  • 14
  • 82
  • 131
  • First of all, thanks for your answer! Seems all logical to me, but I am wondering what I should try to achieve by scaling. The main problem I got is that the window (after it got scaled up) is actually bigger than the screen. What it seems to me (after the stuff explained by you) is that I would have to set the scale of my graphics lower to prevent this problems from happening, is this correct? – FinnK Jun 08 '20 at 20:45
  • Moreover I am confused about this problem happening on so many devices. As you described and I also found on some other GitHub issues, the main problem comes with HiDPI-displays (especially Apples Retina display). But I also got the same problem on some Windows devices (actually it happened only on laptops, furthermore describing only on the own screens of the laptop not on external ones, most of them having FullHD, which I assumed are no HiDPI displays). Is there something I don't know about which display is a HiDPI display or may there be another problem going on? – FinnK Jun 08 '20 at 20:47
  • You can set your window size to match the [resolution of the monitor](https://stackoverflow.com/questions/38204398/pyglet-resolution-of-screen-into-variables) while taking DPI into consideration. Then, seeing as everything will be come very oddly scaled (especially on OSX or 4K monitors) you can use `glScale` or `sprite.scale` to upscale individual objects so that they appear "normal". Laptops in general have started using HiDPI more and more (I have two of them, one Linux and one Windows). Windows have upscaling by default these days and fucks up a lot of things as well heh. – Torxed Jun 09 '20 at 06:06
  • Just to clarify, HiDPI has nothing to do with FullHD or any of those buzzwords. HiDPI just points (as you probably know) how many physical pixels there are per inch in the physical display panel, but not how high the actual render resolution are is up to the software render engine inside the monitor. For instance, having a 480x320 software render makes the CPU (monitor) to CPU (computer) pipeline pretty fast, while 1500DPI would only load the onboard monitor CPU with work load. Altho pointless, perhaps this explains the difference. – Torxed Jun 09 '20 at 06:11
  • Lastly, here's a pretty good writeup of the thing: https://www.sqlshack.com/4k-resolution-and-high-dpi-what-you-need-to-know-about-it-to-have-great-visuals/ – Torxed Jun 09 '20 at 06:11