How to fix rendering from a reflector?

Hello everyone, hope you are having a great day. I am working with an artist doing a web integration of his work in WebGL. To be honest, This is the first time I’m using three.js, but I think I can do some of the things here.

The thing is, I want to replicate a mirror effect with one of his pieces. It consist on mirror circles in the X, Y and Z planes. Each of them have a CYMK paint. So, it depends of your POV to see how the colors adding can create different ones. For example Cyan and Yellow create a green and so on.

I have tried with cubemaps, but I found out the camera sees nearby objects so big, it kind of loose the main point of the piece.

I’m now working with Reflectors, they work ok but when using a skybox the render goes glitchy in the mirror. Any idea of the reason this happens? Recently found out it works good with MeshBasicMaterial but not with MeshPhongMaterial.

Code:

import * as THREE from './three/build/three.module.js';
import { OrbitControls } from './three/examples/jsm/controls/OrbitControls.js';
import { RGBELoader } from './three/examples/jsm/loaders/RGBELoader.js';
import { Reflector } from './three/examples/jsm/objects/Reflector.js';

var container, controls;
var camera, scene, renderer;

init();
animate();

function init() {

	container = document.createElement('div');
	document.body.appendChild(container);

	scene = new THREE.Scene();

	var ambient = new THREE.AmbientLight(0xffffff);
	scene.add(ambient);

	camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 20);
	camera.position.set(- 1.8, 0.6, 2.7);

	

	new RGBELoader()
		.setDataType(THREE.UnsignedByteType)
		.setPath('assets/')
		.load('photo_studio_01_2k.hdr', function (texture) {

			var envMap = pmremGenerator.fromEquirectangular(texture).texture;

			scene.background = envMap;
			scene.environment = envMap;

			texture.dispose();
			pmremGenerator.dispose();

			var geometry = new THREE.BoxBufferGeometry( 1, 1 );
			var material = new THREE.MeshPhongMaterial({ color: 0xff0000 });
			var mesh = new THREE.Mesh(geometry, material);
			scene.add(mesh);
			var geometry = new THREE.CircleBufferGeometry( 1, 32 );
			
			var mirror = new Reflector(geometry, {
				clipBias: 0.003,
				textureWidth: window.innerWidth * window.devicePixelRatio,
				textureHeight: window.innerHeight * window.devicePixelRatio,
				color: 0x777777,
				recursion: 1
			});
			mirror.position.set(0,0,-0.2)
			scene.add(mirror)
			

			});


	renderer = new THREE.WebGLRenderer({ antialias: true });
	renderer.setPixelRatio(window.devicePixelRatio);
	renderer.setSize(window.innerWidth, window.innerHeight);
	renderer.toneMapping = THREE.ACESFilmicToneMapping;
	renderer.toneMappingExposure = 0.8;
	renderer.outputEncoding = THREE.sRGBEncoding;
	container.appendChild(renderer.domElement);

	var pmremGenerator = new THREE.PMREMGenerator(renderer);
	pmremGenerator.compileEquirectangularShader();

	controls = new OrbitControls(camera, renderer.domElement);
	controls.addEventListener('onclick', render); // use if there is no animation loop
	controls.minDistance = 2;
	controls.maxDistance = 10
	controls.target.set(0, 0, - 0.2);
	controls.update();

	window.addEventListener('resize', onWindowResize, false);

}

function onWindowResize() {

	camera.aspect = window.innerWidth / window.innerHeight;
	camera.updateProjectionMatrix();

	renderer.setSize(window.innerWidth, window.innerHeight);

	render();

}

//
function animate() {

	requestAnimationFrame(animate);

	render();

}
function render() {

	renderer.render(scene, camera);

}

Picture of what I see:

Thanks in advance

What version of three.js are you using?

I’m using r115, should I update it?

Yes, there was a PR for r116 which fixed this kind of rendering issues.

Hey thanks for answering! It works fine now. The thing now is that I want to create a mirror based on a GLB file, using GLTF. I used the geometry of the mesh I imported, but the mirror now seems to be reflecting another angle (I think is phased 90 degrees and upside down). I just found out it changes Y and Z axes between the Geometry and the Mesh imported from the same file. Any idea on how to solve this? I’ll really appreciate it

Code:

import * as THREE from './three/build/three.module.js';
import { OrbitControls } from './three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from './three/examples/jsm/loaders/GLTFLoader.js';
import { RGBELoader } from './three/examples/jsm/loaders/RGBELoader.js';
import { Reflector } from './three/examples/jsm/objects/Reflector.js';
var container, controls;
var camera, scene, renderer;

init();
animate();

function init() {
    container = document.createElement('div');
    document.body.appendChild(container);

    scene = new THREE.Scene();

    var ambient = new THREE.AmbientLight(0xffffff);
    scene.add(ambient);

    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 20);
    camera.position.set(- 0.8, 0.6, 0.7);

    new RGBELoader()
        .setDataType(THREE.UnsignedByteType)
        .setPath('assets/')
        .load('photo_studio_01_2k.hdr', function (texture) {
            var envMap = pmremGenerator.fromEquirectangular(texture).texture;
            scene.background = envMap;
            scene.environment = envMap;
            texture.dispose();
            pmremGenerator.dispose();
            var loader = new GLTFLoader().setPath('assets/');
            loader.load('SVD.glb', function (gltf) {
                var model = gltf.scene.getObjectByName('ESP11');
                model.rotation.set(Math.PI / 2, Math.PI / 2, 0)
                var mirror = new Reflector(model.geometry, {
                    clipBias: 0.003,
                    textureWidth: window.innerWidth * window.devicePixelRatio,
                    textureHeight: window.innerHeight * window.devicePixelRatio,
                    color: 0xbbbbbb,
                    recursion: 1
                });
                scene.add(mirror);
                var model = gltf.scene.getObjectByName('INV11');
                scene.add(model);
                render();
            });
        });
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 0.8;
    renderer.outputEncoding = THREE.sRGBEncoding;
    container.appendChild(renderer.domElement);
    var pmremGenerator = new THREE.PMREMGenerator(renderer);
    pmremGenerator.compileEquirectangularShader();
    controls = new OrbitControls(camera, renderer.domElement);
    controls.addEventListener('onclick'); // use if there is no animation loop
    controls.minDistance = 0.2;
    controls.maxDistance = 1
    controls.target.set(0, 0, - 0.2);
    controls.update();
    window.addEventListener('resize', onWindowResize, false);
}

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
    render();
}

//

function animate() {
    requestAnimationFrame(animate);
    render();
}

function render() {
    renderer.render(scene, camera);
}

Result:

The geometry of the mirror has to be flat. It does not work for geometries with a volume. Can you please ensure that this is the case in your app?

Yes, I ensured Im using a plane made in Blender

CIRCLE.blend (1.7 MB)

Mirrors are the ones in Espejos Collection

Can you please try it with CircleBufferGeometry first? Just to ensure it’s not a problem with the geometry exported from Blender.

Hey, thanks for keeping up in this topic. Yes, as I shared in the first code, I used CircleBufferGeometry. Im going to test if I make a circle plane in blender and if this error persist, I’ll share it with you.

Hey! I just tested with a circle plane made in blender. Seems to be that it works with CircleBufferGeometry but not with a circle imported from a GLTF file.

Blender:

Three.js refractor:

Swapping Z for -Y is a exporter setting under Transform. It should be checked.