setGenerateMips() not working

Hi,

I’m trying to configure automatic generation if mipmaps, but the TextureKey.setGenerateMips() method doesn’t seem to work for me.

I’m using 256x256 graphic to test, I compare a PNG graphic with a DDS one. The DDS is the same picture, except it already has its own mipmaps, and I can see it looks much better in the game.

Here is my code:

        boolean useAutoGeneratedMipmaps = true;

        Texture img;
        if (useAutoGeneratedMipmaps) {
            img = assetManager.loadTexture("NW_WATER_LAKE01_A0-szachy.png");
            img.setWrap(Texture.WrapMode.Repeat);
            img.setMinFilter(Texture.MinFilter.BilinearNearestMipMap);
            var imgTk = (TextureKey) img.getKey();
            imgTk.setGenerateMips(true);
            imgTk.setAnisotropy(16);

        } else {
            img = assetManager.loadTexture("NW_WATER_LAKE01_A0.dds");
            img.setWrap(Texture.WrapMode.Repeat);
        }

        var material = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
        material.setTexture("DiffuseMap", img);

        Geometry g = findGeometryOfMaterial(mesh, "NW_WATER_LAKE01__OCEAN_CLOSE_01");
        g.setLocalScale(.004f);
        g.setMaterial(material);

        rootNode.attachChild(g);

And here you can see how it compares:


when I comment out the imgTk.setGenerateMips(true); it doesn’t change anything.

I also tried to set mipmap generation with AssetEventListener like below, with same (lack of) result:

        AssetEventListener asl = new AssetEventListener() {
            @Override
            public void assetLoaded(AssetKey key) {
            }

            @Override
            public void assetRequested(AssetKey key) {
                if (key.getExtension().equals("png") || key.getExtension().equals("jpg")) {
                    TextureKey tkey = (TextureKey) key;
                    tkey.setGenerateMips(true);
                    tkey.setAnisotropy(16);
                    if (key.getExtension().equals("png")) {
                        System.out.println("\tAsset requested: " + key.getName() + "\t" + key);
                    }
                }
            }

            @Override
            public void assetDependencyNotFound(AssetKey parentKey, AssetKey dependentAssetKey) {
            }
        };

Have anyone managed to succesfully auto-generate the mipmaps?
Any ideas why doesn’t it work in my case?
I’d be grateful for any advise…

cheers :slight_smile:

TextureKeys are used to load textures, not control them. You need to enable mips generation on the key before loading the texture.

var key = new TextureKey("NW_WATER_LAKE01_A0-szachy.png");
key.setGenerateMips(true);
key.setAnisotropy(16);
img = assetManager.loadTexture(key);
6 Likes

Good to know! :slight_smile:
Your code works.

It seems the generate-mips option is true by default in TextureKey class. I can see mipmaps being used just by loading the texture with key (as opposed to loading directly):

            var key = new TextureKey("NW_WATER_LAKE01_A0-szachy.png");
            //key.setGenerateMips(true);  // not required, true by default

            img = assetManager.loadTexture(key); // obtains texture with mipmaps

            //img = assetManager.loadTexture("NW_WATER_LAKE01_A0-szachy.png"); // optains texture without mipmaps

Thank you for the help :slight_smile:

btw. I often feel like jMonkeyEngine javadoc could be more helpful explaining the usage of the classes… :frowning:

1 Like

I have another scenario, where I use asset manager to load textured 3d model from a file:
Spatial mesh = assetManager.loadModel("siatka.obj");

The .obj file refers a .mtl which defines materials with .png textures. The model renders fine, textures are used, but mipmaps are not generated.

I expected the AssetEventListener to setup the TextureKey to generate mimpaps before textures gets loaded. Apparently, even though I can see the assetRequested() method gets triggered with my .png image, the mipmaps generation does not work.

 AssetEventListener asl = new AssetEventListener() {
            @Override
            public void assetLoaded(AssetKey key) {
            }

            @Override
            public void assetRequested(AssetKey key) {
                if (key.getExtension().equals("png") || key.getExtension().equals("jpg")) {
                    TextureKey tkey = (TextureKey) key;
                    tkey.setGenerateMips(true);
                    tkey.setAnisotropy(16);
                    if (key.getExtension().equals("png")) {
                        System.out.println("\tAsset requested: " + key.getName() + "\t" + key);
                    }
                }
            }

            @Override
            public void assetDependencyNotFound(AssetKey parentKey, AssetKey dependentAssetKey) {
            }
        };

any thoughts on that one? :slight_smile:

I do not know if the .mtl file allows setting min filter or not or if JME supports reading them in obj/mtl loader (I know that it is supported via GltfLoader).

So you might need to set the min filter on the texture after it is loaded because by default Texture uses the BilinearNoMipMaps filter which does not use mips.

Actually… it seems the generate-mips parameter works opposite to what I was expecting… :face_with_raised_eyebrow:

Is this a bug, or am I misunderstanding the concept?

Set it to true when you want to generate mip maps… like in the bottom image. Set it to false when you don’t want to generate mip maps like in the top image where there is no minification at all.

Maybe there is a misunderstanding of what mipmaps are and how they work?

When I load .dds image which already contains mipmaps inside, the textured object looks like the top screenshot - sharp image even at the distance.

When I load .png image which doesn’t contain mipmaps inside, I nvoke setGenerateMips(true) and I expect jMonkeyEngine to generate mipmaps for the image, in which case it will look similar as if .dds was used.

When I load .png image and invoke setGenerateMips(false) I expect jMonkeyEngine not to generate mipmaps for the image, hence the image without mipmaps would look blurred at a distance - as on the bottom screenshot.

Is my thinking wrong?

The top image is ugly… it’s literally just sampling exact pixels in the highest mip level with no distance filtering at all.

Makes me think your DDS is not using min filtering at all… even if it has mips maybe the min filter is set to “nearest” with no map mapping.

“Blurred” how? The lower level mips are the blur. That’s what the lower level mips are. Shrunk down versions of the original image “filtered” to look nice. 2x2 pixels get averaged to 1 pixel for the first level. 4x4 pixels get averaged to one pixel for the next level, etc…

A checkboard should fade to gray with distance. Yours seems really oversaturated and/or your pixel format for the texture doesn’t have enough bits… but it is definitely getting filtered.

Ok, so I took the top screenshot for the result of mipmapping, while it is not. Thank you for explanations.

That’s probably the source of my mistake (plus lack of experience, obviously :wink: ). When I load .png it looks as the bottom screenshot, so I thought that is because lack of mipmaps.

Maybe I will try to play with MinFilter options and do some comparision png vs dds then.

2 Likes