Calculating transparency in a raytracer

Started by
28 comments, last by Ready4Dis 14 years, 10 months ago
Hi there, I'm building a ray tracer and a crucial requirement is that it is able to generate transparent images. So if the rays hit nothing, it should return transparent as a color I'm having trouble calculating the final color of my transparent textures. It seems a trivial problem but I can't get it right Example. Imagine a plane that has a texture with color1: ARGB 0.5,1,1,1 (white, half transparent). The raytracer sees it is transparent, and continues tracing after which it hits nothing anymore so returns color2: ARGB 0,0,0,0 (black, transparent). My first thought: sourceAlpha = color1.A; finalcolor.Red = sourceAlpha * color1.R + (1-sourceAlpha ) * color2.A finalcolor.A = color1.A + (1-sourceAlpha ) * color2.A; Unfortunately this doesnt work correctly. The alpha is calculated fine, but it returns 0.5 as red, which is wrong (darker). Can anyone help me out here?
Advertisement
if the plane is 0.5 transparent, it seems to be correct if it gets blended with the background, I mean, from the theory point of view.

if you dont want to blend with the empty background, just dont blend, really. check if there was a hit, if not, dont blend. if you rely on the color+alpha of the object that you hit, you invert the blend formular. you could get it right with just one transparent plane and the background, but as soon as you'll have several transparent planes, you'll get in trouble.


not just return a color, but also if you hit something at all, and if not, dont blend.

sorry if that might sound like a stupid advice ;)

thanks for the help,

1. Yea, that extra plane behind the first one is exactly my problem. I have lots of half transparent textures and objects. that overlap.

2. secondly, no that method does not return the correct result. It averages the colors, so with the provided example you get ARGB 0.5, 0.5,0.5,05 which is half transparent grey instead of half transparent white.

I put the whole thing in an analytical equation that seems to be working and is almost finished, I'll post it here tomorrow. Its more complicated than one would think. It appears the alpha calculation is not correct yet.
Quote:Original post by garma83

Example. Imagine a plane that has a texture with color1: ARGB 0.5,1,1,1 (white, half transparent). The raytracer sees it is transparent, and continues tracing after which it hits nothing anymore so returns color2: ARGB 0,0,0,0 (black, transparent).


Unfortunately this doesnt work correctly. The alpha is calculated fine, but it returns 0.5 as red, which is wrong (darker).
Can anyone help me out here?


I have a question: what would be in your example the correct result? Because if I didn't misunderstand your problem, a 0.5 red seems correct to me:
The 'color' of a surface is the light it reflects towards your eyes (diffuse component). If your surface is half transparent, then only half of the incident light will be reflected, and this means that only half of the light reaches your eyes. And this results in a darker color, unless there is somthing bright behind the plane.
Am I missing something?

hi there,

yes those were my first thoughts as well. But note that there is _nothing_ behind the plane. Not a color, just transparency. The result of the blending operation of the color of the plane with the background color (which is nothing, full transparency) should be the original color.

What you are saying is correct if the background color would have no transparency channel. In that case, the background color is black, and red mixed with black indeed gives 0.5. But note that the background color has '0' in the alpha channel! The darker red (0.5) instead of full red is therefore wrong. It should stay full red but half transparent. What you are referring to as 'darker' is only valid when whatever is behind it is darker. If the background would be white, the red would be lighter (washed)

Let me put it differently. If you would have a glass window, fully transparent, and you have a sheet of white paper behind it, the color one sees would be white, right? Now if you hold a sheet of red paper behind it, you would see red. Now imagine you would hold a sheet of _transparent_ paper behind it. The final color would depend on whatever is behind the sheet of paper. In the real world, there is always something behind it. However, in my scenes, there is just transparency. So note how the final color would be fully _transparent_, and not a color. If you introduce a half transparent, red window, you got my problem.

This problem is solved in DirectX and OpenGL by the fact that it is impossible to render transparent render targets. You always specify a background color.
Quote:Original post by garma83
hi there,

yes those were my first thoughts as well. But note that there is _nothing_ behind the plane. Not a color, just transparency. The result of the blending operation of the color of the plane with the background color (which is nothing, full transparency) should be the original color.

What you are saying is correct if the background color would have no transparency channel. In that case, the background color is black, and red mixed with black indeed gives 0.5. But note that the background color has '0' in the alpha channel! The darker red (0.5) instead of full red is therefore wrong. It should stay full red but half transparent. What you are referring to as 'darker' is only valid when whatever is behind it is darker. If the background would be white, the red would be lighter (washed)


Yes, I understand this, but still, I don't get how you could have both full color and transparency. That is, if you need that for compositing, the first equations should still be valid.
Unless your requirements are there for other reasons, and in that case I can't help, sorry :-)
Quote:What you are saying is correct if the background color would have no transparency channel. In that case, the background color is black, and red mixed with black indeed gives 0.5. But note that the background color has '0' in the alpha channel! The darker red (0.5) instead of full red is therefore wrong. It should stay full red but half transparent. What you are referring to as 'darker' is only valid when whatever is behind it is darker. If the background would be white, the red would be lighter (washed)


No, the darker red is STILL the correct result.
no it is REALLY not. it would ONLY be correct if there is a black, nontransparent background.

Compare:
ARGB (0.5,1,0,0) + ARGB (0,0,0,0) = ARGB(0.5,0.5,0,0) -> darkened red
ARGB (0.5,1,0,0) + ARGB (0,1,1,1) = ARGB(0.5,1,0.5,0.5) -> washed out red

The fact that these results DIFFER is wrong, because the background-colors are fully transparent. How can something that is fully transparent, change the final color in ANY way? It shouldn't. If I put a fully transparent bunny in front of the plane, it wouldn't change the final color either, wouldn't it?

Try it in photoshop if you still don't believe me. Make a layer, fill it with red, put the opacity on 50%, disable the background-layer and tell me if the red got darker.
I think that you should use the formulas wich better describe what you want the result to be. That said, I'm not really sure you're looking it from the correct perspective:
If you talk about blending modes, then yes, there are many formulas. Some of them are used also by DX/OGL, and you can find them in the manuals (this should help you finding the one you like most). But you are talking about raytracing: from a physical point of view the diffuse color indicates how the incident light is reflected. If you set a transparency value of 50%, you are just saying that half the incident light will go through (so only half of the light will bounce).
You think in terms of colors, while it is more correct to talk about reflectance function: that red is not 'red', only a function that relates incident and reflected (diffuse, in this case) light.

You said that a transparent background should not change the surface color. It seems to me that a transparent background should not change the amount of light that your surface reflects.

You can't really compare a graphic tool like photoshop to a raytracer, because in the first case there are only pixels wich must be combined with other pixes. In a raytracer it is a matter of light/surface interactions.

Then again, you must implement what you need, and I can be completely wrong :-)
You're way over thinking this... Simply return .5, 1,1,1. Then, whatever application displays the rendered image is responsible for blending it with IT's background color, since you have no background color, it doesn't make a change at all, so you do nothing with the 0,0,0,0. You aren't taking into account DestAlpha, you are only calculating using SrcAlpha. I will try to work out a formula for this today if you'd like. I came up with a few samples and what the results *should* be, just need to find an equation to fit:

(r,g,b,a)
1,1,1,0.5
0,0,0,0
Result = 1,1,1,0.5

1,1,1,.5
0,0,0,.5
Result = .5,.5,.5,0.75

1,1,1,.75
0,0,0,.25
Result = .75, .75, .75, 0.8125

1,0,0,.5
0,1,1,.5
Result = .5,.5,.5,0.75

I will try to get back later (after work) and try to get you a formula if you can't figure something out.

This topic is closed to new replies.

Advertisement