Using HDR lightmap result in weird color banding and lumiance range

I was trying to use HDR format lightmap in my ArchViz scene.
However, I got some really weird color banding. seems I did not correctly interpolate HDR format in my code.
Here is what I got in THREE

and here is what I want to get(rendered in blender)

Here is how I load HDR lightmaps

function loadMesh(){
					
					var pmremGenerator = new THREE.PMREMGenerator(renderer);
					// var rgbeLoader = new THREE.RGBELoader().setDataType(THREE.UnsignedByteType).setPath('mesh/test/test_HDR/lightmap/');
					var rgbeLoader = new RGBELoader()
						.setDataType( THREE.UnsignedByteType )
						.setPath( 'mesh/test/test_HDR/lightmap/' );

					// gltf
					// var loader = new GLTFLoader().setPath( 'mesh/test/' );
					// loader.load( 'test.gltf', function ( gltf ) {


					// glb
					var loader = new GLTFLoader().setPath( 'mesh/test/test_HDR/' );
					loader.load( 'test.glb', function ( gltf ) {

						var i = 0;

					// 	var urls = [
					// 	'./textures/cube/kitchen/cubeMap/b.png',
					// 	'./textures/cube/kitchen/cubeMap/d.png',
					// 	'./textures/cube/kitchen/cubeMap/f.png',	
					// 	'./textures/cube/kitchen/cubeMap/l.png',
					// 	'./textures/cube/kitchen/cubeMap/r.png',
					// 	'./textures/cube/kitchen/cubeMap/u.png',
					// 	];
					// var cubeLoader = new THREE.CubeTextureLoader();
					// var cubeMap = cubeLoader.load(urls);	

						gltf.scene.traverse( function ( child ) {
							if ( child.isMesh ) {
								var tempName = child.name;

								// ----------------------------------
								// var tempLightmap = new THREE.TextureLoader().load('mesh/test/test_HDR/lightmap/' + tempName + '_baked.png');


								// ------------------------------------
								var tempLightmap = rgbeLoader.load(tempName + '_baked.hdr');
								console.log(tempLightmap);


								tempLightmap.flipY = false;
								tempLightmap.wrapS = THREE.RepeatWrapping;
								child.material.lightMap = tempLightmap;
								child.material.lightMapIntensity = 1;
								child.material.needsUpdate = true;
								// child.material.map = null;

								
								//setup EnvMap----------------------------------------------------------------------------------------------
								child.material.envMap = hdrCubeMap;
								//change EnvMap intensity
								child.material.envMapIntensity = 1;

								// check THREEJS Version
								// console.log('THREEJS version: ' + THREE.REVISION);
								child.material.flatShading = true;
								console.log(i + "::" + child.name);
								console.log(child.material);
								console.log(child.geometry);
								meshObject.set(child.name, child);
								
								// child.material = new THREE.MeshStandardMaterial();
								// child.material.lightMap = tempLightmap;
							
								//child.material.aoMap = tempLightmap;
								//child.material.aoMapIntensity  = 2;
								//debug single mesh
								// if(child.name == 'neiqiang')
								// 	child.material.roughness = .8;
									// child.material.visible = true;
									
								// else
								// {
									// child.material.visible = false;
								// }


								
								i++;
							}
						} );
						
						scene.add( gltf.scene );
						changeMaterials();
						// updateCubeMap();
						render();
						
					} );

				}
1 Like

Do you mind sharing the HDR file in this thread?

sure. no problem.
but i test my HDR image and i am sure there is nothing wrong with my HDR image. i also tried HDR image from examples. also had this problem.
i will upload the asset tomorrow since my pc is not at hand.
Thanks for helping!

I tried a little abit today. and I am not sure why the picture frame works fine, it display the HDR lightmap correctly. there is nothing different between all these models.
i have attached the .hdr lightmap and the model(glb file).


wallz0_baked.hdr (657.7 KB) test.glb (1.6 MB)

I figured out the problem, the reason is I had some problem in my code.
for anyone who encounter the same problem, the reason is you did not correctly interporlate the HDR file in code.
here is how to correctly load HDR with RGBE encoding.

var hdrLightmap = rgbeLoader.load(' xxx.hdr ', function(texture, textureData){

	texture.flipY = false;
	child.material.lightMap = texture;
	//child.material.lightMapIntensity = 1;
	//child.material.needsUpdate = true;


});
1 Like

Im struggling with the same problem, any chance I could see your code/project

Did you use the correct image loader?
if you are using HDR image, make sure you are using RGBE loader.
btw, can you share you result and code so that maybe we could help.

1 Like
    import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
    import * as THREE from "../vendor/three";

    export function addLightMap(scene, renderer) {

      var pmremGenerator = new THREE.PMREMGenerator(renderer);

      scene.traverse(function (object) {

        if (object.isMesh) {

          var name = object.name.toString().replace(/_/g, ".") + "_baked.hdr";

          const texture = new RGBELoader()

            .setDataType(THREE.UnsignedByteType)

            .load("./assets/img/hdr/" + name);

          object.geometry.attributes.uv2 = object.geometry.attributes.uv;

          object.material.side = 2;

          object.material.lightMap = texture;

        }

      });

    }

The following is what it looks like, am I using the wrong Light mapping files.
Any recommendations on how I can bake light mapping?

Live version My first three.js app

^^ you will notice 74 errors (404), there’s a total of 167 light maps the wall being one that is working

below are HDR examples

wall.1_baked.hdr (95.2 KB) wall.1_filtered.hdr (92.8 KB) wall.1_denoised.hdr (101.3 KB) Wall.Art.Classical.Plane_denoised.hdr (38.9 KB) wallSide2_filtered.hdr (20.1 KB) wallSide1_filtered.hdr (54.8 KB) wallSide2_denoised.hdr (24.9 KB) wallSide1_denoised.hdr (74.5 KB) wallSide2_baked.hdr (29.9 KB) wallSide1_baked.hdr (116.2 KB) Wall.Art.Classical.Plane_filtered.hdr (34.8 KB)

take a look at this example below. it has the correct way to call RGBE loader.
btw, the lightmap should be automatically assigned to second set of UV.
i would also suggest you to double check if you correctly set up all the UV channel.

link: three.js/RGBELoader.js at master · mrdoob/three.js (github.com)

thats just the RGBELoader source.

For anyone looking at this problem and since threejs devs always abandon threads half way (leaving devs to fend for themselves in this maze), this is how you do it

const updateLightmap = (mat, lmap, flipY, config) =>{
        lmap.flipY = flipY; // true / false
        mat.lightMap = lmap; // texture
        mat.lightMapIntensity = config?.intensity || 1;
        mat.needsUpdate = true;
}
  rgbeloader.load(`lightmap.hdr`, ( texture =>{
        updateLightmap(scn.material,  texture, false, {intensity: 1});
   }));

that should work