Does "ProgressiveLightMap" is supposed to work?

it seems to work only with the provided sample model — I’ve tried several other simple models (cubes, cones, cylinders) with UV unwrapping on both channel 0 and channel 1, but they always come out completely black.

The sample model can’t be imported into Blender to analyze it, and from what I found online there are only old discussions from users reporting the same issue, with no real solution ever given.

What really surprises me is that it’s included in the official Three.js release, even with its own documentation page https://threejs.org/docs/#ProgressiveLightMap (which doesn’t actually explain anything about how to prepare models to use it). So one would assume it should work properly, not just be some experimental feature that only works with one specific and mysterious model — making it basically unusable.

I hope someone can help me figure out whether it’s worth spending more time on this, or if it was accidentally included in Three.js by mistake!
Thanks!

It looks to me like the input meshes may require a second set of lightmap uvs as “uv1”. You can set this up in blender and export via gltf.
So you would have you main texture uvs the “uv” channel, then a second set for the lightmaps “uv1”
Does this sound like what you attempted?
You can probably set up the uv1s manually as a clone of “uv” at runtime.

1 Like

Also maybe need go to “UV Editing”-“Select”-“All”-“UV”-“Lightmap Pack”.

Thank-you @manthrax for your reply, but it’s just what I’ve done in on all my meshes in Blender, before to try to use them with ProgressiveLightMap in ThreeJS.
Please look at this picture for example:

As you can see the Suzanne model has its “uv” and “uv1” attributes (basically the same unwrap), but despite this with ProgressiveLightMap it look totally black:

Curiously if you look better on the Suzanne ear it seem to be some shading (but from nowhere, since it doesn’t react to light and it’s not showed on the debug texture)

Did you ever managed to get ProgressiveLightMap working ?

Thank-you @Chaser_Code for your reply, but I don’t think that lightmap packing can solve the issue, if ProgressiveLightMap don’t work.

Maybe I’m doing something wrong, but actually my opinion is that ProgressiveLightMap is just an experiment that incidentally has been included in ThreeJS

are you simply using the exact code from the official example ( three.js/examples/webgl_shadowmap_progressive.html at f265b19cceb299184bcc26653ad53452c4349e70 · mrdoob/three.js · GitHub ) and switching the model that is loaded?

there are two main important parts of the setup besides the secondary uvMap as @manthrax has suggested, progressiveSurfacemap.addObjectsToLightMap here…

making sure to push your lights to the lightMapObjects array lightmapObjects.push( dirLight ); and ensuring to also disable non mesh objects layers in the loaded object…

} else {

 child.layers.disableAll(); // Disable Rendering for this

}

and the second important part, progressiveSurfacemap.update in the render loop…

and the third thing to check would be the console for the following warning…

console.warn( 'THREE.ProgressiveLightMap: All lightmap objects need normals.' ); continue;

Thank-you @Lawrence3DPK yes, I’m actually using the provided example script from three.js webgl - progressive lightmap accumulation
(I’ve just created a new script from this one because I’m using Vite) and I’m just switching from the provided example model and my models.

And it doesn’t work with any of my models (just with the provided one)

This is my example Suzanne model for test
monkey3.glb (84.0 KB)

I don’t know if someone ever managed to get ProgressiveLightMap working, but at this point I’m really curious about it

Problem in geometry.attrubutes.uv and maybe geometry.attrubutes.normal, geometry.attrubutes.position.

Problems in the generated .glb file from Blender? or in the ProgressiveLightMap.js script?

I’ve checked my glb models with https://gltf.report/ and it doesn’t report any issue, unlike the provided example model ShadowmappableMesh.glb that has a lot of problems…

The problem is with constructing triangles. In Blender, it’s clockwise, but we need it counterclockwise for ProgressiveLightMap.js. No need for second uv1, just default uv.
Just need to replace 2 and 3 items for each triangle index in object.geometry.index.array
Was: 0,1,3,0,3,2.
Now: 0,3,1,0,2,3.

let max_value=object.geometry.index.array.length;
let item=object.geometry.index.array;
for(let n=0;n<max_value;n+=3){
let temp_2=item[n+1];
let temp_3=item[n+2];
item[n+1]=temp_3;
item[n+2]=temp_2;
}

3 Likes

Thank-you @Chaser_Code !
Indeed now it’s “almost” working, because the normals are flipped…
Please look at the picture

I really don’t know why, because I’ve just copied and pasted your code

const manager = new THREE.LoadingManager(loadModel);
    const loader = new GLTFLoader(manager);
    loader.load('models/monkey3.glb', function (obj) {

        object = obj.scene.children[0];

        let max_value = object.geometry.index.array.length;
        let item = object.geometry.index.array;
        for (let n = 0; n < max_value; n += 3) {
            let temp_2 = item[n + 1];
            let temp_3 = item[n + 2];
            item[n + 1] = temp_3;
            item[n + 2] = temp_2;
        }
    });

Did you change something else on the monkey model? Maybe in Blender?
Many thanks!!!

Try this and compare all and material:
webgl_shadowmap_progressive_2.html (8.2 KB)

Many thanks!!! :grinning_face:

One very last question, do you know if is mandatory for ProgressiveLightMap to have so huge models? For example I had to scale the monkey to 100m x 60m x70m (!!!) to get it showing proper lightmap…
I’ve tried to decrease the plane and the monkey (as other objects) to real world size, but it seem that both shadows and lightmap don’t come from the right position anymore…

Test with real world size - light radius 0 - it’s ok

Test with real world size - light radius 20 - shadows and lightmap get wrong light position

Try this
webgl_shadowmap_progressive_2.html (8.2 KB)

2 Likes

Many thanks, but it seem to me that has the same problem as in my test (light from wrong direction)…

Maybe you uploaded the wrong html ?

Increase light position in 100 times


or put *0.01 if its right solution

2 Likes

Hello @Chaser_Code your function to fix the wrong geometry from Blender seem to work only with a single mesh inside the imported GLTF…
I’ve moved your function inside “loadModel()…” in this way:

loader.load('models/twoMonkeys.glb', function (obj) {

object = obj.scene // let's pass all the children

    });
function loadModel() {

        console.log("loadModel")

        console.log("object:", object)


        object.traverse(function (child) {

            if (child.isMesh) {

                console.log("child:", child)


                // Fix wrong geometry from Blender

                let max_value = child.geometry.index.array.length;

                let item = child.geometry.index.array;

                for (let n = 0; n < max_value; n += 3) {

                    let temp_2 = item[n + 1];

                    let temp_3 = item[n + 2];

                    item[n + 1] = temp_3;

                    item[n + 2] = temp_2;

                }


                // child.name = 'Loaded Mesh';

                child.castShadow = true;

                child.receiveShadow = true;

                // This adds the model to the lightmap

                lightmapObjects.push(child);

            } else {

                child.layers.disableAll(); // Disable Rendering for this

            }

        });

        progressiveSurfacemap.addObjectsToLightMap(lightmapObjects);

        scene.add(object);
        …

so to iterate for each child, but it show black again (twoMonkeys.glb)

But, the same code work if there’s only one mesh inside the imported file (oneMonkey.glb)

Am I doing something wrong?
Really many thanks!!

twoMonkeys.glb (130.6 KB)

oneMonkey.glb (83.8 KB)

— EDIT —

It’s really weird, because it seem to happen ONLY on meshes of the same “type” (box, ring, suzanne, etc.)

Maybe blender check objects indexes and if they are same, then save only one index for two objects for optimization. Its like same objects share one index. And when we change index once, its ok, if twice, then it became origin index values and cant see changes. I just put cloning index.
Add child.geometry.index=child.geometry.index.clone();
Before let max_value=child.geometry.index.array.length;

1 Like

I’m really sorry for bothering you again with this, I really appreciate all your help

Your suggestion about inverting the triangles (the clockwise/counterclockwise issue) worked perfectly for models coming straight from Blender. But now I’ve run into a weird new problem, when i modify them somehow in ThreeJS and I export-import again in ThreeJS it doesn’t work anymore.

My workflow is:

1 - Export model from Blender as GLB

2 - Import into Three.js and use XAtlas to generate a UV unwrap (creates a new uv1 channel)

3 - Export the unwrapped model using GLTFExporter

4 - Import this new GLB in Blender, just to check that everyting is correct (“uv” is the original one, new “uv1” is definitely there)

5 - Import this new GLB in ThreeJS and use ProgressiveLightMapwith with its new uv1.

The model shows up completely black in ProgressiveLightMap.

It’s really weird because It doesn’t matter the uv (“uv” or “uv1”) used, and your triangle inversion fix makes absolutely no difference - it’s totally black whether I use it or not.. :downcast_face_with_sweat:

Unfortunately it seem that I can’t upload any file (???) to this post, so here the link to the unwrapped model that doesn’t work

http://issimissimo.com/temp/monkey_unwrap_%20fromXatlas_and_exported_with_GLTFExporter.glb

I Thank you so much again for your patience and expertise, I really don’t know how to check for geometry issues

child.material.metalness=0;
child.material.side=1;
child.material.metalness=0;
child.material.side=1;
child.geometry.index=child.geometry.index.clone();
let max_value=child.geometry.index.array.length;
let item=child.geometry.index.array;
for(let n=0;n<max_value;n+=3){
let temp_2=item[n+1];
let temp_3=item[n+2];
item[n+1]=temp_3;
item[n+2]=temp_2;
}
1 Like