JavaScript Canvas射线投射引擎鱼眼效应校正失效及着色问题求助
射线投射引擎鱼眼校正问题修复与优化方案
校正逻辑失效的常见核心原因
- 三角函数单位不匹配:JS 内置的
Math.cos()接口仅接收弧度制参数,如果你计算rayAngle、player.rot时使用的是角度制数值,直接做差传入余弦函数得到的结果完全偏离预期,校正自然无法生效。 - 角度差未做象限归一化:如果没有把射线角度和玩家朝向的差值折算到
[-π, π]区间,跨象限的角度差会让余弦值符号出错,反而把正常的墙壁拉成反向的弧形变形。
可直接落地的简易校正逻辑
不需要复杂的向量投影运算,按照下面的步骤调整就能稳定解决鱼眼效应:
- 保留你原本计算原始射线行进距离的逻辑,也就是代码里的欧氏距离
d,这部分逻辑是正确的 - 对角度差做归一化处理,消除跨象限的计算误差:
let angleDiff = rays[i].rayAngle - player.rot; // 把角度差循环折算到 -π 到 π 的合法区间 while (angleDiff > Math.PI) angleDiff -= 2 * Math.PI; while (angleDiff < -Math.PI) angleDiff += 2 * Math.PI; - 代入校正公式计算最终渲染用的距离:
const correctedDistance = d * Math.cos(angleDiff);
- 避坑提示:这个校正的本质是把斜向射到墙上的射线长度,折算成垂直于玩家视线平面的投影长度,只要这个投影值算对,原本鱼眼效应造成的墙壁向外凸出的变形会立刻消失,后续绘制竖线时,直接用这个校正后的距离计算竖线高度即可。
引擎着色的实用优化建议
- 着色计算直接绑定校正后的距离值:不要用未校正的原始射线距离算亮度,否则会出现斜向射线位置的墙壁、和正前方同实际距离的墙壁亮度不一致的割裂感。可以提前预设最大可视距离,把亮度值映射为
Math.floor(255 * Math.max(0, 1 - correctedDistance / maxViewDistance)),实现近亮远暗的自然衰减效果。 - 性能优化小技巧:不要每帧对每个屏幕竖线单独计算颜色值,提前把不同距离对应的色值存在一维数组里,绘制时直接按距离索引取色,能大幅降低Canvas逐像素渲染的性能开销。
- 低成本真实感提升:在每道竖线的底部(墙和地面交界位置)做1-2像素的暗化处理,不需要额外加载贴图就能模拟自然的交界阴影,视觉提升非常明显。
内容的提问来源于stack exchange,提问作者Ryan Grube
相关产品推荐
相关产品推荐

