我正在尝试在我的 Metal 片段着色器中实现一些简单的抖动,以摆脱渐变中的条带。它不起作用,我想知道这是否只是一个错误,或者传递给着色器的颜色值是否已经量化(如果这是正确的词)到 8 位。换句话说,片段着色器处理浮点值,但这些值是否已经处于 8 位 rgb 空间强加的离散级别?
这是我的着色器和我用于抖动的矩阵。我基于以下两篇文章/帖子:
http://www.anisopteragames.com/how-to-fix-color-banding-with-dithering/
var dither_pattern:[UInt8] =
[0, 32, 8, 40, 2, 34, 10, 42, /* 8x8 Bayer ordered dithering */
48, 16, 56, 24, 50, 18, 58, 26, /* pattern. Each input pixel */
12, 44, 4, 36, 14, 46, 6, 38, /* is scaled to the 0..63 range */
60, 28, 52, 20, 62, 30, 54, 22, /* before looking in this table */
3, 35, 11, 43, 1, 33, 9, 41, /* to determine the action. */
51, 19, 59, 27, 49, 17, 57, 25,
15, 47, 7, 39, 13, 45, 5, 37,
63, 31, 55, 23, 61, 29, 53, 21]
// this array is passed to the frag shader via a MTLBuffer
fragment float4 window_gradient_fragment(WindowGradientVertexOut interpolated [[stage_in]],
const device unsigned char* pattern [[ buffer(0) ]]) {
int x = (int)interpolated.position.x % 8;
int y = (int)interpolated.position.y % 8;
int val = pattern[x+y*8];
float bayer = 255.0 * (float)val / 64.0;
const float rgbByteMax = 255.0;
float4 rgba = rgbByteMax*interpolated.color;
float4 head = floor(rgba);
float4 tail = rgba-head;
float4 color = head+step(bayer,tail);
return color/255.0;
}
我通过将矩阵更改为一系列交替的 0,63 对来测试这一点,并且近距离观察它确实每隔一个像素产生微弱的垂直条纹。但据我所知,整体乐队保持不变。这让我认为,当它到达片段着色器时,条带已经“内置”了。所以对它应用抖动并没有真正的帮助,因为损害已经造成。我希望这不是真的……这是我天真的假设,因为颜色是浮点数,它们将具有完整的浮点精度,并且在片段着色器之后会发生到 8 位的转换。