Question: Shouldn't threejs set the w value of vertices equal to their depth?
When projecting objects onto a screen, objects that are far away from the focal point get projected further towards the center of the screen. In projective coordinates this effect is achieved by dividing a point's (x, y, z)-coordinates by its distance from the focal point, w. I've been playing around with threejs's projection matrix and it seems to me that threejs doesn't do that.
Consider the following scene:
// src/main.ts
import { AmbientLight, BoxGeometry, DirectionalLight, Mesh,
MeshPhongMaterial, PerspectiveCamera, Scene, WebGLRenderer } from "three";
const canvas = document.getElementById('canvas') as HTMLCanvasElement;
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
const renderer = new WebGLRenderer({
alpha: false,
antialias: false,
canvas: canvas,
depth: true
});
const scene = new Scene();
const camera = new PerspectiveCamera(45, canvas.width / canvas.height, 0.01, 100);
camera.position.set(0, 0, 10);
const light = new DirectionalLight();
light.position.set(-1, 0, 3);
scene.add(light);
const light2 = new AmbientLight();
scene.add(light2);
const cube = new Mesh(new BoxGeometry(1, 1, 1, 1), new MeshPhongMaterial({ color: `rgb(0, 125, 125)` }));
scene.add(cube);
cube.position.set(3.42, 3.42, 0);
renderer.render(scene, camera);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="app" style="width: 600px; height: 600px;">
<canvas id="canvas" style="width: 100%; height: 100%;"></canvas>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
This code yields the following image:

Note how the edges of the turquoise box appear exactly parallel to the edges of the canvas. But the front-top-right vertex is further away from my eye than the front-bottom-left vertex. Shouldn't the top-right vertex be slightly distorted towards the center?
I understand that WebGL automatically divides vertices by their w coordinate in the vertex-post-processing-phase. Shouldn't threejs have used the depth to set w so that this distortion-effect is achieved?
What I imagine is something like this:
import { AmbientLight, BoxGeometry, Mesh, MeshBasicMaterial, PerspectiveCamera,
Scene, ShaderMaterial, SpotLight, TextureLoader, Vector3, WebGLRenderer } from "three";
const canvas = document.getElementById('canvas') as HTMLCanvasElement;
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
const loader = new TextureLoader();
const texture = await loader.loadAsync('bricks.jpg');
const renderer = new WebGLRenderer({
alpha: false,
antialias: true,
canvas: canvas,
depth: true
});
const scene = new Scene();
const camera = new PerspectiveCamera(45, canvas.width / canvas.height, 0.01, 100);
camera.position.set(0, 0, -1);
camera.lookAt(new Vector3(0, 0, 0));
const light = new SpotLight();
light.position.set(-1, 0, -1);
scene.add(light);
const light2 = new AmbientLight();
scene.add(light2);
const box = new Mesh(new BoxGeometry(1, 1, 1, 50, 50, 50), new MeshBasicMaterial({
map: texture
}));
scene.add(box);
box.position.set(-0.6, 0, 1);
const box2 = new Mesh(new BoxGeometry(1, 1, 1, 50, 50, 50), new ShaderMaterial({
uniforms: {
tTexture: {value: texture }
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
vec4 clipSpacePos = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
clipSpacePos.w = length(clipSpacePos.xyz);
gl_Position = clipSpacePos;
}
`,
fragmentShader: `
varying vec2 vUv;
uniform sampler2D tTexture;
void main() {
gl_FragColor = texture2D(tTexture, vUv);
}
`,
}));
scene.add(box2);
box2.position.set(0.6, 0, 1);
renderer.render(scene, camera);
Which gives the following output:

Note how the left block displays strong distortion towards the edges.