OpenGL unwanted pixels when rendering a texture with transparency

最后都变了- 提交于 2019-12-22 10:26:26

问题


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. 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++.

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. 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)

Hope this helps other people with the same problem :)

Thank you again for the awnsers.


回答1:


Short answer: Nicol Bolas is right that you should investigate pre-multiplied alpha, and here's the math that explains why.

Why it won't work correctly

Here's how things work with non-premultiplied alpha.

When you composite a source texture with color and alpha (CS, αS) onto a destination (CD, αD), you get the formula:

C = αS CS + (1 - αS) CD

Now, if we have layer two textures, first (C1, α1) and then (C2, α2), we get the formula:

C = α2 C2 + (1 - α2) (α1 C1 + (1 - α1) CD)

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 C2 + (1 - α2) α1 C1) + (1 - α2) (1 - α1) CD

αS CS = α2 C2 + (1 - α2) α1 C1

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

We can solve for αS:

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

But when we then solve for CS:

CS = (α2 C2 + (1 - α2) α1 C1) / (α1 + α2 - α1 α2)

There's no OpenGL blending mode that lets us calculate CS correctly.

What if alpha is pre-multiplied?

The formula for pre-multiplied alpha blending is different:

C = CS + (1 - αS) CD

With two textures,

C = C2 + (1 - α2) (C1 + (1 - α1) CD)

When we rearrange to match the first formula, we get:

C = C2 + (1 - α2) C1 + (1 - α2) (1 - α1) CD

Then we solve:

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

CS = C2 + (1 - α2) C1

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. Just use that same blend function everywhere, use pre-multiplied alpha everywhere, and you can composite things in any order you like.

Pre-multiplied alpha also interpolates correctly, which is not true of non-premultiplied alpha, but this is a separate issue.

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.



来源:https://stackoverflow.com/questions/34747667/opengl-unwanted-pixels-when-rendering-a-texture-with-transparency

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!