Texture too bright

Hi,

I’m making some sort of ModelEditor to quickly test my assetpipeline (blender -> gltf -> j3o).
I have an issue with the loaded textures of my models, they appear to bright when gamma correction is enabled.

I guess it’s related to colorspace issues, but I don’t fully understand the issue and am not able to fix it.

loaded model with gamma correction: on

loaded model with gamma correction: off (this is also how it looks in Blender)

I added some logging of the material when loading the model:

model.depthFirstTraversal(new SceneGraphVisitorAdapter() {
            @Override
            public void visit(Geometry geom) {
                Material material = geom.getMaterial();
                MatParamTexture texture = material.getTextureParam("BaseColorMap");
                log.info("ColorSpace: {}", texture.getColorSpace());
                log.info("ColorSpace: {}", texture.getTextureValue().getImage().getColorSpace());
            }
        });

both lines output: “ColorSpace: sRGB”.

Changing the ColorSpace of the texture to Linear makes it even brighter.

You have to add the ToneMapFilter to the FilterPostProcessor/viewport.

I’m not 100% sure, but if you have a PBR model and a light probe which only contains a gray background, this might be the result.

Wow… this is brand new information for me. Now I need to see if I can fix all of my scenes that are busted when I turn gamma on. lol

Edit: (And note that in my case, these are not pbr.)

Is there a light probe on scene? If not, you should generate one from a skybox on scene.

Also try to scale down directional light. I usually scale it by 0.1f for PBR scene.
And increase roughness value. In most case I set it to 1.

From my experience of using PBR all the time without a light probe, the only real effect is that ambient is black.

This has a very minor effect, but it doesn’t solve the issue.

ToneMapFilter toneMapFilter = new ToneMapFilter(Vector3f.UNIT_XYZ.mult(4f));
fpp.addFilter(toneMapFilter);

Yes.

The values of the material are: Metallic: 0, Roughness: 1.
Adapting these values, I see the effect of the light probe.

The lights in the scene are:

  • AmbientLight (new ColorRGBA(0.3f, 0.3f, 0.3f, 1))
  • DirectionalLight (new ColorRGBA(1, 1, 1, 1))
  • LightProbe

Indeed, when disabling the lightprobe, this is also the behaviour I experience.

When I change the material to use Lighting.j3md instead of PBRLighting.j3md the issue is resolved…

        model.depthFirstTraversal(new SceneGraphVisitorAdapter() {
            @Override
            public void visit(Geometry geom) {
                Material material = geom.getMaterial();
                Material newMaterial = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
                newMaterial.setBoolean("UseMaterialColors", true);
                newMaterial.setColor("Ambient", ColorRGBA.White);
                newMaterial.setColor("Diffuse", ColorRGBA.White);
                newMaterial.setTexture("DiffuseMap", material.getTextureParam("BaseColorMap").getTextureValue());

                geom.setMaterial(newMaterial);
            }
        });

Is there some setting I’m missing in the PBR material? This is my first try at PBR, so I’m still figuring things out on the go…

Normally for me, PBR from Blender eevee matches pretty well with what JME shows. So it could be that your JME settings for the environment are just significantly different from Blender’s.

What do you mean by settings for the environment? The lights?

I created a small test case to reproduce:

public class TestCase extends SimpleApplication {

    public static void main(String[] args) {
        TestCase testCase = new TestCase();
        testCase.start();
    }

    public TestCase() {
        super(new StatsAppState(), new FlyCamAppState());

        setSettings(createSettings());

        setShowSettings(false);
    }

    @Override
    public void simpleInitApp() {
        DirectionalLight directionalLight = new DirectionalLight(Vector3f.UNIT_Z.negate(), ColorRGBA.White);
        AmbientLight ambientLight = new AmbientLight(new ColorRGBA(0.3f, 0.3f, 0.3f, 1));

        Spatial model = assetManager.loadModel("fighter.glb");
        rootNode.attachChild(model);

        rootNode.addLight(directionalLight);
        rootNode.addLight(ambientLight);
    }

    private AppSettings createSettings() {
        AppSettings settings = new AppSettings(true);
        settings.setRenderer(AppSettings.LWJGL_OPENGL32);
        settings.setGammaCorrection(true);
        settings.setResizable(true);
        settings.setSamples(4);
        settings.setResolution(1280, 800);
        settings.setBitsPerPixel(32);

        return settings;
    }
}

If you want I can upload the model somewhere.

edit: link to model: https://easyupload.io/btrzfm

Eevee in Blender has lots of setting. I don’t know much about them.

For me the biggest effect was picking a similar light probe for both Blender and JME.

Can you retry with removing DirectionalLight from scene and changing AmbientLight to (1, 1, 1, 1) and see the difference.

Yeah, interested to try it.

Thanks for the tip, I’ll dig a bit further into this. But I don’t really see this connected with the gamma correction setting. When I disable this, everything is working fine.

Then the model is completely black.

link to the model: https://easyupload.io/btrzfm

Something is definitely wrong then in your setup.

Check radius of light probe. Is it large enough?

Are you using JME 3.3?

Can you upload your model?

And also, have you set this?

// Configure the scene for PBR
renderManager.setPreferredLightMode(TechniqueDef.LightMode.SinglePassAndImageBased);

Reduce the directional lighting to something like 0.4. For me, ambient light never made any difference to PBR. The probe is the ambient for PBR.

I was referring to the testcase, this has only an ambient light and a directional light. No light probe…

Yes I tried it, but this also doesn’t have an effect. I’ll add it to the testcase for completeness.

TestCase:

public class TestCase extends SimpleApplication implements ActionListener {

    private Spatial model;

    public static void main(String[] args) {
        TestCase testCase = new TestCase();
        testCase.start();
    }

    public TestCase() {
        super(new StatsAppState(), new FlyCamAppState());

        setSettings(createSettings());

        setShowSettings(false);
    }

    @Override
    public void simpleInitApp() {
        renderManager.setPreferredLightMode(TechniqueDef.LightMode.SinglePassAndImageBased);
        
        DirectionalLight directionalLight = new DirectionalLight(Vector3f.UNIT_Z.negate(), new ColorRGBA(0.4f, 0.4f, 0.4f, 1));
        AmbientLight ambientLight = new AmbientLight(new ColorRGBA(0.3f, 0.3f, 0.3f, 1));

        model = assetManager.loadModel("fighter.glb");
        rootNode.attachChild(model);

        rootNode.addLight(directionalLight);
        rootNode.addLight(ambientLight);

        inputManager.addMapping("change-material", new KeyTrigger(KeyInput.KEY_SPACE));
        inputManager.addListener(this, "change-material");

        viewPort.setBackgroundColor(ColorRGBA.LightGray);
    }

    private AppSettings createSettings() {
        AppSettings settings = new AppSettings(true);
        settings.setRenderer(AppSettings.LWJGL_OPENGL32);
        settings.setGammaCorrection(true);
        settings.setResizable(true);
        settings.setSamples(4);
        settings.setResolution(1280, 800);
        settings.setBitsPerPixel(32);

        return settings;
    }

    @Override
    public void onAction(String name, boolean isPressed, float tpf) {
        if ("change-material".equals(name) && isPressed) {
            model.depthFirstTraversal(new SceneGraphVisitorAdapter() {
                @Override
                public void visit(Geometry geom) {
                    Material m = geom.getMaterial();

                    if (m.getTextureParam("BaseColorMap") != null) {
                        // PBR
                        Material material = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
                        material.setBoolean("UseMaterialColors", true);
                        material.setColor("Ambient", ColorRGBA.White);
                        material.setColor("Diffuse", ColorRGBA.White);
                        material.setTexture("DiffuseMap", m.getTextureParam("BaseColorMap").getTextureValue());
                        geom.setMaterial(material);
                    } else {
                        // Lighting
                        Material material = new Material(assetManager, "Common/MatDefs/Light/PBRLighting.j3md");
                        material.setFloat("Metallic", 0);
                        material.setFloat("Roughness", 1);
                        material.setColor("BaseColor", ColorRGBA.White);
                        material.setTexture("BaseColorMap", m.getTextureParam("DiffuseMap").getTextureValue());
                        geom.setMaterial(material);
                    }
                }
            });
        }
    }
}

It definitely should. Support for AmbientLight in PBRLighting added in 3.3.0-alpha2.

1 Like

Setting the directional light to 0.4f is indeed already better, but the model still has this ‘washed-out’ look. I guess by tweaking the light values and setting a light probe I can make it look better.

But I cannot help the feeling that something is wrong in the gamma correction calculation… When disabling this the PBR material and lighting material look correct and almost exactly the same. I remember having the same issues when the ColorSpace was not correctly set on a texture with gamma correction enabled. This gave exactly the same too bright / washed-out look.