Question

I was using glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) for alpha composing as the document said (and actually same thing was said in the Direct3D document).

Everything was fine at first, until I downloaded the result from GPU and made it a PNG image. The result alpha component is wrong. Before drawing, I had cleared the frame buffer with opaque black colour. And after I drew something semi-transparent, the frame buffer became semi-transparent.

Was it helpful?

Solution

Well the reason is obvious. With glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), we actually ignore the destination alpha channel and assume it always be 1. This is OK when we treat the frame buffer as something opaque.

But what if we need the correct alpha value? glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) and make the source premultiplied (premultiplied texture/vertex color or multiply the alpha component with alpha components before setting it to gl_FragColor).

glBlendFunc can only multiply the original color components with one factor, but alpha compositing needs the destination be multiplied with both one_minus_src_alpha and dst_alpha. So it must be premultiplied. We can't do the premultiplication in the frame buffer, but as long as the source and destination are both premultipied, the result is premultipied. That is, we first clear the frame buffer with any premultiplied color (for example: 0.5, 0.5, 0.5, 0.5 for 50% transparent white instead of 1.0, 1.0, 1.0, 0.5), and draw premultipied fragments on it with glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA), and we will have correct alpha channel in the result. But remember to undo the premultiplication if it is not desired for the final result

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top