基于Pygame的自制立方体渲染器屏幕边缘出现畸变的原因是什么
问题原因
你遇到的畸变和光线计算无关,是透视投影的深度轴选择和计算逻辑错误导致的:
你当前代码把X轴作为投影分母(深度轴),但相机移动逻辑修改的是Y、Z轴坐标,当立方体偏离屏幕中心时,深度值(X轴差值)没有对应变化,导致横向/纵向的缩放比例完全错误,就会出现明显的拉伸畸变。
修复方案
只需修改两个部分的代码即可解决:
- 替换投影坐标计算逻辑,采用行业通用的Z轴为深度轴的透视投影规则,适配Pygame的Y轴向下坐标系:
# 把main函数里原来的投影计算代码 for i, point in enumerate(cube): # gets all coords of cube pX = point[0] - camCoord[0] pY = point[1] - camCoord[1] pZ = point[2] - camCoord[2] mpX = pZ / pX mpY = pY / -pX # canvas Y deviation from origin newCoords = coordConvert(mpX * scale, mpY * scale) ... # 替换为以下逻辑 for i, point in enumerate(cube): pX = point[0] - camCoord[0] pY = point[1] - camCoord[1] pZ = point[2] - camCoord[2] # 过滤相机后方的点,避免除零和反向投影 if pZ <= 0: continue # 透视投影核心公式:投影坐标 = 世界坐标 * 焦距 / 深度 mpX = (pX * scale) / pZ mpY = (-pY * scale) / pZ newCoords = coordConvert(mpX, mpY) cubeCoords[i][0] = newCoords[0] cubeCoords[i][1] = newCoords[1] drawCircle(newCoords[0], newCoords[1])
- 调整立方体初始位置和操控逻辑,符合用户直觉:
- 把
moveCubeCoords = [8, -4, -4]修改为moveCubeCoords = [0, 0, 10],让立方体初始位于相机正前方10单位处 - 调整
onEvent的按键映射,让方向键对应相机的上下左右平移:
def onEvent(event): if event.key == pygame.K_UP: camCoord[1] -= camSpeed if event.key == pygame.K_DOWN: camCoord[1] += camSpeed if event.key == pygame.K_RIGHT: camCoord[0] += camSpeed if event.key == pygame.K_LEFT: camCoord[0] -= camSpeed # 可选添加W/S键控制相机前后移动 if event.key == pygame.K_w: camCoord[2] += camSpeed if event.key == pygame.K_s: camCoord[2] -= camSpeed print(camCoord)
修改完成后无论怎么移动相机,立方体都会保持正确的透视比例,不会出现异常畸变。
内容的提问来源于stack exchange,提问作者waffle
相关产品推荐
相关产品推荐

