Sunflow & Processing


I’ve been using the java-based global illumination renderer Sunflow together with Processing for quite some time now. The first ever video I made with Processing (only 10 months ago!) was actually one that employed Sunflow through the P5Sunflow library. Two months ago I went a little further to create a short motion graphics experiment for the 5 second project. All my Sunflow projects until that time worked through the P5Sunflow library. The main advantage of this library is that it automatically ‘translates’ a sketch. This means you don’t have to make any changes to your original sketch, except change the renderer. This is ideal. Unfortunately however, this library was never fully developed. So although it supports geometry, it does not allow for more advanced Sunflow functionalities such as shaders, lighting and Sunflow’s built-in primitives.

SunflowP5 alternatives
For the last few months I’ve been looking at different alternatives to bring full Sunflow functionality to Processing. I checked out some of the P5Sunflow clones like Sunflow4P5. See the discussion in this thread on the old forum. Didn’t work out at all. I then downloaded Sunflow itself and examined the possibility of exporting geometry from Processing, which is subsequently rendered in “the real” Sunflow. This is possible. You can export stuff from Processing as regular 3D models or try to export it in a Sunflow-ready format. Many 3D applications already have plugins to export to Sunflow format and it’s a relatively simple format. Interestingly enough, a very recent attempt to bridge the gap between Processing and Sunflow seems to focus on this technique. Like a hybrid between full translation and using the Sunflow .sc format or something. See this thread in the new forum for more details about this library-in-development called JoonsRenderer. Looks really interesting, although I haven’t tried it yet. It wasn’t around at the time I started my search. Getting back to the story, my attempt to export geometry and then manually render in Sunflow, worked. But it was very time-intensive and for my end goal (animation) not a viable solution at all. So I decided to look into different alternatives.

SunflowAPIAPI
I then found a java-wrapper called SunflowAPIAPI, created by Christopher Warnow back in 2008. It functions like an easier-to-use API for Sunflow’s functionalities. After some figuring out, I got it to work directly from within Processing. I’ve been spending some time (between vacations, my day job and other personal projects!) on learning this wrapper and the possibilities of Sunflow in general. The three big advantages of using SunflowAPIAPI are that it allows for (a) full Sunflow functionality (b) directly from within Processing and (c) can be tweaked at will; as the code is directly accessible from Processing’s IDE. The big disadvantage, especially compared to SunflowP5, is that it requires special syntax. So it will not translate existing sketch code automatically. Instead it requires some manual translation. How much work this will be, depends on the sketch. The syntax itself is not difficult. In fact it’s fairly straight-forward, as it completely mirrors the terminology used in Sunflow. So it all makes sense, but you gotta consider the translation-issue beforehand If you’re aiming for an efficient workflow.

Workflow alternatives
I’ve found two main workflow options. Either work fully in SunflowAPIAPI-ready code and render to Sunflow in preview mode. The advantage of this method is that it’s 1:1. You write it, you see it etcetera. The disadvantage is, that Sunflow is SLOW even for low-resolution, low-quality preview renders. The second method is to program your sketch in OPENGL and have a ‘mirror copy’ of all your code for the SunflowAPIAPI. The advantage is that OPENGL works in real-time. Then at the press of a button you could start rendering to Sunflow. The disadvantage is that all your code is basically doubled and you have to sync geometry, camera’s etcetera. I’ve used both methods. It really depends on your needs and the complexity of the scene, which one you’d wanna use.

How to install SunflowAPIAPI
For people interested in using this API, let me elaborate on the steps you need to make it work.

  1. Create a new empty sketch.
  2. Compile a version of Sunflow or download the latest version 0.073 here.
  3. Copy this file “sunflow-and-janino.jar” into the “/code” subdirectory of your sketch.
  4. Go to the Google repository for SunflowAPIAPI.
  5. Checkout the code via a Subversion client or directly download the files via browse.
  6. The main file you will need is “SunflowAPIAPI.java”. Copy this file into the main sketch directory (besides your “sketchname.pde”).
  7. Now when you code your sketch – using the correct syntax – it should render using Sunflow. A basic code example is provided below.

How to use SunflowAPIAPI (code example)
Once you have followed all of the above steps, all that remains is the content of the sketch. The examples provided with the API are useful, but you have to make some small changes for them to work in Processing. Here is an example for learning purposes, which only has the extremely bare essentials needed to make a simple test render. Code example:


import java.awt.Color;
import com.briansteen.SunflowAPIAPI;

int sceneWidth = 500;
int sceneHeight = 500;

void setup() {
 SunflowAPIAPI sunflow = new SunflowAPIAPI();
 sunflow.setWidth(sceneWidth);
 sunflow.setHeight(sceneHeight);
 sunflow.setCameraPosition(0,2.5,-5);
 sunflow.setCameraTarget(0,0,0);
 sunflow.setThinlensCamera("thinLensCamera", 50f, (float)sceneWidth/sceneHeight);
 sunflow.drawPlane("ground", new Point3(0,-3.5,0), new Vector3(0,1,0));
 sunflow.drawSphereFlake("mySphereFlake", 20, new Vector3(0,1,0), 1);
 sunflow.setPathTracingGIEngine(64);
 sunflow.render(sketchPath + "/SunflowTestRender.png");
 exit();
}

The above code snippet should, if all goes well, result in something like the image below…

Trying out different Sunflow functionalities
All right, so like I said before, this API basically gives you full Sunflow functionality. Christopher’s been adding some of the last remaining functions lately. And I’m also a project committer myself now (yay! :cool:), so in the latest revision I added one little thing, the sphereFlake (as shown in the above code example). I’ve been playing with shaders, lighting options and some of Sunflow’s built-in primitives, like Hair and the JuliaFractal. The former is quite useful, the latter less interesting than it might seem at first sight. I’m of course grateful to Christopher for helping me out along the way and for developing the wrapper to begin with! Perhaps now that I’ve learned how to use it, it will be easier to apply it to actual projects. I’ll definitely be committing interesting and/or useful code additions, if I have any, into the repository. A video which mashes up two of my preliminary test render sessions can be found on Vimeo here.

Connecting Toxiclibs & HEMesh with Sunflow
Once I knew the API could run from inside Processing, I started working on connections with other libraries. So far I’ve successfully come up with methods to get stuff from Toxiclibs into Sunflow, from HEMesh into Sunflow and from external 3D model files into Sunflow. All of them go through Sunflow’s triangleMesh shape. This shape, as the name suggests, is made out of vertices and triangulated faces. Since most 3D shapes are already in  – or can be translated into – this format, it becomes relatively easy to get complex geometry from Processing (libraries) into Sunflow.

Tips & Tricks
Please benefit from some of the lessons I learned the hard way 😆

– The regular render option does not allow saving in Processing. You have to render to a file directly. Of course it’s possible to immediately afterwards load and draw the rendered image in Processing. But you could just as easily go to the output directory to see the rendered result. Depends on your needs.

– The way the API works is somewhat different from regular draw cycles. The API creates a 3D scene, which stays in memory! When nothing changes except for example camera movement, you could use this. Only create the scene once and subsequently just change the camera’s position. If however you have moving/changing objects you will need to re-create them. Initially I did this by removing objects/shaders and then creating them again. Since not removing them results in errors because the names are already in use. This is however not the most efficient way to do it. A better way is to re-create the full Sunflow object on every draw cycle. The old scene goes into the garbage collector. And you don’t have to worry about removing stuff or names already in use. Of course this makes rendering animations much more convenient.

– Syncing the camera between OPENGL en Sunflow is a challenge, which I’ve only figured out partially. I’m using the peasyCam library by the way. Getting the camera position and lookAt points is easy, because they are 1:1 related between renderers. The only thing to consider is the reverse Y due to OPENGL’s coordinate system. PeasyCam’s getPosition and getLookAt functions can be used to get the relevant coordinates, which can be directly inserted into Sunflow’s setCameraPosition and setCameraTarget functions. The problem is that this is not the full transformation, but only two-thirds. I’m guessing the third parameter is the camera’s rotation, probably around it’s own center point. Like I said, haven’t fully figured this one out yet, so suggestions are welcome… 🙂

Future developments
As with all my experiments, the learning process is more important than the final result. And I must say I’ve learned a great many things again. Sunflow stuff like lighting, shading and cool camera tricks. But also coding stuff like how to using the original Sunflow’s source code to your advantage and using subversion to keep track of code revisions. And I finally overcame my long-held reservations to working with advanced libraries like Toxiclibs and HEMesh, only to find out that they’re not as scary as they look from the outside, haha 🙂 Another step forward, but just a first step really. This is only the beginning. I hope to push all of this further. Been reading about fractal geometry, which poses interesting challenges and possibilities. Also I’ve barely scratched the surface of the mentioned libraries so my intention is to dive into those much more and see what comes out at the other end. That’s it for now! See you around and please feel free to share any comments below! 😀

Links related to this post:

  1. Vimeo Video
  2. Flickr Set
Comments
47 Responses to “Sunflow & Processing”
  1. felix says:

    Thanks for sharing your quest to reach the beautiful yet elusive sunflow nirvana. The top image is fantastic – did you make it with the methods above?

    I’ve used P5Sunflow in the past and it works pretty well however it does not seem to like the latest version of Processing.

    Recently I’ve been researching a more direct approach – rendering to sunflow via Blender. Blender v2.49 has a sunflow-export plugin: http://sunflow.svn.sourceforge.net/viewvc/sunflow/trunk/exporters/blender/sunflow_export.py?view=log
    It generates an .sc file that you then render with the sunflow UI. You can also go in and manually edit the sc files to modify materials etc.

    Blender v2.53 beta has a fantastic looking blender to sunflow plugin: http://sunflow.sourceforge.net/phpbb2/viewtopic.php?p=5579&sid=abd29a088f530b31943d4bd892866bcd
    unfortunately I havent been able to get it to work.

    • Amnon says:

      Thanks. Yeah, the top image is actually one of the first test renders I made about two months ago. If I remember correctly the middle sphere is made out of points that were re-routed to Toxiclibs and then displaced. So that was the first proof-of-concept. When posted like this, I suddenly noticed all the other images are black-and-white, but I guess that’s because my main focus has been geometry 🙂

      With regard to Blender. Yes, it’s an alternative and the GUI is impressive. But I think “direct” depends kind of on your viewpoint. Wouldn’t this mean export to 3D format from Processing, load in Blender, export to sunflow .sc, load in Sunflow, render. What if I have an animation of 1200 frames, which (because in my case every frame has different geometry) means 1200 scenes. This sounds like a lot of work to put through this whole process 😉 I think the export-to-3D-application method (be it Blender, Sunflow, 3DSMax or Maxwell) is extremely suitable for fixed 3D models, but I doubt it is practical for flexible animations.

      • felix says:

        The idea is to use Python scripting in blender to generate the shapes and possibly animations. Like I said this all theory at the moment. The lack of documentation or even blog posts on the subject is pretty frustrating – which is why it’s great you posted this.

  2. Gwen Vanhee says:

    Great stuff & thnx for sharing!
    Been playing around with PSunflow myself and getting a decent workflow with it not easy.
    Sounds like you discovered a great alternative, worth exploring.

    How long did the video take render-wise?

    • Amnon says:

      38 hours for the random walk sequence (600 images)
      13 hours for the blackwater sequence (600 images)

      😀

      Image size, shaders and the amount of adaptive anti-aliasing all greatly impact your render time. So if you’re just rendering one image you can make it huge with high aa. But with so many frames and considering Vimeo compression anyway, I usually go for 1280×720 with aa set to constant 1.

  3. Joon says:

    Hey Amnon, thanks for referring to my library. The number of visitors skyrocketed. Anyway, I delivered all the functionalities and documents I promised, and thought you might want to know. Whatever makes Processing a better tool for everyone and rendering less of a pain, man. Cheers 🙂

    • Amnon says:

      Cool! Definitely good to see several alternatives pop-up, which bring ray tracing into the hands of the Processing population. That’s the great thing about open-source. Keep up the good work 🙂

  4. monkstone says:

    I previously commented re: processing on the discussion board, I too have done a bit of exploration:-

    Have you tried StructureSynth, it has an almost immediate opengl display depending on complexicity. Lots of export functionality (including sunflow and povray). Camera seems to works pretty well, it is open source C++ so the code might give some useful pointers, even if you find the environment a bit strange/limited. It requires a different sort of thinking (mainly recursion) similar to context-free. See my website for some of my basic experiments, there is a website dedicated to the images produced but generally there is no code (there are some good examples included with the app though. The exported *.sc and *.pov files are really only templates for hand editing.

    • Amnon says:

      Yeah, I fully agree with you. StructureSynth is definitely an interesting app. I have it installed on my computer, but so far haven’t found the time to really get into it. To-Do-List getting bigger… 😉

  5. Vic says:

    This is awesome , i was coding with P5Sunflow to get shaders to 3D Shapes but is limited( http://www.vimeo.com/12720457 ). im trying to run yr example doing exactly like you say but im getting a bunch of errors(http://i140.photobucket.com/albums/r3/telefea/error.png) etc. What i’m doing wrong? so , and coneccting to toxiclivs could be great, can you provide de code of some running examples with toxiclibs?

    Well congrats man, i really enjoy yr video “Sunflow Overture”

    😉

    • Amnon says:

      Thanks! 😀

      I think that error message is not what it seems. Because the error is not in that function, it just happens to be the first function in the SunflowAPIAPI and thus the first opportunity to throw an error. The real problem I suspect is that the sunflow libraries (“sunflow-and-janino.jar”) are not properly available, which causes domino-effect problems. The reason the sunflow libraries are not working well, might be that you downloaded them from the link I provided. What I forgot to mention was that the sunflow release at POLYQUARK was compiled with Java Native Jet compiler for use in Windows 2000/XP, or so it says on their site. So that may very well cause some issues on a Mac. Do you think this might be it?

      I’ll see if I can make an example for the Toxiclibs connection…

  6. Vic says:

    Hey Amnon thanks for your answer, indeed my error was downloading the janino and sunflow jar file from Sunflow oficial site ,now i been downloaded the sunflow and janino file from POLYQUARK site and everything works fine in OSX too, im trying to modify the code to get glossy shaders etc, but im new in sunfllow code but but it seems to be not much dificult, well thanks in advance if you could post some examples with shaders and toxiclibs, i’m very involved in toxiclibs and it could be helpful to begin creating new stuff with Processing/Sunflow/ToxicLibs. 😉

    • Amnon says:

      Cool, whatever works!

      For shaders take a look at Christopher’s examples with the SunflowAPIAPI or check the API’s source code. For background information on the shaders, check the official Sunflow Wiki.

      Some examples:

      sunflow.setShinyDiffuseShader(“myShinyShader”, new Color(55,55,55), .8f);
      sunflow.setGlassShader(“myGlassShader”, new Color(1f,1f,1f), 2.5f, 3f, new Color(1f,1f,1f));
      sunflow.setPhongShader(“myPhongShader”, new Color(1f,1f,1f), new Color(.5f,.5f,.9f), 10, 16);

      I was looking at the Toxiclibs connection, it’s actually a very basic one, so I’ll save reposting all of the code. Let me just give you the essential lines, which can be applied to any sketch using the triangleMesh. Why? Because the triangleMesh in Toxiclibs is equal to the triangleMesh in Sunflow! Yes, that’s right there is no translation between libs required, just copy-pasting the data. 🙂

      The only thing is that when you import both libraries, some stuff will give an error message like “The type TriangleMesh is ambiguous”. The reason is they have the same name in both libraries, so it’s ambiguous which one you mean. The solution to this problem is to specify it fully. For example TriangleMesh should become toxi.geom.mesh.TriangleMesh or Face should become toxi.geom.mesh.TriangleMesh.Face.

      Now here are the lines… (assuming there is a triangleMesh in your scene called mesh)

      Globally define two arrays:
      float[] vertices;
      int[] triangles;
      Call these two functions either in draw or with keyPressed or something
      vertices = mesh.getUniqueVerticesAsArray();
      triangles = mesh.getFacesAsArray();
      Use these coordinates from Toxiclibs in Sunflow
      sunflow.drawMesh("myMesh", vertices, triangles);

      That’s it! 😀

  7. Vic says:

    Shaders with Sunflow was easy, but now im trying with toxilclibs and im getting some messy errors in SunflowAPIAPI,java( http://i140.photobucket.com/albums/r3/telefea/Imagen1-2.png ) i hope to get the right way to connect it , i will try more with simple examples, thanks for the feedback and i hope to get some more info and examples from you . If i get something interesting i’ll bring the info to this post!

    Thanks

    🙂

    • Amnon says:

      nullpointerexception means the array is empty. You’re not bringing any data into sunflow. Make sure those two arrays are filled with numbers (by using the functions provided) BEFORE you render with sunflow. Doublecheck if they are filled, by using a println output to the console or something.

      • Vic says:

        Thanks Amnon.Yes, arrays are filled with numbers but im gettin this NPE on “sunflow.parameter(“triangles”, triangles);” maybe something in my code is wrong but in doing exactly like you say,so here is my code its pretty simple but i dont know what happen.

        import java.awt.Color;
        import com.briansteen.SunflowAPIAPI;
        import toxi.geom.*;
        import toxi.geom.mesh.*;
        import toxi.volume.*;
        import toxi.math.noise.*;
        import processing.opengl.*;
        int DIMX=64;
        int DIMY=64;
        int DIMZ=64;
        float ISO_THRESHOLD = 0.1;
        float NS=0.03;
        Vec3D SCALE=new Vec3D(1,1,1).scaleSelf(300);
        boolean isWireframe=false;
        float currScale=1;
        VolumetricSpace volume=new VolumetricSpace(SCALE,DIMX,DIMY,DIMZ);
        IsoSurface surface=new IsoSurface(volume);
        toxi.geom.mesh.TriangleMesh mesh;
        int sceneWidth = 1200;
        int sceneHeight = 700;
        float[] vertices;
        int[] triangles;
        void setup() {
        SunflowAPIAPI sunflow = new SunflowAPIAPI();
        sunflow.setWidth(sceneWidth);
        sunflow.setHeight(sceneHeight);
        sunflow.setCameraPosition(0,2.5,-5);
        sunflow.setCameraTarget(0,0,0);
        sunflow.setThinlensCamera(“thinLensCamera”, 100f, (float)sceneWidth/sceneHeight*2);
        sunflow.setSunSkyLight(“mySunskyLight”);
        sunflow.setPointLight(“myPointLight”, new Point3(0,5,5), new Color(255,255,255));
        sunflow.setDirectionalLight(“myDirectionalLight”, new Point3(-2,3,0), new Vector3(0,0,0), 3, new Color(1f,0f,0f));
        sunflow.drawPlane(“ground”, new Point3(0,-3.5,0), new Vector3(0,1,0));
        sunflow.setGlassShader(“myGlassShader”, new Color(1f,1f,1f), 2.5f, 3f, new Color(1f,1f,1f));
        sunflow.drawMesh(“myMesh”, vertices, triangles);
        sunflow.setPathTracingGIEngine(164);
        //sunflow.render();

        }

        void draw() {
        float[] volumeData=volume.getData();
        // fill volume with noise
        for(int z=0,index=0; z<DIMZ; z++) {
        for(int y=0; y<DIMY; y++) {
        for(int x=0; x<DIMX; x++) {
        volumeData[index++]=(float)SimplexNoise.noise(x*NS,y*NS,z*NS,frameCount*NS)*0.5;
        }
        }
        }
        volume.closeSides();
        long t0=System.nanoTime();

        surface.reset();
        mesh=surface.computeSurfaceMesh(mesh, ISO_THRESHOLD);
        float timeTaken=(System.nanoTime()-t0)*1e-6;
        println(timeTaken+"ms to compute "+surface.getNumFaces()+" faces");
        background(128);
        translate(width/2,height/2,0);
        rotateX(mouseY*0.01);
        rotateY(mouseX*0.01);
        scale(currScale);
        ambientLight(48,48,48);
        lightSpecular(230,230,230);
        directionalLight(255,255,255,0,-0.5,-1);
        specular(255,255,255);
        shininess(16.0);
        beginShape(TRIANGLES);
        if (isWireframe) {
        stroke(255);
        noFill();
        }
        else {
        noStroke();
        fill(255);
        }

        int num=mesh.getNumFaces();
        for(int i=0; i<num; i++) {
        toxi.geom.mesh.TriangleMesh.Face f=mesh.faces.get(i);
        vertex(f.a);
        vertex(f.b);
        vertex(f.c);
        }
        endShape();
        vertices = mesh.getUniqueVerticesAsArray();
        triangles = mesh.getFacesAsArray();

        // println(triangles);
        // println(vertices);
        }

        void normal(Vec3D v) {
        normal(v.x,v.y,v.z);
        }

        void vertex(Vec3D v) {
        vertex(v.x,v.y,v.z);
        }

        (:

  8. Amnon says:

    This is exactly the point I was making. You are are calling sunflow.drawMesh in setup(), BEFORE you fill the array with numbers in draw(). You gotta rearrange it. When you want to render one still, move everything to setup like this…

    setup() {
    toxiclibs code
    vertices = mesh.getUniqueVerticesAsArray();
    triangles = mesh.getFacesAsArray();
    sunflow code
    exit();
    }

    If you want an animation organise your code something like this..

    setup() {
    }
    draw() {
    toxiclibs code
    sunflow();
    }
    sunflow() {
    vertices = mesh.getUniqueVerticesAsArray();
    triangles = mesh.getFacesAsArray();
    sunflow code
    }

    • Vic says:

      Thanks for everything Amnon , everything is working fine now!!
      Im working on a tipography experiment i hope to show you something soon and share the code, so a last cuestion, how can i save every frame rendered to a png or tga image?

      • Amnon says:

        Just like you would do in regular sketches…
        Replace...
        sunflow.render(sketchPath + "/SunflowTestRender.png");
        ...by...
        sunflow.render(sketchPath + "/Sequence/Sunflow_" + nf(frameCount,4) + ".png");

        Note: make sure to create a subdirectory (in this case called “Sequence”) in your sketch beforehand.

  9. DieTapete says:

    Yay!! I’ve been waiting for this! Thanks for sharing! I’m thrilled to try it out!

  10. felix says:

    Got SunflowAPIAPI working with Proclipsing and I’m loving it. Thanks!

    Maybe we should set up a WIKI or similar where we can share code and hints. I’m having some issues that I would love to discuss.

    • Amnon says:

      Perhaps the Processing forum is a good place to start for discussion, questions and sharing of tips, tricks and code. Especially since the api is still very much in development. For example, Christopher has been working on automatic translation, i.e. normal Processing code is translated into sunflow, which would make the syntax easier.

  11. Yang Yang Li says:

    Woa!
    Does that program really create those stunning pictures? What a cool software. Nice blog post about it. The pictures were worth it.

  12. nkint says:

    wow,
    you’re a good guy.
    thanks for code

  13. jose says:

    amazing! thanks a lot for sharing.

    how can we modify the background of the sunflow render? Is this background made with sunflow.setSunSkyLight?

    thanks!

    • Amnon says:

      I’m assuming you’re using HemeshGui. In a sense sunflow.setSunSkyLight causes the background, but mainly it creates the light 🙂 The last TRUE in the function, means it also extends the ground. Anyway, if you wanna get rid of it, you can. But you need to be able to see your objects. So either manually add some other lighting or change to a global illumination option (renderer, material) so that the object is self-illuminating.

      For details on different options check out the Sunflow wiki. Also see the source code for SunflowApiApi to see how you can use these options from within Processing.

      Yet another option (included in HemeshGui) is to render a mask. You can use the mask to accurately seperate the object from the background as well. So you can change the background afterwards.

      • jose says:

        thanks a lot for the quick answer! I’ve been checking the wiki for setting up a shader without success.
        I ‘ve placed this line in the void sunflow() function:

        sunflow.setPhongShader(“myPhongShader”, new Color(1f,1f,1f), new Color(.5f,.5f,.9f), 10, 16);
        just before sunflow.drawMesh( ..

        so this part looks like:

        sunflow.setThinlensCamera(“thinLensCamera”, 50f, (float)sceneWidth/sceneHeight);
        sunflow.setCameraPosition(0, 0, 31.5);
        sunflow.setCameraTarget(0, 0, 0);
        sunflow.setGlassShader(“myGlassShader”, new Color(1f,1f,1f), 2.5f, 3f, new Color(1f,1f,1f));
        sunflow.setShinyDiffuseShader(“myShinyShader”, new Color(shapecolor), .25f);
        sunflow.drawMesh(“myHemesh”, verticesHemeshOneDim, facesHemeshOneDim, actualZoom/20, 0,0,0);

        but the shaders are not used. Sure I’m missing something obvious.

        Thanks for your patience!

  14. Amnon says:

    See this page for an explanation of the Sunflow shaders. Setting shaders from SunflowApiApi works kinda like fill() in Processing. The last shader before the object gets used. Pick one. Depending on the shader, lighting and renderer the result will be as expected… or not 😉 For example, using a glassShader in an environment without lights and surrounding objects will not work well. glassShaders work well if they can reflect some of their environment (see the topmost picture on this page). The only shader that doesn’t need anything else to work is the ambientOcclusionShader cause it is self-illuminating. See the code below. You won’t need lights or sunSky or anything. But to get some shadow going, you will need to apply some modifiers to distort the mesh a bit, for example catmullclark + extrude.

    sunflow.setBackground(0f, 1f, 1f);
    sunflow.setThinlensCamera("thinLensCamera", 50f, (float)sceneWidth/sceneHeight);
    sunflow.setCameraPosition(0, 0, 31.5);
    sunflow.setCameraTarget(0, 0, 0);
    sunflow.setAmbientOcclusionShader("myAmbientOcclusionShader", new Color(shapecolor), new Color(0,0,0), 16, 1);
    sunflow.drawMesh("myHemesh", verticesHemeshOneDim, facesHemeshOneDim, actualZoom/20, 0,0,0);
    sunflow.setAmbientOcclusionEngine(new Color(255), new Color(0), samples, 7.5); // optional
    sunflow.render(sketchPath + "/output/screenshots/" + timestamp + " (sunflow).png");
    createHemesh();

    This is just a basic example. To beautify things for most other shaders, you will need to create a good scene (combination of lights, shaders, other objects, ground, renderer). So that will require some experimenting. My tip would be to try stuff out and use the keyboard shortcut ‘X’ to preview things quickly.

  15. Joss Gray says:

    Im getting a “The package “com.briansteen” does not exist….” ” error. I think i might have my files in the wrong place.

    I have sunflowtest.pde, P5SunflowAPIAPI.java and sunflow-and-janino.jar in the same folder, is this correct?

    Thanks

    • Joss Gray says:

      I realised i am dumb 😛

      btw your blog is awesome!

      • Amnon says:

        Hey Joss (and others running into problems)

        1. Follow the installation instructions in this blog post or the ones from Google Code.

        2. If you run into an error and you have Processing 1.5 also follow the steps from this post.

        Joss, In this specific case there are at least two things that will cause problems. The first is that the sunflow-and-janino.jar should be in the code subdirectory. The second is that you should be using SunflowAPIAPI.java and not P5SunflowAPIAPI.java.

        Good luck! 😀

  16. I seem to be unable to use setDirectionalLight() function.
    I’m not sure if it is an api issue or I’m doing something wrong.
    Could you share a quick snippet for this.

    • Amnon says:

      It should look something like this:

      sunflow.setDirectionalLight("myDirectionalLight", new Point3(-2,3,0), new Vector3(0,1,0), 3, new Color(1f,1f,1f));
      
      • I think in my case the issue was the direction of light – just didn’t make it right.
        It’s charm now, thanks for this, I’m really intrigued about sunflow future.

  17. It’s charm now, thanks for this..

  18. Eric Pavey says:

    Just wanted to say thanks for the post. Have been (lazily) trying to get a sunflow solution working for some time, and this got me going. For reference, all I had to do was download the ‘p5sunflowapiapi_1.zip’ from the google code page, stick it in my Processing libraries folder, and it was up and running. For reference, I’m on a Mac running osx 10.7, Processing 1.5.1. This is the modified version of your above code I used to get your example working:

    import java.awt.Color;
    import sunflowapiapi.P5SunflowAPIAPI;
    import org.sunflow.math.Point3;
    import org.sunflow.math.Vector3;

    int sceneWidth = 1024;
    int sceneHeight = 1024;

    P5SunflowAPIAPI sunflow;

    void setup() {
    size(sceneWidth, sceneHeight, “sunflowapiapi.P5SunflowAPIAPI”);
    sunflow = (P5SunflowAPIAPI) g;
    sunflow.setWidth(sceneWidth);
    sunflow.setHeight(sceneHeight);
    sunflow.setCameraPosition(0, 2.5, -5);
    sunflow.setCameraTarget(0, 0, 0);
    sunflow.setThinlensCamera(“thinLensCamera”, 50f, (float)sceneWidth/sceneHeight);
    sunflow.drawPlane(“ground”, new Point3(0, -3.5, 0), new Vector3(0, 1, 0));
    sunflow.drawSphereFlake(“mySphereFlake”, 20, new Vector3(0, 1, 0), 1);
    sunflow.setPathTracingGIEngine(64);
    sunflow.render(sketchPath + “/SunflowTestRender.png”);
    exit();
    }

    Again, thanks for the great post.

    • tal says:

      I tried this, same versions. I am getting this error when I run it:

      unexpected char: ‘\’

      and then it highlights this line:
      size(sceneWidth, sceneHeight, “sunflowapiapi.P5SunflowAPIAPI”);

      • Amnon says:

        That char \ is not on that specific line, nor anywhere else in the provided code. I suggest you search for it in your code and fix the line that actually holds this char.

  19. Any code available for using HeMesh with Sunflow. I just can’t figure out the steps for getting the vertices/faces to a format for Sunflow.

  20. rjdj says:

    Hi,
    It’s been awhile since there was much discussion on the forum about your use with sunflowAPIAPI. I’m curious if you ever tried Joons Renderer? You mentioned not choosing it because you were already working with sunflowAPIAPI. What led you to not go with it?

    It seems pretty well documented so far and it’s been easy to run (so far). I am interested in working with animation as well. What advice could you provide regarding this?

    awesome work!!
    thanks!

    • Amnon says:

      There was really no good reason I never got into Joons other than path depency (I already had started using and gotten to know the alternative) and time limitations. Also after doing a lot of these GI sketches, I got tired of waiting for them to render and wanted to do some realtime work, so I moved on to other projects. All of this is definitely still an area of interest. I guess the most promising development is the work of Karsten Schmidt on his lux4j luxrender library, because it is gpu-based (read: much, much, much faster) and Karsten’s history of producing awesome Processing libraries. So that might be an alternative that at some point could trump them all.

      See: http://www.flickr.com/photos/toxi/sets/72157627354558360/

      Until then there are all the different sunflow alternatives, a POVwriter and perhaps others for you to play with. 😉

Trackbacks
Check out what others are saying...
  1. […] cleverer than me wrote a Java wrapper for it (the catchily titled SunflowAPIAPI), and another did a tutorial about getting it talking nicely to Processing, which I relied on heavily in getting this working. There is also a Processing library by the same […]

  2. […] https://amnonp5.wordpress.com/2010/09/28/sunflow-processing/ ProcessingProcessing, sunflow ← Particle Video with Processing /* */ […]

  3. […] cleverer than me wrote a Java wrapper for it (the catchily titled SunflowAPIAPI), and another did a tutorial about getting it talking nicely to Processing, which I relied on heavily in getting this working. There is also a Processing library by the same […]

  4. […] reading: Sunflow & Processing by Amnon More images: view the project page on […]