编辑:已确认问题不是矩阵,而是画布。画布似乎调整大小,但它实际上是切断模型的一部分,直到我进行整个刷新。
现场预览:http://jsfiddle.net/B5B8k/6/
我将我的C ++底层引擎代码移植到Javascript,我设置了一个由6个顶点(2个三角形)组成的基本正方形,我试图渲染它。我现在发现问题与画布有关。画布正在调整大小到窗口的innerWidth和窗口的innerHeight。每当窗口被拉伸时,画布的一部分仍然是" 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远剪裁平面。
如果您需要查看更多代码,请询问。
答案 0 :(得分:1)
简短的回答是你需要像
一样调用gl.viewport
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
您可以在resize
中调用它,但可以说您应该在draw
函数中调用它,因为将来如果使用帧缓冲对象,每次切换到帧缓冲区时都需要调用它与画布大小不同。
长版本是您永远不应该使用window.innerWidth
和window.innerHeight
作为那些硬编码您的应用程序只能在一个完整的窗口中工作。而是使用canvas.clientWidth
和canvas.clientHeight
,因为它们适用于所有情况,例如画布仅覆盖页面的一部分,例如带有设置列的3d编辑器,或嵌入式,如文章中所示。 / p>
最重要的是,对于经常呈现与您相似的应用,最好是出于同样的原因调用每一帧的大小。
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
事件在调整窗口大小时起作用,但如果画布由于其他原因而调整大小则无效。因此,在所有情况下调用resize每个帧都可以工作,因为仅在resize事件上调用resize只能在一个特定情况下工作。
您甚至可以在绘制函数中移动perspective.mat
操作代码,因为如果将来您绘制到帧缓冲区(比如绘制阴影贴图),您无论如何都必须更改透视矩阵。尽管每帧尽可能少地工作当然是一个好主意,但在大型方案中,你只需要每帧一次或两次计算透视矩阵,而后来有更多对象,你可能会计算大量的东西在你的绘制循环中,所以计算透视矩阵所花费的时间相对来说是最小的成本。
最后,循环结束时gl.useProgram(0)
对WebGL
无效,并在JavaScript控制台中产生大量错误。