openglfx
openglfx copied to clipboard
OpenGL canvas for JavaFX
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.
- Dependency
- Usage
- Rendering events
- Antialiasing (MSAA)
- Async rendering
- Y-flipping
- OpenGL profile
- Auto repaint
- Image transfering
- RenderDoc
- Notes
- Reflection opens
- Under the hood
- Thanks to
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-lwjglopenglfx-lwjgl2openglfx-joglopenglfx-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_MODULELWJGL2_MODULEJOGL_MODULELIBGDX_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
-
Offscreen GL
husker-dev/offscreen-jgl is used to create offscreen thread-independent GL context on Windows, MacOS and Linux.
-
GLExecutor
Executors are the bridges from OpenGLFX inner logic to outer libraries like LWJGL or JOGL.
LWJGL JOGL Class LWJGLExecutor.kt JOGLFXExecutor.kt Instance LWJGL_MODULE JOGL_MODULE If you want to add new OpenGL library, just create your implementation of GLExecutor and use it as existing one:
OpenGLCanvas.create(YOUR_EXECUTOR_INSTANCE). -
Texture sharing
To efficiently connect OpenGL and JavaFX, OpenGLFX uses some techniques based on OS.
Description Sync implementation Async implementation Windows NV_DX_interop is used to synchronize textures between DirectX from JavaFX and OpenGL. NVDXInteropCanvasImpl.kt AsyncNVDXInteropCanvasImpl.kt Linux Creates context that is shared with JavaFX's one. After rendering, shared texture is displayed in JavaFX frame. SharedCanvasImpl.kt AsyncSharedCanvasImpl.kt macOS IOSurface is used to create memory block in VRAM that can be used in different OpenGL contexts. IOSurfaceCanvasImpl.kt AsyncIOSurfaceCanvasImpl.kt Other Copies ByteBuffer from glReadPixelsto JavaFX textureBlitCanvasImpl.kt AsyncBlitCanvasImpl.kt
Thanks to
- streamingdv - big donation, debugging
- James H Ball - macOS tester
- Andrew Hamilton - macOS tester, suggested new additions