-
Notifications
You must be signed in to change notification settings - Fork 63
Introduction
This is a simple quick starting guide for the new version of the Lightweight Java Game Library.
The Lightweight Java Game Library is an open source library that provides you with bindings to OpenGL, OpenCL and OpenAL. It is mostly a wrapper for high-performant computer graphics programming with Java.
For a guide how to set the library up you can take a look here.
With LWJGL3 comes the GLFW library which provides the creation of an OpenGL context and input features.
This very first Guide is based on the getting started guide of GLFW3.
The first thing you should do is setting the error callback, so you can see if an error occurred even if GLFW wasn't initialized yet.
It should be noted, that you need to have a strong reference to any callbacks in LWJGL. This is due to the nature of the garbage collector, if you don't have a strong reference to the callback the VM won't know that you need it and it could get garbage collected which results in a ClosureError
. So make sure to have a class variable for each callback.
Now back to the error callback, to create one you can use the Callbacks
class of the LWJGL which has a function named errorCallbackPrint
which creates a GLFWErrorCallback
for you.
Another way to make an error callback is to just create a new GLFWErrorCallback
and overriding its invoke
function.
For the sake of easiness we just create an error callback that prints to System.err
.
private GLFWErrorCallback errorCallback = GLFWErrorCallback.createPrint(System.err);
After that we just have to set the callback.
glfwSetErrorCallback(errorCallback);
The next step is to initialize GLFW, this is done by calling glfwInit()
.
if (!glfwInit()) {
throw new IllegalStateException("Unable to initialize GLFW");
}
Now that GLFW is initialized we can start creating a window.
In GLFW this is done by calling glfwCreateWindow(width, height, title, monitor, share)
, in this guide we will ignore monitor
and share
for now.
You can also set some window hints, like GLFW_RESIZABLE
or GLFW_VISIBLE
, but at this part of the tutorial we will just go with the default window hints.
If the creation fails this method just returns NULL
which is 0 in LWJGL, but you can make a static import of the MemoryUtil
to just write NULL
, so you don't have to bother if the value get changed sometime. But normally the method won't fail and returns a handle for the window.
long window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
if (window == NULL) {
glfwTerminate();
throw new RuntimeException("Failed to create the GLFW window");
}
With the window created we can set up some other callbacks for that window like a key callback.
Don't forget to make a strong reference to the callback. For creating it you have to override the invoke
function of GLFWKeyCallback
.
The following key callback will for example check if the escape key was pressed and will then tell the window to close.
private GLFWKeyCallback keyCallback = new GLFWKeyCallback() {
@Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, true);
}
}
};
After creating the key callback you can register it to your window.
glfwSetKeyCallback(window, keyCallback);
When done creating a window you can also create the OpenGL context, which is needed for rendering.
This is done by calling glfwMakeContextCurrent(window)
. In LWJGL you also have to call createCapabilities()
from the GL
class, so that the library can detect the context and make the OpenGL bindings available for use.
glfwMakeContextCurrent(window);
GL.createCapabilities();
Now that you have your OpenGL context you can start rendering.
We want our application to run until the window should get closed, so just do a simple while loop.
while (!glfwWindowShouldClose(window)) {
/* Do something */
}
Inside the loop you can do any OpenGL calls to render your application, in the example code it is just a rotating triangle.
For the correct rotating we need a time source. Luckily GLFW3 has its own high-resolution timer by calling glfwGetTime()
. It will give you the passed seconds since glfwInit()
as a double.
double time = glfwGetTime();
After doing your OpenGL calls you have to swap the color buffers, because GLFW uses double-buffering. You can do this by calling glfwSwapBuffers(window)
.
Another thing to do is processing events like the key events through glfwPollEvents()
. You could also do glfwWaitEvents()
if your application should only update when you receive new input.
glfwSwapBuffers(window);
glfwPollEvents();
For the example OpenGL calls just look into Introduction.java
provided in a link below.
When you are ending your application you should release your callbacks, destroy your window and terminate GLFW, so that any allocated resources get released.
First you should destroy your window, and after that release the event callbacks that were registered to that window like the key event.
glfwDestroyWindow(window);
keyCallback.free();
Alternatively you could use Callbacks.free(window)
for releasing all callbacks with just one function.
After destroying the window and releasing its callbacks you should terminate GLFW and finally release the error callback.
glfwTerminate();
errorCallback.free();
This is everything you should know for a quick start into LWJGL3, if something is unclear or you found a mistake just tell me.
In the next tutorial we will take a look into game loops, which are the core of every game.
Until then enjoy testing LWJGL3 out!
This tutorial and it's source code is licensed under the MIT license.
Written by Heiko Brumme, Copyright © 2014-2018