Pixi.js: Retina support

Created on 2 Mar 2014  ·  66Comments  ·  Source: pixijs/pixi.js

On a retina display, shapes drawn with PIXI look blurry. I tried making a forum post about this but it didn't really go anywhere. I looked into this further, and setup some side by side examples of normal canvas vs. PIXI to help better demonstrate the problem. Here's a fiddle

And a screenshot

I'm not sure what the deal is w/ the weird black background on my attempt at scaling the PIXI canvas context... I might've done it incorrectly or something else in the framework is getting in the way or got messed up by modifying the context.

It seems like PIXI could add built in retina support by checking devicePixelRatio and then adjusting the canvas + context properties accordingly, but I'm not sure what other implications that might have.

Most helpful comment

A CSS method that worked for me using canvas (without pixi.js)
canvas { image-rendering: optimizeSpeed; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: optimize-contrast; image-rendering: crisp-edges; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor; }
Just in case this can help anyone.

All 66 comments

I agree with this bug. As a reference, this is how this can be normally handled: http://www.html5rocks.com/en/tutorials/canvas/hidpi/

This is also an issue with text.

Let's say you have a retina screen with devicePixelRatio of 2 and you want to get a crisp-looking 400x300 canvas. To get that you need to initialise the PIXI renderer with your desired canvas dimensions multiplied by devicePixelRatio (800x600) and then manually scale the canvas down to 400x300 using css. And then, of course, you will have to incorporate this scaling into all of your calculations: positions, font sizes, line widths, loaded assets, etc.

I am using something like this:

var canvas = document.getElementById('game'),
    scale = window.devicePixelRatio,
    width = 400,
    height = 300,
    renderer = PIXI.autoDetectRenderer(width * scale, height * scale, canvas);
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';

+1

Any plans to tackle this soon? Having to scale every size, position, font size is really painful. Especially when there's a fairly simple way to do this with the standard canvas.

It is difficult to do this library size, because it is dependant on whether your sprites are hidpi or not. We have kept it in userland because we don't know what sprites of yours to scale for hidpi, if any, and when; but you do.

Hey @englercj . By sprites, do you mean assets loaded by the user?

@dcascais yes

@englercj Thanks for your reply.

Currently, if the renderer view is scaled with the CSS trick (described in my previous link) to get proper display resolution, anything that is added to the the stage and then rendered with the scaled renderer view is not scaled accordingly, it maintains its pixel values, so basically half the size.

This includes content being rendered dynamically on the graphics context, text and assets loaded.

Other platforms assume that it's the user's responsibility to provide the proper assets for the different screen densities, but the internals work seamlessly having a scale factor property that let's you easily decide what display density you'd like to target. I wonder if this would be a simpler approach for the Pixi users. Letting them only worry about the proper assets and making sure that the scale factor is correctly set.

Do you have a suggestion as to how achieve the expected scaling of the content added to the stage?

Manually scaling the x, y, width and height values of every item on the display list and in the case of text, defining different strings that have font names with the proper size can get very cumbersome and bug prone if you are dealing with a big project.

Thanks.

Interesting, I would like to see how some of those systems work. AS far as scaling each item individually, that doesn't seem like the way to go. Since this is a scene graph couldn't you just scale your root DOC appropriately?

@englercj, I had tried this in a sandbox and while it blew things back up to the proper size, it left them pixelated. Would you expect different behavior?

@bmantuano I expect it to be scaled with the algorithm that was chosen (nearest, linear, bicubic, etc).

Chad, thanks for responding here. As for scaling algorithm, do you refer to the PIXI.scaleModes? If so, seems the bicubic option isn't there.

@englercj Here are a few JSFiddles that show what we are trying to do to get crisp text and graphics (dynamically drawn, not assets) on high res displays.

Canvas scaling and scaled main display object container (Correct size but blurry and with some issues)
http://jsfiddle.net/hsv8Q

Canvas scaling (shows up crisp but wrong size and with some issues)
http://jsfiddle.net/hsv8Q/1

No scaling (Correct size but blurry)
http://jsfiddle.net/hsv8Q/2

Hopefully this will help you understand what we mean. Let us know if there's something else that we should be trying.

Thanks @dcascais for adding those fiddles. @englercj, the first one is what you were suggesting, right? Are you able to see the pixelation on a high DPI device there?

@bmantuano Unfortunately I don't have a HDPI device to test one :( I'm going to leave this one for @GoodBoyDigital or @photonstorm to look at.

@englercj, thanks for looking into it thus far. Appreciate the help. @arahlf and @n1313, have you found a workaround?

No, not yet :(

@bmantuano, I am still using the approach described in my previous comment and have no problems whatsoever.

Has there been any movement on this? I've used the scaling method @n1313 mentioned but it's destroying FPS on retina devices.

Any ideas?

@arahlf and @n1313, thx for the replies.

@GoodBoyDigital, is this on your radar? Would be helpful just to get an idea if it's something we can expect in a future update or whether we need to hack around it.

@GoodBoyDigital Just wanted to add my voice here. I'm working on a Massively Multiplayer Online game using Pixi.js because we identified it as the most performant rendering engine out there, but we're really hurting for retina display support!

As it happens, I'm actually half way through adding retina support :) Watch this space..

Awesome :+1:

@GoodBoyDigital, that's fantastic! Thanks for the update. Looking forward to it.

@GoodBoyDigital That's awesome! Thanks so much for getting back to me so quickly. I know it's generally tough to say, but could you give me a very loose ballpark estimate for when you think retina support will be done for Pixi?

I won't hold you to the estimate or complain if it's not done in that time frame-- just curious generally how long you think we'll be waiting!

Hey guys - just uploaded the new "dev-retina" branch to git hub. It would be ace if you could all have a play. There are lots of moving parts in there so figured it would be good to test it with some real projects before merging it into the dev branch.

Renderer now have an option parameter. One of the new options is resolution. So to set the renderer to retina you can create a renderer like this:

PIXI.autodetectRenderer(100, 100, {resolution:2})

Everything should look the same.. but the resolution will be higher :)

BaseTextures also have a resolution now too. If the image is a high res one then you will need to set the resolution to 2. The way to get the resolution set to two automatically on load is to append the image with @2x to the image name.

So if you load in say: [email protected] then pixi will assume it has a resolution of 2.

Best to have a play really! But please ask questions as this probably is not as straight forward as it seems :)

+1

Hey Matt. This looks great! I was able to get the Canvas to render nice and crisp text and assets. Size and Position seem to be correctly handled as far as I've tested.

The only thing I seem to be having issues with is the Pixi.Graphics drawing procedures. I can't seem to be getting those to render crisply. The size and position of the rendering is correct, though.

Graphics objects should be retina too? are ya cacheing as bitmap the
graphics object by chance? or is it straight up PIXI.graphics?

On Tue, Sep 9, 2014 at 5:32 PM, dcascais [email protected] wrote:

Hey Matt. This looks great! I was able to get the Canvas to render nice
and crisp text and assets. Size and Position seem to be correctly handled
as far as I've tested.

The only thing I seem to be having issues with is the Pixi.Graphics
drawing procedures. I can't seem to be getting those to render crisply. The
size and position of the rendering is correct, though.


Reply to this email directly or view it on GitHub
https://github.com/GoodBoyDigital/pixi.js/issues/621#issuecomment-54997804
.

Mat Groves

_Technical Partner_

Telephone: 07708 114496 :: www.goodboydigital.com
First Floor, Unit 9B, Queens Yard, White Post Lane, London, E9 5EN
goodboy©. All Rights Reserved.

@GoodBoyDigital When describing the issue I missed part of the configuration I have. The setup I have is a PIXI.Sprite with a texture based on a PIXI.Graphics object.

I created a JSFiddle to help describe the issue and the resulting rendering:
This one shows the blurry graphics output if the PIXI.Sprite gets a texture based on a PIXI.Graphics:
http://jsfiddle.net/hsv8Q/13/

This setup with a direct usage of a PIXI.Graphics works OK:
http://jsfiddle.net/hsv8Q/7/

gotcha! no worries - i know exactly what is causing that :)
Will let ya know once its tweaked. ta!

Hey @GoodBoyDigital , thanks for the retina support! It comes at a great time too, as we need it for our client :)

One problem I noticed in the retina branch: the rendering is better, but the hit areas are misaligned. The canvas is scaled, but the hit areas are not. So if I want to touch a button in the center of the screen, I have to touch the center of the left-upper quarter of the screen to actually touch it.

kaatje_retina_offset
In this screen, if I want to hit the button in the center, I have to hit in the orange circle (which I added in later as an example) to actually hit it. The hitarea does not scale with the rest.

About the "resolution" parameter in the autodetectRenderer function; we could just use "window.devicePixelRatio" right?

I found a quick/dirty workaround for the issue I described above. The problem seems to be located in the onTouchStart, onTouchMove and onTouchEnd functions of the InteractionManager. It can be fixed by changing the calculation of touchData.global.x and touchData.global.y in those functions and dividing them by this.resolution.

This seems to fix the issue, but there might be a much better solution.

hi @GillesVermeulen
I tweaked the hit area stuff in my last commit. Would trying with the latest version pls? ta!

Hey @GoodBoyDigital , thanks for the quick reply and support, but is it possible that the commit you're talking about is not on Github yet?

@GillesVermeulen - touch should be good now. I was only applying the resolution change to the mouse events. Let me know if it all works ok for ya now. thanks!

Afternoon @dcascais ! I just pushed a fix to the retina branch that will let you define the resolution of the generateTexture function.

So for a nice crispy retina texture all you can do this:

var retinaTexture = myGraphicsObject.generateTexture(2)
var normalTexture = myGraphicsObject.generateTexture(1)
var smallTexture = myGraphicsObject.generateTexture(0.5)

let me know if how that works out for ya. Thanks!

@GoodBoyDigital Nice! This now works quite nicely. I appreciate the update on this.

As a general question. Have you or others run into other things such as performance, memory or crashing issues based on this high res update?

Thank you, Mat.

Glad to hear!

Wish there was a magic bullet for that one! Unfortunately higher resolution will indeed affect performance and memory consumption as you essentially everything will be doubled in size. Retina images take up 2x as much memory and webGL / Canvas will need to render a scene with 2x as many pixels. On low memory / cpu devices this could be a real killer so its it very important to be mindful when doing anything with high res.

Wouldn't those figured be 4x? Also isn't it pretty much guaranteed that people with retina displays will also have fast computers?

@iirelu true indeed! 4x as much!
Yes I don't imagine there would be any issues on computers with retina display as they would be quite high-end.

The memory issues would be more likely to manifest themselves on mobile devices that have retina screens.

@GoodBoyDigital , thanks for the update to the touch functions. It was the same as my temporary fix and seems to do the trick.

On performance: since recently I've been testing stuff out in CocoonJS on IOS7. The performance is definitely better compared to the standard iOS Webview that is used by things like Phonegap, but drawing shapes seems to be very taxing and the shapes are not anti-aliased like in Safari. I imagine this is CocoonJS related and has little to do with Pixi.

As soon as you apply a filter to a retina (@2x) texture, all positioning seems to be off.

Thanks for the heads up @joaomoreno ! Will make sure to take a look :+1:

Just a small question about the API that you present: Isn't there a clash between PIXI.autodetectRenderer(width, height, optionObject) and PIXI.autodetectRenderer(width, height, view, antialias, transparent)?
Would that make the optionObject argument the sixth argument from the second signature as described in src/pixi/utils/Detector.js? I'm not entirely sure where else to put it, as the third argument is already a DOMElement, isn't it?

The next version of pixi will use the new method signature, this is a breaking change.

@englercj Thanks a lot for your quick response. Will the dropped options still remain accessible in some other way, then?

The options object contains all the previous options and new ones. Functionality is not being removed, you just pass the options differently:

https://github.com/GoodBoyDigital/pixi.js/blob/dev/src/pixi/utils/Detector.js#L14-L19

Oh, handy! Thanks a lot for that. :+1:

retina support is in the dev branch now. Please let me know if anyone finds any issues with it :+1: closing for now.

I'm having an issue with a retina macbook pro.

I'm not using {resolution:2}.

The stage width returns the real retina pixels. In my case it's 2540 pixels. The textures are rendered at twice their size and their widths are not in real 1:1 retina pixels either. So a 300 x 200 image occupies 600 x 400 retina pixels, but the width returns 300.

Is this expected behaviour?

@PierBover Yes, the height/width of the object hasn't actually changed. It is just rendered at a different resolution.

@englercj but how come there are dimensions in real pixels and doubled pixels mixed?

Hey guys, am I doing something wrong here. If I make my CanvasRenderer's resolution 2 for a retina display it makes my canvas twice the size and my @x2 images four times the size.

    @scale = window.devicePixelRatio
    width = 960/@scale
    height = 556/@scale

    renderer = new (PIXI.CanvasRenderer)(width, height,{resolution:@scale})
    container = document.getElementById 'container'
    container.appendChild renderer.view

StackOverflow Question
http://stackoverflow.com/questions/29142342/pixi-js-retina-display-canvas-is-doubled-in-size

In this issue and in this blog post http://www.goodboydigital.com/pixi-js-v2-fastest-2d-webgl-renderer/ the retina images are mentioned to need either a @2x or a @x2 before the extension. I am assuming the correct is @2x. Is this correct?

@2x is correct. It can be a folder name or appended to the image name.

assets/@2x/image.png or assets/[email protected]

@Adireddy thanks. That's half the battle. Any idea why my canvas is scaled rather than the resolution increasing?

Same problem here for retina, any usage of resolution: 2, makes some PIXI.Text anchor positioning wrong. Rescaling back the canvas in CSS doesn't help much. I had to set resolution to 1, double my Text font size, then scale it to half.

And Even with that the text still not look smooth.

Hi Elyx0, you may try my text plugin for mobile available here : https://github.com/JiDW/pixi-cocoontext

Does it fix your issues ?

Hi @JiDW , I finally fixed it. I'm using bare PIXI.js so no Cocoon for me, my view canvas wasn't properly setup. Thx

@GillesVermeulen

I'm considering to support High DPI devices in my project, so I'm wondering:

The canvas is scaled, but the hit areas are not.

Has this been solved in PixiJS? (eg in a later/recent version)

Hey @tobireif, I do think so yes. Haven't had the problem for a long time, but that's with Pixi v2. I don't think it's an issue with newer version either.

@GillesVermeulen Sounds good! Thanks!

A CSS method that worked for me using canvas (without pixi.js)
canvas { image-rendering: optimizeSpeed; image-rendering: -moz-crisp-edges; image-rendering: -o-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: optimize-contrast; image-rendering: crisp-edges; image-rendering: pixelated; -ms-interpolation-mode: nearest-neighbor; }
Just in case this can help anyone.

Hi !

I'm having an issue with my last project : http://romaincazier.com/davatars/

I can't get the right pixel resolution on my objects... I don't know if it's about the renderer or the graphics I generated the textures from, but in both case I added the window.devicePixelRatio but it doesn't seem to have any influence.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

madroneropaulo picture madroneropaulo  ·  3Comments

Makio64 picture Makio64  ·  3Comments

st3v0 picture st3v0  ·  3Comments

finscn picture finscn  ·  3Comments

lucap86 picture lucap86  ·  3Comments