2016-01-20 70 views
3

我已经设置了一个测试项目来学习iOS上的Metal来做一些渲染,但是我对如何使棱镜正确地围绕其y轴旋转有点困难。为什么在iOS Metal中旋转这个棱镜不能正确渲染?

这里是没有深度的测试渲染棱镜使各方可以看到,所以它看起来像这部分至少是正确的:

enter image description here

这些顶点:

static const float vertexData[] = { 
    0.f, 1.f, 0.5f, 
    1.f, -1.f, 0.f, 
    -1.f, -1.f, 0.f, 

    0.f, 1.f, 0.5f, 
    1.f, -1.f, 1.f, 
    1.f, -1.f, 0.f, 

    0.f, 1.f, 0.5f, 
    -1.f, -1.f, 1.f, 
    1.f, -1.f, 1.f, 

    0.f, 1.f, 0.5f, 
    -1.f, -1.f, 0.f, 
    -1.f, -1.f, 1.f 
}; 

但是,当我打开旋转时,会发生以下情况:https://www.dropbox.com/s/esg41j3ibncofox/prism_rotate.mov?dl=0

(视频已转向深度测试 上)。为什么棱镜像这样剪切(和/或剪切的是什么)?它并没有围绕它的中心旋转。

下面是如何被计算的MVP矩阵:

static simd::float3 viewEye = {0.f, 0.f, -2.f}; 
static simd::float3 viewCenter = {0.f, 0.f, 1.f}; 
static simd::float3 viewUp = {0.f, 1.f, 0.f}; 
static float fov = 45.f; 

CGSize size = self.view.bounds.size; 
Uniforms *uniforms = (Uniforms *)[uniformBuffer contents]; 
uniforms->view = AAPL::lookAt(viewEye, viewCenter, viewUp); 
uniforms->projection = AAPL::perspective_fov(fov, size.width, size.height, 0.1f, 100.f); 

uniforms->model = AAPL::translate(0.f, 0.f, 12.f) * AAPL::rotate(tAngle, 0.f, 1.f, 0.f); 
tAngle += 0.5f; 

transformlookAtrotate,和perspective_fov功能直接从我用作参考苹果示例代码解除。

这里是着色器:

typedef struct { 
    float4 pos [[ position ]]; 
    half4 color; 
    float mod; 
} VertexOut; 

vertex VertexOut basic_vertex(const device packed_float3* vertex_array [[ buffer(0) ]], 
           const device packed_float3* colors [[ buffer(1) ]], 
           constant Uniforms& uniform [[ buffer(2) ]], 
           uint vid [[ vertex_id ]], 
           uint iid [[ instance_id ]]) 
{ 
    float4 v = float4(vertex_array[vid], 1.f); 
    float4x4 mvp_matrix = uniform.projection * uniform.view * uniform.model; 

    VertexOut out; 
    out.pos = v * mvp_matrix; 
    uint colorIndex = vid/3; 
    out.color = half4(half3(colors[colorIndex]), 1.f); 
    return out; 
} 

fragment half4 basic_fragment(VertexOut f [[ stage_in ]]) { 
    return f.color; 
} 

任何帮助/提示将不胜感激。

回答

2

感叹.. 问题在于MVP矩阵与着色器中顶点的乘法顺序。

所以这个:

out.pos = v * mvp_matrix; 

应该是:

out.pos = mvp_matrix * v; 

无论出于何种原因,我已经习惯了行向量而不是列向量,并有自己相信我误解的东西有关剪辑区域和/或矩阵本身。