我正在尝试使用 JavaScript 创建一个基于网格的影子引擎。我的算法根据它们的位置是否相对于光源在 block “后面”来对正方形进行着色。
到目前为止,这是我的算法: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;
}
不幸的是,正如您在演示中看到的那样,我发现某些 Angular 存在问题。一些应该加阴影的方 block 没有加阴影。对于某些 Angular 和距离(在光源和 block 之间)会发生这种情况,但不会发生在其他 Angular 和距离上。例如,将光源放置在 (60, 90) 处也会显示这些伪像。
我正在使用向量 LP(从光到点)和 LB(从光到 block ),取它们的点积并除以它们的量级的乘积来找到阴影 Angular ,然后根据距离缩放这个 Angular block 和光源之间。
这些伪像可能是由于舍入误差造成的吗?还是算法本身有问题?任何帮助将不胜感激:-)
最佳答案
好问题。你不会喜欢这个的。
这是一道 float 数学题。
Math.acos(1.000000000000000)
的值是多少?
0
。
Math.acos(1.0000000000000003)
的值是多少?
NaN
。
这很烦人,不是吗?
在某些值下,您的点积
是6000
,您的(vec1_mag * vec2_mag)
是5999.999999999999
,前导针对上述问题。
将 (vec1_mag * vec2_mag)
更改为 Math.round(vec1_mag * vec2_mag)
将解决您的问题。
当我们一起盯着这个 fiddle 看时,您应该知道还有另一个错误:
for (var x = 0; x < canvas.width; x += 10) {
for (var y = 0; y < canvas.width; y += 10) {
你在这里使用了两次canvas.width
。我想第二个应该是 canvas.height
,所以确保你在那里写的是你想要的。
关于javascript - 基于网格的照明引擎,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16878885/