Page MenuHome

Better approximation of transparent BSDFs in GLSL
AbandonedPublic

Authored by Ralf Hölzemer (cheleb) on Feb 7 2016, 3:08 PM.

Details

Summary

This patch tries to give a better representation for transparent BSDFs in Material Vieport shading mode.
It is still not correct, but does a better job than the old method.

Diff Detail

Repository
rB Blender

Event Timeline

Ralf Hölzemer (cheleb) retitled this revision from to Better approximation of the Transparency BSDF in GLSL.
Ralf Hölzemer (cheleb) updated this object.
Ralf Hölzemer (cheleb) set the repository for this revision to rB Blender.
Brecht Van Lommel (brecht) edited edge metadata.

Can you explain what the reasoning is behind this change, and show an example of how this helps? I don't understand what HSV has to do with transparency.

Sure. After analysing the rendered results of the BSDF, i realized that the outcome is mostly controlled by the value and the saturation of the incoming color in HSV space.

  Alpha behavior in HSV space

    0.0 ^                ~0.75 ( this is arbitrary, but looks ok)
        |
        |
    val |
        |   
        |
    1.0 +--------------> 1.0
              sat
	
  Color behavior in HSV space
  
  black ^                colored
        |
        |
    val |
        |
        |
  black +--------------> black
              sat

The result of the BSDF in cyles seem to roughly follow these rules:

  • the hue of the result always stays the same and is always fully saturated (changed in Diff ID 6000)
  • the color of the result fades to black with both, decreasing value and saturation of the incoming color. The saturation influence seems to be linear, but the value seems to follow some kind of curve (smaller values make the result black faster). My first guess here was a gamma correction of 2.2, which looked ok. Arbitrary choice here.
  • the alpha of the result is always opaque when the incoming hsv value is zero, but fades between fully transparent and mostly opaque with the incoming hsv saturation. I chose a value of 0.75 for "mostly opaque", which looked ok. This is obviously arbitrary too.

You can try it out by opening

, setting the left viewport to Rendered, then play with the color of the Transparency BSDF.

Ralf Hölzemer (cheleb) updated this revision to Diff 5999.EditedFeb 7 2016, 6:10 PM
Ralf Hölzemer (cheleb) retitled this revision from Better approximation of the Transparency BSDF in GLSL to Better approximation of transparent BSDFs in GLSL.
Ralf Hölzemer (cheleb) updated this object.
Ralf Hölzemer (cheleb) edited edge metadata.
Ralf Hölzemer (cheleb) removed rB Blender as the repository for this revision.

Updated Glass- and Refraction shaders to use the new method. Had to shuffle around some code to make it work. Otherwise the glsl compiler would complain about the missing node_bsdf_transparent function.

to test

  • open or
  • set the left 3dview Shading mode to Rendered
  • play around with the mix nodes and the colors of the Transparency, Glass and Refraction nodes
  • compare the results with the right 3dview
Ralf Hölzemer (cheleb) set the repository for this revision to rB Blender.Feb 7 2016, 6:11 PM

Another change based on wrong observation/assumtion that the result is always fully saturated. This would give wrong colors with full transparency (white color). That itself wasn't very noticable with a single Transparent BSDF, but mixing a Transparent BSDF with another shader would show the color skewing.
Also tweaked the power of the incoming hsv value influence on the results hsv value to more closely match the change in brightness.

This seems all a bit arbitrary to me actually and i'm not even sure it's the biggest problem of transparency in Blender. The unsorted nature of faces in Blender makes transparency work really bad in the viewport.

There was recently paper published, which is probably what we should look into.

After thinking about this for a while, I don't think we should actually be doing this. The idea here seems to be to use emission as an approximation to colored transparency, which OpenGL (and Blender Internal and most image file formats for that matter) do not support.

This approximation works ok with particular light and a particular color of the background or objects behind the transparent object, but if those change then the assumptions break down. For example if you make a dark scene, you'll have bright transparent objects sticking out.

I'd just accept the limitation and do something like this:

void node_bsdf_transparent(vec4 color, out vec4 result)
{
    /* no native colored transparency support in OpenGL, so average */
    result.r = 0;
    result.g = 0;
    result.b = 0;
    result.a = 1 - (color.r + color.g + color.b)/3.0;
}