JavaFX 中的 JOGL canvas
JOGL canvas in JavaFX
我在 JavaFX 场景中获取 JOGL canvas/panel 时遇到问题。我的假设是,如果 JOGL GLCanvas 遵守 awt.Canvas 的合同,将其放置在 JFX 场景中应该没有问题。
我整理了以下代码(所有片段都在 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())))) 在 canvas 处产生黑色内容应该是.Wrapper Stage(Scene(Group(JPanel(GLCanvas())))(跳过使用 GLJPanel)不会为 [=52= 生成黑色方块] 内容,我只得到 JPanel 的蓝色方块。
我在互联网上发现的唯一提及是从 2012/2013 开始的,它似乎不起作用(但当时 SwingNode 似乎也不存在),以及 2016 年在 JOGL 论坛上 link s to dead link in bugzzila.
出于绝望尝试使用 GLJPanel 而不是 GLCanvas,它起作用了。有点。
SwingNode 调整大小存在问题 - 它有一个错误,不允许轻松调整大小(OracleJDK has the bug for quite some time, OpenJDK 似乎已解决)
针对调整大小问题的建议解决方案是在场景中放置 width/height 属性 侦听器,并在每次大小更改时重新插入 canvas:
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,无论如何我首先渲染到屏幕外缓冲区),以所需的分辨率渲染,将结果 blitting 到左上角面板,并将 JFX 场景中的面板裁剪到完全相同的分辨率。
如tomsontom所述,性能不是很好,GLJPanel比GLCanvas[=32慢得多=] 本身(在 4K 时从 800FPS 到 40FPS),当在 SwingNode 时它变得更糟(在 4K 时为 17FPS)。将尽可能推迟 JFX 的使用,并希望他们在即将与 JDK 分离时修复 SwingNode,甚至获得 DirectRenderingNode[=32] =].
我在 JavaFX 场景中获取 JOGL canvas/panel 时遇到问题。我的假设是,如果 JOGL GLCanvas 遵守 awt.Canvas 的合同,将其放置在 JFX 场景中应该没有问题。
我整理了以下代码(所有片段都在 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())))) 在 canvas 处产生黑色内容应该是.Wrapper Stage(Scene(Group(JPanel(GLCanvas())))(跳过使用 GLJPanel)不会为 [=52= 生成黑色方块] 内容,我只得到 JPanel 的蓝色方块。
我在互联网上发现的唯一提及是从 2012/2013 开始的,它似乎不起作用(但当时 SwingNode 似乎也不存在),以及 2016 年在 JOGL 论坛上 link s to dead link in bugzzila.
出于绝望尝试使用 GLJPanel 而不是 GLCanvas,它起作用了。有点。
SwingNode 调整大小存在问题 - 它有一个错误,不允许轻松调整大小(OracleJDK has the bug for quite some time, OpenJDK 似乎已解决)
针对调整大小问题的建议解决方案是在场景中放置 width/height 属性 侦听器,并在每次大小更改时重新插入 canvas:
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,无论如何我首先渲染到屏幕外缓冲区),以所需的分辨率渲染,将结果 blitting 到左上角面板,并将 JFX 场景中的面板裁剪到完全相同的分辨率。
如tomsontom所述,性能不是很好,GLJPanel比GLCanvas[=32慢得多=] 本身(在 4K 时从 800FPS 到 40FPS),当在 SwingNode 时它变得更糟(在 4K 时为 17FPS)。将尽可能推迟 JFX 的使用,并希望他们在即将与 JDK 分离时修复 SwingNode,甚至获得 DirectRenderingNode[=32] =].