Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/LWJGL/lwjgl3/llms.txt

Use this file to discover all available pages before exploring further.

This guide walks you through creating a minimal LWJGL 3 application that opens a window using GLFW and sets up an OpenGL context. By the end you will have a working render loop that you can extend with your own drawing code. LWJGL 3.4.2 is the current release.
LWJGL is not a framework. It does not manage a game loop, a scene graph, or asset loading for you. What it provides is direct, type-safe access to native libraries — the same APIs you would use from C or C++.

Prerequisites

  • JDK 8 or later installed and on your PATH
  • A Gradle or Maven project (this guide uses Gradle)
  • Basic familiarity with Java
1

Add dependencies

LWJGL is distributed as a set of modules on Maven Central under the group org.lwjgl. You always need the core lwjgl artifact plus the binding modules for the APIs you want to use. For each module that has native code, you also need the corresponding natives JAR for your target platform.The example below adds the core module, GLFW, and OpenGL for all three major desktop platforms. If you only need to support one platform you can include a single natives classifier instead.
val lwjglVersion = "3.4.2"
val lwjglNatives = listOf(
    "natives-linux",
    "natives-macos",
    "natives-macos-arm64",
    "natives-windows"
)

dependencies {
    implementation(platform("org.lwjgl:lwjgl-bom:$lwjglVersion"))

    implementation("org.lwjgl:lwjgl")
    implementation("org.lwjgl:lwjgl-glfw")
    implementation("org.lwjgl:lwjgl-opengl")

    lwjglNatives.forEach { natives ->
        runtimeOnly("org.lwjgl:lwjgl::$natives")
        runtimeOnly("org.lwjgl:lwjgl-glfw::$natives")
        runtimeOnly("org.lwjgl:lwjgl-opengl::$natives")
    }
}
Use the LWJGL build configurator to generate dependency declarations tailored to the exact set of bindings and platforms you need.
2

Initialize GLFW and create a window

Before calling any GLFW function you must initialize the library. After initialization you set window hints and then create the window. The glfwMakeContextCurrent call binds the OpenGL context to the current thread, and GL.createCapabilities() interrogates the driver to expose the available OpenGL functions.
HelloWindow.java
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11C.*;
import static org.lwjgl.system.MemoryUtil.*;

public class HelloWindow {

    private long window;

    public void run() {
        init();
        loop();

        // Free callbacks and destroy the window
        glfwFreeCallbacks(window);
        glfwDestroyWindow(window);

        // Terminate GLFW and free the error callback
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }

    private void init() {
        // Set up an error callback that prints to System.err
        GLFWErrorCallback.createPrint(System.err).set();

        // Initialize GLFW — most GLFW functions will not work before this
        if (!glfwInit()) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }

        // Configure the window
        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);   // keep hidden until ready
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);

        // Create the window (width, height, title, monitor, share)
        window = glfwCreateWindow(800, 600, "Hello LWJGL", NULL, NULL);
        if (window == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        // Close on Escape
        glfwSetKeyCallback(window, (win, key, scancode, action, mods) -> {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
                glfwSetWindowShouldClose(win, true);
            }
        });

        // Bind the OpenGL context to this thread
        glfwMakeContextCurrent(window);

        // Enable v-sync
        glfwSwapInterval(1);

        // Make the window visible
        glfwShowWindow(window);
    }
3

Create OpenGL capabilities and render a frame

After binding the context you must call GL.createCapabilities() so that LWJGL can discover which OpenGL extensions are available on the current driver. You then enter the render loop, which polls for OS events, clears the framebuffer, and swaps the front and back buffers on every iteration.
HelloWindow.java (continued)
    private void loop() {
        // Make OpenGL bindings available for this thread
        GL.createCapabilities();

        // Set the clear color (red, green, blue, alpha)
        glClearColor(0.1f, 0.1f, 0.15f, 1.0f);

        // Run until the user closes the window or presses Escape
        while (!glfwWindowShouldClose(window)) {
            // Poll for window events (key presses, resize, etc.)
            glfwPollEvents();

            // Clear the color buffer
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            // --- your drawing code goes here ---

            // Swap front and back buffers
            glfwSwapBuffers(window);
        }
    }

    public static void main(String[] args) {
        new HelloWindow().run();
    }
}
4

Clean up resources

LWJGL uses off-heap memory and native handles that the Java garbage collector does not manage. Always clean up in reverse order of creation: release OpenGL capabilities, free GLFW callbacks, destroy the window, and then terminate GLFW.The pattern shown in step 2 — freeing callbacks, destroying the window, and calling glfwTerminate() — is the correct teardown sequence. In a larger application, consider wrapping initialization in a try/finally block to ensure cleanup runs even if an exception occurs:
teardown pattern
public void run() {
    try {
        init();
        loop();
    } finally {
        glfwFreeCallbacks(window);
        glfwDestroyWindow(window);
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }
}

What’s next

You now have a working window and OpenGL context. From here you can:
See Installation for a complete reference of all available modules, native classifier names, and Maven POM syntax.

Build docs developers (and LLMs) love