news : LiAR sponsors PHD-Motorsports team

November 22nd, 2005 by bramz

LiAR isn’t a raytracer is pleased to announce that it has become the official sponsor of PHD-Motorsports, the Ghent-based racing team owned by Victor De Muer. The team is currently competing in the VRL Live For Speed WinterTrophy 2005.

Last week, LiAR CEO Bram de Greve was contacted by De Muer in search of funds for his team. Both bosses agreed that LiAR will commit to a long-term financial backing of PHD-Motorsports. In return, the corporate logo will be prominently displayed on the team’s racing cars starting from the next championship race on December 4, 2005 in Blackwood.

“It’s a great opportunity for us”, de Greve said. “We’ll be able to showcase our technology that naturally fits the fast cars of PHD-Motorsports. And I also know team member Tom De Muer from his work on LASS, so I have great confidence in their performance.”

Stay tuned for renders of the team’s racing cars. Meanwhile, be sure to check out the team news on their homepage www.phd-motorsports.com.

bramz' diary : snow owl

November 20th, 2005 by bramz

A render of a low poly owl modeled by Wim Verbrugghe. The vertex normals are generated using the smoothNormals() function that’s now available on TriangleMesh. However, this seems to bugger up the wings, so the wings use face normals instead.

low poly owl with texture.  Model courtesy Wim Verbrugghe

bramz' diary : stanford bunny

November 20th, 2005 by bramz

This day, I’ve been mostly rendering … bunnies

render of Stanford Bunny with checker volume texture.   Model by Stanford University Computer Graphics Laboratory

That’s right, I can import models in PLY format now. This format is used by the Standford University Computer Graphics Laboratory for its ever-popular 3D Scanning Repository. The importer is written as a python script src/tools/ply.py. There’s also an example in examples/tools.

(model by Stanford University Computer Graphics Laboratory)

news : triangle meshes added to CVS

November 19th, 2005 by bramz

The code for the triangle meshes is to the CVS. There are also a lot of other minor changes. It’ll probably take a few hours for the anonymous CVS to catch up though. You will also need to upgrade your LASS installation.

bramz' diary : motion blur

November 16th, 2005 by bramz

You can’t properly render fast cars without motion blur, can you? Motion blur is something that’s already in LiAR’s feature set for some time, so I tried it out on the triangle mesh. And here it is …*drumroll* …

fast car with motionblur

This is a scaled down/cropped version of a 2000×1500 image with 16 samples per pixel. This roughly agrees with 256 samples per pixel in the image being displayed.

Adding motion blur to a ray tracer is actually pretty easy. You add an shutter opening and closing time to the camera, and to each sample being rendered you assign a time stamp. You pick these time stamps at random from a uniform distribution between opening and closing time. You also must have a special scene object which applies a time dependent translation to the object to be moved. When you check for intersection, you simply apply the correct translation with respect to time.

In LiAR, this special scene object is called MotionTranslation and is able to apply a linear non-accelerated motion to a child object. It takes a child object, an initial position and a velocity vector as arguments.

There’s also one extra aspect that has to be taken care of: bounding boxes. Many acceleration techniques use bounding boxes to simply a object. And since this is better time independent, you must take care that the bounding box bounds all possible positions of the object (you don’t want to build that AABB tree for each time stamp being sampled, do you?). For a linear non-accelerated motion this is pretty simple: you simply join the bounding boxes of the models at opening and closing time. If you want to take acceleration into account as well, you must take care of other extrema that can be in between …

Oh, btw, obviously the car is moving forward ;)

bramz' diary : triangle meshes OK, but still slow

November 15th, 2005 by bramz

I’ve managed to get the triangle mesh rendering correct now … But it is waaaaay to slow … Currently there’s an AABB tree in there for spatial subdivision, but apparently, that’s not a good choice. I’m trying to clean up the triangle mesh’s source code a bit so I can commit it to the CVS. There are also changes in LASS to make this work, so that will have to be updated as well …

LiAR rendering a triangle mesh ...

There will also be a new folder src/tools which will contain python scripts for file importers and stuff like that … Currently, there’s one: wavefront_obj.py to import wavefront OBJ files (this is of course entirely unrelated to the fact that the first model rendered by LiAR was a OBJ file ;) )

On a sidenote: I’m working to get Depth of Field in LiAR … shouldn’t be much of a problem, stay tuned to see the results!

bramz' diary : triangle meshes, not quite there yet …

November 12th, 2005 by bramz

I’ve been trying to hack together a triangle mesh today. I think i’ve must have made a mistake somewhere … :( Well, tomorrow is another day …

triangle meshes ... still not there yet!

PS: tomz, I don’t have the texture for that car!

bramz' diary : ray differentials & texture anti-aliasing

November 12th, 2005 by bramz

On Mercury’s request, I’ve been playing with ray differentials and texture filtering this week. Ray differentials are essentially derivatives of the viewing ray with respect to the image plane. They give us an estimation of how much of the surface being hit is covered by one pixel on the image plane, the ray’s “footprint”. This can be used for proper texture filtering. There’s a great paper on that topic by Homan Igehy. The idea is that when a viewing is reflected or refracted, you properly recalculate the ray differentials to simulate the divergent effect you get when hitting for example a reflecting sphere.

Of course, to see the full effect of ray differentials, you need proper texture filtering. the Image texture already had mipmapping and trilinear filtering, which was nice. But I also wanted a box filter for the CheckerBoard texture used in the previous post. As usual, a axis aligned box is estimated based on the ray differentials. Then the checkerboard function (1 for texture A, 0 for texture B) is integrated over this box. This turned out to be a little bit tricky. I estimate the integral first by counting complete tiles in the box, to correct it on each side with partial tiles. The key of this is to know what’s the integral over the box (0, 0) to (du, dv) if du < 1 and < 1. It turns out to be the following with sx and sy the split values of the checkerboard pattern (usually 1/2 and 1/2)

min(du, sx) * min(dv, sy) + max(du – sx, 0) * max(dv – sy, 0)

The resulting code can be found in src/textures/checker_board.cpp on the CVS.

Below, I’ve added a render of a reflecting and refracting sphere on a checkerboard pattern to illustrate the effect. The script is on the CVS: examples/textures/anti_aliasing.py. The reflecting sphere looks OK, but the refracting one still has problems. I’ve magnified it in the bottom picture. There’s a large region that is way to blurry. I’ve indicated the edges of this region so you can clearly see this isn’t what’s supposed to happen. I suspect the problem is either in the code to refract a ray differential, or in the differential geometry of the sphere. To be continued …

reflecting and refracting sphere on a checkerboard pattern.  rendered by examples/textures/anti_aliasing.py

problems with refracting sphere

bramz' diary : reflection & refraction

November 6th, 2005 by bramz

I’ve added reflection and refraction to the Simple shader. It was pretty easy, just implementing what i’ve written down in my article Reflections & Refractions in Raytracing. In this implementation, the refraction index is a property of the shader though and it is given as n2 / n1.

To implement reflections and refraction, there’s also the problem of maximum ray depth to be solved. Because you use a recursive algorithm, you may get infinite loops if you don’t take appropriate measures. One way to do that is to add age (recursion depth) to the view ray, but this must be incremented on each castRay call (easy to forget). But since the ray tracer isn’t thread safe anymore anyway, it’s easier and safe to keep state of this in the ray tracer itself: increment age when entering the function, decrement on exit.

Now the Simple shader can do most traditional ray tracer “tricks”, as is shown. The image is rendered using the simple.py script you can find in the folder examples/shaders in the CVS.

rendered by examples/shaders/simple.py

bramz' diary : passing light samples to shaders

November 6th, 2005 by bramz

When the shader is called, it of course need to know what light is reaching its surface. Initially, the shader would call each light for samples and check wether they are obstructed or not. Also, when combined with photonmapping, the shader would have to query the photonmap. All this was a bit too much logic to put on the shader’s burden. So it was decided to move this light sampling to the different ray tracer classes, and to provide the shader a vector of light samples. Each with a direction and radiance. The DirectLight ray tracer would create light samples of direct light only, the PhotonMapper would also query its photonmap to construct these light samples. At the end, the shader must only loop over the light samples which results in a much simpler loop.

When this scheme was applied, a new std::vector was created on the stack for each call for light samples. Unfortunately, this fragmented the heap catastrophically. We had to change it so that it uses one std::vector that is member of the ray tracer, and we give the shader a pair of iterators to a range of light samples that are always stored in this std::vector. Unfortunately, that renders the ray tracer object very much thread unsafe. Thus if we’re going to use threading, we’ll have to find a solution for this