Merge branch 'master' of https://github.com/supertuxkart/stk-code into lights

This commit is contained in:
konstin
2015-01-01 23:05:26 +01:00
38 changed files with 614 additions and 534 deletions

View File

@@ -1,13 +1,7 @@
uniform sampler2D tex;
#if __VERSION__ >= 130
in vec2 uv;
out vec4 FragColor;
#else
varying vec2 uv;
#define FragColor gl_FragColor
#endif
void main(void)
{

View File

@@ -8,13 +8,8 @@ uniform vec3 inlevel;
uniform vec2 outlevel;
uniform mat4 invprojm;
#if __VERSION__ >= 130
in vec2 uv;
out vec4 FragColor;
#else
varying vec2 uv;
#define FragColor gl_FragColor
#endif
#define PI 3.14159265

View File

@@ -1,11 +1,6 @@
uniform ivec4 color;
#if __VERSION__ >= 130
out vec4 FragColor;
#else
#define FragColor gl_FragColor
#endif
void main()
{

View File

@@ -1,11 +1,6 @@
uniform vec3 col;
#if __VERSION__ >= 130
out vec4 FragColor;
#else
#define FragColor gl_FragColor
#endif
void main()
{

View File

@@ -1,16 +1,8 @@
uniform sampler2D tex;
#if __VERSION__ >= 130
in vec2 uv;
in vec4 col;
out vec4 FragColor;
#else
varying vec2 uv;
varying vec4 col;
#define FragColor gl_FragColor
#endif
void main()
{

View File

@@ -8,15 +8,9 @@ uniform sampler2D Detail;
uniform sampler2D SpecMap;
#endif
#if __VERSION__ >= 130
in vec2 uv;
in vec2 uv_bis;
out vec4 FragColor;
#else
varying vec2 uv;
varying vec2 uv_bis;
#define FragColor gl_FragColor
#endif
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue, float emitMapValue);

View File

@@ -5,18 +5,11 @@ uniform sampler2D tex;
uniform vec2 dir;
uniform vec2 dir2;
#if __VERSION__ >= 130
in vec2 uv;
in vec2 uv_bis;
in float camdist;
out vec4 FragColor;
#else
varying vec2 uv;
varying vec2 uv_bis;
varying float camdist;
#define FragColor gl_FragColor
#endif
const float maxlen = 0.02;

View File

@@ -1,12 +1,7 @@
uniform sampler2D tex;
#if __VERSION__ >= 130
in vec2 uv;
out vec4 FragColor;
#else
varying vec2 uv;
#define FragColor gl_FragColor
#endif
void main()
{

View File

@@ -1,13 +1,8 @@
uniform sampler2D tex;
uniform vec3 col;
#if __VERSION__ >= 130
in vec2 uv;
out vec4 FragColor;
#else
varying vec2 uv;
#define FragColor gl_FragColor
#endif
void main()
{

View File

@@ -5,13 +5,8 @@ uniform vec2 sunpos;
const float decaystep = 0.88;
#if __VERSION__ >= 130
in vec2 uv;
out vec4 FragColor;
#else
varying vec2 uv;
#define FragColor gl_FragColor
#endif
void main()
{

View File

@@ -4,14 +4,9 @@ layout(bindless_sampler) uniform sampler2D tex;
uniform sampler2D tex;
#endif
#if __VERSION__ >= 130
in vec3 nor;
in vec2 uv;
out vec3 EncodedNormal;
#else
varying vec3 nor;
#define EncodedNormal gl_FragColor.xy
#endif
vec2 EncodeNormal(vec3 n);

View File

@@ -6,13 +6,8 @@ layout(bindless_sampler) uniform sampler2D tex;
uniform sampler2D tex;
#endif
#if __VERSION__ >= 130
in vec3 nor;
out vec4 FragColor;
#else
varying vec3 nor;
#define FragColor gl_FragColor
#endif
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue, float emitMapValue);

View File

@@ -6,15 +6,9 @@ uniform sampler2D tex;
uniform sampler2D glosstex;
#endif
#if __VERSION__ >= 130
in vec3 nor;
in vec2 uv;
out vec3 EncodedNormal;
#else
varying vec3 nor;
varying vec2 uv;
#define EncodedNormal gl_FragColor.xy
#endif
vec2 EncodeNormal(vec3 n);

View File

@@ -1,11 +1,6 @@
uniform samplerCube tex;
#if __VERSION__ >= 130
out vec4 FragColor;
#else
#define FragColor gl_FragColor
#endif
void main(void)
{

View File

@@ -12,15 +12,9 @@ uniform sampler2D tex_detail2;
uniform sampler2D tex_detail3;
#endif
#if __VERSION__ >= 130
in vec2 uv;
in vec2 uv_bis;
out vec4 FragColor;
#else
varying vec2 uv;
varying vec2 uv_bis;
#define FragColor gl_FragColor
#endif
vec3 getLightFactor(vec3 diffuseMatColor, vec3 specularMatColor, float specMapValue, float emitMapValue);

View File

@@ -1,6 +1,6 @@
uniform sampler2D ntex;
uniform sampler2D dtex;
uniform sampler2DArray shadowtex;
uniform sampler2DArrayShadow shadowtex;
uniform float split0;
uniform float split1;
@@ -22,10 +22,17 @@ float getShadowFactor(vec3 pos, int index)
vec4 shadowcoord = (ShadowViewProjMatrixes[index] * InverseViewMatrix * vec4(pos, 1.0));
shadowcoord.xy /= shadowcoord.w;
vec2 shadowtexcoord = shadowcoord.xy * 0.5 + 0.5;
float d = .5 * shadowcoord.z + .5;
float z = texture(shadowtex, vec3(shadowtexcoord, float(index))).x;
float d = shadowcoord.z;
return min(pow(exp(-32. * d) * z, 8.), 1.);
float result = 0.;
for (float i = -1.; i <= 1.; i += 1.)
{
for (float j = -1.; j <= 1.; j += 1.)
result += texture(shadowtex, vec4(shadowtexcoord + vec2(i,j) / 1024., float(index), d));
}
return result / 9.;
}
void main() {

View File

@@ -0,0 +1,61 @@
uniform sampler2D ntex;
uniform sampler2D dtex;
uniform sampler2DArray shadowtex;
uniform float split0;
uniform float split1;
uniform float split2;
uniform float splitmax;
in vec2 uv;
out vec4 Diff;
out vec4 Spec;
vec3 DecodeNormal(vec2 n);
vec3 SpecularBRDF(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness);
vec3 DiffuseBRDF(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness);
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
vec3 SunMRP(vec3 normal, vec3 eyedir);
float getShadowFactor(vec3 pos, int index)
{
vec4 shadowcoord = (ShadowViewProjMatrixes[index] * InverseViewMatrix * vec4(pos, 1.0));
shadowcoord.xy /= shadowcoord.w;
vec2 shadowtexcoord = shadowcoord.xy * 0.5 + 0.5;
float z = texture(shadowtex, vec3(shadowtexcoord, float(index))).x;
float d = shadowcoord.z;
return min(pow(exp(-32. * d) * z, 8.), 1.);
}
void main() {
vec2 uv = gl_FragCoord.xy / screen;
float z = texture(dtex, uv).x;
vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix);
vec3 norm = normalize(DecodeNormal(2. * texture(ntex, uv).xy - 1.));
float roughness =texture(ntex, uv).z;
vec3 eyedir = -normalize(xpos.xyz);
vec3 Lightdir = SunMRP(norm, eyedir);
float NdotL = clamp(dot(norm, Lightdir), 0., 1.);
vec3 Specular = SpecularBRDF(norm, eyedir, Lightdir, vec3(1.), roughness);
vec3 Diffuse = DiffuseBRDF(norm, eyedir, Lightdir, vec3(1.), roughness);
// Shadows
float factor;
if (xpos.z < split0)
factor = getShadowFactor(xpos.xyz, 0);
else if (xpos.z < split1)
factor = getShadowFactor(xpos.xyz, 1);
else if (xpos.z < split2)
factor = getShadowFactor(xpos.xyz, 2);
else if (xpos.z < splitmax)
factor = getShadowFactor(xpos.xyz, 3);
else
factor = 1.;
Diff = vec4(factor * NdotL * Diffuse * sun_col, 1.);
Spec = vec4(factor * NdotL * Specular * sun_col, 1.);
}

View File

@@ -1,13 +1,7 @@
uniform sampler2D tex;
#if __VERSION__ >= 130
in vec2 uv;
out vec4 FragColor;
#else
varying vec2 uv;
#define FragColor gl_FragColor
#endif
void main()
{

View File

@@ -1,13 +1,8 @@
uniform sampler2D tex;
uniform ivec4 color;
#if __VERSION__ >= 130
in vec2 uv;
out vec4 FragColor;
#else
varying vec2 uv;
#define FragColor gl_FragColor
#endif
void main()
{

View File

@@ -1,11 +1,6 @@
#if __VERSION__ >= 130
in vec4 color;
out vec4 FragColor;
#else
varying vec4 color;
#define FragColor gl_FragColor
#endif
vec3 getLightFactor(float specMapValue);

View File

@@ -1,9 +1,4 @@
#if __VERSION__ >= 130
out vec4 FragColor;
#else
#define FragColor gl_FragColor
#endif
void main()
{

View File

@@ -4651,7 +4651,7 @@ IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RE
pixels = static_cast<u8*>(newImage->lock());
if (pixels)
{
GLenum tgt=GL_FRONT;
GLenum tgt=GL_BACK;
switch (target)
{
case video::ERT_FRAME_BUFFER:

View File

@@ -470,6 +470,9 @@ namespace UserConfigParams
PARAM_PREFIX BoolUserConfigParam m_sdsm
PARAM_DEFAULT(BoolUserConfigParam(false, "enable_sdsm",
&m_video_group, "Enable Sampled Distribued Shadow Map (buggy atm)"));
PARAM_PREFIX BoolUserConfigParam m_esm
PARAM_DEFAULT(BoolUserConfigParam(false, "enable_esm",
&m_video_group, "Enable Exponential Shadow Map (better but slower)"));
// ---- Debug - not saved to config file
/** If gamepad debugging is enabled. */

View File

@@ -309,4 +309,10 @@ bool CentralVideoSettings::isSDSMEnabled() const
bool CentralVideoSettings::isAZDOEnabled() const
{
return supportsIndirectInstancingRendering() && isARBBindlessTextureUsable() && isARBMultiDrawIndirectUsable() && UserConfigParams::m_azdo;
}
// Switch between Exponential Shadow Map (better but slower filtering) and Percentage Closer Filtering (faster but with some stability issue)
bool CentralVideoSettings::isESMEnabled() const
{
return UserConfigParams::m_esm;
}

View File

@@ -65,6 +65,7 @@ public:
bool isTextureCompressionEnabled() const;
bool isSDSMEnabled() const;
bool isAZDOEnabled() const;
bool isESMEnabled() const;
};
extern CentralVideoSettings* CVS;

View File

@@ -727,7 +727,8 @@ public:
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 computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height);
void computeMatrixesAndCameras(scene::ICameraSceneNode * const camnode, size_t width, size_t height);
void uploadLightingData();
// --------------------- OLD RTT --------------------
/**

View File

@@ -271,19 +271,6 @@ void PostProcessing::renderSunlight(const core::vector3df &direction, const vide
DrawFullScreenEffect<FullScreenShader::SunLightShader>(direction, col);
}
extern float shadowSplit[5];
void PostProcessing::renderShadowedSunlight(const core::vector3df &direction, const video::SColorf &col, const std::vector<core::matrix4> &sun_ortho_matrix, GLuint depthtex)
{
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_ONE, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
FullScreenShader::ShadowedSunLightShader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), depthtex);
DrawFullScreenEffect<FullScreenShader::ShadowedSunLightShader>(shadowSplit[1], shadowSplit[2], shadowSplit[3], shadowSplit[4], direction, col);
}
static
std::vector<float> getGaussianWeight(float sigma, size_t count)
{

View File

@@ -75,7 +75,6 @@ public:
/** Generate diffuse and specular map */
void renderSunlight(const core::vector3df &direction, const video::SColorf &col);
void renderShadowedSunlight(const core::vector3df &direction, const video::SColorf &col, const std::vector<core::matrix4> &sun_ortho_matrix, unsigned depthtex);
void renderSSAO();
void renderEnvMap(const float *bSHCoeff, const float *gSHCoeff, const float *rSHCoeff, unsigned skycubemap);

View File

@@ -32,15 +32,10 @@
#include "items/item_manager.hpp"
#include "modes/world.hpp"
#include "physics/physics.hpp"
#include "physics/triangle_mesh.hpp"
#include "tracks/track.hpp"
#include "utils/profiler.hpp"
#include "stkscenemanager.hpp"
#include "items/powerup_manager.hpp"
#include "../../lib/irrlicht/source/Irrlicht/CSceneManager.h"
#include "../../lib/irrlicht/source/Irrlicht/os.h"
#include <limits>
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
#define MIN2(a, b) ((a) > (b) ? (b) : (a))
@@ -187,8 +182,9 @@ void IrrDriver::renderGLSL(float dt)
PROFILER_PUSH_CPU_MARKER("Update Light Info", 0xFF, 0x0, 0x0);
unsigned plc = UpdateLightsInfo(camnode, dt);
PROFILER_POP_CPU_MARKER();
PROFILER_PUSH_CPU_MARKER("Compute camera matrix", 0x0, 0xFF, 0x0);
computeCameraMatrix(camnode, viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y);
PROFILER_PUSH_CPU_MARKER("UBO upload", 0x0, 0xFF, 0x0);
computeMatrixesAndCameras(camnode, viewport.LowerRightCorner.X - viewport.UpperLeftCorner.X, viewport.LowerRightCorner.Y - viewport.UpperLeftCorner.Y);
uploadLightingData();
PROFILER_POP_CPU_MARKER();
renderScene(camnode, plc, glows, dt, track->hasShadows(), false);
@@ -595,393 +591,6 @@ void IrrDriver::renderParticles()
// m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT_EFFECT);
}
/** Given a matrix transform and a set of points returns an orthogonal projection matrix that maps coordinates of
transformed points between -1 and 1.
* \param transform a transform matrix.
* \param pointsInside a vector of point in 3d space.
* \param size returns the size (width, height) of shadowmap coverage
*/
core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, const std::vector<vector3df> &pointsInside, std::pair<float, float> &size)
{
float xmin = std::numeric_limits<float>::infinity();
float xmax = -std::numeric_limits<float>::infinity();
float ymin = std::numeric_limits<float>::infinity();
float ymax = -std::numeric_limits<float>::infinity();
float zmin = std::numeric_limits<float>::infinity();
float zmax = -std::numeric_limits<float>::infinity();
for (unsigned i = 0; i < pointsInside.size(); i++)
{
vector3df TransformedVector;
transform.transformVect(TransformedVector, pointsInside[i]);
xmin = MIN2(xmin, TransformedVector.X);
xmax = MAX2(xmax, TransformedVector.X);
ymin = MIN2(ymin, TransformedVector.Y);
ymax = MAX2(ymax, TransformedVector.Y);
zmin = MIN2(zmin, TransformedVector.Z);
zmax = MAX2(zmax, TransformedVector.Z);
}
float left = xmin;
float right = xmax;
float up = ymin;
float down = ymax;
size.first = right - left;
size.second = down - up;
core::matrix4 tmp_matrix;
// Prevent Matrix without extend
if (left == right || up == down)
return tmp_matrix;
tmp_matrix.buildProjectionMatrixOrthoLH(left, right,
down, up,
zmin - 100, zmax);
return tmp_matrix;
}
float shadowSplit[5] = {1., 5., 20., 50., 150 };
struct CascadeBoundingBox
{
int xmin;
int xmax;
int ymin;
int ymax;
int zmin;
int zmax;
};
static size_t currentCBB = 0;
static CascadeBoundingBox *CBB[2];
struct Histogram
{
int bin[1024];
int mindepth;
int maxdepth;
int count;
};
/** Update shadowSplit values and make Cascade Bounding Box pointer valid.
* The function aunches two compute kernel that generates an histogram of the depth buffer value (between 0 and 250 with increment of 0.25)
* and get an axis aligned bounding box (from SunCamMatrix view) containing all depth buffer value.
* It also retrieves the result from the previous computations (in a Round Robin fashion) and update CBB pointer.
* \param width of the depth buffer
* \param height of the depth buffer
* TODO : The depth histogram part is commented out, needs to tweak it when I have some motivation
*/
void IrrDriver::UpdateSplitAndLightcoordRangeFromComputeShaders(size_t width, size_t height)
{
// Value that should be kept between multiple calls
static GLuint ssbo[2];
static Histogram *Hist[2];
static GLsync LightcoordBBFence = 0;
static size_t currentHist = 0;
static GLuint ssboSplit[2];
static float tmpshadowSplit[5] = { 1., 5., 20., 50., 150. };
if (!LightcoordBBFence)
{
glGenBuffers(2, ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[0]);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(CascadeBoundingBox), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
CBB[0] = (CascadeBoundingBox *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(CascadeBoundingBox), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[1]);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(CascadeBoundingBox), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
CBB[1] = (CascadeBoundingBox *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(CascadeBoundingBox), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
/* glGenBuffers(2, ssboSplit);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboSplit[0]);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(Histogram), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
Hist[0] = (Histogram *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Histogram), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboSplit[1]);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(Histogram), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
Hist[1] = (Histogram *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Histogram), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);*/
}
// Use bounding boxes from last frame
if (LightcoordBBFence)
{
while (glClientWaitSync(LightcoordBBFence, GL_SYNC_FLUSH_COMMANDS_BIT, 0) != GL_ALREADY_SIGNALED);
glDeleteSync(LightcoordBBFence);
}
/* {
memcpy(shadowSplit, tmpshadowSplit, 5 * sizeof(float));
unsigned numpix = Hist[currentHist]->count;
unsigned split = 0;
unsigned i;
for (i = 0; i < 1022; i++)
{
split += Hist[currentHist]->bin[i];
if (split > numpix / 2)
break;
}
tmpshadowSplit[1] = (float)++i / 4.;
for (; i < 1023; i++)
{
split += Hist[currentHist]->bin[i];
if (split > 3 * numpix / 4)
break;
}
tmpshadowSplit[2] = (float)++i / 4.;
for (; i < 1024; i++)
{
split += Hist[currentHist]->bin[i];
if (split > 7 * numpix / 8)
break;
}
tmpshadowSplit[3] = (float)++i / 4.;
for (; i < 1024; i++)
{
split += Hist[currentHist]->bin[i];
}
tmpshadowSplit[0] = (float)(Hist[currentHist]->bin[1024] - 1) / 4.;
tmpshadowSplit[4] = (float)(Hist[currentHist]->bin[1025] + 1) / 4.;
printf("numpix is %d\n", numpix);
printf("total : %d\n", split);
printf("split 0 : %f\n", tmpshadowSplit[1]);
printf("split 1 : %f\n", tmpshadowSplit[2]);
printf("split 2 : %f\n", tmpshadowSplit[3]);
printf("min %f max %f\n", tmpshadowSplit[0], tmpshadowSplit[4]);
currentHist = (currentHist + 1) % 2;
}*/
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo[currentCBB]);
// glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboSplit[currentHist]);
for (unsigned i = 0; i < 4; i++)
{
CBB[currentCBB][i].xmin = CBB[currentCBB][i].ymin = CBB[currentCBB][i].zmin = 1000;
CBB[currentCBB][i].xmax = CBB[currentCBB][i].ymax = CBB[currentCBB][i].zmax = -1000;
}
// memset(Hist[currentHist], 0, sizeof(Histogram));
// Hist[currentHist]->mindepth = 3000;
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
glUseProgram(FullScreenShader::LightspaceBoundingBoxShader::getInstance()->Program);
FullScreenShader::LightspaceBoundingBoxShader::getInstance()->SetTextureUnits(getDepthStencilTexture());
FullScreenShader::LightspaceBoundingBoxShader::getInstance()->setUniforms(m_suncam->getViewMatrix(), tmpshadowSplit[1], tmpshadowSplit[2], tmpshadowSplit[3], tmpshadowSplit[4]);
glDispatchCompute((int)width / 64, (int)height / 64, 1);
/* glUseProgram(FullScreenShader::DepthHistogramShader::getInstance()->Program);
FullScreenShader::DepthHistogramShader::getInstance()->SetTextureUnits(getDepthStencilTexture());
FullScreenShader::DepthHistogramShader::getInstance()->setUniforms();
glDispatchCompute((int)width / 32, (int)height / 32, 1);*/
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
LightcoordBBFence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
currentCBB = (currentCBB + 1) % 2;
}
void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height)
{
if (CVS->isSDSMEnabled())
UpdateSplitAndLightcoordRangeFromComputeShaders(width, height);
static_cast<scene::CSceneManager *>(m_scene_manager)->OnAnimate(os::Timer::getTime());
camnode->render();
irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION));
irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
irr_driver->genProjViewMatrix();
m_current_screen_size = core::vector2df(float(width), float(height));
const float oldfar = camnode->getFarValue();
const float oldnear = camnode->getNearValue();
float FarValues[] =
{
shadowSplit[1],
shadowSplit[2],
shadowSplit[3],
shadowSplit[4],
};
float NearValues[] =
{
shadowSplit[0],
shadowSplit[1],
shadowSplit[2],
shadowSplit[3]
};
float tmp[16 * 9 + 2];
memcpy(tmp, irr_driver->getViewMatrix().pointer(), 16 * sizeof(float));
memcpy(&tmp[16], irr_driver->getProjMatrix().pointer(), 16 * sizeof(float));
memcpy(&tmp[32], irr_driver->getInvViewMatrix().pointer(), 16 * sizeof(float));
memcpy(&tmp[48], irr_driver->getInvProjMatrix().pointer(), 16 * sizeof(float));
memcpy(&tmp[64], irr_driver->getProjViewMatrix().pointer(), 16 * sizeof(float));
m_suncam->render();
for (unsigned i = 0; i < 4; i++)
{
if (m_shadow_camnodes[i])
delete m_shadow_camnodes[i];
m_shadow_camnodes[i] = (scene::ICameraSceneNode *) m_suncam->clone();
}
const core::matrix4 &SunCamViewMatrix = m_suncam->getViewMatrix();
sun_ortho_matrix.clear();
if (World::getWorld() && World::getWorld()->getTrack())
{
btVector3 btmin, btmax;
if (World::getWorld()->getTrack()->getPtrTriangleMesh())
{
World::getWorld()->getTrack()->getTriangleMesh().getCollisionShape().getAabb(btTransform::getIdentity(), btmin, btmax);
}
const Vec3 vmin = btmin , vmax = btmax;
// Build the 3 ortho projection (for the 3 shadow resolution levels)
for (unsigned i = 0; i < 4; i++)
{
if (!CVS->isSDSMEnabled())
{
camnode->setFarValue(FarValues[i]);
camnode->setNearValue(NearValues[i]);
camnode->render();
}
const scene::SViewFrustum *frustrum = camnode->getViewFrustum();
float tmp[24] = {
frustrum->getFarLeftDown().X,
frustrum->getFarLeftDown().Y,
frustrum->getFarLeftDown().Z,
frustrum->getFarLeftUp().X,
frustrum->getFarLeftUp().Y,
frustrum->getFarLeftUp().Z,
frustrum->getFarRightDown().X,
frustrum->getFarRightDown().Y,
frustrum->getFarRightDown().Z,
frustrum->getFarRightUp().X,
frustrum->getFarRightUp().Y,
frustrum->getFarRightUp().Z,
frustrum->getNearLeftDown().X,
frustrum->getNearLeftDown().Y,
frustrum->getNearLeftDown().Z,
frustrum->getNearLeftUp().X,
frustrum->getNearLeftUp().Y,
frustrum->getNearLeftUp().Z,
frustrum->getNearRightDown().X,
frustrum->getNearRightDown().Y,
frustrum->getNearRightDown().Z,
frustrum->getNearRightUp().X,
frustrum->getNearRightUp().Y,
frustrum->getNearRightUp().Z,
};
memcpy(m_shadows_cam[i], tmp, 24 * sizeof(float));
const core::aabbox3df smallcambox = camnode->
getViewFrustum()->getBoundingBox();
core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
core::vector3df(0, 30, 0));
// Set up a nice ortho projection that contains our camera frustum
core::aabbox3df box = smallcambox;
box = box.intersect(trackbox);
std::vector<vector3df> vectors;
vectors.push_back(frustrum->getFarLeftDown());
vectors.push_back(frustrum->getFarLeftUp());
vectors.push_back(frustrum->getFarRightDown());
vectors.push_back(frustrum->getFarRightUp());
vectors.push_back(frustrum->getNearLeftDown());
vectors.push_back(frustrum->getNearLeftUp());
vectors.push_back(frustrum->getNearRightDown());
vectors.push_back(frustrum->getNearRightUp());
core::matrix4 tmp_matrix;
if (CVS->isSDSMEnabled()){
float left = float(CBB[currentCBB][i].xmin / 4 - 2);
float right = float(CBB[currentCBB][i].xmax / 4 + 2);
float up = float(CBB[currentCBB][i].ymin / 4 - 2);
float down = float(CBB[currentCBB][i].ymax / 4 + 2);
// Prevent Matrix without extend
if (left != right && up != down)
{
tmp_matrix.buildProjectionMatrixOrthoLH(left, right,
down, up,
float(CBB[currentCBB][i].zmin / 4 - 100),
float(CBB[currentCBB][i].zmax / 4 + 2));
m_shadow_scales[i] = std::make_pair(right - left, down - up);
}
}
else
tmp_matrix = getTighestFitOrthoProj(SunCamViewMatrix, vectors, m_shadow_scales[i]);
m_shadow_camnodes[i]->setProjectionMatrix(tmp_matrix , true);
m_shadow_camnodes[i]->render();
sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW));
}
if (!m_rsm_matrix_initialized)
{
core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
core::vector3df(0, 30, 0));
if (trackbox.MinEdge.X != trackbox.MaxEdge.X &&
trackbox.MinEdge.Y != trackbox.MaxEdge.Y &&
// Cover the case where SunCamViewMatrix is null
SunCamViewMatrix.getScale() != core::vector3df(0., 0., 0.))
{
SunCamViewMatrix.transformBoxEx(trackbox);
core::matrix4 tmp_matrix;
tmp_matrix.buildProjectionMatrixOrthoLH(trackbox.MinEdge.X, trackbox.MaxEdge.X,
trackbox.MaxEdge.Y, trackbox.MinEdge.Y,
30, trackbox.MaxEdge.Z);
m_suncam->setProjectionMatrix(tmp_matrix, true);
m_suncam->render();
}
rsm_matrix = getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW);
m_rsm_matrix_initialized = true;
m_rsm_map_available = false;
}
rh_extend = core::vector3df(128, 64, 128);
core::vector3df campos = camnode->getAbsolutePosition();
core::vector3df translation(8 * floor(campos.X / 8), 8 * floor(campos.Y / 8), 8 * floor(campos.Z / 8));
rh_matrix.setTranslation(translation);
assert(sun_ortho_matrix.size() == 4);
camnode->setNearValue(oldnear);
camnode->setFarValue(oldfar);
camnode->render();
size_t size = irr_driver->getShadowViewProj().size();
for (unsigned i = 0; i < size; i++)
memcpy(&tmp[16 * i + 80], irr_driver->getShadowViewProj()[i].pointer(), 16 * sizeof(float));
}
tmp[144] = float(width);
tmp[145] = float(height);
glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::ViewProjectionMatrixesUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, (16 * 9 + 2) * sizeof(float), tmp);
float Lighting[36];
Lighting[0] = m_sundirection.X;
Lighting[1] = m_sundirection.Y;
Lighting[2] = m_sundirection.Z;
Lighting[4] = m_suncolor.getRed();
Lighting[5] = m_suncolor.getGreen();
Lighting[6] = m_suncolor.getBlue();
Lighting[7] = 0.54f;
memcpy(&Lighting[8], blueSHCoeff, 9 * sizeof(float));
memcpy(&Lighting[17], greenSHCoeff, 9 * sizeof(float));
memcpy(&Lighting[26], redSHCoeff, 9 * sizeof(float));
glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::LightingDataUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, 36 * sizeof(float), Lighting);
}
static void renderWireFrameFrustrum(float *tmp, unsigned i)
{
glUseProgram(MeshShader::ViewFrustrumShader::getInstance()->Program);

View File

@@ -979,8 +979,12 @@ void IrrDriver::renderShadows()
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
m_rtts->getShadowFBO().Bind();
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.5, 0.);
if (!CVS->isESMEnabled())
{
glDrawBuffer(GL_NONE);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.5, 0.);
}
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
@@ -1026,6 +1030,7 @@ void IrrDriver::renderShadows()
glDisable(GL_POLYGON_OFFSET_FILL);
if (CVS->isESMEnabled())
{
ScopedGPUTimer Timer(getGPUTimer(Q_SHADOW_POSTPROCESS));
@@ -1039,8 +1044,8 @@ void IrrDriver::renderShadows()
}
}
glBindTexture(GL_TEXTURE_2D_ARRAY, m_rtts->getShadowFBO().getRTT()[0]);
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
}
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
}

View File

@@ -106,6 +106,29 @@ unsigned IrrDriver::UpdateLightsInfo(scene::ICameraSceneNode * const camnode, fl
return lightnum;
}
/** Upload lighting info to the dedicated uniform buffer
*/
void IrrDriver::uploadLightingData()
{
float Lighting[36];
Lighting[0] = m_sundirection.X;
Lighting[1] = m_sundirection.Y;
Lighting[2] = m_sundirection.Z;
Lighting[4] = m_suncolor.getRed();
Lighting[5] = m_suncolor.getGreen();
Lighting[6] = m_suncolor.getBlue();
Lighting[7] = 0.54f;
memcpy(&Lighting[8], blueSHCoeff, 9 * sizeof(float));
memcpy(&Lighting[17], greenSHCoeff, 9 * sizeof(float));
memcpy(&Lighting[26], redSHCoeff, 9 * sizeof(float));
glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::LightingDataUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, 36 * sizeof(float), Lighting);
}
extern float shadowSplit[5];
void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
{
//RH
@@ -163,7 +186,23 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
{
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_SUN));
if (World::getWorld() && CVS->isShadowEnabled() && hasShadow)
m_post_processing->renderShadowedSunlight(irr_driver->getSunDirection(), irr_driver->getSunColor(), sun_ortho_matrix, m_rtts->getShadowFBO().getRTT()[0]);
{
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_ONE, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
if (CVS->isESMEnabled())
{
FullScreenShader::ShadowedSunLightShaderESM::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), m_rtts->getShadowFBO().getRTT()[0]);
DrawFullScreenEffect<FullScreenShader::ShadowedSunLightShaderESM>(shadowSplit[1], shadowSplit[2], shadowSplit[3], shadowSplit[4], irr_driver->getSunDirection(), irr_driver->getSunColor());
}
else
{
FullScreenShader::ShadowedSunLightShaderPCF::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), m_rtts->getShadowFBO().getDepthTexture());
DrawFullScreenEffect<FullScreenShader::ShadowedSunLightShaderPCF>(shadowSplit[1], shadowSplit[2], shadowSplit[3], shadowSplit[4], irr_driver->getSunDirection(), irr_driver->getSunColor());
}
}
else
m_post_processing->renderSunlight(irr_driver->getSunDirection(), irr_driver->getSunColor());
}

View File

@@ -319,8 +319,9 @@ FrameBuffer* RTT::render(scene::ICameraSceneNode* camera, float dt)
std::vector<IrrDriver::GlowData> glows;
// TODO: put this outside of the rendering loop
irr_driver->generateDiffuseCoefficients();
irr_driver->computeCameraMatrix(camera, m_width, m_height);
irr_driver->computeMatrixesAndCameras(camera, m_width, m_height);
unsigned plc = irr_driver->UpdateLightsInfo(camera, dt);
irr_driver->uploadLightingData();
irr_driver->renderScene(camera, plc, glows, dt, false, true);
FrameBuffer* frame_buffer = irr_driver->getPostProcessing()->render(camera, false);

View File

@@ -863,10 +863,8 @@ GLuint createShadowSampler()
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int aniso = UserConfigParams::m_anisotropic;
if (aniso == 0) aniso = 1;
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
glSamplerParameterf(id, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glSamplerParameterf(id, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
return id;
#endif
}
@@ -883,6 +881,38 @@ void BindTextureShadow(GLuint TU, GLuint tex)
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
}
GLuint createTrilinearClampedArray()
{
#ifdef GL_VERSION_3_3
unsigned id;
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int aniso = UserConfigParams::m_anisotropic;
if (aniso == 0) aniso = 1;
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
return id;
#endif
}
void BindTrilinearClampedArrayTexture(unsigned TU, unsigned tex)
{
glActiveTexture(GL_TEXTURE0 + TU);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int aniso = UserConfigParams::m_anisotropic;
if (aniso == 0) aniso = 1;
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
}
void BindTextureVolume(GLuint TU, GLuint tex)
{
glActiveTexture(GL_TEXTURE0 + TU);
@@ -1659,7 +1689,7 @@ namespace FullScreenShader
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 2, "probe");
}
ShadowedSunLightShader::ShadowedSunLightShader()
ShadowedSunLightShaderPCF::ShadowedSunLightShaderPCF()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
@@ -1675,6 +1705,22 @@ namespace FullScreenShader
AssignUniforms("split0", "split1", "split2", "splitmax", "direction", "col");
}
ShadowedSunLightShaderESM::ShadowedSunLightShaderESM()
{
Program = LoadProgram(OBJECT,
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/SpecularBRDF.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/DiffuseBRDF.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/SunMRP.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sunlightshadowesm.frag").c_str());
// Use 8 to circumvent a catalyst bug when binding sampler
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 8, "shadowtex");
AssignUniforms("split0", "split1", "split2", "splitmax", "direction", "col");
}
RadianceHintsConstructionShader::RadianceHintsConstructionShader()
{
if (CVS->isAMDVertexShaderLayerUsable())

View File

@@ -426,10 +426,16 @@ public:
IBLShader();
};
class ShadowedSunLightShader : public ShaderHelperSingleton<ShadowedSunLightShader, float, float, float, float, core::vector3df, video::SColorf>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Shadow_Sampler>
class ShadowedSunLightShaderPCF : public ShaderHelperSingleton<ShadowedSunLightShaderPCF, float, float, float, float, core::vector3df, video::SColorf>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Shadow_Sampler>
{
public:
ShadowedSunLightShader();
ShadowedSunLightShaderPCF();
};
class ShadowedSunLightShaderESM : public ShaderHelperSingleton<ShadowedSunLightShaderESM, float, float, float, float, core::vector3df, video::SColorf>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Trilinear_Clamped_Array2D>
{
public:
ShadowedSunLightShaderESM();
};
class RadianceHintsConstructionShader : public ShaderHelperSingleton<RadianceHintsConstructionShader, core::matrix4, core::matrix4, core::vector3df, video::SColorf>, public TextureRead<Bilinear_Filtered, Bilinear_Filtered, Bilinear_Filtered>

View File

@@ -221,6 +221,7 @@ enum SamplerType {
Shadow_Sampler,
Volume_Linear_Filtered,
Trilinear_cubemap,
Trilinear_Clamped_Array2D,
};
void setTextureSampler(GLenum, GLuint, GLuint, GLuint);
@@ -486,6 +487,33 @@ struct BindTexture<Shadow_Sampler, tp...>
}
};
GLuint createTrilinearClampedArray();
template<SamplerType...tp>
struct CreateSamplers<Trilinear_Clamped_Array2D, tp...>
{
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
{
v.push_back(createTrilinearClampedArray());
e.push_back(GL_TEXTURE_2D_ARRAY);
CreateSamplers<tp...>::exec(v, e);
}
};
void BindTrilinearClampedArrayTexture(unsigned TU, unsigned tex);
template<SamplerType...tp>
struct BindTexture<Trilinear_Clamped_Array2D, tp...>
{
template <int N, typename...Args>
static void exec(const std::vector<unsigned> &TU, GLuint TexId, Args... args)
{
BindTrilinearClampedArrayTexture(TU[N], TexId);
BindTexture<tp...>::template exec<N + 1>(TU, args...);
}
};
template<SamplerType...tp>
class TextureRead
{

View File

@@ -0,0 +1,388 @@
#include <limits>
#include <ICameraSceneNode.h>
#include <SViewFrustum.h>
#include "../../lib/irrlicht/source/Irrlicht/CSceneManager.h"
#include "../../lib/irrlicht/source/Irrlicht/os.h"
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/shaders.hpp"
#include "modes/world.hpp"
#include "physics/triangle_mesh.hpp"
#include "tracks/track.hpp"
#define MAX2(a, b) ((a) > (b) ? (a) : (b))
#define MIN2(a, b) ((a) > (b) ? (b) : (a))
static std::vector<vector3df>
getFrustrumVertex(const scene::SViewFrustum &frustrum)
{
std::vector<vector3df> vectors;
vectors.push_back(frustrum.getFarLeftDown());
vectors.push_back(frustrum.getFarLeftUp());
vectors.push_back(frustrum.getFarRightDown());
vectors.push_back(frustrum.getFarRightUp());
vectors.push_back(frustrum.getNearLeftDown());
vectors.push_back(frustrum.getNearLeftUp());
vectors.push_back(frustrum.getNearRightDown());
vectors.push_back(frustrum.getNearRightUp());
return vectors;
}
/** Given a matrix transform and a set of points returns an orthogonal projection matrix that maps coordinates of
transformed points between -1 and 1.
* \param transform a transform matrix.
* \param pointsInside a vector of point in 3d space.
* \param size returns the size (width, height) of shadowmap coverage
*/
static core::matrix4
getTighestFitOrthoProj(const core::matrix4 &transform, const std::vector<vector3df> &pointsInside, std::pair<float, float> &size)
{
float xmin = std::numeric_limits<float>::infinity();
float xmax = -std::numeric_limits<float>::infinity();
float ymin = std::numeric_limits<float>::infinity();
float ymax = -std::numeric_limits<float>::infinity();
float zmin = std::numeric_limits<float>::infinity();
float zmax = -std::numeric_limits<float>::infinity();
for (unsigned i = 0; i < pointsInside.size(); i++)
{
vector3df TransformedVector;
transform.transformVect(TransformedVector, pointsInside[i]);
xmin = MIN2(xmin, TransformedVector.X);
xmax = MAX2(xmax, TransformedVector.X);
ymin = MIN2(ymin, TransformedVector.Y);
ymax = MAX2(ymax, TransformedVector.Y);
zmin = MIN2(zmin, TransformedVector.Z);
zmax = MAX2(zmax, TransformedVector.Z);
}
float left = xmin;
float right = xmax;
float up = ymin;
float down = ymax;
size.first = right - left;
size.second = down - up;
core::matrix4 tmp_matrix;
// Prevent Matrix without extend
if (left == right || up == down)
return tmp_matrix;
tmp_matrix.buildProjectionMatrixOrthoLH(left, right,
down, up,
zmin - 100, zmax);
return tmp_matrix;
}
float shadowSplit[5] = { 1., 5., 20., 50., 150 };
struct CascadeBoundingBox
{
int xmin;
int xmax;
int ymin;
int ymax;
int zmin;
int zmax;
};
static size_t currentCBB = 0;
static CascadeBoundingBox *CBB[2];
struct Histogram
{
int bin[1024];
int mindepth;
int maxdepth;
int count;
};
/** Update shadowSplit values and make Cascade Bounding Box pointer valid.
* The function aunches two compute kernel that generates an histogram of the depth buffer value (between 0 and 250 with increment of 0.25)
* and get an axis aligned bounding box (from SunCamMatrix view) containing all depth buffer value.
* It also retrieves the result from the previous computations (in a Round Robin fashion) and update CBB pointer.
* \param width of the depth buffer
* \param height of the depth buffer
* TODO : The depth histogram part is commented out, needs to tweak it when I have some motivation
*/
void IrrDriver::UpdateSplitAndLightcoordRangeFromComputeShaders(size_t width, size_t height)
{
// Value that should be kept between multiple calls
static GLuint ssbo[2];
static Histogram *Hist[2];
static GLsync LightcoordBBFence = 0;
static size_t currentHist = 0;
static GLuint ssboSplit[2];
static float tmpshadowSplit[5] = { 1., 5., 20., 50., 150. };
if (!LightcoordBBFence)
{
glGenBuffers(2, ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[0]);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(CascadeBoundingBox), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
CBB[0] = (CascadeBoundingBox *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(CascadeBoundingBox), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[1]);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(CascadeBoundingBox), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
CBB[1] = (CascadeBoundingBox *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(CascadeBoundingBox), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
/* glGenBuffers(2, ssboSplit);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboSplit[0]);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(Histogram), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
Hist[0] = (Histogram *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Histogram), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboSplit[1]);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(Histogram), 0, GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
Hist[1] = (Histogram *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Histogram), GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);*/
}
// Use bounding boxes from last frame
if (LightcoordBBFence)
{
while (glClientWaitSync(LightcoordBBFence, GL_SYNC_FLUSH_COMMANDS_BIT, 0) != GL_ALREADY_SIGNALED);
glDeleteSync(LightcoordBBFence);
}
/* {
memcpy(shadowSplit, tmpshadowSplit, 5 * sizeof(float));
unsigned numpix = Hist[currentHist]->count;
unsigned split = 0;
unsigned i;
for (i = 0; i < 1022; i++)
{
split += Hist[currentHist]->bin[i];
if (split > numpix / 2)
break;
}
tmpshadowSplit[1] = (float)++i / 4.;
for (; i < 1023; i++)
{
split += Hist[currentHist]->bin[i];
if (split > 3 * numpix / 4)
break;
}
tmpshadowSplit[2] = (float)++i / 4.;
for (; i < 1024; i++)
{
split += Hist[currentHist]->bin[i];
if (split > 7 * numpix / 8)
break;
}
tmpshadowSplit[3] = (float)++i / 4.;
for (; i < 1024; i++)
{
split += Hist[currentHist]->bin[i];
}
tmpshadowSplit[0] = (float)(Hist[currentHist]->bin[1024] - 1) / 4.;
tmpshadowSplit[4] = (float)(Hist[currentHist]->bin[1025] + 1) / 4.;
printf("numpix is %d\n", numpix);
printf("total : %d\n", split);
printf("split 0 : %f\n", tmpshadowSplit[1]);
printf("split 1 : %f\n", tmpshadowSplit[2]);
printf("split 2 : %f\n", tmpshadowSplit[3]);
printf("min %f max %f\n", tmpshadowSplit[0], tmpshadowSplit[4]);
currentHist = (currentHist + 1) % 2;
}*/
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo[currentCBB]);
// glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboSplit[currentHist]);
for (unsigned i = 0; i < 4; i++)
{
CBB[currentCBB][i].xmin = CBB[currentCBB][i].ymin = CBB[currentCBB][i].zmin = 1000;
CBB[currentCBB][i].xmax = CBB[currentCBB][i].ymax = CBB[currentCBB][i].zmax = -1000;
}
// memset(Hist[currentHist], 0, sizeof(Histogram));
// Hist[currentHist]->mindepth = 3000;
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
glUseProgram(FullScreenShader::LightspaceBoundingBoxShader::getInstance()->Program);
FullScreenShader::LightspaceBoundingBoxShader::getInstance()->SetTextureUnits(getDepthStencilTexture());
FullScreenShader::LightspaceBoundingBoxShader::getInstance()->setUniforms(m_suncam->getViewMatrix(), tmpshadowSplit[1], tmpshadowSplit[2], tmpshadowSplit[3], tmpshadowSplit[4]);
glDispatchCompute((int)width / 64, (int)height / 64, 1);
/* glUseProgram(FullScreenShader::DepthHistogramShader::getInstance()->Program);
FullScreenShader::DepthHistogramShader::getInstance()->SetTextureUnits(getDepthStencilTexture());
FullScreenShader::DepthHistogramShader::getInstance()->setUniforms();
glDispatchCompute((int)width / 32, (int)height / 32, 1);*/
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
LightcoordBBFence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
currentCBB = (currentCBB + 1) % 2;
}
/** Generate View, Projection, Inverse View, Inverse Projection, ViewProjection and InverseProjection matrixes
and matrixes and cameras for the four shadow cascade and RSM.
* \param camnode point of view used
* \param width of the rendering viewport
* \param height of the rendering viewport
*/
void IrrDriver::computeMatrixesAndCameras(scene::ICameraSceneNode * const camnode, size_t width, size_t height)
{
if (CVS->isSDSMEnabled())
UpdateSplitAndLightcoordRangeFromComputeShaders(width, height);
static_cast<scene::CSceneManager *>(m_scene_manager)->OnAnimate(os::Timer::getTime());
camnode->render();
irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION));
irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
irr_driver->genProjViewMatrix();
m_current_screen_size = core::vector2df(float(width), float(height));
const float oldfar = camnode->getFarValue();
const float oldnear = camnode->getNearValue();
float FarValues[] =
{
shadowSplit[1],
shadowSplit[2],
shadowSplit[3],
shadowSplit[4],
};
float NearValues[] =
{
shadowSplit[0],
shadowSplit[1],
shadowSplit[2],
shadowSplit[3]
};
float tmp[16 * 9 + 2];
memcpy(tmp, irr_driver->getViewMatrix().pointer(), 16 * sizeof(float));
memcpy(&tmp[16], irr_driver->getProjMatrix().pointer(), 16 * sizeof(float));
memcpy(&tmp[32], irr_driver->getInvViewMatrix().pointer(), 16 * sizeof(float));
memcpy(&tmp[48], irr_driver->getInvProjMatrix().pointer(), 16 * sizeof(float));
memcpy(&tmp[64], irr_driver->getProjViewMatrix().pointer(), 16 * sizeof(float));
m_suncam->render();
for (unsigned i = 0; i < 4; i++)
{
if (m_shadow_camnodes[i])
delete m_shadow_camnodes[i];
m_shadow_camnodes[i] = (scene::ICameraSceneNode *) m_suncam->clone();
}
sun_ortho_matrix.clear();
const core::matrix4 &SunCamViewMatrix = m_suncam->getViewMatrix();
if (World::getWorld() && World::getWorld()->getTrack())
{
// Compute track extent
btVector3 btmin, btmax;
if (World::getWorld()->getTrack()->getPtrTriangleMesh())
{
World::getWorld()->getTrack()->getTriangleMesh().getCollisionShape().getAabb(btTransform::getIdentity(), btmin, btmax);
}
const Vec3 vmin = btmin, vmax = btmax;
core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
core::vector3df(0, 30, 0));
// Shadow Matrixes and cameras
for (unsigned i = 0; i < 4; i++)
{
core::matrix4 tmp_matrix;
if (!CVS->isSDSMEnabled())
{
camnode->setFarValue(FarValues[i]);
camnode->setNearValue(NearValues[i]);
camnode->render();
const scene::SViewFrustum *frustrum = camnode->getViewFrustum();
float tmp[24] = {
frustrum->getFarLeftDown().X,
frustrum->getFarLeftDown().Y,
frustrum->getFarLeftDown().Z,
frustrum->getFarLeftUp().X,
frustrum->getFarLeftUp().Y,
frustrum->getFarLeftUp().Z,
frustrum->getFarRightDown().X,
frustrum->getFarRightDown().Y,
frustrum->getFarRightDown().Z,
frustrum->getFarRightUp().X,
frustrum->getFarRightUp().Y,
frustrum->getFarRightUp().Z,
frustrum->getNearLeftDown().X,
frustrum->getNearLeftDown().Y,
frustrum->getNearLeftDown().Z,
frustrum->getNearLeftUp().X,
frustrum->getNearLeftUp().Y,
frustrum->getNearLeftUp().Z,
frustrum->getNearRightDown().X,
frustrum->getNearRightDown().Y,
frustrum->getNearRightDown().Z,
frustrum->getNearRightUp().X,
frustrum->getNearRightUp().Y,
frustrum->getNearRightUp().Z,
};
memcpy(m_shadows_cam[i], tmp, 24 * sizeof(float));
std::vector<vector3df> vectors = getFrustrumVertex(*frustrum);
tmp_matrix = getTighestFitOrthoProj(SunCamViewMatrix, vectors, m_shadow_scales[i]);
}
else
{
float left = float(CBB[currentCBB][i].xmin / 4 - 2);
float right = float(CBB[currentCBB][i].xmax / 4 + 2);
float up = float(CBB[currentCBB][i].ymin / 4 - 2);
float down = float(CBB[currentCBB][i].ymax / 4 + 2);
// Prevent Matrix without extend
if (left != right && up != down)
{
tmp_matrix.buildProjectionMatrixOrthoLH(left, right,
down, up,
float(CBB[currentCBB][i].zmin / 4 - 100),
float(CBB[currentCBB][i].zmax / 4 + 2));
m_shadow_scales[i] = std::make_pair(right - left, down - up);
}
}
m_shadow_camnodes[i]->setProjectionMatrix(tmp_matrix, true);
m_shadow_camnodes[i]->render();
sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW));
}
// Rsm Matrix and camera
if (!m_rsm_matrix_initialized)
{
if (trackbox.MinEdge.X != trackbox.MaxEdge.X &&
trackbox.MinEdge.Y != trackbox.MaxEdge.Y &&
// Cover the case where SunCamViewMatrix is null
SunCamViewMatrix.getScale() != core::vector3df(0., 0., 0.))
{
SunCamViewMatrix.transformBoxEx(trackbox);
core::matrix4 tmp_matrix;
tmp_matrix.buildProjectionMatrixOrthoLH(trackbox.MinEdge.X, trackbox.MaxEdge.X,
trackbox.MaxEdge.Y, trackbox.MinEdge.Y,
30, trackbox.MaxEdge.Z);
m_suncam->setProjectionMatrix(tmp_matrix, true);
m_suncam->render();
}
rsm_matrix = getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW);
m_rsm_matrix_initialized = true;
m_rsm_map_available = false;
}
rh_extend = core::vector3df(128, 64, 128);
core::vector3df campos = camnode->getAbsolutePosition();
core::vector3df translation(8 * floor(campos.X / 8), 8 * floor(campos.Y / 8), 8 * floor(campos.Z / 8));
rh_matrix.setTranslation(translation);
assert(sun_ortho_matrix.size() == 4);
// reset normal camera
camnode->setNearValue(oldnear);
camnode->setFarValue(oldfar);
camnode->render();
size_t size = irr_driver->getShadowViewProj().size();
for (unsigned i = 0; i < size; i++)
memcpy(&tmp[16 * i + 80], irr_driver->getShadowViewProj()[i].pointer(), 16 * sizeof(float));
}
tmp[144] = float(width);
tmp[145] = float(height);
glBindBuffer(GL_UNIFORM_BUFFER, SharedObject::ViewProjectionMatrixesUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, (16 * 9 + 2) * sizeof(float), tmp);
}

View File

View File

@@ -416,9 +416,9 @@ void RaceGUIBase::renderPlayerView(const Camera *camera, float dt)
{
const core::recti &viewport = camera->getViewport();
#if 0
if (m_lightning > 0.0f)
{
#ifndef ANDROID
GLint glviewport[4];
glviewport[0] = viewport.UpperLeftCorner.X;
glviewport[1] = viewport.UpperLeftCorner.Y;
@@ -445,9 +445,7 @@ void RaceGUIBase::renderPlayerView(const Camera *camera, float dt)
if (!irr::video::useCoreContext)
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#endif
}
#if 0 // Rainy look, off, TODO: needs to be settable per track
else
{
GLint glviewport[4];