From ddcddf4a0aa1de889871834cd562b07b939ec8da Mon Sep 17 00:00:00 2001
From: hiker <henrichsjoerg@gmail.com>
Date: Thu, 14 Apr 2016 00:49:18 +1000
Subject: [PATCH] Compile SERVER_ONLY (by #ifdef'ing out all graphics related
 code). Does not link yet!!

---
 src/config/hardware_stats.cpp             |    2 +
 src/graphics/2dutils.cpp                  |    4 +
 src/graphics/central_settings.cpp         |    3 +
 src/graphics/gl_headers.hpp               |    9 +
 src/graphics/glwrap.cpp                   |    5 +
 src/graphics/glwrap.hpp                   |    5 +
 src/graphics/gpu_particles.cpp            |    4 +
 src/graphics/gpu_particles.hpp            |    4 +
 src/graphics/irr_driver.cpp               |   34 +-
 src/graphics/lighting_passes.cpp          | 1494 +++++++++++----------
 src/graphics/material.cpp                 |    3 +-
 src/graphics/material_manager.cpp         |    3 +-
 src/graphics/mesh_tools.cpp               |    2 +
 src/graphics/particle_emitter.cpp         |    4 +
 src/graphics/post_processing.cpp          |    4 +
 src/graphics/rtts.cpp                     |    4 +
 src/graphics/shader.cpp                   |    4 +
 src/graphics/shader.hpp                   |    5 +
 src/graphics/shaders.cpp                  |    4 +
 src/graphics/shaders.hpp                  |    4 +
 src/graphics/shadow_matrices.cpp          |    4 +
 src/graphics/shared_gpu_objects.cpp       |    5 +
 src/graphics/show_curve.cpp               |    5 +
 src/graphics/skybox.cpp                   |    2 +
 src/graphics/slip_stream.cpp              |    2 +
 src/graphics/spherical_harmonics.cpp      |    3 +
 src/graphics/stk_animated_mesh.cpp        |    5 +
 src/graphics/stk_billboard.cpp            |    5 +
 src/graphics/stk_mesh.cpp                 |    5 +
 src/graphics/stk_mesh_scene_node.cpp      |    5 +
 src/graphics/stk_mesh_scene_node.hpp      |    2 +
 src/graphics/stk_scene_manager.cpp        |    4 +
 src/graphics/stk_scene_manager.hpp        |    4 +
 src/graphics/stk_text_billboard.cpp       |    5 +
 src/graphics/texture_manager.cpp          |    5 +
 src/graphics/texture_shader.cpp           |    5 +
 src/graphics/texture_shader.hpp           |    4 +
 src/graphics/vao_manager.cpp              |    4 +
 src/graphics/water.cpp                    |    5 +
 src/guiengine/engine.cpp                  |    2 +
 src/guiengine/skin.cpp                    |    2 +
 src/items/rubber_band.cpp                 |    2 +
 src/karts/kart_properties.cpp             |    2 +
 src/states_screens/race_gui.cpp           |    6 +-
 src/states_screens/race_gui_overworld.cpp |    6 +-
 src/tracks/check_line.cpp                 |    4 +
 src/tracks/track.cpp                      |   10 +-
 src/utils/debug.cpp                       |    4 +-
 src/utils/profiler.cpp                    |    4 +
 49 files changed, 968 insertions(+), 754 deletions(-)

diff --git a/src/config/hardware_stats.cpp b/src/config/hardware_stats.cpp
index 91c07f56c..6102bbd87 100644
--- a/src/config/hardware_stats.cpp
+++ b/src/config/hardware_stats.cpp
@@ -335,8 +335,10 @@ void reportHardwareStats()
     if(nr_procs>0)
         json.add("cpu_numprocs", nr_procs);
 
+#ifndef SERVER_ONLY
     json.add("GL_EXTENSIONS", getGLExtensions());
     getGLLimits(&json);
+#endif
     json.finish();
 
     // ------------------------------------------------------------------------
diff --git a/src/graphics/2dutils.cpp b/src/graphics/2dutils.cpp
index 38814a5b4..87bf3a16e 100644
--- a/src/graphics/2dutils.cpp
+++ b/src/graphics/2dutils.cpp
@@ -15,6 +15,7 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
 #include "graphics/2dutils.hpp"
 
 #include "graphics/central_settings.hpp"
@@ -779,3 +780,6 @@ void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position,
 
     glGetError();
 }   // GL32_draw2DRectangle
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/central_settings.cpp b/src/graphics/central_settings.cpp
index c2c839263..eff869a0f 100644
--- a/src/graphics/central_settings.cpp
+++ b/src/graphics/central_settings.cpp
@@ -15,6 +15,7 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
 #include "graphics/central_settings.hpp"
 
 #include "config/user_config.hpp"
@@ -442,3 +443,5 @@ bool CentralVideoSettings::isDefferedEnabled() const
 {
     return UserConfigParams::m_dynamic_lights && !GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_ADVANCED_PIPELINE);
 }
+
+#endif   // !SERVER_ONLY
diff --git a/src/graphics/gl_headers.hpp b/src/graphics/gl_headers.hpp
index 57c63d027..3cc3c8bdd 100644
--- a/src/graphics/gl_headers.hpp
+++ b/src/graphics/gl_headers.hpp
@@ -18,6 +18,8 @@
 #ifndef GL_HEADER_HPP
 #define GL_HEADER_HPP
 
+#ifndef SERVER_ONLY
+
 #define GLEW_STATIC
 
 extern "C" {
@@ -79,5 +81,12 @@ struct DrawElementsIndirectCommand{
     GLuint baseVertex;
     GLuint baseInstance;
 };
+#else
+  typedef unsigned int GLuint;
+  typedef unsigned int GLsync;
+  typedef unsigned int GLenum;
+
+#endif   // server only
 
 #endif
+
diff --git a/src/graphics/glwrap.cpp b/src/graphics/glwrap.cpp
index b411c604d..295f27fb8 100644
--- a/src/graphics/glwrap.cpp
+++ b/src/graphics/glwrap.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/glwrap.hpp"
 
 #include "config/hardware_stats.hpp"
@@ -758,3 +760,6 @@ else \
 
 #endif  // ifdef XX
 }   // getGLLimits
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/glwrap.hpp b/src/graphics/glwrap.hpp
index dbb7522e9..531942839 100644
--- a/src/graphics/glwrap.hpp
+++ b/src/graphics/glwrap.hpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #ifndef GLWRAP_HEADER_H
 #define GLWRAP_HEADER_H
 
@@ -152,3 +154,6 @@ const std::string getGLExtensions();
 void getGLLimits(HardwareStats::Json *json);
 
 #endif
+
+#endif   // supertuxkart
+
diff --git a/src/graphics/gpu_particles.cpp b/src/graphics/gpu_particles.cpp
index 0406c90f5..261ee565b 100644
--- a/src/graphics/gpu_particles.cpp
+++ b/src/graphics/gpu_particles.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/gpu_particles.hpp"
 
 #include "config/user_config.hpp"
@@ -633,3 +635,5 @@ void ParticleSystemProxy::render() {
         draw();
     }
 }
+
+#endif   // SERVER_ONLY
diff --git a/src/graphics/gpu_particles.hpp b/src/graphics/gpu_particles.hpp
index d23d3952f..0b52244e3 100644
--- a/src/graphics/gpu_particles.hpp
+++ b/src/graphics/gpu_particles.hpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #ifndef HEADER_GPU_PARTICLES_HPP
 #define HEADER_GPU_PARTICLES_HPP
 
@@ -109,3 +111,5 @@ public:
 };
 
 #endif // GPUPARTICLES_H
+
+#endif  // !SERVER_ONLY
diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp
index 8771eba4b..f776cfd8e 100644
--- a/src/graphics/irr_driver.cpp
+++ b/src/graphics/irr_driver.cpp
@@ -96,8 +96,9 @@ using namespace irr;
 /** singleton */
 IrrDriver *irr_driver = NULL;
 
-
+#ifndef SERVER_ONLY
 GPUTimer          m_perf_query[Q_LAST];
+#endif
 
 const int MIN_SUPPORTED_HEIGHT = 768;
 const int MIN_SUPPORTED_WIDTH  = 1024;
@@ -144,10 +145,12 @@ IrrDriver::~IrrDriver()
     m_device = NULL;
     m_modes.clear();
 
+#ifndef SERVER_ONLY
     if (CVS->isGLSL())
     {
         Shaders::destroy();
     }
+#endif
     delete m_wind;
     delete m_renderer;
 }   // ~IrrDriver
@@ -179,11 +182,12 @@ core::array<video::IRenderTarget> &IrrDriver::getMainSetup()
 {
   return m_mrt;
 }
-
+#ifndef SERVER_ONLY
 GPUTimer &IrrDriver::getGPUTimer(unsigned i)
 {
     return m_perf_query[i];
 }
+#endif
 
 
 
@@ -587,6 +591,8 @@ void IrrDriver::initDevice()
         UserConfigParams::m_gi = false;
     }*/
 
+#ifndef SERVER_ONLY
+
     // m_glsl might be reset in rtt if an error occurs.
     if (CVS->isGLSL())
     {
@@ -601,6 +607,7 @@ void IrrDriver::initDevice()
         Log::warn("irr_driver", "Using the fixed pipeline (old GPU, or "
                                 "shaders disabled in options)");
     }
+#endif
 
     // Only change video driver settings if we are showing graphics
     if (!ProfileWorld::isNoGraphics())
@@ -689,12 +696,16 @@ void IrrDriver::createSunInterposer()
         scene::IMeshBuffer *mb = sphere->getMeshBuffer(i);
         if (!mb)
             continue;
-        mb->getMaterial().setTexture(0,
+
+#ifndef SERVER_ONLY
+    mb->getMaterial().setTexture(0,
                         getUnicolorTexture(video::SColor(255, 255, 255, 255)));
         mb->getMaterial().setTexture(1,
                                 getUnicolorTexture(video::SColor(0, 0, 0, 0)));
         mb->getMaterial().setTexture(7,
                                 getUnicolorTexture(video::SColor(0, 0, 0, 0)));
+#endif
+        
     }
     m_sun_interposer = new STKMeshSceneNode(sphere,
                                             m_scene_manager->getRootSceneNode(),
@@ -707,7 +718,9 @@ void IrrDriver::createSunInterposer()
     m_sun_interposer->getMaterial(0).Lighting = false;
     m_sun_interposer->getMaterial(0).ColorMask = video::ECP_NONE;
     m_sun_interposer->getMaterial(0).ZWriteEnable = false;
+#ifndef SERVER_ONLY
     m_sun_interposer->getMaterial(0).MaterialType = Shaders::getShader(ES_OBJECTPASS);
+#endif
 
     sphere->drop();
 }
@@ -716,9 +729,11 @@ void IrrDriver::createSunInterposer()
 void IrrDriver::getOpenGLData(std::string *vendor, std::string *renderer,
                               std::string *version)
 {
+#ifndef SERVER_ONLY
     *vendor   = (char*)glGetString(GL_VENDOR  );
     *renderer = (char*)glGetString(GL_RENDERER);
     *version  = (char*)glGetString(GL_VERSION );
+#endif
 }   // getOpenGLData
 
 //-----------------------------------------------------------------------------
@@ -829,6 +844,7 @@ void IrrDriver::changeResolution(const int w, const int h,
 
 void IrrDriver::applyResolutionSettings()
 {
+#ifndef SERVER_ONLY
     // show black before resolution switch so we don't see OpenGL's buffer
     // garbage during switch
     m_video_driver->beginScene(true, true, video::SColor(255,100,101,140));
@@ -918,6 +934,7 @@ void IrrDriver::applyResolutionSettings()
     // above) - this happens dynamically when the tracks are loaded.
     GUIEngine::reshowCurrentScreen();
     MessageQueue::updatePosition();
+#endif   // !SERVER_ONLY
 }   // applyResolutionSettings
 
 // ----------------------------------------------------------------------------
@@ -1133,10 +1150,13 @@ scene::IMeshSceneNode *IrrDriver::addSphere(float radius,
     m.EmissiveColor   = color;
     m.BackfaceCulling = false;
     m.MaterialType    = video::EMT_SOLID;
+
+#ifndef SERVER_ONLY
     //m.setTexture(0, getUnicolorTexture(video::SColor(128, 255, 105, 180)));
     m.setTexture(0, getUnicolorTexture(color));
     m.setTexture(1, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
     m.setTexture(7, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
+#endif
 
     if (CVS->isGLSL())
     {
@@ -2076,6 +2096,8 @@ bool IrrDriver::supportsSplatting()
 }
 
 // ----------------------------------------------------------------------------
+
+#ifndef SERVER_ONLY
 void IrrDriver::applyObjectPassShader(scene::ISceneNode * const node, bool rimlit)
 {
     if (!CVS->isGLSL())
@@ -2153,6 +2175,8 @@ void IrrDriver::applyObjectPassShader()
     applyObjectPassShader(m_scene_manager->getRootSceneNode());
 }
 
+#endif   // !SERVER_ONLY
+
 // ----------------------------------------------------------------------------
 
 scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos,
@@ -2160,6 +2184,7 @@ scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos,
                                        float r, float g, float b,
                                        bool sun, scene::ISceneNode* parent)
 {
+#ifndef SERVER_ONLY
     if (CVS->isGLSL())
     {
         if (parent == NULL) parent = m_scene_manager->getRootSceneNode();
@@ -2194,6 +2219,9 @@ scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos,
                ->addLightSceneNode(m_scene_manager->getRootSceneNode(),
                                    pos, video::SColorf(1.0f, r, g, b));
     }
+#else
+    return NULL;
+#endif
 }   // addLight
 
 // ----------------------------------------------------------------------------
diff --git a/src/graphics/lighting_passes.cpp b/src/graphics/lighting_passes.cpp
index 57679afa3..c56a9fe3c 100644
--- a/src/graphics/lighting_passes.cpp
+++ b/src/graphics/lighting_passes.cpp
@@ -1,746 +1,750 @@
-//  SuperTuxKart - a fun racing game with go-kart
-//  Copyright (C) 2015 SuperTuxKart-Team
-//
-//  This program is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU General Public License
-//  as published by the Free Software Foundation; either version 3
-//  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 General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-#include "graphics/lighting_passes.hpp"
-#include "config/user_config.hpp"
+//  SuperTuxKart - a fun racing game with go-kart
+//  Copyright (C) 2015 SuperTuxKart-Team
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 3
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef SERVER_ONLY
+
+#include "graphics/lighting_passes.hpp"
+#include "config/user_config.hpp"
 #include "graphics/central_settings.hpp"
-#include "graphics/glwrap.hpp"
-#include "graphics/irr_driver.hpp"
-#include "graphics/light.hpp"
-#include "graphics/post_processing.hpp"
-#include "graphics/rtts.hpp"
-#include "graphics/shaders.hpp"
-#include "graphics/shadow_matrices.hpp"
-#include "modes/world.hpp"
-#include "tracks/track.hpp"
-#include "utils/profiler.hpp"
-
-class LightBaseClass
-{
-public:
-    struct PointLightInfo
-    {
-        float posX;
-        float posY;
-        float posZ;
-        float energy;
-        float red;
-        float green;
-        float blue;
-        float radius;
-    };
-public:
-    static const unsigned int MAXLIGHT = 32;
-public:
-    static struct PointLightInfo m_point_lights_info[MAXLIGHT];
-};   // LightBaseClass
-
-const unsigned int LightBaseClass::MAXLIGHT;
-
-// ============================================================================
-LightBaseClass::PointLightInfo m_point_lights_info[LightBaseClass::MAXLIGHT];
-
-
-// ============================================================================
-class FogShader : public TextureShader<FogShader, 1, float, core::vector3df>
-{
-public:
-    FogShader()
-    {
-        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
-                            GL_FRAGMENT_SHADER, "fog.frag");
-        assignUniforms("density", "col");
-        assignSamplerNames(0, "tex", ST_NEAREST_FILTERED);
-    }   // FogShader
-    // ------------------------------------------------------------------------
-    void render(float start, const core::vector3df &color, GLuint depth_stencil_texture)
-    {
-        setTextureUnits(depth_stencil_texture);
-        drawFullScreenEffect(1.f / (40.f * start), color);
-
-    }   // render
-};   // FogShader
-
-// ============================================================================
-class PointLightShader : public TextureShader < PointLightShader, 2 >
-{
-public:
-    GLuint vbo;
-    GLuint vao;
-    PointLightShader()
-    {
-        loadProgram(OBJECT, GL_VERTEX_SHADER, "pointlight.vert",
-                            GL_FRAGMENT_SHADER, "pointlight.frag");
-
-        assignUniforms();
-        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED,
-                           1, "dtex", ST_NEAREST_FILTERED);
-        glGenVertexArrays(1, &vao);
-        glBindVertexArray(vao);
-
-        glGenBuffers(1, &vbo);
-        glBindBuffer(GL_ARRAY_BUFFER, vbo);
-        glBufferData(GL_ARRAY_BUFFER,
-                     LightBaseClass::MAXLIGHT * sizeof(LightBaseClass::PointLightInfo),
-                     0, GL_DYNAMIC_DRAW);
-
-        GLuint attrib_Position = glGetAttribLocation(m_program, "Position");
-        GLuint attrib_Color = glGetAttribLocation(m_program, "Color");
-        GLuint attrib_Energy = glGetAttribLocation(m_program, "Energy");
-        GLuint attrib_Radius = glGetAttribLocation(m_program, "Radius");
-
-        glEnableVertexAttribArray(attrib_Position);
-        glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE,
-                              sizeof(LightBaseClass::PointLightInfo), 0);
-        glEnableVertexAttribArray(attrib_Energy);
-        glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE,
-                              sizeof(LightBaseClass::PointLightInfo),
-                              (GLvoid*)(3 * sizeof(float)));
-        glEnableVertexAttribArray(attrib_Color);
-        glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE,
-                              sizeof(LightBaseClass::PointLightInfo),
-                              (GLvoid*)(4 * sizeof(float)));
-        glEnableVertexAttribArray(attrib_Radius);
-        glVertexAttribPointer(attrib_Radius, 1, GL_FLOAT, GL_FALSE,
-                              sizeof(LightBaseClass::PointLightInfo),
-                              (GLvoid*)(7 * sizeof(float)));
-
-        glVertexAttribDivisorARB(attrib_Position, 1);
-        glVertexAttribDivisorARB(attrib_Energy, 1);
-        glVertexAttribDivisorARB(attrib_Color, 1);
-        glVertexAttribDivisorARB(attrib_Radius, 1);
-    }   // PointLightShader
-};   // PointLightShader
-
-
-
-
-// ============================================================================
-class PointLightScatterShader : public TextureShader<PointLightScatterShader,
-                                                     1, float, core::vector3df>
-{
-public:
-    GLuint vbo;
-    GLuint vao;
-    PointLightScatterShader()
-    {
-        loadProgram(OBJECT, GL_VERTEX_SHADER, "pointlight.vert",
-                            GL_FRAGMENT_SHADER, "pointlightscatter.frag");
-
-        assignUniforms("density", "fogcol");
-        assignSamplerNames(0, "dtex", ST_NEAREST_FILTERED);
-
-        glGenVertexArrays(1, &vao);
-        glBindVertexArray(vao);
-
-        glBindBuffer(GL_ARRAY_BUFFER, PointLightShader::getInstance()->vbo);
-
-        GLuint attrib_Position = glGetAttribLocation(m_program, "Position");
-        GLuint attrib_Color = glGetAttribLocation(m_program, "Color");
-        GLuint attrib_Energy = glGetAttribLocation(m_program, "Energy");
-        GLuint attrib_Radius = glGetAttribLocation(m_program, "Radius");
-
-        glEnableVertexAttribArray(attrib_Position);
-        glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE,
-                              sizeof(LightBaseClass::PointLightInfo), 0);
-        glEnableVertexAttribArray(attrib_Energy);
-        glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE,
-                              sizeof(LightBaseClass::PointLightInfo),
-                              (GLvoid*)(3 * sizeof(float)));
-        glEnableVertexAttribArray(attrib_Color);
-        glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE,
-                              sizeof(LightBaseClass::PointLightInfo),
-                              (GLvoid*)(4 * sizeof(float)));
-        glEnableVertexAttribArray(attrib_Radius);
-        glVertexAttribPointer(attrib_Radius, 1, GL_FLOAT, GL_FALSE,
-                              sizeof(LightBaseClass::PointLightInfo),
-                              (GLvoid*)(7 * sizeof(float)));
-
-        glVertexAttribDivisorARB(attrib_Position, 1);
-        glVertexAttribDivisorARB(attrib_Energy, 1);
-        glVertexAttribDivisorARB(attrib_Color, 1);
-        glVertexAttribDivisorARB(attrib_Radius, 1);
-    }   // PointLightScatterShader
-};
-
-#if !defined(USE_GLES2)
-// ============================================================================
-class RadianceHintsConstructionShader
-    : public TextureShader<RadianceHintsConstructionShader, 3, core::matrix4,
-                          core::matrix4, core::vector3df, video::SColorf>
-{
-public:
-    RadianceHintsConstructionShader()
-    {
-        if (CVS->isAMDVertexShaderLayerUsable())
-        {
-            loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert",
-                                GL_FRAGMENT_SHADER, "rh.frag");
-        }
-        else
-        {
-            loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert",
-                                GL_GEOMETRY_SHADER, "rhpassthrough.geom",
-                                GL_FRAGMENT_SHADER, "rh.frag");
-        }
-
-        assignUniforms("RSMMatrix", "RHMatrix", "extents", "suncol");
-        assignSamplerNames(0, "ctex", ST_BILINEAR_FILTERED,
-                           1, "ntex", ST_BILINEAR_FILTERED,
-                           2, "dtex", ST_BILINEAR_FILTERED);
-    }   // RadianceHintsConstructionShader
-};   // RadianceHintsConstructionShader
-
-// ============================================================================
-// Workaround for a bug found in kepler nvidia linux and fermi nvidia windows
-class NVWorkaroundRadianceHintsConstructionShader
-    : public TextureShader<NVWorkaroundRadianceHintsConstructionShader,
-                           3, core::matrix4, core::matrix4, core::vector3df,
-                           int, video::SColorf >
-{
-public:
-    NVWorkaroundRadianceHintsConstructionShader()
-    {
-        loadProgram(OBJECT,GL_VERTEX_SHADER,"slicedscreenquad_nvworkaround.vert",
-                           GL_GEOMETRY_SHADER, "rhpassthrough.geom",
-                           GL_FRAGMENT_SHADER, "rh.frag");
-
-        assignUniforms("RSMMatrix", "RHMatrix", "extents", "slice", "suncol");
-
-        assignSamplerNames(0, "ctex", ST_BILINEAR_FILTERED,
-                           1, "ntex", ST_BILINEAR_FILTERED,
-                           2, "dtex", ST_BILINEAR_FILTERED);
-    }   // NVWorkaroundRadianceHintsConstructionShader
-};   // NVWorkaroundRadianceHintsConstructionShader
-#endif // !defined(USE_GLES2)
-
-// ============================================================================
-class GlobalIlluminationReconstructionShader
-    : public TextureShader<GlobalIlluminationReconstructionShader, 5,
-                           core::matrix4, core::matrix4, core::vector3df >
-{
-public:
-    GlobalIlluminationReconstructionShader()
-    {
-        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
-                            GL_FRAGMENT_SHADER, "gi.frag");
-
-        assignUniforms("rh_matrix", "inv_rh_matrix", "extents");
-        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED,
-                           1, "dtex", ST_NEAREST_FILTERED,
-                           2, "SHR", ST_VOLUME_LINEAR_FILTERED,
-                           3, "SHG", ST_VOLUME_LINEAR_FILTERED,
-                           4, "SHB", ST_VOLUME_LINEAR_FILTERED);
-    }   // GlobalIlluminationReconstructionShader
-
-    // ------------------------------------------------------------------------
-    void render(const core::matrix4 &rh_matrix,
-                const core::vector3df &rh_extend, const FrameBuffer &fb,
-                GLuint normal_depth_texture,
-                GLuint depth_stencil_texture)
-    {
-        core::matrix4 inv_rh_matrix;
-        rh_matrix.getInverse(inv_rh_matrix);
-        glDisable(GL_DEPTH_TEST);
-        setTextureUnits(normal_depth_texture,
-                        depth_stencil_texture,
-                        fb.getRTT()[0], fb.getRTT()[1], fb.getRTT()[2]);
-        drawFullScreenEffect(rh_matrix, inv_rh_matrix, rh_extend);
-    }   // render
-};   // GlobalIlluminationReconstructionShader
-
-// ============================================================================
-class IBLShader : public TextureShader<IBLShader, 3>
-{
-public:
-    IBLShader()
-    {
-        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
-                            GL_FRAGMENT_SHADER, "IBL.frag");
-        assignUniforms();
-        assignSamplerNames(0, "ntex",  ST_NEAREST_FILTERED,
-                           1, "dtex",  ST_NEAREST_FILTERED,
-                           2, "probe", ST_TRILINEAR_CUBEMAP);
-    }   // IBLShader
-};   // IBLShader
-
-// ============================================================================
-class DegradedIBLShader : public TextureShader<DegradedIBLShader, 1>
-{
-public:
-    DegradedIBLShader()
-    {
-        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
-                            GL_FRAGMENT_SHADER, "degraded_ibl.frag");
-        assignUniforms();
-        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED);
-    }   // DegradedIBLShader
-};   // DegradedIBLShader
-
-// ============================================================================
-class ShadowedSunLightShaderPCF : public TextureShader<ShadowedSunLightShaderPCF,
-                                                       3,  float, float, float,
-                                                       float, float>
-{
-public:
-    ShadowedSunLightShaderPCF()
-    {
-        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
-                            GL_FRAGMENT_SHADER, "sunlightshadow.frag");
-
-        // Use 8 to circumvent a catalyst bug when binding sampler
-        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED,
-                           1, "dtex", ST_NEAREST_FILTERED,
-                           8, "shadowtex", ST_SHADOW_SAMPLER);
-        assignUniforms("split0", "split1", "split2", "splitmax", "shadow_res");
-    }   // ShadowedSunLightShaderPCF
-    // ------------------------------------------------------------------------
-    void render(GLuint normal_depth_texture,
-                GLuint depth_stencil_texture,
-                const FrameBuffer& shadow_framebuffer)
-    {
-        setTextureUnits(normal_depth_texture,
-                        depth_stencil_texture,
-                        shadow_framebuffer.getDepthTexture()                );
-       drawFullScreenEffect(ShadowMatrices::m_shadow_split[1],
-                            ShadowMatrices::m_shadow_split[2],
-                            ShadowMatrices::m_shadow_split[3],
-                            ShadowMatrices::m_shadow_split[4],
-                            float(UserConfigParams::m_shadows_resolution)   );
-
-    }    // render
-};   // ShadowedSunLightShaderPCF
-
-// ============================================================================
-class ShadowedSunLightShaderESM : public TextureShader<ShadowedSunLightShaderESM,
-                                                       3, float, float, float,
-                                                       float>
-{
-public:
-    ShadowedSunLightShaderESM()
-    {
-        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
-                            GL_FRAGMENT_SHADER, "sunlightshadowesm.frag");
-
-        // Use 8 to circumvent a catalyst bug when binding sampler
-        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED,
-                           1, "dtex", ST_NEAREST_FILTERED,
-                           8, "shadowtex", ST_TRILINEAR_CLAMPED_ARRAY2D);
-
-        assignUniforms("split0", "split1", "split2", "splitmax");
-    }   // ShadowedSunLightShaderESM
-    // ------------------------------------------------------------------------
-    void render(GLuint normal_depth_texture,
-                GLuint depth_stencil_texture,
-                const FrameBuffer& shadow_framebuffer)
-    {
-        setTextureUnits(normal_depth_texture,
-                        depth_stencil_texture,
-                        shadow_framebuffer.getRTT()[0]);
-        drawFullScreenEffect(ShadowMatrices::m_shadow_split[1],
-                             ShadowMatrices::m_shadow_split[2],
-                             ShadowMatrices::m_shadow_split[3],
-                             ShadowMatrices::m_shadow_split[4]);
-    }   // render
-};   // ShadowedSunLightShaderESM
-
-
-// ============================================================================
-class SunLightShader : public TextureShader<SunLightShader, 2,
-                                            core::vector3df, video::SColorf>
-{
-public:
-    SunLightShader()
-    {
-        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
-                            GL_FRAGMENT_SHADER, "sunlight.frag");
-
-        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED,
-                           1, "dtex", ST_NEAREST_FILTERED);
-        assignUniforms("direction", "col");
-    }   // SunLightShader
-    // ------------------------------------------------------------------------
-    void render(const core::vector3df &direction, const video::SColorf &col,
-                GLuint normal_depth_texture,
-                GLuint depth_stencil_texture)
-    {
-        glEnable(GL_BLEND);
-        glDisable(GL_DEPTH_TEST);
-        glBlendFunc(GL_ONE, GL_ONE);
-        glBlendEquation(GL_FUNC_ADD);
-
-        setTextureUnits(normal_depth_texture, depth_stencil_texture);
-        drawFullScreenEffect(direction, col);
-    }   // render
-};   // SunLightShader
-
-// ============================================================================
-static void renderPointLights(unsigned count,
-                              GLuint normal_depth_rander_target,
-                              GLuint depth_stencil_texture)
-{
-    glEnable(GL_BLEND);
-    glBlendEquation(GL_FUNC_ADD);
-    glBlendFunc(GL_ONE, GL_ONE);
-    glEnable(GL_DEPTH_TEST);
-    glDepthMask(GL_FALSE);
-
-    PointLightShader::getInstance()->use();
-    glBindVertexArray(PointLightShader::getInstance()->vao);
-    glBindBuffer(GL_ARRAY_BUFFER, PointLightShader::getInstance()->vbo);
-    glBufferSubData(GL_ARRAY_BUFFER, 0,
-                     count * sizeof(LightBaseClass::PointLightInfo),
-                     m_point_lights_info);
-
-    PointLightShader::getInstance()->setTextureUnits(
-        normal_depth_rander_target,
-        depth_stencil_texture);
-    PointLightShader::getInstance()->setUniforms();
-
-    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
-}   // renderPointLights
-
-// ----------------------------------------------------------------------------
-void LightingPasses::renderEnvMap(GLuint normal_depth_texture,
-                                  GLuint depth_stencil_texture,
-                                  GLuint specular_probe)
-{
-    glDisable(GL_DEPTH_TEST);
-    glEnable(GL_BLEND);
-    glBlendEquation(GL_FUNC_ADD);
-    glBlendFunc(GL_ONE, GL_ONE);
-
-    if (UserConfigParams::m_degraded_IBL)
-    {
-        DegradedIBLShader::getInstance()->use();
-        glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO());
-
-        DegradedIBLShader::getInstance()
-            ->setTextureUnits(normal_depth_texture);
-        DegradedIBLShader::getInstance()->setUniforms();
-    }
-    else
-    {
-        IBLShader::getInstance()->use();
-        glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO());
-
-        IBLShader::getInstance()->setTextureUnits(
-            normal_depth_texture,
-            depth_stencil_texture,
-            specular_probe);
-        IBLShader::getInstance()->setUniforms();
-    }
-
-    glDrawArrays(GL_TRIANGLES, 0, 3);
-    glBindVertexArray(0);
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    glEnable(GL_DEPTH_TEST);
-    glDisable(GL_BLEND);
-}   // renderEnvMap
-
-// ----------------------------------------------------------------------------
-void LightingPasses::renderSunlight(const core::vector3df &direction,
-                                    const video::SColorf &col,
-                                    GLuint normal_depth_texture,
-                                    GLuint depth_stencil_texture)
-{
-    SunLightShader::getInstance()->render(direction, col,
-                                          normal_depth_texture,
-                                          depth_stencil_texture);
-}   // renderSunlight
-
-
-// ----------------------------------------------------------------------------
-void LightingPasses::updateLightsInfo(scene::ICameraSceneNode * const camnode,
-                                      float dt)
-{
-    std::vector<LightNode *> lights = irr_driver->getLights();
-    const u32 lightcount = (u32)lights.size();
-    const core::vector3df &campos = camnode->getAbsolutePosition();
-
-    std::vector<LightNode *> BucketedLN[15];
-    for (unsigned int i = 0; i < lightcount; i++)
-    {
-        if (!lights[i]->isVisible())
-            continue;
-
-        if (!lights[i]->isPointLight())
-        {
-            lights[i]->render();
-            continue;
-        }
-        const core::vector3df &lightpos =
-                                 (lights[i]->getAbsolutePosition() - campos);
-        unsigned idx = (unsigned)(lightpos.getLength() / 10);
-        if (idx > 14)
-            idx = 14;
-        BucketedLN[idx].push_back(lights[i]);
-    }
-
-    m_point_light_count = 0;
-    bool multiplayer = (race_manager->getNumLocalPlayers() > 1);
-
-    for (unsigned i = 0; i < 15; i++)
-    {
-        for (unsigned j = 0; j < BucketedLN[i].size(); j++)
-        {
-            if (++m_point_light_count >= LightBaseClass::MAXLIGHT)
-            {
-                LightNode* light_node = BucketedLN[i].at(j);
-                light_node->setEnergyMultiplier(0.0f);
-            }
-            else
-            {
-                LightNode* light_node = BucketedLN[i].at(j);
-
-                float em = light_node->getEnergyMultiplier();
-                if (em < 1.0f)
-                {
-                    // In single-player, fade-in lights.
-                    // In multi-player, can't do that, the light objects are shared by all players
-                    if (multiplayer)
-                        light_node->setEnergyMultiplier(1.0f);
-                    else
-                        light_node->setEnergyMultiplier(std::min(1.0f, em + dt));
-                }
-
-                const core::vector3df &pos = light_node->getAbsolutePosition();
-                m_point_lights_info[m_point_light_count].posX = pos.X;
-                m_point_lights_info[m_point_light_count].posY = pos.Y;
-                m_point_lights_info[m_point_light_count].posZ = pos.Z;
-
-                m_point_lights_info[m_point_light_count].energy =
-                                              light_node->getEffectiveEnergy();
-
-                const core::vector3df &col = light_node->getColor();
-                m_point_lights_info[m_point_light_count].red = col.X;
-                m_point_lights_info[m_point_light_count].green = col.Y;
-                m_point_lights_info[m_point_light_count].blue = col.Z;
-
-                // Light radius
-                m_point_lights_info[m_point_light_count].radius = light_node->getRadius();
-            }
-        }
-        if (m_point_light_count > LightBaseClass::MAXLIGHT)
-        {
-            irr_driver->setLastLightBucketDistance(i * 10);
-            break;
-        }
-    }
-
-    m_point_light_count++;
-}   // updateLightsInfo
-
-// ----------------------------------------------------------------------------
-void LightingPasses::renderGlobalIllumination(  const ShadowMatrices& shadow_matrices,
-                                                const FrameBuffer& radiance_hint_framebuffer,
-                                                const FrameBuffer& reflective_shadow_map_framebuffer,
-                                                const FrameBuffer& diffuse_framebuffer,
-                                                GLuint normal_depth_texture,
-                                                GLuint depth_stencil_texture)
-{
-    //Radiance hints
-#if !defined(USE_GLES2)
-    ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_RH));
-    glDisable(GL_BLEND);
-    radiance_hint_framebuffer.bind();
-    glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO());
-    if (CVS->needRHWorkaround())
-    {
-        NVWorkaroundRadianceHintsConstructionShader::getInstance()->use();
-        NVWorkaroundRadianceHintsConstructionShader::getInstance()
-            ->setTextureUnits(
-                reflective_shadow_map_framebuffer.getRTT()[0],
-                reflective_shadow_map_framebuffer.getRTT()[1],
-                reflective_shadow_map_framebuffer.getDepthTexture());
-        for (unsigned i = 0; i < 32; i++)
-        {
-            NVWorkaroundRadianceHintsConstructionShader::getInstance()
-                ->setUniforms(shadow_matrices.getRSMMatrix(),
-                              shadow_matrices.getRHMatrix(),
-                              shadow_matrices.getRHExtend(), i,
-                              irr_driver->getSunColor());
-            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-        }
-    }
-    else
-    {
-        RadianceHintsConstructionShader::getInstance()->use();
-        RadianceHintsConstructionShader::getInstance()
-            ->setTextureUnits(
-                reflective_shadow_map_framebuffer.getRTT()[0],
-                reflective_shadow_map_framebuffer.getRTT()[1],
-                reflective_shadow_map_framebuffer.getDepthTexture()
-        );
-        RadianceHintsConstructionShader::getInstance()
-            ->setUniforms(shadow_matrices.getRSMMatrix(),
-                          shadow_matrices.getRHMatrix(),
-                          shadow_matrices.getRHExtend(),
-                          irr_driver->getSunColor());
-        glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32);
-    }
-#endif //!defined(USE_GLES2)
-
-    //Global illumination
-    {
-        ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_GI));
-        diffuse_framebuffer.bind();
-        GlobalIlluminationReconstructionShader::getInstance()
-            ->render(shadow_matrices.getRHMatrix(),
-                     shadow_matrices.getRHExtend(),
-                     radiance_hint_framebuffer,
-                     normal_depth_texture,
-                     depth_stencil_texture);
-    }
-}
-
-// ----------------------------------------------------------------------------
-void LightingPasses::renderLights(  bool has_shadow,
-                                    GLuint normal_depth_texture,
-                                    GLuint depth_stencil_texture,
-                                    const FrameBuffer& shadow_framebuffer,
-                                    const FrameBuffer& diffuse_specular_framebuffer,
-                                    GLuint specular_probe)
-{    
-    diffuse_specular_framebuffer.bind();
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    {
-        ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP));
-        renderEnvMap(normal_depth_texture,
-                     depth_stencil_texture,
-                     specular_probe);       
-    } 
-        
-    // Render sunlight if and only if track supports shadow
-    if (!World::getWorld() || World::getWorld()->getTrack()->hasShadows())
-    {
-        ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_SUN));
-        if (World::getWorld() && CVS->isShadowEnabled() && has_shadow)
-        {
-            glEnable(GL_BLEND);
-            glDisable(GL_DEPTH_TEST);
-            glBlendFunc(GL_ONE, GL_ONE);
-            glBlendEquation(GL_FUNC_ADD);
-
-
-            if (CVS->isESMEnabled())
-            {
-                ShadowedSunLightShaderESM::getInstance()->render(normal_depth_texture,
-                                                                 depth_stencil_texture,
-                                                                 shadow_framebuffer);
-            }
-            else
-            {
-                ShadowedSunLightShaderPCF::getInstance()->render(normal_depth_texture,
-                                                                 depth_stencil_texture,
-                                                                 shadow_framebuffer);
-            }
-        }
-        else
-            renderSunlight(irr_driver->getSunDirection(),
-                           irr_driver->getSunColor(),
-                           normal_depth_texture,
-                           depth_stencil_texture);
-    }
-    
-    //points lights
-    {
-        ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_POINTLIGHTS));
-        renderPointLights(std::min(m_point_light_count, LightBaseClass::MAXLIGHT),
-                          normal_depth_texture,
-                          depth_stencil_texture);
-    }
-}   // renderLights    
-
-// ----------------------------------------------------------------------------
-void LightingPasses::renderAmbientScatter(GLuint depth_stencil_texture)
-{
-    const Track * const track = World::getWorld()->getTrack();
-
-    // This function is only called once per frame - thus no need for setters.
-    float start = track->getFogStart() + .001f;
-    const video::SColor tmpcol = track->getFogColor();
-
-    core::vector3df col(tmpcol.getRed() / 255.0f,
-        tmpcol.getGreen() / 255.0f,
-        tmpcol.getBlue() / 255.0f);
-
-    glDisable(GL_DEPTH_TEST);
-    glDepthMask(GL_FALSE);
-    glEnable(GL_BLEND);
-    glBlendEquation(GL_FUNC_ADD);
-    glBlendFunc(GL_ONE, GL_ONE);
-
-    FogShader::getInstance()->render(start, col, depth_stencil_texture);
-}   // renderAmbientScatter
-
-// ----------------------------------------------------------------------------
-void LightingPasses::renderLightsScatter(GLuint depth_stencil_texture,
-                                         const FrameBuffer& half1_framebuffer,
-                                         const FrameBuffer& half2_framebuffer,
-                                         const FrameBuffer& colors_framebuffer,
-                                         const PostProcessing* post_processing)
-{
-    half1_framebuffer.bind();
-    glClearColor(0., 0., 0., 0.);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    const Track * const track = World::getWorld()->getTrack();
-
-    // This function is only called once per frame - thus no need for setters.
-    float start = track->getFogStart() + .001f;
-    const video::SColor tmpcol = track->getFogColor();
-
-    core::vector3df col(tmpcol.getRed() / 255.0f,
-        tmpcol.getGreen() / 255.0f,
-        tmpcol.getBlue() / 255.0f);
-
-    glDepthMask(GL_FALSE);
-    glEnable(GL_BLEND);
-    glBlendEquation(GL_FUNC_ADD);
-    glBlendFunc(GL_ONE, GL_ONE);
-
-    glEnable(GL_DEPTH_TEST);
-    core::vector3df col2(1., 1., 1.);
-
-    PointLightScatterShader::getInstance()->use();
-    glBindVertexArray(PointLightScatterShader::getInstance()->vao);
-
-    PointLightScatterShader::getInstance()
-        ->setTextureUnits(depth_stencil_texture);
-    PointLightScatterShader::getInstance()
-        ->setUniforms(1.f / (40.f * start), col2);
-
-    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4,
-                          std::min(m_point_light_count,
-                          LightBaseClass::MAXLIGHT));
-
-    glDisable(GL_BLEND);
-    post_processing->renderGaussian6Blur(half1_framebuffer,
-                                         half2_framebuffer, 5., 5.);
-    glEnable(GL_BLEND);
-
-    glDisable(GL_DEPTH_TEST);
-    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-    colors_framebuffer.bind();
-    post_processing->renderPassThrough(half1_framebuffer.getRTT()[0],
-                                       colors_framebuffer.getWidth(),
-                                       colors_framebuffer.getHeight());
-}   // renderLightsScatter
-
+#include "graphics/glwrap.hpp"
+#include "graphics/irr_driver.hpp"
+#include "graphics/light.hpp"
+#include "graphics/post_processing.hpp"
+#include "graphics/rtts.hpp"
+#include "graphics/shaders.hpp"
+#include "graphics/shadow_matrices.hpp"
+#include "modes/world.hpp"
+#include "tracks/track.hpp"
+#include "utils/profiler.hpp"
+
+class LightBaseClass
+{
+public:
+    struct PointLightInfo
+    {
+        float posX;
+        float posY;
+        float posZ;
+        float energy;
+        float red;
+        float green;
+        float blue;
+        float radius;
+    };
+public:
+    static const unsigned int MAXLIGHT = 32;
+public:
+    static struct PointLightInfo m_point_lights_info[MAXLIGHT];
+};   // LightBaseClass
+
+const unsigned int LightBaseClass::MAXLIGHT;
+
+// ============================================================================
+LightBaseClass::PointLightInfo m_point_lights_info[LightBaseClass::MAXLIGHT];
+
+
+// ============================================================================
+class FogShader : public TextureShader<FogShader, 1, float, core::vector3df>
+{
+public:
+    FogShader()
+    {
+        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
+                            GL_FRAGMENT_SHADER, "fog.frag");
+        assignUniforms("density", "col");
+        assignSamplerNames(0, "tex", ST_NEAREST_FILTERED);
+    }   // FogShader
+    // ------------------------------------------------------------------------
+    void render(float start, const core::vector3df &color, GLuint depth_stencil_texture)
+    {
+        setTextureUnits(depth_stencil_texture);
+        drawFullScreenEffect(1.f / (40.f * start), color);
+
+    }   // render
+};   // FogShader
+
+// ============================================================================
+class PointLightShader : public TextureShader < PointLightShader, 2 >
+{
+public:
+    GLuint vbo;
+    GLuint vao;
+    PointLightShader()
+    {
+        loadProgram(OBJECT, GL_VERTEX_SHADER, "pointlight.vert",
+                            GL_FRAGMENT_SHADER, "pointlight.frag");
+
+        assignUniforms();
+        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED,
+                           1, "dtex", ST_NEAREST_FILTERED);
+        glGenVertexArrays(1, &vao);
+        glBindVertexArray(vao);
+
+        glGenBuffers(1, &vbo);
+        glBindBuffer(GL_ARRAY_BUFFER, vbo);
+        glBufferData(GL_ARRAY_BUFFER,
+                     LightBaseClass::MAXLIGHT * sizeof(LightBaseClass::PointLightInfo),
+                     0, GL_DYNAMIC_DRAW);
+
+        GLuint attrib_Position = glGetAttribLocation(m_program, "Position");
+        GLuint attrib_Color = glGetAttribLocation(m_program, "Color");
+        GLuint attrib_Energy = glGetAttribLocation(m_program, "Energy");
+        GLuint attrib_Radius = glGetAttribLocation(m_program, "Radius");
+
+        glEnableVertexAttribArray(attrib_Position);
+        glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE,
+                              sizeof(LightBaseClass::PointLightInfo), 0);
+        glEnableVertexAttribArray(attrib_Energy);
+        glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE,
+                              sizeof(LightBaseClass::PointLightInfo),
+                              (GLvoid*)(3 * sizeof(float)));
+        glEnableVertexAttribArray(attrib_Color);
+        glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE,
+                              sizeof(LightBaseClass::PointLightInfo),
+                              (GLvoid*)(4 * sizeof(float)));
+        glEnableVertexAttribArray(attrib_Radius);
+        glVertexAttribPointer(attrib_Radius, 1, GL_FLOAT, GL_FALSE,
+                              sizeof(LightBaseClass::PointLightInfo),
+                              (GLvoid*)(7 * sizeof(float)));
+
+        glVertexAttribDivisorARB(attrib_Position, 1);
+        glVertexAttribDivisorARB(attrib_Energy, 1);
+        glVertexAttribDivisorARB(attrib_Color, 1);
+        glVertexAttribDivisorARB(attrib_Radius, 1);
+    }   // PointLightShader
+};   // PointLightShader
+
+
+
+
+// ============================================================================
+class PointLightScatterShader : public TextureShader<PointLightScatterShader,
+                                                     1, float, core::vector3df>
+{
+public:
+    GLuint vbo;
+    GLuint vao;
+    PointLightScatterShader()
+    {
+        loadProgram(OBJECT, GL_VERTEX_SHADER, "pointlight.vert",
+                            GL_FRAGMENT_SHADER, "pointlightscatter.frag");
+
+        assignUniforms("density", "fogcol");
+        assignSamplerNames(0, "dtex", ST_NEAREST_FILTERED);
+
+        glGenVertexArrays(1, &vao);
+        glBindVertexArray(vao);
+
+        glBindBuffer(GL_ARRAY_BUFFER, PointLightShader::getInstance()->vbo);
+
+        GLuint attrib_Position = glGetAttribLocation(m_program, "Position");
+        GLuint attrib_Color = glGetAttribLocation(m_program, "Color");
+        GLuint attrib_Energy = glGetAttribLocation(m_program, "Energy");
+        GLuint attrib_Radius = glGetAttribLocation(m_program, "Radius");
+
+        glEnableVertexAttribArray(attrib_Position);
+        glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE,
+                              sizeof(LightBaseClass::PointLightInfo), 0);
+        glEnableVertexAttribArray(attrib_Energy);
+        glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE,
+                              sizeof(LightBaseClass::PointLightInfo),
+                              (GLvoid*)(3 * sizeof(float)));
+        glEnableVertexAttribArray(attrib_Color);
+        glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE,
+                              sizeof(LightBaseClass::PointLightInfo),
+                              (GLvoid*)(4 * sizeof(float)));
+        glEnableVertexAttribArray(attrib_Radius);
+        glVertexAttribPointer(attrib_Radius, 1, GL_FLOAT, GL_FALSE,
+                              sizeof(LightBaseClass::PointLightInfo),
+                              (GLvoid*)(7 * sizeof(float)));
+
+        glVertexAttribDivisorARB(attrib_Position, 1);
+        glVertexAttribDivisorARB(attrib_Energy, 1);
+        glVertexAttribDivisorARB(attrib_Color, 1);
+        glVertexAttribDivisorARB(attrib_Radius, 1);
+    }   // PointLightScatterShader
+};
+
+#if !defined(USE_GLES2)
+// ============================================================================
+class RadianceHintsConstructionShader
+    : public TextureShader<RadianceHintsConstructionShader, 3, core::matrix4,
+                          core::matrix4, core::vector3df, video::SColorf>
+{
+public:
+    RadianceHintsConstructionShader()
+    {
+        if (CVS->isAMDVertexShaderLayerUsable())
+        {
+            loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert",
+                                GL_FRAGMENT_SHADER, "rh.frag");
+        }
+        else
+        {
+            loadProgram(OBJECT, GL_VERTEX_SHADER, "slicedscreenquad.vert",
+                                GL_GEOMETRY_SHADER, "rhpassthrough.geom",
+                                GL_FRAGMENT_SHADER, "rh.frag");
+        }
+
+        assignUniforms("RSMMatrix", "RHMatrix", "extents", "suncol");
+        assignSamplerNames(0, "ctex", ST_BILINEAR_FILTERED,
+                           1, "ntex", ST_BILINEAR_FILTERED,
+                           2, "dtex", ST_BILINEAR_FILTERED);
+    }   // RadianceHintsConstructionShader
+};   // RadianceHintsConstructionShader
+
+// ============================================================================
+// Workaround for a bug found in kepler nvidia linux and fermi nvidia windows
+class NVWorkaroundRadianceHintsConstructionShader
+    : public TextureShader<NVWorkaroundRadianceHintsConstructionShader,
+                           3, core::matrix4, core::matrix4, core::vector3df,
+                           int, video::SColorf >
+{
+public:
+    NVWorkaroundRadianceHintsConstructionShader()
+    {
+        loadProgram(OBJECT,GL_VERTEX_SHADER,"slicedscreenquad_nvworkaround.vert",
+                           GL_GEOMETRY_SHADER, "rhpassthrough.geom",
+                           GL_FRAGMENT_SHADER, "rh.frag");
+
+        assignUniforms("RSMMatrix", "RHMatrix", "extents", "slice", "suncol");
+
+        assignSamplerNames(0, "ctex", ST_BILINEAR_FILTERED,
+                           1, "ntex", ST_BILINEAR_FILTERED,
+                           2, "dtex", ST_BILINEAR_FILTERED);
+    }   // NVWorkaroundRadianceHintsConstructionShader
+};   // NVWorkaroundRadianceHintsConstructionShader
+#endif // !defined(USE_GLES2)
+
+// ============================================================================
+class GlobalIlluminationReconstructionShader
+    : public TextureShader<GlobalIlluminationReconstructionShader, 5,
+                           core::matrix4, core::matrix4, core::vector3df >
+{
+public:
+    GlobalIlluminationReconstructionShader()
+    {
+        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
+                            GL_FRAGMENT_SHADER, "gi.frag");
+
+        assignUniforms("rh_matrix", "inv_rh_matrix", "extents");
+        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED,
+                           1, "dtex", ST_NEAREST_FILTERED,
+                           2, "SHR", ST_VOLUME_LINEAR_FILTERED,
+                           3, "SHG", ST_VOLUME_LINEAR_FILTERED,
+                           4, "SHB", ST_VOLUME_LINEAR_FILTERED);
+    }   // GlobalIlluminationReconstructionShader
+
+    // ------------------------------------------------------------------------
+    void render(const core::matrix4 &rh_matrix,
+                const core::vector3df &rh_extend, const FrameBuffer &fb,
+                GLuint normal_depth_texture,
+                GLuint depth_stencil_texture)
+    {
+        core::matrix4 inv_rh_matrix;
+        rh_matrix.getInverse(inv_rh_matrix);
+        glDisable(GL_DEPTH_TEST);
+        setTextureUnits(normal_depth_texture,
+                        depth_stencil_texture,
+                        fb.getRTT()[0], fb.getRTT()[1], fb.getRTT()[2]);
+        drawFullScreenEffect(rh_matrix, inv_rh_matrix, rh_extend);
+    }   // render
+};   // GlobalIlluminationReconstructionShader
+
+// ============================================================================
+class IBLShader : public TextureShader<IBLShader, 3>
+{
+public:
+    IBLShader()
+    {
+        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
+                            GL_FRAGMENT_SHADER, "IBL.frag");
+        assignUniforms();
+        assignSamplerNames(0, "ntex",  ST_NEAREST_FILTERED,
+                           1, "dtex",  ST_NEAREST_FILTERED,
+                           2, "probe", ST_TRILINEAR_CUBEMAP);
+    }   // IBLShader
+};   // IBLShader
+
+// ============================================================================
+class DegradedIBLShader : public TextureShader<DegradedIBLShader, 1>
+{
+public:
+    DegradedIBLShader()
+    {
+        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
+                            GL_FRAGMENT_SHADER, "degraded_ibl.frag");
+        assignUniforms();
+        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED);
+    }   // DegradedIBLShader
+};   // DegradedIBLShader
+
+// ============================================================================
+class ShadowedSunLightShaderPCF : public TextureShader<ShadowedSunLightShaderPCF,
+                                                       3,  float, float, float,
+                                                       float, float>
+{
+public:
+    ShadowedSunLightShaderPCF()
+    {
+        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
+                            GL_FRAGMENT_SHADER, "sunlightshadow.frag");
+
+        // Use 8 to circumvent a catalyst bug when binding sampler
+        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED,
+                           1, "dtex", ST_NEAREST_FILTERED,
+                           8, "shadowtex", ST_SHADOW_SAMPLER);
+        assignUniforms("split0", "split1", "split2", "splitmax", "shadow_res");
+    }   // ShadowedSunLightShaderPCF
+    // ------------------------------------------------------------------------
+    void render(GLuint normal_depth_texture,
+                GLuint depth_stencil_texture,
+                const FrameBuffer& shadow_framebuffer)
+    {
+        setTextureUnits(normal_depth_texture,
+                        depth_stencil_texture,
+                        shadow_framebuffer.getDepthTexture()                );
+       drawFullScreenEffect(ShadowMatrices::m_shadow_split[1],
+                            ShadowMatrices::m_shadow_split[2],
+                            ShadowMatrices::m_shadow_split[3],
+                            ShadowMatrices::m_shadow_split[4],
+                            float(UserConfigParams::m_shadows_resolution)   );
+
+    }    // render
+};   // ShadowedSunLightShaderPCF
+
+// ============================================================================
+class ShadowedSunLightShaderESM : public TextureShader<ShadowedSunLightShaderESM,
+                                                       3, float, float, float,
+                                                       float>
+{
+public:
+    ShadowedSunLightShaderESM()
+    {
+        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
+                            GL_FRAGMENT_SHADER, "sunlightshadowesm.frag");
+
+        // Use 8 to circumvent a catalyst bug when binding sampler
+        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED,
+                           1, "dtex", ST_NEAREST_FILTERED,
+                           8, "shadowtex", ST_TRILINEAR_CLAMPED_ARRAY2D);
+
+        assignUniforms("split0", "split1", "split2", "splitmax");
+    }   // ShadowedSunLightShaderESM
+    // ------------------------------------------------------------------------
+    void render(GLuint normal_depth_texture,
+                GLuint depth_stencil_texture,
+                const FrameBuffer& shadow_framebuffer)
+    {
+        setTextureUnits(normal_depth_texture,
+                        depth_stencil_texture,
+                        shadow_framebuffer.getRTT()[0]);
+        drawFullScreenEffect(ShadowMatrices::m_shadow_split[1],
+                             ShadowMatrices::m_shadow_split[2],
+                             ShadowMatrices::m_shadow_split[3],
+                             ShadowMatrices::m_shadow_split[4]);
+    }   // render
+};   // ShadowedSunLightShaderESM
+
+
+// ============================================================================
+class SunLightShader : public TextureShader<SunLightShader, 2,
+                                            core::vector3df, video::SColorf>
+{
+public:
+    SunLightShader()
+    {
+        loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
+                            GL_FRAGMENT_SHADER, "sunlight.frag");
+
+        assignSamplerNames(0, "ntex", ST_NEAREST_FILTERED,
+                           1, "dtex", ST_NEAREST_FILTERED);
+        assignUniforms("direction", "col");
+    }   // SunLightShader
+    // ------------------------------------------------------------------------
+    void render(const core::vector3df &direction, const video::SColorf &col,
+                GLuint normal_depth_texture,
+                GLuint depth_stencil_texture)
+    {
+        glEnable(GL_BLEND);
+        glDisable(GL_DEPTH_TEST);
+        glBlendFunc(GL_ONE, GL_ONE);
+        glBlendEquation(GL_FUNC_ADD);
+
+        setTextureUnits(normal_depth_texture, depth_stencil_texture);
+        drawFullScreenEffect(direction, col);
+    }   // render
+};   // SunLightShader
+
+// ============================================================================
+static void renderPointLights(unsigned count,
+                              GLuint normal_depth_rander_target,
+                              GLuint depth_stencil_texture)
+{
+    glEnable(GL_BLEND);
+    glBlendEquation(GL_FUNC_ADD);
+    glBlendFunc(GL_ONE, GL_ONE);
+    glEnable(GL_DEPTH_TEST);
+    glDepthMask(GL_FALSE);
+
+    PointLightShader::getInstance()->use();
+    glBindVertexArray(PointLightShader::getInstance()->vao);
+    glBindBuffer(GL_ARRAY_BUFFER, PointLightShader::getInstance()->vbo);
+    glBufferSubData(GL_ARRAY_BUFFER, 0,
+                     count * sizeof(LightBaseClass::PointLightInfo),
+                     m_point_lights_info);
+
+    PointLightShader::getInstance()->setTextureUnits(
+        normal_depth_rander_target,
+        depth_stencil_texture);
+    PointLightShader::getInstance()->setUniforms();
+
+    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
+}   // renderPointLights
+
+// ----------------------------------------------------------------------------
+void LightingPasses::renderEnvMap(GLuint normal_depth_texture,
+                                  GLuint depth_stencil_texture,
+                                  GLuint specular_probe)
+{
+    glDisable(GL_DEPTH_TEST);
+    glEnable(GL_BLEND);
+    glBlendEquation(GL_FUNC_ADD);
+    glBlendFunc(GL_ONE, GL_ONE);
+
+    if (UserConfigParams::m_degraded_IBL)
+    {
+        DegradedIBLShader::getInstance()->use();
+        glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO());
+
+        DegradedIBLShader::getInstance()
+            ->setTextureUnits(normal_depth_texture);
+        DegradedIBLShader::getInstance()->setUniforms();
+    }
+    else
+    {
+        IBLShader::getInstance()->use();
+        glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO());
+
+        IBLShader::getInstance()->setTextureUnits(
+            normal_depth_texture,
+            depth_stencil_texture,
+            specular_probe);
+        IBLShader::getInstance()->setUniforms();
+    }
+
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+    glBindVertexArray(0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    glEnable(GL_DEPTH_TEST);
+    glDisable(GL_BLEND);
+}   // renderEnvMap
+
+// ----------------------------------------------------------------------------
+void LightingPasses::renderSunlight(const core::vector3df &direction,
+                                    const video::SColorf &col,
+                                    GLuint normal_depth_texture,
+                                    GLuint depth_stencil_texture)
+{
+    SunLightShader::getInstance()->render(direction, col,
+                                          normal_depth_texture,
+                                          depth_stencil_texture);
+}   // renderSunlight
+
+
+// ----------------------------------------------------------------------------
+void LightingPasses::updateLightsInfo(scene::ICameraSceneNode * const camnode,
+                                      float dt)
+{
+    std::vector<LightNode *> lights = irr_driver->getLights();
+    const u32 lightcount = (u32)lights.size();
+    const core::vector3df &campos = camnode->getAbsolutePosition();
+
+    std::vector<LightNode *> BucketedLN[15];
+    for (unsigned int i = 0; i < lightcount; i++)
+    {
+        if (!lights[i]->isVisible())
+            continue;
+
+        if (!lights[i]->isPointLight())
+        {
+            lights[i]->render();
+            continue;
+        }
+        const core::vector3df &lightpos =
+                                 (lights[i]->getAbsolutePosition() - campos);
+        unsigned idx = (unsigned)(lightpos.getLength() / 10);
+        if (idx > 14)
+            idx = 14;
+        BucketedLN[idx].push_back(lights[i]);
+    }
+
+    m_point_light_count = 0;
+    bool multiplayer = (race_manager->getNumLocalPlayers() > 1);
+
+    for (unsigned i = 0; i < 15; i++)
+    {
+        for (unsigned j = 0; j < BucketedLN[i].size(); j++)
+        {
+            if (++m_point_light_count >= LightBaseClass::MAXLIGHT)
+            {
+                LightNode* light_node = BucketedLN[i].at(j);
+                light_node->setEnergyMultiplier(0.0f);
+            }
+            else
+            {
+                LightNode* light_node = BucketedLN[i].at(j);
+
+                float em = light_node->getEnergyMultiplier();
+                if (em < 1.0f)
+                {
+                    // In single-player, fade-in lights.
+                    // In multi-player, can't do that, the light objects are shared by all players
+                    if (multiplayer)
+                        light_node->setEnergyMultiplier(1.0f);
+                    else
+                        light_node->setEnergyMultiplier(std::min(1.0f, em + dt));
+                }
+
+                const core::vector3df &pos = light_node->getAbsolutePosition();
+                m_point_lights_info[m_point_light_count].posX = pos.X;
+                m_point_lights_info[m_point_light_count].posY = pos.Y;
+                m_point_lights_info[m_point_light_count].posZ = pos.Z;
+
+                m_point_lights_info[m_point_light_count].energy =
+                                              light_node->getEffectiveEnergy();
+
+                const core::vector3df &col = light_node->getColor();
+                m_point_lights_info[m_point_light_count].red = col.X;
+                m_point_lights_info[m_point_light_count].green = col.Y;
+                m_point_lights_info[m_point_light_count].blue = col.Z;
+
+                // Light radius
+                m_point_lights_info[m_point_light_count].radius = light_node->getRadius();
+            }
+        }
+        if (m_point_light_count > LightBaseClass::MAXLIGHT)
+        {
+            irr_driver->setLastLightBucketDistance(i * 10);
+            break;
+        }
+    }
+
+    m_point_light_count++;
+}   // updateLightsInfo
+
+// ----------------------------------------------------------------------------
+void LightingPasses::renderGlobalIllumination(  const ShadowMatrices& shadow_matrices,
+                                                const FrameBuffer& radiance_hint_framebuffer,
+                                                const FrameBuffer& reflective_shadow_map_framebuffer,
+                                                const FrameBuffer& diffuse_framebuffer,
+                                                GLuint normal_depth_texture,
+                                                GLuint depth_stencil_texture)
+{
+    //Radiance hints
+#if !defined(USE_GLES2)
+    ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_RH));
+    glDisable(GL_BLEND);
+    radiance_hint_framebuffer.bind();
+    glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO());
+    if (CVS->needRHWorkaround())
+    {
+        NVWorkaroundRadianceHintsConstructionShader::getInstance()->use();
+        NVWorkaroundRadianceHintsConstructionShader::getInstance()
+            ->setTextureUnits(
+                reflective_shadow_map_framebuffer.getRTT()[0],
+                reflective_shadow_map_framebuffer.getRTT()[1],
+                reflective_shadow_map_framebuffer.getDepthTexture());
+        for (unsigned i = 0; i < 32; i++)
+        {
+            NVWorkaroundRadianceHintsConstructionShader::getInstance()
+                ->setUniforms(shadow_matrices.getRSMMatrix(),
+                              shadow_matrices.getRHMatrix(),
+                              shadow_matrices.getRHExtend(), i,
+                              irr_driver->getSunColor());
+            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+        }
+    }
+    else
+    {
+        RadianceHintsConstructionShader::getInstance()->use();
+        RadianceHintsConstructionShader::getInstance()
+            ->setTextureUnits(
+                reflective_shadow_map_framebuffer.getRTT()[0],
+                reflective_shadow_map_framebuffer.getRTT()[1],
+                reflective_shadow_map_framebuffer.getDepthTexture()
+        );
+        RadianceHintsConstructionShader::getInstance()
+            ->setUniforms(shadow_matrices.getRSMMatrix(),
+                          shadow_matrices.getRHMatrix(),
+                          shadow_matrices.getRHExtend(),
+                          irr_driver->getSunColor());
+        glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32);
+    }
+#endif //!defined(USE_GLES2)
+
+    //Global illumination
+    {
+        ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_GI));
+        diffuse_framebuffer.bind();
+        GlobalIlluminationReconstructionShader::getInstance()
+            ->render(shadow_matrices.getRHMatrix(),
+                     shadow_matrices.getRHExtend(),
+                     radiance_hint_framebuffer,
+                     normal_depth_texture,
+                     depth_stencil_texture);
+    }
+}
+
+// ----------------------------------------------------------------------------
+void LightingPasses::renderLights(  bool has_shadow,
+                                    GLuint normal_depth_texture,
+                                    GLuint depth_stencil_texture,
+                                    const FrameBuffer& shadow_framebuffer,
+                                    const FrameBuffer& diffuse_specular_framebuffer,
+                                    GLuint specular_probe)
+{    
+    diffuse_specular_framebuffer.bind();
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    {
+        ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP));
+        renderEnvMap(normal_depth_texture,
+                     depth_stencil_texture,
+                     specular_probe);       
+    } 
+        
+    // Render sunlight if and only if track supports shadow
+    if (!World::getWorld() || World::getWorld()->getTrack()->hasShadows())
+    {
+        ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_SUN));
+        if (World::getWorld() && CVS->isShadowEnabled() && has_shadow)
+        {
+            glEnable(GL_BLEND);
+            glDisable(GL_DEPTH_TEST);
+            glBlendFunc(GL_ONE, GL_ONE);
+            glBlendEquation(GL_FUNC_ADD);
+
+
+            if (CVS->isESMEnabled())
+            {
+                ShadowedSunLightShaderESM::getInstance()->render(normal_depth_texture,
+                                                                 depth_stencil_texture,
+                                                                 shadow_framebuffer);
+            }
+            else
+            {
+                ShadowedSunLightShaderPCF::getInstance()->render(normal_depth_texture,
+                                                                 depth_stencil_texture,
+                                                                 shadow_framebuffer);
+            }
+        }
+        else
+            renderSunlight(irr_driver->getSunDirection(),
+                           irr_driver->getSunColor(),
+                           normal_depth_texture,
+                           depth_stencil_texture);
+    }
+    
+    //points lights
+    {
+        ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_POINTLIGHTS));
+        renderPointLights(std::min(m_point_light_count, LightBaseClass::MAXLIGHT),
+                          normal_depth_texture,
+                          depth_stencil_texture);
+    }
+}   // renderLights    
+
+// ----------------------------------------------------------------------------
+void LightingPasses::renderAmbientScatter(GLuint depth_stencil_texture)
+{
+    const Track * const track = World::getWorld()->getTrack();
+
+    // This function is only called once per frame - thus no need for setters.
+    float start = track->getFogStart() + .001f;
+    const video::SColor tmpcol = track->getFogColor();
+
+    core::vector3df col(tmpcol.getRed() / 255.0f,
+        tmpcol.getGreen() / 255.0f,
+        tmpcol.getBlue() / 255.0f);
+
+    glDisable(GL_DEPTH_TEST);
+    glDepthMask(GL_FALSE);
+    glEnable(GL_BLEND);
+    glBlendEquation(GL_FUNC_ADD);
+    glBlendFunc(GL_ONE, GL_ONE);
+
+    FogShader::getInstance()->render(start, col, depth_stencil_texture);
+}   // renderAmbientScatter
+
+// ----------------------------------------------------------------------------
+void LightingPasses::renderLightsScatter(GLuint depth_stencil_texture,
+                                         const FrameBuffer& half1_framebuffer,
+                                         const FrameBuffer& half2_framebuffer,
+                                         const FrameBuffer& colors_framebuffer,
+                                         const PostProcessing* post_processing)
+{
+    half1_framebuffer.bind();
+    glClearColor(0., 0., 0., 0.);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    const Track * const track = World::getWorld()->getTrack();
+
+    // This function is only called once per frame - thus no need for setters.
+    float start = track->getFogStart() + .001f;
+    const video::SColor tmpcol = track->getFogColor();
+
+    core::vector3df col(tmpcol.getRed() / 255.0f,
+        tmpcol.getGreen() / 255.0f,
+        tmpcol.getBlue() / 255.0f);
+
+    glDepthMask(GL_FALSE);
+    glEnable(GL_BLEND);
+    glBlendEquation(GL_FUNC_ADD);
+    glBlendFunc(GL_ONE, GL_ONE);
+
+    glEnable(GL_DEPTH_TEST);
+    core::vector3df col2(1., 1., 1.);
+
+    PointLightScatterShader::getInstance()->use();
+    glBindVertexArray(PointLightScatterShader::getInstance()->vao);
+
+    PointLightScatterShader::getInstance()
+        ->setTextureUnits(depth_stencil_texture);
+    PointLightScatterShader::getInstance()
+        ->setUniforms(1.f / (40.f * start), col2);
+
+    glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4,
+                          std::min(m_point_light_count,
+                          LightBaseClass::MAXLIGHT));
+
+    glDisable(GL_BLEND);
+    post_processing->renderGaussian6Blur(half1_framebuffer,
+                                         half2_framebuffer, 5., 5.);
+    glEnable(GL_BLEND);
+
+    glDisable(GL_DEPTH_TEST);
+    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+    colors_framebuffer.bind();
+    post_processing->renderPassThrough(half1_framebuffer.getRTT()[0],
+                                       colors_framebuffer.getWidth(),
+                                       colors_framebuffer.getHeight());
+}   // renderLightsScatter
+
+#endif    // !SERVER_ONLY
+
diff --git a/src/graphics/material.cpp b/src/graphics/material.cpp
index 37ecada25..3442227e5 100644
--- a/src/graphics/material.cpp
+++ b/src/graphics/material.cpp
@@ -716,6 +716,7 @@ void  Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
                   m_texname.c_str());
     }
 
+#ifndef SERVER_ONLY
     if (CVS->isGLSL())
     {
         ITexture *tex;
@@ -865,7 +866,7 @@ void  Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
         }
         m->setTexture(1, glossytex);
     }
-
+#endif
 
     if (m_shader_type == SHADERTYPE_SOLID_UNLIT)
     {
diff --git a/src/graphics/material_manager.cpp b/src/graphics/material_manager.cpp
index 7c227b7e5..1082f9677 100644
--- a/src/graphics/material_manager.cpp
+++ b/src/graphics/material_manager.cpp
@@ -145,6 +145,7 @@ Material* MaterialManager::getDefaultMaterial(video::E_MATERIAL_TYPE shader_type
         // Try to find a cleaner way
         // If graphics are disabled, shaders should not be accessed (getShader
         // asserts that shaders are initialised).
+#ifndef SERVER_ONLY
         if(!ProfileWorld::isNoGraphics() && CVS->isGLSL() &&
             shader_type == Shaders::getShader(ShaderType::ES_OBJECT_UNLIT))
             default_material->setShaderType(Material::SHADERTYPE_SOLID_UNLIT);
@@ -156,7 +157,7 @@ Material* MaterialManager::getDefaultMaterial(video::E_MATERIAL_TYPE shader_type
         //    default_material->setShaderType(Material::SHADERTYPE_ALPHA_BLEND);
         else
             default_material->setShaderType(Material::SHADERTYPE_SOLID);
-
+#endif
         m_default_materials[shader_type] = default_material;
         return default_material;
     }
diff --git a/src/graphics/mesh_tools.cpp b/src/graphics/mesh_tools.cpp
index 95bf286ee..cbc1f83a7 100644
--- a/src/graphics/mesh_tools.cpp
+++ b/src/graphics/mesh_tools.cpp
@@ -328,6 +328,7 @@ void recalculateTangents(scene::IMesh* mesh, bool recalculate_normals, bool smoo
     }
 }
 
+#ifndef SERVER_ONLY
 bool MeshTools::isNormalMap(scene::IMeshBuffer* mb)
 {
     if (!CVS->isGLSL())
@@ -335,6 +336,7 @@ bool MeshTools::isNormalMap(scene::IMeshBuffer* mb)
     return (mb->getMaterial().MaterialType == Shaders::getShader(ES_NORMAL_MAP) &&
             mb->getVertexType() != video::EVT_TANGENTS);
 }
+#endif
 
 // Copied from irrlicht
 scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh,
diff --git a/src/graphics/particle_emitter.cpp b/src/graphics/particle_emitter.cpp
index 680741c8e..12b9f3c24 100644
--- a/src/graphics/particle_emitter.cpp
+++ b/src/graphics/particle_emitter.cpp
@@ -16,6 +16,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/particle_emitter.hpp"
 
 #include "graphics/central_settings.hpp"
@@ -763,3 +765,5 @@ void ParticleEmitter::resizeBox(float size)
     }
 #endif
 }
+
+#endif   // !SERVER_ONLY
diff --git a/src/graphics/post_processing.cpp b/src/graphics/post_processing.cpp
index ffafefb62..e5bb3260e 100644
--- a/src/graphics/post_processing.cpp
+++ b/src/graphics/post_processing.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
 
+#ifndef SERVER_ONLY
+
 #include "graphics/post_processing.hpp"
 
 #include "config/user_config.hpp"
@@ -1596,3 +1598,5 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode,
 
     return out_fbo;
 }   // render
+
+#endif   // !SERVER_ONLY
diff --git a/src/graphics/rtts.cpp b/src/graphics/rtts.cpp
index 62271c56a..6aa5e0a67 100644
--- a/src/graphics/rtts.cpp
+++ b/src/graphics/rtts.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/rtts.hpp"
 
 #include "config/user_config.hpp"
@@ -317,3 +319,5 @@ RTT::~RTT()
     }
 }
 
+
+#endif   // !SERVER_ONLY
diff --git a/src/graphics/shader.cpp b/src/graphics/shader.cpp
index fd4864777..951c4ed13 100644
--- a/src/graphics/shader.cpp
+++ b/src/graphics/shader.cpp
@@ -16,6 +16,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/shader.hpp"
 
 #include "graphics/central_settings.hpp"
@@ -362,3 +364,5 @@ GLuint ShaderBase::createVAO()
 }   // createVAO
 
 // ============================================================================
+
+#endif   // !SERVER_ONLY
diff --git a/src/graphics/shader.hpp b/src/graphics/shader.hpp
index adfc64cde..e879ac3ff 100644
--- a/src/graphics/shader.hpp
+++ b/src/graphics/shader.hpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #ifndef HEADER_SHADER_HPP
 #define HEADER_SHADER_HPP
 
@@ -382,3 +384,6 @@ public:
 // ============================================================================
 
 #endif
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp
index 205493df5..70155f5e8 100644
--- a/src/graphics/shaders.cpp
+++ b/src/graphics/shaders.cpp
@@ -16,6 +16,8 @@
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 
+#ifndef SERVER_ONLY
+
 /**
 \page shaders_overview Shaders Overview
 
@@ -397,3 +399,5 @@ Shaders::ColoredLine::ColoredLine()
     glBindVertexArray(0);
     glBindBuffer(GL_ARRAY_BUFFER, 0);
 }   // Shaders::ColoredLine
+
+#endif   // !SERVER_ONLY
diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp
index 7433329d4..88a95e148 100644
--- a/src/graphics/shaders.hpp
+++ b/src/graphics/shaders.hpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #ifndef HEADER_SHADERS_HPP
 #define HEADER_SHADERS_HPP
 
@@ -164,3 +166,5 @@ public:
 };   // class Shaders
 
 #endif
+
+#endif   // SHADER_ONLY
diff --git a/src/graphics/shadow_matrices.cpp b/src/graphics/shadow_matrices.cpp
index d67f006ac..ceff5a5f4 100644
--- a/src/graphics/shadow_matrices.cpp
+++ b/src/graphics/shadow_matrices.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/shadow_matrices.hpp"
 
 #include "config/user_config.hpp"
@@ -523,3 +525,5 @@ void ShadowMatrices::renderShadowsDebug(const FrameBuffer &shadow_framebuffer,
     renderWireFrameFrustrum(m_shadows_cam[3], 3);
     glViewport(0, 0, UserConfigParams::m_width, UserConfigParams::m_height);
 }
+
+#endif   // !SERVER_ONLY
diff --git a/src/graphics/shared_gpu_objects.cpp b/src/graphics/shared_gpu_objects.cpp
index 7104c1761..fe5dd8d04 100644
--- a/src/graphics/shared_gpu_objects.cpp
+++ b/src/graphics/shared_gpu_objects.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/shared_gpu_objects.hpp"
 #include "graphics/central_settings.hpp"
 
@@ -213,3 +215,6 @@ void SharedGPUObjects::reset()
 {
     m_has_been_initialised = false;
 }   // reset
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/show_curve.cpp b/src/graphics/show_curve.cpp
index 60601ddac..09a2823f4 100644
--- a/src/graphics/show_curve.cpp
+++ b/src/graphics/show_curve.cpp
@@ -16,6 +16,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/show_curve.hpp"
 
 #include "graphics/irr_driver.hpp"
@@ -200,3 +202,6 @@ void ShowCurve::setPosition(const Vec3 &xyz)
     m_scene_node->setPosition(xyz.toIrrVector());
 }   // setPosition
 // ----------------------------------------------------------------------------
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/skybox.cpp b/src/graphics/skybox.cpp
index 2eda7d50d..fd1c597b8 100644
--- a/src/graphics/skybox.cpp
+++ b/src/graphics/skybox.cpp
@@ -15,6 +15,7 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
 
 #include "graphics/skybox.hpp"
 #include "graphics/central_settings.hpp"
@@ -375,4 +376,5 @@ void Skybox::render(const scene::ICameraSceneNode *camera) const
     glBindVertexArray(0);
 }   // renderSkybox
 
+#endif   // !SERVER_ONLY
 
diff --git a/src/graphics/slip_stream.cpp b/src/graphics/slip_stream.cpp
index eb588f02a..a05245db4 100644
--- a/src/graphics/slip_stream.cpp
+++ b/src/graphics/slip_stream.cpp
@@ -99,8 +99,10 @@ SlipStream::SlipStream(AbstractKart* kart) : MovingTexture(0, 0), m_kart(kart)
         }
         video::SMaterial &mat = buffer->getMaterial();
         // Meshes need a texture, otherwise stk crashes.
+#ifndef SERVER_ONLY
         video::ITexture *red_texture = getUnicolorTexture(red);
         mat.setTexture(0, red_texture);
+#endif
 
         buffer->recalculateBoundingBox();
         m_mesh->setBoundingBox(buffer->getBoundingBox());
diff --git a/src/graphics/spherical_harmonics.cpp b/src/graphics/spherical_harmonics.cpp
index 15d07aab4..0d1f0657b 100644
--- a/src/graphics/spherical_harmonics.cpp
+++ b/src/graphics/spherical_harmonics.cpp
@@ -15,6 +15,7 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
 
 #include "graphics/irr_driver.hpp"
 #include "graphics/spherical_harmonics.hpp"
@@ -528,3 +529,5 @@ void SphericalHarmonics::unprojectSH(size_t width, size_t height,
     }
 }   // unprojectSH
 
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/stk_animated_mesh.cpp b/src/graphics/stk_animated_mesh.cpp
index 5bc634a9f..bab003022 100644
--- a/src/graphics/stk_animated_mesh.cpp
+++ b/src/graphics/stk_animated_mesh.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/stk_animated_mesh.hpp"
 
 #include "graphics/central_settings.hpp"
@@ -281,3 +283,6 @@ void STKAnimatedMesh::render()
     updateNoGL();
     updateGL();
 }
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/stk_billboard.cpp b/src/graphics/stk_billboard.cpp
index 4d770e455..573a0348b 100644
--- a/src/graphics/stk_billboard.cpp
+++ b/src/graphics/stk_billboard.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/stk_billboard.hpp"
 
 #include "graphics/irr_driver.hpp"
@@ -118,3 +120,6 @@ void STKBillboard::render()
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
     glBindVertexArray(0);
 }   // render
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/stk_mesh.cpp b/src/graphics/stk_mesh.cpp
index c12dd8426..1712b3de2 100644
--- a/src/graphics/stk_mesh.cpp
+++ b/src/graphics/stk_mesh.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/stk_mesh.hpp"
 
 #include "graphics/callbacks.hpp"
@@ -442,3 +444,6 @@ void initTexturesTransparent(GLMesh &mesh)
     }
 #endif
 }   // initTexturesTransparent
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/stk_mesh_scene_node.cpp b/src/graphics/stk_mesh_scene_node.cpp
index 3b5b3ac57..2a0ba8ba3 100644
--- a/src/graphics/stk_mesh_scene_node.cpp
+++ b/src/graphics/stk_mesh_scene_node.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/stk_mesh_scene_node.hpp"
 
 #include "graphics/central_settings.hpp"
@@ -580,3 +582,6 @@ void STKMeshSceneNode::render()
         }
     }
 }
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/stk_mesh_scene_node.hpp b/src/graphics/stk_mesh_scene_node.hpp
index 07fc4030f..c75e52d00 100644
--- a/src/graphics/stk_mesh_scene_node.hpp
+++ b/src/graphics/stk_mesh_scene_node.hpp
@@ -73,8 +73,10 @@ public:
             scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
             if (!mb)
                 continue;
+#ifndef SERVER_ONLY
             if (isDisplacement)
                 mb->getMaterial().MaterialType = Shaders::getShader(ES_DISPLACE);
+#endif
         }
     }
     virtual bool glow() const { return isGlow; }
diff --git a/src/graphics/stk_scene_manager.cpp b/src/graphics/stk_scene_manager.cpp
index 1971bf171..b26181ab8 100644
--- a/src/graphics/stk_scene_manager.cpp
+++ b/src/graphics/stk_scene_manager.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/stk_scene_manager.hpp"
 #include <SViewFrustum.h>
 #include <vector>
@@ -61,3 +63,5 @@ bool isCulledPrecise(const scene::ICameraSceneNode *cam, const scene::ISceneNode
             return true;
     return false;
 }
+
+#endif   // !SERVER_ONLY
diff --git a/src/graphics/stk_scene_manager.hpp b/src/graphics/stk_scene_manager.hpp
index aae792da0..8fc984b6a 100644
--- a/src/graphics/stk_scene_manager.hpp
+++ b/src/graphics/stk_scene_manager.hpp
@@ -19,6 +19,8 @@
 // Not really a scene manager yet but hold algorithm that
 // rework scene manager output
 
+#ifndef SERVER_ONLY
+
 #ifndef HEADER_STKSCENEMANAGER_HPP
 #define HEADER_STKSCENEMANAGER_HPP
 
@@ -31,3 +33,5 @@ void addEdge(const irr::core::vector3df &P0, const irr::core::vector3df &P1);
 bool isCulledPrecise(const irr::scene::ICameraSceneNode *cam, const irr::scene::ISceneNode *node);
 
 #endif
+
+#endif   // supertuxkart
diff --git a/src/graphics/stk_text_billboard.cpp b/src/graphics/stk_text_billboard.cpp
index 1ede26873..2258f3bf4 100644
--- a/src/graphics/stk_text_billboard.cpp
+++ b/src/graphics/stk_text_billboard.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/stk_text_billboard.hpp"
 #include "graphics/shaders.hpp"
 #include "graphics/irr_driver.hpp"
@@ -190,3 +192,6 @@ void STKTextBillboard::collectChar(video::ITexture* texture,
 {
     m_chars.push_back(STKTextBillboardChar(texture, destRect, sourceRect, colors));
 }
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/texture_manager.cpp b/src/graphics/texture_manager.cpp
index 7047446cd..201954860 100644
--- a/src/graphics/texture_manager.cpp
+++ b/src/graphics/texture_manager.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/texture_manager.hpp"
 
 #include "graphics/central_settings.hpp"
@@ -258,3 +260,6 @@ video::ITexture* getUnicolorTexture(const video::SColor &c)
         return tex;
     }
 }
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/texture_shader.cpp b/src/graphics/texture_shader.cpp
index e4de23ae8..339434ae8 100644
--- a/src/graphics/texture_shader.cpp
+++ b/src/graphics/texture_shader.cpp
@@ -16,6 +16,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/texture_shader.hpp"
 #include "graphics/central_settings.hpp"
 
@@ -366,3 +368,6 @@ GLuint TextureShaderBase::createSemiTrilinearSampler()
 
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/graphics/texture_shader.hpp b/src/graphics/texture_shader.hpp
index b704ea603..0ed9a1922 100644
--- a/src/graphics/texture_shader.hpp
+++ b/src/graphics/texture_shader.hpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SHADER_ONLY
+
 #ifndef HEADER_TEXTURE_SHADER_HPP
 #define HEADER_TEXTURE_SHADER_HPP
 
@@ -254,3 +256,5 @@ public:
 };   // class TextureShader
 
 #endif
+
+#endif   // SHADER_ONLY
diff --git a/src/graphics/vao_manager.cpp b/src/graphics/vao_manager.cpp
index 6448488be..88c89ec3a 100644
--- a/src/graphics/vao_manager.cpp
+++ b/src/graphics/vao_manager.cpp
@@ -15,6 +15,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/vao_manager.hpp"
 
 #include "graphics/central_settings.hpp"
@@ -343,3 +345,5 @@ std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb, Render
     assert(It != mappedBaseIndex[tp].end());
     return std::pair<unsigned, unsigned>(vtx, It->second);
 }
+
+#endif   // !SERVER_ONLY
diff --git a/src/graphics/water.cpp b/src/graphics/water.cpp
index f8130aaeb..5f587cf39 100644
--- a/src/graphics/water.cpp
+++ b/src/graphics/water.cpp
@@ -16,6 +16,8 @@
 //  along with this program; if not, write to the Free Software
 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
+#ifndef SERVER_ONLY
+
 #include "graphics/water.hpp"
 
 #include "graphics/callbacks.hpp"
@@ -89,3 +91,6 @@ void WaterNode::OnRegisterSceneNode()
         ISceneNode::OnRegisterSceneNode();
     }
 }
+
+#endif   // !SERVER_ONLY
+
diff --git a/src/guiengine/engine.cpp b/src/guiengine/engine.cpp
index c627d7e89..b7bbd28eb 100644
--- a/src/guiengine/engine.cpp
+++ b/src/guiengine/engine.cpp
@@ -664,7 +664,9 @@ namespace GUIEngine
 #include "font/regular_face.hpp"
 #include "input/input_manager.hpp"
 #include "io/file_manager.hpp"
+#ifndef SERVER_ONLY
 #include "graphics/2dutils.hpp"
+#endif
 #include "graphics/irr_driver.hpp"
 #include "guiengine/event_handler.hpp"
 #include "guiengine/modaldialog.hpp"
diff --git a/src/guiengine/skin.cpp b/src/guiengine/skin.cpp
index 62678a3ed..0fc6270d6 100644
--- a/src/guiengine/skin.cpp
+++ b/src/guiengine/skin.cpp
@@ -1958,7 +1958,9 @@ void Skin::process3DPane(IGUIElement *element, const core::recti &rect,
     else if (type == WTYPE_MODEL_VIEW)
     {
         ModelViewWidget* mvw = dynamic_cast<ModelViewWidget*>(widget);
+#ifndef SERVER_ONLY
         mvw->drawRTTScene(rect);
+#endif
     }
     else if (type == WTYPE_ICON_BUTTON)
     {
diff --git a/src/items/rubber_band.cpp b/src/items/rubber_band.cpp
index fe53e56d7..d8143e5e2 100644
--- a/src/items/rubber_band.cpp
+++ b/src/items/rubber_band.cpp
@@ -68,12 +68,14 @@ RubberBand::RubberBand(Plunger *plunger, AbstractKart *kart)
         verts[i].Color = color;
     }
 
+#ifndef SERVER_ONLY
     // Color
     mb->getMaterial().setTexture(0, getUnicolorTexture(video::SColor(255, 255, 255, 255)));
     // Gloss
     mb->getMaterial().setTexture(1, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
     // Colorization mask
     mb->getMaterial().setTexture(7, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
+#endif
     updatePosition();
     m_node = irr_driver->addMesh(m_mesh, "rubberband");
     irr_driver->applyObjectPassShader(m_node);
diff --git a/src/karts/kart_properties.cpp b/src/karts/kart_properties.cpp
index cae3e0c38..099ca110f 100644
--- a/src/karts/kart_properties.cpp
+++ b/src/karts/kart_properties.cpp
@@ -249,10 +249,12 @@ void KartProperties::load(const std::string &filename, const std::string &node)
     else
         m_minimap_icon = NULL;
 
+#ifndef SERVER_ONLY
     if (m_minimap_icon == NULL)
     {
         m_minimap_icon = getUnicolorTexture(m_color);
     }
+#endif
 
     // Only load the model if the .kart file has the appropriate version,
     // otherwise warnings are printed.
diff --git a/src/states_screens/race_gui.cpp b/src/states_screens/race_gui.cpp
index 9a8d030c2..d1a995b12 100644
--- a/src/states_screens/race_gui.cpp
+++ b/src/states_screens/race_gui.cpp
@@ -27,6 +27,9 @@ using namespace irr;
 #include "config/user_config.hpp"
 #include "graphics/camera.hpp"
 #include "graphics/2dutils.hpp"
+#ifndef SERVER_ONLY
+#include "graphics/glwrap.hpp"
+#endif
 #include "graphics/irr_driver.hpp"
 #include "graphics/material_manager.hpp"
 #include "guiengine/engine.hpp"
@@ -370,6 +373,7 @@ void RaceGUI::drawGlobalTimer()
  */
 void RaceGUI::drawGlobalMiniMap()
 {
+#ifndef SERVER_ONLY
     World *world = World::getWorld();
     // draw a map when arena has a navigation mesh.
     if ((world->getTrack()->isArena() || world->getTrack()->isSoccer()) &&
@@ -428,7 +432,7 @@ void RaceGUI::drawGlobalMiniMap()
                                  lower_y   -(int)(draw_at.getY()-(m_minimap_player_size/2.5f)));
         draw2DImage(icon, position, source, NULL, NULL, true);
     }
-
+#endif
 }   // drawGlobalMiniMap
 
 //-----------------------------------------------------------------------------
diff --git a/src/states_screens/race_gui_overworld.cpp b/src/states_screens/race_gui_overworld.cpp
index a41dc7502..89dbb951f 100644
--- a/src/states_screens/race_gui_overworld.cpp
+++ b/src/states_screens/race_gui_overworld.cpp
@@ -25,6 +25,9 @@
 #include "config/user_config.hpp"
 #include "graphics/camera.hpp"
 #include "graphics/2dutils.hpp"
+#ifndef SERVER_ONLY
+#include "graphics/glwrap.hpp"
+#endif
 #include "graphics/irr_driver.hpp"
 #include "graphics/material_manager.hpp"
 #include "guiengine/engine.hpp"
@@ -294,6 +297,7 @@ void RaceGUIOverworld::drawTrophyPoints()
  */
 void RaceGUIOverworld::drawGlobalMiniMap()
 {
+#ifndef SERVER_ONLY
     World *world = World::getWorld();
     // arenas currently don't have a map.
     if(world->getTrack()->isArena() || world->getTrack()->isSoccer()) return;
@@ -534,7 +538,7 @@ void RaceGUIOverworld::drawGlobalMiniMap()
                                        true, true /* vcenter */, NULL);
         }
     }
-
+#endif   // SERVER_ONLY
 }   // drawGlobalMiniMap
 
 //-----------------------------------------------------------------------------
diff --git a/src/tracks/check_line.cpp b/src/tracks/check_line.cpp
index 0bd8490a5..83e0a75f4 100644
--- a/src/tracks/check_line.cpp
+++ b/src/tracks/check_line.cpp
@@ -72,6 +72,7 @@ CheckLine::CheckLine(const XMLNode &node,  unsigned int index)
     m_line.setLine(p1, p2);
     if(UserConfigParams::m_check_debug)
     {
+#ifndef SERVER_ONLY
         video::SMaterial material;
         material.setFlag(video::EMF_BACK_FACE_CULLING, false);
         material.setFlag(video::EMF_LIGHTING, false);
@@ -109,6 +110,7 @@ CheckLine::CheckLine(const XMLNode &node,  unsigned int index)
         //mesh->setBoundingBox(buffer->getBoundingBox());
         m_debug_node = irr_driver->addMesh(mesh, "checkdebug");
         mesh->drop();
+#endif
     }
     else
     {
@@ -150,7 +152,9 @@ void CheckLine::changeDebugColor(bool is_active)
     {
         vertices[i].Color = color;
     }
+#ifndef SERVER_ONLY
     buffer->getMaterial().setTexture(0, getUnicolorTexture(color));
+#endif
 
 }   // changeDebugColor
 
diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp
index 56be84804..0484e7b70 100644
--- a/src/tracks/track.cpp
+++ b/src/tracks/track.cpp
@@ -280,11 +280,13 @@ void Track::cleanup()
 {
     Graph::destroy();
     ItemManager::destroy();
+#ifndef SERVER_ONLY
     VAOManager::kill();
-
     ParticleKindManager::get()->cleanUpTrackSpecificGfx();
     // Clear reminder of transformed textures
     resetTextureTable();
+#endif
+
     // Clear reminder of the link between textures and file names.
     irr_driver->clearTexturesFileName();
 
@@ -787,12 +789,16 @@ void Track::createPhysicsModel(unsigned int main_track_count)
             }
 
             // Color
+#ifndef SERVER_ONLY
             mb->getMaterial().setTexture(0, getUnicolorTexture(video::SColor(255, 255, 105, 180)));
+#endif
             irr_driver->grabAllTextures(mesh);
             // Gloss
+#ifndef SERVER_ONLY
             mb->getMaterial().setTexture(1, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
             // Colorization mask
             mb->getMaterial().setTexture(7, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
+#endif
         }
         else
             irr_driver->removeNode(m_static_physics_only_nodes[i]);
@@ -1029,6 +1035,7 @@ void Track::convertTrackToBullet(scene::ISceneNode *node)
 
 void Track::loadMinimap()
 {
+#ifndef SERVER_ONLY
     //Check whether the hardware can do nonsquare or
     // non power-of-two textures
     video::IVideoDriver* const video_driver = irr_driver->getVideoDriver();
@@ -1055,6 +1062,7 @@ void Track::loadMinimap()
         m_minimap_y_scale = float(m_mini_map_size.Height) / float(mini_map_texture_size.Height);
     else
         m_minimap_y_scale = 0;
+#endif
 }   // loadMinimap
 
 // ----------------------------------------------------------------------------
diff --git a/src/utils/debug.cpp b/src/utils/debug.cpp
index a8d4dd035..f9d82f23d 100644
--- a/src/utils/debug.cpp
+++ b/src/utils/debug.cpp
@@ -234,8 +234,10 @@ bool handleContextMenuAction(s32 cmd_id)
     switch(cmd_id)
     {
     case DEBUG_GRAPHICS_RELOAD_SHADERS:
-            Log::info("Debug", "Reloading shaders...");
+#ifndef SERVER_ONLY
+        Log::info("Debug", "Reloading shaders...");
             ShaderBase::updateShaders();
+#endif
             break;
     case DEBUG_GRAPHICS_RESET:
         if (physics)
diff --git a/src/utils/profiler.cpp b/src/utils/profiler.cpp
index 98de8cd9a..4e7a31e93 100644
--- a/src/utils/profiler.cpp
+++ b/src/utils/profiler.cpp
@@ -17,11 +17,13 @@
 
 #include "profiler.hpp"
 #include "graphics/glwrap.hpp"
+#include "graphics/irr_driver.hpp"
 #include "graphics/2dutils.hpp"
 #include "guiengine/event_handler.hpp"
 #include "guiengine/engine.hpp"
 #include "graphics/irr_driver.hpp"
 #include "guiengine/scalable_font.hpp"
+#include "io/file_manager.hpp"
 #include "utils/vs.hpp"
 
 #include <assert.h>
@@ -372,7 +374,9 @@ void Profiler::draw()
     unsigned int gpu_timers[Q_LAST];
     for (unsigned i = 0; i < Q_LAST; i++)
     {
+#ifndef SERVER_ONLY
         gpu_timers[i] = irr_driver->getGPUTimer(i).elapsedTimeus();
+#endif
         total += gpu_timers[i];
     }