From aeed2618a498c8049758c6e9fc8bf797d94c97a4 Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Mon, 3 Nov 2014 17:47:07 -0500 Subject: [PATCH 01/15] Set anisotropic filtering to 16 on highest graphical level, fixes #1655 --- src/states_screens/options_screen_video.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/states_screens/options_screen_video.cpp b/src/states_screens/options_screen_video.cpp index c6c3a121c..561b30144 100644 --- a/src/states_screens/options_screen_video.cpp +++ b/src/states_screens/options_screen_video.cpp @@ -97,7 +97,7 @@ static GFXPreset GFX_PRESETS[] = { true /* light */, 2 /* shadow */, true /* bloom */, true /* motionblur */, true /* lightshaft */, true /* glow */, true /* mlaa */, true /* ssao */, true /* weather */, - true /* animatedScenery */, 2 /* animatedCharacters */, 8 /* anisotropy */, + true /* animatedScenery */, 2 /* animatedCharacters */, 16 /* anisotropy */, true /* depth of field */, true /* global illumination */ } }; From c93e6c0ee3cd021c3044def005f722945a543ca4 Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Tue, 4 Nov 2014 01:48:50 +0100 Subject: [PATCH 02/15] Fix shadow glitches in minigolf --- src/graphics/render.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 21e64047d..6309117bd 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -638,7 +638,7 @@ core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, const std:: return tmp_matrix; tmp_matrix.buildProjectionMatrixOrthoLH(left, right, down, up, - 30, zmax); + zmin - 30, zmax); return tmp_matrix; } From 2f4edb6183434f84b65d2d94a02166f25093663c Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Tue, 4 Nov 2014 01:55:10 +0100 Subject: [PATCH 03/15] Higher value for zmin --- src/graphics/render.cpp | 2 +- src/graphics/render_geometry.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 6309117bd..ec47e5aa3 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -638,7 +638,7 @@ core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, const std:: return tmp_matrix; tmp_matrix.buildProjectionMatrixOrthoLH(left, right, down, up, - zmin - 30, zmax); + zmin - 100, zmax); return tmp_matrix; } diff --git a/src/graphics/render_geometry.cpp b/src/graphics/render_geometry.cpp index d5fe29c4b..769d082ab 100644 --- a/src/graphics/render_geometry.cpp +++ b/src/graphics/render_geometry.cpp @@ -981,8 +981,8 @@ void IrrDriver::renderShadows() m_rtts->getShadowFBO().Bind(); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.5, 0.); - glCullFace(GL_BACK); - glEnable(GL_CULL_FACE); +// glCullFace(GL_BACK); +// glEnable(GL_CULL_FACE); glClearColor(1., 1., 1., 1.); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); From 3eafdd9729027b0645b52c92134600cc2997cb33 Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Tue, 4 Nov 2014 02:06:17 +0100 Subject: [PATCH 04/15] Culling was wrongly disabled --- src/graphics/render_geometry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/graphics/render_geometry.cpp b/src/graphics/render_geometry.cpp index 769d082ab..d5fe29c4b 100644 --- a/src/graphics/render_geometry.cpp +++ b/src/graphics/render_geometry.cpp @@ -981,8 +981,8 @@ void IrrDriver::renderShadows() m_rtts->getShadowFBO().Bind(); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.5, 0.); -// glCullFace(GL_BACK); -// glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); glClearColor(1., 1., 1., 1.); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); From e27e7a013275d9f4b0aa05c4573a7cb10856b37f Mon Sep 17 00:00:00 2001 From: Deve Date: Tue, 4 Nov 2014 11:27:07 +0100 Subject: [PATCH 05/15] Reset kart rotation when skidding is broken by rescue animation. Minor improvements with breaking during skidding. --- src/karts/skidding.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/karts/skidding.cpp b/src/karts/skidding.cpp index 2f13521b3..4a6060fe5 100644 --- a/src/karts/skidding.cpp +++ b/src/karts/skidding.cpp @@ -77,6 +77,9 @@ void Skidding::reset() m_kart->getKartGFX()->setCreationRateAbsolute(KartGFX::KGFX_SKIDL, 0); m_kart->getKartGFX()->setCreationRateAbsolute(KartGFX::KGFX_SKIDR, 0); m_kart->getControls().m_skid = KartControl::SC_NONE; + + btVector3 rot(0, 0, 0); + m_kart->getVehicle()->setTimedRotation(0, rot); } // reset // ---------------------------------------------------------------------------- @@ -120,8 +123,8 @@ void Skidding::updateSteering(float steer, float dt) break; case SKID_BREAK: m_real_steering = steer; - if (m_visual_rotation > 0.05f) m_visual_rotation -= 0.05f; - else if (m_visual_rotation < -0.05f) m_visual_rotation += 0.05f; + if (m_visual_rotation > 0.1f) m_visual_rotation -= 0.1f; + else if (m_visual_rotation < -0.1f) m_visual_rotation += 0.1f; else { reset(); @@ -212,7 +215,7 @@ void Skidding::update(float dt, bool is_on_ground, } // No skidding backwards or while stopped - if(m_kart->getSpeed() < 0.001f && + if(m_kart->getSpeed() < m_min_skid_speed && m_skid_state != SKID_NONE && m_skid_state != SKID_BREAK) { m_skid_state = SKID_BREAK; @@ -355,7 +358,6 @@ void Skidding::update(float dt, bool is_on_ground, } case SKID_BREAK: { - updateSteering(steering, dt); break; } case SKID_ACCUMULATE_LEFT: From 66a1ff2b2b44e4d2c7d870aae2f1fdc38a5fe2b6 Mon Sep 17 00:00:00 2001 From: Deve Date: Tue, 4 Nov 2014 20:10:36 +0100 Subject: [PATCH 06/15] Don't allow to run locked tracks in random GPs --- src/race/grand_prix_data.cpp | 6 +++ src/states_screens/gp_info_screen.cpp | 68 +++++++++++++++++++-------- src/states_screens/gp_info_screen.hpp | 6 +++ 3 files changed, 61 insertions(+), 19 deletions(-) diff --git a/src/race/grand_prix_data.cpp b/src/race/grand_prix_data.cpp index e1c7d8f25..92e999d64 100644 --- a/src/race/grand_prix_data.cpp +++ b/src/race/grand_prix_data.cpp @@ -106,6 +106,9 @@ void GrandPrixData::changeTrackNumber(const unsigned int number_of_tracks, // Ignore no-racing tracks: if(!track->isRaceTrack()) continue; + + if (PlayerManager::getCurrentPlayer()->isLocked(track->getIdent())) + continue; // Only add tracks that are not already picked. if(std::find(m_tracks.begin(), m_tracks.end(), track->getIdent())== @@ -129,6 +132,9 @@ void GrandPrixData::changeTrackNumber(const unsigned int number_of_tracks, const Track *track = track_manager->getTrack(track_index); std::string id = track->getIdent(); + + if (PlayerManager::getCurrentPlayer()->isLocked(track->getIdent())) + continue; m_tracks.push_back(id); m_laps.push_back(track->getDefaultNumberOfLaps()); diff --git a/src/states_screens/gp_info_screen.cpp b/src/states_screens/gp_info_screen.cpp index db587f75c..f08911cb1 100644 --- a/src/states_screens/gp_info_screen.cpp +++ b/src/states_screens/gp_info_screen.cpp @@ -59,6 +59,7 @@ GPInfoScreen::GPInfoScreen() : Screen("gp_info.stkgui") // Necessary to test if loadedFroMFile() was executed (in setGP) m_reverse_spinner = NULL; m_screenshot_widget = NULL; + m_max_num_tracks = 0; } // GPInfoScreen // ---------------------------------------------------------------------------- @@ -192,16 +193,12 @@ void GPInfoScreen::init() else m_group_name = stringc(m_group_spinner->getStringValue().c_str()).c_str(); - // If there are more tracks selected atm as in the group (which can - // happen if the group has been changed since last time this screen - // was shown), adjust it: - int max_num_tracks = m_group_name=="all" - ? track_manager->getNumberOfRaceTracks() - : (int)track_manager->getTracksInGroup(m_group_name).size(); - m_num_tracks_spinner->setMax(max_num_tracks); - if(m_num_tracks_spinner->getValue() > max_num_tracks) + m_max_num_tracks = getMaxNumTracks(m_group_name); + + m_num_tracks_spinner->setMax(m_max_num_tracks); + if(m_num_tracks_spinner->getValue() > m_max_num_tracks) { - m_num_tracks_spinner->setValue(max_num_tracks); + m_num_tracks_spinner->setValue(m_max_num_tracks); } // Now create the random GP: @@ -330,16 +327,11 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name, { m_group_name = stringc(m_group_spinner->getStringValue()).c_str(); - // Update the maximum for the number of tracks since it's depending on - // the current track. The current value in the Number-of-tracks-spinner - // has to be updated, since otherwise the displayed (and used) value - // can be bigger than the maximum. (Might be a TODO to fix this) - int max_num_tracks = m_group_name=="all" - ? track_manager->getNumberOfRaceTracks() - : (int)track_manager->getTracksInGroup(m_group_name).size(); - m_num_tracks_spinner->setMax(max_num_tracks); - if (m_num_tracks_spinner->getValue() > max_num_tracks) - m_num_tracks_spinner->setValue(max_num_tracks); + m_max_num_tracks = getMaxNumTracks(m_group_name); + + m_num_tracks_spinner->setMax(m_max_num_tracks); + if (m_num_tracks_spinner->getValue() > m_max_num_tracks) + m_num_tracks_spinner->setValue(m_max_num_tracks); // Create a new (i.e. with new tracks) random gp, since the old // tracks might not all belong to the newly selected group. @@ -389,3 +381,41 @@ void GPInfoScreen::onUpdate(float dt) m_screenshot_widget->setImage(file, IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE); m_screenshot_widget->m_properties[PROP_ICON] = file; } // onUpdate + +/** Get number of available tracks for random GPs + */ +int GPInfoScreen::getMaxNumTracks(std::string group) +{ + int max_num_tracks = 0; + + if (group == "all") + { + for (unsigned int i = 0; i < track_manager->getNumberOfTracks(); i++) + { + std::string id = track_manager->getTrack(i)->getIdent(); + + if (!PlayerManager::getCurrentPlayer()->isLocked(id) && + track_manager->getTrack(i)->isRaceTrack()) + { + max_num_tracks++; + } + } + } + else + { + std::vector tracks = track_manager->getTracksInGroup(group); + + for (unsigned int i = 0; i < tracks.size(); i++) + { + std::string id = track_manager->getTrack(tracks[i])->getIdent(); + + if (!PlayerManager::getCurrentPlayer()->isLocked(id) && + track_manager->getTrack(tracks[i])->isRaceTrack()) + { + max_num_tracks++; + } + } + } + + return max_num_tracks; +} diff --git a/src/states_screens/gp_info_screen.hpp b/src/states_screens/gp_info_screen.hpp index 039936e61..2e2149c04 100644 --- a/src/states_screens/gp_info_screen.hpp +++ b/src/states_screens/gp_info_screen.hpp @@ -53,6 +53,12 @@ private: /** The currently selected group name. */ std::string m_group_name; + + /** Number of available tracks */ + int m_max_num_tracks; + + /** Get number of available tracks for random GPs */ + int getMaxNumTracks(std::string group); protected: // Necessary for RandomGPInfoScreen GUIEngine::IconButtonWidget* m_screenshot_widget; From 6d07189474276bc242ae066f91030f98d3f036c0 Mon Sep 17 00:00:00 2001 From: Deve Date: Tue, 4 Nov 2014 20:27:01 +0100 Subject: [PATCH 07/15] Don't allow doubled tracks in random GP. Otherwise track number limit wouldn't have sense. --- src/race/grand_prix_data.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/race/grand_prix_data.cpp b/src/race/grand_prix_data.cpp index 92e999d64..cc91402b1 100644 --- a/src/race/grand_prix_data.cpp +++ b/src/race/grand_prix_data.cpp @@ -135,10 +135,24 @@ void GrandPrixData::changeTrackNumber(const unsigned int number_of_tracks, if (PlayerManager::getCurrentPlayer()->isLocked(track->getIdent())) continue; + + bool is_already_added = false; + for (unsigned int i = 0; i < m_tracks.size(); i++) + { + if (m_tracks[i] == id) + { + is_already_added = true; + break; + } + } + + if (!is_already_added) + { + m_tracks.push_back(id); + m_laps.push_back(track->getDefaultNumberOfLaps()); + m_reversed.push_back(false); // This will be changed later in the code + } - m_tracks.push_back(id); - m_laps.push_back(track->getDefaultNumberOfLaps()); - m_reversed.push_back(false); // This will be changed later in the code track_indices.erase(track_indices.begin()+index); } } From 92ecd01e61c5820214d188f6e775ffe31a7e09d3 Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Mon, 27 Oct 2014 21:19:03 +0100 Subject: [PATCH 08/15] Make cascade split modifiable --- data/shaders/sunlightshadow.frag | 103 ++++++------------------------- src/graphics/post_processing.cpp | 4 +- src/graphics/render.cpp | 18 +++--- src/graphics/shaders.hpp | 2 +- 4 files changed, 32 insertions(+), 95 deletions(-) diff --git a/data/shaders/sunlightshadow.frag b/data/shaders/sunlightshadow.frag index 0bb01c51d..7ad3e08a0 100644 --- a/data/shaders/sunlightshadow.frag +++ b/data/shaders/sunlightshadow.frag @@ -1,14 +1,14 @@ uniform sampler2D ntex; uniform sampler2D dtex; uniform sampler2DArray shadowtex; -//uniform sampler2D warpx; -///uniform sampler2D warpy; + +uniform float split0; +uniform float split1; +uniform float split2; +uniform float splitmax; uniform vec3 direction; uniform vec3 col; -//uniform int hasclouds; -//uniform vec2 wind; -//uniform float shadowoffset; in vec2 uv; out vec4 Diff; @@ -20,8 +20,7 @@ vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix); float getShadowFactor(vec3 pos, float bias, int index) { - //float a[5] = float[](3.4, 4.2, 5.0, 5.2, 1.1); - + vec2 shadowoffset[4] = vec2[]( vec2(-1., -1.), vec2(-1., 1.), @@ -32,27 +31,6 @@ float getShadowFactor(vec3 pos, float bias, int index) vec4 shadowcoord = (ShadowViewProjMatrixes[index] * InverseViewMatrix * vec4(pos, 1.0)); shadowcoord.xy /= shadowcoord.w; vec2 shadowtexcoord = shadowcoord.xy * 0.5 + 0.5; -// shadowcoord = (shadowcoord * 0.5) + vec3(0.5); - -// float movex = decdepth(texture(warpx, shadowcoord.xy)); -// float movey = decdepth(texture(warpy, shadowcoord.xy)); -// float dx = movex * 2.0 - 1.0; -// float dy = movey * 2.0 - 1.0; -// shadowcoord.xy += vec2(dx, dy);*/ - -//float shadowmapz = 2. * texture(shadowtex, vec3(shadowtexcoord, shadowcoord.z).x - 1.; -// bias += smoothstep(0.001, 0.1, moved) * 0.014; // According to the warping - -// float sum = 0.; -// for (float i = -1.5; i <= 1.5; i+= 1.) -// { -// for (float j = -1.5; j <= 1.5; j+= 1.) -// { -// float z = texture(shadowtex, vec3(shadowtexcoord +vec2(i, j) / 1024., float(index))).x; -// sum += (z > 0.5 * shadowcoord.z + 0.5) ? 1. : 0.; -// } -// } -// return sum / 16.; float z = texture(shadowtex, vec3(shadowtexcoord, float(index))).x; float d = shadowcoord.z; @@ -78,86 +56,41 @@ void main() { vec3 outcol = NdotL * col; -// if (hasclouds == 1) -// { -// vec2 cloudcoord = (xpos.xz * 0.00833333) + wind; -// float cloud = texture(cloudtex, cloudcoord).x; -// //float cloud = step(0.5, cloudcoord.x) * step(0.5, cloudcoord.y); - -// outcol *= cloud; -// } // Shadows float bias = 0.005 * tan(acos(NdotL)); // According to the slope bias = clamp(bias, 0., 0.01); float factor; - if (xpos.z < 5.) + if (xpos.z < split0) factor = getShadowFactor(xpos.xyz, bias, 0); - else if (xpos.z < 6.) +/* else if (xpos.z < 6.) { float a = getShadowFactor(xpos.xyz, bias, 0), b = getShadowFactor(xpos.xyz, bias, 1); factor = mix(a, b, (xpos.z - 5.)); - } - else if (xpos.z < 20.) + }*/ + else if (xpos.z < split1) factor = getShadowFactor(xpos.xyz, bias, 1); - else if (xpos.z < 21.) +/* else if (xpos.z < 21.) { float a = getShadowFactor(xpos.xyz, bias, 1), b = getShadowFactor(xpos.xyz, bias, 2); factor = mix(a, b, (xpos.z - 20.)); - } - else if (xpos.z < 50.) + }*/ + else if (xpos.z < split2) factor = getShadowFactor(xpos.xyz, bias, 2); - else if (xpos.z < 55.) +/* else if (xpos.z < 55.) { float a = getShadowFactor(xpos.xyz, bias, 2), b = getShadowFactor(xpos.xyz, bias, 3); factor = mix(a, b, (xpos.z - 50.) / 5.); - } - else if (xpos.z < 145.) + }*/ + else if (xpos.z < splitmax) factor = getShadowFactor(xpos.xyz, bias, 3); - else if (xpos.z < 150.) +/* else if (xpos.z < 150.) { factor = mix(getShadowFactor(xpos.xyz, bias, 3), 1., (xpos.z - 145.) / 5.); - } + }*/ else factor = 1.; Diff = vec4(factor * NdotL * col, 1.); Spec = vec4(factor * Specular, 1.); return; - -// float moved = (abs(dx) + abs(dy)) * 0.5; - -// float avi = 0.002; -// float abi = 0.0025; - -/* float avi = 0.0018; - float abi = 0.002; - - float bias = avi * tan(acos(NdotL)); // According to the slope - bias += smoothstep(0.001, 0.1, moved) * abi; // According to the warping - bias = clamp(bias, 0.001, abi); - - // This ID, and four IDs around this must match for a shadow pixel - float right = texture(shadowtex, shadowcoord.xy + vec2(shadowoffset, 0.0)).a; - float left = texture(shadowtex, shadowcoord.xy + vec2(-shadowoffset, 0.0)).a; - float up = texture(shadowtex, shadowcoord.xy + vec2(0.0, shadowoffset)).a; - float down = texture(shadowtex, shadowcoord.xy + vec2(0.0, -shadowoffset)).a; - - float matching = ((right + left + up + down) * 0.25) - shadowread.a; - matching = abs(matching) * 400.0; - - // If the ID is different, we're likely in shadow - cut the bias to cut peter panning - float off = 7.0 - step(abs(shadowread.a - depthread.a) - matching, 0.004) * 6.0; - bias /= off; - - const float softness = 8.0; // How soft is the light? - float shadowed = step(shadowmapz + bias, shadowcoord.z); - float dist = (shadowcoord.z / shadowmapz) - 1.0; - float penumbra = dist * softness / gl_FragCoord.z; - penumbra *= shadowed;*/ - -/* outcol.r = (shadowcoord.z - shadowmapz) * 50.0; - outcol.g = moved;*/ - -// FragColor = vec4(outcol, 0.05); -// OtherOutput = vec4(shadowed, penumbra, shadowed, shadowed); } diff --git a/src/graphics/post_processing.cpp b/src/graphics/post_processing.cpp index 86a626103..1e18359dd 100644 --- a/src/graphics/post_processing.cpp +++ b/src/graphics/post_processing.cpp @@ -282,6 +282,8 @@ void PostProcessing::renderSunlight() DrawFullScreenEffect(cb->getPosition(), video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue())); } +extern float shadowSplit[5]; + void PostProcessing::renderShadowedSunlight(const std::vector &sun_ortho_matrix, GLuint depthtex) { SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT); @@ -292,7 +294,7 @@ void PostProcessing::renderShadowedSunlight(const std::vector &su glBlendEquation(GL_FUNC_ADD); FullScreenShader::ShadowedSunLightShader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), depthtex); - DrawFullScreenEffect(cb->getPosition(), video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue())); + DrawFullScreenEffect(shadowSplit[1], shadowSplit[2], shadowSplit[3], shadowSplit[4], cb->getPosition(), video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue())); } diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index ec47e5aa3..cfc19e857 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -642,6 +642,8 @@ core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, const std:: return tmp_matrix; } +float shadowSplit[5] = {1., 5., 20., 50., 150 }; + void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height) { static_cast(m_scene_manager)->OnAnimate(os::Timer::getTime()); @@ -656,17 +658,17 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz const float oldnear = camnode->getNearValue(); float FarValues[] = { - 6., - 21., - 55., - 150., + shadowSplit[1], + shadowSplit[2], + shadowSplit[3], + shadowSplit[4], }; float NearValues[] = { - oldnear, - 5., - 20., - 50., + shadowSplit[0], + shadowSplit[1], + shadowSplit[2], + shadowSplit[3] }; diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index 55b773d51..b7ab47882 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -402,7 +402,7 @@ public: EnvMapShader(); }; -class ShadowedSunLightShader : public ShaderHelperSingleton, public TextureRead +class ShadowedSunLightShader : public ShaderHelperSingleton, public TextureRead { public: ShadowedSunLightShader(); From 2077676f8ea4968e62ecf523e7d7b2ee2bb25a43 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 5 Nov 2014 11:23:46 +1100 Subject: [PATCH 09/15] Updated windows build instructions. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 146aca2e1..6d98155f8 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ Hope you enjoy the game. ##Compiling SuperTuxKart ###Windows -1. Install VS 2012 or later. The free express versions work fine. +1. Install VS 2013 (or later). The free express versions work fine. 2. Download and install a source package - either a released package or from our [git/svn repositories](http://supertuxkart.sourceforge.net/Source_control) 3. Download the latest dependency package depdendencies_for_0.8.2.zip from [here](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/). Unzip it in the root directory, so that the dependencies directory is next to the src and data directory (if you are updating from a previous dependency package, you can delete the .dll files in the root directory, they are not needed anymore). 4. Download cmake and install it. Then start cmake-gui and select the STK root directory as 'Where is the source code', and a new directory in the root directory (next to src, data etc) as build directory (for now I assume that this directory is called bld). -5. Click on configure. You will be asked to create the directory (yes), then for your VS version. Make sure to select the right version (be aware of the easy to confuse version numbers: VS 2012 = version 11; VS 2013 = version 12). Click on configure, then generate. This will create the directory 'bld', and a VS solution in that directory. +5. Click on configure. You will be asked to create the directory (yes), then for your VS version. Make sure to select the right version (be aware of the easy to confuse version numbers: VS 2013 = version 12). Click on configure, then generate. This will create the directory 'bld', and a VS solution in that directory. 6. In Visual Studio open the project file generated in the 'bld' folder 7. Right click on the supertuxkart project in the solution explorer, and select "Set as StartUp Project". 8. Select Build->Build Solution (or press F7) to compile. From cfb4dc13a87c3315514d8e5723f766d8f972f0a5 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 5 Nov 2014 13:39:57 +1100 Subject: [PATCH 10/15] Updated GP for new mines track. --- data/grandprix/4_atworldsend.grandprix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/grandprix/4_atworldsend.grandprix b/data/grandprix/4_atworldsend.grandprix index 0aa43f1e2..0341793a1 100644 --- a/data/grandprix/4_atworldsend.grandprix +++ b/data/grandprix/4_atworldsend.grandprix @@ -4,7 +4,7 @@ - + From 884daf90932afcf7d7e5c32493ae243cde54d8a6 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 5 Nov 2014 22:53:25 +1100 Subject: [PATCH 11/15] Fix #1665 (kart hovering in pyramid after jump) by only cushioning with half the computed impulse. --- src/physics/btKart.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index 503f22f0c..7afd4c198 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -420,7 +420,7 @@ void btKart::updateVehicle( btScalar step ) if(-v_down.getY() > max_compensate_speed) { btVector3 impulse = down * (-v_down.getY() - max_compensate_speed) - / m_chassisBody->getInvMass(); + / m_chassisBody->getInvMass()*0.5f; //float v_old = m_chassisBody->getLinearVelocity().getY(); //float x = m_wheelInfo[0].m_raycastInfo.m_isInContact ? m_wheelInfo[0].m_raycastInfo.m_contactPointWS.getY() : -100; m_chassisBody->applyCentralImpulse(impulse); From 2c8f86fabd7879fc5da917213f80bd035800ef8c Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Wed, 5 Nov 2014 18:13:47 -0500 Subject: [PATCH 12/15] Intro cutscene fixes --- src/states_screens/main_menu_screen.cpp | 1 + src/states_screens/race_result_gui.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/states_screens/main_menu_screen.cpp b/src/states_screens/main_menu_screen.cpp index 87289896b..14a1f4aaf 100644 --- a/src/states_screens/main_menu_screen.cpp +++ b/src/states_screens/main_menu_screen.cpp @@ -419,6 +419,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, PlayerProfile *player = PlayerManager::getCurrentPlayer(); if (player->isFirstTime()) { + CutsceneWorld::setUseDuration(true); StateManager::get()->enterGameState(); race_manager->setMinorMode(RaceManager::MINOR_MODE_CUTSCENE); race_manager->setNumKarts( 0 ); diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index e9153d64f..bd59348e5 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -261,6 +261,7 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget, StateManager::get()->getActivePlayer(playerID)->setKart(NULL); World::deleteWorld(); + CutsceneWorld::setUseDuration(true); StateManager::get()->enterGameState(); race_manager->setMinorMode(RaceManager::MINOR_MODE_CUTSCENE); race_manager->setNumKarts( 0 ); From 3c88898113b8960388638ee3669a4588a86d940a Mon Sep 17 00:00:00 2001 From: hiker Date: Fri, 7 Nov 2014 16:36:03 +1100 Subject: [PATCH 13/15] Fixed --camera-wheel-debug command line option (better distance computation, no smoothing); removed unused function. --- src/graphics/camera.cpp | 47 ++++++++++------------------------------- src/graphics/camera.hpp | 2 -- 2 files changed, 11 insertions(+), 38 deletions(-) diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index 5195773dd..32460a4f4 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -64,7 +64,10 @@ Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL) setupCamera(); if (kart != NULL) { - m_distance = kart->getKartProperties()->getCameraDistance(); + if(UserConfigParams::m_camera_debug==2) + m_distance = kart->getKartModel()->getLength(); + else + m_distance = kart->getKartProperties()->getCameraDistance(); setKart(kart); } else @@ -378,37 +381,6 @@ void Camera::smoothMoveCamera(float dt) } } // smoothMoveCamera -//----------------------------------------------------------------------------- -/** Computes the wanted camera position and target for normal camera mode. - * Besides being used in update(dt), it is also used when switching the - * camera from reverse mode to normal mode - in which case we don't want - * to have a smooth camera. - * \param wanted_position The position the camera should be. - * \param wanted_target The target position the camera should target. - */ -void Camera::computeNormalCameraPosition(Vec3 *wanted_position, - Vec3 *wanted_target) -{ - *wanted_target = m_kart->getXYZ(); - wanted_target->setY(wanted_target->getY()+ 0.75f); - - // This first line moves the camera around behind the kart, pointing it - // towards where the kart is turning (and turning even more while skidding). - // The skidding effect is dampened. - float steering = m_kart->getSteerPercent() - * (1.0f + (m_kart->getSkidding()->getSkidFactor() - 1.0f) - /2.3f ); - // quadratically to dampen small variations (but keep sign) - float dampened_steer = fabsf(steering) * steering; - - float tan_up = tan(m_kart->getKartProperties()->getCameraForwardUpAngle()); - Vec3 relative_position(-m_distance*m_rotation_range*dampened_steer*0.5f, - m_distance*tan_up+0.75f, - -m_distance); - *wanted_position = m_kart->getTrans()(relative_position); - -} // computeNormalCameraPosition - //----------------------------------------------------------------------------- /** Determine the camera settings for the current frame. * \param above_kart How far above the camera should aim at. @@ -549,7 +521,10 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle, Vec3 wanted_position; Vec3 wanted_target = m_kart->getXYZ(); if(UserConfigParams::m_camera_debug==2) - wanted_target.setY(m_kart->getVehicle()->getWheelInfo(2).m_raycastInfo.m_contactPointWS.getY()); + { + const btWheelInfo &w = m_kart->getVehicle()->getWheelInfo(2); + wanted_target.setY(w.m_raycastInfo.m_contactPointWS.getY()); + } else wanted_target.setY(wanted_target.getY()+above_kart); float tan_up = tan(cam_angle); @@ -567,7 +542,7 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle, } wanted_position = t(relative_position); - if (smoothing) + if (smoothing && UserConfigParams::m_camera_debug==0) { smoothMoveCamera(dt); } @@ -591,8 +566,8 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle, // Rotate the up vector (0,1,0) by the rotation ... which is just column 1 Vec3 up = m_kart->getTrans().getBasis().getColumn(1); float f = 0.04f; // weight for new up vector to reduce shaking - m_camera->setUpVector(f * up.toIrrVector() + - (1.0f - f) * m_camera->getUpVector()); + m_camera->setUpVector( f * up.toIrrVector() + + (1.0f - f) * m_camera->getUpVector()); } // kart && !flying else m_camera->setUpVector(core::vector3df(0, 1, 0)); diff --git a/src/graphics/camera.hpp b/src/graphics/camera.hpp index c105ee4d3..50f7ba906 100644 --- a/src/graphics/camera.hpp +++ b/src/graphics/camera.hpp @@ -186,8 +186,6 @@ private: void setupCamera(); void smoothMoveCamera(float dt); - void computeNormalCameraPosition(Vec3 *wanted_position, - Vec3 *wanted_target); void handleEndCamera(float dt); void getCameraSettings(float *above_kart, float *cam_angle, float *side_way, float *distance, From cacb008ae6796a71e9767dd1fd8d8a9a2b508535 Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Mon, 27 Oct 2014 01:43:33 +0100 Subject: [PATCH 14/15] Prepare compute shader to stretch lightcoord --- data/shaders/Lightspaceboundingbox.comp | 142 ++++++++++++++++++++++++ src/graphics/irr_driver.cpp | 5 + src/graphics/irr_driver.hpp | 7 ++ src/graphics/render.cpp | 104 ++++++++++++++--- src/graphics/shaders.cpp | 11 ++ src/graphics/shaders.hpp | 6 + 6 files changed, 261 insertions(+), 14 deletions(-) create mode 100644 data/shaders/Lightspaceboundingbox.comp diff --git a/data/shaders/Lightspaceboundingbox.comp b/data/shaders/Lightspaceboundingbox.comp new file mode 100644 index 000000000..e55e69c68 --- /dev/null +++ b/data/shaders/Lightspaceboundingbox.comp @@ -0,0 +1,142 @@ +uniform sampler2D depth; +uniform float split0; +uniform float split1; +uniform float split2; +uniform float splitmax; +uniform mat4 SunCamMatrix; + +layout (local_size_x = 8, local_size_y = 8) in; + +struct CascadeBoundingBox +{ + int xmin; + int xmax; + int ymin; + int ymax; + int zmin; + int zmax; +}; + +layout (std430) buffer BoundingBoxes +{ + CascadeBoundingBox BB[4]; +}; + +vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix); + +shared int xmin[4]; +shared int xmax[4]; +shared int ymin[4]; +shared int ymax[4]; +shared int zmin[4]; +shared int zmax[4]; + +void main() +{ + if (gl_LocalInvocationIndex < 4) { + xmin[gl_LocalInvocationIndex] = ymin[gl_LocalInvocationIndex] = zmin[gl_LocalInvocationIndex] = 1000; + xmax[gl_LocalInvocationIndex] = ymax[gl_LocalInvocationIndex] = zmax[gl_LocalInvocationIndex] = -1000; + } + + barrier(); + + ivec3 lmax0 = ivec3(-1000); + ivec3 lmin0 = ivec3(1000); + ivec3 lmax1 = ivec3(-1000); + ivec3 lmin1 = ivec3(1000); + ivec3 lmax2 = ivec3(-1000); + ivec3 lmin2 = ivec3(1000); + ivec3 lmax3 = ivec3(-1000); + ivec3 lmin3 = ivec3(1000); + + vec2 start_xy = gl_LocalInvocationID.xy + gl_WorkGroupID.xy * gl_WorkGroupSize.xy * 8; + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + + + vec2 uv = (start_xy + vec2(i, j) * gl_WorkGroupID.xy) / screen; + float z = texture(depth, uv).x; + vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix); + vec4 lightcoord = InverseViewMatrix * xpos; + lightcoord /= lightcoord.w; + lightcoord = SunCamMatrix * lightcoord; + lightcoord /= lightcoord.w; + ivec3 lc = ivec3(lightcoord.xyz) * 4; + + if (xpos.z < split0) { + lmax0 = max(lmax0, lc); + lmin0 = min(lmin0, lc); + } else if (xpos.z < split1) { + lmax1 = max(lmax1, lc); + lmin1 = min(lmin1, lc); + } else if (xpos.z < split2) { + lmax2 = max(lmax2, lc); + lmin2 = min(lmin2, lc); + } else if (xpos.z < splitmax) { + lmax3 = max(lmax3, lc); + lmin3 = min(lmin3, lc); + } + } + } + + atomicMax(xmax[0], lmax0.x); + atomicMax(ymax[0], lmax0.y); + atomicMax(zmax[0], lmax0.z); + atomicMin(xmin[0], lmin0.x); + atomicMin(ymin[0], lmin0.y); + atomicMin(zmin[0], lmin0.z); + + atomicMax(xmax[1], lmax1.x); + atomicMax(ymax[1], lmax1.y); + atomicMax(zmax[1], lmax1.z); + atomicMin(xmin[1], lmin1.x); + atomicMin(ymin[1], lmin1.y); + atomicMin(zmin[1], lmin1.z); + + atomicMax(xmax[2], lmax2.x); + atomicMax(ymax[2], lmax2.y); + atomicMax(zmax[2], lmax2.z); + atomicMin(xmin[2], lmin2.x); + atomicMin(ymin[2], lmin2.y); + atomicMin(zmin[2], lmin2.z); + + atomicMax(xmax[3], lmax3.x); + atomicMax(ymax[3], lmax3.y); + atomicMax(zmax[3], lmax3.z); + atomicMin(xmin[3], lmin3.x); + atomicMin(ymin[3], lmin3.y); + atomicMin(zmin[3], lmin3.z); + + barrier(); + + if (gl_LocalInvocationIndex == 0) { + atomicMax(BB[0].xmax, xmax[0]); + atomicMax(BB[0].ymax, ymax[0]); + atomicMax(BB[0].zmax, zmax[0]); + atomicMin(BB[0].xmin, xmin[0]); + atomicMin(BB[0].ymin, ymin[0]); + atomicMin(BB[0].zmin, zmin[0]); + + atomicMax(BB[1].xmax, xmax[1]); + atomicMax(BB[1].ymax, ymax[1]); + atomicMax(BB[1].zmax, zmax[1]); + atomicMin(BB[1].xmin, xmin[1]); + atomicMin(BB[1].ymin, ymin[1]); + atomicMin(BB[1].zmin, zmin[1]); + + atomicMax(BB[2].xmax, xmax[2]); + atomicMax(BB[2].ymax, ymax[2]); + atomicMax(BB[2].zmax, zmax[2]); + atomicMin(BB[2].xmin, xmin[2]); + atomicMin(BB[2].ymin, ymin[2]); + atomicMin(BB[2].zmin, zmin[2]); + + atomicMax(BB[3].xmax, xmax[3]); + atomicMax(BB[3].ymax, ymax[3]); + atomicMax(BB[3].zmax, zmax[3]); + atomicMin(BB[3].xmin, xmin[3]); + atomicMin(BB[3].ymin, ymin[3]); + atomicMin(BB[3].zmin, zmin[3]); + } +} + diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 700481678..8e6b9d95b 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -485,6 +485,7 @@ void IrrDriver::initDevice() m_need_ubo_workaround = false; m_need_rh_workaround = false; m_need_srgb_workaround = false; + m_support_sdsm = false; #ifdef WIN32 // Fix for Intel Sandy Bridge on Windows which supports GL up to 3.1 only if (strstr((const char *)glGetString(GL_VENDOR), "Intel") != NULL && (m_gl_major_version == 3 && m_gl_minor_version == 1)) @@ -492,7 +493,10 @@ void IrrDriver::initDevice() #endif // Fix for Nvidia and instanced RH if (strstr((const char *)glGetString(GL_VENDOR), "NVIDIA") != NULL) + { m_need_rh_workaround = true; + m_support_sdsm = false; + } // Fix for AMD and bindless sRGB textures if (strstr((const char *)glGetString(GL_VENDOR), "ATI") != NULL) @@ -546,6 +550,7 @@ void IrrDriver::initDevice() hasTextureView = true; Log::info("GLDriver", "ARB Texture View enabled"); } + m_support_sdsm = m_support_sdsm && hasComputeShaders && hasBuffserStorage; } #endif diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index 1dc1f29e0..ca1747a20 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -181,6 +181,7 @@ private: bool hasComputeShaders; bool hasTextureStorage; bool hasTextureView; + bool m_support_sdsm; bool m_need_ubo_workaround; bool m_need_rh_workaround; bool m_need_srgb_workaround; @@ -267,6 +268,11 @@ public: return 120; } + bool supportsSDSM() const + { + return m_support_sdsm; + } + bool needUBOWorkaround() const { return m_need_ubo_workaround; @@ -773,6 +779,7 @@ public: void renderScene(scene::ICameraSceneNode * const camnode, unsigned pointlightcount, std::vector& 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); // --------------------- OLD RTT -------------------- diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index cfc19e857..46f2f1184 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -644,8 +644,77 @@ core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, const std:: 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]; + +/** 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 +*/ +void IrrDriver::UpdateSplitAndLightcoordRangeFromComputeShaders(size_t width, size_t height) +{ + // Value that should be kept between multiple calls + static GLuint ssbo[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); + } + + // Use bounding boxes from last frame + if (LightcoordBBFence) + { + while (glClientWaitSync(LightcoordBBFence, GL_SYNC_FLUSH_COMMANDS_BIT, 0) != GL_ALREADY_SIGNALED); + glDeleteSync(LightcoordBBFence); + } + + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo[currentCBB]); + 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; + } + 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); + + 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 (irr_driver->supportsSDSM()) + UpdateSplitAndLightcoordRangeFromComputeShaders(width, height); static_cast(m_scene_manager)->OnAnimate(os::Timer::getTime()); camnode->render(); irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION)); @@ -699,9 +768,12 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz // Build the 3 ortho projection (for the 3 shadow resolution levels) for (unsigned i = 0; i < 4; i++) { - camnode->setFarValue(FarValues[i]); - camnode->setNearValue(NearValues[i]); - camnode->render(); + if (!irr_driver->supportsSDSM()) + { + camnode->setFarValue(FarValues[i]); + camnode->setNearValue(NearValues[i]); + camnode->render(); + } const scene::SViewFrustum *frustrum = camnode->getViewFrustum(); float tmp[24] = { frustrum->getFarLeftDown().X, @@ -739,7 +811,6 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz core::aabbox3df box = smallcambox; box = box.intersect(trackbox); - std::vector vectors; vectors.push_back(frustrum->getFarLeftDown()); vectors.push_back(frustrum->getFarLeftUp()); @@ -750,19 +821,24 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz vectors.push_back(frustrum->getNearRightDown()); vectors.push_back(frustrum->getNearRightUp()); -/* SunCamViewMatrix.transformBoxEx(trackbox); - SunCamViewMatrix.transformBoxEx(box); + core::matrix4 tmp_matrix; - core::vector3df extent = box.getExtent(); - const float w = fabsf(extent.X); - const float h = fabsf(extent.Y); - float z = box.MaxEdge.Z; + if (irr_driver->supportsSDSM()){ + float left = CBB[currentCBB][i].xmin / 4 - 2; + float right = CBB[currentCBB][i].xmax / 4 + 2; + float up = CBB[currentCBB][i].ymin / 4 - 2; + float down = CBB[currentCBB][i].ymax / 4 + 2; - // Snap to texels - const float units_per_w = w / 1024; - const float units_per_h = h / 1024;*/ + // Prevent Matrix without extend + if (left != right && up != down) + tmp_matrix.buildProjectionMatrixOrthoLH(left, right, + down, up, + CBB[currentCBB][i].zmin / 4 - 100, CBB[currentCBB][i].zmax / 4 + 2); + } + else + tmp_matrix = getTighestFitOrthoProj(SunCamViewMatrix, vectors); - m_shadow_camnodes[i]->setProjectionMatrix(getTighestFitOrthoProj(SunCamViewMatrix, vectors) , true); + 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)); diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index 459f276d1..af57d6a9f 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -1789,6 +1789,17 @@ namespace FullScreenShader AssignSamplerNames(Program, 0, "texture"); } + LightspaceBoundingBoxShader::LightspaceBoundingBoxShader() + { + Program = LoadProgram(OBJECT, + GL_COMPUTE_SHADER, file_manager->getAsset("shaders/Lightspaceboundingbox.comp").c_str(), + GL_COMPUTE_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str()); + AssignSamplerNames(Program, 0, "depth"); + AssignUniforms("SunCamMatrix", "split0", "split1", "split2", "splitmax"); + GLuint block_idx = glGetProgramResourceIndex(Program, GL_SHADER_STORAGE_BLOCK, "BoundingBoxes"); + glShaderStorageBlockBinding(Program, block_idx, 2); + } + GlowShader::GlowShader() { Program = LoadProgram(OBJECT, diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index b7ab47882..fb6e946cb 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -511,6 +511,12 @@ public: LinearizeDepthShader(); }; +class LightspaceBoundingBoxShader : public ShaderHelperSingleton, public TextureRead < Nearest_Filtered > +{ +public: + LightspaceBoundingBoxShader(); +}; + class GlowShader : public ShaderHelperSingleton, public TextureRead { public: From 909948c9a4fc543d71d6dc69c90c9e15996499c1 Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Sun, 26 Oct 2014 23:16:42 +0100 Subject: [PATCH 15/15] Implement depth histogram to position cascade split --- data/shaders/depthhistogram.comp | 55 ++++++++++++++++++++++++ src/graphics/post_processing.cpp | 1 + src/graphics/render.cpp | 72 ++++++++++++++++++++++++++++++++ src/graphics/shaders.cpp | 14 ++++++- src/graphics/shaders.hpp | 6 +++ 5 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 data/shaders/depthhistogram.comp diff --git a/data/shaders/depthhistogram.comp b/data/shaders/depthhistogram.comp new file mode 100644 index 000000000..76c46e701 --- /dev/null +++ b/data/shaders/depthhistogram.comp @@ -0,0 +1,55 @@ +uniform sampler2D depth; + +layout (local_size_x = 32, local_size_y = 32) in; + +layout (std430) buffer Histogram +{ + int bin[1024]; + int mindepth; + int maxdepth; + int count; +}; + +vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix); + +shared int sbin[1024]; +shared int smindepth; +shared int smaxdepth; +shared int scount; + +void main() +{ + int x = int(gl_GlobalInvocationID.x), y = int(gl_GlobalInvocationID.y); + vec2 uv = vec2(x, y) / screen; + float z = texture(depth, uv).x; + vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix); + + int lineardepth = int(xpos.z * 4); + + + sbin[gl_LocalInvocationIndex] = 0; + if (gl_LocalInvocationIndex == 0) { + smindepth = 1000; + smaxdepth = 0; + scount = 0; + } + + barrier(); + + if (lineardepth < 1000) { + atomicAdd(sbin[lineardepth], 1); + atomicAdd(scount, 1); + atomicMin(smindepth, lineardepth); + atomicMax(smaxdepth, lineardepth); + } + + barrier(); + + atomicAdd(bin[gl_LocalInvocationIndex], sbin[gl_LocalInvocationIndex]); + if (gl_LocalInvocationIndex == 0) { + atomicAdd(count, scount); + atomicMin(mindepth, smindepth); + atomicMax(maxdepth, smaxdepth); + } +} + diff --git a/src/graphics/post_processing.cpp b/src/graphics/post_processing.cpp index 1e18359dd..dc434116d 100644 --- a/src/graphics/post_processing.cpp +++ b/src/graphics/post_processing.cpp @@ -453,6 +453,7 @@ void PostProcessing::renderSSAO() DrawFullScreenEffect(irr_driver->getSSAORadius(), irr_driver->getSSAOK(), irr_driver->getSSAOSigma()); } + void PostProcessing::renderFog() { const Track * const track = World::getWorld()->getTrack(); diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 46f2f1184..654f8d6f5 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -657,17 +657,28 @@ struct CascadeBoundingBox 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]; @@ -682,6 +693,14 @@ void IrrDriver::UpdateSplitAndLightcoordRangeFromComputeShaders(size_t width, si 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 @@ -691,18 +710,71 @@ void IrrDriver::UpdateSplitAndLightcoordRangeFromComputeShaders(size_t width, si 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); diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index af57d6a9f..4bddbfca4 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -1619,7 +1619,7 @@ namespace FullScreenShader // Use 8 to circumvent a catalyst bug when binding sampler AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 8, "shadowtex"); - AssignUniforms("direction", "col"); + AssignUniforms("split0", "split1", "split2", "splitmax", "direction", "col"); } RadianceHintsConstructionShader::RadianceHintsConstructionShader() @@ -1789,6 +1789,7 @@ namespace FullScreenShader AssignSamplerNames(Program, 0, "texture"); } + LightspaceBoundingBoxShader::LightspaceBoundingBoxShader() { Program = LoadProgram(OBJECT, @@ -1800,6 +1801,17 @@ namespace FullScreenShader glShaderStorageBlockBinding(Program, block_idx, 2); } + DepthHistogramShader::DepthHistogramShader() + { + Program = LoadProgram(OBJECT, + GL_COMPUTE_SHADER, file_manager->getAsset("shaders/depthhistogram.comp").c_str(), + GL_COMPUTE_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str()); + AssignSamplerNames(Program, 0, "depth"); + + GLuint block_idx = glGetProgramResourceIndex(Program, GL_SHADER_STORAGE_BLOCK, "Histogram"); + glShaderStorageBlockBinding(Program, block_idx, 1); + } + GlowShader::GlowShader() { Program = LoadProgram(OBJECT, diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index fb6e946cb..e2d4f062f 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -517,6 +517,12 @@ public: LightspaceBoundingBoxShader(); }; +class DepthHistogramShader : public ShaderHelperSingleton, public TextureRead +{ +public: + DepthHistogramShader(); +}; + class GlowShader : public ShaderHelperSingleton, public TextureRead { public: