金属:使用正交投影矩阵时无任何渲染

时间:2016-03-29 21:23:01

标签: ios graphics metal

我使用以下代码创建正交矩阵:

Matrix4D Matrix4D::fromOrtho(double left, double right, double bottom, double top, double nearZ, double farZ)
{
    double ral = right + left;
    double rsl = right - left;
    double tab = top + bottom;
    double tsb = top - bottom;
    double fan = farZ + nearZ;
    double fsn = farZ - nearZ;

    return Matrix4D ( 2.0f / rsl, 0.0f, 0.0f, 0.0f,
                     0.0f, 2.0f / tsb, 0.0f, 0.0f,
                     0.0f, 0.0f, -2.0f / fsn, 0.0f,
                     -ral / rsl, -tab / tsb, -fan / fsn, 1.0f);
}

并使用以下参数:

double widthToHeightRatio = screenWidth / screenHeight;
Matrix4D::fromOrtho(-10, 10, -7, 7 ,0.1, 5000);

左,右,底部和顶部参数实际上是根据摄像机眼睛和中心坐标计算的,但这是结果参数的示例。

相同的矩阵适用于OpenGL但不适用于Metal。当矩阵是透视矩阵时,一切也都适用于Metal。

可能是什么问题?

2 个答案:

答案 0 :(得分:0)

GL的透视和正投影矩阵在Metal中都是无效的,因为z范围不同。有些矩阵可能仍然可以工作,因为你的z-clip范围在OpenGL中过于深,所以它恰好足以让碎片在Metal中通过,但是这是一件坏事。

从金属编程指南,p。 51“使用视口和像素空间坐标”:

  

Metal将其规范化设备坐标(NDC)系统定义为   2x2x1立方体,其中心位于(0,0,0.5)。 x的左下角   NDC系统和y分别指定为-1。正确的   NDC系统的x和y的顶部和顶部分别指定为   1。

这与OpenGL不同,OpenGL的z从-1到1,在2x2x2矩阵中。

有关详细信息,请参阅此博客文章:http://blog.athenstean.com/post/135771439196/from-opengl-to-metal-the-projection-matrix

更新 - 用户da1找到了一个替代博文,上面的内容目前已关闭:http://metashapes.com/blog/opengl-metal-projection-matrix-problem

答案 1 :(得分:0)

来自AAPLTransfomations.mm这对我有用(金属样本项目)

simd::float4x4 AAPL::ortho2d(const float& left,
                             const float& right,
                             const float& bottom,
                             const float& top,
                             const float& near,
                             const float& far)
{
    float sLength = 1.0f / (right - left);
    float sHeight = 1.0f / (top   - bottom);
    float sDepth  = 1.0f / (far   - near);

    simd::float4 P;
    simd::float4 Q;
    simd::float4 R;
    simd::float4 S;

    P.x = 2.0f * sLength;
    P.y = 0.0f;
    P.z = 0.0f;
    P.w = 0.0f;

    Q.x = 0.0f;
    Q.y = 2.0f * sHeight;
    Q.z = 0.0f;
    Q.w = 0.0f;

    R.x = 0.0f;
    R.y = 0.0f;
    R.z = sDepth;
    R.w = 0.0f;

    S.x =  0.0f;
    S.y =  0.0f;
    S.z = -near  * sDepth;
    S.w =  1.0f;

    return simd::float4x4(P, Q, R, S);
} // ortho2d

并通过传递到

中的着色器来实现
constant_buffer[i].modelview_ortho_matrix = ortho2d(-2.0f, 2.0f, -2.0f, 2.0f, 0, 2); //_projectionMatrix * modelViewMatrix;

然后可能在您的顶点着色器

float4 in_position = float4(float3(vertex_array[vid].position), 1.0);
out.position = constants.modelview_ortho_matrix * in_position;