gpt4 book ai didi

javascript - WebGL 透视相机 Canvas 大小调整问题

转载 作者:行者123 更新时间:2023-12-03 12:26:38 24 4
gpt4 key购买 nike

编辑:已确认问题不是矩阵,而是 Canvas 。 Canvas 似乎在调整大小,但实际上它正在剪切模型的部分内容,直到我进行整个刷新。

实时预览:http://jsfiddle.net/B5B8k/6/

我将 C++ 底层引擎代码移植到 Javascript,并设置了一个由 6 个顶点(2 个三 Angular 形)组成的基本正方形,并尝试渲染它。我现在发现问题与 Canvas 有关。 Canvas 的大小正在调整为窗口的内部宽度和窗口的内部高度。每当窗口被拉伸(stretch)时, Canvas 的一部分仍然是“gl.clear”颜色,它覆盖了我正在渲染的任何内容。

this.getPerspective = function(fov, aspect, zNear, zFar) {
var yMax = zNear * Math.tan(fov * Math.PI / 360);
var yMin = -yMax;
var xMin = yMin * aspect;
var xMax = yMax * aspect;
return this.getFrustrum(xMin, xMax, yMin, yMax, zNear, zFar);
};
this.getFrustrum = function(left, right, bottom, top, zNear, zFar) {
var X = 2*zNear/(right-left);
var Y = 2*zNear/(top-bottom);
var A = (right+left)/(right-left);
var B = (top+bottom)/(top-bottom);
var C = -(zFar + zNear)/(zFar - zNear);
var D = -2*zFar*zNear/(zFar - zNear);

return new Mat4(X,0,A,0, 0,Y,B,0, 0,0,C,D, 0,0,-1,0);
};

此函数接受“数字”:

  • fov(以度为单位)

  • 宽高比(窗口宽度/窗口高度)

  • z 靠近裁剪平面

  • 和 z 远剪裁平面。

如果您需要查看更多代码,请询问。

最佳答案

简短的回答是您需要调用gl.viewport,如下所示

gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

您可以在 resize 中调用它,但可以说您应该在 draw 函数中调用它,因为将来如果您使用帧缓冲区对象,则每次都需要调用它您切换到与 Canvas 大小不同的帧缓冲区。

长版本是您永远不应该使用 window.innerWidthwindow.innerHeight 因为这些硬编码您的应用程序只能在完整窗口中运行。相反,请使用canvas.clientWidth和canvas.clientHeight,因为它们在所有情况下都适用,例如 Canvas 仅覆盖页面的一部分,例如带有设置列的3D编辑器,或嵌入,如文章中。

最重要的是,对于像您的应用程序一样不断呈现的应用程序,最好出于同样的原因调用调整每个帧的大小。

function draw() {
resize();
...

调整大小这样写

        function resize() {
var width = canvas.clientWidth;
var height = canvas.clientHeight;
if (canvas.clientWidth != width ||
canvas.clientHeight != height) {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
perspective = new Mat4()
perspective = perspective.getPerspective(60, canvas.clientWidth / canvas.clientHeight, 0.1, 100);
perspective.mat[3][3] = 1;
perspective = perspective.mul(new Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -5, 0, 0, 0, 1));
}
}

原因是,虽然 resize 事件在窗口大小调整时起作用,但如果 Canvas 因其他原因调整大小则无济于事。再说一遍,在所有情况下每帧调用 resize 都有效,而仅在 resize 事件上调用 resize 仅在一种特定情况下有效。

您甚至可以在绘制函数中移动 perspective.mat 操作代码,因为如果将来您绘制到帧缓冲区(例如绘制阴影贴图),您将不得不更改您的无论如何,透视矩阵。虽然每帧做尽可能少的工作当然是一个好主意,但在大型方案中,每帧您只会计算一次或两次透视矩阵,而稍后随着对象的增多,您可能会计算大量的东西在绘制循环中,因此计算透视矩阵所花费的时间相对来说是最小的成本。

最后,循环末尾的 gl.useProgram(0) 对于 WebGL 无效,并且会在 JavaScript 控制台中生成大量错误。

关于javascript - WebGL 透视相机 Canvas 大小调整问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24173270/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com