Skip to content

husker-dev/openglfx

Repository files navigation

Logo

Buy coffee for the developer.

About

This library adds a new element to the JavaFX for rendering OpenGL graphics using LWJGL, JOGL, LWJGL2 or LibGDX. It is optimized for each platform and includes some auxiliary functions for working with OpenGL from JavaFX.

NOTE: All examples are written in Kotlin + Gradle + LWJGL. If you want to use Java/JOGL/Maven, you can use example code generator.

Dependency

dependencies {
    // implementation JavaFX
    // implementation LWJGL
    // implementation ...

    implementation 'com.huskerdev:openglfx:4.0.5'
    implementation 'com.huskerdev:openglfx-lwjgl:4.0.5'
}

Available modules:

  • openglfx-lwjgl
  • openglfx-lwjgl2
  • openglfx-jogl
  • openglfx-libgdx

Usage

This library adds only one component - GLCanvas, that can be used like a regular element in JavaFX.

After canvas is not needed anymore, call dispose() to free the allocated memory.

import com.huskerdev.openglfx.canvas.GLCanvas
import com.huskerdev.openglfx.lwjgl.LWJGLExecutor.Companion.LWJGL_MODULE

val canvas = GLCanvas(LWJGL_MODULE)

Available modules:

  • LWJGL_MODULE
  • LWJGL2_MODULE
  • JOGL_MODULE
  • LIBGDX_MODULE

Rendering events

GLCanvas uses a logic similar to JOGL. The component has events where you can render the content.

canvas.addOnInitEvent { event ->
    // Init some gl properties only once
}

canvas.addOnRenderEvent { event ->
    // Render some content every frame
}

canvas.addOnReshapeEvent { event ->
    // Change viewport matrices at resizing
}

canvas.addOnDisposeEvent { event ->
    // Clear native data at disposing
}

Antialiasing (MSAA)

GLCanvas supports multi-sampling anti-aliasing. It can be enabled during creation. For maximum possible MSAA level, specify -1.

GLCanvas(.., msaa = 4)

Async rendering

GLCanvas can render graphics in a separated thread. This feature can either improve or decrease performance. Test it on your applications.

GLCanvas(.., async = true)

Y-flipping

By default, OpenGL draws the image upside down. GLCanvas has the ability to flip it without loss of performance. To do this, specify the parameter at startup.

GLCanvas(.., flipY = true)

OpenGL profile

OpenGL has two initialization profiles - Core and Compatibility, you can read about them on the Internet.

In GLCanvas you can specify the desired option. I advise you to always choose Core. To do this, you need to specify a parameter when creating.

GLCanvas(.., profile = GLProfile.Core)
GLCanvas(.., profile = GLProfile.Compatibility)

Auto repaint

If you need to update content with a certain FPS, then you should use GLCanvasAnimator. Keep in mind that JavaFX can limits the refresh rate.

import com.huskerdev.openglfx.canvas.GLCanvasAnimator

canvas.animator = GLCanvasAnimator(60.0) 
canvas.animator = GLCanvasAnimator(GLCanvasAnimator.UNLIMITED_FPS) // For maximum available FPS
canvas.animator = null // To remove animator

Don't forget to disable VSync before JavaFX initialization if you want to get FPS more than monitor's frequency.

System.setProperty("prism.vsync", "false")

Image transfering

openglfx has the ability to move images from JavaFX to OpenGL textures and vice versa. A special class is used for this:

val fbo = GLImageManager.toGL(image)

val image = GLImageManager.fromGL(fbo, width, height)

RenderDoc

openglfx supports RenderDoc integration. Unfortunately, java and javaFX limit how this tool can be used, so the following features have been made.

  • You can take a screenshot of the following frame using the hotkey:
RenderDoc.bind(canvas)  // F12 by default
// or
RenderDoc.bind(canvas, keyCode = KeyCode.F11)
  • You can insert the beginning and ending of capturing into the code:
RenderDoc.startFrameCapture()
// Renders here...
RenderDoc.endFrameCapture()

It is better not to mix these two recording methods.

To view a scene in the Renderdoc application, you need to select one of the processes. It may change depending on the launch settings.

Notes

  • RenderDoc + Windows crashes the JVM. Workaround is described in (#39);
  • JOGL can't initialize on macOS (#22).

If you know how to fix that problem I would be very happy

Reflection opens

--add-opens javafx.base/com.sun.javafx=ALL-UNNAMED
--add-opens javafx.graphics/com.sun.prism=ALL-UNNAMED
--add-opens javafx.graphics/com.sun.prism.d3d=ALL-UNNAMED
--add-opens javafx.graphics/com.sun.javafx.scene.layout=ALL-UNNAMED
--add-opens javafx.graphics/com.sun.javafx.scene=ALL-UNNAMED
--add-opens javafx.graphics/com.sun.javafx.sg.prism=ALL-UNNAMED
--add-opens javafx.graphics/com.sun.javafx.tk=ALL-UNNAMED
--add-opens javafx.graphics/com.sun.javafx.geom=ALL-UNNAMED
--add-opens javafx.graphics/javafx.scene.image=ALL-UNNAMED

Under the hood

Thanks to