Blending black area invisible

Started by
3 comments, last by Juliean 10 years, 6 months ago

I am currently stuck with a blending problem.

Basically I am having a lot of billboards each with an image and some black space around that image. All I want is to replace that black color with whatever is in the background so that it becomes invisible.

Original billboard image:

smiley.jpg

Background:

background.jpg

Expected result:

result_expected.jpg

Yet I have tried everything I could imagine with my BlendStateDescription, DepthStencil and BlendFactor. Nothing bringt me to my expected result.

Without blending I get the following result: (As expected)

result_no_blending.jpg

With :


blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
Or:

blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
I get:
result_add.jpg
As stated earlier I have tried a hundred other combinations. Nothing successful yet.
Also I thought when I set my BlendFactor to {0.0f, 0.0f, 0.0f, 0.0f) it would handle the black color as my alpha channel. But it aparently does not. Actually nothing I do with SrcBlendAlpha, DestBlendAlpha and BlendOpAlpha has ANY effect.
Advertisement

Alpha masking (D3D11_BLEND_SRC_ALPHA and companions) requires an alpha channel provided by the billboard. From your description it isn't clear whether such a channel is available .. the OP mentioned to use the black color as mask. What is the case?

Although not familiar with D3D, I would expect


blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
to work in case that the billboard provides an alpha (where alpha = 0 means full transparency), and the billboard isn't pre-multiplied by alpha. This does a calculation like so:
colordest := ( 1 - alphasrc ) * colordest + alphasrc * colorsrc
If, on the other hand, the billboard is pre-multiplied, then

blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;

should do the job:

colordest := ( 1 - alphasrc ) * colordest + 1 * colorsrc,pre

blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_ONE; blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;

This setting achieves something called aditive blending, where both your new image and the content of the background are added together, to achieve the final color. It should work with:


blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_SRCALPHA;
blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRCALPHA;
blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;

This takes the new image * new image alpha + background * (1 - new image alpha). I'm not to sure if the constants are named 100% correct, just look for the correct equivalent. The one thing that was incorrect in your example is therefore the operation on the background (dest), with one the background color is always considered 100% in the output.

Thank you both!

Apparently I had no alpha channel in my image, that's why it never worked.

Since I am not using additive blending now, my billboards flipping from back to front and vice versa. (In some frames billboard 1 is in front of 2 and then in the next frame it is the other way around)

I guess I have to sort the billboards by depth now am I correct about this or is there another way?


I guess I have to sort the billboards by depth now am I correct about this or is there another way?

For pictures that consist only of solid (1.0f alpha) and completely-transparent (0.0f alpha) pixels, you can clip(image.a > 0.0001f ? 1 : -1) in the pixel shader (refered to as "alpha-testing", and continue using the zbuffer. In this case though, you don't need to enable alpha blending at all. Otherwise, if not usign additive/subtractive blending, you have little choice but to do sorting.

This topic is closed to new replies.

Advertisement