Pixi.js: Mipmapping not working with (Base)RenderTexture that has power of two size

Created on 10 Jul 2017  路  17Comments  路  Source: pixijs/pixi.js

I ran into this bug a while ago with, I think, 4.4.something, but didn't have the time to file a proper bug report. I didn't find it mentioned anywhere, yet, and it seems to still be present in 4.5.3, so here we go.

When creating and using a BaseRenderTexture that has power of 2 dimensions, mipmapping should be enabled automatically or at least when setting the mipmap property to true before rendering to the texture. But mipmaps are never generated and the "isPowerOfTwo" property stays "false". Of course, textures flicker terribly when zooming out far enough.

An example showing this is here:
https://jsfiddle.net/8zxk3f3L/3/
Created and tested with Chrome 59.0.3071.115 on an up to date OSX.

The example also shows a workaround, which is rendering to a canvas and creating a texture from that. This works as expected.

I crawled down the rabbit hole a bit with this.
The mipmaps are created by the texture manager when the texture is uploaded, here: https://github.com/pixijs/pixi.js/blob/dev/src/core/renderers/webgl/TextureManager.js#L143
That does not work for RTs because the isPowerOfTwo property is (still) false at this point.

The isPowerOfTwo property normally gets set in _updateDimensions: https://github.com/pixijs/pixi.js/blob/dev/src/core/textures/BaseTexture.js#L283
This in turn gets called by update just some lines above.
Update gets called for the case of creating a texture from a canvas by _sourceLoaded: https://github.com/pixijs/pixi.js/blob/dev/src/core/textures/BaseTexture.js#L605
This in turn is called by loadSource: https://github.com/pixijs/pixi.js/blob/dev/src/core/textures/BaseTexture.js#L335

Since loadSource seems to never be called for (Base)RenderTexture, the isPowerOfTwo property stays with its initial value of "false".

It seems to me as if just adding the pow2 check in the constructor after setting the realHeight and realWidth (here: https://github.com/pixijs/pixi.js/blob/dev/src/core/textures/BaseRenderTexture.js#L62) should do the trick for this one.

Stale

Most helpful comment

@artch OK, im taking my words back:

https://jsfiddle.net/mhra38m5/2/

First one is graphics, second is mipmapped, third is not mipmapped. My way (second) works better, so mipmaps are working on render texture

All 17 comments

Great job tracking this down @fmhdp, and thanks for the detailed writeup. Would you mind putting in a PR that performs the fix you suggested?

Any news here? We suffer from this issue too. I don't think creating a canvas is an acceptable workaround here.

Its not a bug. You cant have mips with generated stuff, because, well, you have to call gl.generateMipmaps somewhere and pixi doesn't know when exactly did you finish your work with render texture.

Also pow2 is not enough, width must be equal to height.

Also, after you generate mipmaps, there's no way back. you have to re-generate them if you change render texture.

Right, so a way to call gl.generateMipmaps explicitly for render textures would be a nice feature.

You can just bind that texture and then call generateMipmaps manually, and change filtering options on texture itself, like you do with any webgl stuff :) There are also methods in glTexture that allow to do that:

https://github.com/pixijs/pixi-gl-core/blob/master/src/GLTexture.js

//myTexture is BASE TEXTURE, if its not, take baseTexture of yours.


renderer.bindTexture(myTexture);
var glTex = myTexture._glTextures[renderer.CONTEXT_UID];
glTex.enableMipmap();
glTex.enableLinearScaling();

EDIT: updated code.

Ok, we have to add this option in pixi-v5 because people really need it.

I've tried to use your method, but it doesn't seem to work, here is the modified fiddle from the post above: https://jsfiddle.net/mhra38m5/1/ (see lines 41-44)

Sorry, I didn't get to prepare a pull request. Project stress, [excuse, excuse].

Its not a bug.
You cant have mips with generated stuff, because, well, you have to call gl.generateMipmaps somewhere and pixi doesn't know when exactly did you finish your work with render texture.

I am not sure if i agree with that.
The texture has a property signifying whether it has power of 2 dimensions,although it is internal, and it does not get updated when the size of the underlying texture changes. That seems to be a bug to me, but at least it's not pretty.
And that's the underlying cause that the existing flag, that tells whether we want mipmaps to be generated or not, is not working.

Also, pixi does know when to call enableMipMaps for other textures: when uploading it to the GPU. I'm not sure if that sentiment is shared, but I did expect that mipmaps will be regenerated when necessary if I do enable them.

Also pow2 is not enough, width must be equal to height.

I'm quite certain that is not true ad has not been for a long time by now.
I am using a number of textures where width and height are very different and they certainly do use mipmaps.

Ivan, I'd urge you to take a look at the pixi code again before pushing this off to 5.0 and making a wontfix for 4.x out of that.
I think the major places where the logic sits are linked in the initial bug report.

@artch I've modified the code, you forgot glTex.enableLinearScaling(); Also I'm sure that Graphics will give better result than any mip maps.

@artch OK, im taking my words back:

https://jsfiddle.net/mhra38m5/2/

First one is graphics, second is mipmapped, third is not mipmapped. My way (second) works better, so mipmaps are working on render texture

That worked, thanks!

Also, "antialias:true" in options helps for PIXI.Graphics (first one).

Also, pixi does know when to call enableMipMaps for other textures: when uploading it to the GPU. I'm not sure if that sentiment is shared, but I did expect that mipmaps will be regenerated when necessary if I do enable them.

Render textures are not uploaded to GPU, they exist there. We can add special update flag that will be incremented after render() , that we need mipmaps to be uploaded if texture gets bound. That's a good idea.

I'm quite certain that is not true ad has not been for a long time by now.
I am using a number of textures where width and height are very different and they certainly do use mipmaps.

Somehow, I failed to fully manually upload non-square textures mipmaps. But in this fiddle, 128x256 works!! OK, taking my words back, non-square pow2 is working fine.

@ivanpopelyshev Does v5 have what's needed to cover your v5 label you added, or not? Is it still worth closing this one down?

i think we fixed it in v5, ill check it later.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

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

lucap86 picture lucap86  路  3Comments

neciszhang picture neciszhang  路  3Comments

YuryKuvetski picture YuryKuvetski  路  3Comments

samueller picture samueller  路  3Comments

Makio64 picture Makio64  路  3Comments