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