金属法线不插值

Metal normal doesn't interpolate

我一直在学习 Metal 如何使用 Swift 和针对 macOS 的工作原理。事情一直很顺利,但是现在,接近完成的时候,我遇到了一个我无法理解的问题......我希望你们能帮助我:)

我正在加载并显示一个 OBJ 茶壶,我正在使用环境光+漫反射+镜面光对其进行照明。照明本身效果很好,但问题是:在进入片段着色器时,法向量没有被插值,这导致在假定的曲面上有平面照明......不好......

我真的不明白为什么不对法线进行插值而对其他值(位置 + 眼睛)进行插值...这是我的着色器和显示结果的图像:

提前致谢:)

struct Vertex
{
    float4 position;
    float4 normal;
};

struct ProjectedVertex
{
    float4 position [[position]];
    float3 eye;
    float3 normal;
};

vertex ProjectedVertex vertex_project(device Vertex *vertices [[buffer(0)]],
                                      constant Uniforms &uniforms [[buffer(1)]],
                                      uint vid [[vertex_id]])
{
    ProjectedVertex outVert;
    outVert.position = uniforms.modelViewProjectionMatrix * vertices[vid].position;
    outVert.eye =  -(uniforms.modelViewProjectionMatrix * vertices[vid].position).xyz;
    outVert.normal = (uniforms.modelViewProjectionMatrix * float4(vertices[vid].normal)).xyz;

    return outVert;
}

fragment float4 fragment_light(ProjectedVertex vert [[stage_in]],
                               constant Uniforms &uniforms [[buffer(0)]])
{
    float3 ambientTerm = light.ambientColor * material.ambientColor;

    float3 normal = normalize(vert.normal);
    float diffuseIntensity = saturate(dot(normal, light.direction));
    float3 diffuseTerm = light.diffuseColor * material.diffuseColor * diffuseIntensity;

    float3 specularTerm(0);
    if (diffuseIntensity > 0)
    {
        float3 eyeDirection = normalize(vert.eye);
        float3 halfway = normalize(light.direction + eyeDirection);
        float specularFactor = pow(saturate(dot(normal, halfway)), material.specularPower);
        specularTerm = light.specularColor * material.specularColor * specularFactor;
    }

    return float4(ambientTerm + diffuseTerm + specularTerm, 1);
}

screenshot

所以问题是使用 OBJ-C,当我从 OBJ 文件中索引顶点时,我只为表面之间的共享顶点生成了 1 个顶点,所以我只保留了 1 个法线。

将它翻译成swift时,我用来检查顶点是否与我已有的相同位置的散列值是错误的,无法检测到共享顶点,这导致保留所有的法线,所以每个表面都是平坦的。

我不知道我是否足够清楚,但这就是发生的事情,为了将来参考,这个问题是关于制作 "metalbyexample" 书的 Swift 版本的,它只是 Obj-C .