I have a scene with some glass cabinets, and I’m trying to use MeshPhysicalMaterial
with envMap reflections generated from surrounding geometry when the scene loads.
It looks as though the uv/reflection vector isn’t being computed properly. Normals look fine with MeshNormalMaterial
… I’m replacing the geometry of the targeted meshes with BoxGeometry
the size & position of the bounding boxes of the original geometry, and explicitly calling computeVertexNormals()
etc for good measure, but I don’t think that’s making any difference.
The environment map is made with a CubeCamera
/ WebGLCubeRenderTarget
& PMREMGenerator.fromCubemap()
. I tried fromScene()
as well, which also doesn’t help.
You can see the work-in-progress here Shemza - Virtual Gallery
It’ll take a little while to load, and then you can use FPS controls to better see the glass cabinets in the room ahead of you when it starts. There’s some really nasty artefacts from z-fighting with some of the other geometry, but that’ll be taken care of at some point…
This is what I call for the relevant meshes (hopefully not mis-edited as I took out a few lines of dead code):
function setGlassMaterial(mesh: Mesh) {
const pmremGen = new THREE.PMREMGenerator(renderer);
pmremGen.compileCubemapShader();
const envMap = new THREE.WebGLCubeRenderTarget(1024, {
format: THREE.RGBAFormat,
type: THREE.HalfFloatType,
});
const mat = mesh.material = new MeshPhysicalMaterial({
transparent: true,
roughness: 0.02,
// thickness: 10,
transmission: 1,
reflectivity: 1,
metalness: 0.1,
ior: 1.44,
side: DoubleSide,
// envMap: envMap.texture,
});
(mesh.material as any).thickness = 10; //some issue with typescript
mesh.geometry.computeBoundingBox();
const box = mesh.geometry.boundingBox!;
mesh.geometry = new THREE.BoxGeometry(box.max.x - box.min.x, box.max.y - box.min.y, box.max.z - box.min.z);
mesh.geometry.computeVertexNormals();
mesh.geometry.computeTangents();
mesh.geometry.computeBoundingSphere();
//TODO: use Layers to hide things that intersect with the bounding box
const bSphere = mesh.geometry.boundingSphere!;
const cam = new THREE.CubeCamera(bSphere!.radius, 10000, envMap);
cam.position.copy(mesh.position);
const p = new THREE.Vector3();
p.copy(bSphere.center);
mesh.getWorldPosition(cam.position);
mesh.getWorldQuaternion(cam.quaternion);
cam.rotateY(Math.PI);
cam.position.add(p);
// consider using Layers to hide the mesh
// also want to hide things like books inside the glass
mesh.visible = false;
const oldRt = renderer.getRenderTarget();
renderer.setRenderTarget(envMap);
cam.update(renderer, scene);
renderer.setRenderTarget(oldRt);
mesh.visible = true;
scene.position.copy(cam.position);
scene.position.multiplyScalar(-1);
const pmrem = pmremGen.fromCubemap(envMap.texture);
// const pmrem = pmremGen.fromScene(scene, 0, bSphere!.radius, 10000);
envMap.dispose();
scene.position.set(0, 0, 0);
// pmrem.texture.mapping = THREE.CubeReflectionMapping;
pmrem.texture.mapping = THREE.CubeUVReflectionMapping;
mat.envMap = pmrem.texture;
mat.needsUpdate = true;
mesh.updateMatrixWorld();
// mesh.material = new THREE.MeshNormalMaterial();
}