Implement scattering for point light

This commit is contained in:
Vincent Lejeune 2014-11-08 19:47:08 +01:00
parent 8ac0bd6793
commit 09fa1ee3cb
6 changed files with 126 additions and 1 deletions

View File

@ -0,0 +1,46 @@
uniform sampler2D dtex;
uniform float density;
uniform vec3 fogcol;
flat in vec3 center;
flat in float energy;
flat in vec3 col;
flat in float radius;
out vec4 Fog;
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
void main()
{
vec4 pseudocenter = ViewMatrix * vec4(center.xyz, 1.0);
pseudocenter /= pseudocenter.w;
vec3 light_pos = pseudocenter.xyz;
vec3 light_col = col.xyz;
// Compute pixel position
vec2 texc = 2. * gl_FragCoord.xy / screen;
float z = texture(dtex, texc).x;
vec4 pixelpos = getPosFromUVDepth(vec3(texc, z), InverseProjectionMatrix);
vec3 eyedir = -normalize(pixelpos.xyz);
vec3 farthestpoint = - eyedir * (min(dot(-eyedir, light_pos) + radius, length(pixelpos.xyz)));
vec3 closestpoint = - eyedir * (dot(-eyedir, light_pos) - radius);
if (closestpoint.z < 1.) closestpoint = vec3(0.);
float stepsize = length(farthestpoint - closestpoint) / 16;
vec3 fog = vec3(0.);
vec3 xpos = farthestpoint;
for (int i = 0; i < 16; i++)
{
float d = distance(light_pos, xpos);
float l = (16 - i) * stepsize;
float att = energy * 20. / (1. + d * d);
att *= max((radius - d) / radius, 0.);
fog += density * light_col * att * exp(- density * d) * exp(- density * l) * stepsize;
xpos += stepsize * eyedir;
}
Fog = vec4(fogcol * fog, 1.);
}

View File

@ -408,6 +408,7 @@ private:
void renderGlow(std::vector<GlowData>& glows);
void renderSSAO();
void renderLights(unsigned pointlightCount, bool hasShadow);
void renderLightsScatter(unsigned pointlightCount);
void renderShadowsDebug();
void doScreenShot();
void PrepareDrawCalls(scene::ICameraSceneNode *camnode);

View File

@ -420,7 +420,7 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po
World::getWorld()->isFogEnabled())
{
PROFILER_PUSH_CPU_MARKER("- Fog", 0xFF, 0x00, 0x00);
m_post_processing->renderFog();
renderLightsScatter(pointlightcount);
PROFILER_POP_CPU_MARKER();
}

View File

@ -185,3 +185,38 @@ void IrrDriver::renderSSAO()
m_post_processing->renderGaussian17TapBlur(irr_driver->getFBO(FBO_HALF1_R), irr_driver->getFBO(FBO_HALF2_R));
}
void IrrDriver::renderLightsScatter(unsigned pointlightcount)
{
getFBO(FBO_HALF1).Bind();
glClearColor(0., 0., 0., 0.);
glClear(GL_COLOR_BUFFER_BIT);
m_post_processing->renderFog();
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
const Track * const track = World::getWorld()->getTrack();
const float start = track->getFogStart();
const video::SColor tmpcol = track->getFogColor();
core::vector3df col(1., 1., 1.);
glUseProgram(LightShader::PointLightScatterShader::getInstance()->Program);
glBindVertexArray(LightShader::PointLightScatterShader::getInstance()->vao);
LightShader::PointLightScatterShader::getInstance()->SetTextureUnits(irr_driver->getDepthStencilTexture());
LightShader::PointLightScatterShader::getInstance()->setUniforms(1. / (40. * start), col);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, pointlightcount);
glDisable(GL_BLEND);
m_post_processing->renderGaussian6Blur(getFBO(FBO_HALF1), getFBO(FBO_HALF2), 5., 5.);
glEnable(GL_BLEND);
getFBO(FBO_COLORS).Bind();
m_post_processing->renderPassThrough(getRenderTargetTexture(RTT_HALF1));
}

View File

@ -1468,6 +1468,41 @@ namespace LightShader
glVertexAttribDivisorARB(attrib_Color, 1);
glVertexAttribDivisorARB(attrib_Radius, 1);
}
PointLightScatterShader::PointLightScatterShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/pointlight.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/pointlightscatter.frag").c_str());
AssignUniforms("density", "fogcol");
AssignSamplerNames(Program, 0, "dtex");
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, PointLightShader::getInstance()->vbo);
GLuint attrib_Position = glGetAttribLocation(Program, "Position");
GLuint attrib_Color = glGetAttribLocation(Program, "Color");
GLuint attrib_Energy = glGetAttribLocation(Program, "Energy");
GLuint attrib_Radius = glGetAttribLocation(Program, "Radius");
glEnableVertexAttribArray(attrib_Position);
glVertexAttribPointer(attrib_Position, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), 0);
glEnableVertexAttribArray(attrib_Energy);
glVertexAttribPointer(attrib_Energy, 1, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(3 * sizeof(float)));
glEnableVertexAttribArray(attrib_Color);
glVertexAttribPointer(attrib_Color, 3, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(4 * sizeof(float)));
glEnableVertexAttribArray(attrib_Radius);
glVertexAttribPointer(attrib_Radius, 1, GL_FLOAT, GL_FALSE, sizeof(PointLightInfo), (GLvoid*)(7 * sizeof(float)));
glVertexAttribDivisorARB(attrib_Position, 1);
glVertexAttribDivisorARB(attrib_Energy, 1);
glVertexAttribDivisorARB(attrib_Color, 1);
glVertexAttribDivisorARB(attrib_Radius, 1);
}
}

View File

@ -328,6 +328,14 @@ namespace LightShader
GLuint vao;
PointLightShader();
};
class PointLightScatterShader : public ShaderHelperSingleton<PointLightScatterShader, float, core::vector3df>, public TextureRead<Nearest_Filtered>
{
public:
GLuint vbo;
GLuint vao;
PointLightScatterShader();
};
}
namespace ParticleShader