Edit in JSFiddle

var fernetjs = {};

fernetjs.config = {
    maxParticulas: [50, 200, 50],
    dibujarPoligono: false
};

fernetjs.imagenes = {};
fernetjs.imagenes.fondo = new Image();
fernetjs.imagenes.santa = new Image();

fernetjs.navidad = (function(){
    var reqAnimId,
        lastTime = Date.now(),
        time = 0,
        canvas,
        contexto,
        segmentos= [[99,291],[120,240],[156,218],[198,206],[204,171],[220,140],[237,106],[270,94],[307,108],[328,171],[342,186],[338,232],[357,241],[372,258],[383,282],[390,297],[390,237],[439,230],[446,220],[491,228],[520,227],[532,339]];
    particulas = [[], [], []];
    
    function crearParticulas(indice){
        var max = fernetjs.config.maxParticulas[indice];
        var ps = particulas[indice];
        if(max > ps.length){
            var x = Math.floor((Math.random()*canvas.width));
            ps.push({
                x: x,
                y: -Math.floor((Math.random()*400)+20),
                r: Math.floor((Math.random()*5)+1),
                vx: 0,
                vy: Math.floor((Math.random()*20)+10),
                initX: x,
                sinTime: Math.floor((Math.random()*7000)+3000),
                amp: Math.floor((Math.random()*10)+1),
                opacity: Math.floor((Math.random()*10)+5)/10
            });
        }
    }
    
    function actualizarParticulas(dt, indice){
        var ps = particulas[indice];
        for(var i=0; i < ps.length; i++){
            if (ps[i].colision <= 0 || !ps[i].colision){
                ps[i].x = ps[i].amp * Math.sin(time * 2 * Math.PI / ps[i].sinTime) + ps[i].initX;
                ps[i].y += ps[i].vy * dt;
                
                if (ps[i].y + ps[i].r > canvas.height){
                    ps.splice(i, 1);
                }
                else if(indice === 1 && !ps[i].colision && colisionSegmentos(ps[i])){
                    ps[i].colision = 20;
                    ps[i].initX = ps[i].x;
                }
            }
            else {
                ps[i].colision -= dt;
            }
        }
    }
    
    function colisionSegmentos(particula){
        var c = false;
        var cantVertices = segmentos.length;
        
        for(var i=0, j=cantVertices-1; i<cantVertices; j=i++) {
            if ((( segmentos[i][1] > particula.y) != ( segmentos[j][1] > particula.y )) &&
                (particula.x < (segmentos[j][0]-segmentos[i][0]) * (particula.y-segmentos[i][1]) / 
                 ( segmentos[j][1]-segmentos[i][1]) + segmentos[i][0])) {
                c = !c;
            }
        }
        
        return c;
    }
    
    function actualizar(dt) {
        for (var i=0; i <=2; i++){
            crearParticulas(i);
            actualizarParticulas(dt, i);
        }
    }
    
    function dibujarParticulas(indice){
        var ps = particulas[indice];
        for(var i=0; i<ps.length; i++){
            contexto.beginPath();
            contexto.arc(ps[i].x, ps[i].y, ps[i].r, 0, 2 * Math.PI, false);
            contexto.fillStyle = 'rgba(255,255,255,' + ps[i].opacity + ')';
            contexto.fill();
        }
    }
    
    function dibujar() {
        contexto.clearRect(0, 0, canvas.width, canvas.height);  
        
        contexto.drawImage(fernetjs.imagenes.fondo, 0, 0);
        
        dibujarParticulas(0);        
        
        contexto.drawImage(fernetjs.imagenes.santa, 0, 0);
        
        dibujarParticulas(1);
        
        if (fernetjs.config.dibujarPoligono){
            // segmentos
            contexto.save();
            contexto.beginPath();
            contexto.moveTo(segmentos[0][0], segmentos[0][1]);
            for(var i=1; i<segmentos.length; i++){
                contexto.lineTo(segmentos[i][0], segmentos[i][1]);
            }
            contexto.lineWidth = 5;
            contexto.strokeStyle = 'rgb(255,0,255)';
            contexto.stroke();
            contexto.restore();
        }
        
        dibujarParticulas(2);
    }
    
    function iniciarCanvas() {
        canvas = document.getElementById('canvas');
        if (canvas.getContext){
            contexto = canvas.getContext('2d');
        } 
        else throw new Error("canvas no soportado!");
    }
    
    function loop(){
        var now = Date.now();
        var delta = now - lastTime;
        lastTime = now;
        time += delta;
        
        actualizar(delta/1000);
        dibujar();
        
        reqAnimId = window.requestAnimationFrame(loop);
    }
    
    return {
        
        iniciar: function() {
            if (!canvas)
                iniciarCanvas();
            
            if(reqAnimId)
                this.detener();
            
            loop();
        },
        
        detener: function() {
            window.cancelAnimationFrame(reqAnimId);
            reqAnimId = 0;
        }
    }
  
})();

var carga = 0;
fernetjs.imagenes.fondo.onload = function() { carga++; iniciar(); };
fernetjs.imagenes.santa.onload = function() { carga++; iniciar(); };

fernetjs.imagenes.fondo.src = 'http://fernetjs.com/wp-content/uploads/2013/12/bg.png';
fernetjs.imagenes.santa.src = 'http://fernetjs.com/wp-content/uploads/2013/12/santa.png';

function iniciar(){
    if (carga === 2) {
        fernetjs.navidad.iniciar();
    }
}
//detener:
//fernetjs.navidad.detener();

$("#debug").on("click", function(){
   fernetjs.config.dibujarPoligono = !fernetjs.config.dibujarPoligono;
});

/*
$("#canvas").on("click", function(e){
    var offset = $(e.target).offset();
  var pos =  {
    x: e.pageX - offset.left,
    y: e.pageY - offset.top
  };
  $("#coords").append(",[" + pos.x + "," + pos.y + "]");
});
*/



<a id="debug" href="#">mostrar/ocultar segmentos</a>
<br/>
<canvas id="canvas" width="600" height="600"></canvas>
<label id="coords"></label>
canvas {
    border: solid 1px silver;
    background-color: black;
}