Add GI support

This commit is contained in:
vlj 2014-05-21 21:44:00 +02:00 committed by Vincent Lejeune
parent 5caf028a71
commit af16682a9e
6 changed files with 207 additions and 4 deletions

101
data/shaders/gi.frag Normal file
View File

@ -0,0 +1,101 @@
// From http://graphics.cs.aueb.gr/graphics/research_illumination.html
// "Real-Time Diffuse Global Illumination Using Radiance Hints"
// paper and shader code
uniform sampler2D ntex;
uniform sampler2D dtex;
uniform sampler3D SHR;
uniform sampler3D SHG;
uniform sampler3D SHB;
uniform float R_wcs = 10.;
uniform vec3 extents;
uniform mat4 RHMatrix;
layout (std140) uniform MatrixesData
{
mat4 ViewMatrix;
mat4 ProjectionMatrix;
mat4 InverseViewMatrix;
mat4 InverseProjectionMatrix;
mat4 ShadowViewProjMatrixes[4];
vec2 screen;
};
vec4 SHBasis (const in vec3 dir)
{
float L00 = 0.282095;
float L1_1 = 0.488603 * dir.y;
float L10 = 0.488603 * dir.z;
float L11 = 0.488603 * dir.x;
return vec4 (L11, L1_1, L10, L00);
}
vec3 SH2RGB (in vec4 sh_r, in vec4 sh_g, in vec4 sh_b, in vec3 dir)
{
vec4 Y = vec4(1.023326*dir.x, 1.023326*dir.y, 1.023326*dir.z, 0.886226);
return vec3 (dot(Y,sh_r), dot(Y,sh_g), dot(Y,sh_b));
}
in vec2 uv;
layout (location = 0) out vec4 Diffuse;
layout (location = 1) out vec4 Specular;
vec3 DecodeNormal(vec2 n);
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
vec3 resolution = vec3(32, 16, 32);
void main()
{
vec3 GI = vec3(0.);
float depth = texture2D(dtex, uv).x;
// Discard background fragments
if (depth==1.0) discard;
vec4 pos_screen_space = getPosFromUVDepth(vec3(uv, depth), InverseProjectionMatrix);
vec4 tmp = (inverse(RHMatrix) * InverseViewMatrix * pos_screen_space);
vec3 pos = tmp.xyz / tmp.w;
vec3 normal_screen_space = normalize(DecodeNormal(2. * texture(ntex, uv).xy - 1.));
vec3 normal = (transpose(ViewMatrix) * vec4(normal_screen_space, 0.)).xyz;
// Convert to grid coordinates
vec3 uvw = .5 + 0.5 * pos / extents;
if (uvw.x < 0. || uvw.x > 1. || uvw.y < 0. || uvw.y > 1. || uvw.z < 0. || uvw.z > 1.) discard;
// Sample the RH volume at 4 locations, one directly above the shaded point,
// three on a ring 80degs away from the normal direction.
vec3 rnd = vec3(0,0,0);
// Generate the sample locations
vec3 v_rand = vec3(0.5);
vec3 tangent = normalize(cross(normal, v_rand));
vec3 bitangent = cross(normal, tangent);
vec3 D[4];
D[0] = vec3(1.0,0.0,0.0);
int i;
for (i=1; i<4; i++)
{
D[i] = vec3(0.1, 0.8*cos((rnd.x*1.5+i)*6.2832/3.0), 0.8*sin((rnd.x*1.5+i)*6.2832/3.0));
D[i] = normalize(D[i]);
}
for (i=0; i<4; i++)
{
vec3 SampleDir = normal * D[i].x + tangent * D[i].y + bitangent *D[i].z;
vec3 SampleOffset = (0.5 * normal + SampleDir) / resolution;
vec3 uvw_new = uvw + SampleOffset;
vec4 IncidentSHR = texture(SHR, uvw_new);
vec4 IncidentSHG = texture(SHG, uvw_new);
vec4 IncidentSHB = texture(SHB, uvw_new);
GI += SH2RGB(IncidentSHR, IncidentSHG, IncidentSHB, -normal);
}
GI /= 4;
Diffuse = max(16. * vec4(GI, 1.), vec4(0.));
Specular = vec4(0.);
}

View File

@ -261,6 +261,35 @@ void PostProcessing::renderDiffuseEnvMap(const float *bSHCoeff, const float *gSH
glDisable(GL_BLEND);
}
void PostProcessing::renderGI(const core::matrix4 &RHMatrix, const core::vector3df &rh_extend, GLuint shr, GLuint shg, GLuint shb)
{
glDisable(GL_DEPTH_TEST);
glUseProgram(FullScreenShader::GlobalIlluminationReconstructionShader::Program);
glBindVertexArray(FullScreenShader::GlobalIlluminationReconstructionShader::vao);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, shr);
{
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_3D, shg);
{
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_3D, shb);
{
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
setTexture(3, irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), GL_NEAREST, GL_NEAREST);
setTexture(4, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST);
FullScreenShader::GlobalIlluminationReconstructionShader::setUniforms(RHMatrix, rh_extend, 3, 4, 0, 1, 2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
void PostProcessing::renderSunlight()
{
SunLightProvider * const cb = (SunLightProvider *) irr_driver->getCallback(ES_SUNLIGHT);

View File

@ -81,6 +81,7 @@ public:
void renderFog();
void renderSSAO();
void renderDiffuseEnvMap(const float *bSHCoeff, const float *gSHCoeff, const float *rSHCoeff);
void renderGI(const core::matrix4 &RHMatrix, const core::vector3df &rh_extend, unsigned shr, unsigned shg, unsigned shb);
/** Blur the in texture */
void renderGaussian3Blur(FrameBuffer &in_fbo, FrameBuffer &auxiliary);

View File

@ -323,6 +323,28 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, std::vector
renderSkybox(camnode);
PROFILER_POP_CPU_MARKER();
if (getRH())
{
glEnable(GL_PROGRAM_POINT_SIZE);
m_rtts->getFBO(FBO_COLORS).Bind();
glUseProgram(FullScreenShader::RHDebug::Program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, m_rtts->getRH().getRTT()[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_3D, m_rtts->getRH().getRTT()[1]);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_3D, m_rtts->getRH().getRTT()[2]);
FullScreenShader::RHDebug::setUniforms(rh_extend, 0, 1, 2);
glDrawArrays(GL_POINTS, 0, 128 * 128 * 128);
glDisable(GL_PROGRAM_POINT_SIZE);
}
if (getGI())
{
m_rtts->getFBO(FBO_COLORS).Bind();
m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]);
}
PROFILER_PUSH_CPU_MARKER("- Glow", 0xFF, 0xFF, 0x00);
// Render anything glowing.
if (!m_mipviz && !m_wireframe && UserConfigParams::m_glow)
@ -895,10 +917,9 @@ void IrrDriver::renderLights(scene::ICameraSceneNode * const camnode, float dt)
glClearColor(.5, .5, .5, .5);
glClear(GL_COLOR_BUFFER_BIT);
if (!UserConfigParams::m_dynamic_lights)
{
//gl_driver->extGlDrawBuffers(1, bufs);
return;
}
m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]);
if (SkyboxCubeMap)
irr_driver->getSceneManager()->setAmbientLight(SColor(0, 0, 0, 0));
@ -974,7 +995,6 @@ void IrrDriver::renderLights(scene::ICameraSceneNode * const camnode, float dt)
renderPointLights(MIN2(lightnum, MAXLIGHT));
if (SkyboxCubeMap)
m_post_processing->renderDiffuseEnvMap(blueSHCoeff, greenSHCoeff, redSHCoeff);
// gl_driver->extGlDrawBuffers(1, bufs);
}
void IrrDriver::renderSSAO()

View File

@ -282,6 +282,7 @@ void Shaders::loadShaders()
FullScreenShader::ShadowedSunLightShader::init();
FullScreenShader::ShadowedSunLightDebugShader::init();
FullScreenShader::RadianceHintsConstructionShader::init();
FullScreenShader::GlobalIlluminationReconstructionShader::init();
FullScreenShader::MotionBlurShader::init();
FullScreenShader::GodFadeShader::init();
FullScreenShader::GodRayShader::init();
@ -2351,6 +2352,46 @@ namespace FullScreenShader
glUniform3f(uniform_extents, extents.X, extents.Y, extents.Z);
}
GLuint GlobalIlluminationReconstructionShader::Program;
GLuint GlobalIlluminationReconstructionShader::uniform_ntex;
GLuint GlobalIlluminationReconstructionShader::uniform_dtex;
GLuint GlobalIlluminationReconstructionShader::uniform_SHR;
GLuint GlobalIlluminationReconstructionShader::uniform_SHG;
GLuint GlobalIlluminationReconstructionShader::uniform_SHB;
GLuint GlobalIlluminationReconstructionShader::uniform_extents;
GLuint GlobalIlluminationReconstructionShader::uniform_RHMatrix;
GLuint GlobalIlluminationReconstructionShader::vao;
void GlobalIlluminationReconstructionShader::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/gi.frag").c_str());
uniform_ntex = glGetUniformLocation(Program, "ntex");
uniform_dtex = glGetUniformLocation(Program, "dtex");
uniform_SHR = glGetUniformLocation(Program, "SHR");
uniform_SHG = glGetUniformLocation(Program, "SHG");
uniform_SHB = glGetUniformLocation(Program, "SHB");
uniform_RHMatrix = glGetUniformLocation(Program, "RHMatrix");
uniform_extents = glGetUniformLocation(Program, "extents");
vao = createVAO(Program);
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0);
}
void GlobalIlluminationReconstructionShader::setUniforms(const core::matrix4 &RHMatrix, const core::vector3df &extents, unsigned TU_ntex, unsigned TU_dtex, unsigned TU_SHR, unsigned TU_SHG, unsigned TU_SHB)
{
glUniformMatrix4fv(uniform_RHMatrix, 1, GL_FALSE, RHMatrix.pointer());
glUniform1i(uniform_ntex, TU_ntex);
glUniform1i(uniform_dtex, TU_dtex);
glUniform1i(uniform_SHR, TU_SHR);
glUniform1i(uniform_SHG, TU_SHG);
glUniform1i(uniform_SHB, TU_SHB);
glUniform3f(uniform_extents, extents.X, extents.Y, extents.Z);
}
GLuint Gaussian17TapHShader::Program;
GLuint Gaussian17TapHShader::uniform_tex;
GLuint Gaussian17TapHShader::uniform_pixel;

View File

@ -620,6 +620,17 @@ public:
static void setUniforms(const core::matrix4 &RSMMatrix, const core::matrix4 &RHMatrix, const core::vector3df &extents, unsigned TU_ctex, unsigned TU_ntex, unsigned TU_dtex);
};
class GlobalIlluminationReconstructionShader
{
public:
static GLuint Program;
static GLuint uniform_ntex, uniform_dtex, uniform_extents, uniform_SHR, uniform_SHG, uniform_SHB, uniform_RHMatrix;
static GLuint vao;
static void init();
static void setUniforms(const core::matrix4 &RHMatrix, const core::vector3df &extents, unsigned TU_ntex, unsigned TU_dtex, unsigned TU_SHR, unsigned TU_SHG, unsigned TU_SHB);
};
class Gaussian17TapHShader
{
public: