Moved more methods from irr_driver to renderer
This commit is contained in:
@@ -131,17 +131,6 @@ void AbstractRenderer::drawJoint(bool drawline, bool drawname,
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
if (drawline)
|
||||
{
|
||||
irr_driver->getVideoDriver()->draw3DLine(jointpos,
|
||||
core::vector3df(0,0,0),
|
||||
color);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (joint->Children.size() == 0)
|
||||
{
|
||||
@@ -206,3 +195,10 @@ void AbstractRenderer::drawJoint(bool drawline, bool drawname,
|
||||
} //drawJoint
|
||||
|
||||
#endif //DEBUG
|
||||
|
||||
|
||||
AbstractRenderer::AbstractRenderer()
|
||||
{
|
||||
m_wireframe = false;
|
||||
m_mipviz = false;
|
||||
}
|
||||
|
||||
@@ -18,12 +18,17 @@
|
||||
#ifndef HEADER_ABSTRACT_RENDERER_HPP
|
||||
#define HEADER_ABSTRACT_RENDERER_HPP
|
||||
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include <irrlicht.h>
|
||||
#include <vector>
|
||||
|
||||
struct GlowData;
|
||||
|
||||
class AbstractRenderer
|
||||
{
|
||||
protected:
|
||||
bool m_wireframe;
|
||||
bool m_mipviz;
|
||||
|
||||
#ifdef DEBUG
|
||||
void drawDebugMeshes() const;
|
||||
@@ -34,9 +39,22 @@ protected:
|
||||
#endif
|
||||
|
||||
public:
|
||||
AbstractRenderer();
|
||||
virtual ~AbstractRenderer(){}
|
||||
|
||||
virtual void render(float dt) = 0;
|
||||
|
||||
virtual void renderScene(irr::scene::ICameraSceneNode * const camnode,
|
||||
unsigned pointlightcount, std::vector<GlowData>& glows,
|
||||
float dt, bool hasShadows, bool forceRTT) = 0;
|
||||
|
||||
virtual unsigned updateLightsInfo(irr::scene::ICameraSceneNode * const camnode,
|
||||
float dt) = 0;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
void toggleWireframe() { m_wireframe = !m_wireframe; }
|
||||
// ------------------------------------------------------------------------
|
||||
void toggleMipVisualization() { m_mipviz = !m_mipviz; }
|
||||
};
|
||||
|
||||
#endif //HEADER_ABSTRACT_RENDERER_HPP
|
||||
|
||||
@@ -48,7 +48,6 @@ void FixedPipelineRenderer::render(float dt)
|
||||
camera->activate();
|
||||
rg->preRenderCallback(camera); // adjusts start referee
|
||||
|
||||
//m_renderpass = ~0; //TODO: is it useful for fixed function pipeline?
|
||||
irr_driver->getSceneManager()->drawAll();
|
||||
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
@@ -25,6 +25,11 @@ class FixedPipelineRenderer: public AbstractRenderer
|
||||
public:
|
||||
|
||||
void render(float dt);
|
||||
void renderScene(irr::scene::ICameraSceneNode * const camnode,
|
||||
unsigned pointlightcount, std::vector<GlowData>& glows,
|
||||
float dt, bool hasShadows, bool forceRTT){}
|
||||
unsigned updateLightsInfo(irr::scene::ICameraSceneNode * const camnode,
|
||||
float dt){}
|
||||
};
|
||||
|
||||
#endif //HEADER_FIXED_PIPELINE_RENDERER_HPP
|
||||
|
||||
@@ -60,6 +60,7 @@ class RTT;
|
||||
class FrameBuffer;
|
||||
class ShadowImportanceProvider;
|
||||
class AbstractKart;
|
||||
class AbstractRenderer;
|
||||
class Camera;
|
||||
class PerCameraNode;
|
||||
class PostProcessing;
|
||||
@@ -178,6 +179,12 @@ enum TypeRTT
|
||||
RTT_COUNT
|
||||
};
|
||||
|
||||
|
||||
struct GlowData {
|
||||
scene::ISceneNode * node;
|
||||
float r, g, b;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief class that creates the irrLicht device and offers higher-level
|
||||
* ways to manage the 3D scene
|
||||
@@ -185,8 +192,11 @@ enum TypeRTT
|
||||
*/
|
||||
class IrrDriver : public IEventReceiver, public NoCopy
|
||||
{
|
||||
public:
|
||||
GLsync m_sync; //TODO: set public to fix compile error, find a clean fix
|
||||
|
||||
private:
|
||||
GLsync m_sync;
|
||||
//GLsync m_sync;
|
||||
/** The irrlicht device. */
|
||||
IrrlichtDevice *m_device;
|
||||
/** Irrlicht scene manager. */
|
||||
@@ -257,10 +267,7 @@ public:
|
||||
|
||||
video::SColorf getAmbientLight() const;
|
||||
|
||||
struct GlowData {
|
||||
scene::ISceneNode * node;
|
||||
float r, g, b;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
std::vector<VideoMode> m_modes;
|
||||
@@ -315,6 +322,7 @@ private:
|
||||
std::vector<irr::scene::IAnimatedMeshSceneNode*> m_debug_meshes;
|
||||
#endif
|
||||
|
||||
public: //TODO: move into renderer class
|
||||
void renderSolidFirstPass();
|
||||
void renderSolidSecondPass();
|
||||
void renderNormalsVisualisation();
|
||||
@@ -324,11 +332,8 @@ private:
|
||||
void renderRSM();
|
||||
void renderGlow(std::vector<GlowData>& glows);
|
||||
void renderSSAO();
|
||||
void renderLights(unsigned pointlightCount, bool hasShadow);
|
||||
void renderAmbientScatter();
|
||||
void renderLightsScatter(unsigned pointlightCount);
|
||||
void renderShadowsDebug();
|
||||
void doScreenShot();
|
||||
void doScreenShot();
|
||||
void PrepareDrawCalls(scene::ICameraSceneNode *camnode);
|
||||
public:
|
||||
IrrDriver();
|
||||
@@ -492,6 +497,8 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
RTT* getRTT() { return m_rtts; }
|
||||
// ------------------------------------------------------------------------
|
||||
AbstractRenderer* getRenderer() { return m_renderer; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a list of all video modes supports by the graphics card. */
|
||||
const std::vector<VideoMode>& getVideoModes() const { return m_modes; }
|
||||
// ------------------------------------------------------------------------
|
||||
@@ -559,10 +566,6 @@ public:
|
||||
m_boundingboxesviz = false;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void toggleWireframe() { m_wireframe = !m_wireframe; }
|
||||
// ------------------------------------------------------------------------
|
||||
void toggleMipVisualization() { m_mipviz = !m_mipviz; }
|
||||
// ------------------------------------------------------------------------
|
||||
void toggleNormals() { m_normals = !m_normals; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool getNormals() { return m_normals; }
|
||||
@@ -756,11 +759,6 @@ public:
|
||||
void onLoadWorld();
|
||||
void onUnloadWorld();
|
||||
|
||||
void renderScene(scene::ICameraSceneNode * const camnode,
|
||||
unsigned pointlightcount, std::vector<GlowData>& glows,
|
||||
float dt, bool hasShadows, bool forceRTT);
|
||||
unsigned updateLightsInfo(scene::ICameraSceneNode * const camnode,
|
||||
float dt);
|
||||
void updateSplitAndLightcoordRangeFromComputeShaders(size_t width,
|
||||
size_t height);
|
||||
void computeMatrixesAndCameras(scene::ICameraSceneNode * const camnode,
|
||||
|
||||
@@ -58,197 +58,6 @@ public:
|
||||
} // InstancedColorizeShader
|
||||
}; // InstancedColorizeShader
|
||||
|
||||
// ============================================================================
|
||||
void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned pointlightcount, std::vector<GlowData>& glows, float dt, bool hasShadow, bool forceRTT)
|
||||
{
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedGPUObjects::getViewProjectionMatricesUBO());
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 1, SharedGPUObjects::getLightingDataUBO());
|
||||
m_scene_manager->setActiveCamera(camnode);
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- Draw Call Generation", 0xFF, 0xFF, 0xFF);
|
||||
PrepareDrawCalls(camnode);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
// Shadows
|
||||
{
|
||||
// To avoid wrong culling, use the largest view possible
|
||||
m_scene_manager->setActiveCamera(getShadowMatrices()->getSunCam());
|
||||
if (CVS->isDefferedEnabled() &&
|
||||
CVS->isShadowEnabled() && hasShadow)
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Shadow", 0x30, 0x6F, 0x90);
|
||||
renderShadows();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
if (CVS->isGlobalIlluminationEnabled())
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- RSM", 0xFF, 0x0, 0xFF);
|
||||
renderRSM();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
}
|
||||
m_scene_manager->setActiveCamera(camnode);
|
||||
|
||||
}
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- Solid Pass 1", 0xFF, 0x00, 0x00);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_CULL_FACE);
|
||||
if (CVS->isDefferedEnabled() || forceRTT)
|
||||
{
|
||||
m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).bind();
|
||||
glClearColor(0., 0., 0., 0.);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
renderSolidFirstPass();
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need a cleared depth buffer for some effect (eg particles depth blending)
|
||||
if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_FRAMEBUFFER_SRGB_WORKING))
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).bind();
|
||||
// Bind() modifies the viewport. In order not to affect anything else,
|
||||
// the viewport is just reset here and not removed in Bind().
|
||||
const core::recti &vp = Camera::getActiveCamera()->getViewport();
|
||||
glViewport(vp.UpperLeftCorner.X,
|
||||
irr_driver->getActualScreenSize().Height - vp.LowerRightCorner.Y,
|
||||
vp.LowerRightCorner.X - vp.UpperLeftCorner.X,
|
||||
vp.LowerRightCorner.Y - vp.UpperLeftCorner.Y);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_FRAMEBUFFER_SRGB_WORKING))
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
|
||||
|
||||
// Lights
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Light", 0x00, 0xFF, 0x00);
|
||||
if (CVS->isDefferedEnabled())
|
||||
renderLights(pointlightcount, hasShadow);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
// Handle SSAO
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- SSAO", 0xFF, 0xFF, 0x00);
|
||||
ScopedGPUTimer Timer(getGPUTimer(Q_SSAO));
|
||||
if (UserConfigParams::m_ssao)
|
||||
renderSSAO();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- Solid Pass 2", 0x00, 0x00, 0xFF);
|
||||
if (CVS->isDefferedEnabled() || forceRTT)
|
||||
{
|
||||
m_rtts->getFBO(FBO_COLORS).bind();
|
||||
SColor clearColor(0, 150, 150, 150);
|
||||
if (World::getWorld() != NULL)
|
||||
clearColor = World::getWorld()->getClearColor();
|
||||
|
||||
glClearColor(clearColor.getRed() / 255.f, clearColor.getGreen() / 255.f,
|
||||
clearColor.getBlue() / 255.f, clearColor.getAlpha() / 255.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
renderSolidSecondPass();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
if (getNormals())
|
||||
{
|
||||
m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).bind();
|
||||
renderNormalsVisualisation();
|
||||
m_rtts->getFBO(FBO_COLORS).bind();
|
||||
}
|
||||
|
||||
// Render ambient scattering
|
||||
if (CVS->isDefferedEnabled() && World::getWorld() != NULL &&
|
||||
World::getWorld()->isFogEnabled())
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Ambient scatter", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(getGPUTimer(Q_FOG));
|
||||
renderAmbientScatter();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Skybox", 0xFF, 0x00, 0xFF);
|
||||
ScopedGPUTimer Timer(getGPUTimer(Q_SKYBOX));
|
||||
renderSkybox(camnode);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
// Render discrete lights scattering
|
||||
if (CVS->isDefferedEnabled() && World::getWorld() != NULL &&
|
||||
World::getWorld()->isFogEnabled())
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- PointLight Scatter", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(getGPUTimer(Q_FOG));
|
||||
renderLightsScatter(pointlightcount);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
if (getRH())
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
m_rtts->getFBO(FBO_COLORS).bind();
|
||||
m_post_processing->renderRHDebug(m_rtts->getRH().getRTT()[0],
|
||||
m_rtts->getRH().getRTT()[1],
|
||||
m_rtts->getRH().getRTT()[2],
|
||||
getShadowMatrices()->getRHMatrix(),
|
||||
getShadowMatrices()->getRHExtend());
|
||||
}
|
||||
|
||||
if (getGI())
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
m_rtts->getFBO(FBO_COLORS).bind();
|
||||
m_post_processing->renderGI(getShadowMatrices()->getRHMatrix(),
|
||||
getShadowMatrices()->getRHExtend(),
|
||||
m_rtts->getRH());
|
||||
}
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- Glow", 0xFF, 0xFF, 0x00);
|
||||
// Render anything glowing.
|
||||
if (!m_mipviz && !m_wireframe && UserConfigParams::m_glow)
|
||||
{
|
||||
ScopedGPUTimer Timer(getGPUTimer(Q_GLOW));
|
||||
irr_driver->setPhase(GLOW_PASS);
|
||||
renderGlow(glows);
|
||||
} // end glow
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
// Render transparent
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(getGPUTimer(Q_TRANSPARENT));
|
||||
renderTransparent();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
// Render particles
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Particles", 0xFF, 0xFF, 0x00);
|
||||
ScopedGPUTimer Timer(getGPUTimer(Q_PARTICLES));
|
||||
renderParticles();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
if (!CVS->isDefferedEnabled() && !forceRTT)
|
||||
{
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that no object will be drawn after that by using invalid pass
|
||||
irr_driver->setPhase(PASS_COUNT);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void IrrDriver::renderSkybox(const scene::ICameraSceneNode *camera)
|
||||
|
||||
@@ -34,375 +34,11 @@
|
||||
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN2(a, b) ((a) > (b) ? (b) : (a))
|
||||
|
||||
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
|
||||
|
||||
// ============================================================================
|
||||
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
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
unsigned IrrDriver::updateLightsInfo(scene::ICameraSceneNode * const camnode,
|
||||
float dt)
|
||||
{
|
||||
const u32 lightcount = (u32)m_lights.size();
|
||||
const core::vector3df &campos = camnode->getAbsolutePosition();
|
||||
|
||||
std::vector<LightNode *> BucketedLN[15];
|
||||
for (unsigned int i = 0; i < lightcount; i++)
|
||||
{
|
||||
if (!m_lights[i]->isVisible())
|
||||
continue;
|
||||
|
||||
if (!m_lights[i]->isPointLight())
|
||||
{
|
||||
m_lights[i]->render();
|
||||
continue;
|
||||
}
|
||||
const core::vector3df &lightpos =
|
||||
(m_lights[i]->getAbsolutePosition() - campos);
|
||||
unsigned idx = (unsigned)(lightpos.getLength() / 10);
|
||||
if (idx > 14)
|
||||
idx = 14;
|
||||
BucketedLN[idx].push_back(m_lights[i]);
|
||||
}
|
||||
|
||||
unsigned lightnum = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Upload lighting info to the dedicated uniform buffer
|
||||
@@ -428,107 +64,6 @@ void IrrDriver::uploadLightingData()
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, 36 * sizeof(float), Lighting);
|
||||
} // uploadLightingData
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
|
||||
{
|
||||
//RH
|
||||
if (CVS->isGlobalIlluminationEnabled() && hasShadow)
|
||||
{
|
||||
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_RH));
|
||||
glDisable(GL_BLEND);
|
||||
m_rtts->getRH().bind();
|
||||
glBindVertexArray(SharedGPUObjects::getFullScreenQuadVAO());
|
||||
if (CVS->needRHWorkaround())
|
||||
{
|
||||
NVWorkaroundRadianceHintsConstructionShader::getInstance()->use();
|
||||
NVWorkaroundRadianceHintsConstructionShader::getInstance()
|
||||
->setTextureUnits(
|
||||
m_rtts->getRSM().getRTT()[0],
|
||||
m_rtts->getRSM().getRTT()[1],
|
||||
m_rtts->getRSM().getDepthTexture());
|
||||
for (unsigned i = 0; i < 32; i++)
|
||||
{
|
||||
NVWorkaroundRadianceHintsConstructionShader::getInstance()
|
||||
->setUniforms(getShadowMatrices()->getRSMMatrix(),
|
||||
getShadowMatrices()->getRHMatrix(),
|
||||
getShadowMatrices()->getRHExtend(), i,
|
||||
irr_driver->getSunColor());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RadianceHintsConstructionShader::getInstance()->use();
|
||||
RadianceHintsConstructionShader::getInstance()
|
||||
->setTextureUnits(
|
||||
m_rtts->getRSM().getRTT()[0],
|
||||
m_rtts->getRSM().getRTT()[1],
|
||||
m_rtts->getRSM().getDepthTexture()
|
||||
);
|
||||
RadianceHintsConstructionShader::getInstance()
|
||||
->setUniforms(getShadowMatrices()->getRSMMatrix(),
|
||||
getShadowMatrices()->getRHMatrix(),
|
||||
getShadowMatrices()->getRHExtend(),
|
||||
irr_driver->getSunColor());
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32);
|
||||
}
|
||||
}
|
||||
getShadowMatrices()->updateSunOrthoMatrices();
|
||||
m_rtts->getFBO(FBO_COMBINED_DIFFUSE_SPECULAR).bind();
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
m_rtts->getFBO(FBO_DIFFUSE).bind();
|
||||
if (CVS->isGlobalIlluminationEnabled() && hasShadow)
|
||||
{
|
||||
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_GI));
|
||||
m_post_processing->renderGI(getShadowMatrices()->getRHMatrix(),
|
||||
getShadowMatrices()->getRHExtend(),
|
||||
m_rtts->getRH());
|
||||
}
|
||||
|
||||
m_rtts->getFBO(FBO_COMBINED_DIFFUSE_SPECULAR).bind();
|
||||
|
||||
{
|
||||
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_ENVMAP));
|
||||
if(m_skybox)
|
||||
{
|
||||
m_post_processing->renderEnvMap(m_skybox->getSpecularProbe());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_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(m_rtts);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShadowedSunLightShaderPCF::getInstance()->render(m_rtts);
|
||||
}
|
||||
}
|
||||
else
|
||||
m_post_processing->renderSunlight(irr_driver->getSunDirection(),
|
||||
irr_driver->getSunColor());
|
||||
}
|
||||
{
|
||||
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_POINTLIGHTS));
|
||||
renderPointLights(MIN2(pointlightcount, LightBaseClass::MAXLIGHT));
|
||||
}
|
||||
} // renderLights
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void IrrDriver::renderSSAO()
|
||||
@@ -546,73 +81,4 @@ void IrrDriver::renderSSAO()
|
||||
|
||||
} // renderSSAO
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void IrrDriver::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 IrrDriver::renderLightsScatter(unsigned pointlightcount)
|
||||
{
|
||||
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,
|
||||
MIN2(pointlightcount, LightBaseClass::MAXLIGHT));
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
m_post_processing->renderGaussian6Blur(getFBO(FBO_HALF1),
|
||||
getFBO(FBO_HALF2), 5., 5.);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
getFBO(FBO_COLORS).bind();
|
||||
m_post_processing->renderPassThrough(getRenderTargetTexture(RTT_HALF1),
|
||||
getFBO(FBO_COLORS).getWidth(),
|
||||
getFBO(FBO_COLORS).getHeight());
|
||||
} // renderLightsScatter
|
||||
|
||||
@@ -303,11 +303,11 @@ FrameBuffer* RTT::render(scene::ICameraSceneNode* camera, float dt)
|
||||
|
||||
irr_driver->getSceneManager()->setActiveCamera(camera);
|
||||
|
||||
std::vector<IrrDriver::GlowData> glows;
|
||||
std::vector<GlowData> glows;
|
||||
irr_driver->computeMatrixesAndCameras(camera, m_width, m_height);
|
||||
unsigned plc = irr_driver->updateLightsInfo(camera, dt);
|
||||
unsigned plc = irr_driver->getRenderer()->updateLightsInfo(camera, dt);
|
||||
irr_driver->uploadLightingData();
|
||||
irr_driver->renderScene(camera, plc, glows, dt, false, true);
|
||||
irr_driver->getRenderer()->renderScene(camera, plc, glows, dt, false, true);
|
||||
FrameBuffer* frame_buffer = irr_driver->getPostProcessing()->render(camera, false);
|
||||
|
||||
// reset
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "graphics/shader_based_renderer.hpp"
|
||||
|
||||
#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"
|
||||
@@ -36,6 +40,307 @@
|
||||
|
||||
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()
|
||||
{
|
||||
@@ -80,11 +385,11 @@ void ShaderBasedRenderer::setOverrideMaterial()
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<IrrDriver::GlowData> ShaderBasedRenderer::updateGlowingList()
|
||||
std::vector<GlowData> ShaderBasedRenderer::updateGlowingList()
|
||||
{
|
||||
// Get a list of all glowing things. The driver's list contains the static ones,
|
||||
// here we add items, as they may disappear each frame.
|
||||
std::vector<IrrDriver::GlowData> glows = irr_driver->getGlowingNodes();
|
||||
std::vector<GlowData> glows = irr_driver->getGlowingNodes();
|
||||
|
||||
ItemManager * const items = ItemManager::get();
|
||||
const u32 itemcount = items->getNumberOfItems();
|
||||
@@ -109,7 +414,7 @@ std::vector<IrrDriver::GlowData> ShaderBasedRenderer::updateGlowingList()
|
||||
scene::ISceneNode * const node = lod->getAllNodes()[level];
|
||||
node->updateAbsolutePosition();
|
||||
|
||||
IrrDriver::GlowData dat;
|
||||
GlowData dat;
|
||||
dat.node = node;
|
||||
|
||||
dat.r = 1.0f;
|
||||
@@ -141,6 +446,460 @@ void ShaderBasedRenderer::prepareForwardRenderer()
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
||||
// ============================================================================
|
||||
void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode, unsigned pointlightcount, std::vector<GlowData>& glows, float dt, bool hasShadow, bool forceRTT)
|
||||
{
|
||||
ShadowMatrices *shadow_matrices = irr_driver->getShadowMatrices();
|
||||
PostProcessing *post_processing = irr_driver->getPostProcessing();
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedGPUObjects::getViewProjectionMatricesUBO());
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 1, SharedGPUObjects::getLightingDataUBO());
|
||||
irr_driver->getSceneManager()->setActiveCamera(camnode);
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- Draw Call Generation", 0xFF, 0xFF, 0xFF);
|
||||
irr_driver->PrepareDrawCalls(camnode);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
// Shadows
|
||||
{
|
||||
// To avoid wrong culling, use the largest view possible
|
||||
irr_driver->getSceneManager()->setActiveCamera(shadow_matrices->getSunCam());
|
||||
if (CVS->isDefferedEnabled() &&
|
||||
CVS->isShadowEnabled() && hasShadow)
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Shadow", 0x30, 0x6F, 0x90);
|
||||
irr_driver->renderShadows();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
if (CVS->isGlobalIlluminationEnabled())
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- RSM", 0xFF, 0x0, 0xFF);
|
||||
irr_driver->renderRSM();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
}
|
||||
irr_driver->getSceneManager()->setActiveCamera(camnode);
|
||||
|
||||
}
|
||||
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- Solid Pass 1", 0xFF, 0x00, 0x00);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_CULL_FACE);
|
||||
RTT *rtts = irr_driver->getRTT();
|
||||
if (CVS->isDefferedEnabled() || forceRTT)
|
||||
{
|
||||
rtts->getFBO(FBO_NORMAL_AND_DEPTHS).bind();
|
||||
glClearColor(0., 0., 0., 0.);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
irr_driver->renderSolidFirstPass();
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need a cleared depth buffer for some effect (eg particles depth blending)
|
||||
if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_FRAMEBUFFER_SRGB_WORKING))
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
rtts->getFBO(FBO_NORMAL_AND_DEPTHS).bind();
|
||||
// Bind() modifies the viewport. In order not to affect anything else,
|
||||
// the viewport is just reset here and not removed in Bind().
|
||||
const core::recti &vp = Camera::getActiveCamera()->getViewport();
|
||||
glViewport(vp.UpperLeftCorner.X,
|
||||
irr_driver->getActualScreenSize().Height - vp.LowerRightCorner.Y,
|
||||
vp.LowerRightCorner.X - vp.UpperLeftCorner.X,
|
||||
vp.LowerRightCorner.Y - vp.UpperLeftCorner.Y);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_FRAMEBUFFER_SRGB_WORKING))
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
|
||||
|
||||
// Lights
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Light", 0x00, 0xFF, 0x00);
|
||||
if (CVS->isDefferedEnabled())
|
||||
renderLights(pointlightcount, hasShadow);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
// Handle SSAO
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- SSAO", 0xFF, 0xFF, 0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_SSAO));
|
||||
if (UserConfigParams::m_ssao)
|
||||
irr_driver->renderSSAO();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- Solid Pass 2", 0x00, 0x00, 0xFF);
|
||||
if (CVS->isDefferedEnabled() || forceRTT)
|
||||
{
|
||||
rtts->getFBO(FBO_COLORS).bind();
|
||||
video::SColor clearColor(0, 150, 150, 150);
|
||||
if (World::getWorld() != NULL)
|
||||
clearColor = World::getWorld()->getClearColor();
|
||||
|
||||
glClearColor(clearColor.getRed() / 255.f, clearColor.getGreen() / 255.f,
|
||||
clearColor.getBlue() / 255.f, clearColor.getAlpha() / 255.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
irr_driver->renderSolidSecondPass();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
if (irr_driver->getNormals())
|
||||
{
|
||||
rtts->getFBO(FBO_NORMAL_AND_DEPTHS).bind();
|
||||
irr_driver->renderNormalsVisualisation();
|
||||
rtts->getFBO(FBO_COLORS).bind();
|
||||
}
|
||||
|
||||
// Render ambient scattering
|
||||
if (CVS->isDefferedEnabled() && World::getWorld() != NULL &&
|
||||
World::getWorld()->isFogEnabled())
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Ambient scatter", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_FOG));
|
||||
renderAmbientScatter();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Skybox", 0xFF, 0x00, 0xFF);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_SKYBOX));
|
||||
irr_driver->renderSkybox(camnode);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
// Render discrete lights scattering
|
||||
if (CVS->isDefferedEnabled() && World::getWorld() != NULL &&
|
||||
World::getWorld()->isFogEnabled())
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- PointLight Scatter", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_FOG));
|
||||
renderLightsScatter(pointlightcount);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
if (irr_driver->getRH())
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
rtts->getFBO(FBO_COLORS).bind();
|
||||
post_processing->renderRHDebug(rtts->getRH().getRTT()[0],
|
||||
rtts->getRH().getRTT()[1],
|
||||
rtts->getRH().getRTT()[2],
|
||||
shadow_matrices->getRHMatrix(),
|
||||
shadow_matrices->getRHExtend());
|
||||
}
|
||||
|
||||
if (irr_driver->getGI())
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
rtts->getFBO(FBO_COLORS).bind();
|
||||
post_processing->renderGI(shadow_matrices->getRHMatrix(),
|
||||
shadow_matrices->getRHExtend(),
|
||||
rtts->getRH());
|
||||
}
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("- Glow", 0xFF, 0xFF, 0x00);
|
||||
// Render anything glowing.
|
||||
if (!m_mipviz && !m_wireframe && UserConfigParams::m_glow)
|
||||
{
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_GLOW));
|
||||
irr_driver->setPhase(GLOW_PASS);
|
||||
irr_driver->renderGlow(glows);
|
||||
} // end glow
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
// Render transparent
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_TRANSPARENT));
|
||||
irr_driver->renderTransparent();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
irr_driver->m_sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
// Render particles
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Particles", 0xFF, 0xFF, 0x00);
|
||||
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_PARTICLES));
|
||||
irr_driver->renderParticles();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
if (!CVS->isDefferedEnabled() && !forceRTT)
|
||||
{
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that no object will be drawn after that by using invalid pass
|
||||
irr_driver->setPhase(PASS_COUNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ShaderBasedRenderer::renderBoundingBoxes()
|
||||
{
|
||||
Shaders::ColoredLine *line = Shaders::ColoredLine::getInstance();
|
||||
@@ -235,10 +994,9 @@ void ShaderBasedRenderer::renderPostProcessing(Camera * const camera)
|
||||
}
|
||||
}
|
||||
|
||||
ShaderBasedRenderer::ShaderBasedRenderer()
|
||||
|
||||
ShaderBasedRenderer::ShaderBasedRenderer():AbstractRenderer()
|
||||
{
|
||||
m_wireframe = false;
|
||||
m_mipviz = false;
|
||||
}
|
||||
|
||||
void ShaderBasedRenderer::render(float dt)
|
||||
@@ -249,7 +1007,7 @@ void ShaderBasedRenderer::render(float dt)
|
||||
|
||||
setOverrideMaterial(); //TODO: is it useful every frame?
|
||||
|
||||
std::vector<IrrDriver::GlowData> glows = updateGlowingList();
|
||||
std::vector<GlowData> glows = updateGlowingList();
|
||||
|
||||
// Start the RTT for post-processing.
|
||||
// We do this before beginScene() because we want to capture the glClear()
|
||||
@@ -286,13 +1044,13 @@ void ShaderBasedRenderer::render(float dt)
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("Update Light Info", 0xFF, 0x0, 0x0);
|
||||
unsigned plc = irr_driver->updateLightsInfo(camnode, dt); //TODO: move updateLightsInfo method
|
||||
unsigned plc = updateLightsInfo(camnode, dt); //TODO: replace plc by a more explicit name
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
PROFILER_PUSH_CPU_MARKER("UBO upload", 0x0, 0xFF, 0x0);
|
||||
irr_driver->computeMatrixesAndCameras(camnode, viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y);
|
||||
irr_driver->uploadLightingData(); //TODO: move method; update "global" lighting (sun and spherical harmonics)
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
irr_driver->renderScene(camnode, plc, glows, dt, track->hasShadows(), false); //TODO: move renderScene method in renderer class
|
||||
renderScene(camnode, plc, glows, dt, track->hasShadows(), false);
|
||||
|
||||
if (irr_driver->getBoundingBoxesViz())
|
||||
{
|
||||
|
||||
@@ -19,21 +19,22 @@
|
||||
#define HEADER_LIGHT_PREPASS_RENDERER_HPP
|
||||
|
||||
#include "graphics/abstract_renderer.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
|
||||
|
||||
class ShaderBasedRenderer: public AbstractRenderer
|
||||
{
|
||||
private:
|
||||
bool m_wireframe;
|
||||
bool m_mipviz;
|
||||
|
||||
|
||||
void compressPowerUpTextures();
|
||||
void setOverrideMaterial();
|
||||
std::vector<IrrDriver::GlowData> updateGlowingList();
|
||||
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);
|
||||
void renderBoundingBoxes();
|
||||
void debugPhysics();
|
||||
void renderPostProcessing(Camera * const camera);
|
||||
|
||||
@@ -319,7 +319,7 @@ bool onEvent(const SEvent &event)
|
||||
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
|
||||
|
||||
irr_driver->resetDebugModes();
|
||||
irr_driver->toggleWireframe();
|
||||
irr_driver->getRenderer()->toggleWireframe();
|
||||
}
|
||||
else if (cmdID == DEBUG_GRAPHICS_MIPMAP_VIZ)
|
||||
{
|
||||
@@ -327,7 +327,7 @@ bool onEvent(const SEvent &event)
|
||||
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
|
||||
|
||||
irr_driver->resetDebugModes();
|
||||
irr_driver->toggleMipVisualization();
|
||||
irr_driver->getRenderer()->toggleMipVisualization();
|
||||
}
|
||||
else if (cmdID == DEBUG_GRAPHICS_NORMALS_VIZ)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user