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

Arcade中如何让GLSL着色器协同Pymunk与相机正常工作

问题根因

三个核心问题导致绘制错位:

  • 坐标空间不匹配:直接将精灵的世界坐标传入Shadertoy的uniform变量,但Arcade内置Shadertoy默认使用窗口屏幕坐标空间渲染,不会自动应用游戏世界相机的视图、投影变换。世界坐标随相机移动会产生对应偏移和缩放,直接传入屏幕空间着色器,自然会出现特效移动速度快于实体、坐标尺度不符的问题。
  • 渲染流程错误:on_draw中未先激活世界相机就开始绘制着色器特效,且着色器绘制顺序和普通精灵割裂,两类内容没有走同一套坐标变换管线。
  • 参数未同步:初始化Shadertoy时仅传入了窗口初始尺寸,后续窗口resize、相机缩放时没有同步更新Shadertoy的视口、投影参数,进一步放大了坐标错位问题。
修复步骤

1. 修正渲染流程,统一坐标空间

调整on_draw逻辑,所有世界空间内容(普通精灵、着色器特效)必须在激活世界相机后绘制,保证共用同一套视图/投影变换,GUI内容单独切GUI相机绘制:

def on_draw(self):
    self.clear()
    # 激活世界相机,所有游戏内世界对象的绘制都放在这之后
    self.camera.use()

    # 批量绘制普通精灵
    self.bullet_list.draw()
    self.glow_bullet_list.draw()

    # 绘制着色器特效,和普通精灵处于同一坐标空间
    for bullet in self.glow_bullet_list:
        bullet.draw()

    # 切换GUI相机绘制UI元素
    self.camera_gui.use()
    # 此处绘制血条、分数、菜单等UI内容

之前手动用「玩家坐标减相机坐标」算偏移的逻辑可以全部删掉,坐标变换由相机统一处理,手动计算反而会引入额外偏移。

2. 着色器坐标转换适配

修改GlowBall.draw()方法,将精灵的世界坐标通过当前相机的视图、投影矩阵转换为着色器使用的裁剪空间坐标,同时传入相机缩放值修正特效尺寸:

def draw(self):
    # 获取当前激活相机的变换矩阵
    view_mat = self.window.current_camera.view_matrix
    proj_mat = self.window.current_camera.projection_matrix
    
    # 计算精灵在裁剪空间的实际位置
    world_pos = (self.center_x, self.center_y, 0.0, 1.0)
    clip_pos = proj_mat @ view_mat @ world_pos
    
    # 向着色器传参
    self.shadertoy.program['pos'] = (clip_pos.x, clip_pos.y)
    self.shadertoy.program['color'] = arcade.get_three_float_color(self.glowcolor)
    self.shadertoy.program['cam_zoom'] = self.window.current_camera.zoom
    self.shadertoy.render()

对应GLSL着色器中,辉光半径计算需要除以cam_zoom,保证相机缩放时特效显示尺寸符合预期。

3. 同步窗口与相机参数变化

监听窗口尺寸变化事件,同步更新Shadertoy的渲染尺寸,避免视口不匹配:

def on_resize(self, width: int, height: int):
    super().on_resize(width, height)
    self.glowball_shadertoy.resize((width, height))

4. Pymunk物理引擎适配

Pymunk更新的精灵坐标本身就是标准世界坐标,只要按前面的流程统一在世界相机激活状态下绘制,不需要对物理计算出的坐标做额外转换,之前给辉光子弹加力、设置质量的逻辑可以正常保留,不会和渲染冲突。

优化建议
  • 不要使用全屏四边形(quad_2d_fs)绘制单个辉光子弹,否则每颗子弹都会触发一次全屏渲染,性能损耗极大。替换为和精灵碰撞盒尺寸匹配的小矩形面片绘制单个特效,和普通精灵的绘制逻辑对齐即可。
  • 如果使用Arcade 2.6以上版本,推荐直接用SpriteList自带的自定义着色器功能,不需要单独遍历精灵调用draw方法,引擎会自动处理批渲染、坐标变换、相机适配,性能更高也不会出现坐标错位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 14:21:26