Clap your hands say yeah right

Archive for the 'Verso Renderer' Category

Verso, EOL

Just descided to give up on the Verso thing. I realize that the next step would be to implement some modern form av global-illumination (such as Bidirectional Metropolis Light Transport or Energy Redistribution Path Tracing). That requires more time, careful analysis and deeper insights than I currently have. I might get back to the Verso efforts again some day … in another 15 years or so.

BTW. If you’re interested in a snapshot of the current state-of-the art when it comes to unbiased-renderers, just have a look at these:

Commercial: http://www.maxwellrender.com/
Free: http://www.indigorenderer.com/

1 comment

Depth of field

I enhanced the camera model slightly. Now it handles depth of field quite ok … as can be seen on the thumbnail on the right (click it).

The depth of field is controlled by two additional parameters to the camera primitive, focal distance and lens size. The former defines how far from the camera the things in focus will be, the latter how blurry it gets the farther away we get from the focal plane.

The lens was approximated as a circle. While being simple, it is somewhat incorrect. The diaphragm blades in a real camera do not form a hole that is perfectly circular. For instance most Hasselblad lenses have 5 blades which will give a pentagon, while most hobbyist SLRs have 6 blades giving a hexagon. It would be rather straightforward to also add parameters for the number of diaphragm blades and their curvature and sample a N-gon instead of a circle … but I don’t think the time spent on it will be justified by the very slight visual enhancement.

A final word. The lens-size in the image above is set to 3 which is rather high given the size of the geometry in that model. For a slightly more realistic setting see this.

2 comments

Verso the cluster (shine K9, shine)

Nothing new when it comes to the actual rendering routines. I just want to describe how I implemented collaborative rendering in Verso. It came out very well in just a few lines of code thanks to a third party product (together with the desire to keep the system as insanely simple as I can).

My prerequisites:

  • Clustered rendering should take a minimum (preferably none) config-effort.
  • Distributing a new rendering-kernel (new code) to the slaves should be automatic.
  • Preferably I’d like to avoid installing anything on the helper nodes. It should be easy to jump in for anyone who has some CPU-cycles to share.
  • The clustering must not make the system more complex or harder to understand, or in any aspect bulky.

My solution:
I embedded a minimal web server (jetty) in the rendering system. This server is started alongside the rendering process. This server just sits there silently and does not interfere with the rendering, unless we connect to it from another machine.

The web server presents a minimal static web application that just serves a java applet to anyone connecting to it. The applet is a tiny boot strapper for the rendering. The codebase for the served java applet is (you guessed it) the same as my classes path in my application. Hence I get rendering-kernel-distribution for free – any helper-node connecting to the master will get the same code as the master runs.

When the applet starts it just queries the server for the scene-data which is sent as a serialized object from the server to the client. This is all the new helper-node needs to get going.

Whenever the helper-node has a frame (a predefined size of rendered data) ready it http-POSTs the result (as a zipped datastream) to the server who just unzips the data and add the contribution to the picture currently being rendered.

Rather powerful and totally non-interfering codewise. Just three minimal servlets, an applet and a jetty-jar.

The picture above was just my test-picture for the clustering. 9 white dogs colored by three omni-lights in different colors rendered collaboratively on three nodes. The shadows on the floor came out quite nice.

No comments

Verso anisotropic

I was fed-up following my initial roadmap and was looking for something quick to implement. I decided to go for Ashikhmin-Shirley anisotropic shading model which seemed easy enough and would give me a high visual impact.

I was wrong. In both aspects.

First of all it took more time to get it right than I expected. The reason for this was a bug in another part of the code. When a ray intersects a primitive I store some needed information about the actual intersection. For instance I need a local coordinate system (an ON-base) around the intersection point. To find this ON-base I let the surface normal be the w-base and two orthogonal surface-tangential vectors be the u- and v-bases. Unfortunately initially I had got this thing slightly wrong why the shading-routine got an “ON-base” that hadn’t orthogonal bases. Since it is anisotropic it needs a correct set of tangential-vectors.

Secondly, it didn’t look as good as I hoped. Well no. Probably due to the fact that I am still in ray-tracing-land which give me no global-illumination-contribution. Must take the step into path-tracing land … and I better make it soon or I’ll probably get fed up with the whole verso-thing.

And speaking of that (not looking good) … I made a minor hack to at least get some soft shadows. I took the 3 point-lights available in the scene and split each into some hundred new point-lighs all with only a fraction of the power of the original one. Then I distributed this cloud of “micro-lights” randomly in a sphere around the point where the original point-light had been (like creating a homogenous bulb almost). The result of this hack came out pretty good although this is not the way to do it in the long run. A few lines of code.

[ftf w="470" h="270" def="js.xml"]
private void distributeLights() {
distributedLights = new ArrayList ();
int SAMPLES = 750;
double RADIUS = 2500;

for (Light light : lights) {
Point pos = light.getPosition();
Color dColor = light.getColor().scale(1.0 / SAMPLES);
for (int i = 0; i < SAMPLES; i++) {
// Generating random spherical offset.
Vec offset = new Vec(Math.random(), Math.random(), Math.random());
offset = offset.normalize().scale(Math.sqrt(Math.random()) * RADIUS);

// Offset microlight in this direction
Light microLight = new OmniPointLight(pos.translate(offset), dColor);
distributedLights.add(microLight);
}
}
}
[/ftf]

By the way. I use a rescaled version of Schlicks estimate for the freshnel-coefficent: http://www.iit.bme.hu/~szirmay/fresnel.pdf

No comments

Verso, step 3 (Bulldog fields forever)


Did some final fixes:

  • Made instancing work properly. Now the bounding boxes from the object-local-coordinate system is transformed into world-coordinates and expanded to be axis-aligned … as it of course should have been all the time.
  • Added the acceleration structure (HBV) on a more global level as well. Now all objects are globally spatially ordered (as a big rather low-resolution HBV) and at a lower level each mesh is subdivided in a mesh tight HBV.
  • Made it optional to declare that an instance or primitive in the scene should not be part of the HBV.
  • Added very rudimentary per-instance material (still only naïve phong … but in different colors … wohoo!).
  • Cleaned up code. Separated geometry from shading.

Of course I had to test the new features by instancing 196 bulldogs (click thumbnail to see more dogs) in different colors and with different local-to-world transformation matrices. Sort of a bulldog-vector-field. The rendering time for the 800×800 at 12 samples per pixel with 2 shadow-feeler-rays per intersection of this scene containing 3.000.000 triangles took 986 seconds.

(To add some relevance to the figures: All renderings are done on a 3½ year old Dell latitude laptop. Pure 1.5 J2SE java.)

1 comment

Next Page »