Interlaced 3D

experimental^2
number Zero 2017-08-16 16:51:18 +03:00
parent de7ff3f9db
commit 3ac96d2670
5 changed files with 335 additions and 50 deletions

View File

@ -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;
}

View File

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

View File

@ -11,6 +11,11 @@ RenderingCore::RenderingCore(irr::IrrlichtDevice *_device) :
device(_device),
driver(device->getVideoDriver()),
smgr(device->getSceneManager())
{
screensize = driver->getScreenSize();
}
void RenderingCore::update_screen_size()
{
}
@ -26,7 +31,10 @@ void RenderingCore::setup(Camera *_camera, Client *_client, LocalPlayer *_player
mapper = _mapper;
guienv = _guienv;
screensize = _screensize;
if (screensize != _screensize) {
screensize = _screensize;
update_screen_size();
}
skycolor = _skycolor;
show_hud = _show_hud;
show_minimap = _show_minimap;
@ -94,17 +102,32 @@ RenderingCoreStereo::RenderingCoreStereo(irr::IrrlichtDevice *_device) :
parallax_strength = g_settings->getFloat("3d_paralax_strength");
}
void RenderingCoreStereo::use_eye(Eye eye)
void RenderingCoreStereo::pre_draw()
{
irr::scene::ICameraSceneNode *cam = camera->getCameraNode();
irr::core::matrix4 transform = cam->getRelativeTransformation();
irr::core::matrix4 move;
move.setTranslation(irr::core::vector3df(static_cast<int>(eye) * parallax_strength, 0.0f, 0.0f));
cam->setPosition((transform * move).getTranslation());
cam = camera->getCameraNode();
base_transform = cam->getRelativeTransformation();
}
void RenderingCoreStereo::use_default()
void RenderingCoreStereo::use_eye(bool right)
{
irr::core::matrix4 move;
move.setTranslation(irr::core::vector3df(right ? parallax_strength : -parallax_strength, 0.0f, 0.0f));
cam->setPosition((base_transform * move).getTranslation());
}
void RenderingCoreStereo::reset_eye()
{
cam->setPosition(base_transform.getTranslation());
}
void RenderingCoreStereo::draw_two()
{
use_eye(false);
draw_3d();
reset_eye();
use_eye(true);
draw_3d();
reset_eye();
}
RenderingCoreAnaglyph::RenderingCoreAnaglyph(irr::IrrlichtDevice *_device) :
@ -114,28 +137,18 @@ RenderingCoreAnaglyph::RenderingCoreAnaglyph(irr::IrrlichtDevice *_device) :
void RenderingCoreAnaglyph::draw()
{
use_eye(Eye::Left);
draw_3d();
use_eye(Eye::Right);
draw_3d();
use_default();
pre_draw();
draw_two();
draw_last_fx();
draw_hud();
}
void RenderingCoreAnaglyph::use_eye(Eye eye)
void RenderingCoreAnaglyph::use_eye(bool right)
{
RenderingCoreStereo::use_eye(eye);
RenderingCoreStereo::use_eye(right);
driver->clearZBuffer();
irr::video::SOverrideMaterial &mat = driver->getOverrideMaterial();
switch (eye) {
case Eye::Left:
mat.Material.ColorMask = irr::video::ECP_RED;
break;
case Eye::Right:
mat.Material.ColorMask = irr::video::ECP_GREEN | irr::video::ECP_BLUE;
break;
}
mat.Material.ColorMask = right ? irr::video::ECP_GREEN | irr::video::ECP_BLUE : irr::video::ECP_RED;
mat.EnableFlags = irr::video::EMF_COLOR_MASK;
mat.EnablePasses =
irr::scene::ESNRP_SKY_BOX | irr::scene::ESNRP_SOLID |
@ -143,9 +156,8 @@ void RenderingCoreAnaglyph::use_eye(Eye eye)
irr::scene::ESNRP_TRANSPARENT_EFFECT | irr::scene::ESNRP_SHADOW;
}
void RenderingCoreAnaglyph::use_default()
void RenderingCoreAnaglyph::reset_eye()
{
RenderingCoreStereo::use_default();
irr::video::SOverrideMaterial &mat = driver->getOverrideMaterial();
mat.Material.ColorMask = irr::video::ECP_ALL;
mat.EnableFlags = irr::video::EMF_COLOR_MASK;
@ -155,20 +167,220 @@ void RenderingCoreAnaglyph::use_default()
irr::scene::ESNRP_TRANSPARENT_EFFECT + irr::scene::ESNRP_SHADOW;
}
RenderingCoreDouble::RenderingCoreDouble(irr::IrrlichtDevice *_device, RenderingCoreDouble::Mode _mode) :
RenderingCoreSideBySide::RenderingCoreSideBySide(irr::IrrlichtDevice *_device) :
RenderingCoreStereo(_device)
{
init_textures();
}
void RenderingCoreDouble::draw()
RenderingCoreSideBySide::~RenderingCoreSideBySide()
{
clear_textures();
}
void RenderingCoreSideBySide::init_textures()
{
image_size = v2u32(screensize.X / 2, screensize.Y);
left = driver->addRenderTargetTexture(image_size, "3d_render_left", irr::video::ECF_A8R8G8B8);
right = driver->addRenderTargetTexture(image_size, "3d_render_right", irr::video::ECF_A8R8G8B8);
hud = driver->addRenderTargetTexture(screensize, "3d_render_hud", irr::video::ECF_A8R8G8B8);
}
void RenderingCoreSideBySide::clear_textures()
{
driver->removeTexture(left);
driver->removeTexture(right);
driver->removeTexture(hud);
}
void RenderingCoreSideBySide::update_screen_size()
{
clear_textures();
init_textures();
}
void RenderingCoreSideBySide::draw()
{
pre_draw();
draw_two();
driver->setRenderTarget(hud, true, true, video::SColor(0, 0, 0, 0));
draw_hud();
driver->setRenderTarget(nullptr, false, false, skycolor);
driver->draw2DImage(left, v2s32(0, 0));
driver->draw2DImage(right, v2s32(screensize.X / 2, 0));
driver->draw2DImage(hud,
irr::core::rect<s32>(0, 0, screensize.X / 2, screensize.Y),
irr::core::rect<s32>(0, 0, screensize.X, screensize.Y), 0, 0,
true);
driver->draw2DImage(hud,
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);
}
void RenderingCoreSideBySide::use_eye(bool _right)
{
driver->setRenderTarget(_right ? right : left, true, true, skycolor);
RenderingCoreStereo::use_eye(_right);
}
void RenderingCoreSideBySide::reset_eye()
{
driver->setRenderTarget(nullptr, false, false, skycolor);
RenderingCoreStereo::reset_eye();
}
RenderingCorePageflip::RenderingCorePageflip(irr::IrrlichtDevice *_device) :
RenderingCoreStereo(_device)
{
init_textures();
}
RenderingCorePageflip::~RenderingCorePageflip()
{
clear_textures();
}
void RenderingCorePageflip::init_textures()
{
hud = driver->addRenderTargetTexture(screensize, "3d_render_hud", irr::video::ECF_A8R8G8B8);
}
void RenderingCorePageflip::clear_textures()
{
driver->removeTexture(hud);
}
void RenderingCorePageflip::update_screen_size()
{
clear_textures();
init_textures();
}
void RenderingCorePageflip::draw()
{
pre_draw();
driver->setRenderTarget(hud, true, true, video::SColor(0, 0, 0, 0));
draw_hud();
driver->setRenderTarget(nullptr, false, false, skycolor);
draw_two();
}
void RenderingCorePageflip::use_eye(bool _right)
{
driver->setRenderTarget(
_right ? irr::video::ERT_STEREO_RIGHT_BUFFER : irr::video::ERT_STEREO_LEFT_BUFFER,
true, true, skycolor);
RenderingCoreStereo::use_eye(_right);
}
void RenderingCorePageflip::reset_eye()
{
driver->draw2DImage(hud, v2s32(0, 0));
driver->setRenderTarget(irr::video::ERT_FRAME_BUFFER, false, false, skycolor);
RenderingCoreStereo::reset_eye();
}
RenderingCoreInterlaced::RenderingCoreInterlaced(irr::IrrlichtDevice *_device) :
RenderingCoreStereo(_device)
{
mat.MaterialType = (video::E_MATERIAL_TYPE)0;
init_textures();
}
RenderingCoreInterlaced::~RenderingCoreInterlaced()
{
clear_textures();
}
void RenderingCoreInterlaced::init_material()
{
if (mat.MaterialType)
return;
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 = irr::video::ETC_CLAMP_TO_EDGE;
mat.TextureLayer[k].TextureWrapV = irr::video::ETC_CLAMP_TO_EDGE;
}
}
void RenderingCoreInterlaced::init_textures()
{
image_size = v2u32(screensize.X, screensize.Y / 2);
left = driver->addRenderTargetTexture(image_size, "3d_render_left", irr::video::ECF_A8R8G8B8);
right = driver->addRenderTargetTexture(image_size, "3d_render_right", irr::video::ECF_A8R8G8B8);
mask = driver->addTexture(screensize, "3d_render_mask", irr::video::ECF_A8R8G8B8);
init_mask();
mat.TextureLayer[0].Texture = left;
mat.TextureLayer[1].Texture = right;
mat.TextureLayer[2].Texture = mask;
}
void RenderingCoreInterlaced::clear_textures()
{
driver->removeTexture(left);
driver->removeTexture(right);
driver->removeTexture(mask);
}
void RenderingCoreInterlaced::init_mask()
{
u8 *data = reinterpret_cast<u8 *>(mask->lock());
for (unsigned 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::update_screen_size()
{
clear_textures();
init_textures();
}
void RenderingCoreInterlaced::draw()
{
pre_draw();
draw_two();
merge();
draw_hud();
}
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 };
init_material();
driver->setMaterial(mat);
driver->drawVertexPrimitiveList(&vertices, 4, &indices, 2);
}
void RenderingCoreInterlaced::use_eye(bool _right)
{
driver->setRenderTarget(_right ? right : left, true, true, skycolor);
RenderingCoreStereo::use_eye(_right);
}
void RenderingCoreInterlaced::reset_eye()
{
driver->setRenderTarget(nullptr, false, false, skycolor);
RenderingCoreStereo::reset_eye();
}

View File

@ -48,11 +48,13 @@ protected:
irr::scene::ISceneManager *smgr;
irr::gui::IGUIEnvironment *guienv;
virtual void update_screen_size();
public:
RenderingCore(irr::IrrlichtDevice *_device);
RenderingCore(const RenderingCore &) = delete;
RenderingCore(RenderingCore &&) = delete;
~RenderingCore() = default;
virtual ~RenderingCore() = default;
RenderingCore &operator= (const RenderingCore &) = delete;
RenderingCore &operator= (RenderingCore &&) = delete;
@ -78,45 +80,91 @@ public:
class RenderingCoreStereo: public RenderingCore
{
protected:
irr::scene::ICameraSceneNode *cam;
irr::core::matrix4 base_transform;
float parallax_strength;
void pre_draw();
virtual void use_eye(bool right);
virtual void reset_eye();
void draw_two();
public:
enum class Eye
{
Left = -1,
Right = 1,
};
RenderingCoreStereo(irr::IrrlichtDevice *_device);
virtual void use_eye(Eye eye);
virtual void use_default();
};
class RenderingCoreAnaglyph: public RenderingCoreStereo
{
protected:
void use_eye(bool right) override;
void reset_eye() override;
public:
RenderingCoreAnaglyph(irr::IrrlichtDevice *_device);
void draw() override;
void use_eye(Eye eye) override;
void use_default() override;
};
class RenderingCoreDouble: public RenderingCoreStereo
class RenderingCoreSideBySide: public RenderingCoreStereo
{
public:
enum class Mode
{
SideBySide,
TopBottom,
Pageflip
};
protected:
v2u32 image_size;
video::ITexture *left = nullptr;
video::ITexture *right = nullptr;
video::ITexture *hud = nullptr;
RenderingCoreDouble(irr::IrrlichtDevice *_device, Mode _mode);
void init_textures();
void clear_textures();
void update_screen_size() override;
void use_eye(bool right) override;
void reset_eye() override;
public:
RenderingCoreSideBySide(irr::IrrlichtDevice *_device);
~RenderingCoreSideBySide() override;
void draw() override;
};
class RenderingCorePageflip: public RenderingCoreStereo
{
protected:
video::ITexture *hud = nullptr;
void init_textures();
void clear_textures();
void update_screen_size() override;
void use_eye(bool right) override;
void reset_eye() override;
public:
RenderingCorePageflip(irr::IrrlichtDevice *_device);
~RenderingCorePageflip() override;
void draw() override;
};
class RenderingCoreInterlaced: public RenderingCoreStereo
{
protected:
v2u32 image_size;
video::ITexture *left = nullptr;
video::ITexture *right = nullptr;
video::ITexture *mask = nullptr;
video::SMaterial mat;
void init_material();
void init_textures();
void clear_textures();
void init_mask();
void update_screen_size() override;
void use_eye(bool right) override;
void reset_eye() override;
void merge();
public:
RenderingCoreInterlaced(irr::IrrlichtDevice *_device);
~RenderingCoreInterlaced() override;
void draw() override;
};

View File

@ -107,11 +107,9 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver)
else if (draw_mode == "interlaced")
core.reset(new RenderingCoreInterlaced(m_device));
else if (draw_mode == "sidebyside")
core.reset(new RenderingCoreDouble(m_device, RenderingCoreDouble::Mode::SideBySide));
else if (draw_mode == "topbottom")
core.reset(new RenderingCoreDouble(m_device, RenderingCoreDouble::Mode::TopBottom));
core.reset(new RenderingCoreSideBySide(m_device));
else if (draw_mode == "pageflip")
core.reset(new RenderingCoreDouble(m_device, RenderingCoreDouble::Mode::Pageflip));
core.reset(new RenderingCorePageflip(m_device));
else
core.reset(new RenderingCorePlain(m_device));