LWJGL教程01 - 创建窗口

从示范代码到Window类

先来看实例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
[imports ...]

public class HelloWorld {

// The window handle
private long window;

public void run() {
System.out.println("Hello LWJGL " + Version.getVersion() + "!");

init();
loop();

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

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

private void init() {
// Setup an error callback. The default implementation
// will print the error message in System.err.
GLFWErrorCallback.createPrint(System.err).set();

// Initialize GLFW. Most GLFW functions will not work before doing this.
if ( !glfwInit() )
throw new IllegalStateException("Unable to initialize GLFW");

// Configure GLFW
glfwDefaultWindowHints(); // optional, the current window hints are already the default
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

// Create the window
window = glfwCreateWindow(300, 300, "Hello World!", NULL, NULL);
if ( window == NULL )
throw new RuntimeException("Failed to create the GLFW window");

// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
});

// Get the thread stack and push a new frame
try ( MemoryStack stack = stackPush() ) {
IntBuffer pWidth = stack.mallocInt(1); // int*
IntBuffer pHeight = stack.mallocInt(1); // int*

// Get the window size passed to glfwCreateWindow
glfwGetWindowSize(window, pWidth, pHeight);

// Get the resolution of the primary monitor
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

// Center the window
glfwSetWindowPos(
window,
(vidmode.width() - pWidth.get(0)) / 2,
(vidmode.height() - pHeight.get(0)) / 2
);
} // the stack frame is popped automatically

// Make the OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);

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

private void loop() {
// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// 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();

// Set the clear color
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while ( !glfwWindowShouldClose(window) ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

glfwSwapBuffers(window); // swap the color buffers

// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents();
}
}

[main ...]

}

虽然不多,但初见着实让人有点头晕。

将整个程序归纳为:

1
2
3
4
5
[init ...]
while(!glfwWindowShouldClose(window)) {
[do something ...]
}
[close ...]

Window类的工作大致就是实现init()的内容。

为了能够自定义窗口的各种属性,在Window类中创建一个内部类Settings来存储相关参数。

1
2
3
4
5
6
7
8
9
10
public static class Settings {
public int width;
public int height;
public String ztitle;
public boolean vsync = false;
public float[] color = new float[4];
public Callable resizeCallback = () -> null;

[Setter & Getter ...]
}

然后将示例代码终端init()提取出来,并将widthheighttitle替换进去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
[imports ...]

public class Window {
[Settings]

public static long window;
public static Settings settings;

public static void createWindow(Settings settings) {
Window.settings = settings;

[...]

// Create the window
window = glfwCreateWindow(settings.width, settings.height, settings.title, NULL, NULL);

[...]

// Enable v-sync
glfwSwapInterval(0);
if(settings.vsync)
glfwSwapInterval(1);

glfwSetFramebufferSizeCallback(window, (window, width, height) -> {
Window.width = width;
Window.height = height;
try {
settings.resizeCallback.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
});

GL.createCapabilities();
}

public static boolean windowShouldClose() {
return glfwWindowShouldClose(window);
}

public static void pollEvents() {
glfwPollEvents();
}

public static void cleanup() {
// Free the window callbacks and destroy the window
glfwFreeCallbacks(window);
glfwDestroyWindow(window);

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

public static void setWindowVisible() {
glfwShowWindow(window);
}

public static boolean isKeyPressed(int keyCode) {
return glfwGetKey(window, keyCode) == GLFW_PRESS;
}
}

现在测试一下Window类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[imports ...]

public class TestWindow {
public static void main(String[] args) {
Window.Settings settings = new Window.Settings();
settings.width = 800;
settings.height = 600;
settings.title = "Test Window";
Window.createWindow(settings);
Window.setWindowVisible();
while (!Window.windowShouldClose())
Window.pollEvents();
Window.cleanup();
}
}

运行结果


LWJGL教程01 - 创建窗口
https://panxy02.github.io/2024/07/17/lwjgl-01/
作者
52Hertz
发布于
2024年7月17日
许可协议