菜鸟教程小白 发表于 2022-12-12 16:30:36

ios - 在 iOS Metal 中透视正确的纹理映射


                                            <p><p>我尝试了各种方法来进行插值工作并生成透视正确的图像,但建议的方法都不起作用。</p>

<p>我当前的代码是:</p>

<pre><code>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.x, vertices.y, 0.0, 127.0);

return outVertices;
}

fragment half4 testFragment(VertexStruct inFrag [[ stage_in ]],
                            texture2d&lt;half, access::sample&gt; 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);
}
</code></pre>

<p>纹理为 128x128,顶点为:</p>

<ul>
<li>0,0</li>
<li>0,127</li>
<li>127,0</li>
<li>127,127</li>
</ul>

<p>理论上,第 4 个参数 <code>w</code> 应该有助于透视正确插值。据报道,此技巧可在 OpenGL ES 中使用,但就我而言,无论我是否拥有它,都不会发生任何变化。</p>

<p>我得到的是:</p>

<p> <a href="/image/cFEHC.png" rel="noreferrer noopener nofollow"><img src="/image/cFEHC.png" alt="enter image description here"/></a> </p>

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

<p> <a href="/image/IvtF8.png" rel="noreferrer noopener nofollow"><img src="/image/IvtF8.png" alt="enter image description here"/></a> </p>

<p>这意味着渲染的两个三角形没有通过透视正确采样读取纹理。这是纹理映射的经典问题,但我无法理解。</p>

<p>任何人都可以看到错误吗?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>透视正确的纹理映射已经成为十多年的规范,并且被每个图形 API 默认使用,尤其是 Metal。你不需要做任何事情来获得正确的结果,<em>只要你没有在你的设置中做一些完全错误的事情</em>。</p>

<p>事实上,Metal 允许您直接在 MSL 中指定插值和采样。 <strong>默认情况下</strong>,所有内容都使用 <code>center_perspective</code> 限定符(像素中心、透视正确插值,但位置明显异常(exception),即 <code>center_no_perspective</code>。</code> p>

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

<pre><code>struct Fragment {

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

};
</code></pre>

<p>至于您的其他选项,它基本上是 center/centroid/sample 和 perspective/no_perspective 组合,以及 <code>flat</code> (没有插值,显然是整数)。在列表中,它看起来像:</p>

<ul>
<li><code>[[ flat ]]</code> 无插值,整数成员。</li>
<li><code>[[ center_perspective ]]</code> 居中,透视正确<strong>(默认)</strong></li>
<li><code>[[ center_no_perspective ]]</code> 中心,线性 <strong>(默认位置)</strong></li>
<li><code>[[ centroid_perspective ]]</code> 质心,透视正确</li>
<li><code>[[ centroid_no_perspective ]]</code>质心,线性</li>
<li><code>[[ sample_perspective ]]</code>示例,透视正确*</li>
<li><code>[[ sample_no_perspective ]]</code> 样本,线性*</li>
</ul>

<p><strong>警告:</strong> <code>sample_*</code> 限定符将使片段函数按样本执行,而不是通常按片段执行。去亚像素是一个潜在的性能危险信号,所以在必要时使用。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 在 iOS Metal 中透视正确的纹理映射,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/33048343/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/33048343/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 在 iOS Metal 中透视正确的纹理映射