Create Elliptical renderTarget view

Hello,

I’m recreating portal’s effect of the game Portal.
I’m rendering a camera inside a BoxGeometry, then I’m adding an ellipse curve.
But I saw (ofc) that the BoxGeometry should be an ellipse too (look image below).
When I created a filled ellipse and I added the camera rendering, it was bugging (maybe because an ellipse / circle aren’t created like other basic shapes.

So I’m trying to clip the rectangle shape of the camera inside an ellipse one, but, even searching on the net, I found nothing to help me.
I don’t think CSG can help me because it’s not including THREE.js shapes in its clip methods (else please write me how to do ?).

Here’s the code on how I proceed and the result.

Have you a solution ?

  • To get the portal size I’ve this:
const portalConf = this.default.portal;
const size = {
    x: portalConf.size[0],
    y: portalConf.size[1],
    z: portalConf.size[2]
};
  • Then I’m adding a camera renderTarget:
this.addCamera(cx, cy, cz, dx, dy, dz, size.z / size.y);

/* addCamera method: */
addCamera(x, y, z, dx=0, dy=0, dz=0, ratio=this.aspect) {
    const camera = new THREE.PerspectiveCamera(this.default.env.FOW, ratio, this.default.env.near, this.default.env.far);
    camera.position.set(x, y, z);

    camera.lookAt(dx, dy, dz);

    this.scene.add(camera);
    this.cameras.push(camera);

    this.renderTarget = new THREE.WebGLRenderTarget(500, 250, {antialias: true});
}

(The renderTarget will be rendered in the render method.)

  • Then I create the rectangle shape to render the camera view:
const material = new THREE.MeshLambertMaterial({
    map: this.renderTarget.texture
});

const geometry = new THREE.BoxGeometry(size.x, size.y, size.z);
const shape = new THREE.Mesh(geometry, material);
        
shape.position.set(x, y, z);

And finally the blue ellipse curve to do the outline.

/* http://jsfiddle.net/nu69ed8t/1 */
const path = new Ellipse(size.z/2, size.y/2);

const pathSegments      = 64;
const tubeRadius        = 0.5;
const radiusSegments    = 16;
const closed            = true;

const geometryE = new THREE.TubeBufferGeometry(path, pathSegments, tubeRadius, radiusSegments, closed);

const materialE = new THREE.MeshLambertMaterial({
    color: portalConf.color[0], 
});

const ellipse = new THREE.Mesh(geometryE, materialE);
ellipse.position.set(x, y, z);
ellipse.rotation.y = Math.PI / 2;

image(1)

Thanks for your time.

Hello! You need to change virtualCamera to mainCamera here https://github.com/mrdoob/three.js/blob/79edf22a345079dc6cf5d8c6ad38ee22e9edab3c/examples/jsm/objects/Reflector.js
and make a rectangle at first. After that you can modify it to ellipse.

Thanks for replying.
Why must I use reflector.js for a virtual camera ? what’s the difference with what I’m using right now ?
And How can I change a rectangle to an ellipse ?

The reason why I am suggesting you to take this class, because with the same technique we creating reflections. But they also mirroring camera and change it to virtual one.

This topic described in book by Eric Lengyel. Mathematics for 3D game programming and computer graphics page ~120. And also you can see comment in this class

// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf

You can just take a rectangle place it on the portal, hack mirror class and than add transparency on edges to make it look like ellipse. In this way, you can minimize rendering on scene. Another approach is to use depth masking https://threejs.org/examples/?q=mask#webgl_postprocessing_masking .

Thanks you, I understand now.