为什么我在 libGDX 中的纹理上变黑 outlines/edges?

Why do I get black outlines/edges on a texture in libGDX?

每当我绘制边缘周围有 alpha 的纹理(它被 photoshop 抗锯齿)时,这些边缘就会变暗。我无休止地使用纹理过滤器和混合模式,但没有成功。

我的意思是:

minFilter: Linear magFilter: Linear

minFilter: MipMapLinearNearest magFilter: Linear

minFilter: MipMapLinearLinear magFilter: Linear

如您所见,更改 libGDX Texture Packer 上的过滤器会对外观产生很大影响,但 alpha 仍然黑暗.

我尝试在 libgdx 中手动设置纹理过滤器:

texture.setFilter(minFilter, magFilter);

但这不起作用。

我听说使用线性滤镜进行缩小会导致 alpha 像素默认为黑色?如果是这样,我该如何避免呢?

我也试过改变混合模式:glBlend(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_APHA)没有区别。 glBlend(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) 完全删除了 alpha,所以这不起作用。

不想 想将我的 minFilter 设置为 Nearest,因为它让事情看起来非常像素化。我已经尝试了所有其他的纹理过滤器组合,但所有结果都是相同的 black/dark edges/outline 效果。

I have read that downscaling with a linear filter causes the alpha pixels to default to black?

这不一定是真的;这取决于 Photoshop 决定在 完全透明 像素中放入什么颜色。显然你的情况是黑色的。

出现问题是因为 GPU 正在两个相邻像素之间进行插值,其中一个像素是完全透明的(所有颜色通道也都设置为零)。假设另一个像素是鲜红色:

(255,   0,   0, 255)  // Bright red, fully opaque
(  0,   0,   0,   0)  // Black, fully transparent

以 50/50 的比率进行插值得到:

(128,   0,   0, 128)

这是一个半不透明的 深红色 像素,这解释了您看到的暗条纹。

有两种可能的解决方案。

1。向透明区域添加出血

确保为完全透明的像素分配了正确的颜色;基本上 "bleed" 从最近的非透明像素到相邻的完全透明像素的颜色。我不确定 Photoshop 可以做到这一点,但 libGDX TexturePacker 可以;见bleed and bleedIterations settings。您需要注意将 bleedIterations 设置得足够高, 添加足够的填充以使出血扩展到您的特定缩小级别。

现在例子出来是这样的:

(255,   0,   0, 255)
(255,   0,   0,   0)  // Red bled into the transparent region

插值现在根据需要提供明亮的红色透明像素:

(255,   0,   0, 128)

2。使用预乘 alpha

要做到这一点并不那么挑剔,但它有助于准确了解您在做什么。 TexturePacker 再次为您提供 premultipliedAlpha 设置。这是 OpenGL 混合模式 glBlend(GL_ONE, GL_ONE_MINUS_SRC_ALPHA).

示例中的数字不变;这还是出来的像素:

(128,   0,   0, 128)

但是,这不再被解释为 "half-transparent dark red",而是 "add some red, and remove some background"。更一般地说,对于预乘 alpha,颜色通道不是 "which colour to blend in" 而是 "how much colour to add".

请注意,像 (255, 0, 0, 0) 这样的像素不能再存在于源纹理中:因为 alpha 是预乘的,所以 alpha 为零自动意味着所有颜色通道也必须为零。 (如果你想变得非常花哨,你甚至可以使用这样的像素来应用 additive 混合在相同的渲染通道和相同的纹理中作为常规混合!)

进一步阅读预乘 alpha:

我通过将 Texture Packer Pro 上的过滤从线性更改为 MipMap

解决了这个问题