diff --git a/.travis.yml b/.travis.yml index aa360748304..86a20337874 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ script: # Build commands - mkdir build - cd build - - cmake .. -DCMAKE_BUILD_TYPE=Debug + - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCHECK_ASSETS=off - make VERBOSE=1 -j 4 notifications: irc: diff --git a/CMakeLists.txt b/CMakeLists.txt index aec8eb348bf..3d94deb4063 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ endif() option(USE_WIIUSE "Support for wiimote input devices" ON) option(USE_FRIBIDI "Support for right-to-left languages" ON) +option(CHECK_ASSETS "Check if assets are installed in ../stk-assets" ON) + if(UNIX) option(USE_CPP2011 "Activate C++ 2011 mode (GCC only)" OFF) endif() @@ -313,6 +315,21 @@ install(FILES ${PROJECT_BINARY_DIR}/supertuxkart.desktop DESTINATION share/appli install(FILES data/supertuxkart_32.png data/supertuxkart_128.png DESTINATION share/pixmaps) install(FILES data/supertuxkart.appdata DESTINATION share/appdata) +# ==== Checking if data folder exists ==== +if(NOT IS_DIRECTORY ../data) + message( FATAL_ERROR "${CMAKE_CURRENT_SOURCE_DIR}/data folder doesn't exist" ) +endif() + +# ==== Checking if stk-assets folder exists ==== +if(CHECK_ASSETS) + if(NOT IS_DIRECTORY ../../stk-assets) + set (CUR_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + get_filename_component(PARENT_DIR ${CUR_DIR} PATH) + message( FATAL_ERROR "${PARENT_DIR}/stk-assets folder doesn't exist. " + "Please download the stk-assets, or disable this test with -DCHECK_ASSETS=off." ) + endif() +endif() + set(PREFIX ${CMAKE_INSTALL_PREFIX}) configure_file(data/supertuxkart_desktop.template supertuxkart.desktop) add_dependencies(supertuxkart supertuxkart.desktop) diff --git a/data/shaders/pointlight.frag b/data/shaders/pointlight.frag index 6369a7850a4..398506752d3 100644 --- a/data/shaders/pointlight.frag +++ b/data/shaders/pointlight.frag @@ -32,8 +32,7 @@ void main() vec3 light_pos = pseudocenter.xyz; vec3 light_col = col.xyz; float d = distance(light_pos, xpos.xyz); - float att = energy * 200. / (1 + d + 4. * 3.14 * d * d); - float spec_att = energy * 200. / (1 + d + 4. * 3.14 * d * d); + float att = energy * 200. / (1. + 33. * d + 33. * d * d); // Light Direction vec3 L = -normalize(xpos.xyz - light_pos); @@ -41,5 +40,5 @@ void main() float NdotL = max(0., dot(norm, L)); Diffuse = vec4(NdotL * light_col * att, 1.); - Specular = vec4(getSpecular(norm, eyedir, L, light_col, roughness) * NdotL * spec_att, 1.); + Specular = vec4(getSpecular(norm, eyedir, L, light_col, roughness) * NdotL * att, 1.); } diff --git a/data/shaders/pointlight.vert b/data/shaders/pointlight.vert index 1831d4559b5..dc854fd38af 100644 --- a/data/shaders/pointlight.vert +++ b/data/shaders/pointlight.vert @@ -16,7 +16,7 @@ const float zNear = 1.; void main(void) { // Beyond that value, light is too attenuated - float r = 500 * Energy; + float r = 100 * Energy; center = Position; energy = Energy; vec4 Center = ViewMatrix * vec4(Position, 1.); diff --git a/data/shaders/sunlightshadow.frag b/data/shaders/sunlightshadow.frag index 64ef8f36510..4dd96f04155 100644 --- a/data/shaders/sunlightshadow.frag +++ b/data/shaders/sunlightshadow.frag @@ -53,7 +53,7 @@ float getShadowFactor(vec3 pos, float bias, int index) float sum = 0.; for (int i = 0; i < 4; i++) { - sum += texture(shadowtex, vec4(shadowtexcoord + shadowoffset[i] / 2048., float(index), 0.5 * (shadowcoord.z - bias * 0.01) + 0.5)); + sum += texture(shadowtex, vec4(shadowtexcoord + shadowoffset[i] / 2048., float(index), 0.5 * shadowcoord.z + 0.5)); } return sum / 4.; } @@ -88,8 +88,8 @@ void main() { // } // Shadows - float bias = 0.002 * tan(acos(NdotL)); // According to the slope - bias = clamp(bias, 0.001, 0.014); + float bias = 0.005 * tan(acos(NdotL)); // According to the slope + bias = clamp(bias, 0., 0.01); float factor; if (xpos.z < 5.) factor = getShadowFactor(xpos.xyz, bias, 0); diff --git a/data/shaders/sunlightshadowdebug.frag b/data/shaders/sunlightshadowdebug.frag index 96a4d3cb810..b0c39ec8e4e 100644 --- a/data/shaders/sunlightshadowdebug.frag +++ b/data/shaders/sunlightshadowdebug.frag @@ -22,7 +22,7 @@ out vec4 Spec; vec3 DecodeNormal(vec2 n); vec3 getSpecular(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness); -vec3 getShadowFactor(vec3 pos, float bias) +vec3 getShadowFactor(vec3 pos) { vec3 cascadeColor[] = vec3[]( vec3(1., 0., 0.), @@ -37,7 +37,7 @@ vec3 getShadowFactor(vec3 pos, float bias) vec2 shadowtexcoord = shadowcoord.xy * 0.5 + 0.5; if (shadowtexcoord.x < 0. || shadowtexcoord.x > 1. || shadowtexcoord.y < 0. || shadowtexcoord.y > 1.) continue; - return cascadeColor[i] * texture(shadowtex, vec4(shadowtexcoord, float(i), 0.5 * (shadowcoord.z + bias * 0.001) + 0.5)); + return cascadeColor[i] * texture(shadowtex, vec4(shadowtexcoord, float(i), 0.5 * shadowcoord.z + 0.5)); } return vec3(1.); } @@ -61,9 +61,7 @@ void main() { vec3 outcol = NdotL * col; // Shadows - float bias = 0.002 * tan(acos(NdotL)); // According to the slope - bias = clamp(bias, 0.001, 0.014); - vec3 factor = getShadowFactor(xpos.xyz, bias); + vec3 factor = getShadowFactor(xpos.xyz); Diff = vec4(factor * NdotL * col, 1.); Spec = vec4(factor * Specular, 1.); return; diff --git a/data/shaders/tonemap.frag b/data/shaders/tonemap.frag index 9e23b9bc526..4b8077317ec 100644 --- a/data/shaders/tonemap.frag +++ b/data/shaders/tonemap.frag @@ -2,6 +2,8 @@ uniform sampler2D tex; uniform sampler2D logluminancetex; +uniform float exposure = .09; +uniform float Lwhite = 1.; in vec2 uv; out vec4 FragColor; @@ -9,8 +11,7 @@ out vec4 FragColor; vec3 getCIEYxy(vec3 rgbColor); vec3 getRGBFromCIEXxy(vec3 YxyColor); -float exposure = .09; -float Lwhite = 1.; + float delta = .0001; float saturation = 1.; @@ -22,10 +23,16 @@ void main() vec3 Cw = getCIEYxy(col.xyz); float Lw = Cw.y; - float L = Lw * exposure / avgLw; - float Ld = L * (1. + L / (Lwhite * Lwhite)); - Ld /= (1. + L); - FragColor = vec4(Ld * pow(col.xyz / Lw, vec3(saturation)), 1.); + /* Reinhard, for reference */ +// float L = Lw * exposure / avgLw; +// float Ld = L * (1. + L / (Lwhite * Lwhite)); +// Ld /= (1. + L); +// FragColor = vec4(Ld * pow(col.xyz / Lw, vec3(saturation)), 1.); + + // Uncharted2 tonemap with Auria's custom coefficients + vec4 perChannel = (col * (6.9 * col + .5)) / (col * (5.2 * col + 1.7) + 0.06); + perChannel = pow(perChannel, vec4(2.2)); + FragColor = vec4(perChannel.xyz, 1.); } diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index 60bb9839b36..3d1d995ce0d 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -99,6 +99,8 @@ class IrrDriver : public IEventReceiver, public NoCopy Shaders *m_shaders; /** Wind. */ Wind *m_wind; + float m_exposure; + float m_lwhite; /** RTTs. */ RTT *m_rtts; /** Shadow importance. */ @@ -160,6 +162,26 @@ class IrrDriver : public IEventReceiver, public NoCopy return 120; } + float getExposure() const + { + return m_exposure; + } + + void setExposure(float v) + { + m_exposure = v; + } + + float getLwhite() const + { + return m_lwhite; + } + + void setLwhite(float v) + { + m_lwhite = v; + } + private: std::vector m_modes; diff --git a/src/graphics/post_processing.cpp b/src/graphics/post_processing.cpp index 70ff32bc7a8..96cc955d0bd 100644 --- a/src/graphics/post_processing.cpp +++ b/src/graphics/post_processing.cpp @@ -530,7 +530,7 @@ static void toneMap(GLuint fbo, GLuint rtt) glBindVertexArray(FullScreenShader::ToneMapShader::vao); setTexture(0, rtt, GL_NEAREST, GL_NEAREST); setTexture(1, irr_driver->getRenderTargetTexture(RTT_LOG_LUMINANCE), GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST); - FullScreenShader::ToneMapShader::setUniforms(0, 1); + FullScreenShader::ToneMapShader::setUniforms(irr_driver->getExposure(), irr_driver->getLwhite(), 0, 1); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -655,7 +655,8 @@ void PostProcessing::render() std::swap(in_fbo, out_fbo); PROFILER_PUSH_CPU_MARKER("- Godrays", 0xFF, 0x00, 0x00); - if (UserConfigParams::m_light_shaft && m_sunpixels > 30)//World::getWorld()->getTrack()->hasGodRays() && ) // god rays + const bool hasgodrays = World::getWorld()->getTrack()->hasGodRays(); + if (UserConfigParams::m_light_shaft && m_sunpixels > 30 && hasgodrays) { glEnable(GL_DEPTH_TEST); // Grab the sky diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 3c78c9d792c..d19277decd6 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -236,7 +236,7 @@ void IrrDriver::renderGLSL(float dt) // Is the lens flare enabled & visible? Check last frame's query. const bool hasflare = World::getWorld()->getTrack()->hasLensFlare(); const bool hasgodrays = World::getWorld()->getTrack()->hasGodRays(); - if (UserConfigParams::m_light_shaft)//hasflare || hasgodrays) + if (UserConfigParams::m_light_shaft && hasgodrays)//hasflare || hasgodrays) { irr::video::COpenGLDriver* gl_driver = (irr::video::COpenGLDriver*)m_device->getVideoDriver(); @@ -665,8 +665,8 @@ void IrrDriver::renderShadows(//ShadowImportanceProvider * const sicb, irr_driver->setPhase(SHADOW_PASS); glDisable(GL_BLEND); - glEnable(GL_CULL_FACE); - glCullFace(GL_FRONT); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.5, 0.); glBindFramebuffer(GL_FRAMEBUFFER, m_rtts->getShadowFBO()); glViewport(0, 0, 1024, 1024); glClear(GL_DEPTH_BUFFER_BIT); @@ -674,7 +674,7 @@ void IrrDriver::renderShadows(//ShadowImportanceProvider * const sicb, glBindBufferBase(GL_UNIFORM_BUFFER, 0, SharedObject::ViewProjectionMatrixesUBO); m_scene_manager->drawAll(scene::ESNRP_SOLID); - glCullFace(GL_BACK); + glDisable(GL_POLYGON_OFFSET_FILL); glViewport(0, 0, UserConfigParams::m_width, UserConfigParams::m_height); @@ -901,7 +901,7 @@ void IrrDriver::renderLights(const core::aabbox3df& cambox, if (!m_lights[i]->isPointLight()) { m_lights[i]->render(); - if (UserConfigParams::m_shadows) + if (UserConfigParams::m_shadows && World::getWorld()->getTrack()->hasShadows()) m_post_processing->renderShadowedSunlight(sun_ortho_matrix, m_rtts->getShadowDepthTex()); else m_post_processing->renderSunlight(); @@ -1391,14 +1391,20 @@ void IrrDriver::generateSkyboxCubemap() int sh_w = 16; int sh_h = 16; + const video::SColorf& ambientf = irr_driver->getSceneManager()->getAmbientLight(); + video::SColor ambient = ambientf.toSColor(); + char *sh_rgba[6]; for (unsigned i = 0; i < 6; i++) { sh_rgba[i] = new char[sh_w * sh_h * 4]; - for (int j = 0; j < sh_w * sh_h * 4; j++) + for (int j = 0; j < sh_w * sh_h * 4; j+=4) { - sh_rgba[i][j] = 150; + sh_rgba[i][j] = ambient.getBlue(); + sh_rgba[i][j + 1] = ambient.getGreen(); + sh_rgba[i][j + 2] = ambient.getRed(); + sh_rgba[i][j + 3] = 255; } } diff --git a/src/graphics/shaders.cpp b/src/graphics/shaders.cpp index 0494c6adbb3..0c5a8ca3c64 100644 --- a/src/graphics/shaders.cpp +++ b/src/graphics/shaders.cpp @@ -2069,6 +2069,8 @@ namespace FullScreenShader GLuint ToneMapShader::Program; GLuint ToneMapShader::uniform_tex; GLuint ToneMapShader::uniform_logluminancetex; + GLuint ToneMapShader::uniform_exposure; + GLuint ToneMapShader::uniform_lwhite; GLuint ToneMapShader::vao; void ToneMapShader::init() @@ -2080,13 +2082,17 @@ namespace FullScreenShader GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/tonemap.frag").c_str()); uniform_tex = glGetUniformLocation(Program, "tex"); uniform_logluminancetex = glGetUniformLocation(Program, "logluminancetex"); + uniform_exposure = glGetUniformLocation(Program, "exposure"); + uniform_lwhite = glGetUniformLocation(Program, "Lwhite"); vao = createVAO(Program); } - void ToneMapShader::setUniforms(unsigned TU_tex, unsigned TU_loglum) + void ToneMapShader::setUniforms(float exposure, float Lwhite, unsigned TU_tex, unsigned TU_loglum) { glUniform1i(uniform_tex, TU_tex); glUniform1i(uniform_logluminancetex, TU_loglum); + glUniform1f(uniform_exposure, exposure); + glUniform1f(uniform_lwhite, Lwhite); } GLuint DepthOfFieldShader::Program; diff --git a/src/graphics/shaders.hpp b/src/graphics/shaders.hpp index bf5e2af1ed2..8a6b62ccf99 100644 --- a/src/graphics/shaders.hpp +++ b/src/graphics/shaders.hpp @@ -524,11 +524,11 @@ class ToneMapShader { public: static GLuint Program; - static GLuint uniform_tex, uniform_logluminancetex; + static GLuint uniform_tex, uniform_logluminancetex, uniform_exposure, uniform_lwhite; static GLuint vao; static void init(); - static void setUniforms(unsigned TU_tex, unsigned TU_logluminance); + static void setUniforms(float exposure, float Lwhite, unsigned TU_tex, unsigned TU_logluminance); }; class DepthOfFieldShader diff --git a/src/graphics/stkmeshscenenode.cpp b/src/graphics/stkmeshscenenode.cpp index f5fe882ad16..04c1209d03e 100644 --- a/src/graphics/stkmeshscenenode.cpp +++ b/src/graphics/stkmeshscenenode.cpp @@ -462,10 +462,12 @@ void STKMeshSceneNode::render() glDisable(GL_CULL_FACE); GLMesh* mesh; - if (!GeometricMesh[FPSM_DEFAULT].empty()) + if (!GeometricMesh[FPSM_DEFAULT].empty() || !GeometricMesh[FPSM_NORMAL_MAP].empty()) glUseProgram(MeshShader::ShadowShader::Program); for_in(mesh, GeometricMesh[FPSM_DEFAULT]) drawShadow(*mesh, AbsoluteTransformation); + for_in(mesh, GeometricMesh[FPSM_NORMAL_MAP]) + drawShadow(*mesh, AbsoluteTransformation); if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty()) glUseProgram(MeshShader::RefShadowShader::Program); diff --git a/src/states_screens/dialogs/debug_slider.cpp b/src/states_screens/dialogs/debug_slider.cpp index 4c5b02c57f4..d8b7b95366b 100644 --- a/src/states_screens/dialogs/debug_slider.cpp +++ b/src/states_screens/dialogs/debug_slider.cpp @@ -26,6 +26,7 @@ #include "modes/world.hpp" #include "states_screens/state_manager.hpp" #include "utils/translation.hpp" +#include "graphics/irr_driver.hpp" using namespace GUIEngine; @@ -47,6 +48,14 @@ DebugSliderDialog::DebugSliderDialog(std::string id, irr::core::stringw msg) : LabelWidget* message = getWidget("title"); message->setText( msg.c_str(), false ); + + float val; + if (m_id == "lwhite") + val = irr_driver->getLwhite() * 10.; + if (m_id == "exposure") + val = irr_driver->getExposure() * 100.; + + getWidget("value_slider")->setValue(val); } // ------------------------------------------------------------------------------------------------------ @@ -73,6 +82,10 @@ GUIEngine::EventPropagation DebugSliderDialog::processEvent(const std::string& e { int value = getWidget("value_slider")->getValue(); Log::info("DebugSlider", "Value for <%s> : %i", m_id.c_str(), value); + if (m_id == "lwhite") + irr_driver->setLwhite(value / 10.); + if (m_id == "exposure") + irr_driver->setExposure(value / 100.); return GUIEngine::EVENT_BLOCK; } diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 9e7f1e0a48c..cf6068168be 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -356,6 +356,8 @@ void Track::cleanup() //----------------------------------------------------------------------------- void Track::loadTrackInfo() { + irr_driver->setLwhite(1.); + irr_driver->setExposure(0.09); // Default values m_use_fog = false; m_fog_max = 1.0f;