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

JavaFX 3D游戏中PointLight无法照亮Z轴正方向法线面的问题

问题分析与解决方案

核心原因

问题出在光源与gameGroup的层级关系:你将PointLight放在根节点root下,所有八面体却都在gameGroup中,且gameGroup会通过RotateTransition进行旋转。JavaFX的3D光照计算依赖节点的局部坐标系,当gameGroup旋转后,其内部八面体的局部Z轴方向发生改变,但根节点下的PointLight不会跟随这个变换,导致光照在gameGroup的局部空间中被“截断”——只有局部Z值小于光源位置的面能接收到光照。

而玩家模型直接在根节点下,和光源处于同一坐标系,所以能正常被全方向照亮;八面体的正面(平行于XY平面)因为法线方向不受Z轴旋转影响,也能接收到光照,这进一步验证了坐标系不匹配的问题。

修复步骤

将PointLight添加到gameGroup内部,让光源和八面体共享同一局部坐标系,随gameGroup一起旋转,这样光照就能在八面体的局部空间中保持全方向特性。

修改OctagonView中的initSceneGraph方法:

private void initSceneGraph() {
    root = new StackPane();

    // build the control layout
    controlsLayout = new VBox();
    switchToEndingButton = new Button("Switch to Ending Scene");
    controlsLayout.getChildren().addAll(new Label("Octagon Game Scene!"), switchToEndingButton);

    // build the 3d game group layout
    gameGroup = new Group();

    int h = 2000;
    int r = 5;
    // set a light on the scene to render colors better
    PointLight l1 = new PointLight(Color.WHITE);
    l1.setTranslateZ(-300);

    // Red line along the x-axis
    Cylinder xAxisRed = new Cylinder(r, h);
    xAxisRed.setMaterial(new PhongMaterial(Color.RED));
    xAxisRed.getTransforms().add(new Rotate(90, Rotate.Z_AXIS));

    // Green line along the y-axis
    Cylinder yAxisGreen = new Cylinder(r, h);
    yAxisGreen.setMaterial(new PhongMaterial(Color.GREEN));

    // Blue line along the z-axis
    Cylinder zAxisBlue = new Cylinder(r, h);
    zAxisBlue.getTransforms().add(new Rotate(90, Rotate.X_AXIS));
    zAxisBlue.setMaterial(new PhongMaterial(Color.BLUE));

    Group axes = new Group();
    axes.getChildren().addAll(xAxisRed, yAxisGreen, zAxisBlue);

    Box player = new Box(60, 100, 30);
    player.setTranslateZ(-200);
    player.setTranslateY(80);
    player.setMaterial(new PhongMaterial(Color.HOTPINK));

    // 将光源添加到gameGroup中,而非root
    gameGroup.getChildren().add(l1);
    root.getChildren().addAll(axes, gameGroup, player, controlsLayout);
}

额外验证点

如果修复后仍有问题,可以检查以下两点:

  • 确认八面体的Box没有设置CullFace.BACK导致背面被剔除(你的代码中未设置,默认值为CullFace.BACK,但如果旋转后背面法线朝向光源,应该能被照亮)。
  • 检查gameGroup是否存在额外的Translate/Rotate变换,避免局部坐标系被意外修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 04:57:05