thepaperpilot

Maintaining Sharpness while Downscaling Large Sprites

Recommended Posts

I have a program where images are shown in normal HTML <img> tags as well as inside of PIXI canvases. If I have a large image, I notice it has very crisp edges even when shown at ~1% of its size. The pixi.js canvas is using pixi-viewport (https://www.npmjs.com/package/pixi-viewport) so I can zoom in and out, and I noticed that if I zoom out so that the image is the same size as the HTML one, the edges look blurry. I've tried changing the SCALE_MODE and resolution, tried forcing the canvas renderer or forcing FXAA, and even the image-rendering css property, but I can't seem to make it look like the image inside the <img> tag. This is what I'm seeing:

image.png.7cadc29ef0457301de78cc68827f0f83.png

 

To be clear, the one on the left is inside the <img> and the one on the right is inside a pixi.js canvas. Despite them being about the same size, you'll notice its less clear. 

If I change the SCALE_MODE it just looks pixelated. If I change the resolution (I've tried 1, 2, 4, and 10) I have to zoom in more, but once I have its just as blurry. Forcing the canvas renderer just made it look worse, and FXAA didn't seem to change anything. The image-rendering property seemed to have no effect except on the pixelate setting (which, obviously, just made it look pixelated).

Edit: For reference I'm using pixi.js-4.5.3 and pixi-viewport-3.23.1

Share this post


Link to post
Share on other sites

Thanks Jon, but that doesn't solve my issue. I tried changing the scale mode from linear (shown in the OP) to nearest neighbor, but the image still didn't look right:

image.png.a3ca0309068b5c222abff784163e1b39.png

For good measure I also tried changing the resolution to 10 as well as using nearest neighbor, with no effect (apart from me needing to zoom in further)

Share this post


Link to post
Share on other sites

Do you have mipmaps on? Changing that could have some affect. Also does your sprite align to subpixel coordinates? That can cause some blurrines.

You could also try changing the minFilter of the gl texture, though I'm not sure if pixi overrides it with setting from scalemode. In webgl possible options are LINEAR, NEAREST, NEAREST_MIPMAP_NEAREST, LINEAR_MIPMAP_NEAREST, NEAREST_MIPMAP_LINEAR, LINEAR_MIPMAP_LINEAR.

I'm not sure what minification algorithm browser uses with img tags, but I'm pretty sure it's something more expensive and with better quality than the ones used in realtime rendering.

 

Share this post


Link to post
Share on other sites

What's the size of image and what's the size of PNG?

if PNG is power-of-two. then you can enable "baseTexture.mipmap=PIXI.MIPMAP_MODES.POW2" before it first renders then in case of big downscale (>2) it'll look better, it'll use those MIPMAP constants in webgl.

If its not pow2 (512, 1024, 2048, e.t.c.) there are two ways:

1. make it pow2 - either scale either add more pixels at right-bottom, you can adjust "texture.frame" afterwards.

2. enable mipmap for webgl2 for any sizes: "baseTexture.mipmap = PIXI.MIPMAP_MODES.ON". It works only on webgl2 devices.

In general, if you try big downscale in any WebGL renderer you'll have that problem. ThreeJS  does resizing automatically.

SUMMARY:

its one of those things you have to know when you move your app to WebGL. There are others like that, for example: anti-aliasing, blending modes.

DEMO:

Try it here, comment the respective lines, switch to different modes: https://www.pixiplayground.com/#/edit/qWXxeV7e1KOyWayy6DLu5 . I know that even Google Skia webasm port has problems when you try to downscale "Google.png" ;)

Share this post


Link to post
Share on other sites

Extra info, what does mipmapping do: it scales down 2 times, then again 2 times, and obtains several "mip-levels" . then it samples the texture from levels depending on scale. Scale is determined through comparing "What coordinates of texture were asked in neighbour pixel shader". If we upload FAKE mipmap levels, we can see result like this: https://github.com/Busyrev/mipExploration , here we have curved space and its scaled in the center => mipmap is automatically switched there to next level (red), then next one (green) and so on.

Manually scaling the texture and choosing sprite texture based on downscale also works! You have to use whatever you udnerstand and whatever is better for your case. Yes, it might be strange if you come from Web that now , in WebGL, you  have to manage many other parameters: texture filtering, antialias, blendmodes, premultiplied alpha, gamma sRGB. Usually its managed automatically by browser, but that automatic managing can affect performance, and in WebGL world its significant, its all about performance.

I'll have a talk in russian conference HolyJS about those things, I hope to translate it afterwards and use in other places too. I know that many people are smart enough to make their algorithms fast, but that kind of problems stop them just because they dont know specifics of WebGL switches and how big control they actually have, what responsobilities it raises.

Share this post


Link to post
Share on other sites
32 minutes ago, thepaperpilot said:

I'll check out those mipmap settings. I'm on pixi v4 right now, so I'll try migrating but it's an electron app so might take a bit of tweaking. Thank you Ivan!

in v4 "baseTexture.mipmap=true" is default setting so it should work if you have pow2 texture. If not - well, pick your poison. Use pow2 size or don't make big downscales.

Oh, right, Welcome to the Forums!

Share this post


Link to post
Share on other sites
37 minutes ago, ivan.popelyshev said:

in v4 "baseTexture.mipmap=true" is default setting so it should work if you have pow2 texture

hey @ivan.popelyshev, this sujet intrigue me.
So alway better to perform this kind of packaging algo in texturePacker ?
Do you mean the texture from pixi or make a spritesheet in pow2 will also ok ?
From what i understand, the size constraint from texturePacker resize only the baseTexture.
ZdMBy24n_o.png

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.