29a.ch

Entries tagged “canvas”

Path tracing a cornell box in Javascript

Last Saturday I have released my little javascript pathtracer that rendered a very simple scene. This time I want to show off some of the more advanced effects that can be simulated nicely using path tracing. I decided to set up a scene similar to the well known Cornell Box to demonstrate effects such as soft shadows, color bleeding, reflection, refraction and caustics. I did not include Depth of Field in this experiment because it didn't fit the scene well in my opinion.

The experiment

cornell box

Click the image to start the rendering. Warning, this experiment is slow. Run it using a fast web browser (google chrome) and be a little bit patient. Opera won't work because it doesn't support web workers.

You might also want to check out my previous path tracing experiment.

Path tracing

Path tracing is a way of solving the rendering equation using monte carlo integration. It is a form of ray tracing. According to wikipedia 'Path tracing is the simplest, most physically-accurate and slowest rendering method'. Sounds like the perfect target for a javascript experiment!

Implementation

The implementation is basically an extended version of the path tracer in my last post. It is using html5 web workers to render the image on up to 4 cores without locking up the page. One of the cool things I came up with is jittering the points on the view plane for each pixel to get rid of aliasing. I also changed the color of the light to that of warm sunlight (~5400k). I probably got the fresnel equations wrong and generally things are quite rough. I'm not an expert in the field of raytracing and I probably did a lot of things in a suboptimal way. But feel free to have a look at the source code (~300 LOC) and ask questions. I think the code should be quite easy to understand.

Please write a comment if you've got anything to say. If you think my experiments are interesting, follow me on twitter or subscribe to my atom feed.

Path tracing in Javascript using web workers

Improved version

An improved version of this path tracer is available here.

The experiment

screenshot

Click to start. If it doesn't work in your browser and it's not IE or Opera, please write a comment. The output of the javascript error console would be very helpful too.

Path tracing

Path tracing is a way of solving the rendering equation using monte carlo integration. It is a form of ray tracing. According to wikipedia 'Path tracing is the simplest, most physically-accurate and slowest rendering method'. Sounds like the perfect target for a javascript experiment!

Implementation

My implementation is currently only calculating the diffuse term of the rendering equation. The only light source is the sky. The big sky speeds up the rendering and convergence quite a lot.

The sourcecode is split up into two files. main.js is the glue for initializing the workers and aggregating the results. worker.js is where you'll find the real meat. I'm spawning four workers right now to take advantage of modern multicore cpus. Feel free to ask questions if something is unclear.

Performance

As you can tell from the sourcecode it is clearly not optimized for performance. What is still interesting though is how various webbrowsers perform. On my Intel Core i7 machine google chrome (4.1) is roughly 26 times faster than firefox (3.6)! Chrome does 13 iterations/s, Firefox does 0.5. Also firefox seems to support only 3 workers, this leaves one core almost idle. The dev version of chrome is even faster at 18.75 iterations/s. My congratulations to the chrome and v8 developers. I hope firefox will catch up soon.

Twitter

On a side note, I created a twitter account for those who prefer it over the rss/atom feeds.
Follow 29a_ch on Twitter

Update

I found a little bug in the code that affected the performance. I'm now getting more than 20.5 iterations/s in chrome dev. I think a faster random function would make it even faster.

Flip Images using HTML5 Canvas

You can flip an Image using HTML5 like this:

// flip x axis
ctx.scale(-1, 1);
ctx.drawImage(img, x, y);
// flip it back again
ctx.scale(-1, 1);

You can flip along the y axis in the same way. I'm note sure how fast this transformation is, in practice so you might need to cache it if you are doing realtime graphics.

Hand drawn lines using javascript canvas


For an upcoming game I'm working on I want the lines to look hand drawn. I found a nice paper on the subject. My algorithm is inspired by that paper, but not an exact implementation. But the results look good anyway. I also wrote a method to draw circles, but it needs improvement. Please let me know if you use it anywhere. :)

// randomize a variable
function fuzz(x, f){
    return x + Math.random()*f - f/2;
}

// estimate the movement of the arm
// x0: start
// x1: end
// t: step from 0 to 1
function handDrawMovement(x0, x1, t){
    return x0 + (x0-x1)*(
            15*Math.pow(t, 4) -
            6*Math.pow(t, 5) -
            10*Math.pow(t,3)
    )
}

// hand draw a circle
// ctx: Context2D
// x, y: Coordinates
// r: radius
function handDrawCircle(ctx, x, y, r){
    var steps = Math.ceil(Math.sqrt(r)*3);

    // fuzzyness dependent on radius
    var f = 0.12*r;

    // distortion of the circle
    var xs = 1.0+Math.random()*0.1-0.05;
    var ys = 2.0-xs;

    ctx.moveTo(x+r*xs, y);

    for(var i = 1; i <= steps; i++)
    {
        var t0 = (Math.PI*2/steps)*(i-1);
        var t1 = (Math.PI*2/steps)*i;
        var x0 = x+Math.cos(t0)*r*xs;
        var y0 = y+Math.sin(t0)*r*ys;
        var x1 = x+Math.cos(t1)*r*xs;
        var y1 = y+Math.sin(t1)*r*ys;

        ctx.quadraticCurveTo(fuzz(x0, f), fuzz(y0, f), x1, y1);
        ctx.moveTo(x1, y1);
    }
}

// inspired by this paper http://iwi.eldoc.ub.rug.nl/FILES/root/2008/ProcCAGVIMeraj/2008ProcCAGVIMeraj.pdf
function handDrawLine(ctx, x0, y0, x1, y1){
    ctx.moveTo(x0, y0)

    var d = Math.sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0))

    var steps = d/25;
    if(steps < 4) {
        steps = 4;
    }

    // fuzzyness
    var f = 8.0;
    for(var i = 1; i <= steps; i++)
    {
        var t1 = i/steps;
        var t0 = t1-1/steps
        var xt0 = handDrawMovement(x0, x1, t0)
        var yt0 = handDrawMovement(y0, y1, t0)
        var xt1 = handDrawMovement(x0, x1, t1)
        var yt1 = handDrawMovement(y0, y1, t1)
        ctx.quadraticCurveTo(fuzz(xt0, f), fuzz(yt0, f), xt1, yt1)
        ctx.moveTo(xt1, yt1)
    }
}

Emulating Canvas fillText in Firefox 3.0

After running into problems with canvas-text I wrote this code to emulate the html5 canvas text methods in firefox 3.0. It's not a complete implementation but it should be enough for most cases.

if(proto.mozMeasureText && !proto.measureText) {
    proto.__defineSetter__('font', function(x) { this.mozTextStyle = x;});
    proto.__defineGetter__('font', function() { return this.mozTextStyle;});
}
if(proto.mozMeasureText && !proto.measureText) {
    proto.measureText = function(text) { return {'width': this.mozMeasureText(text)}; };
}
if(proto.mozPathText && !proto.strokeText) {
    proto.strokeText = function(text, x, y) {
        this.translate(x, y);
        this.mozPathText(text);
        this.stroke();
        this.translate(-x, -y);
    };
}
if(proto.mozDrawText && !proto.fillText) {
    proto.fillText = function(text, x, y) {
        this.translate(x, y);
        this.mozDrawText(text);
        this.translate(-x, -y);
    };
}
Author

Jonas Wagner Jonas Wagner
Software Engineer
Zürich, Switzerland

More about me

Follow 29a_ch on Twitter

Experiments

screenshot screenshot screenshot screenshot

More Experiments

Latest Posts Tags Archive Links

guitarmasterclass.net (guitar lessons)