OpenTK 倾斜切片(镜头移位)
OpenTK Oblique Frustum (Lens Shift)
我是 OpenGL 的新手,正在使用最新版本的 OpenTK 和 C#。
我的相机 class 当前执行以下操作,
public Matrix4 GetProjectionMatrix()
{
return Matrix4.CreatePerspectiveFieldOfView(_fov, AspectRatio, 0.01f, 100f);
}
public Matrix4 GetViewMatrix()
{
Vector3 lookAt = new Vector3(myObject.Pos.X, myObject.Pos.Y, myObject.Pos.Z);
return Matrix4.LookAt(Position, lookAt, _up);
}
我有一个有点奇怪的用例,我的游戏 window 会很长,类似于 4:12 比率,它会呈现一个长对象。根据我的阅读,在网上以我想要的方式呈现此内容的最佳方式是进行镜头移位(斜视锥体)。
我在网上看过有关如何执行此操作的文章,即:
http://www.terathon.com/code/oblique.html
https://docs.unity3d.com/Manual/ObliqueFrustum.html
但是我在将其转换为 OpenTk 时遇到了问题。
想知道这里是否有人在 OpenTK 中做过类似的事情。
编辑:
这种方法有效,但不是我想要的:(
private float sgn(float a)
{
if (a > 0.0F) return (1.0F);
if (a < 0.0F) return (-1.0F);
return (0.0F);
}
public Matrix4 CreatePerspectiveFieldOfView(Matrix4 projectionMatrix)
{
Vector4 clipPlane = new Vector4(0.0f, 0.7f, 1.0f , 1.0f);
Vector4 q = new Vector4
{
X = (sgn(clipPlane.X) + projectionMatrix.M13) / projectionMatrix.M11,
Y = (sgn(clipPlane.Y) + projectionMatrix.M23) / projectionMatrix.M22,
Z = -1.0f,
W = (1.0F + projectionMatrix.M33) / projectionMatrix.M34
};
Vector4 c = clipPlane * (2.0F / Vector4.Dot(clipPlane, q));
projectionMatrix.M31 = c.X;
projectionMatrix.M32 = c.Y;
projectionMatrix.M33 = c.Z + 1.0f;
projectionMatrix.M34 = c.W;
return projectionMatrix;
}
编辑 2:
基本上我想要做的是将观察点靠近平截头体的边缘,如下所示:
有一些明显的问题。 OpenGL 矩阵是列主要顺序。因此,i 是列,j 是 Mij
属性的行:
后面的列是从上到下,行是从左到右,因为这是内存中矩阵字段的表示以及矩阵"looks"在调试器:
row1 row2 row3 row4 indices
column1 (M11, M12, M13, M14) ( 0, 1, 2, 3)
column2 (M21, M22, M23, M24) ( 4, 5, 6, 7)
column3 (M31, M32, M33, M34) ( 8, 9, 10, 11)
column4 (M41, M42, M43, M44) (12, 13, 14, 15)
因此
q.x = (sgn(clipPlane.x) + matrix[8]) / matrix[0];
q.y = (sgn(clipPlane.y) + matrix[9]) / matrix[5];
q.z = -1.0F;
q.w = (1.0F + matrix[10]) / matrix[14];
必须翻译成:
Vector4 q = new Vector4
{
X = (sgn(clipPlane.X) + projectionMatrix.M31) / projectionMatrix.M11,
Y = (sgn(clipPlane.Y) + projectionMatrix.M32) / projectionMatrix.M22,
Z = -1.0f,
W = (1.0f + projectionMatrix.M33) / projectionMatrix.M43
};
and
```cpp
matrix[2] = c.x;
matrix[6] = c.y;
matrix[10] = c.z + 1.0F;
matrix[14] = c.w;
必须
projectionMatrix.M13 = c.X;
projectionMatrix.M23 = c.Y;
projectionMatrix.M33 = c.Z + 1.0f;
projectionMatrix.M43 = c.W;
如果你想要一个不对称的透视投影,然后考虑通过 Matrix4.CreatePerspectiveOffCenter
创建全投影矩阵。
public Matrix4 GetProjectionMatrix()
{
var offset_x = -0.0f;
var offset_y = -0.005f; // just for instance
var tan_fov_2 = Math.Tan(_fov / 2.0);
var near = 0.01f;
var far = 100.0f;
var left = -near * AspectRatio * tan_fov_2 + offset_x;
var right = near * AspectRatio * tan_fov_2 + offset_x;
var bottom = -near * tan_fov_2 + offset_y;
var top = near * tan_fov_2 + offset_y;
return Matrix4.CreatePerspectiveOffCenter(left, right, bottom, top, near, far);
}
我是 OpenGL 的新手,正在使用最新版本的 OpenTK 和 C#。
我的相机 class 当前执行以下操作,
public Matrix4 GetProjectionMatrix()
{
return Matrix4.CreatePerspectiveFieldOfView(_fov, AspectRatio, 0.01f, 100f);
}
public Matrix4 GetViewMatrix()
{
Vector3 lookAt = new Vector3(myObject.Pos.X, myObject.Pos.Y, myObject.Pos.Z);
return Matrix4.LookAt(Position, lookAt, _up);
}
我有一个有点奇怪的用例,我的游戏 window 会很长,类似于 4:12 比率,它会呈现一个长对象。根据我的阅读,在网上以我想要的方式呈现此内容的最佳方式是进行镜头移位(斜视锥体)。
我在网上看过有关如何执行此操作的文章,即: http://www.terathon.com/code/oblique.html https://docs.unity3d.com/Manual/ObliqueFrustum.html
但是我在将其转换为 OpenTk 时遇到了问题。
想知道这里是否有人在 OpenTK 中做过类似的事情。
编辑: 这种方法有效,但不是我想要的:(
private float sgn(float a)
{
if (a > 0.0F) return (1.0F);
if (a < 0.0F) return (-1.0F);
return (0.0F);
}
public Matrix4 CreatePerspectiveFieldOfView(Matrix4 projectionMatrix)
{
Vector4 clipPlane = new Vector4(0.0f, 0.7f, 1.0f , 1.0f);
Vector4 q = new Vector4
{
X = (sgn(clipPlane.X) + projectionMatrix.M13) / projectionMatrix.M11,
Y = (sgn(clipPlane.Y) + projectionMatrix.M23) / projectionMatrix.M22,
Z = -1.0f,
W = (1.0F + projectionMatrix.M33) / projectionMatrix.M34
};
Vector4 c = clipPlane * (2.0F / Vector4.Dot(clipPlane, q));
projectionMatrix.M31 = c.X;
projectionMatrix.M32 = c.Y;
projectionMatrix.M33 = c.Z + 1.0f;
projectionMatrix.M34 = c.W;
return projectionMatrix;
}
编辑 2:
基本上我想要做的是将观察点靠近平截头体的边缘,如下所示:
有一些明显的问题。 OpenGL 矩阵是列主要顺序。因此,i 是列,j 是 Mij
属性的行
后面的列是从上到下,行是从左到右,因为这是内存中矩阵字段的表示以及矩阵"looks"在调试器:
row1 row2 row3 row4 indices
column1 (M11, M12, M13, M14) ( 0, 1, 2, 3)
column2 (M21, M22, M23, M24) ( 4, 5, 6, 7)
column3 (M31, M32, M33, M34) ( 8, 9, 10, 11)
column4 (M41, M42, M43, M44) (12, 13, 14, 15)
因此
q.x = (sgn(clipPlane.x) + matrix[8]) / matrix[0];
q.y = (sgn(clipPlane.y) + matrix[9]) / matrix[5];
q.z = -1.0F;
q.w = (1.0F + matrix[10]) / matrix[14];
必须翻译成:
Vector4 q = new Vector4
{
X = (sgn(clipPlane.X) + projectionMatrix.M31) / projectionMatrix.M11,
Y = (sgn(clipPlane.Y) + projectionMatrix.M32) / projectionMatrix.M22,
Z = -1.0f,
W = (1.0f + projectionMatrix.M33) / projectionMatrix.M43
};
and
```cpp
matrix[2] = c.x;
matrix[6] = c.y;
matrix[10] = c.z + 1.0F;
matrix[14] = c.w;
必须
projectionMatrix.M13 = c.X;
projectionMatrix.M23 = c.Y;
projectionMatrix.M33 = c.Z + 1.0f;
projectionMatrix.M43 = c.W;
如果你想要一个不对称的透视投影,然后考虑通过 Matrix4.CreatePerspectiveOffCenter
创建全投影矩阵。
public Matrix4 GetProjectionMatrix()
{
var offset_x = -0.0f;
var offset_y = -0.005f; // just for instance
var tan_fov_2 = Math.Tan(_fov / 2.0);
var near = 0.01f;
var far = 100.0f;
var left = -near * AspectRatio * tan_fov_2 + offset_x;
var right = near * AspectRatio * tan_fov_2 + offset_x;
var bottom = -near * tan_fov_2 + offset_y;
var top = near * tan_fov_2 + offset_y;
return Matrix4.CreatePerspectiveOffCenter(left, right, bottom, top, near, far);
}