]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/game.c
Add node selection box
[dragonblocks_alpha.git] / src / client / game.c
1 #define STB_IMAGE_WRITE_IMPLEMENTATION
2 #include <GL/glew.h>
3 #include <GL/gl.h>
4 #include <GLFW/glfw3.h>
5 #include <stb/stb_image_write.h>
6 #include <stdio.h>
7 #include <unistd.h>
8 #include "client/camera.h"
9 #include "client/client.h"
10 #include "client/client_entity.h"
11 #include "client/client_node.h"
12 #include "client/client_player.h"
13 #include "client/client_terrain.h"
14 #include "client/debug_menu.h"
15 #include "client/font.h"
16 #include "client/frustum.h"
17 #include "client/game.h"
18 #include "client/gl_debug.h"
19 #include "client/gui.h"
20 #include "client/input.h"
21 #include "client/interact.h"
22 #include "client/sky.h"
23 #include "client/window.h"
24 #include "day.h"
25 #include "interrupt.h"
26
27 int game_fps = 0;
28
29 static void crosshair_init()
30 {
31         gui_add(NULL, (GUIElementDefinition) {
32                 .pos = {0.5f, 0.5f},
33                 .z_index = 0.0f,
34                 .offset = {0, 0},
35                 .margin = {0, 0},
36                 .align = {0.5f, 0.5f},
37                 .scale = {1.0f, 1.0f},
38                 .scale_type = SCALE_IMAGE,
39                 .affect_parent_scale = false,
40                 .text = NULL,
41                 .image = texture_load(RESSOURCE_PATH "textures/crosshair.png", false),
42                 .text_color = {0.0f, 0.0f, 0.0f, 0.0f},
43                 .bg_color = {0.0f, 0.0f, 0.0f, 0.0f},
44         });
45 }
46
47 static void render(f64 dtime)
48 {
49         glEnable(GL_DEPTH_TEST); GL_DEBUG
50         glEnable(GL_BLEND); GL_DEBUG
51         glEnable(GL_MULTISAMPLE); GL_DEBUG
52         glEnable(GL_CULL_FACE); GL_DEBUG
53
54         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DEBUG
55         glCullFace(GL_BACK); GL_DEBUG
56         glFrontFace(GL_CCW); GL_DEBUG
57
58         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GL_DEBUG
59
60         frustum_update();
61         terrain_gfx_update();
62         client_entity_gfx_update();
63
64         sky_render();
65         model_scene_render(dtime);
66         interact_render();
67         gui_render();
68 }
69
70 static void game_loop()
71 {
72         f64 fps_update_timer = 1.0f;
73         unsigned int frames = 0;
74
75         struct timespec ts, ts_old;
76         clock_gettime(CLOCK_REALTIME, &ts_old);
77
78         while (!glfwWindowShouldClose(window.handle) && !interrupt.set) {
79                 clock_gettime(CLOCK_REALTIME, &ts);
80                 f64 dtime = (f64) (ts.tv_sec - ts_old.tv_sec) + (f64) (ts.tv_nsec - ts_old.tv_nsec) / 1.0e9;
81                 ts_old = ts;
82
83                 if ((fps_update_timer -= dtime) <= 0.0) {
84                         debug_menu_changed(ENTRY_FPS);
85                         game_fps = frames;
86                         fps_update_timer += 1.0;
87                         frames = 0;
88                 }
89
90                 frames++;
91
92                 input_tick(dtime);
93                 client_player_tick(dtime);
94                 interact_tick();
95
96                 debug_menu_changed(ENTRY_TIME);
97                 debug_menu_changed(ENTRY_DAYLIGHT);
98                 debug_menu_changed(ENTRY_SUN_ANGLE);
99                 debug_menu_update();
100
101                 render(dtime);
102
103                 glfwSwapBuffers(window.handle);
104                 glfwPollEvents();
105         }
106 }
107
108 bool game(Flag *gfx_init)
109 {
110         if (!window_init())
111                 return false;
112
113         if (!font_init())
114                 return false;
115
116         model_init();
117
118         if (!sky_init())
119                 return false;
120
121         if (!terrain_gfx_init())
122                 return false;
123
124         if (!client_entity_gfx_init())
125                 return false;
126
127         client_player_gfx_init();
128
129         if (!interact_init())
130                 return false;
131
132         client_node_init();
133         client_terrain_start();
134
135         camera_set_position((v3f32) {0.0f, 0.0f, 0.0f});
136         camera_set_angle(0.0f, 0.0f);
137
138         if (!gui_init())
139                 return false;
140
141         debug_menu_init();
142         crosshair_init();
143         input_init();
144
145         flag_set(gfx_init);
146         game_loop();
147
148         client_terrain_stop();
149
150         font_deinit();
151         gui_deinit();
152         model_deinit();
153         sky_deinit();
154         terrain_gfx_deinit();
155         client_entity_gfx_deinit();
156         client_player_gfx_deinit();
157         interact_deinit();
158
159         return true;
160 }
161
162 char *game_take_screenshot()
163 {
164         // renderbuffer for depth & stencil buffer
165         GLuint rbo;
166         glGenRenderbuffers(1, &rbo); GL_DEBUG
167         glBindRenderbuffer(GL_RENDERBUFFER, rbo); GL_DEBUG
168         glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_DEPTH24_STENCIL8, window.width, window.height); GL_DEBUG
169
170         // 2 textures, one with AA, one without
171
172         GLuint txos[2];
173         glGenTextures(2, txos); GL_DEBUG
174
175         glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, txos[0]); GL_DEBUG
176         glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGB, window.width, window.height, GL_TRUE); GL_DEBUG
177
178         glBindTexture(GL_TEXTURE_2D, txos[1]); GL_DEBUG
179         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window.width, window.height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); GL_DEBUG
180
181         // 2 framebuffers, one with AA, one without
182
183         GLuint fbos[2];
184         glGenFramebuffers(2, fbos); GL_DEBUG
185
186         glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); GL_DEBUG
187         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, txos[0], 0); GL_DEBUG
188         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); GL_DEBUG
189
190         glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); GL_DEBUG
191         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, txos[1], 0); GL_DEBUG
192
193         // render scene
194         glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); GL_DEBUG
195         render(0.0);
196         glBindFramebuffer(GL_FRAMEBUFFER, 0); GL_DEBUG
197
198         // blit AA-buffer into no-AA buffer
199         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]); GL_DEBUG
200         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); GL_DEBUG
201         glBlitFramebuffer(0, 0, window.width, window.height, 0, 0, window.width, window.height, GL_COLOR_BUFFER_BIT, GL_NEAREST); GL_DEBUG
202
203         // read data
204         GLubyte data[window.width * window.height * 3];
205         glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); GL_DEBUG
206         glPixelStorei(GL_PACK_ALIGNMENT, 1); GL_DEBUG
207         glReadPixels(0, 0, window.width, window.height, GL_RGB, GL_UNSIGNED_BYTE, data); GL_DEBUG
208
209         // create filename
210         char filename[BUFSIZ];
211         time_t timep = time(0);
212         strftime(filename, BUFSIZ, "screenshot-%Y-%m-%d-%H:%M:%S.png", localtime(&timep));
213
214         // save screenshot
215         stbi_flip_vertically_on_write(true);
216         stbi_write_png(filename, window.width, window.height, 3, data, window.width * 3);
217
218         // delete buffers
219         glDeleteRenderbuffers(1, &rbo); GL_DEBUG
220         glDeleteTextures(2, txos); GL_DEBUG
221         glDeleteFramebuffers(2, fbos); GL_DEBUG
222
223         return strdup(filename);
224 }