google / filament

Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WebGL2
https://google.github.io/filament/
Apache License 2.0
17.82k stars 1.89k forks source link

Sharp specular reflections on a rough object when using IBL #4668

Closed rawnsley closed 2 years ago

rawnsley commented 3 years ago

This is a little subjective, but the reflected light from an IBL on a 100% rough PBR material feels off. It also differs significantly from an equivalent three.js render.

Here is the filament render on Android using the gltf-viewer sample and the Venice HDR IBL device-2021-09-23-135021 Here is the equivalent in glTF Viewer using three.js

Screenshot 2021-09-23 at 13 51 25

The sample model has 100% roughness and is non-metallic, but the filament render definitely looks shiny. Other objects with 50% roughness are almost as shiny as those with 0% and the effect is particularly pronounced on HDR images with small bright points of light.

My guess is that there's something wrong with the IBL cubemap, either the initial generation or the eventual roughness-based selection, none of which I understand very well. I was trying to investigate this assumption, but I got stuck working out how to write the various IBL cubemaps out as bitmaps so I could look at them.

romainguy commented 3 years ago

Our rendering is correct:

Screen Shot 2021-09-23 at 8 34 42 AM

You can see automated comparison between Filament and other glTF renderers. Aside from specific (known) differences with some extensions, they all compare roughly the same: https://modelviewer.dev/fidelity/

It seems like you are not generating/loading your IBL properly. The easiest way to properly load an IBL is to use cmgen -f ktx -x path/to/output envmap.hdr and then to use KTXLoader.createIndirectLight(). Example:

    private fun createIndirectLight() {
        val engine = modelViewer.engine
        val scene = modelViewer.scene
        val ibl = "default_env"
        readCompressedAsset("envs/$ibl/${ibl}_ibl.ktx").let {
            scene.indirectLight = KTXLoader.createIndirectLight(engine, it)
            scene.indirectLight!!.intensity = 30_000.0f
            viewerContent.indirectLight = modelViewer.scene.indirectLight
        }
        readCompressedAsset("envs/$ibl/${ibl}_skybox.ktx").let {
            scene.skybox = KTXLoader.createSkybox(engine, it)
        }
    }
rawnsley commented 3 years ago

@romainguy That comparison site is super useful, but my screenshot is straight from the sample-gltf-viewer not my own code. It uses an IBLPrefilterContext to generate the IBL reflections object at runtime rather than cmgen.

romainguy commented 3 years ago

It looks fine there as well: Screenshot_1632412432

rawnsley commented 3 years ago

Oh. Perhaps it is device specific? I'm using a Pocophone F1 and a Snapdragon XR1 based VR headset and I get the same issue on both I think. I'll do some more testing to try and narrow it down.

Is there any easy way to dump the cubemap textures that IBLPrefilterContext spits out? It might help debugging.

romainguy commented 3 years ago

You could try and dump the textures but they are in R11G11B10F format, so you won't be able to look at them easily. The best way to inspect them is to use a GL debugger like AGI or vendor tools like Adreno/Snapdragon Profiler.

rawnsley commented 2 years ago

Apologies for bringing this one back after so long. I can't find a single hardware device where this works like it does in the emulator. Is anyone able to confirm it working on a real device?

In case it isn't clear from the screenshots, the specular component is too sharp and the diffuse component has a much more defined highlight than the reference renders.

This is the reference model roughness.glb.zip. It's non-metallic spheres with roughness varying from 0% to 100%. The background IBL is from three.js, but I see the same thing with other HDRIs, particularly when they have very bright elements like noonday sun.

glTF Viewer (for reference)

glTFViewer-Web

Emulator

Emulator

Qualcomm XR1 (Ardeno GPU)

QualcommXR1-Ardeno

Samsung S6 (Mali-T760MP8)

SamsungS6-Exynos

Generic RK3399 Tablet (Mali-T860MP4)

RK3399-Mali

romainguy commented 2 years ago

Looks fine with the built-in IBL:

device-2021-12-07-091126

The issue only shows up (Pixel 6) when prefiltering an IBL at runtime:

device-2021-12-07-091350

Looks like it's not a rendering bug but either a bug in libibl or how gltf_viewer uses it.

romainguy commented 2 years ago

Offline generation looks fine (desktop render):

Screen Shot 2021-12-07 at 9 37 53 AM
pixelflinger commented 2 years ago

Thank you for reopening this, we caught a bunch of problems on mobile.