Incandescence and Transparency

Hey All,

I am looking for suggestions on how to implement Incandescence and Transparency together in an OpenGL application.

Incandescence (which is light energy created from heat) can be simulated using the GL_EMISSION mode of glColorMaterial() as long as you are dealing with opaque objects.

However, when transparent objects get added to a scene then the blending of transparent incandescent objects becomes incorrect as blending happens last in the openGL pipeline.

To correctly do incandescence you would want the incandescent contribution added after blending (eg think of glass, a near fully transparent object yet when heated it turns white and is completely opaque).

Does anyone know of a good method for doing this?

Well, I think your only option is to do a second pass. When rendering your alpha blended objects (I’m assuming you’re sorting these back to front? =), simply do two passes. The first pass should do the regular alpha blend, and the second pass should blend in the incandescent portion. I would recommend setting up your second pass so that it is “fully incandescent”, and then use the alpha value to blend between the normal alpha blend state and the fully incandescent state.

Mathematically, you’ll have:

t = transparency
i = incandescence
C = object color
Ci = incandescence color
Rd = current render target contents

pass 1:
Rd = (1-a)Rd + aC;
pass 2:
Rd = (1-i)Rd + i
Ci

Note that as incandescence gets larger, it will eliminate the color of the object (for instance, glass does not appear transparent when it’s really hot).

Hope this makes sense!

  • Kevin B

Well a second pass will not work for cases where you have multiple overlapped incandescent transparent objects.

Consider from back to front having an opaque object and then 2 transparent objects all of which are incandescent.

To be drawn correctly, you need to draw the opaque object first then draw the transparent object and blend it with the first… then add the incandescence. Then you need to draw the second transparent object and blend it with the first result and then again add the incandescence.

So think of it like ((((Op * T1) + I1) * T2) + I2) where * is a blend and + is adding the incandescence.

However using your method you would instead get (Op * T1 * T2) from the first pass plus (I1 + I2) from the second giving ((Op * T1 * T2) + I1 + I2) as a result which is not the same thing.

So then the next question is… is that close enough? Unfortunately the answer is no, I have a software raytracer whose results I have to match exactly and thus close just won’t cut it.

Anyone else have some idea’s? I was considering trying to use Pixel Mapping but I think that might be very slow.

I think you need to re-examine what I’m suggesting. Here it is expressed in a different way:

 
render all opaque objects
for each transparent object
  glBlendFunc( GL_ALPHA, GL_ONE_MINUS_ALPHA );
  setupColorGLMaterial();
  renderObject();
  //glBlendFunc( GL_ONE, GL_ONE ); I wouldn't recommend this due to precision (saturated at 1.0 in the framebuffer).
  setupIncandescentGLMaterial();
  renderObject();
end for

Hope this helps. Also note that I assume your transparent objects are back to front. Note that you could easily do an add for the incandescence, but I wouldn’t recommend it as you have very limited precision to work with.

  • Kevin B.

Dorbie solved a similar problem for me a while ago. You can do it in one pass with a shader.

a = transparency
C = object color
Ci = incandescence color

Normally you would use use blend mode GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
In your shader, you would have gl_FragColor = vec4(C, a), and you would need a second pass to add on the incandescent part.

Instead, use GL_ONE, GL_ONE_MINUS_SRC_ALPHA
Then in your shader do this:
gl_FragColor = vec4(C * a + Ci, a);

Kevin I see what your saying now, I will give it a try.

Mogumbo thanks, when I get to doing a shader implementation I will take a look at your suggestion. However I find that once I am able to do a fixed pipeline version (which I have to do for legacy issues) that doing the shader version is always 1000 times easier. :slight_smile: