Orthographic camera with limits

Hi all,
I have recently been trying to add a new responsive type of orthographic camera to my project, what I want to achieve is an orthographic camera that doesn’t show anything after the limits, like this:

-Default Scene

-Scaled Scenes

As you can see in the example, in the scaled scenes (2x1, 1x2, 1.7x0.6) the camera never shows something after the yellow border (which is the limit), only before. It works similarly to CSS’s object-fit: cover; property.

This issue has been covered before, but I couldn’t find any example that works with an Orthographic camera. I’ve been trying for the last couple of days to make some other scripts work, but I couldn’t manage to make those function. This is my current script:

// ...
function resize()
{
    let width, height;

    // Make camera responsive
    if (window.innerWidth < window.innerHeight) {
        // Make height smaller while keeping the width/height ratio constant
    }
    else {
        // Default case
        width = window.innerWidth / window.innerHeight;
        height = 1;
    }

    // Set Orthographic camera width and height 
    camera.right = width;
    camera.left = -width;
    camera.top = height;
    camera.bottom = -height;
    camera.updateProjectionMatrix();

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

    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
}

window.addEventListener('resize', function() { resize(); });
// ...

I also found some other solutions (that I didn’t manage to adapt) that scaled the scene instead of bothering with the camera. Does anybody have a solution?

TLDR: I’m trying to make this code or any other solution for keeping a camera in its limits use an Orthographic Camera.

This?

The example you linked is really close to what I’m trying to get to but, unfortunately, it does a bit the opposite of what I’m trying to achieve, it’s probably because of my unclear explanation in the last post so I’ll try to explain myself better.

So, in the example, when you augment the width of the preview window, you can see that it adds more black on the sides (as shown with the orange lines):

But what I’m trying to do is the contrary:

I believe that a better way to imagine this situation is to think of the scene as an image, we can’t stretch it nor we can enlarge it, so the only option remaining is to make the camera fit in the image rather than making the image fit in the camera.

More examples (with the same ratios from before):

I think what your saying is that you don’t want the view to scale to fit when you change the aspect ratio. Or maybe you do?

I don’t know a method that can reliably handle changing both height and width without scaling, or the opposite. There probably is a way though.

Using my Orthographic example

  1. This first method doesn’t scale to fit when you change canvas width, but does when you change height.
function onWindowResize() {
    const aspect = window.innerWidth / window.innerHeight

    camera.left = (-data.frustumSize * aspect) / 2
    camera.right = (data.frustumSize * aspect) / 2
    camera.top = data.frustumSize / 2
    camera.bottom = -data.frustumSize / 2

    camera.updateProjectionMatrix()

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

image

  1. This second method doesn’t scale to fit when you change canvas height, but does when you change width.
function onWindowResize() {
    const aspect = window.innerWidth / window.innerHeight

    camera.left = -data.frustumSize / 2
    camera.right = data.frustumSize / 2
    camera.top = data.frustumSize / aspect / 2
    camera.bottom = -data.frustumSize / aspect / 2

    camera.updateProjectionMatrix()

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

image

I’m curious what the answer would be, if it is that you don’t want the scale to fit when changing the aspect ratio, or you do.

1 Like

The new code you provided was exactly the answer I needed! I mixed the two codes you wrote like this:

// ...
function onWindowResize() {
    const aspect = window.innerWidth / window.innerHeight
    let width, height

    // If/else case to make the camera responsive
    if (window.innerWidth > window.innerHeight) {
        width = data.frustumSize / 2
        height = data.frustumSize / aspect / 2
    }
    else {
        width = data.frustumSize * aspect / 2
        height = data.frustumSize / 2
    }

    // Orthographic's way
    camera.right = width
    camera.left = -width
    camera.top = height
    camera.bottom = -height
    camera.updateProjectionMatrix()

    // Remember to set 'true' to interfere with the canvas's style, or else the it won't scale
    renderer.setSize(window.innerWidth, window.innerHeight, true)

    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
}

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

And it work like a charm!
I also forked your example (with proper attributions) to show the result. Thanks so much for helping me, I’m making your post the solution since it has the scripts needed for the result.

1 Like