I'm wondering if someone could help me with this rendering bug that I can't find the cause. I have a webGL webpage that renders some very simple stuff (a 3D maze, but it doesn't really matter), and when I move the position of the camera (the observer), part of the screen dissapears. It looks like a big blob of nothing that increases when you move the camera outwards.

I drawed a simple cube to illustrate the problem. It mostly happens when you go "to the back" of the cube (coordinate z negative), and start rotating your camera, or moving yourself.

I'm pretty sure that the problem is with the formula for calculating the mvp matrix when doing a camera movement. I use Gauss-Schmidt to calculate an orthonormal base (I don't quite remember why but I remember I had to do it to find the direction of the translation view).

I attach some gifs and links to youtube:

https://imgur.com/xXW9nLf https://youtu.be/7POI3sty0aE

https://imgur.com/1K4Ot37 https://youtu.be/7POI3sty0aE

```
function GetModelViewMatrix(translationX, translationY, translationZ,
rotationX, rotationY, rotationZ, cameraRotationXY) {
const cosRotationX = Math.cos(rotationX);
const sinRotationX = Math.sin(rotationX);
const cosRotationY = Math.cos(rotationY);
const sinRotationY = Math.sin(rotationY);
const cosRotationZ = Math.cos(rotationZ);
const sinRotationZ = Math.sin(rotationZ);
let rotationMatrixX = [
1, 0, 0, 0,
0, cosRotationX, sinRotationX, 0,
0, -sinRotationX, cosRotationX, 0,
0, 0, 0, 1
]
let rotationMatrixY = [
cosRotationY, 0, -sinRotationY, 0,
0, 1, 0, 0,
sinRotationY, 0, cosRotationY, 0,
0, 0, 0, 1
]
let rotationMatrixZ = [
cosRotationZ, sinRotationZ, 0, 0,
-sinRotationZ, cosRotationZ, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
]
let rotations = MatrixMult(rotationMatrixZ, MatrixMult(rotationMatrixX, rotationMatrixY));
let trans = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
translationX, translationY, translationZ, 1
];
let mv = MatrixMult(trans, rotations);
let alpha = 0;
let theta = cameraRotationXY;
let w = new Vertex([
Math.cos(alpha) * Math.sin(theta),
Math.sin(alpha) * Math.sin(theta),
Math.cos(theta)]);
let v2 = new Vertex([-w.z, 0, w.y]);
let p = proj(w, v2);
let u2 = new Vertex([v2.x - p.x, v2.y - p.y, v2.z - p.z]);
let u = Normalize(u2);
let u3 = crossProduct(w, u);
let v = Normalize(u3);
let direction = [
-u.x, -u.y, -u.z, 0,
-v.x, -v.y, -v.z, 0,
w.x, w.y, w.z, 0,
0, 0, 0, 1
];
return MatrixMult(direction, mv);
}
```

The projection matrix is:

```
function UpdateProjectionMatrix() {
perspectiveMatrix = ProjectionMatrix(canvas, transZ);
}
// Calculates the perspective matrix (column-major)
function ProjectionMatrix(c, z, fov_angle = 60) {
const magia_z = 1.74;
let r = c.width / c.height;
let n = (z - magia_z);
const min_n = 0.001;
if (n < min_n) n = min_n;
let f = (z + magia_z);
let fov = Math.PI * fov_angle / 180;
let s = 1 / Math.tan(fov / 2);
return [
s / r, 0, 0, 0,
0, s, 0, 0,
0, 0, (n + f) / (f - n), 1,
0, 0, -2 * n * f / (f - n), 0
];
}
```

And then the mvp matrix is calculated as:

```
let mv = GetModelViewMatrix(transX, transY, transZ, rotX, autorot + rotY, rotZ, cameraRotationXY);
let mvp = MatrixMult(perspectiveMatrix, mv);
```

`.01`

to`100.0`

. The traditional matrix stack is built like a camera: the projection matrix is the lens(defining the field of view, zoom and focus), the view matrix the actual camera(translation and orientation) and the model matrix is your subject(position, orientation, scale). Scratchpixel appears to have a thorough section about projection.