Akao
Akao

Reputation: 131

Three.js set plane size to full view

I am Japanese, not good at English, sorry.

I am studying Three.js.

I want to set Plane as a background right in front of the camera.

And I want the Plane background to be completely filling the window(renderer).

But now it's like this.

The Plane is blue.

It is little bit small.

Here is the code.

function init() {
    var scene = new THREE.Scene();

    var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
    scene.add(camera);

    camera.position.x = 0;
    camera.position.y = 0;
    camera.position.z = 100;
    camera.lookAt(scene.position); // (0, 0, 0)

    var renderer = new THREE.WebGLRenderer();
    renderer.setClearColor(new THREE.Color(0xe3e3e3));
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;

    var spotLight = new THREE.SpotLight(0xffffff);
    spotLight.position.set(50, 50, 50);
    spotLight.castShadow = true;
    scene.add(spotLight);

    // I want to put Plane's size as full background. not (82, 82 * window.innerHeight / window.innerWidth)
    var planeGeometry = new THREE.PlaneGeometry(82, 82 * window.innerHeight / window.innerWidth);
    var planeMaterial = new THREE.MeshLambertMaterial({color: 0x123abc});
    var plane = new THREE.Mesh(planeGeometry, planeMaterial);
    plane.receiveShadow = true;
    plane.position.x = 0;
    plane.position.y = 0;
    plane.position.z = 0;

    scene.add(plane);

    var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
    var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
    var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

    cube.position.x = 2
    cube.position.y = 10
    cube.position.z = 2

    cube.castShadow = true

    scene.add(cube);

    document.getElementById("WebGL-output").appendChild(renderer.domElement);
    renderer.render(scene, camera);
}
window.onload = init;
<script src="https://rawcdn.githack.com/mrdoob/three.js/r113/build/three.js"></script>
<div id="WebGL-output"></div>

I want to use the plane as a completely filled background of window.

My camera position is

camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 100;

So it is watching the seen from perfectly front.

And the reason why I set 82 as Plane's width sample is this

I set camera.position.z = 100; and fov is 45deg.

So I thought if you make a triangle like the image and calculate, the full width of (0, 0, 0) should be like that.

I get the 82.842... from some website that can calculate triangle from is's shape and degree.

Upvotes: 4

Views: 2889

Answers (1)

Rabbid76
Rabbid76

Reputation: 210889

82.842 is correct, but the field of view angle of the PerspectiveCamera is the angle on the y-axis (vertical).
To compute the field of view you have to use the tangents (tan). The field of view along the y axis is

fov_y = z * tan(angle / 2) * 2

Apply that to your code:

let ang_rad = 45.0 * Math.PI / 180;
let fov_y = 100 * Math.tan(ang_rad / 2) * 2;
var planeGeometry = 
    new THREE.PlaneGeometry(fov_y * window.innerWidth / window.innerHeight, fov_y);

Respectively

let ang_rad = camera.fov * Math.PI / 180;
let fov_y = camera.position.z * Math.tan(ang_rad / 2) * 2;
var planeGeometry = new THREE.PlaneGeometry(fov_y * camera.aspect, fov_y);

You can simplify the computation by retrieving the focal length (.getFocalLength ()) and the film height (.getFilmHeight()):

let fov_y = camera.position.z * camera.getFilmHeight() / camera.getFocalLength();
var planeGeometry = new THREE.PlaneGeometry(fov_y * camera.aspect, fov_y);

function init() {
    var scene = new THREE.Scene();

    var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
    scene.add(camera);

    camera.position.x = 0;
    camera.position.y = 0;
    camera.position.z = 100;
    camera.lookAt(scene.position); // (0, 0, 0)

    var renderer = new THREE.WebGLRenderer();
    renderer.setClearColor(new THREE.Color(0xe3e3e3));
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;

    var spotLight = new THREE.SpotLight(0xffffff);
    spotLight.position.set(50, 50, 50);
    spotLight.castShadow = true;
    scene.add(spotLight);

    // I want to put Plane's size as full background. not (82, 82 * window.innerHeight / window.innerWidth)
    let ang_rad = camera.fov * Math.PI / 180;
    let fov_y = camera.position.z * Math.tan(ang_rad / 2) * 2;
    var planeGeometry = new THREE.PlaneGeometry(fov_y * camera.aspect, fov_y);
    var planeMaterial = new THREE.MeshLambertMaterial({color: 0x123abc});
    var plane = new THREE.Mesh(planeGeometry, planeMaterial);
    plane.receiveShadow = true;
    plane.position.x = 0;
    plane.position.y = 0;
    plane.position.z = 0;

    scene.add(plane);

    var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
    var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
    var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

    cube.position.x = 2
    cube.position.y = 10
    cube.position.z = 2

    cube.castShadow = true

    scene.add(cube);

    document.getElementById("WebGL-output").appendChild(renderer.domElement);
    renderer.render(scene, camera);
}
window.onload = init;
<script src="https://rawcdn.githack.com/mrdoob/three.js/r113/build/three.js"></script>#
<div id="WebGL-output"></div>

Upvotes: 6

Related Questions