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