简体   繁体   English

渲染具有透明度的纹理时,OpenGL不需要的像素

[英]OpenGL unwanted pixels when rendering a texture with transparency

I've been struggling with this problem for a while now. 我一直在努力解决这个问题。 When I use OpenGL to render 2D textures, which have transparency values on the transition between no transparency and some transparency, I get some annoying grey pixel which I assume are a product of pixel value interpolation. 当我使用OpenGL渲染2D纹理时,在无透明度和一些透明度之间的过渡上具有透明度值,我得到一些恼人的灰色像素,我认为这是像素值插值的产物。 Any ideas on how I can improve that? 关于如何改进的任何想法?

I'm attaching an image to exemplify what I'm talking about: 我附上一张图片来举例说明我在说什么: 红色箭头显示一些不需要的像素可见的部分

Not that I think it will make a difference but I'm using Qt to create a QGLWidget and C++. 不是我认为它会有所作为,但我正在使用Qt创建一个QGLWidget和C ++。

SOLVED: 解决了:

I've been trying to solve this problem for a while. 我一直试图解决这个问题。 I tried using images with pre-multiplied alpha channel, using separate blend functions for color and alpha... For me nothing worked, I've might have done it wrong, I don't know. 我尝试使用带有预乘Alpha通道的图像,使用单独的颜色和alpha混合函数...对我来说没有任何效果,我可能做错了,我不知道。 For me what worked was exporting the .png image with Anti-Aliasing: Type Optimized (Hinted) on Adobe Illustrator and using glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 对我来说,使用抗锯齿输出.png图像是有效的:在Adobe Illustrator上键入优化(提示)并使用glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

Hope this helps other people with the same problem :) 希望这有助于其他人有同样的问题:)

Thank you again for the awnsers. 再次感谢你的帮助。

Short answer: Nicol Bolas is right that you should investigate pre-multiplied alpha, and here's the math that explains why. 简短的回答:Nicol Bolas是对的,你应该研究预乘的alpha,这是解释原因的数学。

Why it won't work correctly 为什么它不能正常工作

Here's how things work with non-premultiplied alpha. 以下是非预乘alpha的工作原理。

When you composite a source texture with color and alpha (C S , α S ) onto a destination (C D , α D ), you get the formula: 当复合物的源纹理颜色和alpha(C S,αS)到目的地(C d,αd),则得到下式:

C = α S C S + (1 - α S ) C D C =αS(C S)+(1 - αS)C d

Now, if we have layer two textures, first (C 1 , α 1 ) and then (C 2 , α 2 ), we get the formula: 现在,如果我们有层两个纹理,第一(C 1,α1),然后(C 2,α2),我们得到下式:

C = α 2 C 2 + (1 - α 2 ) (α 1 C 1 + (1 - α 1 ) C D ) C =α2 C 2 +(1 - α2)(α1 C 1 +(1 - α1)C d)

If we want to do this in one step with a pre-composited texture, like the way you are rendering to a texture, we need to rearrange this formula to match the original formula: 如果我们想要使用预合成纹理一步完成此操作,就像渲染到纹理的方式一样,我们需要重新排列此公式以匹配原始公式:

C = (α 2 C 2 + (1 - α 2 ) α 1 C 1 ) + (1 - α 2 ) (1 - α 1 ) C D C =(α2 C 2 +(1 - α2)α1 C 1)+(1 - α2)(1 - α1)C d

α S C S = α 2 C 2 + (1 - α 2 ) α 1 C 1 αS(C S)=α2 C 2 +(1 - α2)α1 C 1

(1 - α S ) C D = (1 - α 2 ) (1 - α 1 ) C D (1 - αS)C d =(1 - α2)(1 - α1)C d

We can solve for α S : 我们可以解决αS

α S = 1 - (1 - α 1 ) (1 - α 2 ) = α 1 + α 2 - α 1 α 2 αS = 1 - (1 - α1)(1 - α2)=α1 +α2 - α1α2

But when we then solve for C S : 但是当我们解决C S时

C S = (α 2 C 2 + (1 - α 2 ) α 1 C 1 ) / (α 1 + α 2 - α 1 α 2 ) (C S)=(α2 C 2 +(1 - α2)α1 C 1)/(α1 +α2 - α1α2)

There's no OpenGL blending mode that lets us calculate C S correctly. 没有OpenGL混合模式可以让我们正确计算C S.

What if alpha is pre-multiplied? 如果alpha预乘的怎么办?

The formula for pre-multiplied alpha blending is different: 预乘Alpha混合的公式是不同的:

C = C S + (1 - α S ) C D C = C S +(1- αS )C D.

With two textures, 有两个纹理,

C = C 2 + (1 - α 2 ) (C 1 + (1 - α 1 ) C D ) C = C 2 +(1 - α2)(C 1 +(1 - α1)C d)

When we rearrange to match the first formula, we get: 当我们重新排列以匹配第一个公式时,我们得到:

C = C 2 + (1 - α 2 ) C 1 + (1 - α 2 ) (1 - α 1 ) C D C = C 2 +(1 - α2)C 1 +(1 - α2)(1 - α1)C d

Then we solve: 然后我们解决:

α S = 1 - (1 - α 1 ) (1 - α 2 ) = α 1 + α 2 - α 1 α 2 αS = 1 - (1 - α1)(1 - α2)=α1 +α2 - α1α2

C S = C 2 + (1 - α 2 ) C 1 (C S)= C 2 +(1 - α2)C 1

This is just the same as: 这与以下内容相同:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

So, if you use pre-multiplied alpha for all of your textures, then all the math works out perfectly, and you don't have to worry about this stuff. 所以,如果你对所有纹理使用预乘的alpha,那么所有数学运算都很完美,你不必担心这些东西。 Just use that same blend function everywhere, use pre-multiplied alpha everywhere, and you can composite things in any order you like. 只需在任何地方使用相同的混合功能,在任何地方使用预乘的alpha,你可以按照自己喜欢的任何顺序组合。

Pre-multiplied alpha also interpolates correctly, which is not true of non-premultiplied alpha, but this is a separate issue. 预乘的alpha也会正确插值,而非预乘的alpha则不然,但这是一个单独的问题。

Summary 摘要

The pre-multiplied composition operator is associative which means that you can take a bunch of layers and squash them into one texture, exactly the way you want. 预乘的合成运算符是关联的 ,这意味着你可以采用一堆图层并将它们压缩成一个纹理,完全按照你想要的方式。

Without pre-multiplied alpha, the math doesn't work out the way you want. 如果没有预先乘以的alpha,数学就不会按照你想要的方式运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM