0

我以前在这里看到过这种类型的问题,但没有一个给我完整的答案,所以我将发布我的代码,看看是否有人能给我任何见解。基本上,这段代码有效,但我有一个神奇的 z 偏移 (height * 1.205) [与宽度无关],我不知道为什么。

设置大小并创建对齐向量:

gl.viewportWidth = gl.canvas.width;
gl.viewportHeight = gl.canvas.height;
gl.viewportHalfWidth = gl.viewportWidth / 2;
gl.viewportHalfHeight = gl.viewportHeight / 2;
gl.viewportAspect = gl.viewportWidth / gl.viewportHeight;
gl.viewportZoom = -gl.viewportHeight * 1.205;
if (gl.alignmentTest) {
    gl.alignmentVertices = (new Buffer(    // TL, TM, BM, BR, TR, BL, TL
       [    1.0,                        -1.0,                    0.0,
        gl.viewportHalfWidth - 0.5,     -1.0,                    0.0,
        gl.viewportHalfWidth - 0.5, -(gl.viewportHeight - 1.0),  0.0,
        gl.viewportWidth - 1.0,     -(gl.viewportHeight - 1.0),  0.0,
        gl.viewportWidth - 1.0,         -1.0,                    0.0,
            1.0,                    -(gl.viewportHeight - 1.0),  0.0,
            1.0,                        -1.0,                    0.0], 3)).post();
}

绘制对齐向量:

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
mat4.perspective(45, gl.viewportAspect, 0.1, 1000.0, gl.perspective.current);
gl.perspective.post();    // ^ writes directly to current perspective buffer

gl.modelView.resetToIdentity();

gl.enable(gl.BLEND);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);

// Translate to pixel resolution
gl.modelView.push();
gl.modelView.translate([-gl.viewportHalfWidth, gl.viewportHalfHeight, gl.viewportZoom]);
gl.modelView.post();

// Alignment test?
if (gl.alignmentTest && gl.alignmentVertices) {
    gl.red.useAsAttribute(gl.shaderProg.vertexColour);
    gl.zero.vec2.useAsAttribute(gl.shaderProg.vertexTextureCoord);
    gl.alignmentVertices.drawAsPrimitives(gl.shaderProg.vertexPosition, gl.LINE_STRIP);
}

gl.disable(gl.BLEND);

有问题的行是:

gl.viewportZoom = -gl.viewportHeight * 1.205;

和:

gl.modelView.translate([-gl.viewportHalfWidth, gl.viewportHalfHeight, gl.viewportZoom]);

此代码适用于任何尺寸。

这是 700x300 的屏幕截图:http: //oi49.tinypic.com/2my9ir7.jpg

另一个是 400x600: http ://oi46.tinypic.com/i2irh3.jpg

所以问题是:为什么会存在 1.205 这个神奇的比例因子?或者我可能做错了什么以使其成为必要?

4

1 回答 1

3

我还没有计算出数学,但我猜这个因素来自你的透视投影矩阵的 FOV 和近平面。大多数试图获得 1:1 像素的应用程序也不使用透视投影。

如果你有理由使用透视,那么我建议不要使用基于 FOV 的透视计算,而是使用基于平截头体的(glFrustum-alike)——实际上更容易得出投影平截头体的效果,并且你可以计算出该校正从第一原则考虑因素,而不是手动调整它。


这本质上是一个三角问题。想象一下视锥体,或者更确切地说是视图金字塔(即不被近平面和远平面切断);它的尖端位于“相机位置”和四个倾斜面。传统定义的 FOV 等于顶面和底面之间的角度(这就是为什么,正如您所提到的,宽度没有影响)。但是,出于您的目的,您关心的参数不是角度,而是斜率(Z 与 X 或 Y 运动的比率)——这是您的任意数字的来源。

如果我们查看好的 ol' 文档gluPerspective(我将假设它使用与您的透视操作相同的数学),它会说: f = cotangent(fovy/2). 这正是我们关心的计算。(如果试图重现这一点,请注意数学库中的大多数三角函数都以弧度表示角度,而不是度数。)

之所以会出现 2 的因素,是因为 FOV 通常是作为全视角测量的,但感兴趣的值是全视角的一半——“正前方”和“就在视图边缘”之间的角度。

您可能知道,余切(或正切)函数的值可以解释为斜率。上面的斜率f准确地告诉您 Z 运动和 X 或 Y 运动之间的比率;例如,如果您将对象缩放某个值d,并沿 Z 轴移动f*d,那么它似乎不会改变大小。这可能正是您viewportZoom已经在做的事情:

f / 2 = cot(45° / 2) / 2 ≈ 1.207106

这非常接近您的 1.205。如果情况确实如此,我还没有弄清楚因子 2 的来源。

您需要做的就是计算f一次(或者可能是它的倒数tan(fovy/2),具体取决于最终哪个更方便)并使用它来计算“缩放”距离和投影矩阵。


(顺便说一句,您的代码包含很多不是 WebGL 的东西,例如BufferpostdrawAsPrimitives等。如果您提到您正在使用的库,这可能会有所帮助。)

于 2012-12-11T05:34:09.177 回答