Friday, December 15, 2006

Point cloud experiments with Sunflow

This is just a quick heads up about my ongoing efforts to create a Processing library to integrate Sunflow, an opensource global illumination renderer, into my toolchain. Initially, I'm only after exporting generated 3D scenes/geometry, shaders and various render specific settings to Sunflow's scene description format.

ultimate bling
using a glass shader
macro molecular #1
ambient occlusion (AO)
macro molecular #2
AO & depth of field

This series and the previous images (with the random triangles) were fully rendered outside Processing. Currently this is far more flexible than my other plan to have Sunflow wrapped in a PGraphics. For one, the export option allows for easier tweaking the scene parameters (the global illumination lighting models have a lot of parameters and options to explore) as well as batch rendering frame sequences from the command line. This is far more resource friendly and efficient than handling the rendering directly from within a PApplet context, especially with high quality rendering times often lasting several hours per frame (you can get decent preview within seconds/minutes though).

So the library currently only supports triangulated geometry and I still need to make a decision & come up with a better mechanism to support various Sunflow primitive object types. This decision might involve breaking away from the restrictions imposed by my current implementation, which is based on Processing's beginRaw() mechanism, just like the existing DXF/PDF export libraries. What's fine for these other formats is not quite good enough for my case. For example, using sphere() together with beginRaw() in Processing will currently export a triangulated version of the sphere, not the pure mathematical surface. The problem is, there don't seem to be any API hooks in PGraphics for various drawing commands and or state changes (box() is similar, but not problematic in this case). Unless I'm really missing something quite obvious, "recorder" PGraphics classes only get involved with and get access to the final, world transformed geometry. For my purposes I'd also like to get access to the current fill/stroke colours and transform matrices. Because PGraphics has "protected" access and doesn't provide any getters for these properties, users are currently forced to duplicate some of these drawing commands in order to keep the library in synch with the "main" PGraphics instance used. So am still wading through the source(s) and trying to come up with a more user friendly solution...

By popular demand, here's some more background info about the making of the 3 images above.

The lastest version of Sunflow (still unreleased, need to check out from SVN) is featuring a new ParticleSurface object primitive, which is the basis for the images above. Reading through the source code, I quickly figured out this type of object is only based on 2 parameters: a "point cloud" of 3d particles and a global radius size used for each particle. In order to quickly test drive & define some point clouds of my own, I wrote this absolute basic generator script below:

// point cloud generator for
// Sunflow's (v0.7.0+) ParticleSurface primitive
void setup() {
try {
FileOutputStream fs = new FileOutputStream("c:/molecule_"+(System.currentTimeMillis()/1000)+".pointcloud");
DataOutputStream ds = new DataOutputStream(fs);
float x=0,y=0,z=0; // start at origin
float scl=0.25;
float dim=50;
for (int i = 0; i < 250000; i++) {
// randomly progress within the bounding box
// write out coordinates as raw floats
catch (Exception e) {

The next step then is to reference this generated data from a Sunflow scene file (You'll need to edit the file name near the end)...

sunflow test scene skeleton
image {
resolution 768 432
% resolution 1920 1080
aa 1 2

background {
color 1 1 1

accel kdtree
filter gaussian 2 2
bucket 128 hilbert

%% camera definitions

% uncomment this one to enable depth-of-field
/* camera {
type thinlens
eye 0 10 70
target -20 -20 0
up 0 1 0
fov 60
aspect 1.7777777
fdist 27
lensr 0.85
} */

camera {
type pinhole
eye 0 10 70
target -20 -20 0
up 0 1 0
fov 60
aspect 1.7777777

%% define a simple area light for soft shadows

light {
type meshlight
name l1
emit 1 1 1
radiance 48
samples 32
points 3
-60 20 60
0 60 -60
60 20 60
triangles 1
0 1 2

shader {
name a
type amb-occ
bright .4 .9 1
dark 0 0 0
samples 128
dist 16

object {
shader a
type dlasurface
% need edit this file path
filename c:/molecule_1166058556.dat
radius 0.125

Save this file using the ".sc" extension and open it in Sunflow. Use the "IPR" renderer for easier previewing. You might need to adjust camera settings to better fit your generated particles.

If you end up successfully rendering something and have a flickr account, please do submit images to the newly created Sunflow group pool. Thanks!

Finally, I'm no expert in global illumination (in fact playing around with Sunflow are my very 1st baby steps with that technology). Everything I know so far about the SC file format is collected from examining the source code of the SCParser class and the demo files you can download. If you have any questions about rendering with Sunflow (not related to the tie-in with Processing), please check the official forum @ sourceforge...