subuc
subuc

Reputation: 39

Java FX 3D light rendering problem on MacOS

I am trying to use JavaFX3D to display 3D shapes but there is a problem with them rendering. The light is not working properly, filling darker sides with solid black color. I am using Sonoma 14.2.1 on MacBook Air M2 and JAVAFX sdk 21.0.1. I tried using both Java JDK 20 and 17.

The code I used is from this tutorial and expected this result: properly working box render

Instead I result in this: my box render

The same happens to the sphere shape: my sphere render

This is a code I used:

import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.*;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Transform;
import javafx.stage.Stage;

/**
 * @author afsal villan
 * @version 1.0
 *
 * http://www.genuinecoder.com
 */
public class DrawingBox extends Application {

    private static final int WIDTH = 1400;
    private static final int HEIGHT = 1000;

    private double anchorX, anchorY;
    private double anchorAngleX = 0;
    private double anchorAngleY = 0;
    private final DoubleProperty angleX = new SimpleDoubleProperty(0);
    private final DoubleProperty angleY = new SimpleDoubleProperty(0);

    @Override
    public void start(Stage primaryStage) {
        Box box = new Box(100, 20, 50);
        PhongMaterial material = new PhongMaterial();
        material.setDiffuseColor(Color.AQUA);
        box.setMaterial(material);

        SmartGroup group = new SmartGroup();
        group.getChildren().add(box);

        Camera camera = new PerspectiveCamera();
        Scene scene = new Scene(group, WIDTH, HEIGHT);
        scene.setFill(Color.SILVER);
        scene.setCamera(camera);

        group.translateXProperty().set(WIDTH / 2);
        group.translateYProperty().set(HEIGHT / 2);
        group.translateZProperty().set(-1500);

        initMouseControl(group, scene);

        primaryStage.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
            switch (event.getCode()) {
                case Z:
                    group.translateZProperty().set(group.getTranslateZ() + 100);
                    break;
                case X:
                    group.translateZProperty().set(group.getTranslateZ() - 100);
                    break;
                case S:
                    group.rotateByX(10);
                    break;
                case W:
                    group.rotateByX(-10);
                    break;
                case D:
                    group.rotateByY(10);
                    break;
                case A:
                    group.rotateByY(-10);
                    break;
            }
        });

        primaryStage.setTitle("Genuine Coder");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void initMouseControl(SmartGroup group, Scene scene) {
        Rotate xRotate;
        Rotate yRotate;
        group.getTransforms().addAll(
                xRotate = new Rotate(0, Rotate.X_AXIS),
                yRotate = new Rotate(0, Rotate.Y_AXIS)
        );
        xRotate.angleProperty().bind(angleX);
        yRotate.angleProperty().bind(angleY);

        scene.setOnMousePressed(event -> {
            anchorX = event.getSceneX();
            anchorY = event.getSceneY();
            anchorAngleX = angleX.get();
            anchorAngleY = angleY.get();
        });

        scene.setOnMouseDragged(event -> {
            angleX.set(anchorAngleX - (anchorY - event.getSceneY()));
            angleY.set(anchorAngleY + anchorX - event.getSceneX());
        });
    }

    public static void main(String[] args) {
        launch(args);
    }

    class SmartGroup extends Group {

        Rotate r;
        Transform t = new Rotate();

        void rotateByX(int ang) {
            r = new Rotate(ang, Rotate.X_AXIS);
            t = t.createConcatenation(r);
            this.getTransforms().clear();
            this.getTransforms().addAll(t);
        }

        void rotateByY(int ang) {
            r = new Rotate(ang, Rotate.Y_AXIS);
            t = t.createConcatenation(r);
            this.getTransforms().clear();
            this.getTransforms().addAll(t);
        }
    }
}

Edit: We tested it on two other MacBooks, one with Sonoma installed, and one with the older - Ventura version. The Ventura version worked just fine, while Sonoma failed the same way.

Upvotes: 3

Views: 323

Answers (4)

Florian Enner
Florian Enner

Reputation: 494

I submitted a bug report for this a few months ago. From https://bugs.openjdk.org/browse/JDK-8318985:

After debugging with some default values in shaders, it looks like this issue is related to how to we default specular values in shaders. From the Java side even when we don't have specular parameters we set (1, 1, 1, 32) value and in case of OpenGL shader when specular is not set we use (0, 0, 0, 0). If we use 32 specular power with 0 attenuation (0, 0, 0, 32) we see appropriate output. Looks like some of these default values are interpreted differently in aarch64 vs x64 scenario.

Setting the specular color fixed it for me.

Upvotes: 0

Adam Hausknecht
Adam Hausknecht

Reputation: 59

I have found a fix for my program and the basic program above: Under MacOS Ventura, there is no need to specify a PhongMaterial's specular color only the ambient color is necessary, but under MacOS Sonoma, you need to specify both the ambient color and the specular color. This means that, for some reason, the lighting calculations are being done differently.

Upvotes: 2

Adam Hausknecht
Adam Hausknecht

Reputation: 59

Today, I ran my example on a 6-core Intel 16GB iMac running MacOS 14.2.1 without the PointLight-AmbientLight rendering issues. @jewelsea, thanks for following up! I've also read somewhere that Apple depreciated OpenGL in favor of Apple Metal.

Upvotes: -1

Adam Hausknecht
Adam Hausknecht

Reputation: 59

Mesh rendering correctly on a M1 Mac running Mac OS 13.6.3

Mesh Rendering issue on M2 Mac running Mac OS 14.2.1

I also have JavaFX 21 Mesh PointLight/AmbientLight rendering issues on a M2 MacBookPro running Mac OS 14.2.1 (Sonoma) but NOT on an M1 MacBookAir running Mac OS 13.6.3. So this may be a Sonoma 14.2.1 issue. My example program, is from pages 254-267 of the Apress book "JavaFX 8 Introduction by Example", 2014, by C Dea, M. Heckler. G. Grunwald, J. Pereda, and S. Phillips.

Upvotes: 4

Related Questions