1

JavaScript を使用してグリッドベースのシャドウ エンジンを作成しようとしています。私のアルゴリズムは、光源に対して、その位置がブロックの「後ろ」にあるかどうかに基づいて正方形をシェーディングします。

これはこれまでの私のアルゴリズムです: https://jsfiddle.net/jexqpfLf/

var canvas = document.createElement('canvas');
canvas.width = 600;
canvas.height = 400;
document.body.appendChild(canvas);
var ctx = canvas.getContext('2d');

var light_x = 90;
var light_y = 110;

var block_x = 120;
var block_y = 120;

requestAnimationFrame(render);
function render() {
    ctx.fillStyle = 'white';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    var vec1_x = block_x - light_x;
    var vec1_y = block_y - light_y;
    var vec1_mag = Math.sqrt(vec1_x * vec1_x + vec1_y * vec1_y);

    ctx.fillStyle = 'black';
    for (var x = 0; x < canvas.width; x += 10)
        for (var y = 0; y < canvas.width; y += 10) {
            var vec2_x = x - light_x;
            var vec2_y = y - light_y;
            var vec2_mag = Math.sqrt(vec2_x * vec2_x + vec2_y * vec2_y);
            var dotproduct = vec1_x * vec2_x + vec1_y * vec2_y;

            var angle = Math.acos(dotproduct / (vec1_mag * vec2_mag));

            if (vec2_mag > vec1_mag && angle < Math.PI / 8 / vec1_mag * 10)
                ctx.fillRect(x, y, 10, 10);
        }

    ctx.fillStyle = 'green';
    ctx.fillRect(light_x, light_y, 10, 10);

    ctx.fillStyle = 'red';
    ctx.fillRect(block_x, block_y, 10, 10);

    requestAnimationFrame(render);
}

onkeydown = function (e) {
    if (e.which == 65)
        light_x -= 10;
    if (e.which == 68)
        light_x += 10;
    if (e.which == 87)
        light_y -= 10;
    if (e.which == 83)
        light_y += 10;
}

残念ながら、デモンストレーションでわかるように、いくつかの角度に問題があることがわかりました。影を付ける必要があるいくつかの正方形は、影を付けずに残されます。これは、特定の角度と距離 (光源とブロックの間) で発生しますが、他の角度と距離では発生しません。たとえば、光源を (60, 90) に配置すると、これらのアーティファクトも表示されます。

ベクトル LP (ライトからポイントへ) と LB (ライトからブロックへ) を使用し、ドット積を取り、それらの大きさの積で除算してシェーディング角度を見つけ、ブロック間の距離に応じてこの角度をスケーリングします。そして光源。

これらのアーティファクトは、丸め誤差によるものでしょうか? それともアルゴリズム自体に問題があるのでしょうか? どんな助けでも大歓迎です:-)

4

1 に答える 1