Hard-coded undersampling.
authornumber Zero <silverunicorn2011@yandex.ru>
Thu, 12 Jan 2017 09:19:36 +0000 (12:19 +0300)
committerAuke Kok <sofar@foo-projects.org>
Mon, 10 Apr 2017 00:30:19 +0000 (17:30 -0700)
Adds uniform undersampling for the 3D rendered scene. GUI elements
are not undersampled, resulting in better playability for users
with low-performance platforms with readable fonts and formspecs.

The undersampling setting can be set to 0 (disabled), 2, 3, 4 pixels
which translates into a resolution reduction of x4, x9 or x16, and
is significant.

builtin/settingtypes.txt
minetest.conf.example
src/defaultsettings.cpp
src/drawscene.cpp
src/settings_translation_file.cpp

index a3b91fe74b87c53d2196718e6fbfb28e85f398ac..2c74d6c441dcd1f51da8b41c32456678bf1f08a3 100644 (file)
@@ -362,6 +362,11 @@ texture_min_size (Minimum texture size for filters) int 64
 #    when set to higher number than 0.
 fsaa (FSAA) enum 0 0,1,2,4,8,16
 
+#    Undersampling is similar to using lower screen resolution, but it applies
+#    to the game world only, keeping the GUI intact.
+#    It should give significant performance boost at the cost of less detailed image.
+undersampling (Undersampling) enum 0 0,2,3,4
+
 [***Shaders]
 
 #    Shaders allow advanced visual effects and may increase performance on some video cards.
index 9e9039bf275d374d68c13940d6e775cbd31bd0ae..d147ebfac37ad8ad3baa39b358cdd3db02f4bc38 100644 (file)
 #    type: enum values: 0, 1, 2, 4, 8, 16
 # fsaa = 0
 
+#    Undersampling is similar to using lower screen resolution, but it applies
+#    to the game world only, keeping the GUI intact.
+#    It should give significant performance boost at the cost of less detailed image.
+#    type: enum values: 0, 2, 3, 4
+# undersampling = 0
+
 #### Shaders
 
 #    Shaders allow advanced visual effects and may increase performance on some video cards.
index 2a49a0ecaf1f57fe8ac14bcfc88974ff0fb960c8..c6ced593157a718927d11906a131c220f52f37da 100644 (file)
@@ -108,6 +108,7 @@ void set_default_settings(Settings *settings)
        settings->setDefault("show_debug", "true");
 #endif
        settings->setDefault("fsaa", "0");
+       settings->setDefault("undersampling", "0");
        settings->setDefault("enable_fog", "true");
        settings->setDefault("fog_start", "0.4");
        settings->setDefault("3d_mode", "none");
index 663c8828c311f2f350923a6949f699433a0ed570..421b96f124bef3e86e2e11618c454dbf39b08345 100644 (file)
@@ -459,10 +459,37 @@ void draw_pageflip_3d_mode(Camera& camera, bool show_hud,
 #endif
 }
 
-void draw_plain(Camera &camera, bool show_hud, Hud &hud,
-               video::IVideoDriver *driver, bool draw_wield_tool,
-               Client &client, gui::IGUIEnvironment *guienv)
+// returns (size / coef), rounded upwards
+inline int scaledown(int coef, int size)
 {
+       return (size + coef - 1) / coef;
+}
+
+void draw_plain(Camera &camera, bool show_hud,
+               Hud &hud, video::IVideoDriver *driver,
+               scene::ISceneManager *smgr, const v2u32 &screensize,
+               bool draw_wield_tool, Client &client, gui::IGUIEnvironment *guienv,
+               video::SColor skycolor)
+{
+       // Undersampling-specific stuff
+       static video::ITexture *image = NULL;
+       static v2u32 last_pixelated_size = v2u32(0, 0);
+       int undersampling = g_settings->getU16("undersampling");
+       v2u32 pixelated_size;
+       v2u32 dest_size;
+       if (undersampling > 0) {
+               pixelated_size = v2u32(scaledown(undersampling, screensize.X),
+                               scaledown(undersampling, screensize.Y));
+               dest_size = v2u32(undersampling * pixelated_size.X, undersampling * pixelated_size.Y);
+               if (pixelated_size != last_pixelated_size) {
+                       init_texture(driver, pixelated_size, &image, "mt_drawimage_img1");
+                       last_pixelated_size = pixelated_size;
+               }
+               driver->setRenderTarget(image, true, true, skycolor);
+       }
+
+       // Render
+       smgr->drawAll();
        driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
        if (show_hud) {
                hud.drawSelectionMesh();
@@ -470,10 +497,18 @@ void draw_plain(Camera &camera, bool show_hud, Hud &hud,
                        camera.drawWieldedTool();
                }
        }
+
+       // Upscale lowres render
+       if (undersampling > 0) {
+               driver->setRenderTarget(0, true, true);
+               driver->draw2DImage(image,
+                               irr::core::rect<s32>(0, 0, dest_size.X, dest_size.Y),
+                               irr::core::rect<s32>(0, 0, pixelated_size.X, pixelated_size.Y));
+       }
 }
 
 void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr,
-               Camera &camera, Clientclient, LocalPlayer *player, Hud &hud,
+               Camera &camera, Client &client, LocalPlayer *player, Hud &hud,
                Minimap &mapper, gui::IGUIEnvironment *guienv,
                const v2u32 &screensize, const video::SColor &skycolor,
                bool show_hud, bool show_minimap)
@@ -496,8 +531,6 @@ void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr,
 
        const std::string &draw_mode = g_settings->get("3d_mode");
 
-       smgr->drawAll();
-
        if (draw_mode == "anaglyph")
        {
                draw_anaglyph_3d_mode(camera, show_hud, hud, driver,
@@ -531,7 +564,7 @@ void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr,
        }
        else {
                draw_plain(camera, show_hud, hud, driver,
-                               draw_wield_tool, client, guienv);
+                               smgr, screensize, draw_wield_tool, client, guienv, skycolor);
        }
 
        /*
index 9ec21c415f9d4712b7ce3ecbd089bb5d978d4920..93f2688d7e3346e1413e08740905c7c5c4e7ac94 100644 (file)
@@ -152,6 +152,8 @@ fake_function() {
        gettext("When using bilinear/trilinear/anisotropic filters, low-resolution textures\ncan be blurred, so automatically upscale them with nearest-neighbor\ninterpolation to preserve crisp pixels.  This sets the minimum texture size\nfor the upscaled textures; higher values look sharper, but require more\nmemory.  Powers of 2 are recommended.  Setting this higher than 1 may not\nhave a visible effect unless bilinear/trilinear/anisotropic filtering is\nenabled.");
        gettext("FSAA");
        gettext("Experimental option, might cause visible spaces between blocks\nwhen set to higher number than 0.");
+       gettext("Undersampling");
+       gettext("Undersampling is similar to using lower screen resolution, but it applies\nto the game world only, keeping the GUI intact.\nIt should give significant performance boost at the cost of less detailed image.");
        gettext("Shaders");
        gettext("Shaders");
        gettext("Shaders allow advanced visual effects and may increase performance on some video cards.\nThy only work with the OpenGL video backend.");