Rewrite rendering engine (#6253)

* Clean draw_*() arguments

* Split rendering core

* Add anaglyph 3D

* Interlaced 3D

* Drop obsolete methods
This commit is contained in:
Vitaliy 2017-10-31 21:27:10 +03:00 committed by Loïc Blot
parent 65c5539035
commit 28841961ba
25 changed files with 1008 additions and 618 deletions

@ -608,6 +608,7 @@ fall_bobbing_amount (Fall bobbing factor) float 0.0
# - topbottom: split screen top/bottom. # - topbottom: split screen top/bottom.
# - sidebyside: split screen side by side. # - sidebyside: split screen side by side.
# - pageflip: quadbuffer based 3d. # - pageflip: quadbuffer based 3d.
# Note that the interlaced mode requires shaders to be enabled.
3d_mode (3D mode) enum none none,anaglyph,interlaced,topbottom,sidebyside,pageflip 3d_mode (3D mode) enum none none,anaglyph,interlaced,topbottom,sidebyside,pageflip
# In-game chat console height, between 0.1 (10%) and 1.0 (100%). # In-game chat console height, between 0.1 (10%) and 1.0 (100%).

@ -0,0 +1,21 @@
uniform sampler2D baseTexture;
uniform sampler2D normalTexture;
uniform sampler2D textureFlags;
#define leftImage baseTexture
#define rightImage normalTexture
#define maskImage textureFlags
void main(void)
{
vec2 uv = gl_TexCoord[0].st;
vec4 left = texture2D(leftImage, uv).rgba;
vec4 right = texture2D(rightImage, uv).rgba;
vec4 mask = texture2D(maskImage, uv).rgba;
vec4 color;
if (mask.r > 0.5)
color = right;
else
color = left;
gl_FragColor = color;
}

@ -0,0 +1,6 @@
void main(void)
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_Vertex;
gl_FrontColor = gl_BackColor = gl_Color;
}

@ -700,6 +700,7 @@
# - topbottom: split screen top/bottom. # - topbottom: split screen top/bottom.
# - sidebyside: split screen side by side. # - sidebyside: split screen side by side.
# - pageflip: quadbuffer based 3d. # - pageflip: quadbuffer based 3d.
# Note that the interlaced mode requires shaders to be enabled.
# type: enum values: none, anaglyph, interlaced, topbottom, sidebyside, pageflip # type: enum values: none, anaglyph, interlaced, topbottom, sidebyside, pageflip
# 3d_mode = none # 3d_mode = none

@ -1,4 +1,12 @@
set(client_SRCS set(client_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/render/anaglyph.cpp
${CMAKE_CURRENT_SOURCE_DIR}/render/core.cpp
${CMAKE_CURRENT_SOURCE_DIR}/render/factory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/render/interlaced.cpp
${CMAKE_CURRENT_SOURCE_DIR}/render/pageflip.cpp
${CMAKE_CURRENT_SOURCE_DIR}/render/plain.cpp
${CMAKE_CURRENT_SOURCE_DIR}/render/sidebyside.cpp
${CMAKE_CURRENT_SOURCE_DIR}/render/stereo.cpp
${CMAKE_CURRENT_SOURCE_DIR}/renderingengine.cpp ${CMAKE_CURRENT_SOURCE_DIR}/renderingengine.cpp
${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp ${CMAKE_CURRENT_SOURCE_DIR}/clientlauncher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/inputhandler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/inputhandler.cpp
@ -6,4 +14,3 @@ set(client_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/joystick_controller.cpp ${CMAKE_CURRENT_SOURCE_DIR}/joystick_controller.cpp
PARENT_SCOPE PARENT_SCOPE
) )

@ -0,0 +1,51 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "anaglyph.h"
void RenderingCoreAnaglyph::drawAll()
{
renderBothImages();
drawPostFx();
drawHUD();
}
void RenderingCoreAnaglyph::setupMaterial(int color_mask)
{
video::SOverrideMaterial &mat = driver->getOverrideMaterial();
mat.Material.ColorMask = color_mask;
mat.EnableFlags = video::EMF_COLOR_MASK;
mat.EnablePasses = scene::ESNRP_SKY_BOX | scene::ESNRP_SOLID |
scene::ESNRP_TRANSPARENT | scene::ESNRP_TRANSPARENT_EFFECT |
scene::ESNRP_SHADOW;
}
void RenderingCoreAnaglyph::useEye(bool right)
{
RenderingCoreStereo::useEye(right);
driver->clearZBuffer();
setupMaterial(right ? video::ECP_GREEN | video::ECP_BLUE : video::ECP_RED);
}
void RenderingCoreAnaglyph::resetEye()
{
setupMaterial(video::ECP_ALL);
RenderingCoreStereo::resetEye();
}

@ -0,0 +1,34 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "stereo.h"
class RenderingCoreAnaglyph : public RenderingCoreStereo
{
protected:
void setupMaterial(int color_mask);
void useEye(bool right) override;
void resetEye() override;
public:
using RenderingCoreStereo::RenderingCoreStereo;
void drawAll() override;
};

101
src/client/render/core.cpp Normal file

@ -0,0 +1,101 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "core.h"
#include "camera.h"
#include "client.h"
#include "clientmap.h"
#include "hud.h"
#include "minimap.h"
RenderingCore::RenderingCore(IrrlichtDevice *_device, Client *_client, Hud *_hud)
: device(_device), driver(device->getVideoDriver()), smgr(device->getSceneManager()),
guienv(device->getGUIEnvironment()), client(_client), camera(client->getCamera()),
mapper(client->getMinimap()), hud(_hud)
{
screensize = driver->getScreenSize();
virtual_size = screensize;
}
RenderingCore::~RenderingCore()
{
clearTextures();
}
void RenderingCore::initialize()
{
// have to be called late as the VMT is not ready in the constructor:
initTextures();
}
void RenderingCore::updateScreenSize()
{
virtual_size = screensize;
clearTextures();
initTextures();
}
void RenderingCore::draw(video::SColor _skycolor, bool _show_hud, bool _show_minimap,
bool _draw_wield_tool, bool _draw_crosshair)
{
v2u32 ss = driver->getScreenSize();
if (screensize != ss) {
screensize = ss;
updateScreenSize();
}
skycolor = _skycolor;
show_hud = _show_hud;
show_minimap = _show_minimap;
draw_wield_tool = _draw_wield_tool;
draw_crosshair = _draw_crosshair;
beforeDraw();
drawAll();
}
void RenderingCore::draw3D()
{
smgr->drawAll();
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
if (!show_hud)
return;
hud->drawSelectionMesh();
if (draw_wield_tool)
camera->drawWieldedTool();
}
void RenderingCore::drawHUD()
{
if (show_hud) {
if (draw_crosshair)
hud->drawCrosshair();
hud->drawHotbar(client->getPlayerItem());
hud->drawLuaElements(camera->getOffset());
camera->drawNametags();
if (mapper && show_minimap)
mapper->drawMinimap();
}
guienv->drawAll();
}
void RenderingCore::drawPostFx()
{
client->getEnv().getClientMap().renderPostFx(camera->getCameraMode());
}

75
src/client/render/core.h Normal file

@ -0,0 +1,75 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "irrlichttypes_extrabloated.h"
class Camera;
class Client;
class Hud;
class Minimap;
class RenderingCore
{
protected:
v2u32 screensize;
v2u32 virtual_size;
video::SColor skycolor;
bool show_hud;
bool show_minimap;
bool draw_wield_tool;
bool draw_crosshair;
IrrlichtDevice *device;
video::IVideoDriver *driver;
scene::ISceneManager *smgr;
gui::IGUIEnvironment *guienv;
Client *client;
Camera *camera;
Minimap *mapper;
Hud *hud;
void updateScreenSize();
virtual void initTextures() {}
virtual void clearTextures() {}
virtual void beforeDraw() {}
virtual void drawAll() = 0;
void draw3D();
void drawHUD();
void drawPostFx();
public:
RenderingCore(IrrlichtDevice *_device, Client *_client, Hud *_hud);
RenderingCore(const RenderingCore &) = delete;
RenderingCore(RenderingCore &&) = delete;
virtual ~RenderingCore();
RenderingCore &operator=(const RenderingCore &) = delete;
RenderingCore &operator=(RenderingCore &&) = delete;
void initialize();
void draw(video::SColor _skycolor, bool _show_hud, bool _show_minimap,
bool _draw_wield_tool, bool _draw_crosshair);
inline v2u32 getVirtualSize() const { return virtual_size; }
};

@ -0,0 +1,45 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "factory.h"
#include <stdexcept>
#include "plain.h"
#include "anaglyph.h"
#include "interlaced.h"
#include "pageflip.h"
#include "sidebyside.h"
RenderingCore *createRenderingCore(const std::string &stereo_mode, IrrlichtDevice *device,
Client *client, Hud *hud)
{
if (stereo_mode == "none")
return new RenderingCorePlain(device, client, hud);
if (stereo_mode == "anaglyph")
return new RenderingCoreAnaglyph(device, client, hud);
if (stereo_mode == "interlaced")
return new RenderingCoreInterlaced(device, client, hud);
if (stereo_mode == "pageflip")
return new RenderingCorePageflip(device, client, hud);
if (stereo_mode == "sidebyside")
return new RenderingCoreSideBySide(device, client, hud);
if (stereo_mode == "topbottom")
return new RenderingCoreSideBySide(device, client, hud, true);
throw std::invalid_argument("Invalid rendering mode: " + stereo_mode);
}

@ -0,0 +1,25 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string>
#include "core.h"
RenderingCore *createRenderingCore(const std::string &stereo_mode, IrrlichtDevice *device,
Client *client, Hud *hud);

@ -0,0 +1,116 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "interlaced.h"
#include "client.h"
#include "shader.h"
#include "client/tile.h"
RenderingCoreInterlaced::RenderingCoreInterlaced(
IrrlichtDevice *_device, Client *_client, Hud *_hud)
: RenderingCoreStereo(_device, _client, _hud)
{
initMaterial();
}
void RenderingCoreInterlaced::initMaterial()
{
IShaderSource *s = client->getShaderSource();
mat.UseMipMaps = false;
mat.ZBuffer = false;
mat.ZWriteEnable = false;
u32 shader = s->getShader("3d_interlaced_merge", TILE_MATERIAL_BASIC, 0);
mat.MaterialType = s->getShaderInfo(shader).material;
for (int k = 0; k < 3; ++k) {
mat.TextureLayer[k].AnisotropicFilter = false;
mat.TextureLayer[k].BilinearFilter = false;
mat.TextureLayer[k].TrilinearFilter = false;
mat.TextureLayer[k].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
mat.TextureLayer[k].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
}
}
void RenderingCoreInterlaced::initTextures()
{
v2u32 image_size{screensize.X, screensize.Y / 2};
left = driver->addRenderTargetTexture(
image_size, "3d_render_left", video::ECF_A8R8G8B8);
right = driver->addRenderTargetTexture(
image_size, "3d_render_right", video::ECF_A8R8G8B8);
mask = driver->addTexture(screensize, "3d_render_mask", video::ECF_A8R8G8B8);
initMask();
mat.TextureLayer[0].Texture = left;
mat.TextureLayer[1].Texture = right;
mat.TextureLayer[2].Texture = mask;
}
void RenderingCoreInterlaced::clearTextures()
{
driver->removeTexture(left);
driver->removeTexture(right);
driver->removeTexture(mask);
}
void RenderingCoreInterlaced::initMask()
{
u8 *data = reinterpret_cast<u8 *>(mask->lock());
for (u32 j = 0; j < screensize.Y; j++) {
u8 val = j % 2 ? 0xff : 0x00;
memset(data, val, 4 * screensize.X);
data += 4 * screensize.X;
}
mask->unlock();
}
void RenderingCoreInterlaced::drawAll()
{
renderBothImages();
merge();
drawHUD();
}
void RenderingCoreInterlaced::merge()
{
static const video::S3DVertex vertices[4] = {
video::S3DVertex(1.0, -1.0, 0.0, 0.0, 0.0, -1.0,
video::SColor(255, 0, 255, 255), 1.0, 0.0),
video::S3DVertex(-1.0, -1.0, 0.0, 0.0, 0.0, -1.0,
video::SColor(255, 255, 0, 255), 0.0, 0.0),
video::S3DVertex(-1.0, 1.0, 0.0, 0.0, 0.0, -1.0,
video::SColor(255, 255, 255, 0), 0.0, 1.0),
video::S3DVertex(1.0, 1.0, 0.0, 0.0, 0.0, -1.0,
video::SColor(255, 255, 255, 255), 1.0, 1.0),
};
static const u16 indices[6] = {0, 1, 2, 2, 3, 0};
driver->setMaterial(mat);
driver->drawVertexPrimitiveList(&vertices, 4, &indices, 2);
}
void RenderingCoreInterlaced::useEye(bool _right)
{
driver->setRenderTarget(_right ? right : left, true, true, skycolor);
RenderingCoreStereo::useEye(_right);
}
void RenderingCoreInterlaced::resetEye()
{
driver->setRenderTarget(nullptr, false, false, skycolor);
RenderingCoreStereo::resetEye();
}

@ -0,0 +1,43 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "stereo.h"
class RenderingCoreInterlaced : public RenderingCoreStereo
{
protected:
video::ITexture *left = nullptr;
video::ITexture *right = nullptr;
video::ITexture *mask = nullptr;
video::SMaterial mat;
void initMaterial();
void initTextures() override;
void clearTextures() override;
void initMask();
void useEye(bool right) override;
void resetEye() override;
void merge();
public:
RenderingCoreInterlaced(IrrlichtDevice *_device, Client *_client, Hud *_hud);
void drawAll() override;
};

@ -0,0 +1,55 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "pageflip.h"
void RenderingCorePageflip::initTextures()
{
hud = driver->addRenderTargetTexture(
screensize, "3d_render_hud", video::ECF_A8R8G8B8);
}
void RenderingCorePageflip::clearTextures()
{
driver->removeTexture(hud);
}
void RenderingCorePageflip::drawAll()
{
driver->setRenderTarget(hud, true, true, video::SColor(0, 0, 0, 0));
drawHUD();
driver->setRenderTarget(nullptr, false, false, skycolor);
renderBothImages();
}
void RenderingCorePageflip::useEye(bool _right)
{
driver->setRenderTarget(_right ? video::ERT_STEREO_RIGHT_BUFFER
: video::ERT_STEREO_LEFT_BUFFER,
true, true, skycolor);
RenderingCoreStereo::useEye(_right);
}
void RenderingCorePageflip::resetEye()
{
driver->draw2DImage(hud, v2s32(0, 0));
driver->setRenderTarget(video::ERT_FRAME_BUFFER, false, false, skycolor);
RenderingCoreStereo::resetEye();
}

@ -0,0 +1,37 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "stereo.h"
class RenderingCorePageflip : public RenderingCoreStereo
{
protected:
video::ITexture *hud = nullptr;
void initTextures() override;
void clearTextures() override;
void useEye(bool right) override;
void resetEye() override;
public:
using RenderingCoreStereo::RenderingCoreStereo;
void drawAll() override;
};

@ -0,0 +1,76 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "plain.h"
#include "settings.h"
inline u32 scaledown(u32 coef, u32 size)
{
return (size + coef - 1) / coef;
}
RenderingCorePlain::RenderingCorePlain(
IrrlichtDevice *_device, Client *_client, Hud *_hud)
: RenderingCore(_device, _client, _hud)
{
scale = g_settings->getU16("undersampling");
}
void RenderingCorePlain::initTextures()
{
if (!scale)
return;
v2u32 size{scaledown(scale, screensize.X), scaledown(scale, screensize.Y)};
lowres = driver->addRenderTargetTexture(
size, "render_lowres", video::ECF_A8R8G8B8);
}
void RenderingCorePlain::clearTextures()
{
if (!scale)
return;
driver->removeTexture(lowres);
}
void RenderingCorePlain::beforeDraw()
{
if (!scale)
return;
driver->setRenderTarget(lowres, true, true, skycolor);
}
void RenderingCorePlain::upscale()
{
if (!scale)
return;
driver->setRenderTarget(0, true, true);
v2u32 size{scaledown(scale, screensize.X), scaledown(scale, screensize.Y)};
v2u32 dest_size{scale * size.X, scale * size.Y};
driver->draw2DImage(lowres, core::rect<s32>(0, 0, dest_size.X, dest_size.Y),
core::rect<s32>(0, 0, size.X, size.Y));
}
void RenderingCorePlain::drawAll()
{
draw3D();
drawPostFx();
upscale();
drawHUD();
}

38
src/client/render/plain.h Normal file

@ -0,0 +1,38 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "core.h"
class RenderingCorePlain : public RenderingCore
{
protected:
int scale = 0;
video::ITexture *lowres = nullptr;
void initTextures() override;
void clearTextures() override;
void beforeDraw() override;
void upscale();
public:
RenderingCorePlain(IrrlichtDevice *_device, Client *_client, Hud *_hud);
void drawAll() override;
};

@ -0,0 +1,74 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "sidebyside.h"
#include <ICameraSceneNode.h>
#include "hud.h"
RenderingCoreSideBySide::RenderingCoreSideBySide(
IrrlichtDevice *_device, Client *_client, Hud *_hud, bool _horizontal)
: RenderingCoreStereo(_device, _client, _hud), horizontal(_horizontal)
{
}
void RenderingCoreSideBySide::initTextures()
{
if (horizontal) {
image_size = {screensize.X, screensize.Y / 2};
rpos = v2s32(0, screensize.Y / 2);
} else {
image_size = {screensize.X / 2, screensize.Y};
rpos = v2s32(screensize.X / 2, 0);
}
virtual_size = image_size;
left = driver->addRenderTargetTexture(
image_size, "3d_render_left", video::ECF_A8R8G8B8);
right = driver->addRenderTargetTexture(
image_size, "3d_render_right", video::ECF_A8R8G8B8);
}
void RenderingCoreSideBySide::clearTextures()
{
driver->removeTexture(left);
driver->removeTexture(right);
}
void RenderingCoreSideBySide::drawAll()
{
driver->OnResize(image_size); // HACK to make GUI smaller
renderBothImages();
driver->OnResize(screensize);
driver->draw2DImage(left, {});
driver->draw2DImage(right, rpos);
}
void RenderingCoreSideBySide::useEye(bool _right)
{
driver->setRenderTarget(_right ? right : left, true, true, skycolor);
RenderingCoreStereo::useEye(_right);
}
void RenderingCoreSideBySide::resetEye()
{
hud->resizeHotbar();
drawHUD();
driver->setRenderTarget(nullptr, false, false, skycolor);
RenderingCoreStereo::resetEye();
}

@ -0,0 +1,42 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "stereo.h"
class RenderingCoreSideBySide : public RenderingCoreStereo
{
protected:
video::ITexture *left = nullptr;
video::ITexture *right = nullptr;
bool horizontal = false;
core::dimension2du image_size;
v2s32 rpos;
void initTextures() override;
void clearTextures() override;
void useEye(bool right) override;
void resetEye() override;
public:
RenderingCoreSideBySide(IrrlichtDevice *_device, Client *_client, Hud *_hud,
bool _horizontal = false);
void drawAll() override;
};

@ -0,0 +1,60 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "stereo.h"
#include "camera.h"
#include "constants.h"
#include "settings.h"
RenderingCoreStereo::RenderingCoreStereo(
IrrlichtDevice *_device, Client *_client, Hud *_hud)
: RenderingCore(_device, _client, _hud)
{
eye_offset = BS * g_settings->getFloat("3d_paralax_strength");
}
void RenderingCoreStereo::beforeDraw()
{
cam = camera->getCameraNode();
base_transform = cam->getRelativeTransformation();
}
void RenderingCoreStereo::useEye(bool right)
{
core::matrix4 move;
move.setTranslation(
core::vector3df(right ? eye_offset : -eye_offset, 0.0f, 0.0f));
cam->setPosition((base_transform * move).getTranslation());
}
void RenderingCoreStereo::resetEye()
{
cam->setPosition(base_transform.getTranslation());
}
void RenderingCoreStereo::renderBothImages()
{
useEye(false);
draw3D();
resetEye();
useEye(true);
draw3D();
resetEye();
}

@ -0,0 +1,38 @@
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2017 numzero, Lobachesky Vitaly <numzer0@yandex.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "core.h"
class RenderingCoreStereo : public RenderingCore
{
protected:
scene::ICameraSceneNode *cam;
core::matrix4 base_transform;
float eye_offset;
void beforeDraw() override;
virtual void useEye(bool right);
virtual void resetEye();
void renderBothImages();
public:
RenderingCoreStereo(IrrlichtDevice *_device, Client *_client, Hud *_hud);
};

@ -31,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "minimap.h" #include "minimap.h"
#include "clientmap.h" #include "clientmap.h"
#include "renderingengine.h" #include "renderingengine.h"
#include "render/core.h"
#include "render/factory.h"
#include "inputhandler.h" #include "inputhandler.h"
#include "gettext.h" #include "gettext.h"
@ -102,17 +104,22 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver)
#endif #endif
m_device = createDeviceEx(params); m_device = createDeviceEx(params);
driver = m_device->getVideoDriver();
s_singleton = this; s_singleton = this;
} }
RenderingEngine::~RenderingEngine() RenderingEngine::~RenderingEngine()
{ {
core.reset();
m_device->drop(); m_device->drop();
s_singleton = nullptr; s_singleton = nullptr;
} }
v2u32 RenderingEngine::getWindowSize() const v2u32 RenderingEngine::getWindowSize() const
{ {
if (core)
return core->getVirtualSize();
return m_device->getVideoDriver()->getScreenSize(); return m_device->getVideoDriver()->getScreenSize();
} }
@ -121,11 +128,6 @@ void RenderingEngine::setResizable(bool resize)
m_device->setResizable(resize); m_device->setResizable(resize);
} }
video::IVideoDriver *RenderingEngine::getVideoDriver()
{
return m_device->getVideoDriver();
}
bool RenderingEngine::print_video_modes() bool RenderingEngine::print_video_modes()
{ {
IrrlichtDevice *nulldevice; IrrlichtDevice *nulldevice;
@ -213,11 +215,10 @@ bool RenderingEngine::setWindowIcon()
"-xorg-icon-128.png"); "-xorg-icon-128.png");
#endif #endif
#elif defined(_WIN32) #elif defined(_WIN32)
const video::SExposedVideoData exposedData = const video::SExposedVideoData exposedData = driver->getExposedVideoData();
m_device->getVideoDriver()->getExposedVideoData();
HWND hWnd; // Window handle HWND hWnd; // Window handle
switch (m_device->getVideoDriver()->getDriverType()) { switch (driver->getDriverType()) {
case video::EDT_DIRECT3D8: case video::EDT_DIRECT3D8:
hWnd = reinterpret_cast<HWND>(exposedData.D3D8.HWnd); hWnd = reinterpret_cast<HWND>(exposedData.D3D8.HWnd);
break; break;
@ -253,14 +254,12 @@ bool RenderingEngine::setXorgWindowIconFromPath(const std::string &icon_file)
{ {
#ifdef XORG_USED #ifdef XORG_USED
video::IVideoDriver *v_driver = m_device->getVideoDriver();
video::IImageLoader *image_loader = NULL; video::IImageLoader *image_loader = NULL;
u32 cnt = v_driver->getImageLoaderCount(); u32 cnt = driver->getImageLoaderCount();
for (u32 i = 0; i < cnt; i++) { for (u32 i = 0; i < cnt; i++) {
if (v_driver->getImageLoader(i)->isALoadableFileExtension( if (driver->getImageLoader(i)->isALoadableFileExtension(
icon_file.c_str())) { icon_file.c_str())) {
image_loader = v_driver->getImageLoader(i); image_loader = driver->getImageLoader(i);
break; break;
} }
} }
@ -313,7 +312,7 @@ bool RenderingEngine::setXorgWindowIconFromPath(const std::string &icon_file)
img->drop(); img->drop();
icon_f->drop(); icon_f->drop();
const video::SExposedVideoData &video_data = v_driver->getExposedVideoData(); const video::SExposedVideoData &video_data = driver->getExposedVideoData();
Display *x11_dpl = (Display *)video_data.OpenGLLinux.X11Display; Display *x11_dpl = (Display *)video_data.OpenGLLinux.X11Display;
@ -442,558 +441,22 @@ std::vector<irr::video::E_DRIVER_TYPE> RenderingEngine::getSupportedVideoDrivers
return drivers; return drivers;
} }
void RenderingEngine::_draw_scene(Camera *camera, Client *client, LocalPlayer *player, void RenderingEngine::_initialize(Client *client, Hud *hud)
Hud *hud, Minimap *mapper, gui::IGUIEnvironment *guienv,
const v2u32 &screensize, const video::SColor &skycolor, bool show_hud,
bool show_minimap)
{ {
bool draw_wield_tool =
(show_hud && (player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE) &&
camera->getCameraMode() < CAMERA_MODE_THIRD);
bool draw_crosshair = ((player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
(camera->getCameraMode() != CAMERA_MODE_THIRD_FRONT));
#ifdef HAVE_TOUCHSCREENGUI
try {
draw_crosshair = !g_settings->getBool("touchtarget");
} catch (SettingNotFoundException) {
}
#endif
const std::string &draw_mode = g_settings->get("3d_mode"); const std::string &draw_mode = g_settings->get("3d_mode");
core.reset(createRenderingCore(draw_mode, m_device, client, hud));
if (draw_mode == "anaglyph") { core->initialize();
draw_anaglyph_3d_mode(
camera, show_hud, hud, draw_wield_tool, client, guienv);
draw_crosshair = false;
} else if (draw_mode == "interlaced") {
draw_interlaced_3d_mode(camera, show_hud, hud, screensize,
draw_wield_tool, client, guienv, skycolor);
draw_crosshair = false;
} else if (draw_mode == "sidebyside") {
draw_sidebyside_3d_mode(camera, show_hud, hud, screensize,
draw_wield_tool, client, guienv, skycolor);
show_hud = false;
} else if (draw_mode == "topbottom") {
draw_top_bottom_3d_mode(camera, show_hud, hud, screensize,
draw_wield_tool, client, guienv, skycolor);
show_hud = false;
} else if (draw_mode == "pageflip") {
draw_pageflip_3d_mode(camera, show_hud, hud, screensize, draw_wield_tool,
client, guienv, skycolor);
draw_crosshair = false;
show_hud = false;
} else {
draw_plain(camera, show_hud, hud, screensize, draw_wield_tool, client,
guienv, skycolor);
}
/*
Post effects
*/
client->getEnv().getClientMap().renderPostFx(camera->getCameraMode());
// TODO how to make those 3d too
if (show_hud) {
if (draw_crosshair)
hud->drawCrosshair();
hud->drawHotbar(client->getPlayerItem());
hud->drawLuaElements(camera->getOffset());
camera->drawNametags();
if (mapper && show_minimap)
mapper->drawMinimap();
}
guienv->drawAll();
} }
void RenderingEngine::draw_anaglyph_3d_mode(Camera *camera, bool show_hud, Hud *hud, void RenderingEngine::_finalize()
bool draw_wield_tool, Client *client, gui::IGUIEnvironment *guienv)
{ {
core.reset();
/* preserve old setup*/
irr::core::vector3df oldPosition = camera->getCameraNode()->getPosition();
irr::core::vector3df oldTarget = camera->getCameraNode()->getTarget();
irr::core::matrix4 startMatrix =
camera->getCameraNode()->getAbsoluteTransformation();
irr::core::vector3df focusPoint =
(camera->getCameraNode()->getTarget() -
camera->getCameraNode()->getAbsolutePosition())
.setLength(1) +
camera->getCameraNode()->getAbsolutePosition();
// Left eye...
irr::core::vector3df leftEye;
irr::core::matrix4 leftMove;
leftMove.setTranslation(irr::core::vector3df(
-g_settings->getFloat("3d_paralax_strength"), 0.0f, 0.0f));
leftEye = (startMatrix * leftMove).getTranslation();
// clear the depth buffer, and color
getVideoDriver()->beginScene(true, true, irr::video::SColor(0, 200, 200, 255));
getVideoDriver()->getOverrideMaterial().Material.ColorMask = irr::video::ECP_RED;
getVideoDriver()->getOverrideMaterial().EnableFlags = irr::video::EMF_COLOR_MASK;
getVideoDriver()->getOverrideMaterial().EnablePasses =
irr::scene::ESNRP_SKY_BOX + irr::scene::ESNRP_SOLID +
irr::scene::ESNRP_TRANSPARENT +
irr::scene::ESNRP_TRANSPARENT_EFFECT + irr::scene::ESNRP_SHADOW;
camera->getCameraNode()->setPosition(leftEye);
camera->getCameraNode()->setTarget(focusPoint);
get_scene_manager()->drawAll();
getVideoDriver()->setTransform(video::ETS_WORLD, core::IdentityMatrix);
if (show_hud) {
hud->drawSelectionMesh();
if (draw_wield_tool)
camera->drawWieldedTool(&leftMove);
}
guienv->drawAll();
// Right eye...
irr::core::vector3df rightEye;
irr::core::matrix4 rightMove;
rightMove.setTranslation(irr::core::vector3df(
g_settings->getFloat("3d_paralax_strength"), 0.0f, 0.0f));
rightEye = (startMatrix * rightMove).getTranslation();
// clear the depth buffer
getVideoDriver()->clearZBuffer();
getVideoDriver()->getOverrideMaterial().Material.ColorMask =
irr::video::ECP_GREEN + irr::video::ECP_BLUE;
getVideoDriver()->getOverrideMaterial().EnableFlags = irr::video::EMF_COLOR_MASK;
getVideoDriver()->getOverrideMaterial().EnablePasses =
irr::scene::ESNRP_SKY_BOX + irr::scene::ESNRP_SOLID +
irr::scene::ESNRP_TRANSPARENT +
irr::scene::ESNRP_TRANSPARENT_EFFECT + irr::scene::ESNRP_SHADOW;
camera->getCameraNode()->setPosition(rightEye);
camera->getCameraNode()->setTarget(focusPoint);
get_scene_manager()->drawAll();
getVideoDriver()->setTransform(video::ETS_WORLD, core::IdentityMatrix);
if (show_hud) {
hud->drawSelectionMesh();
if (draw_wield_tool)
camera->drawWieldedTool(&rightMove);
}
guienv->drawAll();
getVideoDriver()->getOverrideMaterial().Material.ColorMask = irr::video::ECP_ALL;
getVideoDriver()->getOverrideMaterial().EnableFlags = 0;
getVideoDriver()->getOverrideMaterial().EnablePasses = 0;
camera->getCameraNode()->setPosition(oldPosition);
camera->getCameraNode()->setTarget(oldTarget);
} }
void RenderingEngine::init_texture( void RenderingEngine::_draw_scene(video::SColor skycolor, bool show_hud,
const v2u32 &screensize, video::ITexture **texture, const char *name) bool show_minimap, bool draw_wield_tool, bool draw_crosshair)
{ {
if (*texture) { core->draw(skycolor, show_hud, show_minimap, draw_wield_tool, draw_crosshair);
getVideoDriver()->removeTexture(*texture);
}
*texture = getVideoDriver()->addRenderTargetTexture(
core::dimension2d<u32>(screensize.X, screensize.Y), name,
irr::video::ECF_A8R8G8B8);
}
video::ITexture *RenderingEngine::draw_image(const v2u32 &screensize, parallax_sign psign,
const irr::core::matrix4 &startMatrix,
const irr::core::vector3df &focusPoint, bool show_hud, Camera *camera,
Hud *hud, bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor)
{
static video::ITexture *images[2] = {NULL, NULL};
static v2u32 last_screensize = v2u32(0, 0);
video::ITexture *image = NULL;
if (screensize != last_screensize) {
init_texture(screensize, &images[1], "mt_drawimage_img1");
init_texture(screensize, &images[0], "mt_drawimage_img2");
last_screensize = screensize;
}
if (psign == RIGHT)
image = images[1];
else
image = images[0];
getVideoDriver()->setRenderTarget(image, true, true,
irr::video::SColor(255, skycolor.getRed(), skycolor.getGreen(),
skycolor.getBlue()));
irr::core::vector3df eye_pos;
irr::core::matrix4 movement;
movement.setTranslation(irr::core::vector3df(
(int)psign * g_settings->getFloat("3d_paralax_strength"), 0.0f,
0.0f));
eye_pos = (startMatrix * movement).getTranslation();
// clear the depth buffer
getVideoDriver()->clearZBuffer();
camera->getCameraNode()->setPosition(eye_pos);
camera->getCameraNode()->setTarget(focusPoint);
get_scene_manager()->drawAll();
getVideoDriver()->setTransform(video::ETS_WORLD, core::IdentityMatrix);
if (show_hud) {
hud->drawSelectionMesh();
if (draw_wield_tool)
camera->drawWieldedTool(&movement);
}
guienv->drawAll();
/* switch back to real renderer */
getVideoDriver()->setRenderTarget(0, true, true,
irr::video::SColor(0, skycolor.getRed(), skycolor.getGreen(),
skycolor.getBlue()));
return image;
}
video::ITexture *RenderingEngine::draw_hud(const v2u32 &screensize, bool show_hud,
Hud *hud, Client *client, bool draw_crosshair,
const video::SColor &skycolor, gui::IGUIEnvironment *guienv,
Camera *camera)
{
static video::ITexture *image = nullptr;
init_texture(screensize, &image, "mt_drawimage_hud");
getVideoDriver()->setRenderTarget(
image, true, true, irr::video::SColor(255, 0, 0, 0));
if (show_hud) {
if (draw_crosshair)
hud->drawCrosshair();
hud->drawHotbar(client->getPlayerItem());
hud->drawLuaElements(camera->getOffset());
camera->drawNametags();
guienv->drawAll();
}
getVideoDriver()->setRenderTarget(0, true, true,
irr::video::SColor(0, skycolor.getRed(), skycolor.getGreen(),
skycolor.getBlue()));
return image;
}
void RenderingEngine::draw_interlaced_3d_mode(Camera *camera, bool show_hud, Hud *hud,
const v2u32 &screensize, bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor)
{
/* save current info */
irr::core::vector3df oldPosition = camera->getCameraNode()->getPosition();
irr::core::vector3df oldTarget = camera->getCameraNode()->getTarget();
irr::core::matrix4 startMatrix =
camera->getCameraNode()->getAbsoluteTransformation();
irr::core::vector3df focusPoint =
(camera->getCameraNode()->getTarget() -
camera->getCameraNode()->getAbsolutePosition())
.setLength(1) +
camera->getCameraNode()->getAbsolutePosition();
/* create left view */
video::ITexture *left_image = draw_image(screensize, LEFT, startMatrix,
focusPoint, show_hud, camera, hud, draw_wield_tool, client,
guienv, skycolor);
// Right eye...
irr::core::vector3df rightEye;
irr::core::matrix4 rightMove;
rightMove.setTranslation(irr::core::vector3df(
g_settings->getFloat("3d_paralax_strength"), 0.0f, 0.0f));
rightEye = (startMatrix * rightMove).getTranslation();
// clear the depth buffer
getVideoDriver()->clearZBuffer();
camera->getCameraNode()->setPosition(rightEye);
camera->getCameraNode()->setTarget(focusPoint);
get_scene_manager()->drawAll();
getVideoDriver()->setTransform(video::ETS_WORLD, core::IdentityMatrix);
if (show_hud) {
hud->drawSelectionMesh();
if (draw_wield_tool)
camera->drawWieldedTool(&rightMove);
}
guienv->drawAll();
for (unsigned int i = 0; i < screensize.Y; i += 2) {
#if (IRRLICHT_VERSION_MAJOR >= 1) && (IRRLICHT_VERSION_MINOR >= 8)
getVideoDriver()->draw2DImage(left_image,
irr::core::position2d<s32>(0, i),
#else
getVideoDriver()->draw2DImage(left_image,
irr::core::position2d<s32>(0, screensize.Y - i),
#endif
irr::core::rect<s32>(0, i, screensize.X, i + 1), 0,
irr::video::SColor(255, 255, 255, 255), false);
}
/* cleanup */
camera->getCameraNode()->setPosition(oldPosition);
camera->getCameraNode()->setTarget(oldTarget);
}
void RenderingEngine::draw_sidebyside_3d_mode(Camera *camera, bool show_hud, Hud *hud,
const v2u32 &screensize, bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor)
{
/* save current info */
irr::core::vector3df oldPosition = camera->getCameraNode()->getPosition();
irr::core::vector3df oldTarget = camera->getCameraNode()->getTarget();
irr::core::matrix4 startMatrix =
camera->getCameraNode()->getAbsoluteTransformation();
irr::core::vector3df focusPoint =
(camera->getCameraNode()->getTarget() -
camera->getCameraNode()->getAbsolutePosition())
.setLength(1) +
camera->getCameraNode()->getAbsolutePosition();
/* create left view */
video::ITexture *left_image = draw_image(screensize, LEFT, startMatrix,
focusPoint, show_hud, camera, hud, draw_wield_tool, client,
guienv, skycolor);
/* create right view */
video::ITexture *right_image = draw_image(screensize, RIGHT, startMatrix,
focusPoint, show_hud, camera, hud, draw_wield_tool, client,
guienv, skycolor);
/* create hud overlay */
video::ITexture *hudtexture = draw_hud(screensize, show_hud, hud, client, false,
skycolor, guienv, camera);
getVideoDriver()->makeColorKeyTexture(
hudtexture, irr::video::SColor(255, 0, 0, 0));
// makeColorKeyTexture mirrors texture so we do it twice to get it right again
getVideoDriver()->makeColorKeyTexture(
hudtexture, irr::video::SColor(255, 0, 0, 0));
draw2DImageFilterScaled(getVideoDriver(), left_image,
irr::core::rect<s32>(0, 0, screensize.X / 2, screensize.Y),
irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0,
false);
draw2DImageFilterScaled(getVideoDriver(), hudtexture,
irr::core::rect<s32>(0, 0, screensize.X / 2, screensize.Y),
irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0,
true);
draw2DImageFilterScaled(getVideoDriver(), right_image,
irr::core::rect<s32>(
screensize.X / 2, 0, screensize.X, screensize.Y),
irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0,
false);
draw2DImageFilterScaled(getVideoDriver(), hudtexture,
irr::core::rect<s32>(
screensize.X / 2, 0, screensize.X, screensize.Y),
irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0,
true);
left_image = nullptr;
right_image = nullptr;
/* cleanup */
camera->getCameraNode()->setPosition(oldPosition);
camera->getCameraNode()->setTarget(oldTarget);
}
void RenderingEngine::draw_top_bottom_3d_mode(Camera *camera, bool show_hud, Hud *hud,
const v2u32 &screensize, bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor)
{
/* save current info */
irr::core::vector3df oldPosition = camera->getCameraNode()->getPosition();
irr::core::vector3df oldTarget = camera->getCameraNode()->getTarget();
irr::core::matrix4 startMatrix =
camera->getCameraNode()->getAbsoluteTransformation();
irr::core::vector3df focusPoint =
(camera->getCameraNode()->getTarget() -
camera->getCameraNode()->getAbsolutePosition())
.setLength(1) +
camera->getCameraNode()->getAbsolutePosition();
/* create left view */
video::ITexture *left_image = draw_image(screensize, LEFT, startMatrix,
focusPoint, show_hud, camera, hud, draw_wield_tool, client,
guienv, skycolor);
/* create right view */
video::ITexture *right_image = draw_image(screensize, RIGHT, startMatrix,
focusPoint, show_hud, camera, hud, draw_wield_tool, client,
guienv, skycolor);
/* create hud overlay */
video::ITexture *hudtexture = draw_hud(screensize, show_hud, hud, client, false,
skycolor, guienv, camera);
getVideoDriver()->makeColorKeyTexture(
hudtexture, irr::video::SColor(255, 0, 0, 0));
// makeColorKeyTexture mirrors texture so we do it twice to get it right again
getVideoDriver()->makeColorKeyTexture(
hudtexture, irr::video::SColor(255, 0, 0, 0));
draw2DImageFilterScaled(getVideoDriver(), left_image,
irr::core::rect<s32>(0, 0, screensize.X, screensize.Y / 2),
irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0,
false);
draw2DImageFilterScaled(getVideoDriver(), hudtexture,
irr::core::rect<s32>(0, 0, screensize.X, screensize.Y / 2),
irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0,
true);
draw2DImageFilterScaled(getVideoDriver(), right_image,
irr::core::rect<s32>(
0, screensize.Y / 2, screensize.X, screensize.Y),
irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0,
false);
draw2DImageFilterScaled(getVideoDriver(), hudtexture,
irr::core::rect<s32>(
0, screensize.Y / 2, screensize.X, screensize.Y),
irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0,
true);
left_image = NULL;
right_image = NULL;
/* cleanup */
camera->getCameraNode()->setPosition(oldPosition);
camera->getCameraNode()->setTarget(oldTarget);
}
void RenderingEngine::draw_pageflip_3d_mode(Camera *camera, bool show_hud, Hud *hud,
const v2u32 &screensize, bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor)
{
#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8
errorstream << "Pageflip 3D mode is not supported"
<< " with your Irrlicht version!" << std::endl;
#else
/* preserve old setup*/
irr::core::vector3df oldPosition = camera->getCameraNode()->getPosition();
irr::core::vector3df oldTarget = camera->getCameraNode()->getTarget();
irr::core::matrix4 startMatrix =
camera->getCameraNode()->getAbsoluteTransformation();
irr::core::vector3df focusPoint =
(camera->getCameraNode()->getTarget() -
camera->getCameraNode()->getAbsolutePosition())
.setLength(1) +
camera->getCameraNode()->getAbsolutePosition();
// Left eye...
getVideoDriver()->setRenderTarget(irr::video::ERT_STEREO_LEFT_BUFFER);
irr::core::vector3df leftEye;
irr::core::matrix4 leftMove;
leftMove.setTranslation(irr::core::vector3df(
-g_settings->getFloat("3d_paralax_strength"), 0.0f, 0.0f));
leftEye = (startMatrix * leftMove).getTranslation();
// clear the depth buffer, and color
getVideoDriver()->beginScene(true, true, irr::video::SColor(200, 200, 200, 255));
camera->getCameraNode()->setPosition(leftEye);
camera->getCameraNode()->setTarget(focusPoint);
get_scene_manager()->drawAll();
getVideoDriver()->setTransform(video::ETS_WORLD, core::IdentityMatrix);
if (show_hud) {
hud->drawSelectionMesh();
if (draw_wield_tool)
camera->drawWieldedTool(&leftMove);
hud->drawHotbar(client->getPlayerItem());
hud->drawLuaElements(camera->getOffset());
camera->drawNametags();
}
guienv->drawAll();
// Right eye...
getVideoDriver()->setRenderTarget(irr::video::ERT_STEREO_RIGHT_BUFFER);
irr::core::vector3df rightEye;
irr::core::matrix4 rightMove;
rightMove.setTranslation(irr::core::vector3df(
g_settings->getFloat("3d_paralax_strength"), 0.0f, 0.0f));
rightEye = (startMatrix * rightMove).getTranslation();
// clear the depth buffer, and color
getVideoDriver()->beginScene(true, true, irr::video::SColor(200, 200, 200, 255));
camera->getCameraNode()->setPosition(rightEye);
camera->getCameraNode()->setTarget(focusPoint);
get_scene_manager()->drawAll();
getVideoDriver()->setTransform(video::ETS_WORLD, core::IdentityMatrix);
if (show_hud) {
hud->drawSelectionMesh();
if (draw_wield_tool)
camera->drawWieldedTool(&rightMove);
hud->drawHotbar(client->getPlayerItem());
hud->drawLuaElements(camera->getOffset());
camera->drawNametags();
}
guienv->drawAll();
camera->getCameraNode()->setPosition(oldPosition);
camera->getCameraNode()->setTarget(oldTarget);
#endif
}
// returns (size / coef), rounded upwards
inline int scaledown(int coef, int size)
{
return (size + coef - 1) / coef;
}
void RenderingEngine::draw_plain(Camera *camera, bool show_hud, Hud *hud,
const v2u32 &screensize, bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor)
{
// Undersampling-specific stuff
static video::ITexture *image = NULL;
static v2u32 last_pixelated_size = v2u32(0, 0);
static thread_local 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(pixelated_size, &image, "mt_drawimage_img1");
last_pixelated_size = pixelated_size;
}
getVideoDriver()->setRenderTarget(image, true, true, skycolor);
}
// Render
get_scene_manager()->drawAll();
getVideoDriver()->setTransform(video::ETS_WORLD, core::IdentityMatrix);
if (show_hud) {
hud->drawSelectionMesh();
if (draw_wield_tool) {
camera->drawWieldedTool();
}
}
// Upscale lowres render
if (undersampling > 0) {
getVideoDriver()->setRenderTarget(0, true, true);
getVideoDriver()->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));
}
} }
const char *RenderingEngine::getVideoDriverName(irr::video::E_DRIVER_TYPE type) const char *RenderingEngine::getVideoDriverName(irr::video::E_DRIVER_TYPE type)

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once #pragma once
#include <vector> #include <vector>
#include <memory>
#include <string> #include <string>
#include "irrlichttypes_extrabloated.h" #include "irrlichttypes_extrabloated.h"
#include "debug.h" #include "debug.h"
@ -32,6 +33,8 @@ class LocalPlayer;
class Hud; class Hud;
class Minimap; class Minimap;
class RenderingCore;
class RenderingEngine class RenderingEngine
{ {
public: public:
@ -41,7 +44,7 @@ public:
v2u32 getWindowSize() const; v2u32 getWindowSize() const;
void setResizable(bool resize); void setResizable(bool resize);
video::IVideoDriver *getVideoDriver(); video::IVideoDriver *getVideoDriver() { return driver; }
static const char *getVideoDriverName(irr::video::E_DRIVER_TYPE type); static const char *getVideoDriverName(irr::video::E_DRIVER_TYPE type);
static const char *getVideoDriverFriendlyName(irr::video::E_DRIVER_TYPE type); static const char *getVideoDriverFriendlyName(irr::video::E_DRIVER_TYPE type);
@ -107,15 +110,20 @@ public:
text, guienv, tsrc, dtime, percent, clouds); text, guienv, tsrc, dtime, percent, clouds);
} }
inline static void draw_scene(Camera *camera, Client *client, LocalPlayer *player, inline static void draw_scene(video::SColor skycolor, bool show_hud,
Hud *hud, Minimap *mapper, gui::IGUIEnvironment *guienv, bool show_minimap, bool draw_wield_tool, bool draw_crosshair)
const v2u32 &screensize, const video::SColor &skycolor,
bool show_hud, bool show_minimap)
{ {
s_singleton->_draw_scene(camera, client, player, hud, mapper, guienv, s_singleton->_draw_scene(skycolor, show_hud, show_minimap,
screensize, skycolor, show_hud, show_minimap); draw_wield_tool, draw_crosshair);
} }
inline static void initialize(Client *client, Hud *hud)
{
s_singleton->_initialize(client, hud);
}
inline static void finalize() { s_singleton->_finalize(); }
static bool run() static bool run()
{ {
sanity_check(s_singleton && s_singleton->m_device); sanity_check(s_singleton && s_singleton->m_device);
@ -126,60 +134,19 @@ public:
static std::vector<irr::video::E_DRIVER_TYPE> getSupportedVideoDrivers(); static std::vector<irr::video::E_DRIVER_TYPE> getSupportedVideoDrivers();
private: private:
enum parallax_sign
{
LEFT = -1,
RIGHT = 1,
EYECOUNT = 2
};
void _draw_load_screen(const std::wstring &text, gui::IGUIEnvironment *guienv, void _draw_load_screen(const std::wstring &text, gui::IGUIEnvironment *guienv,
ITextureSource *tsrc, float dtime = 0, int percent = 0, ITextureSource *tsrc, float dtime = 0, int percent = 0,
bool clouds = true); bool clouds = true);
void _draw_scene(Camera *camera, Client *client, LocalPlayer *player, Hud *hud, void _draw_scene(video::SColor skycolor, bool show_hud, bool show_minimap,
Minimap *mapper, gui::IGUIEnvironment *guienv, bool draw_wield_tool, bool draw_crosshair);
const v2u32 &screensize, const video::SColor &skycolor,
bool show_hud, bool show_minimap);
void draw_anaglyph_3d_mode(Camera *camera, bool show_hud, Hud *hud, void _initialize(Client *client, Hud *hud);
bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv);
void draw_interlaced_3d_mode(Camera *camera, bool show_hud, Hud *hud, void _finalize();
const v2u32 &screensize, bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor);
void draw_sidebyside_3d_mode(Camera *camera, bool show_hud, Hud *hud,
const v2u32 &screensize, bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor);
void draw_top_bottom_3d_mode(Camera *camera, bool show_hud, Hud *hud,
const v2u32 &screensize, bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor);
void draw_pageflip_3d_mode(Camera *camera, bool show_hud, Hud *hud,
const v2u32 &screensize, bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor);
void draw_plain(Camera *camera, bool show_hud, Hud *hud, const v2u32 &screensize,
bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor);
void init_texture(const v2u32 &screensize, video::ITexture **texture,
const char *name);
video::ITexture *draw_image(const v2u32 &screensize, parallax_sign psign,
const irr::core::matrix4 &startMatrix,
const irr::core::vector3df &focusPoint, bool show_hud,
Camera *camera, Hud *hud, bool draw_wield_tool, Client *client,
gui::IGUIEnvironment *guienv, const video::SColor &skycolor);
video::ITexture *draw_hud(const v2u32 &screensize, bool show_hud, Hud *hud,
Client *client, bool draw_crosshair,
const video::SColor &skycolor, gui::IGUIEnvironment *guienv,
Camera *camera);
std::unique_ptr<RenderingCore> core;
irr::IrrlichtDevice *m_device = nullptr; irr::IrrlichtDevice *m_device = nullptr;
irr::video::IVideoDriver *driver;
static RenderingEngine *s_singleton; static RenderingEngine *s_singleton;
}; };

@ -1656,6 +1656,8 @@ bool Game::startup(bool *kill,
if (!createClient(playername, password, address, port)) if (!createClient(playername, password, address, port))
return false; return false;
RenderingEngine::initialize(client, hud);
return true; return true;
} }
@ -1745,6 +1747,7 @@ void Game::run()
void Game::shutdown() void Game::shutdown()
{ {
RenderingEngine::finalize();
#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 8 #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 8
if (g_settings->get("3d_mode") == "pageflip") { if (g_settings->get("3d_mode") == "pageflip") {
driver->setRenderTarget(irr::video::ERT_STEREO_BOTH_BUFFERS); driver->setRenderTarget(irr::video::ERT_STEREO_BOTH_BUFFERS);
@ -4339,9 +4342,20 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
TimeTaker tt_draw("mainloop: draw"); TimeTaker tt_draw("mainloop: draw");
driver->beginScene(true, true, skycolor); driver->beginScene(true, true, skycolor);
RenderingEngine::draw_scene(camera, client, player, hud, mapper, bool draw_wield_tool = (flags.show_hud &&
guienv, screensize, skycolor, flags.show_hud, (player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE) &&
flags.show_minimap); (camera->getCameraMode() == CAMERA_MODE_FIRST));
bool draw_crosshair = (
(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
(camera->getCameraMode() != CAMERA_MODE_THIRD_FRONT));
#ifdef HAVE_TOUCHSCREENGUI
try {
draw_crosshair = !g_settings->getBool("touchtarget");
} catch (SettingNotFoundException) {
}
#endif
RenderingEngine::draw_scene(skycolor, flags.show_hud, flags.show_minimap,
draw_wield_tool, draw_crosshair);
/* /*
Profiler graph Profiler graph
@ -4402,7 +4416,7 @@ inline static const char *yawToDirectionString(int yaw)
void Game::updateGui(const RunStats &stats, f32 dtime, const CameraOrientation &cam) void Game::updateGui(const RunStats &stats, f32 dtime, const CameraOrientation &cam)
{ {
v2u32 screensize = driver->getScreenSize(); v2u32 screensize = RenderingEngine::get_instance()->getWindowSize();
LocalPlayer *player = client->getEnv().getLocalPlayer(); LocalPlayer *player = client->getEnv().getLocalPlayer();
v3f player_position = player->getPosition(); v3f player_position = player->getPosition();

@ -286,7 +286,7 @@ fake_function() {
gettext("Fall bobbing factor"); gettext("Fall bobbing factor");
gettext("Multiplier for fall bobbing.\nFor example: 0 for no view bobbing; 1.0 for normal; 2.0 for double."); gettext("Multiplier for fall bobbing.\nFor example: 0 for no view bobbing; 1.0 for normal; 2.0 for double.");
gettext("3D mode"); gettext("3D mode");
gettext("3D support.\nCurrently supported:\n- none: no 3d output.\n- anaglyph: cyan/magenta color 3d.\n- interlaced: odd/even line based polarisation screen support.\n- topbottom: split screen top/bottom.\n- sidebyside: split screen side by side.\n- pageflip: quadbuffer based 3d."); gettext("3D support.\nCurrently supported:\n- none: no 3d output.\n- anaglyph: cyan/magenta color 3d.\n- interlaced: odd/even line based polarisation screen support.\n- topbottom: split screen top/bottom.\n- sidebyside: split screen side by side.\n- pageflip: quadbuffer based 3d.\nNote that the interlaced mode requires shaders to be enabled.");
gettext("Console height"); gettext("Console height");
gettext("In-game chat console height, between 0.1 (10%) and 1.0 (100%)."); gettext("In-game chat console height, between 0.1 (10%) and 1.0 (100%).");
gettext("Console color"); gettext("Console color");