在iOS Metal中透视正确的纹理贴图

时间:2015-10-09 23:01:39

标签: ios opengl-es 3d texture-mapping metal

我尝试了各种方法来进行插值工作并生成透视正确的图像,但没有一种建议的方法有效。

我目前的代码是:

struct VertexStruct
{
  float4 normalizedPosition [[ position ]];
  float4 texCoord;
}

vertex VertexStruct testVertex(device float4 *vertices [[ buffer(0) ]],
                                     uint vid [[ vertex_id ]])
{
  VertexStruct outVertices;

  outVertices.normalizedPosition = ...;

  outVertices.texCoord = float4(vertices[vid].x, vertices[vid].y, 0.0, 127.0);

  return outVertices;
}

fragment half4 testFragment(VertexStruct inFrag [[ stage_in ]],
                            texture2d<half, access::sample> volume [[ texture(0) ]])
{
  float2 texCoord = float2(inFrag.texCoord.xy * (1.0 / inFrag.texCoord.w));
  constexpr sampler s(coord::normalized, filter::linear, address::clamp_to_zero);
  return volume.sample(s, texCoord);
}

纹理为128x128,顶点为:

  • 0,0
  • 0127
  • 127,0
  • 127127

理论上,第4个参数w应该有助于透视正确插值。据报道,这个技巧在OpenGL ES中有效,但在我的情况下,如果我有或没有,没有任何变化。

我得到的是:

enter image description here

蓝色是清晰的颜色,而黑色梯形内的任何东西都是纹理的内容。红色梯形应位于黑色梯形的中心。如果你用Photoshop打开它并追踪黑色梯形的对角线,它将完全正确地通过红色梯形的对角线。

enter image description here

这意味着渲染的两个三角形不会使用透视正确采样读取纹理。这是纹理映射的经典问题,但我无法理解它。

有人能看到错误吗?

1 个答案:

答案 0 :(得分:2)

透视 - 正确的纹理映射已经成为十多年的标准,并且默认为每个图形API,尤其是Metal。您不必做任何事情来获得透视正确的结果,只要您在设置中没有完全出错。

实际上,Metal允许您直接在MSL中指定插值和采样。 默认,所有内容都使用center_perspective限定符(像素中心,透视正确插值,明显例外的位置为center_no_perspective

鉴于从光栅化器到您的片段函数的数据是stage_in,您只需在MSL代码中直接声明成员后添加所需的采样/插值限定符,就像任何其他属性一样。显式详细规范的示例:

struct Fragment {

    float4 position             [[ center_no_perspective ]];    // Default, can be omitted.
    float4 specialTreatment     [[ centroid_perspective ]];     // Let's say you need centroid + perspective correct.
    float2 textureCoordinates   [[ center_perspective ]];       // Default, can be omitted.

};

至于你的其他选项,它基本上是中心/质心/样本和透视/ no_perspective组合,以及flat(没有插值,显然是整数)。在列表中,它看起来像:

  • [[ flat ]]没有插值,整数成员。
  • [[ center_perspective ]]中心,透视正确(默认)
  • [[ center_no_perspective ]]中心,线性(位置默认)
  • [[ centroid_perspective ]] Centroid,perspective-correct
  • [[ centroid_no_perspective ]] Centroid,linear
  • [[ sample_perspective ]]示例,透视正确*
  • [[ sample_no_perspective ]]示例,线性*

警告: sample_*限定符将使每个样本执行片段函数,而不是通常的每个片段。转子像素是潜在的性能红旗,因此必要时使用。