split shader_based_renderer into smaller objects

This commit is contained in:
Elderme 2015-09-20 21:14:01 +02:00
parent b7ab99e5e2
commit f56baaefcb
6 changed files with 696 additions and 564 deletions

View File

@ -0,0 +1,589 @@
// 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 "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, "utils/getPosFromUVDepth.frag",
GL_FRAGMENT_SHADER, "fog.frag");
assignUniforms("density", "col");
assignSamplerNames(0, "tex", ST_NEAREST_FILTERED);
} // FogShader
// ------------------------------------------------------------------------
void render(float start, const core::vector3df &color)
{
setTextureUnits(irr_driver->getDepthStencilTexture());
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, "utils/decodeNormal.frag",
GL_FRAGMENT_SHADER, "utils/SpecularBRDF.frag",
GL_FRAGMENT_SHADER, "utils/DiffuseBRDF.frag",
GL_FRAGMENT_SHADER, "utils/getPosFromUVDepth.frag",
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, "utils/getPosFromUVDepth.frag",
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
};
// ============================================================================
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
// ============================================================================
class ShadowedSunLightShaderPCF : public TextureShader<ShadowedSunLightShaderPCF,
3, float, float, float,
float, float>
{
public:
ShadowedSunLightShaderPCF()
{
loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
GL_FRAGMENT_SHADER, "utils/decodeNormal.frag",
GL_FRAGMENT_SHADER, "utils/SpecularBRDF.frag",
GL_FRAGMENT_SHADER, "utils/DiffuseBRDF.frag",
GL_FRAGMENT_SHADER, "utils/getPosFromUVDepth.frag",
GL_FRAGMENT_SHADER, "utils/SunMRP.frag",
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(RTT *rtts)
{
setTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH),
irr_driver->getDepthStencilTexture(),
rtts->getShadowFBO().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, "utils/decodeNormal.frag",
GL_FRAGMENT_SHADER, "utils/SpecularBRDF.frag",
GL_FRAGMENT_SHADER, "utils/DiffuseBRDF.frag",
GL_FRAGMENT_SHADER, "utils/getPosFromUVDepth.frag",
GL_FRAGMENT_SHADER, "utils/SunMRP.frag",
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(RTT *rtt)
{
setTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH),
irr_driver->getDepthStencilTexture(),
rtt->getShadowFBO().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
// ============================================================================
static void renderPointLights(unsigned count)
{
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(
irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH),
irr_driver->getDepthStencilTexture());
PointLightShader::getInstance()->setUniforms();
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
} // renderPointLights
// ----------------------------------------------------------------------------
unsigned 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]);
}
unsigned lightnum = 0;
bool multiplayer = (race_manager->getNumLocalPlayers() > 1);
for (unsigned i = 0; i < 15; i++)
{
for (unsigned j = 0; j < BucketedLN[i].size(); j++)
{
if (++lightnum >= 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[lightnum].posX = pos.X;
m_point_lights_info[lightnum].posY = pos.Y;
m_point_lights_info[lightnum].posZ = pos.Z;
m_point_lights_info[lightnum].energy =
light_node->getEffectiveEnergy();
const core::vector3df &col = light_node->getColor();
m_point_lights_info[lightnum].red = col.X;
m_point_lights_info[lightnum].green = col.Y;
m_point_lights_info[lightnum].blue = col.Z;
// Light radius
m_point_lights_info[lightnum].radius = light_node->getRadius();
}
}
if (lightnum > LightBaseClass::MAXLIGHT)
{
irr_driver->setLastLightBucketDistance(i * 10);
break;
}
}
lightnum++;
return lightnum;
} // updateLightsInfo
void LightingPasses::renderLights(unsigned pointlightcount, bool hasShadow)
{
RTT *rtts = irr_driver->getRTT();
ShadowMatrices *shadow_matrices = irr_driver->getShadowMatrices();
//RH
if (CVS->isGlobalIlluminationEnabled() && hasShadow)
{
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_RH));
glDisable(GL_BLEND);
rtts->getRH().bind();
glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO());
if (CVS->needRHWorkaround())
{
NVWorkaroundRadianceHintsConstructionShader::getInstance()->use();
NVWorkaroundRadianceHintsConstructionShader::getInstance()
->setTextureUnits(
rtts->getRSM().getRTT()[0],
rtts->getRSM().getRTT()[1],
rtts->getRSM().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(
rtts->getRSM().getRTT()[0],
rtts->getRSM().getRTT()[1],
rtts->getRSM().getDepthTexture()
);
RadianceHintsConstructionShader::getInstance()
->setUniforms(shadow_matrices->getRSMMatrix(),
shadow_matrices->getRHMatrix(),
shadow_matrices->getRHExtend(),
irr_driver->getSunColor());
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32);
}
}
shadow_matrices->updateSunOrthoMatrices();
rtts->getFBO(FBO_COMBINED_DIFFUSE_SPECULAR).bind();
glClear(GL_COLOR_BUFFER_BIT);
rtts->getFBO(FBO_DIFFUSE).bind();
PostProcessing *post_processing = irr_driver->getPostProcessing();
if (CVS->isGlobalIlluminationEnabled() && hasShadow)
{
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_GI));
post_processing->renderGI(shadow_matrices->getRHMatrix(),
shadow_matrices->getRHExtend(),
rtts->getRH());
}
rtts->getFBO(FBO_COMBINED_DIFFUSE_SPECULAR).bind();
{
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP));
Skybox *skybox = irr_driver->getSkybox();
if(skybox)
{
post_processing->renderEnvMap(skybox->getSpecularProbe());
}
else
{
post_processing->renderEnvMap(0);
}
}
// 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() && hasShadow)
{
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_ONE, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
if (CVS->isESMEnabled())
{
ShadowedSunLightShaderESM::getInstance()->render(rtts);
}
else
{
ShadowedSunLightShaderPCF::getInstance()->render(rtts);
}
}
else
post_processing->renderSunlight(irr_driver->getSunDirection(),
irr_driver->getSunColor());
}
{
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_POINTLIGHTS));
renderPointLights(std::min(pointlightcount, LightBaseClass::MAXLIGHT));
}
} // renderLights
// ----------------------------------------------------------------------------
void LightingPasses::renderAmbientScatter()
{
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);
} // renderAmbientScatter
// ----------------------------------------------------------------------------
void LightingPasses::renderLightsScatter(unsigned pointlightcount)
{
irr_driver->getFBO(FBO_HALF1).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(irr_driver->getDepthStencilTexture());
PointLightScatterShader::getInstance()
->setUniforms(1.f / (40.f * start), col2);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4,
std::min(pointlightcount, LightBaseClass::MAXLIGHT));
glDisable(GL_BLEND);
PostProcessing *post_processing = irr_driver->getPostProcessing();
post_processing->renderGaussian6Blur(irr_driver->getFBO(FBO_HALF1),
irr_driver->getFBO(FBO_HALF2), 5., 5.);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
irr_driver->getFBO(FBO_COLORS).bind();
post_processing->renderPassThrough(irr_driver->getRenderTargetTexture(RTT_HALF1),
irr_driver->getFBO(FBO_COLORS).getWidth(),
irr_driver->getFBO(FBO_COLORS).getHeight());
} // renderLightsScatter

View File

@ -0,0 +1,38 @@
// 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 HEADER_LIGHTING_PASSES_HPP
#define HEADER_LIGHTING_PASSES_HPP
#include <irrlicht.h>
class LightingPasses
{
private:
public:
unsigned updateLightsInfo(irr::scene::ICameraSceneNode * const camnode,
float dt);
void renderLights(unsigned pointlightcount, bool hasShadow);
void renderAmbientScatter();
void renderLightsScatter(unsigned pointlightCount);
};
#endif //HEADER_LIGHTING_PASSES_HPP

View File

@ -20,7 +20,6 @@
#include "graphics/central_settings.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/graphics_restrictions.hpp"
#include "graphics/light.hpp"
#include "graphics/lod_node.hpp"
#include "graphics/post_processing.hpp"
#include "graphics/rtts.hpp"
@ -40,307 +39,6 @@
extern std::vector<float> BoundingBoxes; //TODO
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 PointLightShader : public TextureShader < PointLightShader, 2 >
{
public:
GLuint vbo;
GLuint vao;
PointLightShader()
{
loadProgram(OBJECT, GL_VERTEX_SHADER, "pointlight.vert",
GL_FRAGMENT_SHADER, "utils/decodeNormal.frag",
GL_FRAGMENT_SHADER, "utils/SpecularBRDF.frag",
GL_FRAGMENT_SHADER, "utils/DiffuseBRDF.frag",
GL_FRAGMENT_SHADER, "utils/getPosFromUVDepth.frag",
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, "utils/getPosFromUVDepth.frag",
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
};
// ============================================================================
class ShadowedSunLightShaderPCF : public TextureShader<ShadowedSunLightShaderPCF,
3, float, float, float,
float, float>
{
public:
ShadowedSunLightShaderPCF()
{
loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
GL_FRAGMENT_SHADER, "utils/decodeNormal.frag",
GL_FRAGMENT_SHADER, "utils/SpecularBRDF.frag",
GL_FRAGMENT_SHADER, "utils/DiffuseBRDF.frag",
GL_FRAGMENT_SHADER, "utils/getPosFromUVDepth.frag",
GL_FRAGMENT_SHADER, "utils/SunMRP.frag",
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(RTT *rtts)
{
setTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH),
irr_driver->getDepthStencilTexture(),
rtts->getShadowFBO().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, "utils/decodeNormal.frag",
GL_FRAGMENT_SHADER, "utils/SpecularBRDF.frag",
GL_FRAGMENT_SHADER, "utils/DiffuseBRDF.frag",
GL_FRAGMENT_SHADER, "utils/getPosFromUVDepth.frag",
GL_FRAGMENT_SHADER, "utils/SunMRP.frag",
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(RTT *rtt)
{
setTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH),
irr_driver->getDepthStencilTexture(),
rtt->getShadowFBO().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 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
// ============================================================================
class FogShader : public TextureShader<FogShader, 1, float, core::vector3df>
{
public:
FogShader()
{
loadProgram(OBJECT, GL_VERTEX_SHADER, "screenquad.vert",
GL_FRAGMENT_SHADER, "utils/getPosFromUVDepth.frag",
GL_FRAGMENT_SHADER, "fog.frag");
assignUniforms("density", "col");
assignSamplerNames(0, "tex", ST_NEAREST_FILTERED);
} // FogShader
// ------------------------------------------------------------------------
void render(float start, const core::vector3df &color)
{
setTextureUnits(irr_driver->getDepthStencilTexture());
drawFullScreenEffect(1.f / (40.f * start), color);
} // render
}; // FogShader
// ============================================================================
static void renderPointLights(unsigned count)
{
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(
irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH),
irr_driver->getDepthStencilTexture());
PointLightShader::getInstance()->setUniforms();
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
} // renderPointLights
void ShaderBasedRenderer::compressPowerUpTextures()
{
@ -450,262 +148,8 @@ void ShaderBasedRenderer::prepareForwardRenderer()
unsigned ShaderBasedRenderer::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]);
}
unsigned lightnum = 0;
bool multiplayer = (race_manager->getNumLocalPlayers() > 1);
for (unsigned i = 0; i < 15; i++)
{
for (unsigned j = 0; j < BucketedLN[i].size(); j++)
{
if (++lightnum >= 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[lightnum].posX = pos.X;
m_point_lights_info[lightnum].posY = pos.Y;
m_point_lights_info[lightnum].posZ = pos.Z;
m_point_lights_info[lightnum].energy =
light_node->getEffectiveEnergy();
const core::vector3df &col = light_node->getColor();
m_point_lights_info[lightnum].red = col.X;
m_point_lights_info[lightnum].green = col.Y;
m_point_lights_info[lightnum].blue = col.Z;
// Light radius
m_point_lights_info[lightnum].radius = light_node->getRadius();
}
}
if (lightnum > LightBaseClass::MAXLIGHT)
{
irr_driver->setLastLightBucketDistance(i * 10);
break;
}
}
lightnum++;
return lightnum;
} // updateLightsInfo
// ----------------------------------------------------------------------------
void ShaderBasedRenderer::renderLights(unsigned pointlightcount, bool hasShadow)
{
RTT *rtts = irr_driver->getRTT();
ShadowMatrices *shadow_matrices = irr_driver->getShadowMatrices();
//RH
if (CVS->isGlobalIlluminationEnabled() && hasShadow)
{
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_RH));
glDisable(GL_BLEND);
rtts->getRH().bind();
glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO());
if (CVS->needRHWorkaround())
{
NVWorkaroundRadianceHintsConstructionShader::getInstance()->use();
NVWorkaroundRadianceHintsConstructionShader::getInstance()
->setTextureUnits(
rtts->getRSM().getRTT()[0],
rtts->getRSM().getRTT()[1],
rtts->getRSM().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(
rtts->getRSM().getRTT()[0],
rtts->getRSM().getRTT()[1],
rtts->getRSM().getDepthTexture()
);
RadianceHintsConstructionShader::getInstance()
->setUniforms(shadow_matrices->getRSMMatrix(),
shadow_matrices->getRHMatrix(),
shadow_matrices->getRHExtend(),
irr_driver->getSunColor());
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32);
}
}
shadow_matrices->updateSunOrthoMatrices();
rtts->getFBO(FBO_COMBINED_DIFFUSE_SPECULAR).bind();
glClear(GL_COLOR_BUFFER_BIT);
rtts->getFBO(FBO_DIFFUSE).bind();
PostProcessing *post_processing = irr_driver->getPostProcessing();
if (CVS->isGlobalIlluminationEnabled() && hasShadow)
{
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_GI));
post_processing->renderGI(shadow_matrices->getRHMatrix(),
shadow_matrices->getRHExtend(),
rtts->getRH());
}
rtts->getFBO(FBO_COMBINED_DIFFUSE_SPECULAR).bind();
{
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP));
Skybox *skybox = irr_driver->getSkybox();
if(skybox)
{
post_processing->renderEnvMap(skybox->getSpecularProbe());
}
else
{
post_processing->renderEnvMap(0);
}
}
// 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() && hasShadow)
{
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_ONE, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
if (CVS->isESMEnabled())
{
ShadowedSunLightShaderESM::getInstance()->render(rtts);
}
else
{
ShadowedSunLightShaderPCF::getInstance()->render(rtts);
}
}
else
post_processing->renderSunlight(irr_driver->getSunDirection(),
irr_driver->getSunColor());
}
{
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_POINTLIGHTS));
renderPointLights(std::min(pointlightcount, LightBaseClass::MAXLIGHT));
}
} // renderLights
// ----------------------------------------------------------------------------
void ShaderBasedRenderer::renderAmbientScatter()
{
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);
} // renderAmbientScatter
// ----------------------------------------------------------------------------
void ShaderBasedRenderer::renderLightsScatter(unsigned pointlightcount)
{
irr_driver->getFBO(FBO_HALF1).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(irr_driver->getDepthStencilTexture());
PointLightScatterShader::getInstance()
->setUniforms(1.f / (40.f * start), col2);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4,
std::min(pointlightcount, LightBaseClass::MAXLIGHT));
glDisable(GL_BLEND);
PostProcessing *post_processing = irr_driver->getPostProcessing();
post_processing->renderGaussian6Blur(irr_driver->getFBO(FBO_HALF1),
irr_driver->getFBO(FBO_HALF2), 5., 5.);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
irr_driver->getFBO(FBO_COLORS).bind();
post_processing->renderPassThrough(irr_driver->getRenderTargetTexture(RTT_HALF1),
irr_driver->getFBO(FBO_COLORS).getWidth(),
irr_driver->getFBO(FBO_COLORS).getHeight());
} // renderLightsScatter
return m_lighting_passes->updateLightsInfo(camnode, dt);
}
// ============================================================================
void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode, unsigned pointlightcount, std::vector<GlowData>& glows, float dt, bool hasShadow, bool forceRTT)
@ -782,7 +226,7 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode, u
{
PROFILER_PUSH_CPU_MARKER("- Light", 0x00, 0xFF, 0x00);
if (CVS->isDefferedEnabled())
renderLights(pointlightcount, hasShadow);
m_lighting_passes->renderLights(pointlightcount, hasShadow);
PROFILER_POP_CPU_MARKER();
}
@ -824,7 +268,7 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode, u
{
PROFILER_PUSH_CPU_MARKER("- Ambient scatter", 0xFF, 0x00, 0x00);
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_FOG));
renderAmbientScatter();
m_lighting_passes->renderAmbientScatter();
PROFILER_POP_CPU_MARKER();
}
@ -841,7 +285,7 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode, u
{
PROFILER_PUSH_CPU_MARKER("- PointLight Scatter", 0xFF, 0x00, 0x00);
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_FOG));
renderLightsScatter(pointlightcount);
m_lighting_passes->renderLightsScatter(pointlightcount);
PROFILER_POP_CPU_MARKER();
}
@ -1003,6 +447,14 @@ void ShaderBasedRenderer::renderPostProcessing(Camera * const camera)
ShaderBasedRenderer::ShaderBasedRenderer():AbstractRenderer()
{
m_solid_passes = new SolidPasses();
m_lighting_passes = new LightingPasses();
}
ShaderBasedRenderer::~ShaderBasedRenderer()
{
delete m_solid_passes;
delete m_lighting_passes;
}
void ShaderBasedRenderer::render(float dt)

View File

@ -19,19 +19,23 @@
#define HEADER_LIGHT_PREPASS_RENDERER_HPP
#include "graphics/abstract_renderer.hpp"
#include "graphics/solid_passes.hpp"
#include "graphics/lighting_passes.hpp"
class ShaderBasedRenderer: public AbstractRenderer
{
private:
SolidPasses *m_solid_passes;
LightingPasses *m_lighting_passes;
void compressPowerUpTextures();
void setOverrideMaterial();
std::vector<GlowData> updateGlowingList();
void prepareForwardRenderer();
unsigned updateLightsInfo(irr::scene::ICameraSceneNode * const camnode,
float dt);
void renderLights(unsigned pointlightcount, bool hasShadow);
void renderAmbientScatter();
void renderLightsScatter(unsigned pointlightCount);
void renderScene(irr::scene::ICameraSceneNode * const camnode,
unsigned pointlightcount, std::vector<GlowData>& glows,
float dt, bool hasShadows, bool forceRTT);
@ -42,6 +46,8 @@ private:
public:
ShaderBasedRenderer();
~ShaderBasedRenderer();
void render(float dt);
};

View File

@ -0,0 +1,18 @@
// 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/solid_passes.hpp"

View File

@ -0,0 +1,29 @@
// 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 HEADER_SOLID_PASSES_HPP
#define HEADER_SOLID_PASSES_HPP
class SolidPasses
{
private:
public:
};
#endif //HEADER_SOLID_PASSES_HPP