Incorrect PBR rendering

Hello, I modeled and textured this big rock in Blender and Substance Painter.

I exported it in gltf format in two different ways:

  • model only, with textures applied procedurally using Common/MatDefs/Light/PBRLighting.j3md
    EDIT code:
 val material = Material(assetManager, "Common/MatDefs/Light/PBRLighting.j3md")
        material.setTexture("BaseColorMap", assetManager.loadTexture(basepath + "_Base_Color.png"))
        material.setTexture("MetallicMap", assetManager.loadTexture(basepath + "_Metallic.png"))
        material.setTexture("RoughnessMap", assetManager.loadTexture(basepath + "_Roughness.png"))
        material.setTexture("NormalMap", assetManager.loadTexture(basepath + "_Normal_OpenGL.png"))
      
  • model and textures bundled together in a single file by Blender.

My problems with these renderings are

  • The first one has some UV mapping issues
  • both of them appear very pale, blanched out, and the normals seem to be rendered with very high contrast.

What am I doing wrong?

Thanks!

With the coded material, I suspect all your textures are upside down because jme automatically flips textures on the Y axis when it loads them. To fix that, load the texture with a texture key that disables flipping.

TextureKey key = new TextureKey("myTex.png");
key.setFlipY(false);
Texture t = assetManager.loadTexture(key);
1 Like

Also, we can’t see anything else about your scene setup or how you load the model.

For example, what lights do you use? Did you generate tangents for the model?

1 Like

Hi pspeed, thanks for the reply.
here’s the light configuration

 val sunColor = ColorRGBA(1f, .855f, .558f, 1f)
        val sun = DirectionalLight(Vector3f(-1f, -1f, -1f), sunColor.mult(3f))
        worldSpatialRoot.addLight(sun)

        val ambientColor = ColorRGBA(0.51f, 0.6f, 1f, 1f)

        val ambient: Light = AmbientLight(ambientColor.mult(0.2f))
        worldSpatialRoot.addLight(ambient)

        /*
        val probeHolder: Spatial = app.assetManager.loadModel("Models/defaultProbe.j3o")
        val probe = probeHolder.localLightList[0] as LightProbe
        probeHolder.removeLight(probe)
        probe.position = Vector3f.ZERO
        worldSpatialRoot.addLight(probe)
*/
        addSkyBox()

        val fpp = FilterPostProcessor(assetManager)
        val fogFilter = FogFilter().apply {
            fogDensity = .2f
            fogDistance = 100f
            //fogColor = ColorRGBA()
        }

        val dlsf = DirectionalLightShadowFilter(assetManager, shadowMapSize, 3)
        dlsf.light = sun
        dlsf.lambda = 0.55f
        dlsf.shadowIntensity = 0.8f
        dlsf.edgeFilteringMode = EdgeFilteringMode.PCF4 //SLOW might tweak later idk
        dlsf.isEnabled = true

        fpp.addFilter(dlsf)
        // fpp.addFilter(SSAOFilter(2.9299974f, 100f, 2f, 0.091000035f))

        fpp.addFilter(fogFilter)
        val fxaaFilter = FXAAFilter() //SLOW might tweak later idk
        fxaaFilter.reduceMul = .01f
        fpp.addFilter(fxaaFilter)

I also included the filters applied for the screenshots I posted. the commented adding a probe was a try, but It only seems to affect ambient light.


I post a screen with white light and no ambient (it shouldn’t have any effect without probe, but still)
as you can see the roughness seems to be still different as there seems to be like a white layer on top of the texture.
on a side note, flipping the texture keys fixed the first issue, thanks!

1 Like

update:
on a closer look to the fragment shader, I noticed that, in case of non glossy pipeline, the following code is compiled:

        float specular = 0.5;
        float nonMetalSpec = 0.08 * specular;
        vec4 specularColor = (nonMetalSpec - nonMetalSpec * Metallic) + albedo * Metallic;
        vec4 diffuseColor = albedo - albedo * Metallic;
        vec3 fZero = vec3(specular);

I am presuming that the pale layer on top of the diffuse is that 0.5. in order to change this I can override the PBRLighting shader and move the m_Specular definition out of the #ifdef SPECGLOSSPIPELINE block on line 65. this way it would be possible to inject it thru the j3md and this should solve it for me.

Does anybody think this is correct?

I don’t think the non-specularGlossiness pipeline should require adjusting the specular color, as that is determined by the metallic value and albedo color of the material.

Is it possible that your MatDef in JME has a different Roughnes or Metallic value than it does in Blender and SubstancePainter?

Typically, that faded gray color will be the result of too high of a roughness or possibly too low/high of a metallic value. Usually if you use the engine to convert from gltf > j3o, it will make sure all of those matParams are set correctly.

But in your case, if you are creating the material with code, it is possible that your float values for roughness or metallic are not the same as they are in blender (even if you are using a MetallicMap and RoughnessMap, the final values will still be multiplied by the float values for Roughness and Metallic)

The best way to troubleshoot the model would probably be to use the SDK, and open up both the model (in the scene composer) and the model’s material (in the material editor) and then you can inspect all of the values, and see if tweaking the roughness or metallic values changes anything.

It also looks like your lights are not a fully white light (1.0f, 1.0f, 1.0f, 1.0f). I would suggest always using a full white light for both the directionalLight and ambientLight (with a lightProbe) and no filters to ensure the model renders correctly, and then you can adjust the lighting after ensuring it is rendering correctly.

Hello! AFAIK principled bsdf shader doesn’t have a secondary Roughness parameter, it just either has one roughness value for the whole material or some kind of function for each point. Same thing for Substance Painter but I’m not sure of the latter.

In the picture in the first post you can see that aside from the flipped UV textures both coded and the material read from gltf have the same white layer.

Yeah I guess so, but I couldn’t manage to make it run correctly and I am more comfortable with live debugging and coding.

check the picture in the third (?) post.

anyway, I did a try and actually when manually overriding the shader to have a specular base value of 0.2 instead of 0.5 it is easily fixed. Nevertheless I will try to fiddle with the official material by adjusting the metallicity.
I think that Metallicity is set to a higher value by default in the SDK, and that’s why usually nobody notices this problem.

Unless I am mistaken, I read your 3rd post as you saying you were only using a white DirectionalLight (and not a lightprobe or ambientLight):

Is that correct?

And in your original post where you do have a light probe (albeit commented out) the ambient light’s color appears to be set to a non-white value, and is multiplied by 0.2, which will be effectively making the ambient color a dull gray, and then that value is used to scale down the lightProbe. Which is likely the reason you have a dull gray lighting on your model that looks almost the same as if you have no lightProbe at all.

For PBR to render correctly, you will always need at least a light probe (with a valid radius) and a directional light.

So if you are indeed using a LightProbe in combination with a white DirectionalLight and white AmbientLight (or no ambientLight; ambientLight is the only optional light for PBR) and the issue still persists, then we might need a copy of your model in gltf format to investigate further.

yaRnMcDonuts, thanks a lot and sorry if I created confusion. In order to make sure we are all on the same point I am posting two more screen shots. for both of them the setup is

  • one directional light , ColorRGBA.White.
  • one ambient light, ColorRGBA.White (mutliplied by 0.2)
  • one light probe.
  • DirectionalLightShadowFilter with shadow intensity to .8 (also, how do I make sure that cast shadows are darker than other shadows? )
  • I also removed any fog and other post processing.
    I am using different models but they all have the same material.
    in the first picture I am using the good old Common/MatDefs/Light/PBRLighting.j3md
    in the second picture I used my override, whose only difference is
float specular = 0.1;

instead of

float specular = 0.5;

on line 203.

1 Like

Does it look any different if you remove this multiplication?

The ambient light is used for scaling the final color of the lightProbes in the scene. So it is typically only multiplied by values <1.0 to simulate things like night-time.

Stressing again for extra underlining.

If you have a normal PBR scene you should NOT have an AmbientLight.

Allowing AmbientLight to scale the light probe is a USEFUL HACK for making your scene INCORRECT for very important but very specific reasons (as stated above).

Edit: put another way…

It’s possible… even probable… that your issue has nothing to do with that hacky ambient light that you’ve added… but most folks aren’t going to look deeper while your scene is hacked with an ambient light that shouldn’t be there.

2 Likes

Alright, alright. I’m going to delete the ambient light :smiley:

I decided to rebuild the modeling pipeline to make sure that there are no other problems before getting into JME, and this will take a while.

On a side note, I confess I had a hard time finding information on how to use materials in JME. Is there any guide floating around perhaps?

thank you for all your support so far!