JamesTKhan/Mundus

Highly reflective objects using default cubemaps

Opened this issue · 1 comments

Describe the bug
When gdx-gltf was added in, environmental maps were not really fleshed out. Mundus is using gdx-gltf's IBLBuilder.createOutdoor() method and this creates a basic outdoor area for environmental diffuse/specular maps which does not match the Mundus scenes environment / skybox at all.

Not sure what the solution will be yet but this will require some refactoring. More research is needed find out if we can generate these textures based on skybox ( I doubt it ) or if we need the user to provide them.

Related to: #236

Docs on gdx-gltf
https://github.com/mgsx-dev/gdx-gltf/blob/master/docs/IBL.md

Code within Mundus:

public void initPBR() {
    IBLBuilder iblBuilder = IBLBuilder.createOutdoor(dirLight);
    Cubemap diffuseCubemap = iblBuilder.buildIrradianceMap(512);
    Cubemap specularCubemap = iblBuilder.buildRadianceMap(10);
    iblBuilder.dispose();

    PBRTextureAttribute tex = (PBRTextureAttribute) environment.get(PBRTextureAttribute.BRDFLUTTexture);
    if (tex == null) {
        Texture brdfLUT = new Texture(Gdx.files.classpath("net/mgsx/gltf/shaders/brdfLUT.png"));
        environment.set(new PBRTextureAttribute(PBRTextureAttribute.BRDFLUTTexture, brdfLUT));
    }

    PBRCubemapAttribute specularEnv = (PBRCubemapAttribute) environment.get(PBRCubemapAttribute.SpecularEnv);
    if (specularEnv != null) {
        specularEnv.textureDescription.texture.dispose();
        specularEnv.textureDescription.texture = specularCubemap;
    } else {
        environment.set(PBRCubemapAttribute.createSpecularEnv(specularCubemap));
    }

    PBRCubemapAttribute diffuseEnv = (PBRCubemapAttribute) environment.get(PBRCubemapAttribute.DiffuseEnv);
    if (diffuseEnv != null) {
        diffuseEnv.textureDescription.texture.dispose();
        diffuseEnv.textureDescription.texture = diffuseCubemap;
    } else {
        environment.set(PBRCubemapAttribute.createDiffuseEnv(diffuseCubemap));
    }
}

To Reproduce
Steps to reproduce the behavior:

  1. Edit a models material make it fully metallic and low roughness.

Screenshots
On left you can see how it looks in a vanilla gdx-gltf app, on right with a metallic cube you can see it in Mundus as well, not matching the scene skybox at all
image

So there are a few work arounds.

1: is to use IBLBuilder iblBuilder = IBLBuilder.createIndoor(dirLight); but its produces a slightly darker rendering.

2: The other is to modify your own IBLBuilder based on the default outdoor (color settings might still need to be tweaked)... the goal is to make sure you do not have major contrast between sky and ground colors:

    public static IBLBuilder createCustom(DirectionalLight sun) {
        IBLBuilder ibl = IBLBuilder.createOutdoor(sun);

        Color tint = new Color(1f, .9f, .8f, 1).mul(.7f);

        ibl.nearGroundColor.set(tint).mul(.7f);
        ibl.farGroundColor.set(tint);
        ibl.farSkyColor.set(tint);
        ibl.nearSkyColor.set(tint).mul(2f);

        IBLBuilder.Light light = new IBLBuilder.Light();
        light.direction.set(sun.direction).nor();
        light.color.set(1f, .5f, 0f, 1f).mul(.5f);
        light.exponent = 3f;
        ibl.lights.add(light);

        return ibl;
    }

3: the last option which produces the best results is to use IBLComposer in gdx-gltf to produce the cubemaps but Mundus now needs a way to import and add the produced assets (enviromentCubemap, diffuseCubemap, specularCubemap).