webGL问题:移动相机时部分屏幕消失
webGL problem: part of the screen dissapears when moving the camera
我想知道是否有人可以帮助我解决这个我找不到原因的渲染错误。我有一个 webGL 网页,它呈现一些非常简单的东西(一个 3D 迷宫,但这并不重要),当我移动相机(观察者)的位置时,部分屏幕消失了。当你向外移动相机时,它看起来像一团空无一物的东西。
我画了一个简单的立方体来说明问题。它主要发生在你走到立方体的“后面”(坐标 z 负),并开始旋转你的相机,或者移动你自己。
我很确定问题出在进行相机移动时计算 mvp 矩阵的公式。我使用 Gauss-Schmidt 来计算正交基(我不太记得为什么但我记得我必须这样做才能找到平移视图的方向)。
我附加了一些 gif 和 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);
}
投影矩阵为:
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
];
}
然后mvp矩阵计算为:
let mv = GetModelViewMatrix(transX, transY, transZ, rotX, autorot + rotY, rotZ, cameraRotationXY);
let mvp = MatrixMult(perspectiveMatrix, mv);
您需要定义适用于场景的静态近距和远距裁剪平面,例如.01 到 100.0。传统的矩阵堆栈像相机一样构建:投影矩阵是镜头(定义视野、缩放和聚焦),视图矩阵是实际相机(平移和方向),模型矩阵是你的主题(位置、方向) , 规模)。 Scratchpixel 似乎有一个关于投影的完整部分。 –
LJᛃ
我想知道是否有人可以帮助我解决这个我找不到原因的渲染错误。我有一个 webGL 网页,它呈现一些非常简单的东西(一个 3D 迷宫,但这并不重要),当我移动相机(观察者)的位置时,部分屏幕消失了。当你向外移动相机时,它看起来像一团空无一物的东西。
我画了一个简单的立方体来说明问题。它主要发生在你走到立方体的“后面”(坐标 z 负),并开始旋转你的相机,或者移动你自己。
我很确定问题出在进行相机移动时计算 mvp 矩阵的公式。我使用 Gauss-Schmidt 来计算正交基(我不太记得为什么但我记得我必须这样做才能找到平移视图的方向)。
我附加了一些 gif 和 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);
}
投影矩阵为:
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
];
}
然后mvp矩阵计算为:
let mv = GetModelViewMatrix(transX, transY, transZ, rotX, autorot + rotY, rotZ, cameraRotationXY);
let mvp = MatrixMult(perspectiveMatrix, mv);
您需要定义适用于场景的静态近距和远距裁剪平面,例如.01 到 100.0。传统的矩阵堆栈像相机一样构建:投影矩阵是镜头(定义视野、缩放和聚焦),视图矩阵是实际相机(平移和方向),模型矩阵是你的主题(位置、方向) , 规模)。 Scratchpixel 似乎有一个关于投影的完整部分。 – LJᛃ