我需要一些帮助来理解平截头体转换的基础知识。主要是深度是如何工作的。
下面使用 768x1024 的视口。使用正交投影和 768x768(z 默认为 0)的正方形,不进行平移或缩放,并且glViewport(0, 0, 768, 1024)
该正方形的视口很容易填充框架的宽度:
现在,当我将项目更改为平截头体并弄乱 z 平移时,由于视角的变化,正方形会适当地缩放。
这是这样一个环境中的同一个广场:
我可以使用这个 z 平移,以及截头体矩阵的近距和远距参数,并相应地使正方形变化在屏幕尺寸上很明显。美好的。
但我无法弄清楚的是它的屏幕尺寸和这些深度参数之间的明显关系。
例如,假设我想使用平截头体,但让正方形填充框架宽度,如上面的第一个示例图像所示。如何做到这一点?
我认为如果 z 平移与near
平面相匹配,那么您基本上会在“相机正前方”有一个正方形,填充框架。但我想不出办法来实现这一点。如果我的近端是1
并且我的 z 平移是-1
,那么正方形应该正好位于近端平面本身(对吗?!),填充框架的宽度(平截头体的左右平面与正交投影相同) .
我可以在这里粘贴一堆代码来展示我在做什么,但我认为这里的概念很清楚。我只是想弄清楚近平面实际上在哪里,如何在上面放置一些东西,因为这将帮助我了解平截头体是如何工作的。
好的,这是我正在使用的相关代码,wherewidth=768
和height=1024
.
我的顶点着色器很简单gl_Position=Projection*Modelview*Position;
因此,我的投影矩阵(平截头体)是:
Frustum(-width/2, width/2, -height/2, height/2, 1,10);
这个功能是:
static Matrix4<T> Frustum(T left, T right, T bottom, T top, T near, T far)
{
T a = 2 * near / (right - left);
T b = 2 * near / (top - bottom);
T c = (right + left) / (right - left);
T d = (top + bottom) / (top - bottom);
T e = - (far + near) / (far - near);
T f = -2 * far * near / (far - near);
Matrix4 m;
m.x.x = a; m.x.y = 0; m.x.z = 0; m.x.w = 0;
m.y.x = 0; m.y.y = b; m.y.z = 0; m.y.w = 0;
m.z.x = c; m.z.y = d; m.z.z = e; m.z.w = -1;
m.w.x = 0; m.w.y = 0; m.w.z = f; m.w.w = 1;
return m;
}
我的正方形只是两个 2d 三角形,默认 z=0,x 范围从左侧为 -768/2,右侧为 768/2。正如我上面的第一张图片所示,使用正交投影,正方形显然可以正常工作。(虽然我切换到这个问题的截锥投影)
为了绘制正方形,我将 Modelview 翻译为:
Translate(0, 0, -1);
使用:
static Matrix4<T> Translate(T x, T y, T z)
{
Matrix4 m;
m.x.x = 1; m.x.y = 0; m.x.z = 0; m.x.w = 0;
m.y.x = 0; m.y.y = 1; m.y.z = 0; m.y.w = 0;
m.z.x = 0; m.z.y = 0; m.z.z = 1; m.z.w = 0;
m.w.x = x; m.w.y = y; m.w.z = z; m.w.w = 1;
return m;
}
如您所见,平移应该将正方形放在近平面上,但它看起来像这样:
如果我翻译而不是 -1.01 只是为了确保避免接近削波,结果是一样的。如果我不翻译,因此 z=0,正方形不会出现,如您所料,因为它会在相机后面。