Canvas - Preencha um retângulo em todas as áreas totalmente transparentes

Estou escrevendo um mecanismo de jogo 2D simples usando a tela HTML5. Eu vim para adicionar um mecanismo de iluminação. Cada fonte de luz possui um valor de raio e um valor de intensidade (0-1, por exemplo, 1 seria muito brilhante). Há também um valor de luz ambiente usado para iluminar todo o resto do mundo que não está perto de uma fonte de luz (0-1, por exemplo, 0,1 seria a luz da lua). O processo de iluminação é feito em uma tela separada acima da tela principal:

Para cada fonte de luz, um gradiente radial é desenhado nessa posição com o mesmo raio da fonte de luz. O gradiente recebe duas paradas: o centro é preto com um alfa de 1 intensidade da luz e a extremidade / borda é preta com alfa de 1 valor de luz ambiente. Isso tudo funciona bem. É aqui que dá errado: / Preciso preencher toda a tela com preto com alfa e valor de luz 1-ambiente e, no momento, faço isso configurando o context.globalCompositeOperation para a origem e preenchendo a tela inteira.

O meu código para este material é:

var amb = 'rgba(0,0,0,' + (1-f.ambientLight) + ')';
for(i in f.entities) {
    var e = f.entities[i], p = f.toScreenPoint(e.position.x, e.position.y), radius = e.light.radius;

    if(radius > 0) {
        var g = cxLighting.createRadialGradient(p.x, p.y, 0, p.x, p.y, radius);
        g.addColorStop(0, 'rgba(0,0,0,' + (1-e.light.intensity) + ')');
        g.addColorStop(1, amb);

        cxLighting.fillStyle = g;
        cxLighting.beginPath();
        cxLighting.arc(p.x, p.y, radius, 0, Math.PI*2, true);
        cxLighting.closePath();
        cxLighting.fill();
    }
}
//Ambient light
cxLighting.globalCompositeOperation = 'source-out';
cxLighting.fillStyle = amb;
cxLighting.fillRect(0, 0, f.width, f.height);
cxLighting.globalCompositeOperation = 'source-over';

No entanto, em vez de tirar o que não quero do motor (à esquerda), recebo uma espécie de gradiente invertido (à direita). Eu acho que é porque quando eu desenho o retângulo com osource-out operação composta afeta as cores do próprio gradiente porque são semitransparente

Existe uma maneira de fazer isso de maneira diferente ou melhor? Talvez use recorte ou desenhe um retângulo sobre tudo primeiro?

Também modifiquei o @ do Mozila Dev Centexempla compostagem para replicar o que eu preciso fazer e nenhum dos modos compostos parecia funcionadê uma olhad se isso ajudasse.

Muito obrigado, qualquer resposta seria ótima:)

questionAnswers(2)

yourAnswerToTheQuestion