You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于MiniLibX的C语言光线投射:为何需要纹理镜像校正?

光线投射纹理镜像问题解析

我正在用C语言结合MiniLibX开发类似《Wolfenstein 3D》的光线投射FPS项目,遇到部分墙体纹理镜像的问题,找到修复代码后想搞懂底层原理。相关光线投射函数片段如下:

void raycast(g *g)
{
    // ... [其他光线投射代码] ...

    if (g->side == 0)
        g->wallX = g->posY + g->perpWallDist * g->rayDirY;
    else 
        g->wallX = g->posX + g->perpWallDist * g->rayDirX;
    g->wallX = g->wallX - (int)g->wallX;

    g->texX = (int)(g->wallX * (double)texWidth);
    if (g->side == 0 && g->rayDirX > 0)
        g->texX = texWidth - g->texX - 1;
    if (g->side == 1 && g->rayDirY < 0)
        g->texX = texWidth - g->texX - 1;

    // ... [剩余光线投射代码] ...
}

我知道g->texX是用来确定墙体纹理的X坐标,但搞不懂最后两个if的纹理镜像校正为什么必须。想问两个问题:

  1. 不校正的话,为什么部分墙体会出现纹理镜像?
  2. 条件(g->side == 0 && g->rayDirX > 0)和(g->side == 1 && g->rayDirY < 0)是怎么判断什么时候需要镜像校正的?

问题1:未校正时纹理镜像的原因

光线投射中,wallX是射线击中墙体时在墙面上的水平偏移量(范围0~1)。我们默认wallX=0对应纹理左边缘、wallX=1对应纹理右边缘,但这个对应关系会被射线击中墙体的方向打乱:

  • 当射线向右(rayDirX>0)击中垂直墙体(side=0,比如地图格子的右边界)时,射线是从墙体的右侧撞上去的。此时wallX=0实际对应墙体的右边缘,wallX=1对应左边缘,直接映射纹理坐标的话,纹理就会被左右翻转,也就是镜像。
  • 同理,射线向上(rayDirY<0)击中水平墙体(side=1,比如地图格子的上边界)时,射线从墙体的顶部撞上去,wallX的偏移顺序和纹理默认的左→右相反,直接映射就会出现镜像。

问题2:校正条件的判断逻辑

先明确两个关键变量的含义:

  • side=0:射线击中垂直墙体(X轴方向的墙面,比如地图格子的左/右边界);side=1:击中水平墙体(Y轴方向的墙面,比如地图格子的上/下边界)。
  • rayDirX/rayDirY:射线的方向向量,正负表示射线在对应轴上的走向(rayDirX>0为向右,rayDirY<0为向上)。

两个条件分别对应两种需要翻转的场景:

  1. g->side == 0 && g->rayDirX > 0:
    击中垂直墙体且射线向右发射,此时射线从墙体右侧(格子右边界)撞击,wallX的偏移方向和纹理默认顺序相反,通过texWidth - texX - 1翻转纹理X坐标,让wallX的偏移和纹理的左→右对应,修正镜像。
  2. g->side == 1 && g->rayDirY < 0:
    击中水平墙体且射线向上发射,此时射线从墙体顶部(格子上边界)撞击,wallX的偏移方向和纹理默认顺序相反,同样翻转texX来校正镜像。

其他场景下,射线从墙体左侧(rayDirX<0击中垂直墙)或底部(rayDirY>0击中水平墙)撞击,wallX的偏移顺序和纹理默认一致,不需要翻转。


内容的提问来源于stack exchange,提问作者nathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:46:19