Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Retina / High-DPI support #1127

Closed
slime73 opened this issue Jan 15, 2016 · 3 comments
Closed

Improve Retina / High-DPI support #1127

slime73 opened this issue Jan 15, 2016 · 3 comments
Labels
11.0 change Change to existing functionality

Comments

@slime73
Copy link
Member

slime73 commented Jan 15, 2016

Original report by Alex Szpakowski (Bitbucket: slime73, GitHub: slime73).


LÖVE's current support for high-dpi displays (on supported operating systems – #1106 would make it easier to add Windows support) just makes love.graphics use the full pixel density of the window, and adds love.window.toPixels and love.window.fromPixels to convert between pixels and "density-independent units". All love.graphics objects and functions have units in pixels, and mouse and touch coordinates are in pixels as well.

This is not an ideal situation when dealing with high-dpi displays (especially common on mobile), as users will expect things to have the same final output scale with high-dpi enabled as if it were disabled (where the pixel density of the window is greatly reduced). LÖVE also doesn't provide many ways to help with using higher resolution assets for high-dpi screens.

In my eyes, there are two main topics when dealing with high-dpi that LÖVE could improve:

  • Using assets of different resolutions that are meant to have the same output size on-screen, e.g. a 1024x1024 version of a sprite sheet (and 32x32 pixel sprites in the sheet), and a 2048x2048 version (and 64x64 pixel sprites in the sheet) for higher DPI devices, which should be interchangeable without having lots of code to deal with scaling the output size of the assets.

  • Graphics coordinates which should be scaled to what the OS says is the expected size. For example all other apps on my iPhone treat the screen as having 375x667 points ('dpi-independent units') in their code for placing content on the screen, even though the actual screen resolution is 750x1334 pixels. If a LÖVE game were to enable high-dpi mode and draw normally without accounting for the pixel scale (love.window.getPixelScale or love.window.fromPixels), it would display things really small on my iPhone compared to what I expect.

For the first topic, there is actually a nice but unintuitive solution in LÖVE already for the specific example I gave: If you use love.graphics.newQuad(0, 0, 32, 32, 1024, 1024) but draw the 2048x2048 sprite sheet using that Quad, it will show up at the exact same scale as the low resolution sprite sheet and use the proper sprite.

A more intuitive solution might be to have a 'scale' parameter in love.graphics.newQuad, love.graphics.newImage, and love.graphics.newCanvas (more on Canvases later). A scale of 2 would make a 2048x2048 image show up on-screen as 1024x1024 normally. Maybe images and canvases would report their "scaled size" when getWidth and getHeight are called, and new getPixelWidth and getPixelHeight would report the full pixel sizes in case that's needed sometimes.

For the second topic, LÖVE should probably report mouse and touch coordinates in terms of 'DPI-independent units' rather than pixels, and the graphics coordinate system (orthographic projection matrix) should be in those units instead of pixels as well. love.graphics.getDimensions would return the equivalent of 0.10.0's love.window.fromPixels(love.graphics.getDimensions()), and there could be a new love.graphics.getPixelDimensions function to get the actual pixel resolution when needed.

Canvases could probably have a default 'scale' parameter equal to love.window.getPixelScale() (so they'd act like the main screen by default). Having a non-default canvas scale would affect both its pixel dimensions and the screen coordinates when rendering to it. e.g. love.graphics.newCanvas(1024, 1024, {scale=2}) would make a 2048x2048 pixel canvas where Canvas:getDimensions would report 1024x1024, drawing it to the screen would make it show up at the same size as a 1024x1024 rectangle, and when drawing content to the canvas, love.graphics.points(512, 512) would draw a point to the middle of the canvas.

All of this is just in my head at the moment, I haven't done any real tests or implementations, so some parts might not be good ideas or could change. I could make the graphics orthographic projection matrix completely runtime-modifiable per Canvas or globally, but I'm not sure whether that would be more useful or more confusing.

@slime73
Copy link
Member Author

slime73 commented Sep 17, 2016

Original comment by Alex Szpakowski (Bitbucket: slime73, GitHub: slime73).


I have an incomplete / work-in-progress branch for this here: https://bitbucket.org/bartbes/love-experiments/branch/retina3

@slime73
Copy link
Member Author

slime73 commented Dec 30, 2016

Original comment by Alex Szpakowski (Bitbucket: slime73, GitHub: slime73).


Revamped and streamlined retina / high-DPI support (resolves #1127).

With the highdpi window flag enabled on a retina-capable display and OS, content should now appear to the user at the same size and in the same positions as with the flag disabled.

As a result, mouse and touch coordinates, Texture and graphics dimensions, and the graphics coordinate system now use pixel density-scaled units instead of pixels. Raw pixel units should generally only be used for things such as shader algorithms which execute per-pixel and rely on accurate pixel dimensions. love.window.fromPixels and friends typically don’t need to be used anymore.

Images, Canvases, and Fonts can have an optional explicit ‘pixel density’ set when creating them. This allows for easily loading high pixel density content which displays at the same size as regular or low pixel density content.

API changes:

  • Added Texture:getPixelWidth/getPixelHeight/getPixelDimensions and Texture:getPixelDensity. Texture:getWidth/getHeight return the pixel density-scaled width and height (as it will appear on the screen when drawn) rather than the number of pixels on each texture dimension.

  • Added love.graphics.getPixelWidth/getPixelHeight/getPixelDimensions.

  • Added optional ‘pixeldensity’ field to the settings table parameter of love.graphics.newImage. It defaults to 1, or if the file the Image was loaded from has “@2x”, “@3x”, etc. at the end of its name, it uses that number as the pixel density scale by default.

  • love.graphics.newCanvas now takes a table as its third parameter, with fields “format”, “msaa”, and “pixeldensity”. pixeldensity defaults to the main screen’s pixel density. The width and height parameters specify the visual size that the Canvas will be drawn at / can be drawn to (pixel density-scaled units).

  • love.graphics.newVideo accepts a table as its second parameter, with optional fields “audio” and “pixeldensity”. pixeldensity defaults to 1.

  • love.graphics.newFont variants have an optional pixeldensity parameter at the end of the argument list. For TrueType fonts this defaults to the current pixel density scale of the screen, and for BMFonts and ImageFonts this defaults to 1.

  • Added Font:getPixelDensity.

  • Renamed love.window.getPixelScale to love.window.getPixelDensity.

@slime73 slime73 closed this as completed Dec 30, 2016
@slime73 slime73 added major change Change to existing functionality 11.0 labels Feb 20, 2020
@Kiotwo
Copy link

Kiotwo commented Aug 20, 2020

Hi @slime73, I think some of these changes haven't been documented in the API pages of the Löve Wiki yet.

From https://love2d.org/wiki/11.0:

  • Updated love.graphics.newImage to treat file names ending with "@2x", "@3x", etc. as a pixel density scale factor if none is explicitly supplied.
  • Added the ability to specify a per-object pixel density scale factor when creating Images, Canvases, Fonts, and Videos. Affects drawing.

These two changes were not mentioned on https://love2d.org/wiki/love.graphics.newImage. I've added the first one to the page, but I can't add the second change to the Wiki because I don't know to which function signatures it applies. Could you please add this to the Wiki page?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
11.0 change Change to existing functionality
Projects
None yet
Development

No branches or pull requests

2 participants