【问题标题】:JOGL canvas in JavaFXJavaFX 中的 JOGL 画布
【发布时间】:2018-10-09 20:07:06
【问题描述】:

在 JavaFX 场景中获取 JOGL 画布/面板时遇到问题。我的假设是,如果 JOGL GLCanvas 遵守 awt.Canvas 的合同,那么将它放在 JFX 场景中应该没有问题。

我收集了以下代码(所有 sn-ps 都在 JFX Application::start 中)。

首次创建 JOGL“hello world”(脉动背景只是为了查看物体是否渲染和移动):

GLCanvas glCanvas = new GLCanvas();
glCanvas.setSize(size-10, size-10);
glCanvas.addGLEventListener(new GLEventListener() {
    private final long t0 = System.currentTimeMillis();
    @Override
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
    @Override
    public void init(GLAutoDrawable drawable) {
        new Thread(() -> {while (true) glCanvas.display();}).start();
    }
    @Override
    public void dispose(GLAutoDrawable drawable) {}
    @Override
    public void display(GLAutoDrawable drawable) {
        GL4 gl = drawable.getGL().getGL4();
        float t = (float)(Math.sin((System.currentTimeMillis()-t0)/1000f)+1)/2f;
        gl.glClearColor(t, 1-t, 0, 1);
        gl.glClear(GL4.GL_COLOR_BUFFER_BIT);
    }
});

GLJPanel glPanel = new GLJPanel();
glPanel.add(glCanvas);
glPanel.setBackground(Color.BLUE);

另一种你好世界(不动,这显然有效):

Canvas awtCanvas = new Canvas() {
    @Override
    public void paint(Graphics g) {g.fillRect(0, 0, getWidth(), getHeight());}
};
awtCanvas.setSize(size-10, size-10);

JPanel swingPanel = new JPanel();
swingPanel.add(awtCanvas);
swingPanel.setBackground(Color.BLUE);

然后将测试代码放在一起:

if (jfx) {
    SwingNode swingNode = new SwingNode();
    swingNode.setContent(swingPanel);
    primaryStage.setScene(new Scene(new Group(swingNode), size, size+30));
    primaryStage.show();
} else {
    JFrame frame = new JFrame();
    frame.setSize(size, size+30);
    frame.add(swingPanel);
    frame.setVisible(true);
}

参考解决方案JFrame(Panel(Canvas()))JFrame(JPanel(GLCanvas()))JFrame(GLJPanel(GLCanvas() )) 按预期工作(有点,GLPanel 似乎忽略了背景颜色设置)。

当我尝试非 JOGL 包装器 Stage(Scene(Group(JPanel(Canvas()))) 时,按预期工作(JFX 工作)。

现在对于 JOGL,包装器 Stage(Scene(Group(JPanel(GLJPanel(GLCanvas())))) 在画布内容应该存在的地方生成黑色。包装器 Stage(Scene(Group( JPanel(GLCanvas())))(跳过使用 GLJPanel)不会为画布内容生成黑色方块,我只会为 JPanel 生成蓝色方块。

我在互联网上发现的唯一提及来自 2012/2013 年,它似乎不起作用(但当时似乎 SwingNode 不存在),以及 2016 年在 JOGL 论坛上链接到 bugzzila 中的死链接。

【问题讨论】:

  • 即使它会起作用 - 性能也会非常非常糟糕。 JavaFX 需要获得 DirectRendering-Node 的真正解决方案,您可以在其中使用您想要绘制的任何技术(JOGL、LWJGL、Native ......)进行绘制。目前正在讨论如何实现这样的节点,所以订阅 openjfx-Mailing 列表(或者你可能想关注我的博客)看看这是否会实现
  • 不如试试 NewtCanvasJFX(从 JOGL 2.4 开始):github.com/sgothel/jogl/blob/master/src/newt/classes/com/jogamp/…

标签: java swing javafx awt jogl


【解决方案1】:

出于绝望,尝试使用 GLJPanel 而不是 GLCanvas,并且它有效。有点像。

SwingNode 调整大小存在问题 - 它有一个不允许轻松调整大小的错误(OracleJDK 的错误已经有一段时间了,OpenJDK 似乎已经解决了)

调整大小问题的建议解决方案是在场景上放置宽度/高度属性监听器,并在每次大小更改时重新插入画布:

Dimension dim = new Dimension((int)scene.getWidth(), (int)scene.getHeight());
ChangeListener<Number> stageSizeListener = (obs, prev, next) -> {
    dim.setSize(scene.getWidth(), scene.getHeight());
    component.setSize(dim);
    swingNode.setContent(swingPanel);
};
scene.heightProperty().addListener(stageSizeListener);
scene.widthProperty().addListener(stageSizeListener);

这适用于问题中的代码,但每次重新插入都会触发 dispose(GL)init(GL) 循环,这对于某些应用程序可能没问题,而不是在我的案例。

决定做一些小改动,使 GLJPanel 的大小达到某个允许的最大分辨率(比如 4K,无论如何我都会先渲染到屏幕外缓冲区),以所需的分辨率渲染,在面板的左上角显示结果,并将 JFX 场景中的面板裁剪为相同的分辨率。

正如 tomsontom 提到的,性能不是很好,GLJPanel 本身比 GLCanvas 慢得多(从 800FPS 到 40FPS 的 4K ),而在 SwingNode 中它变得更糟(4K 时为 17FPS)。将尽可能推迟 JFX 的使用,并希望他们在即将与 JDK 分离时修复 SwingNode,甚至获得 DirectRenderingNode

【讨论】:

  • 真正的问题在我们的错误跟踪器中得到了解释,OpenJFX/JavaFX 没有等效的 Java AWT 本地接口,它阻止我们实现持久的解决方案,而我们为 AWT、SWT 和 Swing 实现了它.
  • @gouessej 这种情况到 2020 年有没有改变?让 JOGL 与 JavaFX 一起工作。
  • @BAR 是的,JOGL >= 2.4.0 更好,因为有 com.jogamp.newt.javafx.NewtCanvasJFX,但仍有一些限制。顺便说一句,如果你有 JOGL 特定的问题要问,最好在我们的官方论坛上提问,因为 StackOverflow 上只有极少数的贡献者。我忘了提这个:jogamp.org/bugzilla/show_bug.cgi?id=607
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-15
  • 2015-08-12
  • 1970-01-01
相关资源
最近更新 更多