基于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的纹理镜像校正为什么必须。想问两个问题:
- 不校正的话,为什么部分墙体会出现纹理镜像?
- 条件
(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为向上)。
两个条件分别对应两种需要翻转的场景:
g->side == 0 && g->rayDirX > 0:
击中垂直墙体且射线向右发射,此时射线从墙体右侧(格子右边界)撞击,wallX的偏移方向和纹理默认顺序相反,通过texWidth - texX - 1翻转纹理X坐标,让wallX的偏移和纹理的左→右对应,修正镜像。g->side == 1 && g->rayDirY < 0:
击中水平墙体且射线向上发射,此时射线从墙体顶部(格子上边界)撞击,wallX的偏移方向和纹理默认顺序相反,同样翻转texX来校正镜像。
其他场景下,射线从墙体左侧(rayDirX<0击中垂直墙)或底部(rayDirY>0击中水平墙)撞击,wallX的偏移顺序和纹理默认一致,不需要翻转。
内容的提问来源于stack exchange,提问作者nathan
相关产品推荐
相关产品推荐

