I have the following three.js code that renders a cube hovering above a floor, with the camera looking at the cube:
let renderer, camera, scene, light, floor, cube;
init();
render();
function init() {
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);
scene = new THREE.Scene();
scene.background = new THREE.Color('skyblue');
light = new THREE.DirectionalLight('white', 3);
light.position.set(15, 10, 20);
light.castShadow = true;
light.shadow.camera.zoom = 2;
scene.add(light);
floor = new THREE.Mesh();
floor.geometry = new THREE.CircleGeometry(camera.far);
floor.material = new THREE.MeshToonMaterial({ color: 'forestgreen' });
floor.rotation.x = THREE.MathUtils.degToRad(-90);
floor.receiveShadow = true;
scene.add(floor);
cube = new THREE.Mesh();
cube.geometry = new THREE.BoxGeometry();
cube.material = new THREE.MeshPhysicalMaterial({ color: 'red' });
cube.position.set(0, 2, 0);
cube.castShadow = true;
scene.add(cube);
// Look at the cube with the horizon being at 80% screen height.
camera.position.set(0, getCameraY(0.8), 4);
camera.lookAt(cube.position);
}
function render() {
requestAnimationFrame(render);
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
function getCubeY() {
// In my real world scenario this is dynamic.
return 2;
}
function getCameraY(horizonPercent) {
// Don't know how to calculate this.
// Hardcoded to an approximation of 80% for now.
return 3.1;
}
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/[email protected]/build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
window.THREE = THREE; // lol
</script>
What I’m struggling with is how to implement the getCameraY
function. I want the horizon to be positioned at a specified percentage of the canvas height. For example if I were to specify horizonPercent = 0.2
:
horizonPercent = 0.5
:
horizonPercent = 0.8
:
I assume this involves some math to calculate the intersection of the camera’s far plane with the floor, but I’m not sure where to start.