OpenGL (lwjgl) with JavaFX sharing same context

Hall Hank hall0330 at hotmail.com
Wed May 6 15:13:27 UTC 2020


Hi again guys.
Sorry for my last email, but i thought that it was possible to attach some file.

Here is the code of the small application. I will create a github account with this part of code and the screenshot.


package sample;

import com.sun.javafx.sg.prism.NGRegion;
import com.sun.prism.Graphics;
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;

import static org.lwjgl.opengl.GL11.*;

public class Main extends Application {

  @Override
  public void start(Stage primaryStage) throws Exception{

    Region glNode = new Region() {
      @Override
      public NGRegion impl_createPeer() {
        return new NGRegion() {
          boolean shouldInitLwjgl = true;

          @Override
          protected void renderContent(Graphics g) {

            // We must call this clearQuad method to flush everything.
            // I didn't find out to be able to render something without calling this method.
            g.clearQuad(0,0,1,1);
            if(shouldInitLwjgl) {
              // Extracted documentation from https://www.lwjgl.org/guide
              // "LWJGL detects the context that is current in the current thread,
              // creates the GLCapabilities instance and makes the OpenGL
              // bindings available for use."
              GL.createCapabilities();
              shouldInitLwjgl = false;
            }

            // Start to save JavaFX OpenGL context states, in order to restore it properly at the
            // end
            int[] viewport = new int[4];
            GL11.glGetIntegerv(GL11.GL_VIEWPORT, viewport);
            boolean isScissorEnabled = GL11.glIsEnabled(GL11.GL_SCISSOR_TEST);
            int[] scissor = new int[4];
            GL11.glGetIntegerv(GL11.GL_SCISSOR_BOX, scissor);
            float[] clearColors = new float[4];
            GL11.glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColors);

            // Now we can start to draw but first thing to do is to enable the GL_SCISSOR_TEST
            // and put the scissor value to the bounds of the node.
            Bounds bounds = localToScene(getLayoutBounds());
            glEnable(GL_SCISSOR_TEST);
            GL11.glScissor((int)bounds.getMinX() * 2,(int)bounds.getMinY() * 2,
                    (int)getPrefWidth() * 2,(int) getPrefHeight() * 2);

            // And now we can start to draw our things. Here is just a clear color to green for the example.
            GL11.glClearColor(0.0f,1.0f,0.0f, 1.0f);
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
            glDisable(GL_SCISSOR_TEST);

            // At the end, we must restore the JavaFX OpenGL states
            if(isScissorEnabled) {
              glEnable(GL_SCISSOR_TEST);
              GL11.glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
            }
            GL11.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
            GL11.glClearColor(clearColors[0], clearColors[1], clearColors[2], clearColors[3]);

            // Call super to handle children
            super.renderContent(g);
          }
        };
      }
    };

    // Here is just a simple layout in a VBox, with one button followed by one
    // OpenGL node followed by one new button
    VBox root = new VBox();
    Button button1 = new Button(("Hello 1"));
    button1.setPrefSize(100, 100);
    Button button2 = new Button(("Hello 2"));
    button2.setPrefSize(100, 100);
    root.getChildren().addAll(button1,glNode, button2);
    glNode.setPrefSize(100,100);


    primaryStage.setScene(new Scene(root, 600, 300));
    primaryStage.show();
  }


  public static void main(String[] args) {
    launch(args);
  }
}

Sorry again, and thank's for reading.

Hank.


More information about the openjfx-dev mailing list