Separate alpha blend enable states for MRT

Started by
12 comments, last by eigers 15 years, 5 months ago
What about premultiplied alpha ?

RT1 : I want src to be multiplied by alpha and dst to be multiplied by 1-alpha and both be added together : final1 = (1-alpha1) * dstcolor1 + alpha1 *srccolor1
RT2 : I want src to be overwritten over dst : final2 = 1 * srccolor2 + 0 * dstcolor2

As a blend op you take D3DOP_ADD obviously.
As blend source you take D3DBLEND_ONE (<- important in the premultiplied alpha case)
As blend dest you take D3DBLEND_INVSRCALPHA

when you write color 0 in your pixel shader you do :
mul r0.rgb, r0.rgbb, r0.aaaa
mov oC0, r0

Assuming ro.aaaa contained alpha1 and r0.rgb contained srcColor1.rgb
oC0.rgb then contains srccolor1.rgb * alpha1
oC0.a then contains alpha1
the result of the equation is oC0.rgba * ONE + destcolor1 * (1 - oC0.a)
or srcColor1.rgb * alpha1 + destcolor1.rgb * (1 - alpha1) which is what you wanted.

when you write color 1 you :
mov r1.a, constant(1.0,1.0,1.0,1.0)
mov oC1, r1

oC1.rgb contains srcColor2.rgb
oC1.a contains 1
the result of the equation is oC1.rgb * ONE + destcolor2 * (1 - oC1.a)
or srcColor2.rgb + destColor2.rgb * 0 which is also what you wanted.

The only problem with this approach obviously is that you've replaced the alpha value. But that's a general problem with blending is that it always assume the fourth channel of anything is going to be the blending factor (and that is also true for single RT case) which means in alpha blending situations you can only effectively write 3 components at a time per rendertarget.. Use more RTs (in MRT mode) if you want to write more.

LeGreg
Advertisement
Thanks for this interseting idea.

However, as ET3D pointed out, each RT is blended with its own alpha, so I don't really have a problem with the SRCALPHA/INVSRCALPHA type of blending. I just set the source alpha to 1 when writing to oC1, and so the destination is overwritten.
My problem is with blending states where the factor of the destination color is not related to the source at all (such as D3DRS_DESTBLEND = D3DBLEND_ONE), which are generally used for glowing effects. I don't see how I can overcome this without knowing the current destination color, which of course I can't. Am I'm missing something here?
Quote:Original post by eigers
However, as ET3D pointed out, each RT is blended with its own alpha, so I don't really have a problem with the SRCALPHA/INVSRCALPHA type of blending. I just set the source alpha to 1 when writing to oC1, and so the destination is overwritten.
My problem is with blending states where the factor of the destination color is not related to the source at all (such as D3DRS_DESTBLEND = D3DBLEND_ONE), which are generally used for glowing effects. I don't see how I can overcome this without knowing the current destination color, which of course I can't. Am I'm missing something here?


Didn't I just tell you how ? Sorry if that wasn't clear..

The problem you had was that you were using SRCALPHA/INVSRCALPHA, where what you wanted was the premultiplied alpha.

If you want to replace, you set output alpha to one (without changing the source color). If you want to add (src+dst as in the glow effect) you output alpha to zero : that way dest is multiplied by (1-zero) before being added to the srccolor (that you don't modify either). You can also emulate the srcalpha/invsrcalpha case by premultiplying (hence the premultiplied alpha name) the srccolor by the alpha before outputing it.

A thing that doesn't work with this approach is if you want different alpha per channel to affect the dest color before combining (say dest.r * (1- alpha1), dest.g * (1 - alpha2), dest.b * (1 - alpha3) ). Well that level would require an extra color being output and used in the blend equation, which is only possible in dual blend mode using the Direct3D10 API.

LeGreg
ahm... I see it now, sorry for being a little slow.
Thanks a lot.

Shai.

This topic is closed to new replies.

Advertisement