Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Professional Discussion / Transparency and alpha blending issue

Author
Message
Kuper
9
Years of Service
User Offline
Joined: 25th Feb 2008
Playing: Planescape:Torment
Posted: 16th Feb 2017 17:10 Edited at: 16th Feb 2017 17:11
So I never get transparency work perfectly in DBPro - so I changed all vegetation shaders and
other stuff to just cut off transparent pixels.But now I need smooth transparency blending for GUI
In effect file we have:

alphablendenable = true;
blendop = add;
srcBlend = srcAlpha;
destBlend = invSrcAlpha;

But result is weird. Some objects blends good other cut off others.Also doesnt blend between its faces ( this I think is impossible anyway )
When I try to render all alpha objects in rgbw camera image i get black edges around objects - they blends with background and not with each other.

Attachments

Login to view attachments
Green Gandalf
12
Years of Service
User Offline
Joined: 3rd Jan 2005
Location: Cornwall UK
Posted: 16th Feb 2017 18:27
Which transparency mode are you using in DBPro? There are about 6 different modes you can try.
Kuper
9
Years of Service
User Offline
Joined: 25th Feb 2008
Playing: Planescape:Torment
Posted: 16th Feb 2017 19:29 Edited at: 16th Feb 2017 19:29
I dont set transparency in DBPro.only in shader.
( all transparency modes are unuseful - just clip pixels without blending or doesnt blend correctly )
So I get two main problems :
1) objects doesnt blend with each other - just clip one another ( z sorting ? ) ( first image )
2) doesnt blend alpha correctly.dark edges when blend between objects ( third image )

ps
I get good result only when objects are in screen mode.
Green Gandalf
12
Years of Service
User Offline
Joined: 3rd Jan 2005
Location: Cornwall UK
Posted: 16th Feb 2017 22:00
I'm not entirely sure what you are doing, but you might to look at the use of alpha blending and transparency modes in the attached demo of an old fire effect of mine.

Attachments

Login to view attachments
Kuper
9
Years of Service
User Offline
Joined: 25th Feb 2008
Playing: Planescape:Torment
Posted: 16th Feb 2017 22:49
Thanks for demo.It works - cause fires blended by their rgb colors in add mode.
Dark parts of fire are transparent.
But I need to blend objects only by their alpha.I need black object be visible if its alpha >0
I add small demo to play with, hope it helps

Attachments

Login to view attachments
Green Gandalf
12
Years of Service
User Offline
Joined: 3rd Jan 2005
Location: Cornwall UK
Posted: 16th Feb 2017 23:38
Quote: "It works - cause fires blended by their rgb colors in add mode."


I don't think it does. It uses max operation and blends using the alpha component which is all fully opaque or fully transparent if I recall correctly, i.e. 1 or 0.

Unfortunately I don't have much time to look into this further at the moment as I'll be away for 3 weeks. If this is still an issue when I return I'll look at it again then.

Hopefully someone else will be able to look at this for you.
smerf
12
Years of Service
User Offline
Joined: 24th Feb 2005
Location: nm usa
Posted: 17th Feb 2017 03:30
your running into a complex problem I believe there is not a simple solution to. Rgb vales blend based off a photon flux algorithm I believe based off of the way light behaves. Its not quit as easy as adding or subtracting a color and multiplying times an opacity value.

To blend using alpha channels, you can use these formulas:
r = new Color();
r.A = 1 - (1 - fg.A) * (1 - bg.A);
if (r.A < 1.0e-6) return r; // Fully transparent -- R,G,B not important
r.R = fg.R * fg.A / r.A + bg.R * bg.A * (1 - fg.A) / r.A;
r.G = fg.G * fg.A / r.A + bg.G * bg.A * (1 - fg.A) / r.A;
r.B = fg.B * fg.A / r.A + bg.B * bg.A * (1 - fg.A) / r.A;

fg is the paint color. bg is the background. r is the resulting color. 1.0e-6 is just a really small number, to compensate for rounding errors.

NOTE: All variables used here are in the range [0.0, 1.0]. You have to divide or multiply by 255 if you want to use values in the range [0, 255].

For example, 50% red on top of 50% green:
// background, 50% green
var bg = new Color { R = 0.00, G = 1.00, B = 0.00, A = 0.50 };
// paint, 50% red
var fg = new Color { R = 1.00, G = 0.00, B = 0.00, A = 0.50 };
// The result
var r = new Color();
r.A = 1 - (1 - fg.A) * (1 - bg.A); // 0.75
r.R = fg.R * fg.A / r.A + bg.R * bg.A * (1 - fg.A) / r.A; // 0.67
r.G = fg.G * fg.A / r.A + bg.G * bg.A * (1 - fg.A) / r.A; // 0.33
r.B = fg.B * fg.A / r.A + bg.B * bg.A * (1 - fg.A) / r.A; // 0.00

Resulting color is: (0.67, 0.33, 0.00, 0.75), or 75% brown (or dark orange).


You could also reverse these formulas:
var bg = new Color();
if (1 - fg.A <= 1.0e-6) return null; // No result -- 'fg' is fully opaque
if (r.A - fg.A < -1.0e-6) return null; // No result -- 'fg' can't make the result more transparent
if (r.A - fg.A < 1.0e-6) return bg; // Fully transparent -- R,G,B not important
bg.A = 1 - (1 - r.A) / (1 - fg.A);
bg.R = (r.R * r.A - fg.R * fg.A) / (bg.A * (1 - fg.A));
bg.G = (r.G * r.A - fg.G * fg.A) / (bg.A * (1 - fg.A));
bg.B = (r.B * r.A - fg.B * fg.A) / (bg.A * (1 - fg.A));

or
var fg = new Color();
if (1 - bg.A <= 1.0e-6) return null; // No result -- 'bg' is fully opaque
if (r.A - bg.A < -1.0e-6) return null; // No result -- 'bg' can't make the result more transparent
if (r.A - bg.A < 1.0e-6) return bg; // Fully transparent -- R,G,B not important
fg.A = 1 - (1 - r.A) / (1 - bg.A);
fg.R = (r.R * r.A - bg.R * bg.A * (1 - fg.A)) / fg.A;
fg.G = (r.G * r.A - bg.G * bg.A * (1 - fg.A)) / fg.A;
fg.B = (r.B * r.A - bg.B * bg.A * (1 - fg.A)) / fg.A;

The formulas will calculate that background or paint color would have to be to produce the given resulting color.


If your background is opaque, the result would also be opaque. The foreground color could then take a range of values with different alpha values. For each channel (red, green and blue), you have to check which range of alphas results in valid values (0 - 1).
A child's dream never dies.





Green Gandalf
12
Years of Service
User Offline
Joined: 3rd Jan 2005
Location: Cornwall UK
Posted: 17th Feb 2017 10:32
Kuper

I've realized I misunderstood your point about how my demo works. You're right that it can't be used in your situation. I'm fairly sure your problem is mainly a render order issue which doesn't have a simple solution covering all situations.

What you need is for pixels to be drawn from back to front, i.e. render distant pixels first. I recall there was a way of achieving this per object but as far as I know there is no way of doing it per pixel so if your semi transparent objects intersect each other in a strange way then you will have problems. As you say I was able to avoid that issue because of the fire objects' special properties.

smerf

Unfortunately I don't have the time right now to digest what your method is doing exactly. It looks intricate and somewhat counter intuitive but I've probably misunderstood. A simple demo showing your method in action would be helpful.
Kuper
9
Years of Service
User Offline
Joined: 25th Feb 2008
Playing: Planescape:Torment
Posted: 17th Feb 2017 15:06 Edited at: 17th Feb 2017 15:24
@smerf
I get. So only one solution I can see is to just render GUI with alpha mapping over objects geometry in the final pass.
It works.
But there is last problem - sorting.DBPro sort sometimes correctly sometimes not.


For example if objects are moved only in Z direction (X and Y position is the same for all) - blending is correct!


PS:
use ENABLE OBJECT ZBIAS and set sorting manually!!

Attachments

Login to view attachments
WickedX
8
Years of Service
User Offline
Joined: 8th Feb 2009
Location: A Mile High
Posted: 17th Feb 2017 17:35
With sprites the image with the lowest image id will have priority. Obviously sprite priority can be changed with - Set Sprite Priority. Idk how image id will effect using transparencies and blending.
Chris Tate
DBPro Master
9
Years of Service
User Offline
Joined: 29th Aug 2008
Location: London, England
Posted: 17th Feb 2017 17:57
Here are two solutions with an example. I am sure there are other solutions, but these are straight forward to implement. The first is ID sorting, the second is Limb sorting.

By running my sample code with valid transparent images loaded from your local machine, you will notice that we have two cube objects inside a sphere with their transparency mode set to 1; yet none of the objects appear to be transparent. Why so? This is because in common cases, texture ID will affect the draw order of objects. The object in front uses a lower texture ID, and is thus drawn first. Switching the texture ID parameters of the texture object commands reverses this affect. The nearest object would then use a higher texture ID and would overlap the object behind it with its transparent pixels revealing the previously rendered texture.

If you do not use Matrix1 utilities, you can easily replace the unsupported commands

+ Code Snippet

This behaviour has been documented in the Texture Object help page.

Quote: "Essentially objects are rendered by texture order, so it will take all the textures at ID=1 and render them first, then all the ones at ID=2 and render those second, and so forth. This is done because it is quicker to render multiple objects that use the same texture than it is to keep swapping textures for each mesh to be rendered. The upshot then is that any objects that use a lower texture ID will be rendered before an object with a higher texture ID. "


The second solution is based on the use of limbs, and indicates that the above is only true of OBJECTS when NOT using the Texture Object overload with the ignoreSorting parameter set to true.

In the example if you uncomment the limb creation section, you will notice that limbs are drawn in order of their IDs, but not their texture IDs.

Attempting to use shaders to overcome this problem is futile because DBP is taking charge of render sorting and not the shader.
smerf
12
Years of Service
User Offline
Joined: 24th Feb 2005
Location: nm usa
Posted: 17th Feb 2017 17:58 Edited at: 17th Feb 2017 18:00
Sorry I misunderstood kuper. the method I posted is for pixel by pixel rgb blending with opacity for overlaying color on images. Did the Zbias fix your problem? looks like there is still a blending issue to me. There are transparent crescent areas where the images overlap instead of straight cut lines. is your alpha map transparent or white?
A child's dream never dies.





Green Gandalf
12
Years of Service
User Offline
Joined: 3rd Jan 2005
Location: Cornwall UK
Posted: 17th Feb 2017 18:31
Quote: "Attempting to use shaders to overcome this problem is futile because DBP is taking charge of render sorting and not the shader."


Yep.

I'll check out your example when I get back from holiday. I haven't tried the texture sorting idea but it sounds like it's a solution in 95% of cases.
Kuper
9
Years of Service
User Offline
Joined: 25th Feb 2008
Playing: Planescape:Torment
Posted: 17th Feb 2017 22:47 Edited at: 17th Feb 2017 22:55
Thanks guys!
Yep ENABLE OBJECT ZBIAS Object Number, Slope Scale, Depth
solve all problems with sorting.
I have this settings for all object with alpha blending:
set object transparency obj,2
and in shader:
AlphaBlendEnable=True;
SrcBlend=srcalpha;
DestBlend=invsrcalpha;
I dont know how "Slope Scale" value affect te result - set it to 0.5

Login to post a reply

Server time is: 2017-10-20 18:47:55
Your offset time is: 2017-10-20 18:47:55