]> git.lizzy.rs Git - dragonblocks_alpha.git/commitdiff
Add screenshot key
authorElias Fleckenstein <eliasfleckenstein@web.de>
Wed, 29 Sep 2021 11:30:42 +0000 (13:30 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Wed, 29 Sep 2021 11:30:42 +0000 (13:30 +0200)
.gitignore
README.md
snapshot.sh
src/client/game.c
src/client/game.h
src/client/input.c
src/client/window.c

index 21e15f08714ecf05234661d8a014252ba702f875..0d0a330fe83bd27b44e98793eb75e4d036944c69 100644 (file)
@@ -14,3 +14,4 @@ Dragonblocks
 world.sqlite
 DragonblocksAlpha-*.zip
 src/version.h
+screenshot-*.png
index 3b58989917980776a4896a8618136e9e2c2a78c9..74a162627a46418618ac6b1c2268bd628f03e6c1 100644 (file)
--- a/README.md
+++ b/README.md
@@ -30,8 +30,9 @@ or alternatively:
 | F | Toggle flight |
 | C | Toggle collision |
 | T | Toggle timelapse |
-| F11 | Toggle fullscreen |
+| F2 | Take screenshot |
 | F3 | Toggle debug info |
+| F11 | Toggle fullscreen |
 | ESC | Pause / unpause game |
 
 ## Dependencies
index 06df6c67ef22ce8dc352945b0aa9c814f01ca6d1..55be6ded370c0fadd623c90a0310a48e1f46a1b3 100755 (executable)
@@ -11,7 +11,7 @@ if ! (cmake -B . -S ../src -DCMAKE_BUILD_TYPE=Release && make clean && make -j$(
 fi
 cp Dragonblocks DragonblocksServer ..
 cd ..
-rm -rf .git* deps src build BUILDING.md snapshot.sh upload.sh DragonblocksAlpha-*.zip
+rm -rf .git* deps src build BUILDING.md snapshot.sh upload.sh DragonblocksAlpha-*.zip screenshot-*.png
 cd ..
 mv .build DragonblocksAlpha
 VERSION=`git tag --points-at HEAD`
index e9dbebc9f82281d021a77db5ffe759c36baf63a7..0f66bf03ee8b878d04bf91e418bd29897f71e117 100644 (file)
@@ -3,6 +3,8 @@
 #include <GL/glew.h>
 #include <GL/gl.h>
 #include <GLFW/glfw3.h>
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+#include <stb/stb_image_write.h>
 #include "client/camera.h"
 #include "client/client.h"
 #include "client/client_map.h"
@@ -17,6 +19,8 @@
 #include "day.h"
 #include "signal_handlers.h"
 
+int window_width, window_height;
+
 static void crosshair_init()
 {
        gui_add(&gui_root, (GUIElementDefinition) {
@@ -35,6 +39,29 @@ static void crosshair_init()
        });
 }
 
+static void render()
+{
+       glEnable(GL_DEPTH_TEST);
+       glEnable(GL_ALPHA_TEST);
+       glEnable(GL_BLEND);
+       glEnable(GL_MULTISAMPLE);
+       glEnable(GL_CULL_FACE);
+
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glAlphaFunc(GL_GREATER, 0.0f);
+       glCullFace(GL_BACK);
+       glFrontFace(GL_CCW);
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+       scene_render();
+
+       glDisable(GL_CULL_FACE);
+       sky_render();
+
+       glDisable(GL_DEPTH_TEST);
+       gui_render();
+}
+
 static void game_loop(Client *client)
 {
        f64 fps_update_timer = 1.0f;
@@ -56,31 +83,14 @@ static void game_loop(Client *client)
 
                frames++;
 
-               debug_menu_update_time();
-               debug_menu_update_daylight();
-               debug_menu_update_sun_angle();
-
-               glEnable(GL_DEPTH_TEST);
-               glEnable(GL_ALPHA_TEST);
-               glEnable(GL_BLEND);
-               glEnable(GL_MULTISAMPLE);
-               glEnable(GL_CULL_FACE);
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               glAlphaFunc(GL_GREATER, 0.0f);
-               glCullFace(GL_BACK);
-               glFrontFace(GL_CCW);
-               glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
                input_tick();
                client_player_tick(dtime);
 
-               scene_render();
-
-               glDisable(GL_CULL_FACE);
-               sky_render();
+               debug_menu_update_time();
+               debug_menu_update_daylight();
+               debug_menu_update_sun_angle();
 
-               glDisable(GL_DEPTH_TEST);
-               gui_render();
+               render();
 
                glfwSwapBuffers(window.handle);
                glfwPollEvents();
@@ -89,11 +99,10 @@ static void game_loop(Client *client)
 
 bool game(Client *client)
 {
-       int width, height;
-       width = 1250;
-       height = 750;
+       window_width = 1250;
+       window_height = 750;
 
-       if (! window_init(width, height))
+       if (! window_init(window_width, window_height))
                return false;
 
        if (! font_init())
@@ -102,7 +111,7 @@ bool game(Client *client)
        if (! scene_init())
                return false;
 
-       scene_on_resize(width, height);
+       scene_on_resize(window_width, window_height);
 
        if (! sky_init())
                return false;
@@ -116,7 +125,7 @@ bool game(Client *client)
        if (! gui_init())
                return false;
 
-       gui_on_resize(width, height);
+       gui_on_resize(window_width, window_height);
 
        debug_menu_init();
        debug_menu_toggle();
@@ -147,3 +156,71 @@ bool game(Client *client)
 
        return true;
 }
+
+void take_screenshot()
+{
+       // renderbuffer for depth & stencil buffer
+       GLuint RBO;
+       glGenRenderbuffers(1, &RBO);
+       glBindRenderbuffer(GL_RENDERBUFFER, RBO);
+       glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_DEPTH24_STENCIL8, window_width, window_height);
+
+       // 2 textures, one with AA, one without
+
+       GLuint textures[2];
+       glGenTextures(2, textures);
+
+       glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
+       glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGB, window_width, window_height, GL_TRUE);
+
+       glBindTexture(GL_TEXTURE_2D, textures[1]);
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window_width, window_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+
+       // 2 framebuffers, one with AA, one without
+
+       GLuint FBOs[2];
+       glGenFramebuffers(2, FBOs);
+
+       glBindFramebuffer(GL_FRAMEBUFFER, FBOs[0]);
+       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
+       glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO);
+
+       glBindFramebuffer(GL_FRAMEBUFFER, FBOs[1]);
+       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1], 0);
+
+       // render scene
+       glBindFramebuffer(GL_FRAMEBUFFER, FBOs[0]);
+       render();
+       glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+       // blit AA-buffer into no-AA buffer
+       glBindFramebuffer(GL_READ_FRAMEBUFFER, FBOs[0]);
+       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBOs[1]);
+       glBlitFramebuffer(0, 0, window_width, window_height, 0, 0, window_width, window_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+       // read data
+       GLubyte data[window_width * window_height * 3];
+       glBindFramebuffer(GL_FRAMEBUFFER, FBOs[1]);
+       glPixelStorei(GL_PACK_ALIGNMENT, 1);
+       glReadPixels(0, 0, window_width, window_height, GL_RGB, GL_UNSIGNED_BYTE, data);
+
+       // create filename
+       char filename[BUFSIZ];
+       time_t timep = time(0);
+       strftime(filename, BUFSIZ, "screenshot-%Y-%m-%d-%H:%M:%S.png", localtime(&timep));
+
+       // save screenshot
+       stbi_flip_vertically_on_write(true);
+       stbi_write_png(filename, window_width, window_height, 3, data, window_width * 3);
+
+       // delete buffers
+       glDeleteRenderbuffers(1, &RBO);
+       glDeleteTextures(2, textures);
+       glDeleteFramebuffers(2, FBOs);
+}
+
+void game_on_resize(int width, int height)
+{
+       window_width = width;
+       window_height = height;
+}
index ad4bb0541808a3013d02b1cf592a6dcf3776e467..99412641986c10db4ed00632dfe153f28179cb9d 100644 (file)
@@ -4,5 +4,7 @@
 #include "client/client.h"
 
 bool game(Client *client);
+void take_screenshot();
+void game_on_resize(int width, int height);
 
 #endif
index 063e34b6dc554478933466c32f7036b2805fc6a3..687d6f3b71ed6ae0c5a35ecd9a61c00983d0d60d 100644 (file)
@@ -3,6 +3,7 @@
 #include "client/client.h"
 #include "client/client_player.h"
 #include "client/debug_menu.h"
+#include "client/game.h"
 #include "client/gui.h"
 #include "client/input.h"
 #include "client/window.h"
@@ -25,6 +26,7 @@ static struct
        KeyListener collision_listener;
        KeyListener timelapse_listener;
        KeyListener debug_menu_listener;
+       KeyListener screenshot_listener;
 } input;
 
 void input_on_cursor_pos(double current_x, double current_y)
@@ -120,6 +122,7 @@ void input_tick()
                do_key_listener(&input.collision_listener);
                do_key_listener(&input.timelapse_listener);
                do_key_listener(&input.debug_menu_listener);
+               do_key_listener(&input.screenshot_listener);
 
                if (input.fly_listener.fired) {
                        client_player.fly = ! client_player.fly;
@@ -140,6 +143,9 @@ void input_tick()
 
                if (input.debug_menu_listener.fired)
                        debug_menu_toggle();
+
+               if (input.screenshot_listener.fired)
+                       take_screenshot();
        }
 
        client_player.velocity.x = 0.0f;
@@ -169,6 +175,7 @@ void input_init()
        input.collision_listener = create_key_listener(GLFW_KEY_C);
        input.timelapse_listener = create_key_listener(GLFW_KEY_T);
        input.debug_menu_listener = create_key_listener(GLFW_KEY_F3);
+       input.screenshot_listener = create_key_listener(GLFW_KEY_F2);
 
        input.pause_menu = gui_add(&gui_root, (GUIElementDefinition) {
                .pos = {0.0f, 0.0f},
index 15c7aeeec74a23d533dc34de2bc56cb2b3aa4134..29cab14f62d951b6504183e2bcbb6496fac9e224 100644 (file)
@@ -2,6 +2,7 @@
 #include <GL/glew.h>
 #include <GL/gl.h>
 #include "client/debug_menu.h"
+#include "client/game.h"
 #include "client/gui.h"
 #include "client/input.h"
 #include "client/scene.h"
@@ -21,6 +22,7 @@ static void framebuffer_size_callback(unused GLFWwindow *handle, int width, int
 
        scene_on_resize(width, height);
        gui_on_resize(width, height);
+       game_on_resize(width, height);
 }
 
 static void cursor_pos_callback(unused GLFWwindow *handle, double current_x, double current_y)