虽然这是对计算着色器的不恰当使用,但我正在做一些实验,以确定是否可以使用一个来生成一般的UV渐变,其中图像的一个通道在x轴上从0到0线性地线性化通道在图像的y轴上从0到0。然而,当我通过thread_position_in_grid.x值除以图像宽度来改变纹理的b值来生成此图像时,我感到困惑。我在thread_position_in_grid位置编辑了纹理的像素:
是的,这是一个渐变,但它似乎并不是我想要的0-1的渐变。我将它放入图像编辑器中,确定它不是线性的。 (下面添加的部分显示了0-1的线性渐变)
似乎我不明白thread_position_in_grid值究竟是什么意思。我知道它与每个线程组和线程执行宽度的线程有关,但我不完全明白什么。我想我的最终目标是知道是否可以在计算着色器中生成下面的渐变,但我不明白发生了什么。
作为参考,我正在使用100x100纹理,并具有以下线程设置。真的我不知道为什么我使用这些值,但这是我在某处看到的推荐,所以我坚持使用它们。我希望能够将这个问题概括为其他纹理大小,包括矩形。
let w = greenPipeline.threadExecutionWidth
let h = greenPipeline.maxTotalThreadsPerThreadgroup / w
let threadsPerThreadgroup = MTLSizeMake(w, h, 1)
let threadgroupsPerGrid = MTLSize(width: (texture.width + w - 1) / w,
height: (texture.height + h - 1) / h,
depth: 1)
encoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup)
我的着色器看起来像这样:
kernel void green(texture2d<float, access::write> outputTexture [[texture(0)]],
uint2 position [[thread_position_in_grid]])
{
if (position.x >= outputTexture.get_width() || position.y >= outputTexture.get_height()) {
return;
}
outputTexture.write(float4(position.x / 100.0, 0.0, 0.0, 0.0), position);
}
关于这个着色器的两件事让我感到困惑,因为我无法解释它们:
position.x / 100.0
重新设置position.x / outputTexture.getWidth()
值,即使它也应该是100.这样做会导致黑色图像。然而,当我制作一个使用outputTexture.getWidth()作为其值对所有颜色进行着色的着色器时,确实将所有颜色都设置为相当于100的值(或者因为四舍五入而更准确地为101)发生了什么事?
答案 0 :(得分:0)
thread_position_in_grid
表示您想要它的意思,因为您决定网格的大小以及网格中每个线程的作用。
在您的示例中,thread_position_in_grid
是纹理中的像素坐标,因为您的网格大小等于纹理中的像素数(向上舍入到管道的最大线程执行宽度的倍数)。
如果您将threadGroupsPerGrid
更改为:
let threadgroupsPerGrid = MTLSize(width: (texture.width/2 + w - 1) / w,
height: (texture.height/2 + h - 1) / h,
depth: 1)
现在只应填充纹理的前四分之一,因为网格只覆盖纹理宽度和高度的一半。
至于为什么你的纹理看起来很怪异,它可能与像素格式有关。毕竟,你正在写入红色组件,你的纹理会变成蓝色。