我已经获得了以下着色器(为了长度和清晰度而移除了碎片),并希望找到更好的方法来执行此操作。我想将一个大小可变的纹理数组发送到我的金属着色器。我将对顶点位置进行一些计算,然后确定要使用的纹理。
目前我只是硬编码并使用了几个if语句,但这很难看(而且我猜不快)。我有什么方法可以计算i
,然后使用i
作为纹理下标(如tex[i].sample
)?
// Current code - its ugly
fragment half4 SimpleTextureFragment(VertextOut inFrag [[stage_in]],
texture2d<half> tex0 [[ texture(0) ]]
texture2d<half> tex1 [[ texture(1) ]]
texture2d<half> tex2 [[ texture(2) ]]
...
texture2d<half> texN [[ texture(N) ]]
)
{
constexpr sampler quad_sampler;
int i = (Compute_Correct_Texture_to_Use);
if(i==0)
{
half4 color = tex0.sample(quad_sampler, inFrag.tex_coord);
}
else if(i==1)
{
half4 color = tex1.sample(quad_sampler, inFrag.tex_coord);
}
...
else if(i==n)
{
half4 color = texN.sample(quad_sampler, inFrag.tex_coord);
}
return color;
}
答案 0 :(得分:2)
你的方法不会很快你是对的。最好的情况是,着色器将有很多分支(这是不好的),更糟糕的情况下,着色器实际上将从所有纹理中采样,然后丢弃它不使用的结果(这将更慢)。
这不是GPU处理得特别好的情况,所以我的建议是稍微重构你的方法以更加GPU友好。如果不了解更多关于你在更高层次上做了什么,我的第一个建议是考虑使用 2d数组纹理。
2d数组纹理基本上将X 2D纹理合并到具有X切片的单个纹理中。您只需要将单个纹理传递给Metal,您就可以完全按照您的方式计算着色器中要采样的切片,但是使用这种方法,您将摆脱所有&#39; if&#39;分支,只需要像这样调用一次样本:tex.sample( my_sampler, inFrag.tex_coord, i );
如果您的纹理大小和格式都相同,那么这将非常容易。您只需将每个2D纹理复制到数组纹理的切片中即可。如果您的纹理大小或格式不同,您可能需要通过拉伸一些来解决这些问题,以便它们都以相同的尺寸结束。
请点击此处查看文档:{{3}} (寻找&#39;纹理切片&#39;)
此处使用金属着色器语言文档:https://developer.apple.com/library/prerelease/ios/documentation/Metal/Reference/MTLTexture_Ref/index.html#//apple_ref/c/econst/MTLTextureType2DArray(查找&#39; 2D纹理数组&#39;)