torutkのブログ

ソフトウェア・エンジニアのブログ

JavaFX 3Dの動く環境、動かない環境


JavaOne 2013 SFで、いくつかJavaFX 3Dのセッションを聴講したので、簡単な3D表示プログラムを動かしてみたくなりました。自宅・職場のPCでプログラミングして実行したところ、PCの環境によって動いたもの、動かないものがありました。

試してみた環境

Javaは、JDK 8 b108または109です。

ノートPC(1)

2,3年前のモデルで、CPUはIntel Core i7 640M(Nehalemアーキテクチャ)、グラフィックスはCPU内蔵のIntel HD Graphics、OSはWindows 7 32bit、です。

このPCでは、JavaFX 3Dプログラムは実行可能なものの3Dシェープが表示されません。JVM起動オプションに-Dprism.verbose=trueを指定してログを見ると、

  • Direct3D初期化に失敗
    • ドライバのバージョンが古いので8.15.10.2302以上にアップデートせよ
  • Prismソフトウェアパイプラインにフォールバック
  • ConditionalFeature.SCENE3Dをサポートせず

といった内容のメッセージが出ています。

次がログの主要部分(抜粋)です。

Prism pipeline init order: d3d sw 
Using platform text rasterizer
Using native-based Pisces rasterizer
Using dirty region optimizations
Not using texture mask for primitives
Not forcing power of 2 sizes for textures
Using hardware CLAMP_TO_ZERO mode
Opting in for HiDPI pixel scaling
Prism pipeline name = com.sun.prism.d3d.D3DPipeline
Loading D3D native library ...
	succeeded.
D3DPipelineManager: Created D3D9 device
Direct3D initialization failed
Adapter validation failed for all adapters
Device "Intel(R) HD Graphics" (\\.\DISPLAY1) initialization failed : 
WARNING: bad driver version detected, device disabled. Please update your driver to at least version 8.15.10.2302
(X) Got class = class com.sun.prism.d3d.D3DPipeline
GraphicsPipeline.createPipeline: error initializing pipeline com.sun.prism.d3d.D3DPipeline
*** Fallback to Prism SW pipeline
Prism pipeline name = com.sun.prism.sw.SWPipeline
(X) Got class = class com.sun.prism.sw.SWPipeline
Initialized prism pipeline: com.sun.prism.sw.SWPipeline
 vsync: true vpipe: false
10 12, 2013 3:07:48 午後 javafx.scene.PerspectiveCamera <init>
WARNING: System can't support ConditionalFeature.SCENE3D
10 12, 2013 3:07:48 午後 javafx.scene.paint.Material <init>
WARNING: System can't support ConditionalFeature.SCENE3D
10 12, 2013 3:07:48 午後 javafx.scene.paint.Material <init>
WARNING: System can't support ConditionalFeature.SCENE3D
10 12, 2013 3:07:48 午後 javafx.scene.shape.Shape3D <init>
WARNING: System can't support ConditionalFeature.SCENE3D
10 12, 2013 3:07:48 午後 javafx.scene.LightBase <init>
WARNING: System can't support ConditionalFeature.SCENE3D
10 12, 2013 3:07:48 午後 javafx.scene.Scene <init>
WARNING: System can't support ConditionalFeature.SCENE3D
10 12, 2013 3:07:48 午後 javafx.scene.Scene$7 invalidated
WARNING: System can't support ConditionalFeature.SCENE3D
10 12, 2013 3:07:49 午後 javafx.scene.shape.Mesh <init>
WARNING: System can't support ConditionalFeature.SCENE3D
QuantumRenderer: shutdown

Intelのサイトを見ると、次のドライバダウンロードページから最新ドライバ(15.22.58.2993)がダウンロード可能となっていました。

これを入れることができれば動作するかもしれませんが、PCメーカーがカスタマイズしたドライバが入っているので、更新できないとエラーになってしまいました。
メーカーはドライバの更新をしてないので、難しいです。

(追記)いったんディスプレイドライバーを削除します。すると、再起動がかかってVGA(640x480)の低解像度となるので、そこでIntelから入手したドライバーをインストールします。これでJavaFX 3Dがうごくようになりました。

ノートPC(2)

8年前のモデルで、CPUはPentium M 750(Dothanアーキテクチャ)、グラフィックスは GeForce GO 6200 with TC、OSはWindows XP 32bitです。

このPCでは、jdk 8 b109をインストールするときに警告(Windowsの新しいバージョンしかサポートしませんよ)が表示されますが、インストールは続行できます。JavaFX 3Dのプログラムを実行して画面表示されました。

グラフィックスドライバの更新も不要でした。

デスクトップPC

自作PCで、CPUはAMD Phenom II 1055T、グラフィックスはAMD Radeon HD5750、OSはWindows 7 64bitです。

このPCではJavaFX 3Dは問題なく表示されました。

JavaFX 3Dの単純なプログラム

JavaFX 3DのいわゆるHello World的なプログラムを探してみました。見つかったのは次ですが、やはりちょっと複雑です。

球と立方体を表示するサンプルです。

JavaFX公式ドキュメントの一つです。ちょっと複雑なサンプルです。

そこで、球体を1つだけ表示する超入門サンプル作りにチャレンジしました(これが難物でした・・・)。

最初の取り組み、真っ白な表示

まず、空っぽのシーングラフを表示するJavaFXアプリケーションのスケルトンを記述します。

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Group;

public class Hello extends Application {

    @Override
    public void start(Stage stage) {
	Group root = new Group();
	Scene scene = new Scene(root, 640, 480);
	stage.setTitle("Hello JavaFX 3D World!");
	stage.setScene(scene);
	stage.show();
    }

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

これを実行すると中身が真っ白のウィンドウが表示されます。

次に、3次元の球体を表現するシェープSphereをシーングラフに追加します。

--- Hello.java.1        2013-10-12 22:22:57.900452400 +0900
+++ Hello.java  2013-10-12 22:30:07.583576200 +0900
@@ -2,12 +2,15 @@
 import javafx.stage.Stage;
 import javafx.scene.Scene;
 import javafx.scene.Group;
+import javafx.scene.shape.Sphere;
 
 public class Hello extends Application {
 
     @Override
     public void start(Stage stage) {
        Group root = new Group();
+       Sphere Sphere = new Sphere(200);
+       root.getChildren().add(Sphere);
        Scene scene = new Scene(root, 640, 480);
        stage.setTitle("Hello JavaFX 3D World!");
        stage.setScene(scene);

これを実行すると先ほどの中身が真っ白のウィンドウが表示されるだけでした。

JavaFX 3Dには、カメラという概念があり、3次元上の物体をパースペクティブ表示する際の視線の位置や方向を指定します。この視線が定まって始めて3次元上の物体が2次元である画面に描画されます。カメラの定義がないと、3次元空間の物体が2次元の画面に描画できないので、カメラの定義を追加します。

--- Hello.java.2        2013-10-12 22:35:38.448159400 +0900
+++ Hello.java  2013-10-12 22:55:46.012454400 +0900
@@ -3,6 +3,8 @@
 import javafx.scene.Scene;
 import javafx.scene.Group;
 import javafx.scene.shape.Sphere;
+import javafx.scene.Camera;
+import javafx.scene.PerspectiveCamera;
 
 public class Hello extends Application {
 
@@ -12,6 +14,8 @@
        Sphere Sphere = new Sphere(100);
        root.getChildren().add(Sphere);
        Scene scene = new Scene(root, 320, 320);
+       Camera camera = new PerspectiveCamera();
+       scene.setCamera(camera);
        stage.setTitle("Hello JavaFX 3D World!");
        stage.setScene(scene);
        stage.show();

すると、なにやら球体っぽい表示が出ました。

まず、デフォルトのカメラ(PerspetiveCamera)はコンストラクタの引数なしの場合、画面左上隅を原点(0, 0, 0)とした座標系(2Dと同じ)となります。
シーンに球体を半径100で作成したので、位置は球体中心が(0, 0, 0)となります。そのため、このような表示になります。

なお、カメラには視野角(Field of View)、クリッピング面などいくつもパラメータがありますが、ここでは考えないことにします。

このあと、球体の材質、色、位置の指定や、光源の指定などをするのですが、その指定方法はまたいずれ・・・