I have an application that includes meshes rendered with MeshPhongMaterials. They work well with the full suite of lights available in three.js.
However, I want to combine them with imported GLB/GLTF models. In order to have the models lit, I believe I must use an environment map such as the following:
function _Environment() {
const env_scene = new THREE.Scene();
const roomMaterial = new THREE.MeshStandardMaterial( { side: THREE.BackSide } );
const room = new THREE.Mesh( new THREE.BoxGeometry(), roomMaterial );
room.position.set( 0, 0, 0 );
room.scale.set( 40, 40, 40 );
env_scene.add( room );
const env_alight = new THREE.AmbientLight(0xFFFFFF, .1);
env_scene.add(env_alight);
return env_scene;
}
function main() {
canvas = document.getElementById('c');
renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true});
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.outputEncoding = THREE.sRGBEncoding;
const aspect = 4/3; // the canvas default
camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(5, 0, 2);
camera.up.set(0,1,0);
camera.lookAt(new THREE.Vector3());
camera.updateProjectionMatrix()
const environment = new _Environment();
const pmremGenerator = new THREE.PMREMGenerator(renderer);
scene = new THREE.Scene();
scene.background = new THREE.Color(DefaultBackgroundColor);
scene.environment = pmremGenerator.fromScene(environment).texture;
dlight = new THREE.DirectionalLight(0xFFFFFF, .7);
dlight.position.set(5, 5, 10);
dlight.target.position.set(0, 0, 0);
scene.add(dlight);
scene.add(dlight.target);
alight = new THREE.AmbientLight(0xFFFFFF, .3);
scene.add(alight);
requestAnimationFrame(render);
}
However, it seems that the environment map causes the Phong materials to show up saturated and I cannot find a good combination of lights that work.
One can always convert everything to PBR, but am I missing something? Can Phong and PBR co-exist in a well lit, natural looking scene?