Monthly Archives: October 2009

High Dynamic Range galore

In January, during my internship activity, I was researching in the field of HDR imaging, today I had the time, at last, to polish a bit and release the two demos I made at the time.

They both load an RGBE image (the two you see here are courtesy of the Paul Devebec’s Light Probe Image Gallery) through the library of Bruce Walter.

Light probe at different exposure levels (hdr_load1)

Light probe at different exposure levels (hdr_load1)

The first demo implements the technique described in the article High Dynamic Range Rendering published on GameDev.net and is based on five passes and four FBOs:

  1. Rendering of the floating-point texture in an FBO
  2. Down-sampling in a 1/4 FBO and high-pass filter
  3. Gaussian filter along the X axis
  4. Gaussian filter along the Y axis
  5. Tone-mapping and composition

The algorithm is very simple, it first renders the original scene then it extracts bright parts at the second pass, which merely discards fragments which are below a specified threshold:

// excrpt from hipass.frag
if (colorMap.r > 1.0 || colorMap.g > 1.0 || colorMap.b > 1.0)
	gl_FragColor = colorMap;
else
	gl_FragColor = vec4(0.0);

While the third and fourth passes blurs the bright mask, the last one mixes it with the first FBO and sets exposure and gamma to achieve a bloom effect.

// excerpt from tonemap.frag
gl_FragColor = colorMap + Factor * (bloomMap - colorMap);
gl_FragColor *= Exposure;
gl_FragColor = pow(gl_FragColor, vec4(Gamma));
Light probe at different exposure levels (hdr_load2)

Light probe at different exposure levels (hdr_load2)

The second demo implements the technique described in the article High Dynamic Range Rendering in XNA published on Ziggyware and is based on seven passed and more than five FBOs:

  1. Rendering of the floating-point texture in an FBO
  2. Calculating maximum and mean luminance for the entire scene
  3. Bright-pass filter
  4. Gaussian filter along the X axis
  5. Gaussian filter along the Y axis
  6. Tone-mapping
  7. Bloom layer addition

This approach is far more complex than the previous one and is based on converting the scene to its luminance (defined as Y = 0.299*R + 0.587*G + 0.114*B) version, the mean and maximum value can be calculated using a particular downsampling shader and working in more passes, at each one rendering on an FBO with a smaller resolution than the previous until the last pass, when you render the luminance of the entire scene on a 1×1 FBO.

As usual you can have a look at YouTube (GLSL_hdrload1, GLSL_hdrload2) or Vimeo (GLSL_hdrload1, GLSL_hdrload2) videos and download the sources.

GL O.B.S.: two years after

You’re reading about GL O.B.S. after *exactly* 730 days (I swear it was not made on purpose ;-)): today revision 50 has been committed.
No new feature has been added, I’ve dedicated the efforts of the last days to a case study about updating an application after a very long time, the process mainly involved removing deprecated things and adding support for new ones.

GL O.B.S. GUI is now based on GtkBuider

GL O.B.S. GUI is now based on GtkBuider

Let’s read together some lines from the revision log:

  • GUI migrated from libglade to GtkBuilder
    This was, with no doubt, the most time consuming task: gtk-builder-convert tool was not so reliable and I was compelled to recreate the GUI from scratch with Glade. I have also set the minimum GTK version required to 2.16
  • using JSON format for storing benchmark information dictionaries
    This feature is a way to get rid of the deprecated execfile() built-in function, instead of executing a python script to read a dictionary, the Benchmark class now parses a JSON file with the new integrated json module.
    Comparing an old and a new file you can notice how simple it was the conversion, I’ve only lost the ability to comment a line. 😉
  • importing numpy instead of numerix in matplotlib
    This is another deprecation related issue, matplotlib is now based upon numpy.
  • matplotlib canvas get refreshed instead of being destroyed and then recreated
    I don’t know why two years ago I was destroying and recreating the object instead of just calling the draw() method every time it had to be refreshed. 😀
  • some more attributes and objects integrated in the GtkBuilder XML file
    I’ve integrated more attributes in the XML GUI file, like default size for secondary windows or Paned positions.
    Moreover, thanks to GtkBuilder, even some objects have been integrated, like Adjustment or TextBuffer.
    Actually also TreeModel objects should be configurable inside Glade and integrated inside the XML, but I didn’t manage to make them work. 🙂

Other remarkable changes in the field of Python3 future support and deprecated features removal were:

  • all the print statements converted to functions
    Well, we all know the content of PEP 3105… 😉
  • using hashlib.md5 instead of md5
    The md5 module has been deprecated in favour of the hashlib one
  • using “key in dict” instead of dict.has_key()
    The has_key() method no longer exists in Python 3
  • using subprocess.Popen instead of os.popen()
    os.popen() have been deprecated in favour of the subprocess module
  • using urllib2.urlopen() instead of urllib.urlopen()
    Another deprecation suggested substitution, from urllib.urlopen() to urllib2.urlopen()
  • removed “copyright” argument and added “classifiers” in setup.py
    The distutils.core.setup() function loses the “copyright” argument but gains “classifiers”. 🙂
  • dropped support for pysqlite2 and old webbrowser module
    Now that the minimum requirement is Python 2.6, there is no need for pysqlite2 or old webbrowser module support
  • I have also removed the deprecated Options class in some SCons scripts.

I’m not sure I will have some time in the future to continue developing, but this was a nice “reboot” and I also have some new ideas in my to-do list. 😉