0

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);
4
  • 2
    You're feeding Z-Translation as the far clipping distance to your projection matrix? That seems pretty wrong since the clipping planes of the projection matrix are already transformed by the view matrix (or in your case the modelview).
    – LJᛃ
    Jan 19 at 11:47
  • I see. What would you use intead of the trans z distance? Where can I read more about this? :) Thank you Jan 21 at 2:04
  • 1
    You'd define static near and far clipping planes that work for your scene e.g. .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.
    – LJᛃ
    Jan 21 at 10:03
  • Thanks, that was the problem. Setting f to a big number that didn't depend on z fixed the issue. Also reading about clipping planes made the problem clearer to me. Thank you. Jan 26 at 17:29

1 Answer 1

0

You'd define static near and far clipping planes that work for your scene e.g. .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. – LJᛃ

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.