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