Skip to content

husker-dev/openglfx

Repository files navigation

logo

boosty

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-lwjgl:4.1.14'
}

Available modules:

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

If you are using JPMS (Java 9+), then you need to add the following module in module-info.java:

requires openglfx.lwjgl;

openglfx adds exports for JavaFX at runtime, but if you experience issues with package access, then add following arguments to JVM:

-Dopenglfx.disable.exports=true

Then add --add-exports by hand:

--add-exports=javafx.graphics/com.sun.prism=ALL-UNNAMED
--add-exports=javafx.graphics/com.sun.javafx.scene.layout=ALL-UNNAMED
--add-exports=javafx.graphics/com.sun.javafx.scene=ALL-UNNAMED
--add-exports=javafx.graphics/com.sun.javafx.sg.prism=ALL-UNNAMED
--add-exports=javafx.graphics/com.sun.scenario=ALL-UNNAMED
--add-exports=javafx.graphics/com.sun.javafx.tk=ALL-UNNAMED
--add-exports=javafx.graphics/com.sun.glass.ui=ALL-UNNAMED

Example

https://github.com/husker-dev/openglfx-example

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)

Swap buffers

GLCanvas based on the swap chain system - you can think of it as "double buffering".

The best UI performance is achieved with 2 (default). The most responsive to resizing is 1.

GLCanvas(.., swapBuffers = 1)

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

In GLCanvas you can specify the desired profile. I advise you to always choose Core. To do this, you need to specify a parameter in constructor.

GLCanvas(.., profile = GLProfile.CORE)
GLCanvas(.., profile = GLProfile.COMPATIBILITY)

FPS control

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

Value Behavior
< 0 Monitor refresh rate
0 Do not updates automatically
(Keep in mind that the update may be triggered by resizing or other commands from JavaFX)
> 0 Update with desired FPS
// In constructor
val canvas = GLCanvas(..., fps = 30)

// Or at runtime
canvas.fps = 40

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 & NSight

openglfx supports RenderDoc integration. To use it, you need to set externalWindow in GLCanvas constructor to true.

This will create a separate window with the rendered image, which you can connect to via RenderDoc or NSight.

LibGDX

To use in LibGDX project, you should create new module.

Minimal build.gradle example:

plugins {
    id("org.jetbrains.kotlin.jvm")
}

sourceSets.main.resources.srcDirs += [ rootProject.file('assets').path ]

dependencies {
    implementation project(':core')
    implementation "com.badlogicgames.gdx:gdx-backend-lwjgl3:$gdxVersion"
    implementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"

    // openglfx
    api("com.huskerdev:openglfx-libgdx:4.1.0")
  
    // implementation(/* JavaFX */)
    // implementation(/* LWJGL */)
}

Instead of using GLCanvas, you should use LibGDXCanvas:

val canvas = LibGDXCanvas(Main()) // Main is ApplicationAdapter

Under the hood

Thanks to