[SOLVED] Why does my PBR material appear grey in game?

I am playing around with PBR materials and I cant get them to work correctly. When I create a material using PBR the model appears gray in game. Any ideas on why I’m not getting the same result?

val floorMaterial = Material(assetManager, "Common/MatDefs/Light/PBRLighting.j3md")
floorMaterial.setTexture("BaseColorMap", assetManager.loadTexture("Textures/Floor_Diffuse.png"))
floorMaterial.setTexture("NormalMap", assetManager.loadTexture("Textures/Floor_Normal.png"))
floorMaterial.setTexture("SpecularMap", assetManager.loadTexture("Textures/Floor_Specular.png"))
val sun = DirectionalLight()
sun.color = ColorRGBA.White.mult(1.3f)
sun.direction = Vector3f(-.5f, -.5f, -.5f).normalizeLocal()
main.rootNode.addLight(sun)
val lightProbe = LightProbe()
lightProbe.position = Vector3f(0f, 10f, 0f)
addLight(lightProbe)

For comparison when I use regular lighting this is the result

val floorMaterial = Material(assetManager, "Common/MatDefs/Light/Lighting.j3md")
floorMaterial.setTexture("DiffuseMap", assetManager.loadTexture("Textures/Floor_Diffuse.png"))
floorMaterial.setTexture("NormalMap", assetManager.loadTexture("Textures/Floor_Normal.png"))
val sun = DirectionalLight()
sun.color = ColorRGBA.White.mult(1.3f)
sun.direction = Vector3f(-.5f, -.5f, -.5f).normalizeLocal()
main.rootNode.addLight(sun)
val lightProbe = LightProbe()
lightProbe.position = Vector3f(0f, 10f, 0f)
addLight(lightProbe)

This appears to be creating a new light probe with no pre-generated environment map, and from my experience will not work.

You will need to use a probe that has been properly prepared. You can either generate it yourself using the static methods in LightProbeFactory:
https://javadoc.jmonkeyengine.org/v3.3.0-beta1/com/jme3/environment/LightProbeFactory.html

Or much easier you can use a pre-saved light probe that is loaded from .j3o format, such as this one here titled “defaultProbe.j3o”:

1 Like

Thanks for the info. I would rather use the factory but when I call makeProbe and pass in stateManager.getState(EnvironmentCamera::class.java) it throws a NullPointerException here at getApplication inside EnvironmentCamera:

 public void snapshot(final Spatial scene, final JobProgressListener<TextureCubeMap> done) {
    getApplication().enqueue(new Callable<Void>() {

        @Override
        public Void call() throws Exception {
            SnapshotJob job = new SnapshotJob(done, scene);
            jobs.add(job);
            return null;
        }
    });
}

Here is my updated light probe I have to attach EnvironmentCamera as it is not initially added by the engine:

stateManager.attach(EnvironmentCamera(256, Vector3f(0f, 10f, 0f)))
    val lightProbe = LightProbeFactory.makeProbe(
        stateManager.getState(EnvironmentCamera::class.java),
        this,
        EnvMapUtils.GenerationType.Fast,
        null
    )
    lightProbe.position = Vector3f(0f, 10f, 0f)
    addLight(lightProbe)

Please note you can pre-bake light probe and save it / load it later.

or you can just generate and save one in SDK so later you just load j3o file with light probe.

This code what you do is good if you want dynamically change envmap of light probe, or dynamically generate light probes from environment.

same as in other topic, sending you video:

If that’s the line where the NPE happens then the outer app state has not been initialized yet. You are calling it too soon or you haven’t attached it yet.

And I guess we see that’s true here.

I don’t know what the normal pattern for runtime probe generation is but that can’t work. (I use pregenerated probes all the time so I’ve never dealt with this personally.) I thought there was a jme-example maybe.

I was unsure about using one that was pre-generated already. Will the lighting and shadows be accurate if it was generated using a different Scene?

The shadows will still be accurate.

The indirect lighting may not be accurate, depending on your scene. That probe I linked has a green, foresty environment map, so it may look good in outdoors scenes, but would appear noticeably inaccurate in a gray/blue spaceship scene.

Any inaccuracies between the light probe and the scene will be most apparent in shiny areas, where the inderect lighting is clear and is closer to a full reflection (high glossiness, or low roughness values in pbr material).

So using a pre-generated probe like the one i linked or from someone else is likely the best option for testing, and also for early on in the scene development process when your own scene is not finished enough to generate your own light probe.

Once your scene is big / finished enough to generate your own light probes, you may still need to re-generate new ones when you make major updates to your scene. Like if you add a big red bridge into a city scene that was previously predominantly gray, then you’l definitely want to generate a new light probe in order to capture the redness of that bridge into a new light probe’s environment map to maintain accurate indirect lighting.

1 Like

A lot of times it looks fine enough, too… depending on how reflective your stuff is supposed to be.

Here are a bunch of pregenerated probes that I use for various things:

And this is the thumbnails of what they look like:

“Studio” is one I use for generic indoor scenes:

1 Like

Thanks for the assistance. I was able to finally get it working with a prebuilt light cube and increasing the light intensity a bit. I added a light cube but it was still gray like that. I then made the lights brighter and it looks very good now.

1 Like

I did get it working but it appears the 4k textures I’m using, I can only see about 1/4 of the texture on the model. How do I get the texture to scale to fit the model. I tried texture modes MirroredRepeat, EdgeClamp and Repeat. None of which worked. The rest I didnt try as they are depreciated.

First we were talking about light probes and now we seem to be talking about the texture on the model. Unless you are still talking about light probes and then I’m confused.

If it’s the texture on the model then it sounds like your texture coordinates are messed up. Given we have 0 additional information to go on that’s probably the best answer we can give. (No code, no information about the model, etc.)