Alpha Blending using comparative rgb values. [Big picture warning]

BlitzPlus Forums/BlitzPlus Programming/Alpha Blending using comparative rgb values. [Big picture warning]

Myke-P(Posted 2003) [#1]
I'm currently playing about with a "seamless space nebula generator", for want of a better buzz word.

I'm almost there, but the final hurdle appears to be my alphablending. I have three "clouds" (tinted to a colored 'gas' which are applied to the base image (black background with random 'stars') one after the other. Or so the theory goes. ;)

My problem is the difference in results when doing it in code and 'mocking' it up in PSP.

PSP (the desired result)


Generated:


After a chat with Rob Cummings, it looks like I'm using a kind of 'additive alpha blending' technique. The result is that the more I 'alpha-layer', the more 'muddy' the image gets. I remember a topic about blood textures in 3D saying that the alpha-blending should be; "multiplicative"? So, I'm wondering how to achieve that effect using rgb comparisons.

The current code goes like this:
	redlevel# = redlevel# - ((redlevel# - redlevel1#)*alphalevel1#)
	greenlevel# = greenlevel# - ((greenlevel# - greenlevel1#)*alphalevel1#) 
	bluelevel# = bluelevel# - ((bluelevel# - bluelevel1#)*alphalevel1#)



Where redlevel# is the current pixel color, redlevel1# is the color that I want to alpha-blend and alphalevel1# is the transparency level (0.0 to 1.0) Similarly for green and blue.

After discussing it further with Rob, we've speculated it may be something to do with redlevel# (current pixel color)'s value being over or under 127, as was the case in my Image_Processing_Brightness function:

	If redlevel < 128 Then
		redlevel = Int(redlevel - (127-redlevel)*contrast) + brightness
	Else
		redlevel = Int(redlevel + (redlevel-127)*contrast) + brightness
	End If


But I'm drawing a blank to be honest. So, I'm here for a bit of a brainstorming session, hopefully resulting in a modified alpha-blending equation that produces the PSP-style result.

Let me know if you need any more Gen, but for now, over to you guys. :D


Floyd(Posted 2003) [#2]
I think you have to figure out exactly what "'mocking' it up in PSP" did and then mimic that.

If all else fails, you could try 'reverse engineering' the results.

Examine pixel values, both color and alpha, in the source images used to assemble the desired result.
Then examine the values in the final image and try to determine what calculations PSP is doing to produce it.


Ross C(Posted 2003) [#3]
why don't you create it based on the layers. Don't blend all the layers together, bland the first layer with the backround. blend the second layer with the original black backround, then blend the third layer with the orignal black backround. Then blend the three seperate one together.


Myke-P(Posted 2003) [#4]
Cheers for the suggestions guys. Somewhat spookily, the combination of these two resulted in me stumbling upon the (now obvious) difference between my Mocks and my Code. Turns out that I was doing things ever so slightly differently in PSP than my code was doing on its own.

I hadn't taken into account the colorisation of the luminance for each pixel. So my transparent pixels were too pure a sample of the intended color.. Or something.. :\

Anyway, having already done this with my Image Processing Functions, it was just a code adaption. :)

tempred# = Red_Level_1#/255
tempgreen# = Green_Level_1#/255
tempblue# = Blue_Level_1#/255

greylevel# = alphalevel1#*255
If greylevel# >= 128 Then
	redlevel1# = 255 * tempred# + (1-tempred#)*(greylevel#-(255-greylevel#))
	greenlevel1# = 255 * tempgreen# + (1-tempgreen#)*(greylevel#-(255-greylevel#))
	bluelevel1# = 255 * tempblue# + (1-tempblue#)*(greylevel#-(255-greylevel#))
Else
	redlevel1# = Int(greylevel#*tempred#)*2
	greenlevel1# = Int(greylevel#*tempgreen#)*2
	bluelevel1# = Int(greylevel#*tempblue#)*2
End If

redlevel# = redlevel# - ((redlevel# - redlevel1#)*alphalevel1#)
greenlevel# = greenlevel# - ((greenlevel# - greenlevel1#)*alphalevel1#) 
bluelevel# = bluelevel# - ((bluelevel# - bluelevel1#)*alphalevel1#)


Thanks again.

Now, saying all that. It would be nice to come up with an "Additive" and "Multiplicative" version of alpha-transparency, so if anyone's got any ideas on where to begin I'd be very interested.


Rob Farley(Posted 2003) [#5]
Additive : You just add the rgb values to the exisiting rgb values and crop the end result to a max of 255.
result=existing_r+r_to_add
if result>255 then result=255
Also, if you're doing a lot of this it's handy to create a function
function crop(n)
if n>255 then n=255
return n
end function
Then you can just write
result=crop(existing_r + r_to_add)


Multiply : Take the component value, divide it by 255 to get a value from 0 to 1 and multiply the existing component value by that number.
result=existing_r*float(r_to_multiply/255)



DarkEagle(Posted 2003) [#6]
for multiplication try this:
r1 = 255
g1 = 255
b1 = 0

r2 = 255
g2 = 128
b2 = 128

rout# = (r2/255) * r1
gout# = (g2/255) * g1
bout# = (b2/255) * b1



matt!(Posted 2003) [#7]
Hi Myke, I was wondering if your routine is freely available for use?


matt!(Posted 2003) [#8]
no worries Myke, i've managed to modify the Sunteam alpha include to do multiply blending:

adjustalpha(t,a#,a#,a#)
u\r = (u\r + (t\r*op))
u\g = (u\g + (t\g*op))
u\b = (u\b + (t\b*op))

becomes
u\r = u\r + (t\r - u\r) * a
u\g = u\g + (t\g - u\g) * a
u\b = u\b + (t\b - u\b) * a



Bagels(Posted 2003) [#9]
For the multiplying, it would be a good idea to make sure the calculations are done in floating point; otherwise that first value would end up as just 0 or 1, no in-between values.


Michael Reitzenstein(Posted 2003) [#10]
There is more information available on Blitz3D's blending here.