Merged with trunk, part 1 (due to previous failures I am splitting this

patch).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/uni@14605 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2013-12-02 04:27:55 +00:00
parent c0783283e0
commit bced8cdb9f
559 changed files with 12644 additions and 27623 deletions

View File

@ -1139,7 +1139,7 @@ MATHJAX_RELPATH = http://www.mathjax.org/mathjax
# typically be disabled. For large projects the javascript based search engine
# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
SEARCHENGINE = NO
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a PHP enabled web server instead of at the web client

View File

@ -1202,7 +1202,7 @@ MATHJAX_EXTENSIONS =
# typically be disabled. For large projects the javascript based search engine
# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
SEARCHENGINE = NO
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a PHP enabled web server instead of at the web client

View File

@ -69,10 +69,14 @@ supertuxkart_SOURCES = \
config/device_config.hpp \
graphics/CBatchingMesh.cpp \
graphics/CBatchingMesh.hpp \
graphics/callbacks.cpp \
graphics/callbacks.hpp \
graphics/camera.cpp \
graphics/camera.hpp \
graphics/explosion.cpp \
graphics/explosion.hpp \
graphics/glow.cpp \
graphics/glow.hpp \
graphics/hardware_skinning.cpp \
graphics/hardware_skinning.hpp \
graphics/hit_effect.hpp \
@ -80,6 +84,11 @@ supertuxkart_SOURCES = \
graphics/hit_sfx.hpp \
graphics/irr_driver.cpp \
graphics/irr_driver.hpp \
graphics/large_mesh_buffer.hpp \
graphics/lens_flare.cpp \
graphics/lens_flare.hpp \
graphics/light.hpp \
graphics/light.cpp \
graphics/lod_node.cpp \
graphics/lod_node.hpp \
graphics/material.cpp \
@ -102,10 +111,19 @@ supertuxkart_SOURCES = \
graphics/post_processing.hpp \
graphics/rain.cpp \
graphics/rain.hpp \
graphics/render.cpp \
graphics/referee.cpp \
graphics/referee.hpp \
graphics/rtts.hpp \
graphics/rtts.cpp \
graphics/screenquad.cpp \
graphics/screenquad.hpp \
graphics/shaders.cpp \
graphics/shaders.hpp \
graphics/shadow.cpp \
graphics/shadow.hpp \
graphics/shadow_importance.cpp \
graphics/shadow_importance.hpp \
graphics/show_curve.cpp \
graphics/show_curve.hpp \
graphics/skid_marks.cpp \
@ -114,6 +132,12 @@ supertuxkart_SOURCES = \
graphics/slip_stream.hpp \
graphics/stars.cpp \
graphics/stars.hpp \
graphics/sun.hpp \
graphics/sun.cpp \
graphics/water.hpp \
graphics/water.cpp \
graphics/wind.hpp \
graphics/wind.cpp \
guiengine/CGUISpriteBank.cpp \
guiengine/CGUISpriteBank.h \
guiengine/abstract_state_manager.cpp \
@ -496,6 +520,8 @@ supertuxkart_SOURCES = \
utils/aligned_array.hpp \
utils/constants.hpp \
utils/constants.cpp \
utils/helpers.hpp \
utils/helpers.cpp \
utils/leak_check.cpp \
utils/leak_check.hpp \
utils/log.cpp \
@ -510,6 +536,7 @@ supertuxkart_SOURCES = \
utils/string_utils.hpp \
utils/synchronised.hpp \
utils/time.hpp \
utils/time.cpp \
utils/translation.cpp \
utils/translation.hpp \
utils/utf8.h \
@ -517,7 +544,8 @@ supertuxkart_SOURCES = \
utils/utf8/core.h \
utils/utf8/unchecked.h \
utils/vec3.cpp \
utils/vec3.hpp
utils/vec3.hpp \
utils/vs.hpp
# Link in the specific gcc 4.1 bug work around
supertuxkart_LDADD = \

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Lucas Baudin, Joerg Henrichs
// Copyright (C) 2010-2013 Lucas Baudin, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -162,7 +162,7 @@ void Addon::writeXML(std::ofstream *out_stream)
// ----------------------------------------------------------------------------
std::string Addon::getDateAsString() const
{
return Time::toString(m_date);
return StkTime::toString(m_date);
} // getDateAsString
// ----------------------------------------------------------------------------

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Lucas Baudin, Joerg Henrichs
// Copyright (C) 2010-2013 Lucas Baudin, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -99,7 +99,7 @@ private:
* in the addons.xml file. */
bool m_still_exists;
/** Date when the addon was added. */
Time::TimeType m_date;
StkTime::TimeType m_date;
/** A description of this addon. */
core::stringw m_description;
/** The URL of the icon (relative to the server) */
@ -171,7 +171,7 @@ public:
// ------------------------------------------------------------------------
/** Returns the date (in seconds since epoch) when the addon was
* uploaded. */
Time::TimeType getDate() const { return m_date; }
StkTime::TimeType getDate() const { return m_date; }
// ------------------------------------------------------------------------
/** Returns a user readable date as a string. */
std::string getDateAsString() const;

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Lucas Baudin
// Copyright (C) 2010-2013 Lucas Baudin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Lucas Baudin, Joerg Henrichs
// Copyright (C) 2010-2013 Lucas Baudin, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Lucas Baudin
// Copyright (C) 2010-2013 Lucas Baudin
// 2011 Lucas Baudin, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2012 Joerg Henrichs
// Copyright (C) 2012-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Lucas Baudin
// 2011 Lucas Baudin, Joerg Henrichs
// Copyright (C) 2010-2013 Lucas Baudin
// Copyright (C) 2011-2013 Lucas Baudin, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Lucas Baudin
// 2011 Lucas Baudin, Joerg Henrichs
// Copyright (C) 2010-2013 Lucas Baudin
// Copyright (C) 2011-2013 Lucas Baudin, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -24,14 +24,7 @@
#include <errno.h>
#include <stdio.h>
#include <string>
#if defined(WIN32) && !defined(__CYGWIN__)
# include <windows.h>
# define isnan _isnan
#else
# include <sys/time.h>
# include <math.h>
#endif
#include <math.h>
#include "addons/news_manager.hpp"
#include "addons/request.hpp"
@ -42,6 +35,7 @@
#include "utils/string_utils.hpp"
#include "utils/time.hpp"
#include "utils/translation.hpp"
#include "utils/vs.hpp"
// ----------------------------------------------------------------------------
/** Create a thread that handles all network functions independent of the
@ -270,7 +264,7 @@ CURLcode NetworkHttp::init(bool forceRefresh)
bool download = UserConfigParams::m_news_last_updated==0 ||
UserConfigParams::m_news_last_updated
+UserConfigParams::m_news_frequency
< Time::getTimeSinceEpoch() || forceRefresh;
< StkTime::getTimeSinceEpoch() || forceRefresh;
if(!download)
{
@ -303,7 +297,7 @@ CURLcode NetworkHttp::init(bool forceRefresh)
{
std::string xml_file = file_manager->getAddonsFile("news.xml");
if(download)
UserConfigParams::m_news_last_updated = Time::getTimeSinceEpoch();
UserConfigParams::m_news_last_updated = StkTime::getTimeSinceEpoch();
const XMLNode *xml = new XMLNode(xml_file);
// A proper news file has at least a version number, mtime, and
@ -319,7 +313,7 @@ CURLcode NetworkHttp::init(bool forceRefresh)
status = downloadFileInternal(&r);
if(status==CURLE_OK)
UserConfigParams::m_news_last_updated =
Time::getTimeSinceEpoch();
StkTime::getTimeSinceEpoch();
delete xml;
xml = new XMLNode(xml_file);
}
@ -416,7 +410,7 @@ CURLcode NetworkHttp::loadAddonsList(const XMLNode *xml,
bool forceRefresh)
{
std::string addon_list_url("");
Time::TimeType mtime(0);
StkTime::TimeType mtime(0);
const XMLNode *include = xml->getNode("include");
if(include)
{
@ -456,7 +450,7 @@ CURLcode NetworkHttp::loadAddonsList(const XMLNode *xml,
{
std::string xml_file = file_manager->getAddonsFile("addons.xml");
if(download)
UserConfigParams::m_addons_last_updated=Time::getTimeSinceEpoch();
UserConfigParams::m_addons_last_updated=StkTime::getTimeSinceEpoch();
const XMLNode *xml = new XMLNode(xml_file);
addons_manager->initOnline(xml);
if(UserConfigParams::logAddons())

View File

@ -1,6 +1,6 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Lucas Baudin
// 2011 Lucas Baudin, Joerg Henrichs
// Copyright (C) 2010-2013 Lucas Baudin
// Copyright (C) 2011-2013 Lucas Baudin, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs
// Copyright (C) 2011-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -50,7 +50,7 @@ NewsManager::~NewsManager()
*/
void NewsManager::init()
{
UserConfigParams::m_news_last_updated = Time::getTimeSinceEpoch();
UserConfigParams::m_news_last_updated = StkTime::getTimeSinceEpoch();
std::string xml_file = file_manager->getAddonsFile("news.xml");
const XMLNode *xml = new XMLNode(xml_file);

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs
// Copyright (C) 2011-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs
// Copyright (C) 2011-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs
// Copyright (C) 2011-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Lucas Baudin
// Copyright (C) 2010-2013 Lucas Baudin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Lucas Baudin
// Copyright (C) 2010-2013 Lucas Baudin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
// Copyright (C) 2009-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -21,14 +21,10 @@
#include "animations/ipo.hpp"
#include "io/file_manager.hpp"
#include "io/xml_node.hpp"
#include "utils/vs.hpp"
#include <algorithm>
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
# define isnan _isnan
#else
# include <math.h>
#endif
#include <math.h>
AnimationBase::AnimationBase(const XMLNode &node)

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
// Copyright (C) 2009-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
// Copyright (C) 2009-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -19,14 +19,11 @@
#include "animations/ipo.hpp"
#include "io/xml_node.hpp"
#include "utils/vs.hpp"
#include <string.h>
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
# define isnan _isnan
#else
# include <math.h>
#endif
#include <algorithm>
#include <math.h>
const std::string Ipo::m_all_channel_names[IPO_MAX] =
{"LocX", "LocY", "LocZ", "LocXYZ",

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
// Copyright (C) 2009-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
// Copyright (C) 2009-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
// Copyright (C) 2009-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,7 +1,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2008 Joerg Henrichs, Patrick Ammann
// Copyright (C) 2006-2013 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2008-2013 Joerg Henrichs, Patrick Ammann
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2006-2013 Patrick Ammann <pammann@aro.ch>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2006-2013 Patrick Ammann <pammann@aro.ch>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
// Copyright (C) 2008-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
// Copyright (C) 2008-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,7 +1,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2008 Patrick Ammann <pammann@aro.ch>, Joerg Henrichs
// Copyright (C) 2006-2013 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2008-2013 Patrick Ammann <pammann@aro.ch>, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,7 +1,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2008 Patrick Ammann <pammann@aro.ch>, Joerg Henrichs
// Copyright (C) 2006-2013 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2008-2013 Patrick Ammann <pammann@aro.ch>, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2007 Damien Morel <divdams@free.fr>
// Copyright (C) 2007-2013 Damien Morel <divdams@free.fr>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2007 Damien Morel <divdams@free.fr>
// Copyright (C) 2007-2013 Damien Morel <divdams@free.fr>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,7 +1,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2008 Joerg Henrichs, Patrick Ammann
// Copyright (C) 2006-2013 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2008-2013 Joerg Henrichs, Patrick Ammann
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -55,6 +55,7 @@ public:
virtual void resume() = 0;
virtual void speed(float factor) = 0;
virtual void volume(float gain) = 0;
virtual void masterVolume(float gain) = 0;
virtual SFXManager::SFXStatus
getStatus() = 0;
virtual void onSoundEnabledBack() = 0;

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Marianne Gagnon
// Copyright (C) 2010-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -18,6 +18,7 @@
#include "audio/sfx_buffer.hpp"
#include "audio/sfx_manager.hpp"
#include "config/user_config.hpp"
#include "io/file_manager.hpp"
#include "utils/constants.hpp"
@ -76,6 +77,8 @@ SFXBuffer::SFXBuffer(const std::string& file,
bool SFXBuffer::load()
{
if (UserConfigParams::m_sfx == false) return false;
#if HAVE_OGGVORBIS
if (m_loaded) return false;

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Marianne Gagnon
// Copyright (C) 2010-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
// Copyright (C) 2008-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -154,14 +154,16 @@ void SFXManager::loadSfx()
std::cerr << "Could not read sounf effects XML file " << sfx_config_name.c_str() << std::endl;
}
int i;
const int amount = root->getNumNodes();
for (int i=0; i<amount; i++)
for (i=0; i<amount; i++)
{
const XMLNode* node = root->getNode(i);
if (node->getName() == "sfx")
{
loadSingleSfx(node);
loadSingleSfx(node, "", false);
}
else
{
@ -171,7 +173,27 @@ void SFXManager::loadSfx()
}// nend for
delete root;
} // loadSfx
// Now load them in parallel
const int max = m_all_sfx_types.size();
SFXBuffer **array = new SFXBuffer *[max];
i = 0;
for (std::map<std::string, SFXBuffer*>::iterator it = m_all_sfx_types.begin();
it != m_all_sfx_types.end(); it++)
{
SFXBuffer* const buffer = (*it).second;
array[i++] = buffer;
}
#pragma omp parallel for private(i)
for (i = 0; i < max; i++)
{
array[i]->load();
}
delete [] array;
} // loadSfx
// -----------------------------------------------------------------------------
/** Introduces a mechanism by which one can load sound effects beyond the basic
@ -188,7 +210,8 @@ SFXBuffer* SFXManager::addSingleSfx(const std::string &sfx_name,
bool positional,
float rolloff,
float max_width,
float gain)
float gain,
const bool load)
{
SFXBuffer* buffer = new SFXBuffer(sfx_file, positional, rolloff, max_width, gain);
@ -205,7 +228,7 @@ SFXBuffer* SFXManager::addSingleSfx(const std::string &sfx_name,
if (UserConfigParams::logMisc())
Log::debug("SFXManager", "Loading SFX %s\n", sfx_file.c_str());
if (buffer->load()) return buffer;
if (load && buffer->load()) return buffer;
return NULL;
} // addSingleSFX
@ -215,7 +238,8 @@ SFXBuffer* SFXManager::addSingleSfx(const std::string &sfx_name,
* \param node The XML node with the data for this sfx.
*/
SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
const std::string &path)
const std::string &path,
const bool load)
{
std::string filename;
@ -254,7 +278,8 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
tmpbuffer.isPositional(),
tmpbuffer.getRolloff(),
tmpbuffer.getMaxDist(),
tmpbuffer.getGain());
tmpbuffer.getGain(),
load);
} // loadSingleSfx
@ -288,7 +313,7 @@ SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
SFXBase* sfx = new DummySFX(buffer, positional, buffer->getGain(), owns_buffer);
#endif
sfx->volume(m_master_gain);
sfx->masterVolume(m_master_gain);
if (add_to_SFX_list) m_all_sfx.push_back(sfx);
@ -442,7 +467,7 @@ void SFXManager::setMasterSFXVolume(float gain)
for (std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
i!=m_all_sfx.end(); i++)
{
(*i)->volume(m_master_gain);
(*i)->masterVolume(m_master_gain);
} // for i in m_all_sfx
}
@ -451,7 +476,7 @@ void SFXManager::setMasterSFXVolume(float gain)
std::map<std::string, SFXBase*>::iterator i = m_quick_sounds.begin();
for (; i != m_quick_sounds.end(); i++)
{
(*i).second->volume(m_master_gain);
(*i).second->masterVolume(m_master_gain);
}
}

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
// Copyright (C) 2008-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -106,13 +106,15 @@ public:
virtual ~SFXManager();
bool sfxAllowed();
SFXBuffer* loadSingleSfx(const XMLNode* node,
const std::string &path=std::string(""));
const std::string &path=std::string(""),
const bool load = true);
SFXBuffer* addSingleSfx(const std::string &sfx_name,
const std::string &filename,
bool positional,
float rolloff,
float max_width,
float gain);
float gain,
const bool load = true);
SFXBase* createSoundSource(SFXBuffer* info,
const bool addToSFXList=true,

View File

@ -1,7 +1,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Patrick Ammann <pammann@aro.ch>
// 2009-2011 Marianne Gagnon
// Copyright (C) 2006-2013 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2009-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -20,11 +20,11 @@
#if HAVE_OGGVORBIS
#include "audio/sfx_openal.hpp"
#include "audio/sfx_buffer.hpp"
#include "config/user_config.hpp"
#include "io/file_manager.hpp"
#include "race/race_manager.hpp"
#include <assert.h>
#include <stdio.h>
#include <string>
#ifdef __APPLE__
# include <OpenAL/al.h>
@ -32,8 +32,16 @@
# include <AL/al.h>
#endif
#include "config/user_config.hpp"
#include "io/file_manager.hpp"
#include <assert.h>
#include <stdio.h>
#include <string>
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
# define isnan _isnan
#else
# include <math.h>
#endif
SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain, bool ownsBuffer) : SFXBase()
{
@ -44,6 +52,7 @@ SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain, bool ownsBu
m_defaultGain = gain;
m_loop = false;
m_gain = -1.0f;
m_master_gain = 1.0f;
m_owns_buffer = ownsBuffer;
// Don't initialise anything else if the sfx manager was not correctly
@ -98,11 +107,11 @@ bool SFXOpenAL::init()
if (m_gain < 0.0f)
{
alSourcef (m_soundSource, AL_GAIN, m_defaultGain);
alSourcef (m_soundSource, AL_GAIN, m_defaultGain * m_master_gain);
}
else
{
alSourcef (m_soundSource, AL_GAIN, m_gain);
alSourcef (m_soundSource, AL_GAIN, m_gain * m_master_gain);
}
if (m_positional) alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_FALSE);
@ -121,7 +130,7 @@ bool SFXOpenAL::init()
*/
void SFXOpenAL::speed(float factor)
{
if(!m_ok) return;
if(!m_ok || isnan(factor)) return;
//OpenAL only accepts pitches in the range of 0.5 to 2.0
if(factor > 2.0f)
@ -146,10 +155,22 @@ void SFXOpenAL::volume(float gain)
if(!m_ok) return;
alSourcef(m_soundSource, AL_GAIN, m_defaultGain * gain);
alSourcef(m_soundSource, AL_GAIN, m_gain * m_master_gain);
SFXManager::checkError("setting volume");
} // volume
//-----------------------------------------------------------------------------
void SFXOpenAL::masterVolume(float gain)
{
m_master_gain = gain;
if(!m_ok) return;
alSourcef(m_soundSource, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
SFXManager::checkError("setting volume");
}
//-----------------------------------------------------------------------------
/** Loops this sound effect.
*/
@ -258,7 +279,7 @@ void SFXOpenAL::position(const Vec3 &position)
}
else
{
alSourcef(m_soundSource, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain));
alSourcef(m_soundSource, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
}
SFXManager::checkError("positioning");
@ -295,7 +316,7 @@ void SFXOpenAL::onSoundEnabledBack()
alSourcef(m_soundSource, AL_GAIN, 0);
play();
pause();
alSourcef(m_soundSource, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain));
alSourcef(m_soundSource, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
}
}
}

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2006-2013 Patrick Ammann <pammann@aro.ch>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -56,6 +56,9 @@ private:
sounds later. */
float m_gain;
/** The master gain set in user preferences */
float m_master_gain;
bool m_owns_buffer;
public:
@ -74,6 +77,7 @@ public:
virtual void speed(float factor);
virtual void position(const Vec3 &position);
virtual void volume(float gain);
virtual void masterVolume(float gain);
virtual SFXManager::SFXStatus getStatus();
virtual void onSoundEnabledBack();
virtual void setRolloff(float rolloff);

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
// Copyright (C) 2008-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
// Copyright (C) 2008-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
// Copyright (C) 2008-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
// Copyright (C) 2008-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 SuperTuxKart-Team
// Copyright (C) 2010-2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 SuperTuxKart-Team
// Copyright (C) 2010-2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
// Copyright (C) 2008-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2008 Joerg Henrichs
// Copyright (C) 2008-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 SuperTuxKart-Team
// Copyright (C) 2010-2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 SuperTuxKart-Team
// Copyright (C) 2010-2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2012
// Copyright (C) 2012-2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -79,7 +79,7 @@ void PlayerProfile::incrementUseFrequency()
//------------------------------------------------------------------------------
int64_t PlayerProfile::generateUniqueId(const char* playerName)
{
return ((int64_t)(Time::getTimeSinceEpoch()) << 32) |
return ((int64_t)(StkTime::getTimeSinceEpoch()) << 32) |
((rand() << 16) & 0xFFFF0000) |
(StringUtils::simpleHash(playerName) & 0xFFFF);
}

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 SuperTuxKart-Team
// Copyright (C) 2010-2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013
// Copyright (C) 2013-2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -19,6 +19,7 @@
#include "config/saved_grand_prix.hpp"
#include "karts/kart_properties_manager.hpp"
#include "utils/ptr_vector.hpp"
#include "utils/string_utils.hpp"
@ -145,10 +146,12 @@ void SavedGrandPrix::loadKarts(std::vector<RaceManager::KartStatus> & kart_list)
int aikarts = 0;
for(int i = 0; i < m_karts.size(); i++)
{
const KartProperties *kp = kart_properties_manager->getKart(m_karts[i].m_ident);
if(m_karts[i].m_local_player_id == -1)
{
//AI kart found
kart_list[aikarts].m_ident = m_karts[i].m_ident;
if(kp) kart_list[aikarts].m_ident = m_karts[i].m_ident;
kart_list[aikarts].m_score = m_karts[i].m_score;
kart_list[aikarts].m_overall_time = m_karts[i].m_overall_time;
aikarts++;

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 SuperTuxKart-Team
// Copyright (C) 2010-2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Joerg Henrichs
// Copyright (C) 2006-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -181,6 +181,13 @@ void STKConfig::init_defaults()
m_disable_steer_while_unskid = false;
m_camera_follow_skid = false;
m_nitro_glow_color[0] = 1.0f;
m_nitro_glow_color[1] = 1.0f;
m_nitro_glow_color[2] = 1.0f;
m_box_glow_color[0] = 1.0f;
m_box_glow_color[1] = 1.0f;
m_box_glow_color[2] = 1.0f;
m_score_increase.clear();
m_leader_intervals.clear();
m_switch_items.clear();
@ -362,6 +369,25 @@ void STKConfig::getAllData(const XMLNode * root)
replay_node->get("delta-pos", &m_replay_delta_pos2 );
replay_node->get("delta-t", &m_replay_dt );
}
if(const XMLNode *colors = root->getNode("glow-colors"))
{
video::SColor tmpcol;
if (colors->get("nitro", &tmpcol))
{
m_nitro_glow_color[0] = tmpcol.getRed() / 255.0f;
m_nitro_glow_color[1] = tmpcol.getGreen() / 255.0f;
m_nitro_glow_color[2] = tmpcol.getBlue() / 255.0f;
}
if (colors->get("box", &tmpcol))
{
m_box_glow_color[0] = tmpcol.getRed() / 255.0f;
m_box_glow_color[1] = tmpcol.getGreen() / 255.0f;
m_box_glow_color[2] = tmpcol.getBlue() / 255.0f;
}
}
// Get the default KartProperties
// ------------------------------
const XMLNode *node = root -> getNode("general-kart-defaults");

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Joerg Henrichs
// Copyright (C) 2006-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -148,6 +148,11 @@ public:
* be generated. */
float m_replay_delta_angle;
/** Colors for glows */
float m_nitro_glow_color[3];
float m_box_glow_color[3];
private:
/** True if stk_config has been loaded. This is necessary if the
* --stk-config command line parameter has been specified to avoid

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 SuperTuxKart-Team
// Copyright (C) 2006-2013 SuperTuxKart-Team
// Modelled after Supertux's configfile.cpp
//
// This program is free software; you can redistribute it and/or
@ -46,6 +46,9 @@ static PtrVector<UserConfigParam, REF> all_params;
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
const int UserConfig::m_current_config_version = 8;
// ----------------------------------------------------------------------------
UserConfigParam::~UserConfigParam()
{
@ -242,7 +245,7 @@ void IntUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node)
} // findYourDataInAnAttributeOf
// ============================================================================
TimeUserConfigParam::TimeUserConfigParam(Time::TimeType default_value,
TimeUserConfigParam::TimeUserConfigParam(StkTime::TimeType default_value,
const char* param_name,
const char* comment)
{
@ -254,7 +257,7 @@ TimeUserConfigParam::TimeUserConfigParam(Time::TimeType default_value,
} // TimeUserConfigParam
// ----------------------------------------------------------------------------
TimeUserConfigParam::TimeUserConfigParam(Time::TimeType default_value,
TimeUserConfigParam::TimeUserConfigParam(StkTime::TimeType default_value,
const char* param_name,
GroupUserConfigParam* group,
const char* comment)
@ -649,13 +652,14 @@ bool UserConfig::loadConfig()
}
// ---- Read config file version
int configFileVersion = CURRENT_CONFIG_VERSION;
if(root->get("version", &configFileVersion) < 1)
int config_file_version = m_current_config_version;
if(root->get("version", &config_file_version) < 1)
{
GUIEngine::showMessage( _("Your config file was malformed, so it was deleted and a new one will be created."), 10.0f);
std::cerr << "Warning, malformed user config file! Contains no version\n";
Log::error("UserConfig",
"Warning, malformed user config file! Contains no version");
}
if (configFileVersion < CURRENT_CONFIG_VERSION)
if (config_file_version < m_current_config_version)
{
// current version (8) is 100% incompatible with other versions (which were lisp)
// so we just delete the old config. in the future, for smaller updates, we can
@ -713,6 +717,16 @@ bool UserConfig::loadConfig()
return true;
} // loadConfig
// ----------------------------------------------------------------------------
void UserConfig::postLoadInit()
{
for (int i = 0; i < UserConfigParams::m_all_players.size(); i++)
{
PlayerProfile* player = UserConfigParams::m_all_players.get(i);
if (player->isGuestAccount()) player->setName(_LTR("Guest"));
}
}
// ----------------------------------------------------------------------------
/** Write settings to config file. */
@ -732,7 +746,8 @@ void UserConfig::saveConfig()
XMLWriter configfile(filename.c_str());
configfile << L"<?xml version=\"1.0\"?>\n";
configfile << L"<stkconfig version=\"" << CURRENT_CONFIG_VERSION << L"\" >\n\n";
configfile << L"<stkconfig version=\"" << m_current_config_version
<< L"\" >\n\n";
const int paramAmount = all_params.size();
for(int i=0; i<paramAmount; i++)

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 SuperTuxKart-Team
// Copyright (C) 2006-2013 SuperTuxKart-Team
// Modelled after Supertux's configfile.h
//
// This program is free software; you can redistribute it and/or
@ -37,8 +37,6 @@
cause an undefined game action now
6: Added stick configurations.
*/
const int CURRENT_CONFIG_VERSION = 8;
#include <string>
#include <map>
#include <vector>
@ -132,14 +130,14 @@ public:
// ============================================================================
class TimeUserConfigParam : public UserConfigParam
{
Time::TimeType m_value;
Time::TimeType m_default_value;
StkTime::TimeType m_value;
StkTime::TimeType m_default_value;
public:
TimeUserConfigParam(Time::TimeType default_value, const char* param_name,
TimeUserConfigParam(StkTime::TimeType default_value, const char* param_name,
const char* comment = NULL);
TimeUserConfigParam(Time::TimeType default_value, const char* param_name,
TimeUserConfigParam(StkTime::TimeType default_value, const char* param_name,
GroupUserConfigParam* group, const char* comment=NULL);
void write(XMLWriter& stream) const;
@ -148,10 +146,10 @@ public:
irr::core::stringw toString() const;
void revertToDefaults() { m_value = m_default_value; }
operator Time::TimeType() const { return m_value; }
Time::TimeType& operator=(const Time::TimeType& v)
operator StkTime::TimeType() const { return m_value; }
StkTime::TimeType& operator=(const StkTime::TimeType& v)
{ m_value = v; return m_value; }
Time::TimeType& operator=(const TimeUserConfigParam& v)
StkTime::TimeType& operator=(const TimeUserConfigParam& v)
{ m_value = (int)v; return m_value; }
}; // TimeUserConfigParam
@ -328,6 +326,9 @@ namespace UserConfigParams
PARAM_PREFIX IntUserConfigParam m_num_laps
PARAM_DEFAULT( IntUserConfigParam(4, "numlaps",
&m_race_setup_group, "Default number of laps.") );
PARAM_PREFIX IntUserConfigParam m_num_goals
PARAM_DEFAULT( IntUserConfigParam(3, "numgoals",
&m_race_setup_group, "Default number of goals in soccer mode.") );
PARAM_PREFIX IntUserConfigParam m_difficulty
PARAM_DEFAULT( IntUserConfigParam(0, "difficulty",
&m_race_setup_group,
@ -348,18 +349,18 @@ namespace UserConfigParams
PARAM_PREFIX GroupUserConfigParam m_wiimote_group
PARAM_DEFAULT( GroupUserConfigParam("WiiMote",
"Settings for the wiimote") );
PARAM_PREFIX FloatUserConfigParam m_wiimote_max
PARAM_DEFAULT( FloatUserConfigParam(90.0f, "wiimote-max",
PARAM_PREFIX FloatUserConfigParam m_wiimote_raw_max
PARAM_DEFAULT( FloatUserConfigParam(20.0f, "wiimote-raw-max",
&m_wiimote_group,
"At what angle (0-128) maximum steering is reached.") );
"At what raw input value maximum steering is reached (between 1 and 25).") );
PARAM_PREFIX FloatUserConfigParam m_wiimote_weight_linear
PARAM_DEFAULT( FloatUserConfigParam(0.2f, "wiimote-weight-linear",
PARAM_DEFAULT( FloatUserConfigParam(1.0f, "wiimote-weight-linear",
&m_wiimote_group,
"A weight applied to the linear component of mapping wiimote angle to steering angle"));
PARAM_PREFIX FloatUserConfigParam m_wiimote_weight_square
PARAM_DEFAULT( FloatUserConfigParam(0.8f, "wiimote-weight-square",
PARAM_DEFAULT( FloatUserConfigParam(0.0f, "wiimote-weight-square",
&m_wiimote_group,
"A weight applied to the square component of mapping wiimote angle to steering angle"));
@ -448,8 +449,9 @@ namespace UserConfigParams
/** True if check structures should be debugged. */
PARAM_PREFIX bool m_check_debug PARAM_DEFAULT( false );
/** Special debug camera being high over the kart. */
PARAM_PREFIX bool m_camera_debug PARAM_DEFAULT( false );
/** Special debug camera: 0: normal cameral; 1: being high over the kart.;
2: on ground level. */
PARAM_PREFIX int m_camera_debug PARAM_DEFAULT( false );
/** True if physics debugging should be enabled. */
PARAM_PREFIX bool m_physics_debug PARAM_DEFAULT( false );
@ -481,9 +483,6 @@ namespace UserConfigParams
/** True if hardware skinning should be enabled */
PARAM_PREFIX bool m_hw_skinning_enabled PARAM_DEFAULT( false );
/** True if Christmas Mode should be enabled */
PARAM_PREFIX bool m_xmas_enabled PARAM_DEFAULT( false );
// not saved to file
// ---- Networking
@ -513,14 +512,15 @@ namespace UserConfigParams
#define FBO_DEFAULT true
#endif
PARAM_PREFIX BoolUserConfigParam m_fbo
PARAM_DEFAULT( BoolUserConfigParam(FBO_DEFAULT, "fbo",
&m_graphics_quality, "Use frame buffer objects (FBOs)") );
PARAM_PREFIX BoolUserConfigParam m_graphical_effects
PARAM_DEFAULT( BoolUserConfigParam(true, "anim_gfx",
&m_graphics_quality, "Scenery animations") );
// This saves the actual user preference.
PARAM_PREFIX IntUserConfigParam m_xmas_mode
PARAM_DEFAULT( IntUserConfigParam(0, "christmas-mode",
&m_graphics_quality, "Christmas hats: 0 use calendar, 1 always on, 2 always off") );
PARAM_PREFIX BoolUserConfigParam m_weather_effects
PARAM_DEFAULT( BoolUserConfigParam(true, "weather_gfx",
&m_graphics_quality, "Weather effects") );
@ -538,10 +538,12 @@ namespace UserConfigParams
&m_graphics_quality,
"Whether trilinear filtering is allowed to be "
"used (true or false)") );
/*
PARAM_PREFIX IntUserConfigParam m_antialiasing
PARAM_DEFAULT( IntUserConfigParam(0,
"antialiasing", &m_graphics_quality,
"Whether antialiasing is enabled (0 = disabled, 1 = 2x, 2 = 4x, 3 = 8x") );
*/
PARAM_PREFIX BoolUserConfigParam m_vsync
PARAM_DEFAULT( BoolUserConfigParam(false, "vsync",
&m_graphics_quality,
@ -550,18 +552,27 @@ namespace UserConfigParams
PARAM_DEFAULT( BoolUserConfigParam(true, "pixel_shaders",
&m_graphics_quality,
"Whether to enable pixel shaders (splatting, normal maps, ...)") );
PARAM_PREFIX BoolUserConfigParam m_postprocess_enabled
PARAM_PREFIX BoolUserConfigParam m_motionblur
PARAM_DEFAULT( BoolUserConfigParam(false,
"postprocess_enabled", &m_graphics_quality,
"Whether post-processing (motion blur...) should "
"be enabled") );
"motionblur_enabled", &m_graphics_quality,
"Whether motion blur should be enabled") );
PARAM_PREFIX BoolUserConfigParam m_mlaa
PARAM_DEFAULT( BoolUserConfigParam(false,
"mlaa", &m_graphics_quality,
"Whether MLAA anti-aliasing should be enabled") );
PARAM_PREFIX IntUserConfigParam m_ssao
PARAM_DEFAULT( IntUserConfigParam(0,
"ssao", &m_graphics_quality,
"Whether SSAO is enabled (0 = disabled, 1 = low, 2 = high") );
PARAM_PREFIX IntUserConfigParam m_shadows
PARAM_DEFAULT( IntUserConfigParam(0,
"shadows", &m_graphics_quality,
"Whether shadows are enabled (0 = disabled, 1 = low, 2 = high") );
// ---- Misc
PARAM_PREFIX BoolUserConfigParam m_cache_overworld
PARAM_DEFAULT( BoolUserConfigParam(true, "cache-overworld") );
PARAM_PREFIX BoolUserConfigParam m_minimal_race_gui
PARAM_DEFAULT( BoolUserConfigParam(false, "minimal-race-gui") );
// TODO : is this used with new code? does it still work?
PARAM_PREFIX BoolUserConfigParam m_crashed
PARAM_DEFAULT( BoolUserConfigParam(false, "crashed") );
@ -735,6 +746,8 @@ private:
std::string m_filename;
irr::core::stringw m_warning;
static const int m_current_config_version;
public:
/** Create the user config object; does not actually load it,
* UserConfig::loadConfig needs to be called. */
@ -747,7 +760,7 @@ public:
const irr::core::stringw& getWarning() { return m_warning; }
void resetWarning() { m_warning=""; }
void setWarning(irr::core::stringw& warning) { m_warning=warning; }
void postLoadInit();
void addDefaultPlayer();
}; // UserConfig

775
src/graphics/callbacks.cpp Normal file
View File

@ -0,0 +1,775 @@
// SuperTuxKart - a fun racing game with go-kart
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/callbacks.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/wind.hpp"
#include "guiengine/engine.hpp"
#include "modes/world.hpp"
#include "tracks/track.hpp"
#include "utils/helpers.hpp"
using namespace video;
using namespace core;
//-------------------------------------
void NormalMapProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
s32 decaltex = 0;
srv->setPixelShaderConstant("DecalTex", &decaltex, 1);
s32 bumptex = 1;
srv->setPixelShaderConstant("BumpTex", &bumptex, 1);
s32 lightmapTex = (m_with_lightmap ? 2 : 0);
srv->setPixelShaderConstant("LightMapTex", &lightmapTex, 1);
s32 hasLightMap = (m_with_lightmap ? 1 : 0);
srv->setPixelShaderConstant("HasLightMap", &hasLightMap, 1);
// We could calculate light direction as coming from the sun (then we'd need to
// transform it into camera space). But I find that pretending light
// comes from the camera gives good results
const float lightdir[] = {0.1852f, -0.1852f, -0.9259f};
srv->setVertexShaderConstant("lightdir", lightdir, 3);
firstdone = true;
}
}
//-------------------------------------
void WaterShaderProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
float strength = time;
strength = 1.4f - fabsf(noise2d(strength / 30.0f + 133)) * 0.8f;
m_dx_1 += GUIEngine::getLatestDt() * m_water_shader_speed_1 * strength;
m_dy_1 += GUIEngine::getLatestDt() * m_water_shader_speed_1 * strength;
m_dx_2 += GUIEngine::getLatestDt() * m_water_shader_speed_2 * strength;
m_dy_2 -= GUIEngine::getLatestDt() * m_water_shader_speed_2 * strength;
if (m_dx_1 > 1.0f) m_dx_1 -= 1.0f;
if (m_dy_1 > 1.0f) m_dy_1 -= 1.0f;
if (m_dx_2 > 1.0f) m_dx_2 -= 1.0f;
if (m_dy_2 < 0.0f) m_dy_2 += 1.0f;
const float d1[2] = { m_dx_1, m_dy_1 };
const float d2[2] = { m_dx_2, m_dy_2 };
srv->setVertexShaderConstant("delta1", d1, 2);
srv->setVertexShaderConstant("delta2", d2, 2);
const float speed = irr_driver->getDevice()->getTimer()->getTime() / m_speed;
const float height = m_height * strength;
srv->setVertexShaderConstant("height", &height, 1);
srv->setVertexShaderConstant("speed", &speed, 1);
srv->setVertexShaderConstant("waveLength", &m_length, 1);
// Can't use the firstdone optimization, as the callback is shared
//if (!firstdone)
{
s32 decaltex = 0;
srv->setPixelShaderConstant("DecalTex", &decaltex, 1);
s32 bumptex = 1;
srv->setPixelShaderConstant("BumpTex1", &bumptex, 1);
bumptex = 2;
srv->setPixelShaderConstant("BumpTex2", &bumptex, 1);
// Calculate light direction as coming from the sun.
matrix4 normalm = srv->getVideoDriver()->getTransform(ETS_VIEW);
normalm.makeInverse();
normalm = normalm.getTransposed();
vector3df tmp = m_sunpos;
normalm.transformVect(tmp);
tmp.normalize();
const float lightdir[] = {tmp.X, tmp.Y, tmp.Z};
srv->setVertexShaderConstant("lightdir", lightdir, 3);
firstdone = true;
}
}
//-------------------------------------
void GrassShaderProvider::OnSetConstants(IMaterialRendererServices *srv, int userData)
{
IVideoDriver * const drv = srv->getVideoDriver();
const core::vector3df pos = drv->getTransform(ETS_WORLD).getTranslation();
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
float strength = (pos.X + pos.Y + pos.Z) * 1.2f + time * m_speed;
strength = noise2d(strength / 10.0f) * m_amplitude * 5;
// * 5 is to work with the existing amplitude values.
// Pre-multiply on the cpu
vector3df wind = irr_driver->getWind() * strength;
srv->setVertexShaderConstant("windDir", &wind.X, 3);
if (!firstdone)
{
s32 tex = 0;
srv->setVertexShaderConstant("tex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void SplattingProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float camfar = irr_driver->getSceneManager()->getActiveCamera()->getFarValue();
srv->setVertexShaderConstant("far", &camfar, 1);
// The normal is transformed by the inverse transposed world matrix
// because we want world-space normals
matrix4 invtworldm = irr_driver->getVideoDriver()->getTransform(ETS_WORLD);
invtworldm.makeInverse();
invtworldm = invtworldm.getTransposed();
srv->setVertexShaderConstant("invtworldm", invtworldm.pointer(), 16);
float objectid = 0;
const stringc name = mat.TextureLayer[0].Texture->getName().getPath();
objectid = shash8((const u8 *) name.c_str(), name.size()) / 255.0f;
srv->setVertexShaderConstant("objectid", &objectid, 1);
if (!firstdone)
{
s32 tex_layout = 1;
srv->setPixelShaderConstant("tex_layout", &tex_layout, 1);
s32 tex_detail0 = 2;
srv->setPixelShaderConstant("tex_detail0", &tex_detail0, 1);
s32 tex_detail1 = 3;
srv->setPixelShaderConstant("tex_detail1", &tex_detail1, 1);
s32 tex_detail2 = 4;
srv->setPixelShaderConstant("tex_detail2", &tex_detail2, 1);
s32 tex_detail3 = 5;
srv->setPixelShaderConstant("tex_detail3", &tex_detail3, 1);
firstdone = true;
}
}
//-------------------------------------
void BubbleEffectProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float start = fabsf(mat.MaterialTypeParam2);
const bool visible = mat.MaterialTypeParam2 > 0;
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
float transparency;
const float diff = (time - start) / 3.0f;
if (visible)
{
transparency = diff;
}
else
{
transparency = 1.0 - diff;
}
transparency = clampf(transparency, 0, 1);
srv->setVertexShaderConstant("time", &time, 1);
srv->setVertexShaderConstant("transparency", &transparency, 1);
}
//-------------------------------------
void RainEffectProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float screenw = UserConfigParams::m_width;
const float time = irr_driver->getDevice()->getTimer()->getTime() / 90.0f;
const matrix4 viewm = srv->getVideoDriver()->getTransform(ETS_VIEW);
const vector3df campos = irr_driver->getSceneManager()->getActiveCamera()->getPosition();
srv->setVertexShaderConstant("screenw", &screenw, 1);
srv->setVertexShaderConstant("time", &time, 1);
srv->setVertexShaderConstant("viewm", viewm.pointer(), 16);
srv->setVertexShaderConstant("campos", &campos.X, 3);
}
//-------------------------------------
void SnowEffectProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
srv->setVertexShaderConstant("time", &time, 1);
}
//-------------------------------------
void MotionBlurProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
// We need the maximum texture coordinates:
float max_tex_height = m_maxheight[m_current_camera];
srv->setPixelShaderConstant("max_tex_height", &max_tex_height, 1);
// Scale the boost time to get a usable boost amount:
float boost_amount = m_boost_time[m_current_camera] * 0.7f;
// Especially for single screen the top of the screen is less blurred
// in the fragment shader by multiplying the blurr factor by
// (max_tex_height - texcoords.t), where max_tex_height is the maximum
// texture coordinate (1.0 or 0.5). In split screen this factor is too
// small (half the value compared with non-split screen), so we
// multiply this by 2.
if(Camera::getNumCameras() > 1)
boost_amount *= 2.0f;
srv->setPixelShaderConstant("boost_amount", &boost_amount, 1);
srv->setPixelShaderConstant("center",
&(m_center[m_current_camera].X), 2);
srv->setPixelShaderConstant("direction",
&(m_direction[m_current_camera].X), 2);
// Use a radius of 0.15 when showing a single kart, otherwise (2-4 karts
// on splitscreen) use only 0.75.
float radius = Camera::getNumCameras()==1 ? 0.15f : 0.075f;
srv->setPixelShaderConstant("mask_radius", &radius, 1);
const int texunit = 0;
srv->setPixelShaderConstant("color_buffer", &texunit, 1);
}
//-------------------------------------
void GaussianBlurProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("pixel", m_pixel, 2);
}
//-------------------------------------
void MipVizProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const ITexture * const tex = mat.TextureLayer[0].Texture;
const int notex = (mat.TextureLayer[0].Texture == NULL);
srv->setVertexShaderConstant("notex", &notex, 1);
if (!tex) return;
const dimension2du size = tex->getSize();
const float texsize[2] = {
size.Width,
size.Height
};
srv->setVertexShaderConstant("texsize", texsize, 2);
}
//-------------------------------------
void ColorizeProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("col", m_color, 3);
}
//-------------------------------------
void GlowProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("res", m_res, 2);
}
//-------------------------------------
void ObjectPassProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float camfar = irr_driver->getSceneManager()->getActiveCamera()->getFarValue();
srv->setVertexShaderConstant("far", &camfar, 1);
// The normal is transformed by the inverse transposed world matrix
// because we want world-space normals
matrix4 invtworldm = irr_driver->getVideoDriver()->getTransform(ETS_WORLD);
invtworldm.makeInverse();
invtworldm = invtworldm.getTransposed();
srv->setVertexShaderConstant("invtworldm", invtworldm.pointer(), 16);
const int hastex = mat.TextureLayer[0].Texture != NULL;
srv->setVertexShaderConstant("hastex", &hastex, 1);
const int haslightmap = mat.TextureLayer[1].Texture != NULL;
srv->setVertexShaderConstant("haslightmap", &haslightmap, 1);
float objectid = 0;
if (hastex)
{
const stringc name = mat.TextureLayer[0].Texture->getName().getPath();
objectid = shash8((const u8 *) name.c_str(), name.size()) / 255.0f;
}
srv->setVertexShaderConstant("objectid", &objectid, 1);
//if (!firstdone)
// Can't use the firstdone optimization, as this callback is used for multiple shaders
{
int tex = 0;
srv->setVertexShaderConstant("tex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("lighttex", &tex, 1);
}
}
//-------------------------------------
void LightBlendProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const SColorf s = irr_driver->getSceneManager()->getAmbientLight();
float ambient[3] = { s.r, s.g, s.b };
srv->setVertexShaderConstant("ambient", ambient, 3);
int spectex = 1;
srv->setVertexShaderConstant("spectex", &spectex, 1);
}
//-------------------------------------
void PointLightProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("screen", m_screen, 2);
srv->setVertexShaderConstant("spec", &m_specular, 1);
srv->setVertexShaderConstant("col", m_color, 3);
srv->setVertexShaderConstant("campos", m_campos, 3);
srv->setVertexShaderConstant("center", m_pos, 3);
srv->setVertexShaderConstant("r", &m_radius, 1);
srv->setVertexShaderConstant("invprojview", m_invprojview.pointer(), 16);
if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("ntex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("dtex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void SunLightProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const int hasclouds = World::getWorld()->getTrack()->hasClouds() &&
UserConfigParams::m_weather_effects;
srv->setVertexShaderConstant("screen", m_screen, 2);
srv->setVertexShaderConstant("col", m_color, 3);
srv->setVertexShaderConstant("center", m_pos, 3);
srv->setVertexShaderConstant("invprojview", m_invprojview.pointer(), 16);
srv->setVertexShaderConstant("hasclouds", &hasclouds, 1);
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
float strength = time;
strength = fabsf(noise2d(strength / 10.0f)) * 0.003f;
const vector3df winddir = irr_driver->getWind() * strength;
m_wind[0] += winddir.X;
m_wind[1] += winddir.Z;
srv->setVertexShaderConstant("wind", m_wind, 2);
if (UserConfigParams::m_shadows)
{
srv->setVertexShaderConstant("shadowmat", m_shadowmat.pointer(), 16);
}
// Can't use the firstdone optimization, as this callback is used for multiple shaders
//if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("ntex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("dtex", &tex, 1);
tex = 2;
srv->setVertexShaderConstant("cloudtex", &tex, 1);
tex = 3;
srv->setVertexShaderConstant("shadowtex", &tex, 1);
tex = 4;
srv->setVertexShaderConstant("warpx", &tex, 1);
tex = 5;
srv->setVertexShaderConstant("warpy", &tex, 1);
const float shadowoffset = 1.0f / irr_driver->getRTT(RTT_SHADOW)->getSize().Width;
srv->setVertexShaderConstant("shadowoffset", &shadowoffset, 1);
firstdone = true;
}
}
//-------------------------------------
void BloomProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("low", &m_threshold, 1);
}
//-------------------------------------
void MLAAColor1Provider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
const float pixels[2] = {
1.0f / UserConfigParams::m_width,
1.0f / UserConfigParams::m_height
};
srv->setPixelShaderConstant("PIXEL_SIZE", pixels, 2);
firstdone = true;
}
}
//-------------------------------------
void MLAABlend2Provider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
const float pixels[2] = {
1.0f / UserConfigParams::m_width,
1.0f / UserConfigParams::m_height
};
srv->setPixelShaderConstant("PIXEL_SIZE", pixels, 2);
int tex = 0;
srv->setPixelShaderConstant("edgesMap", &tex, 1);
tex = 1;
srv->setPixelShaderConstant("areaMap", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void MLAANeigh3Provider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
const float pixels[2] = {
1.0f / UserConfigParams::m_width,
1.0f / UserConfigParams::m_height
};
srv->setPixelShaderConstant("PIXEL_SIZE", pixels, 2);
int tex = 0;
srv->setPixelShaderConstant("blendMap", &tex, 1);
tex = 1;
srv->setPixelShaderConstant("colorMap", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void SSAOProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
int tex = 0;
srv->setPixelShaderConstant("tex", &tex, 1);
tex = 1;
srv->setPixelShaderConstant("oldtex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void GodRayProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setPixelShaderConstant("sunpos", m_sunpos, 2);
}
//-------------------------------------
void ShadowPassProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const int hastex = mat.TextureLayer[0].Texture != NULL;
srv->setVertexShaderConstant("hastex", &hastex, 1);
int viz = irr_driver->getShadowViz();
srv->setVertexShaderConstant("viz", &viz, 1);
int wireframe = mat.Wireframe;
srv->setVertexShaderConstant("wireframe", &wireframe, 1);
float objectid = 0;
if (hastex)
{
const stringc name = mat.TextureLayer[0].Texture->getName().getPath();
objectid = shash8((const u8 *) name.c_str(), name.size()) / 255.0f;
}
srv->setVertexShaderConstant("objectid", &objectid, 1);
//if (!firstdone)
// Can't use the firstdone optimization, as this callback is used for multiple shaders
{
int tex = 0;
srv->setVertexShaderConstant("tex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("warpx", &tex, 1);
tex = 2;
srv->setVertexShaderConstant("warpy", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void ShadowImportanceProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("shadowmat", m_shadowmat.pointer(), 16);
srv->setVertexShaderConstant("ipvmat", m_invprojview.pointer(), 16);
srv->setVertexShaderConstant("campos", m_campos, 3);
int low = UserConfigParams::m_shadows == 1;
srv->setVertexShaderConstant("low", &low, 1);
if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("ntex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("dtex", &tex, 1);
tex = 2;
srv->setVertexShaderConstant("ctex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void CollapseProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("pixel", m_pixel, 2);
srv->setVertexShaderConstant("multi", m_multi, 2);
srv->setVertexShaderConstant("size", &m_size, 1);
//if (!firstdone)
// Can't use the firstdone optimization, as this callback is used for multiple shaders
{
int tex = 0;
srv->setVertexShaderConstant("tex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("oldtex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void BloomPowerProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
srv->setVertexShaderConstant("power", &m_power, 1);
}
//-------------------------------------
void MultiplyProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("tex1", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("tex2", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void ShadowGenProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("halft", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("quarter", &tex, 1);
tex = 2;
srv->setVertexShaderConstant("eighth", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void CausticsProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
const float speed = World::getWorld()->getTrack()->getCausticsSpeed();
float strength = time;
strength = fabsf(noise2d(strength / 10.0f)) * 0.006f + 0.001f;
vector3df wind = irr_driver->getWind() * strength * speed;
m_dir[0] += wind.X;
m_dir[1] += wind.Z;
strength = time * 0.56f + sinf(time);
strength = fabsf(noise2d(0.0, strength / 6.0f)) * 0.0095f + 0.001f;
wind = irr_driver->getWind() * strength * speed;
wind.rotateXZBy(cosf(time));
m_dir2[0] += wind.X;
m_dir2[1] += wind.Z;
srv->setVertexShaderConstant("dir", m_dir, 2);
srv->setVertexShaderConstant("dir2", m_dir2, 2);
if (!firstdone)
{
int tex = 0;
srv->setVertexShaderConstant("tex", &tex, 1);
tex = 1;
srv->setVertexShaderConstant("caustictex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void DisplaceProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
const float speed = World::getWorld()->getTrack()->getDisplacementSpeed();
float strength = time;
strength = fabsf(noise2d(strength / 10.0f)) * 0.006f + 0.002f;
vector3df wind = irr_driver->getWind() * strength * speed;
m_dir[0] += wind.X;
m_dir[1] += wind.Z;
strength = time * 0.56f + sinf(time);
strength = fabsf(noise2d(0.0, strength / 6.0f)) * 0.0095f + 0.0025f;
wind = irr_driver->getWind() * strength * speed;
wind.rotateXZBy(cosf(time));
m_dir2[0] += wind.X;
m_dir2[1] += wind.Z;
srv->setVertexShaderConstant("dir", m_dir, 2);
srv->setVertexShaderConstant("dir2", m_dir2, 2);
srv->setVertexShaderConstant("screen", m_screen, 2);
}
//-------------------------------------
void PPDisplaceProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
int viz = irr_driver->getDistortViz();
srv->setPixelShaderConstant("viz", &viz, 1);
if (!firstdone)
{
int tex = 0;
srv->setPixelShaderConstant("tex", &tex, 1);
tex = 1;
srv->setPixelShaderConstant("dtex", &tex, 1);
firstdone = true;
}
}
//-------------------------------------
void FogProvider::OnSetConstants(IMaterialRendererServices *srv, int)
{
const Track * const track = World::getWorld()->getTrack();
// This function is only called once per frame - thus no need for setters.
const float fogmax = track->getFogMax();
const float startH = track->getFogStartHeight();
const float endH = track->getFogEndHeight();
const float start = track->getFogStart();
const float end = track->getFogEnd();
const SColor tmpcol = track->getFogColor();
const float col[3] = { tmpcol.getRed() / 255.0f,
tmpcol.getGreen() / 255.0f,
tmpcol.getBlue() / 255.0f };
srv->setPixelShaderConstant("fogmax", &fogmax, 1);
srv->setPixelShaderConstant("startH", &startH, 1);
srv->setPixelShaderConstant("endH", &endH, 1);
srv->setPixelShaderConstant("start", &start, 1);
srv->setPixelShaderConstant("end", &end, 1);
srv->setPixelShaderConstant("col", col, 3);
srv->setVertexShaderConstant("ipvmat", m_invprojview.pointer(), 16);
srv->setVertexShaderConstant("campos", m_campos, 3);
}

712
src/graphics/callbacks.hpp Normal file
View File

@ -0,0 +1,712 @@
// SuperTuxKart - a fun racing game with go-kart
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_CALLBACKS_HPP
#define HEADER_CALLBACKS_HPP
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include <IShaderConstantSetCallBack.h>
#include <SMaterial.h>
#include <ISceneManager.h>
#include <ICameraSceneNode.h>
#include <IMaterialRendererServices.h>
#include <set>
#include <algorithm>
using namespace irr;
class CallBase: public video::IShaderConstantSetCallBack
{
public:
CallBase()
{
firstdone = 0;
}
virtual void OnSetMaterial(const video::SMaterial &material)
{
mat = material;
}
protected:
bool firstdone;
video::SMaterial mat;
};
//
class NormalMapProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
NormalMapProvider(bool withLightmap)
{
m_with_lightmap = withLightmap;
}
private:
bool m_with_lightmap;
};
//
class WaterShaderProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setSpeed(const float s1, const float s2)
{
m_water_shader_speed_1 = s1;
m_water_shader_speed_2 = s2;
}
WaterShaderProvider()
{
m_dx_1 = 0.0f;
m_dx_2 = 0.0f;
m_dy_1 = 0.0f;
m_dy_2 = 0.0f;
m_water_shader_speed_1 =
m_water_shader_speed_2 = 0.0f;
}
void setSunPosition(const core::vector3df &in)
{
m_sunpos = in;
m_sunpos.normalize();
}
void setSpeed(float speed) { m_speed = speed; }
void setHeight(float height) { m_height = height; }
void setLength(float length) { m_length = length; }
private:
core::vector3df m_sunpos;
float m_dx_1, m_dy_1, m_dx_2, m_dy_2;
float m_water_shader_speed_1;
float m_water_shader_speed_2;
float m_speed;
float m_height;
float m_length;
};
//
class GrassShaderProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
GrassShaderProvider()
{
m_amplitude =
m_speed = 0.0f;
}
void setSpeed(float speed)
{
m_speed = speed;
}
void setAmplitude(float amp)
{
m_amplitude = amp;
}
private:
float m_amplitude, m_speed;
};
//
class SplattingProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class BubbleEffectProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
BubbleEffectProvider()
{
}
// We hijack the material type param 2 of bubbles.
// It's time to start the fade, negative if fade out, positive if in.
// It'd be unused otherwise.
void onMadeVisible(scene::IMeshBuffer * const mb)
{
if (!contains(mb))
return;
video::SMaterial &mat = mb->getMaterial();
mat.MaterialTypeParam2 = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
}
void onHidden(scene::IMeshBuffer * const mb)
{
if (!contains(mb))
return;
video::SMaterial &mat = mb->getMaterial();
mat.MaterialTypeParam2 = irr_driver->getDevice()->getTimer()->getTime() / -1000.0f;
}
void isInitiallyHidden(scene::IMeshBuffer * const mb)
{
if (!contains(mb))
return;
video::SMaterial &mat = mb->getMaterial();
mat.MaterialTypeParam2 = irr_driver->getDevice()->getTimer()->getTime() / -1000.0f;
}
void removeBubble(const scene::IMeshBuffer * const mb)
{
m_bubbles.erase(mb);
}
void addBubble(scene::IMeshBuffer * const mb)
{
m_bubbles.insert(mb);
video::SMaterial &mat = mb->getMaterial();
mat.MaterialTypeParam2 = 1;
}
bool contains(const scene::IMeshBuffer * const mb) const
{
return m_bubbles.count(mb);
}
private:
std::set<const scene::IMeshBuffer *> m_bubbles;
};
//
class RainEffectProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class SnowEffectProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class MotionBlurProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setMaxHeight(u32 who, float height)
{
assert(who < MAX_PLAYER_COUNT);
m_maxheight[who] = height;
}
void setBoostTime(u32 who, float time)
{
assert(who < MAX_PLAYER_COUNT);
m_boost_time[who] = time;
}
void setCenter(u32 who, float X, float Y)
{
assert(who < MAX_PLAYER_COUNT);
m_center[who].X = X;
m_center[who].Y = Y;
}
void setDirection(u32 who, float X, float Y)
{
assert(who < MAX_PLAYER_COUNT);
m_direction[who].X = X;
m_direction[who].Y = Y;
}
void setCurrentCamera(u32 who)
{
m_current_camera = who;
}
private:
float m_maxheight[MAX_PLAYER_COUNT];
u32 m_current_camera;
float m_boost_time[MAX_PLAYER_COUNT];
core::vector2df m_center[MAX_PLAYER_COUNT];
core::vector2df m_direction[MAX_PLAYER_COUNT];
};
//
class GaussianBlurProvider: public CallBase
{
public:
GaussianBlurProvider()
{
m_pixel[0] = 1.0f / UserConfigParams::m_width;
m_pixel[1] = 1.0f / UserConfigParams::m_height;
}
void setResolution(float x, float y)
{
m_pixel[0] = 1.0f / x;
m_pixel[1] = 1.0f / y;
}
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
private:
float m_pixel[2];
};
//
class MipVizProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class ColorizeProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setColor(float r, float g, float b)
{
m_color[0] = r;
m_color[1] = g;
m_color[2] = b;
}
private:
float m_color[3];
};
//
class GlowProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setResolution(float x, float y)
{
m_res[0] = x;
m_res[1] = y;
}
private:
float m_res[2];
};
//
class ObjectPassProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class LightBlendProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class PointLightProvider: public CallBase
{
public:
PointLightProvider()
{
m_screen[0] = UserConfigParams::m_width;
m_screen[1] = UserConfigParams::m_height;
m_specular = 200;
}
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setColor(float r, float g, float b)
{
m_color[0] = r;
m_color[1] = g;
m_color[2] = b;
}
void setPosition(float x, float y, float z)
{
m_pos[0] = x;
m_pos[1] = y;
m_pos[2] = z;
}
void setRadius(float r)
{
m_radius = r;
}
void setSpecular(float s)
{
m_specular = s;
}
void updateIPVMatrix()
{
// Update the campos and IPV matrix, only once per frame since it's costly
const core::vector3df &campos =
irr_driver->getSceneManager()->getActiveCamera()->getAbsolutePosition();
m_campos[0] = campos.X;
m_campos[1] = campos.Y;
m_campos[2] = campos.Z;
const video::IVideoDriver * const drv = irr_driver->getVideoDriver();
m_invprojview = drv->getTransform(video::ETS_PROJECTION);
m_invprojview *= drv->getTransform(video::ETS_VIEW);
m_invprojview.makeInverse();
}
private:
core::matrix4 m_invprojview;
float m_campos[3];
float m_color[3];
float m_pos[3];
float m_screen[2];
float m_radius;
float m_specular;
};
//
class SunLightProvider: public CallBase
{
public:
SunLightProvider()
{
m_screen[0] = UserConfigParams::m_width;
m_screen[1] = UserConfigParams::m_height;
m_wind[0] = m_wind[1] = 0;
}
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setColor(float r, float g, float b)
{
m_color[0] = r;
m_color[1] = g;
m_color[2] = b;
}
void setPosition(float x, float y, float z)
{
m_pos[0] = x;
m_pos[1] = y;
m_pos[2] = z;
}
void updateIPVMatrix()
{
// Update the IPV matrix, only once per frame since it's costly
const video::IVideoDriver * const drv = irr_driver->getVideoDriver();
m_invprojview = drv->getTransform(video::ETS_PROJECTION);
m_invprojview *= drv->getTransform(video::ETS_VIEW);
m_invprojview.makeInverse();
}
void setShadowMatrix(const core::matrix4 &mat)
{
m_shadowmat = mat;
}
private:
core::matrix4 m_invprojview, m_shadowmat;
float m_color[3];
float m_pos[3];
float m_screen[2];
float m_wind[2];
};
//
class BloomProvider: public CallBase
{
public:
BloomProvider() { m_threshold = 0.75f; }
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setThreshold(const float f) { m_threshold = f; }
private:
float m_threshold;
};
//
class MLAAColor1Provider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class MLAABlend2Provider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class MLAANeigh3Provider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class SSAOProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class GodRayProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
// In texcoords
void setSunPosition(float x, float y) { m_sunpos[0] = x; m_sunpos[1] = y; }
private:
float m_sunpos[2];
};
//
class ShadowPassProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class ShadowImportanceProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void updateIPVMatrix()
{
// Update the IPV matrix, only once per frame since it's costly
const video::IVideoDriver * const drv = irr_driver->getVideoDriver();
const core::vector3df &campos =
irr_driver->getSceneManager()->getActiveCamera()->getAbsolutePosition();
m_campos[0] = campos.X;
m_campos[1] = campos.Y;
m_campos[2] = campos.Z;
m_invprojview = drv->getTransform(video::ETS_PROJECTION);
m_invprojview *= drv->getTransform(video::ETS_VIEW);
m_invprojview.makeInverse();
}
void setShadowMatrix(const core::matrix4 &mat)
{
m_shadowmat = mat;
}
private:
core::matrix4 m_invprojview, m_shadowmat;
float m_campos[3];
};
//
class CollapseProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setResolution(const float x, const float y)
{
m_pixel[0] = 1.0f / x;
m_pixel[1] = 1.0f / y;
m_multi[0] = m_multi[1] = 1;
if (x < 2 || y < 2)
{
u32 i;
for (i = 0; i < 2; i++)
{
// No increase for the other direction
if (m_pixel[i] > 0.9f) m_pixel[i] = m_multi[i] = 0;
}
std::swap(m_multi[0], m_multi[1]);
}
m_size = std::max(x, y);
}
private:
float m_pixel[2];
int m_size;
float m_multi[2];
};
//
class BloomPowerProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void setPower(float power)
{
m_power = power / 10.0f;
}
private:
float m_power;
};
//
class MultiplyProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class ShadowGenProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class CausticsProvider: public CallBase
{
public:
CausticsProvider() { m_dir[0] = m_dir[1] = m_dir2[0] = m_dir2[1] = 0; }
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
private:
float m_dir[2], m_dir2[2];
};
//
class DisplaceProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
DisplaceProvider()
{
m_screen[0] = UserConfigParams::m_width;
m_screen[1] = UserConfigParams::m_height;
m_dir[0] = m_dir[1] = m_dir2[0] = m_dir2[1] = 0;
}
private:
float m_screen[2];
float m_dir[2], m_dir2[2];
};
//
class PPDisplaceProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
};
//
class FogProvider: public CallBase
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices *srv, int);
void updateIPVMatrix()
{
// Update the campos and IPV matrix, only once per frame since it's costly
const core::vector3df &campos =
irr_driver->getSceneManager()->getActiveCamera()->getAbsolutePosition();
m_campos[0] = campos.X;
m_campos[1] = campos.Y;
m_campos[2] = campos.Z;
const video::IVideoDriver * const drv = irr_driver->getVideoDriver();
m_invprojview = drv->getTransform(video::ETS_PROJECTION);
m_invprojview *= drv->getTransform(video::ETS_VIEW);
m_invprojview.makeInverse();
}
private:
core::matrix4 m_invprojview;
float m_campos[3];
};
#endif

View File

@ -1,7 +1,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004-2005 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2006 SuperTuxKart-Team, Steve Baker
// Copyright (C) 2004-2013 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2006-2013 SuperTuxKart-Team, Steve Baker
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -19,11 +19,7 @@
#include "graphics/camera.hpp"
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
# define isnan _isnan
#else
# include <math.h>
#endif
#include <math.h>
#include "audio/music_manager.hpp"
#include "config/user_config.hpp"
@ -35,10 +31,12 @@
#include "karts/kart_properties.hpp"
#include "karts/skidding.hpp"
#include "modes/world.hpp"
#include "physics/btKart.hpp"
#include "race/race_manager.hpp"
#include "tracks/track.hpp"
#include "utils/aligned_array.hpp"
#include "utils/constants.hpp"
#include "utils/vs.hpp"
#include "ICameraSceneNode.h"
#include "ISceneManager.h"
@ -386,14 +384,22 @@ void Camera::getCameraSettings(float *above_kart, float *cam_angle,
}
// Fall through to falling mode.
case CM_FALLING:
{
if(UserConfigParams::m_camera_debug==2)
{
*above_kart = 0;
*cam_angle = 0;
}
else
{
*above_kart = 0.75f;
*cam_angle = kp->getCameraForwardUpAngle();
}
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;
*cam_angle = kp->getCameraForwardUpAngle();
*sideway = -m_rotation_range*dampened_steer*0.5f;
*distance = -m_distance;
*smoothing = true;
@ -442,19 +448,12 @@ void Camera::getCameraSettings(float *above_kart, float *cam_angle,
*/
void Camera::update(float dt)
{
if (UserConfigParams::m_graphical_effects)
{
if (m_rain)
{
m_rain->setPosition( getCameraSceneNode()->getPosition() );
m_rain->update(dt);
}
} // UserConfigParams::m_graphical_effects
float above_kart, cam_angle, side_way, distance;
bool smoothing;
// The following settings give a debug camera which shows the track from
// high above the kart straight down.
if(UserConfigParams::m_camera_debug)
if (UserConfigParams::m_camera_debug==1)
{
core::vector3df xyz = m_kart->getXYZ().toIrrVector();
m_camera->setTarget(xyz);
@ -464,24 +463,18 @@ void Camera::update(float dt)
// To view inside tunnels (FIXME 27>15 why??? makes no sense
// - the kart should not be visible, but it works)
m_camera->setNearValue(27.0);
return;
}
if(m_mode==CM_FINAL)
else if (m_mode==CM_FINAL)
{
handleEndCamera(dt);
return;
}
float above_kart, cam_angle, side_way, distance;
bool smoothing;
getCameraSettings(&above_kart, &cam_angle, &side_way, &distance,
&smoothing);
// If an explosion is happening, stop moving the camera,
// but keep it target on the kart.
if(dynamic_cast<ExplosionAnimation*>(m_kart->getKartAnimation()))
else if (dynamic_cast<ExplosionAnimation*>(m_kart->getKartAnimation()))
{
getCameraSettings(&above_kart, &cam_angle, &side_way, &distance, &smoothing);
// The camera target needs to be 'smooth moved', otherwise
// there will be a noticable jump in the first frame
@ -495,10 +488,19 @@ void Camera::update(float dt)
current_target += ((wanted_target-current_target)*m_target_speed)*dt;
m_camera->setTarget(current_target);
return;
}
else
{
getCameraSettings(&above_kart, &cam_angle, &side_way, &distance, &smoothing);
positionCamera(dt, above_kart, cam_angle, side_way, distance, smoothing);
}
if (UserConfigParams::m_graphical_effects && m_rain)
{
m_rain->setPosition( getCameraSceneNode()->getPosition() );
m_rain->update(dt);
} // UserConfigParams::m_graphical_effects
} // update
// ----------------------------------------------------------------------------
@ -513,9 +515,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());
else
wanted_target.setY(wanted_target.getY()+above_kart);
float tan_up = tan(cam_angle);
Vec3 relative_position(side_way,
fabsf(distance)*tan_up+above_kart,

View File

@ -1,7 +1,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004-2005 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2006 SuperTuxKart-Team, Steve Baker
// Copyright (C) 2004-2013 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2006-2013 SuperTuxKart-Team, Steve Baker
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2004-2013 Steve Baker <sjbaker1@airmail.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2004-2013 Steve Baker <sjbaker1@airmail.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

85
src/graphics/glow.cpp Normal file
View File

@ -0,0 +1,85 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Lauri Kasanen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/glow.hpp"
#include "graphics/callbacks.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/material.hpp"
#include "graphics/rtts.hpp"
#include "graphics/shaders.hpp"
using namespace video;
using namespace scene;
using namespace core;
IMesh * GlowNode::sphere = NULL;
SMaterial GlowNode::mat;
aabbox3df GlowNode::box;
GlowNode::GlowNode(scene::ISceneManager* mgr, float radius): ISceneNode(mgr->getRootSceneNode(), mgr, -1)
{
if (!sphere)
{
mat.Lighting = false;
mat.MaterialType = irr_driver->getShader(ES_GLOW);
mat.setTexture(0, irr_driver->getRTT(RTT_QUARTER1));
mat.TextureLayer[0].TextureWrapU =
mat.TextureLayer[0].TextureWrapV = ETC_CLAMP_TO_EDGE;
mat.setFlag(EMF_TRILINEAR_FILTER, true);
mat.BlendOperation = EBO_ADD;
sphere = mgr->getGeometryCreator()->createSphereMesh(1, 4, 4);
box = sphere->getBoundingBox();
}
setScale(vector3df(radius));
}
GlowNode::~GlowNode()
{
}
void GlowNode::render()
{
IVideoDriver * const drv = irr_driver->getVideoDriver();
drv->setTransform(ETS_WORLD, AbsoluteTransformation);
drv->setMaterial(mat);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 0, ~0);
glEnable(GL_STENCIL_TEST);
drv->drawMeshBuffer(sphere->getMeshBuffer(0));
glDisable(GL_STENCIL_TEST);
}
void GlowNode::OnRegisterSceneNode()
{
if (IsVisible)
{
SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT);
}
ISceneNode::OnRegisterSceneNode();
}

53
src/graphics/glow.hpp Normal file
View File

@ -0,0 +1,53 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Lauri Kasanen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_GLOW_HPP
#define HEADER_GLOW_HPP
#include <ISceneNode.h>
#include <IMesh.h>
using namespace irr;
// The actual node
class GlowNode: public scene::ISceneNode
{
public:
GlowNode(scene::ISceneManager* mgr, float radius);
~GlowNode();
virtual void render();
virtual const core::aabbox3d<f32>& getBoundingBox() const
{
return box;
}
virtual void OnRegisterSceneNode();
virtual u32 getMaterialCount() const { return 1; }
virtual video::SMaterial& getMaterial(u32 i) { return mat; }
private:
static video::SMaterial mat;
static core::aabbox3df box;
static scene::IMesh *sphere;
};
#endif

21
src/graphics/glwrap.hpp Normal file
View File

@ -0,0 +1,21 @@
#ifndef GLWRAP_HEADER_H
#define GLWRAP_HEADER_H
#if defined(__APPLE__)
# include <OpenGL/gl.h>
#elif defined(ANDROID)
# include <GLES/gl.h>
#elif defined(WIN32)
# define _WINSOCKAPI_
// has to be included before gl.h because of WINGDIAPI and APIENTRY definitions
# include <windows.h>
# include <GL/gl.h>
#else
# include <GL/gl.h>
#endif
// already includes glext.h, which defines useful GL constants.
// COpenGLDriver has already loaded the extension GL functions we use (e.g glBeginQuery)
#include "../../lib/irrlicht/source/Irrlicht/COpenGLDriver.h"
#endif

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2004-2013 Steve Baker <sjbaker1@airmail.net>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 the SuperTuxKart team
// Copyright (C) 2011-2013 the SuperTuxKart team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs
// Copyright (C) 2011-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs
// Copyright (C) 2011-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs
// Copyright (C) 2011-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
// Copyright (C) 2009-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -19,13 +19,23 @@
#include "graphics/irr_driver.hpp"
#include "config/user_config.hpp"
#include "graphics/callbacks.hpp"
#include "graphics/camera.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/hardware_skinning.hpp"
#include "graphics/lens_flare.hpp"
#include "graphics/light.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "graphics/per_camera_node.hpp"
#include "graphics/post_processing.hpp"
#include "graphics/referee.hpp"
#include "graphics/shaders.hpp"
#include "graphics/shadow_importance.hpp"
#include "graphics/sun.hpp"
#include "graphics/rtts.hpp"
#include "graphics/water.hpp"
#include "graphics/wind.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/modaldialog.hpp"
#include "guiengine/scalable_font.hpp"
@ -47,6 +57,7 @@
#include "utils/constants.hpp"
#include "utils/log.hpp"
#include "utils/profiler.hpp"
#include "utils/vs.hpp"
#include <irrlicht.h>
@ -62,19 +73,12 @@
using namespace irr;
#ifndef round
# define round(x) (floor(x+0.5f))
#endif
#ifdef WIN32
#include <Windows.h>
#endif
#if defined(__linux__) && !defined(ANDROID)
namespace X11
{
#include <X11/Xlib.h>
#include <X11/Xutil.h>
}
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif
/** singleton */
@ -96,6 +100,11 @@ IrrDriver::IrrDriver()
m_resolution_changing = RES_CHANGE_NONE;
m_device = createDevice(video::EDT_NULL);
m_request_screenshot = false;
m_shaders = NULL;
m_rtts = NULL;
m_wind = new Wind();
m_mipviz = m_wireframe = m_normals = m_ssaoviz = \
m_lightviz = m_shadowviz = m_distortviz = 0;
} // IrrDriver
// ----------------------------------------------------------------------------
@ -117,6 +126,9 @@ IrrDriver::~IrrDriver()
m_device->drop();
m_device = NULL;
m_modes.clear();
delete m_shaders;
delete m_wind;
} // ~IrrDriver
// ----------------------------------------------------------------------------
@ -124,7 +136,7 @@ IrrDriver::~IrrDriver()
*/
void IrrDriver::reset()
{
m_post_processing->reset();
if (m_glsl) m_post_processing->reset();
} // reset
// ----------------------------------------------------------------------------
@ -135,22 +147,22 @@ Returns the parent window of "window" (i.e. the ancestor of window
that is a direct child of the root, or window itself if it is a direct child).
If window is the root window, returns window.
*/
X11::Window get_toplevel_parent(X11::Display* display, X11::Window window)
Window get_toplevel_parent(Display* display, Window window)
{
X11::Window parent;
X11::Window root;
X11::Window * children;
Window parent;
Window root;
Window * children;
unsigned int num_children;
while (true)
{
if (0 == X11::XQueryTree(display, window, &root,
if (0 == XQueryTree(display, window, &root,
&parent, &children, &num_children))
{
Log::fatal("irr_driver", "XQueryTree error\n");
}
if (children) { //must test for null
X11::XFree(children);
XFree(children);
}
if (window == root || parent == root) {
return window;
@ -201,7 +213,6 @@ void IrrDriver::updateConfigIfRelevant()
Log::warn("irr_driver", "Could not retrieve window location\n");
}
#elif defined(__linux__) && !defined(ANDROID)
using namespace X11;
const video::SExposedVideoData& videoData =
m_device->getVideoDriver()->getExposedVideoData();
Display* display = (Display*)videoData.OpenGLLinux.X11Display;
@ -326,6 +337,8 @@ void IrrDriver::initDevice()
params.WindowSize =
core::dimension2du(UserConfigParams::m_width,
UserConfigParams::m_height);
/*
switch ((int)UserConfigParams::m_antialiasing)
{
case 0:
@ -345,9 +358,12 @@ void IrrDriver::initDevice()
"anti-alias setting : %i\n",
(int)UserConfigParams::m_antialiasing);
}
*/
m_device = createDeviceEx(params);
if(m_device)
break;
} // for bits=32, 24, 16
m_device = createDeviceEx(params);
// if still no device, try with a standard 800x600 window size, maybe
// size is the problem
@ -382,7 +398,8 @@ void IrrDriver::initDevice()
m_gui_env = m_device->getGUIEnvironment();
m_video_driver = m_device->getVideoDriver();
m_glsl = m_video_driver->queryFeature(video::EVDF_ARB_GLSL) &&
m_video_driver->queryFeature(video::EVDF_TEXTURE_NPOT);
m_video_driver->queryFeature(video::EVDF_TEXTURE_NPOT) &&
UserConfigParams::m_pixel_shaders;
// This remaps the window, so it has to be done before the clear to avoid flicker
m_device->setResizable(false);
@ -394,10 +411,48 @@ void IrrDriver::initDevice()
if (m_glsl)
{
Log::info("irr_driver", "GLSL supported.");
// Order matters, create RTTs as soon as possible, as they are the largest blocks.
m_rtts = new RTT();
m_shaders = new Shaders();
m_shadow_importance = new ShadowImportance();
m_mrt.clear();
m_mrt.reallocate(3);
m_mrt.push_back(m_rtts->getRTT(RTT_COLOR));
m_mrt.push_back(m_rtts->getRTT(RTT_NORMAL));
m_mrt.push_back(m_rtts->getRTT(RTT_DEPTH));
irr::video::COpenGLDriver* gl_driver = (irr::video::COpenGLDriver*)m_device->getVideoDriver();
gl_driver->extGlGenQueries(1, &m_lensflare_query);
scene::IMesh * const sphere = m_scene_manager->getGeometryCreator()->createSphereMesh(1, 16, 16);
m_sun_interposer = m_scene_manager->addMeshSceneNode(sphere);
m_sun_interposer->grab();
m_sun_interposer->setParent(NULL);
m_sun_interposer->setScale(core::vector3df(20));
m_sun_interposer->getMaterial(0).Lighting = false;
m_sun_interposer->getMaterial(0).ColorMask = video::ECP_NONE;
m_sun_interposer->getMaterial(0).ZWriteEnable = false;
m_sun_interposer->getMaterial(0).MaterialType = m_shaders->getShader(ES_PASSFAR);
sphere->drop();
m_lensflare = new scene::CLensFlareSceneNode(NULL, m_scene_manager, -1);
video::ITexture * const tex =
m_video_driver->getTexture((file_manager->getTextureDir() + "lensflare.png").c_str());
if (!tex) Log::fatal("irr_driver", "Cannot find lens flare texture");
m_lensflare->setMaterialTexture(0, tex);
m_lensflare->setAutomaticCulling(scene::EAC_OFF);
m_suncam = m_scene_manager->addCameraSceneNode(0, vector3df(0), vector3df(0), -1, false);
m_suncam->grab();
m_suncam->setParent(NULL);
}
else
{
Log::warn("irr_driver", "Too old GPU; using the fixed pipeline.");
Log::warn("irr_driver", "Using the fixed pipeline (old GPU, or shaders disabled in options)");
}
// Only change video driver settings if we are showing graphics
@ -405,7 +460,6 @@ void IrrDriver::initDevice()
{
#if defined(__linux__) && !defined(ANDROID)
// Set class hints on Linux, used by Window Managers.
using namespace X11;
const video::SExposedVideoData& videoData = m_video_driver
->getExposedVideoData();
XClassHint* classhint = XAllocClassHint();
@ -421,11 +475,6 @@ void IrrDriver::initDevice()
->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
m_device->getVideoDriver()
->setTextureCreationFlag(video::ETCF_OPTIMIZED_FOR_QUALITY, true);
if (!UserConfigParams::m_fbo)
{
m_device->getVideoDriver()
->disableFeature(video::EVDF_FRAMEBUFFER_OBJECT);
}
// Force creation of mipmaps even if the mipmaps flag in a b3d file
// does not set the 'enable mipmap' flag.
@ -524,7 +573,6 @@ bool IrrDriver::moveWindow(const int x, const int y)
return false;
}
#elif defined(__linux__) && !defined(ANDROID)
using namespace X11;
const video::SExposedVideoData& videoData = m_video_driver->getExposedVideoData();
// TODO: Actually handle possible failure
XMoveWindow((Display*)videoData.OpenGLLinux.X11Display,
@ -769,6 +817,7 @@ void IrrDriver::setAllMaterialFlags(scene::IMesh *mesh) const
* \param wave_length Lenght of a water wave.
*/
scene::ISceneNode* IrrDriver::addWaterNode(scene::IMesh *mesh,
scene::IMesh **welded,
float wave_height,
float wave_speed,
float wave_length)
@ -776,11 +825,24 @@ scene::ISceneNode* IrrDriver::addWaterNode(scene::IMesh *mesh,
mesh->setMaterialFlag(video::EMF_GOURAUD_SHADING, true);
scene::IMesh* welded_mesh = m_scene_manager->getMeshManipulator()
->createMeshWelded(mesh);
scene::ISceneNode* out = m_scene_manager->addWaterSurfaceSceneNode(welded_mesh,
scene::ISceneNode* out = NULL;
if (!m_glsl)
{
out = m_scene_manager->addWaterSurfaceSceneNode(welded_mesh,
wave_height, wave_speed,
wave_length);
} else
{
out = new WaterNode(m_scene_manager, welded_mesh, wave_height, wave_speed,
wave_length);
}
out->getMaterial(0).setFlag(video::EMF_GOURAUD_SHADING, true);
welded_mesh->drop(); // The scene node keeps a reference
*welded = welded_mesh;
return out;
} // addWaterNode
@ -839,11 +901,22 @@ PerCameraNode *IrrDriver::addPerCameraMesh(scene::IMesh* mesh,
scene::ICameraSceneNode* camera,
scene::ISceneNode *parent)
{
scene::ISceneNode *node = m_scene_manager->addMeshSceneNode(mesh);
return new PerCameraNode((parent ? parent
: m_scene_manager->getRootSceneNode()),
m_scene_manager, -1, camera, mesh);
m_scene_manager, -1, camera, node);
} // addMesh
PerCameraNode *IrrDriver::addPerCameraNode(scene::ISceneNode* node,
scene::ICameraSceneNode* camera,
scene::ISceneNode *parent)
{
return new PerCameraNode((parent ? parent
: m_scene_manager->getRootSceneNode()),
m_scene_manager, -1, camera, node);
} // addNode
// ----------------------------------------------------------------------------
/** Adds a billboard node to scene.
@ -994,9 +1067,9 @@ void IrrDriver::removeTexture(video::ITexture *t)
/** Adds an animated mesh to the scene.
* \param mesh The animated mesh to add.
*/
scene::IAnimatedMeshSceneNode *IrrDriver::addAnimatedMesh(scene::IAnimatedMesh *mesh)
scene::IAnimatedMeshSceneNode *IrrDriver::addAnimatedMesh(scene::IAnimatedMesh *mesh, scene::ISceneNode* parent)
{
return m_scene_manager->addAnimatedMeshSceneNode(mesh, NULL, -1,
return m_scene_manager->addAnimatedMeshSceneNode(mesh, parent, -1,
core::vector3df(0,0,0),
core::vector3df(0,0,0),
core::vector3df(1,1,1),
@ -1067,6 +1140,32 @@ void IrrDriver::removeCameraSceneNode(scene::ICameraSceneNode *camera)
camera->remove();
} // removeCameraSceneNode
// ----------------------------------------------------------------------------
/** Sets an error message to be displayed when a texture is not found. This
* error message is shown before the "Texture '%s' not found" message. It can
* be used to supply additional details like what kart is currently being
* loaded.
* \param error Error message, potentially with a '%' which will be replaced
* with detail.
* \param detail String to replace a '%' in the error message.
*/
void IrrDriver::setTextureErrorMessage(const std::string &error,
const std::string &detail)
{
if(detail=="")
m_texture_error_message = error;
else
m_texture_error_message = StringUtils::insertValues(error, detail);
} // setTextureErrorMessage
// ----------------------------------------------------------------------------
/** Disables the texture error message again.
*/
void IrrDriver::unsetTextureErrorMessage()
{
m_texture_error_message = "";
} // unsetTextureErrorMessage
// ----------------------------------------------------------------------------
/** Loads a texture from a file and returns the texture object.
* \param filename File name of the texture to load.
@ -1096,7 +1195,7 @@ video::ITexture *IrrDriver::getTexture(const std::string &filename,
// PNGs are non premul, but some are used for premul tasks, so convert
// http://home.comcast.net/~tom_forsyth/blog.wiki.html#[[Premultiplied%20alpha]]
// FIXME check param, not name
if(is_premul &&
if(img && is_premul &&
StringUtils::hasSuffix(filename.c_str(), ".png") &&
(img->getColorFormat() == video::ECF_A8R8G8B8) &&
img->lock())
@ -1119,7 +1218,7 @@ video::ITexture *IrrDriver::getTexture(const std::string &filename,
} // if png and ColorFOrmat and lock
// Other formats can be premul, but the tasks can be non premul
// So divide to get the separate RGBA (only possible if alpha!=0)
else if(is_prediv &&
else if(img && is_prediv &&
(img->getColorFormat() == video::ECF_A8R8G8B8) &&
img->lock())
{
@ -1148,9 +1247,12 @@ video::ITexture *IrrDriver::getTexture(const std::string &filename,
if (complain_if_not_found && out == NULL)
{
Log::error("irr_driver", "Texture '%s' not found; Put a breakpoint "
"at line %s:%i to debug!\n",
filename.c_str(), __FILE__, __LINE__);
if(m_texture_error_message.size()>0)
{
Log::error("irr_driver", m_texture_error_message.c_str());
}
Log::error("irr_driver", "Texture '%s' not found.", filename.c_str());
}
return out;
@ -1581,6 +1683,11 @@ void IrrDriver::update(float dt)
return;
}
// If we quit via the menu the m_device->run() does not return true.
// To avoid any other calls, we return here.
if(main_loop->isAborted())
return;
// If the resolution should be switched, do it now. This will delete the
// old device and create a new one.
if (m_resolution_changing!=RES_CHANGE_NONE)
@ -1591,6 +1698,8 @@ void IrrDriver::update(float dt)
m_resolution_changing = RES_CHANGE_NONE;
}
m_wind->update();
World *world = World::getWorld();
// Handle cut scenes (which do not have any karts in it)
@ -1615,97 +1724,24 @@ void IrrDriver::update(float dt)
m_video_driver->endScene();
return;
}
const bool inRace = world!=NULL;
if (inRace)
else if (!world)
{
// Start the RTT for post-processing.
// We do this before beginScene() because we want to capture the glClear()
// because of tracks that do not have skyboxes (generally add-on tracks)
m_post_processing->beginCapture();
}
m_video_driver->beginScene(/*backBuffer clear*/ true, /*zBuffer*/ true,
world ? world->getClearColor()
: video::SColor(255,100,101,140));
video::SColor(255,100,101,140));
if (inRace)
{
irr_driver->getVideoDriver()->enableMaterial2D();
RaceGUIBase *rg = world->getRaceGUI();
if (rg) rg->update(dt);
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
Camera *camera = Camera::getCamera(i);
#ifdef ENABLE_PROFILER
std::ostringstream oss;
oss << "drawAll() for kart " << i << std::flush;
PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), (i+1)*60,
0x00, 0x00);
#endif
camera->activate();
rg->preRenderCallback(camera); // adjusts start referee
m_scene_manager->drawAll();
PROFILER_POP_CPU_MARKER();
// Note that drawAll must be called before rendering
// the bullet debug view, since otherwise the camera
// is not set up properly. This is only used for
// the bullet debug view.
if (UserConfigParams::m_artist_debug_mode)
World::getWorld()->getPhysics()->draw();
} // for i<world->getNumKarts()
// Stop capturing for the post-processing
m_post_processing->endCapture();
// Render the post-processed scene
m_post_processing->render();
// Set the viewport back to the full screen for race gui
m_video_driver->setViewPort(core::recti(0, 0,
UserConfigParams::m_width,
UserConfigParams::m_height));
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
Camera *camera = Camera::getCamera(i);
char marker_name[100];
sprintf(marker_name, "renderPlayerView() for kart %d", i);
PROFILER_PUSH_CPU_MARKER(marker_name, 0x00, 0x00, (i+1)*60);
rg->renderPlayerView(camera, dt);
PROFILER_POP_CPU_MARKER();
} // for i<getNumKarts
}
// Either render the gui, or the global elements of the race gui.
GUIEngine::render(dt);
// Render the profiler
if(UserConfigParams::m_profiler_enabled)
{
PROFILER_DRAW();
m_video_driver->endScene();
return;
}
#ifdef DEBUG
drawDebugMeshes();
#endif
m_video_driver->endScene();
if (m_glsl)
renderGLSL(dt);
else
renderFixed(dt);
if (m_request_screenshot) doScreenShot();
getPostProcessing()->update(dt);
// Enable this next print statement to get render information printed
// E.g. number of triangles rendered, culled etc. The stats is only
// printed while the race is running and not while the in-game menu
@ -1739,7 +1775,7 @@ bool IrrDriver::OnEvent(const irr::SEvent &event)
// Ignore 'normal' messages
if (event.LogEvent.Level > 1)
{
printf("[IrrDriver Temp Logger] Level %d: %s\n",
Log::warn("[IrrDriver Temp Logger]", "Level %d: %s\n",
event.LogEvent.Level,event.LogEvent.Text);
}
return true;
@ -1755,7 +1791,7 @@ bool IrrDriver::OnEvent(const irr::SEvent &event)
bool IrrDriver::supportsSplatting()
{
return UserConfigParams::m_pixel_shaders && m_glsl;
return m_glsl;
}
// ----------------------------------------------------------------------------
@ -1941,6 +1977,11 @@ video::ITexture* IrrDriver::RTTProvider::renderToTexture(float angle,
if (angle != -1 && m_rtt_main_node != NULL)
m_rtt_main_node->setRotation( core::vector3df(0, angle, 0) );
video::SOverrideMaterial &overridemat = m_video_driver->getOverrideMaterial();
overridemat.EnablePasses = scene::ESNRP_SOLID;
overridemat.EnableFlags = video::EMF_MATERIAL_TYPE;
overridemat.Material.MaterialType = video::EMT_SOLID;
if (m_rtt_main_node == NULL)
{
irr_driver->getSceneManager()->drawAll();
@ -1954,6 +1995,129 @@ video::ITexture* IrrDriver::RTTProvider::renderToTexture(float angle,
m_light->setVisible(false);
}
overridemat.EnablePasses = 0;
m_video_driver->setRenderTarget(0, false, false);
return m_render_target_texture;
}
void IrrDriver::applyObjectPassShader(scene::ISceneNode * const node, bool rimlit)
{
if (!m_glsl)
return;
// Don't override sky
if (node->getType() == scene::ESNT_SKY_DOME ||
node->getType() == scene::ESNT_SKY_BOX)
return;
const u32 mcount = node->getMaterialCount();
u32 i;
const video::E_MATERIAL_TYPE ref = rimlit ? m_shaders->getShader(ES_OBJECTPASS_RIMLIT):
m_shaders->getShader(ES_OBJECTPASS_REF);
const video::E_MATERIAL_TYPE pass = rimlit ? m_shaders->getShader(ES_OBJECTPASS_RIMLIT):
m_shaders->getShader(ES_OBJECTPASS);
const video::E_MATERIAL_TYPE origref = m_shaders->getShader(ES_OBJECTPASS_REF);
const video::E_MATERIAL_TYPE origpass = m_shaders->getShader(ES_OBJECTPASS);
bool viamb = false;
scene::IMesh *mesh = NULL;
if (node->getType() == scene::ESNT_ANIMATED_MESH)
{
viamb = ((scene::IAnimatedMeshSceneNode *) node)->isReadOnlyMaterials();
mesh = ((scene::IAnimatedMeshSceneNode *) node)->getMesh();
}
else if (node->getType() == scene::ESNT_MESH)
{
viamb = ((scene::IMeshSceneNode *) node)->isReadOnlyMaterials();
mesh = ((scene::IMeshSceneNode *) node)->getMesh();
}
for (i = 0; i < mcount; i++)
{
video::SMaterial &nodemat = node->getMaterial(i);
video::SMaterial &mbmat = mesh ? mesh->getMeshBuffer(i)->getMaterial() : nodemat;
video::SMaterial *mat = &nodemat;
if (viamb)
mat = &mbmat;
if (mat->MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF ||
mat->MaterialType == origref)
mat->MaterialType = ref;
else if (mat->MaterialType == video::EMT_SOLID ||
mat->MaterialType == origpass ||
(mat->MaterialType >= video::EMT_LIGHTMAP &&
mat->MaterialType <= video::EMT_LIGHTMAP_LIGHTING_M4))
mat->MaterialType = pass;
}
core::list<scene::ISceneNode*> kids = node->getChildren();
scene::ISceneNodeList::Iterator it = kids.begin();
for (; it != kids.end(); ++it)
{
applyObjectPassShader(*it, rimlit);
}
}
void IrrDriver::applyObjectPassShader()
{
if (!m_glsl)
return;
applyObjectPassShader(m_scene_manager->getRootSceneNode());
}
scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos, float radius,
float r, float g, float b, bool sun)
{
if (m_glsl)
{
LightNode *light = NULL;
if (!sun)
light = new LightNode(m_scene_manager, radius, r, g, b);
else
light = new SunNode(m_scene_manager, r, g, b);
light->grab();
light->setParent(NULL);
light->setPosition(pos);
light->updateAbsolutePosition();
m_lights.push_back(light);
if (sun) {
m_sun_interposer->setPosition(pos);
m_sun_interposer->updateAbsolutePosition();
m_lensflare->setPosition(pos);
m_lensflare->updateAbsolutePosition();
m_suncam->setPosition(pos);
m_suncam->updateAbsolutePosition();
((WaterShaderProvider *) m_shaders->m_callbacks[ES_WATER])->setSunPosition(pos);
}
return light;
} else
{
return m_scene_manager->addLightSceneNode(NULL, pos, video::SColorf(r, g, b), radius);
}
}
void IrrDriver::clearLights()
{
u32 i;
const u32 max = m_lights.size();
for (i = 0; i < max; i++)
{
m_lights[i]->drop();
}
m_lights.clear();
}

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
// Copyright (C) 2009-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -39,11 +39,15 @@
namespace irr
{
namespace scene { class ISceneManager; class IMesh; class IAnimatedMeshSceneNode; class IAnimatedMesh;
class IMeshSceneNode; class IParticleSystemSceneNode; class ICameraSceneNode; class ILightSceneNode; }
class IMeshSceneNode; class IParticleSystemSceneNode; class ICameraSceneNode; class ILightSceneNode;
class CLensFlareSceneNode; }
namespace gui { class IGUIEnvironment; class IGUIFont; }
}
using namespace irr;
#include "graphics/rtts.hpp"
#include "graphics/shaders.hpp"
#include "graphics/wind.hpp"
#include "utils/aligned_array.hpp"
#include "utils/no_copy.hpp"
#include "utils/ptr_vector.hpp"
@ -53,6 +57,8 @@ class AbstractKart;
class Camera;
class PerCameraNode;
class PostProcessing;
class LightNode;
class ShadowImportance;
/**
* \brief class that creates the irrLicht device and offers higher-level
@ -74,6 +80,21 @@ private:
gui::IGUIFont *m_race_font;
/** Post-processing. */
PostProcessing *m_post_processing;
/** Shaders. */
Shaders *m_shaders;
/** Wind. */
Wind *m_wind;
/** RTTs. */
RTT *m_rtts;
/** Shadow importance. */
ShadowImportance *m_shadow_importance;
/** Additional details to be shown in case that a texture is not found.
* This is used to specify details like: "while loading kart '...'" */
std::string m_texture_error_message;
/** The main MRT setup. */
core::array<video::IRenderTarget> m_mrt;
/** Flag to indicate if a resolution change is pending (which will be
* acted upon in the next update). None means no change, yes means
@ -95,6 +116,12 @@ public:
int getWidth() const {return m_width; }
int getHeight() const {return m_height; }
}; // VideoMode
struct BloomData {
scene::ISceneNode * node;
float power;
};
private:
std::vector<VideoMode> m_modes;
@ -112,6 +139,34 @@ private:
bool m_request_screenshot;
bool m_wireframe;
bool m_mipviz;
bool m_normals;
bool m_ssaoviz;
bool m_shadowviz;
bool m_lightviz;
bool m_distortviz;
u32 m_renderpass;
u32 m_lensflare_query;
scene::IMeshSceneNode *m_sun_interposer;
scene::CLensFlareSceneNode *m_lensflare;
scene::ICameraSceneNode *m_suncam;
struct GlowData {
scene::ISceneNode * node;
float r, g, b;
};
std::vector<GlowData> m_glowing;
std::vector<LightNode *> m_lights;
std::vector<BloomData> m_forcedbloom;
std::vector<scene::ISceneNode *> m_displacing;
std::vector<scene::ISceneNode *> m_background;
#ifdef DEBUG
/** Used to visualise skeletons. */
std::vector<irr::scene::IAnimatedMeshSceneNode*> m_debug_meshes;
@ -122,6 +177,9 @@ private:
irr::scene::ISkinnedMesh* mesh, int id);
#endif
void renderFixed(float dt);
void renderGLSL(float dt);
void doScreenShot();
public:
IrrDriver();
@ -147,7 +205,8 @@ public:
bool create_one_quad=false);
scene::IMesh *createTexturedQuadMesh(const video::SMaterial *material,
const double w, const double h);
scene::ISceneNode *addWaterNode(scene::IMesh *mesh, float wave_height,
scene::ISceneNode *addWaterNode(scene::IMesh *mesh, scene::IMesh **welded,
float wave_height,
float wave_speed, float wave_length);
scene::IMeshSceneNode*addOctTree(scene::IMesh *mesh);
scene::IMeshSceneNode*addSphere(float radius,
@ -157,6 +216,9 @@ public:
PerCameraNode *addPerCameraMesh(scene::IMesh* mesh,
scene::ICameraSceneNode* node,
scene::ISceneNode *parent = NULL);
PerCameraNode *addPerCameraNode(scene::ISceneNode* node,
scene::ICameraSceneNode* cam,
scene::ISceneNode *parent = NULL);
scene::ISceneNode *addBillboard(const core::dimension2d< f32 > size,
video::ITexture *texture,
scene::ISceneNode* parent=NULL, bool alphaTesting = false);
@ -171,7 +233,7 @@ public:
void removeMeshFromCache(scene::IMesh *mesh);
void removeTexture(video::ITexture *t);
scene::IAnimatedMeshSceneNode
*addAnimatedMesh(scene::IAnimatedMesh *mesh);
*addAnimatedMesh(scene::IAnimatedMesh *mesh, scene::ISceneNode* parent=NULL);
scene::ICameraSceneNode
*addCameraSceneNode();
Camera *addCamera(unsigned int index, AbstractKart *kart);
@ -193,6 +255,9 @@ public:
void printRenderStats();
bool supportsSplatting();
void requestScreenshot();
void setTextureErrorMessage(const std::string &error,
const std::string &detail="");
void unsetTextureErrorMessage();
void draw2dTriangle(const core::vector2df &a, const core::vector2df &b,
const core::vector2df &c,
@ -203,6 +268,55 @@ public:
// ------------------------------------------------------------------------
/** Convenience function that loads a texture with default parameters
* but includes an error message.
* \param filename File name of the texture to load.
* \param error Error message, potentially with a '%' which will be replaced
* with detail.
* \param detail String to replace a '%' in the error message.
*/
video::ITexture* getTexture(const std::string &filename,
const std::string &error_message,
const std::string &detail="")
{
setTextureErrorMessage(error_message, detail);
video::ITexture *tex = getTexture(filename);
unsetTextureErrorMessage();
return tex;
} // getTexture
// ------------------------------------------------------------------------
/** Convenience function that loads a texture with default parameters
* but includes an error message.
* \param filename File name of the texture to load.
* \param error Error message, potentially with a '%' which will be replaced
* with detail.
* \param detail String to replace a '%' in the error message.
*/
video::ITexture* getTexture(const std::string &filename,
char *error_message,
char *detail=NULL)
{
if(!detail)
return getTexture(filename, std::string(error_message),
std::string(""));
return getTexture(filename, std::string(error_message),
std::string(detail));
} // getTexture
// ------------------------------------------------------------------------
/** Returns the currently defined texture error message, which is used
* by event_handler.cpp to print additional info about irrlicht
* internal errors or warnings. If no error message is currently
* defined, the error message is "".
*/
const std::string &getTextureErrorMessage()
{
return m_texture_error_message;
} // getTextureErrorMessage
// ------------------------------------------------------------------------
/** Returns a list of all video modes supports by the graphics card. */
const std::vector<VideoMode>& getVideoModes() const { return m_modes; }
@ -230,9 +344,89 @@ public:
/** Returns a pointer to the post processing object. */
inline PostProcessing* getPostProcessing() {return m_post_processing;}
// ------------------------------------------------------------------------
inline core::vector3df getWind() {return m_wind->getWind();}
// ------------------------------------------------------------------------
inline video::E_MATERIAL_TYPE getShader(const ShaderType num) {return m_shaders->getShader(num);}
// ------------------------------------------------------------------------
inline video::IShaderConstantSetCallBack* getCallback(const ShaderType num)
{
return (m_shaders == NULL ? NULL : m_shaders->m_callbacks[num]);
}
// ------------------------------------------------------------------------
inline video::ITexture* getRTT(TypeRTT which) {return m_rtts->getRTT(which);}
// ------------------------------------------------------------------------
inline bool isGLSL() const { return m_glsl; }
// ------------------------------------------------------------------------
void toggleWireframe() { m_wireframe ^= 1; }
// ------------------------------------------------------------------------
void toggleMipVisualization() { m_mipviz ^= 1; }
// ------------------------------------------------------------------------
void toggleNormals() { m_normals ^= 1; }
// ------------------------------------------------------------------------
bool getNormals() { return m_normals; }
// ------------------------------------------------------------------------
void toggleSSAOViz() { m_ssaoviz ^= 1; }
// ------------------------------------------------------------------------
void toggleLightViz() { m_lightviz ^= 1; }
// ------------------------------------------------------------------------
bool getSSAOViz() { return m_ssaoviz; }
// ------------------------------------------------------------------------
void toggleShadowViz() { m_shadowviz ^= 1; }
// ------------------------------------------------------------------------
bool getShadowViz() { return m_shadowviz; }
// ------------------------------------------------------------------------
void toggleDistortViz() { m_distortviz ^= 1; }
// ------------------------------------------------------------------------
bool getDistortViz() { return m_distortviz; }
// ------------------------------------------------------------------------
u32 getRenderPass() { return m_renderpass; }
// ------------------------------------------------------------------------
void addGlowingNode(scene::ISceneNode *n, float r = 1.0f, float g = 1.0f, float b = 1.0f)
{
GlowData dat;
dat.node = n;
dat.r = r;
dat.g = g;
dat.b = b;
m_glowing.push_back(dat);
}
// ------------------------------------------------------------------------
void clearGlowingNodes() { m_glowing.clear(); }
// ------------------------------------------------------------------------
void addForcedBloomNode(scene::ISceneNode *n, float power = 1)
{
BloomData dat;
dat.node = n;
dat.power = power;
m_forcedbloom.push_back(dat);
}
// ------------------------------------------------------------------------
void clearForcedBloom() { m_forcedbloom.clear(); }
// ------------------------------------------------------------------------
const std::vector<BloomData> &getForcedBloom() const { return m_forcedbloom; }
// ------------------------------------------------------------------------
void clearDisplacingNodes() { m_displacing.clear(); }
// ------------------------------------------------------------------------
const std::vector<scene::ISceneNode *> &getDisplacingNodes() const { return m_displacing; }
// ------------------------------------------------------------------------
void addDisplacingNode(scene::ISceneNode * const n) { m_displacing.push_back(n); }
// ------------------------------------------------------------------------
void clearBackgroundNodes() { m_background.clear(); }
// ------------------------------------------------------------------------
void addBackgroundNode(scene::ISceneNode * const n) { m_background.push_back(n); }
// ------------------------------------------------------------------------
void applyObjectPassShader();
void applyObjectPassShader(scene::ISceneNode * const node, bool rimlit = false);
// ------------------------------------------------------------------------
scene::ISceneNode *addLight(const core::vector3df &pos, float radius = 1.0f, float r = 1.0f,
float g = 1.0f, float b = 1.0f, bool sun = false);
// ------------------------------------------------------------------------
void clearLights();
// ------------------------------------------------------------------------
scene::IMeshSceneNode *getSunInterposer() { return m_sun_interposer; }
#ifdef DEBUG
/** Removes debug meshes. */
void clearDebugMesh() { m_debug_meshes.clear(); }

View File

@ -0,0 +1,58 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __LARGE_MESH_BUFFER_H_INCLUDED__
#define __LARGE_MESH_BUFFER_H_INCLUDED__
#include "irrArray.h"
#include "IMeshBuffer.h"
#include "CMeshBuffer.h"
namespace irr
{
namespace scene
{
//! A SMeshBuffer with 32-bit indices
class LargeMeshBuffer : public SMeshBuffer
{
public:
//! Get type of index data which is stored in this meshbuffer.
/** \return Index type of this buffer. */
virtual video::E_INDEX_TYPE getIndexType() const
{
return video::EIT_32BIT;
}
//! Get pointer to indices
/** \return Pointer to indices. */
virtual const u16* getIndices() const
{
return (u16 *) Indices.const_pointer();
}
//! Get pointer to indices
/** \return Pointer to indices. */
virtual u16* getIndices()
{
return (u16 *) Indices.pointer();
}
//! Get number of indices
/** \return Number of indices. */
virtual u32 getIndexCount() const
{
return Indices.size();
}
//! Indices into the vertices of this buffer.
core::array<u32> Indices;
};
} // end namespace scene
} // end namespace irr
#endif

264
src/graphics/lens_flare.cpp Normal file
View File

@ -0,0 +1,264 @@
/* TODO: copyright */
#include "graphics/lens_flare.hpp"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "ISceneCollisionManager.h"
namespace irr
{
namespace scene
{
CLensFlareSceneNode::CLensFlareSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id) :
scene::ISceneNode(parent, mgr, id)
{
#ifdef _DEBUG
setDebugName("CLensFlareSceneNode");
#endif
// set the bounding box
BBox.MaxEdge.set(0,0,0);
BBox.MinEdge.set(0,0,0);
// set the initial Strength
Strength = 1.0f;
// setup the vertices
Vertices[0] = video::S3DVertex(-1.f, -1.f, 0.f, 0.f, 0.f, 1.f, 0xffffffff, 0.f, 1.f);
Vertices[1] = video::S3DVertex(-1.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0xffffffff, 0.f, 0.f);
Vertices[2] = video::S3DVertex( 1.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0xffffffff, 1.f, 0.f);
Vertices[3] = video::S3DVertex( 1.f, -1.f, 0.f, 0.f, 0.f, 1.f, 0xffffffff, 1.f, 1.f);
// setup the indices
Indices[0] = 0;
Indices[1] = 1;
Indices[2] = 2;
Indices[3] = 2;
Indices[4] = 3;
Indices[5] = 0;
// set the default material properties
Material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
Material.Lighting = false;
Material.ZBuffer = video::ECFN_NEVER;
FlareData.reallocate(30);
// prepare the flare data array
// circles, halos and ring behind the sun
FlareData.push_back(SFlareData(EFT_CIRCLE, 0.5f, 0.12f, video::SColor(120, 60, 180, 35)));
FlareData.push_back(SFlareData(EFT_HALO, 0.45f, 0.4f, video::SColor(200, 100, 200, 60)));
FlareData.push_back(SFlareData(EFT_CIRCLE, 0.4f, 0.17f, video::SColor(240, 120, 220, 40)));
FlareData.push_back(SFlareData(EFT_CIRCLE, 0.2f, 0.35f, video::SColor(175, 175, 255, 20)));
FlareData.push_back(SFlareData(EFT_RING, 0.15f, 0.2f, video::SColor(120, 60, 255, 100)));
// sun and glow effect at sun position
FlareData.push_back(SFlareData(EFT_SUN, 0.0f, 0.75f, video::SColor(255, 255, 255, 255)));
// FlareData.push_back(SFlareData(EFT_STREAKS, 0.0f, 2.9f, video::SColor(255, 255, 255, 255)));
FlareData.push_back(SFlareData(EFT_GLOW, 0.0f, 3.5f, video::SColor(255, 255, 255, 255)));
// FlareData.push_back(SFlareData(EFT_RING, 0.0f, 1.5f, video::SColor(120, 120, 120, 150)));
// some lenses, halos and circles
FlareData.push_back(SFlareData(EFT_LENS, -0.15f, 0.15f, video::SColor(255, 60, 60, 90)));
FlareData.push_back(SFlareData(EFT_HALO, -0.3f, 0.3f, video::SColor(120, 60, 255, 180)));
FlareData.push_back(SFlareData(EFT_HALO, -0.4f, 0.2f, video::SColor(220, 80, 80, 98)));
FlareData.push_back(SFlareData(EFT_CIRCLE, -0.45f, 0.1f, video::SColor(220, 80, 80, 85)));
FlareData.push_back(SFlareData(EFT_RING, -0.42f, 0.3f, video::SColor(180, 60, 255, 110)));
// some small lenses, halos and rings
FlareData.push_back(SFlareData(EFT_LENS, -0.55f, 0.2f, video::SColor(255, 60, 60, 130)));
FlareData.push_back(SFlareData(EFT_HALO, -0.6f, 0.3f, video::SColor(120, 60, 255, 80)));
FlareData.push_back(SFlareData(EFT_LENS, -0.7f, 0.2f, video::SColor(200, 60, 60, 130)));
FlareData.push_back(SFlareData(EFT_LENS, -0.71f, 0.2f, video::SColor(200, 60, 130, 60)));
FlareData.push_back(SFlareData(EFT_LENS, -0.72f, 0.2f, video::SColor(200, 130, 130, 60)));
FlareData.push_back(SFlareData(EFT_LENS, -0.74f, 0.2f, video::SColor(200, 130, 60, 60)));
// some polyons, lenses and circle
FlareData.push_back(SFlareData(scene::EFT_POLY, -0.79f, 0.2f, video::SColor(200, 60, 130, 60)));
FlareData.push_back(SFlareData(scene::EFT_POLY, -0.86f, 0.3f, video::SColor(200, 130, 130, 60)));
FlareData.push_back(SFlareData(scene::EFT_LENS, -0.87f, 0.3f, video::SColor(180,255,192,178)));
FlareData.push_back(SFlareData(scene::EFT_CIRCLE, -0.9f, 0.1f, video::SColor(200, 60, 60, 130)));
FlareData.push_back(SFlareData(scene::EFT_POLY, -0.93f, 0.4f, video::SColor(200, 130, 60, 60)));
// finally som polygons
FlareData.push_back(SFlareData(EFT_POLY, -0.95f, 0.6f, video::SColor(120, 60, 255, 120)));
FlareData.push_back(SFlareData(EFT_POLY, -1.0f, 0.15f, video::SColor(120, 20, 255, 85)));
}
CLensFlareSceneNode::~CLensFlareSceneNode()
{
}
u32 CLensFlareSceneNode::getMaterialCount() const
{
// return the material count (always one in our case)
return 1;
}
video::SMaterial& CLensFlareSceneNode::getMaterial(u32 i)
{
// return the material
return Material;
}
core::array<SFlareData>& CLensFlareSceneNode::getFlareData()
{
// return the flare data array
return FlareData;
}
void CLensFlareSceneNode::OnRegisterSceneNode()
{
// if node is visible and Strength is greater than 0 register it for the ESNRP_TRANSPARENT_EFFECT pass
if(IsVisible && Strength > 0.0f)
{
SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT_EFFECT);
}
// call base OnRegisterSceneNode
ISceneNode::OnRegisterSceneNode();
}
void CLensFlareSceneNode::render()
{
// get the videodriver and the active camera
video::IVideoDriver* driver = SceneManager->getVideoDriver();
ICameraSceneNode* camera = SceneManager->getActiveCamera();
// return if we don't have a valid driver or a valid camera
// or if we have no texture attached to the material
if (!camera || !driver || !Material.getTexture(0))
return;
// get screencenter
const core::vector2d<s32> screenCenter = core::vector2d<s32>(
SceneManager->getVideoDriver()->getScreenSize().Width,
SceneManager->getVideoDriver()->getScreenSize().Height)/2;
// get screencoordinates of the node
const core::vector2d<s32> lightPos = SceneManager->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(
getAbsolutePosition(),
camera);
// store old projection matrix
core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
// store old view matrix
core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
// clear the projection matrix
driver->setTransform(video::ETS_PROJECTION, core::IdentityMatrix);
// clear the view matrix
driver->setTransform(video::ETS_VIEW, core::IdentityMatrix);
// set the transform
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
// set the material
driver->setMaterial(Material);
// calculate some handy constants
const f32 texPos = 1.0f/EFT_COUNT;
const s32 texHeight = s32(Material.getTexture(0)->getSize().Height*0.5f);
const f32 screenWidth = f32(driver->getScreenSize().Width);
const f32 screenHeight = f32(driver->getScreenSize().Height);
// render the flares
for (u32 i=0; i<FlareData.size(); ++i)
{
// get the flare element
SFlareData& flare = FlareData[i];
// calculate center of the flare
core::vector2d<s32>flarePos = screenCenter.getInterpolated(lightPos, -2.0*flare.Position);
// calculate flareposition in vertex coordinates using the scalefactor of the flare
s32 flareScale = s32((texHeight*flare.Scale));
core::rect<f32> flareRect = core::rect<f32>(
-1.f + 2.f * f32(flarePos.X-flareScale) / screenWidth,
-1.f + 2.f * f32(screenHeight-flarePos.Y-flareScale) / screenHeight,
-1.f + 2.f * f32(flarePos.X+flareScale) / screenWidth,
-1.f + 2.f * f32(screenHeight-flarePos.Y+flareScale) / screenHeight);
// calculate flarecolor in dependence of occlusion
f32 flareAlpha = f32(flare.Color.getAlpha()) / 255.f;
video::SColor flareColor(255,
(u32)(Strength * flareAlpha * flare.Color.getRed()),
(u32)(Strength * flareAlpha * flare.Color.getGreen()),
(u32)(Strength * flareAlpha * flare.Color.getBlue()));
// set vertex colors
Vertices[0].Color = flareColor;
Vertices[1].Color = flareColor;
Vertices[2].Color = flareColor;
Vertices[3].Color = flareColor;
// set texture coordinates
Vertices[0].TCoords.set( flare.Type * texPos, 1.0f);
Vertices[1].TCoords.set( flare.Type * texPos, 0.0f);
Vertices[2].TCoords.set((flare.Type+1) * texPos, 0.0f);
Vertices[3].TCoords.set((flare.Type+1) * texPos, 1.0f);
// set vertex positions
Vertices[0].Pos.set(flareRect.UpperLeftCorner.X, flareRect.UpperLeftCorner.Y, 0);
Vertices[1].Pos.set(flareRect.UpperLeftCorner.X, flareRect.LowerRightCorner .Y, 0);
Vertices[2].Pos.set(flareRect.LowerRightCorner.X, flareRect.LowerRightCorner.Y, 0);
Vertices[3].Pos.set(flareRect.LowerRightCorner.X, flareRect.UpperLeftCorner.Y, 0);
//draw the mesh
driver->drawIndexedTriangleList(Vertices, 4, Indices, 2);
}
// restore view matrix
driver->setTransform(video::ETS_VIEW, oldViewMat);
// restore projection matrix
driver->setTransform(video::ETS_PROJECTION, oldProjMat);
}
const core::aabbox3df& CLensFlareSceneNode::getBoundingBox() const
{
// return the bounding box
return BBox;
}
ESCENE_NODE_TYPE CLensFlareSceneNode::getType() const
{
// return type of the scene node
// (important when using with a custom scene node factory)
return scene::ESNT_UNKNOWN; //(ESCENE_NODE_TYPE) ECSNT_LENSFLARE;
}
void CLensFlareSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
{
// write attributes of the scene node.
ISceneNode::serializeAttributes(out, options);
}
void CLensFlareSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
// read attributes of the scene node.
ISceneNode::deserializeAttributes(in, options);
}
ISceneNode* CLensFlareSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
{
if (!newParent)
newParent = Parent;
if (!newManager)
newManager = SceneManager;
CLensFlareSceneNode* nb = new CLensFlareSceneNode(newParent, newManager, ID);
nb->cloneMembers(this, newManager);
nb->Material = Material;
nb->drop();
return nb;
}
}// end irr namespace
}// end scene namespace

117
src/graphics/lens_flare.hpp Normal file
View File

@ -0,0 +1,117 @@
#ifndef _CLENSFLARESCENENODE_H
#define _CLENSFLARESCENENODE_H
#include <ISceneNode.h>
#include <S3DVertex.h>
namespace irr
{
namespace scene
{
// enum with different flare types (used by SFlareData)
enum E_FLARE_TYPE
{
EFT_SUN = 0,
EFT_GLOW,
EFT_LENS,
EFT_STREAKS,
EFT_RING,
EFT_HALO,
EFT_CIRCLE,
EFT_POLY,
EFT_COUNT
};
// struct holding the flare specification
struct SFlareData
{
public:
// constructor
SFlareData(const E_FLARE_TYPE type, const float position,
const float scale, const video::SColor &color)
{
Type = type;
Position = position;
Scale = scale;
Color = color;
}
// flare type
E_FLARE_TYPE Type;
// position
f32 Position;
// flare scale
f32 Scale;
// flare color
video::SColor Color;
};
class CLensFlareSceneNode : public ISceneNode
{
public:
// constructor
CLensFlareSceneNode(ISceneNode* parent, scene::ISceneManager* mgr, s32 id = -1);
// destructor
virtual ~CLensFlareSceneNode();
protected:
// material of the node
video::SMaterial Material;
// Bounding box
core::aabbox3d<f32> BBox;
// vertices and indices of a flare element
video::S3DVertex Vertices[4];
u16 Indices[6];
// flare data array
core::array<SFlareData> FlareData;
// Strength of the flare effect (between 0 and 1)
f32 Strength;
public:
// typical OnRegisterSceneNode function
virtual void OnRegisterSceneNode();
// renders the node
virtual void render();
// returns the bounding box
virtual const core::aabbox3d<f32>& getBoundingBox() const;
// returns the node type
virtual ESCENE_NODE_TYPE getType() const;
// returns the material count
virtual u32 getMaterialCount() const;
// returns the material
virtual video::SMaterial& getMaterial(u32 i);
// writes attributes of the scene node.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options = 0) const;
// reads attributes of the scene node.
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options = 0);
// clones the node
virtual ISceneNode* clone(ISceneNode* newParent = 0, ISceneManager* newManager = 0);
// returns the flare data array
core::array<SFlareData>& getFlareData();
// returns the strength (visibility) of the flares
f32 getStrength() { return Strength; }
// sets the strength (visibility) of the flares
void setStrength(f32 strength) { Strength = core::clamp(strength, 0.0f, 0.7f); }
};
} // end namespace scene
} // end namespace irr
#endif

93
src/graphics/light.cpp Normal file
View File

@ -0,0 +1,93 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Lauri Kasanen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/light.hpp"
#include "graphics/callbacks.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/material.hpp"
#include "graphics/rtts.hpp"
#include "graphics/shaders.hpp"
using namespace video;
using namespace scene;
using namespace core;
IMesh * LightNode::sphere = NULL;
SMaterial LightNode::mat;
aabbox3df LightNode::box;
LightNode::LightNode(scene::ISceneManager* mgr, float radius, float r, float g, float b):
ISceneNode(mgr->getRootSceneNode(), mgr, -1)
{
if (!sphere)
{
mat.Lighting = false;
mat.MaterialType = irr_driver->getShader(ES_POINTLIGHT);
mat.setTexture(0, irr_driver->getRTT(RTT_NORMAL));
mat.setTexture(1, irr_driver->getRTT(RTT_DEPTH));
for (u32 i = 0; i < MATERIAL_MAX_TEXTURES; ++i)
{
mat.TextureLayer[i].TextureWrapU =
mat.TextureLayer[i].TextureWrapV = ETC_CLAMP_TO_EDGE;
}
mat.setFlag(EMF_BILINEAR_FILTER, false);
mat.setFlag(EMF_ZWRITE_ENABLE, false);
mat.MaterialTypeParam = pack_textureBlendFunc(EBF_ONE, EBF_ONE);
mat.BlendOperation = EBO_ADD;
sphere = mgr->getGeometryCreator()->createSphereMesh(1, 16, 16);
box = sphere->getBoundingBox();
}
setScale(vector3df(radius));
m_radius = radius;
m_color[0] = r;
m_color[1] = g;
m_color[2] = b;
}
LightNode::~LightNode()
{
}
void LightNode::render()
{
PointLightProvider * const cb = (PointLightProvider *) irr_driver->getCallback(ES_POINTLIGHT);
cb->setColor(m_color[0], m_color[1], m_color[2]);
cb->setPosition(getPosition().X, getPosition().Y, getPosition().Z);
cb->setRadius(m_radius);
IVideoDriver * const drv = irr_driver->getVideoDriver();
drv->setTransform(ETS_WORLD, AbsoluteTransformation);
drv->setMaterial(mat);
drv->drawMeshBuffer(sphere->getMeshBuffer(0));
}
void LightNode::OnRegisterSceneNode()
{ // This node is only drawn manually.
}

64
src/graphics/light.hpp Normal file
View File

@ -0,0 +1,64 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Lauri Kasanen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_LIGHT_HPP
#define HEADER_LIGHT_HPP
#include <ISceneNode.h>
#include <utils/cpp2011.h>
using namespace irr;
namespace irr
{
namespace scene { class IMesh; }
}
// The actual node
class LightNode: public scene::ISceneNode
{
public:
LightNode(scene::ISceneManager* mgr, float radius, float r, float g, float b);
virtual ~LightNode();
virtual void render() OVERRIDE;
virtual const core::aabbox3d<f32>& getBoundingBox() const OVERRIDE
{
return box;
}
virtual void OnRegisterSceneNode() OVERRIDE;
virtual u32 getMaterialCount() const OVERRIDE { return 1; }
virtual video::SMaterial& getMaterial(u32 i) OVERRIDE { return mat; }
float getRadius() const { return m_radius; }
void getColor(float out[3]) const { memcpy(out, m_color, 3 * sizeof(float)); }
protected:
static video::SMaterial mat;
static core::aabbox3df box;
static scene::IMesh *sphere;
float m_radius;
float m_color[3];
};
#endif

View File

@ -1,6 +1,6 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Marianne Gagnon
// based on code Copyright (C) 2002-2010 Nikolaus Gebhardt
// Copyright (C) 2011-2013 Marianne Gagnon
// based on code Copyright 2002-2010 Nikolaus Gebhardt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -49,6 +49,7 @@ LODNode::LODNode(std::string group_name, scene::ISceneNode* parent,
drop();
m_forced_lod = -1;
m_last_tick = 0;
}
LODNode::~LODNode()
@ -81,6 +82,11 @@ int LODNode::getLevel()
if (dist < m_detail[n])
return n;
}
// If it's the shadow pass, and we would have otherwise hidden the item, show the min one
if (curr_cam->isOrthogonal())
return m_detail.size() - 1;
return -1;
} // getLevel
@ -139,9 +145,12 @@ void LODNode::OnRegisterSceneNode()
shown = true;
}
const u32 now = irr_driver->getDevice()->getTimer()->getTime();
// support an optional, mostly hard-coded fade-in/out effect for objects with a single level
if (m_nodes.size() == 1 && (m_nodes[0]->getType() == scene::ESNT_MESH ||
m_nodes[0]->getType() == scene::ESNT_ANIMATED_MESH))
m_nodes[0]->getType() == scene::ESNT_ANIMATED_MESH) &&
now > m_last_tick)
{
if (m_previous_visibility == WAS_HIDDEN && shown)
{
@ -237,6 +246,7 @@ void LODNode::OnRegisterSceneNode()
}
m_previous_visibility = (shown ? WAS_SHOWN : WAS_HIDDEN);
m_last_tick = now;
// If this node has children other than the LOD nodes, draw them
core::list<ISceneNode*>::Iterator it;
@ -279,7 +289,13 @@ void LODNode::add(int level, scene::ISceneNode* node, bool reparent)
if(UserConfigParams::m_hw_skinning_enabled && node->getType() == scene::ESNT_ANIMATED_MESH)
HardwareSkinning::prepareNode((scene::IAnimatedMeshSceneNode*)node);
if (node->getType() == scene::ESNT_ANIMATED_MESH)
((scene::IAnimatedMeshSceneNode *) node)->setReadOnlyMaterials(true);
if (node->getType() == scene::ESNT_MESH)
((scene::IMeshSceneNode *) node)->setReadOnlyMaterials(true);
node->drop();
node->updateAbsolutePosition();
irr_driver->applyObjectPassShader(node);
}

View File

@ -1,6 +1,6 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Marianne Gagnon
// based on code Copyright (C) 2002-2010 Nikolaus Gebhardt
// Copyright (C) 2011-2013 Marianne Gagnon
// based on code Copyright 2002-2010 Nikolaus Gebhardt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -71,6 +71,8 @@ private:
PreviousVisibility m_previous_visibility;
u32 m_last_tick;
public:
LODNode(std::string group_name, scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id=-1);

View File

@ -1,7 +1,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
// 2010 Steve Baker, Joerg Henrichs
// Copyright (C) 2010-2013 Steve Baker, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -27,8 +27,10 @@
#include "config/user_config.hpp"
#include "config/stk_config.hpp"
#include "guiengine/engine.hpp"
#include "graphics/callbacks.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "graphics/shaders.hpp"
#include "io/file_manager.hpp"
#include "io/xml_node.hpp"
#include "utils/string_utils.hpp"
@ -36,7 +38,6 @@
#include "tracks/track.hpp"
#include "utils/log.hpp"
#include <IGPUProgrammingServices.h>
#include <IMaterialRendererServices.h>
#include <ISceneNode.h>
#include <IShaderConstantSetCallBack.h>
@ -46,351 +47,6 @@ using namespace irr::video;
const unsigned int UCLAMP = 1;
const unsigned int VCLAMP = 2;
//-----------------------------------------------------------------------------
class NormalMapProvider : public video::IShaderConstantSetCallBack
{
bool m_with_lightmap;
public:
LEAK_CHECK()
NormalMapProvider(bool withLightmap)
{
m_with_lightmap = withLightmap;
}
virtual void OnSetConstants(
irr::video::IMaterialRendererServices *services,
s32 userData)
{
s32 decaltex = 0;
services->setPixelShaderConstant("DecalTex", &decaltex, 1);
s32 bumptex = 1;
services->setPixelShaderConstant("BumpTex", &bumptex, 1);
s32 lightmapTex = (m_with_lightmap ? 2 : 0);
services->setPixelShaderConstant("LightMapTex", &lightmapTex, 1);
s32 hasLightMap = (m_with_lightmap ? 1 : 0);
services->setPixelShaderConstant("HasLightMap", &hasLightMap, 1);
// We could calculate light direction as coming from the sun (then we'd need to
// transform it into camera space). But I find that pretending light
// comes from the camera gives good results
const float lightdir[] = {0.1852f, -0.1852f, -0.9259f};
services->setVertexShaderConstant("lightdir", lightdir, 3);
}
};
//-----------------------------------------------------------------------------
class WaterShaderProvider : public video::IShaderConstantSetCallBack
{
float m_dx_1, m_dy_1, m_dx_2, m_dy_2;
float m_water_shader_speed_1;
float m_water_shader_speed_2;
bool m_fog;
public:
LEAK_CHECK()
void enableFog(bool enable)
{
m_fog = enable;
}
WaterShaderProvider(float water_shader_speed_1,
float water_shader_speed_2)
{
m_dx_1 = 0.0f;
m_dy_1 = 0.0f;
m_dx_2 = 0.0f;
m_dy_2 = 0.0f;
m_water_shader_speed_1 = water_shader_speed_1/100.0f;
m_water_shader_speed_2 = water_shader_speed_2/100.0f;
m_fog = false;
}
virtual void OnSetConstants(
irr::video::IMaterialRendererServices *services,
s32 userData)
{
m_dx_1 += GUIEngine::getLatestDt()*m_water_shader_speed_1;
m_dy_1 += GUIEngine::getLatestDt()*m_water_shader_speed_1;
m_dx_2 += GUIEngine::getLatestDt()*m_water_shader_speed_2;
m_dy_2 -= GUIEngine::getLatestDt()*m_water_shader_speed_2;
if (m_dx_1 > 1.0f) m_dx_1 -= 1.0f;
if (m_dy_1 > 1.0f) m_dy_1 -= 1.0f;
if (m_dx_2 > 1.0f) m_dx_2 -= 1.0f;
if (m_dy_2 < 0.0f) m_dy_2 += 1.0f;
s32 decaltex = 0;
services->setPixelShaderConstant("DecalTex", &decaltex, 1);
s32 bumptex = 1;
services->setPixelShaderConstant("BumpTex1", &bumptex, 1);
bumptex = 2;
services->setPixelShaderConstant("BumpTex2", &bumptex, 1);
// We could calculate light direction as coming from the sun (then we'd need to
// transform it into camera space). But I find that pretending light
// comes from the camera gives good results
const float lightdir[] = {-0.315f, 0.91f, -0.3f};
services->setVertexShaderConstant("lightdir", lightdir, 3);
services->setVertexShaderConstant("delta1", &m_dx_1, 2);
services->setVertexShaderConstant("delta2", &m_dx_2, 2);
if (m_fog)
{
Track* t = World::getWorld()->getTrack();
float fogStart = t->getFogStart();
services->setPixelShaderConstant("fogFrom", &fogStart, 1);
float fogEnd = t->getFogEnd();
services->setPixelShaderConstant("fogTo", &fogEnd, 1);
video::SColor fogColor = t->getFogColor();
float fogColorVec[] = {fogColor.getRed()/255.0f,
fogColor.getGreen()/255.0f,
fogColor.getBlue()/255.0f, 1.0f};
services->setVertexShaderConstant("fogColor", fogColorVec, 4);
}
}
};
//-----------------------------------------------------------------------------
// FIXME: refactor this hack to get per-instance properties, and apply the
// clean fix to all shaders why we're at it......
std::map<int, float> grass_shaders_times;
int grass_shaders_times_index = 0;
class GrassShaderProvider : public video::IShaderConstantSetCallBack
{
bool m_fog;
float m_angle;
float m_amplitude;
float m_speed;
public:
LEAK_CHECK()
GrassShaderProvider(float amplitude, float speed)
{
m_fog = false;
m_angle = 0.0f;
m_amplitude = amplitude;
m_speed = speed;
}
void enableFog(bool enable)
{
m_fog = enable;
}
void update(float dt)
{
m_angle += GUIEngine::getLatestDt()*m_speed;
if (m_angle > M_PI*2) m_angle -= M_PI*2;
}
virtual void OnSetConstants(irr::video::IMaterialRendererServices *services,
s32 userData)
{
grass_shaders_times[userData] += GUIEngine::getLatestDt()*m_speed;
if (grass_shaders_times[userData] > M_PI*2) grass_shaders_times[userData] -= M_PI*2;
services->setVertexShaderConstant("angle", &grass_shaders_times[userData], 1);
int fog = (m_fog ? 1 : 0);
services->setVertexShaderConstant("fog", &fog, 1);
s32 tex = 0;
services->setVertexShaderConstant("tex", &tex, 1);
services->setVertexShaderConstant("amplitude", &m_amplitude, 1);
if (m_fog)
{
Track* t = World::getWorld()->getTrack();
float fogStart = t->getFogStart();
services->setPixelShaderConstant("fogFrom", &fogStart, 1);
float fogEnd = t->getFogEnd();
services->setPixelShaderConstant("fogTo", &fogEnd, 1);
video::SColor fogColor = t->getFogColor();
float fogColorVec[] = {fogColor.getRed()/255.0f,
fogColor.getGreen()/255.0f,
fogColor.getBlue()/255.0f, 1.0f};
services->setVertexShaderConstant("fogColor", fogColorVec, 4);
}
}
};
//-----------------------------------------------------------------------------
#if 0
#pragma mark -
#endif
class SplattingProvider : public video::IShaderConstantSetCallBack
{
core::vector3df m_light_direction;
bool m_light_dir_calculated;
bool m_lightmap;
public:
LEAK_CHECK()
SplattingProvider(bool lightmap)
{
m_light_dir_calculated = false;
m_lightmap = lightmap;
}
virtual void OnSetConstants(
irr::video::IMaterialRendererServices *services,
s32 userData)
{
if (!m_light_dir_calculated)
{
m_light_dir_calculated = true;
m_light_direction = -World::getWorld()->getTrack()->getSunRotation().rotationToDirection();
}
s32 tex_layout = 1;
services->setPixelShaderConstant("tex_layout", &tex_layout, 1);
s32 tex_detail0 = 2;
services->setPixelShaderConstant("tex_detail0", &tex_detail0, 1);
s32 tex_detail1 = 3;
services->setPixelShaderConstant("tex_detail1", &tex_detail1, 1);
s32 tex_detail2 = 4;
services->setPixelShaderConstant("tex_detail2", &tex_detail2, 1);
s32 tex_detail3 = 5;
services->setPixelShaderConstant("tex_detail3", &tex_detail3, 1);
if (m_lightmap)
{
s32 tex_lightmap = 6;
services->setPixelShaderConstant("tex_lightmap", &tex_lightmap, 1);
}
services->setVertexShaderConstant("lightdir", &m_light_direction.X, 3);
}
};
//-----------------------------------------------------------------------------
#if 0
#pragma mark -
#endif
class SphereMapProvider: public video::IShaderConstantSetCallBack
{
core::vector3df m_light_direction;
public:
LEAK_CHECK()
SphereMapProvider()
{
m_light_direction = core::vector3df(-0.6f, -0.5f, -0.63f);
//m_light_direction = core::vector3df(-0.315f, 0.91f, -0.3f);
}
virtual void OnSetConstants(
irr::video::IMaterialRendererServices *services,
s32 userData)
{
s32 texture = 0;
services->setPixelShaderConstant("texture", &texture, 1);
services->setVertexShaderConstant("lightdir", &m_light_direction.X, 3);
}
};
//-----------------------------------------------------------------------------
#if 0
#pragma mark -
#endif
class BubbleEffectProvider : public video::IShaderConstantSetCallBack
{
irr::u32 initial_time;
float m_transparency;
bool m_is_visible;
public:
LEAK_CHECK()
BubbleEffectProvider()
{
initial_time = irr_driver->getDevice()->getTimer()->getRealTime();
m_transparency = 1.0f;
m_is_visible = true;
}
virtual void OnSetConstants(
irr::video::IMaterialRendererServices *services,
s32 userData)
{
if (m_is_visible && m_transparency < 1.0f)
{
m_transparency += GUIEngine::getLatestDt()*0.3f;
if (m_transparency > 1.0f) m_transparency = 1.0f;
}
else if (!m_is_visible && m_transparency > 0.0f)
{
m_transparency -= GUIEngine::getLatestDt()*0.3f;
if (m_transparency < 0.0f) m_transparency = 0.0f;
}
float time = (irr_driver->getDevice()->getTimer()->getRealTime() - initial_time) / 1000.0f;
services->setVertexShaderConstant("time", &time, 1);
services->setVertexShaderConstant("transparency", &m_transparency, 1);
}
void onMadeVisible()
{
m_is_visible = true;
}
void onHidden()
{
m_is_visible = false;
m_transparency = 0.0f;
}
void isInitiallyHidden()
{
m_is_visible = false;
m_transparency = 0.0f;
}
};
#if 0
#pragma mark -
#endif
//-----------------------------------------------------------------------------
/** Create a new material using the parameters specified in the xml file.
* \param node Node containing the parameters for this material.
@ -430,7 +86,8 @@ Material::Material(const XMLNode *node, int index, bool deprecated)
else if (s=="" || s=="none")
m_adjust_image = ADJ_NONE;
else
printf("Incorrect adjust-image specification: '%s' - ignored.\n",
Log::warn("material",
"Incorrect adjust-image specification: '%s' - ignored.",
s.c_str());
node->get("alpha", &m_alpha_blending );
node->get("light", &m_lighting );
@ -458,9 +115,14 @@ Material::Material(const XMLNode *node, int index, bool deprecated)
{
m_collision_reaction = PUSH_BACK;
}
else if (creaction == "push-soccer")
{
m_collision_reaction = PUSH_SOCCER_BALL;
}
else if (creaction.size() > 0)
{
fprintf(stderr, "[Material] WARNING: Unknown collision reaction '%s'\n", creaction.c_str());
Log::warn("Material","Unknown collision reaction '%s'",
creaction.c_str());
}
node->get("below-surface", &m_below_surface );
@ -562,15 +224,18 @@ Material::Material(const XMLNode *node, int index, bool deprecated)
node->get("splatting-texture-2", &m_splatting_texture_2);
node->get("splatting-texture-3", &m_splatting_texture_3);
node->get("splatting-texture-4", &m_splatting_texture_4);
node->get("splatting-lightmap", &m_splatting_lightmap);
}
else if (s == "caustics")
{
m_graphical_effect = GE_CAUSTICS;
}
else if (s == "none")
{
}
else if (s != "")
{
fprintf(stderr,
"Invalid graphical effect specification: '%s' - ignored.\n",
Log::warn("material",
"Invalid graphical effect specification: '%s' - ignored.",
s.c_str());
}
else
@ -591,7 +256,8 @@ Material::Material(const XMLNode *node, int index, bool deprecated)
}
else
{
fprintf(stderr, "[Material] WARNING: could not find normal map image in materials.xml\n");
Log::warn("material",
"Could not find normal map image in materials.xml");
}
node->get("normal-light-map", &m_normal_map_shader_lightmap);
@ -614,8 +280,7 @@ Material::Material(const XMLNode *node, int index, bool deprecated)
else if (s == "additive") m_add = true;
else if (s == "coverage") m_alpha_to_coverage = true;
else if (s != "none")
fprintf(stderr,
"[Material] WARNING: Unknown compositing mode '%s'\n",
Log::warn("material", "Unknown compositing mode '%s'",
s.c_str());
}
@ -661,9 +326,8 @@ Material::Material(const XMLNode *node, int index, bool deprecated)
}
else
{
fprintf(stderr,
"[Material] WARNING: unknown node type '%s' for texture "
"'%s' - ignored.\n",
Log::warn("material", "Unknown node type '%s' for texture "
"'%s' - ignored.",
child_node->getName().c_str(), m_texname.c_str());
}
@ -735,8 +399,6 @@ void Material::init(unsigned int index)
m_water_splash = false;
m_is_jump_texture = false;
m_shaders.resize(SHADER_COUNT, NULL);
for (int n=0; n<EMIT_KINDS_COUNT; n++)
{
m_particles_effects[n] = NULL;
@ -752,14 +414,16 @@ void Material::install(bool is_full_path, bool complain_if_not_found)
if (complain_if_not_found && full_path.size() == 0)
{
fprintf(stderr, "[Material] WARNING, cannot find texture '%s'\n", m_texname.c_str());
Log::error("material", "Cannot find texture '%s'.", m_texname.c_str());
m_texture = NULL;
}
else
{
m_texture = irr_driver->getTexture(full_path,
isPreMul(),
isPreDiv(),
complain_if_not_found);
}
if (m_texture == NULL) return;
@ -776,9 +440,8 @@ void Material::install(bool is_full_path, bool complain_if_not_found)
}
else
{
fprintf(stderr, "Applying mask failed for '%s'!\n",
Log::warn("material", "Applying mask failed for '%s'!",
m_texname.c_str());
return;
}
}
m_texture->grab();
@ -794,20 +457,6 @@ Material::~Material()
irr_driver->removeTexture(m_texture);
}
for (unsigned int n=0; n<m_shaders.size(); n++)
{
if (m_shaders[n])
{
m_shaders[n]->drop();
}
}
for (std::map<scene::IMeshBuffer*, BubbleEffectProvider*>::iterator it = m_bubble_provider.begin();
it != m_bubble_provider.end(); it++)
{
it->second->drop();
}
// If a special sfx is installed (that isn't part of stk itself), the
// entry needs to be removed from the sfx_manager's mapping, since other
// tracks might use the same name.
@ -830,8 +479,8 @@ void Material::initCustomSFX(const XMLNode *sfx)
if (filename.empty())
{
fprintf(stderr, "[Material] WARNING: sfx node has no 'filename' "
"attribute, sound effect will be ignored\n");
Log::warn("material", "Sfx node has no 'filename' "
"attribute, sound effect will be ignored.");
return;
}
@ -909,9 +558,9 @@ void Material::initParticlesEffect(const XMLNode *node)
if (count == 0)
{
fprintf(stderr, "[Material::initParticlesEffect] WARNING: Particles "
Log::warn("material", "initParticlesEffect: Particles "
"'%s' for material '%s' are declared but not used "
"(no emission condition set)\n",
"(no emission condition set).",
base.c_str(), m_texname.c_str());
}
@ -927,8 +576,8 @@ void Material::initParticlesEffect(const XMLNode *node)
}
else
{
fprintf(stderr, "[Material::initParticlesEffect] WARNING: Unknown "
"condition '%s' for material '%s'\n",
Log::warn("material", "initParticlesEffect: Unknown "
"condition '%s' for material '%s'",
conditions[c].c_str(), m_texname.c_str());
}
}
@ -938,8 +587,9 @@ void Material::initParticlesEffect(const XMLNode *node)
/** Adjusts the pitch of the given sfx depending on the given speed.
* \param sfx The sound effect to adjust.
* \param speed The speed of the kart.
* \param should_be_paused Pause for other reasons, i.e. kart is rescued.
*/
void Material::setSFXSpeed(SFXBase *sfx, float speed) const
void Material::setSFXSpeed(SFXBase *sfx, float speed, bool should_be_paused) const
{
// Still make a sound when driving backwards on the material.
if (speed < 0) speed = -speed;
@ -947,14 +597,14 @@ void Material::setSFXSpeed(SFXBase *sfx, float speed) const
// If we paused it due to too low speed earlier, we can continue now.
if (sfx->getStatus() == SFXManager::SFX_PAUSED)
{
if (speed<m_sfx_min_speed) return;
if (speed<m_sfx_min_speed || should_be_paused == 1) return;
// TODO: Do we first need to stop the sound completely so it
// starts over?
sfx->play();
}
else if (sfx->getStatus() == SFXManager::SFX_PLAYING)
{
if (speed<m_sfx_min_speed)
if (speed<m_sfx_min_speed || should_be_paused == 1)
{
// Pausing it to differentiate with sounds that ended etc
sfx->pause();
@ -981,9 +631,12 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
// materials.xml, if you want to set flags for all surfaces, see
// 'MaterialManager::setAllMaterialFlags'
if (m_deprecated || (m->getTexture(0) != NULL && ((core::stringc)m->getTexture(0)->getName()).find("deprecated") != -1))
if (m_deprecated ||
(m->getTexture(0) != NULL &&
((core::stringc)m->getTexture(0)->getName()).find("deprecated") != -1))
{
fprintf(stderr, "WARNING: track uses deprecated texture <%s>\n", m_texname.c_str());
Log::warn("material", "Track uses deprecated texture '%s'\n",
m_texname.c_str());
}
@ -1022,24 +675,9 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
}
if (m_smooth_reflection_shader)
{
IVideoDriver* video_driver = irr_driver->getVideoDriver();
if (UserConfigParams::m_pixel_shaders &&
irr_driver->isGLSL())
if (irr_driver->isGLSL())
{
if (m_shaders[SHADER_SPHERE_MAP] == NULL)
{
m_shaders[SHADER_SPHERE_MAP] = new SphereMapProvider();
}
// Material and shaders
IGPUProgrammingServices* gpu =
irr_driver->getVideoDriver()->getGPUProgrammingServices();
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir() + "spheremap.vert").c_str(),
"main", video::EVST_VS_2_0,
(file_manager->getShaderDir() + "spheremap.frag").c_str(),
"main", video::EPST_PS_2_0,
m_shaders[SHADER_SPHERE_MAP], video::EMT_SOLID_2_LAYER );
m->MaterialType = (E_MATERIAL_TYPE)material_type;
m->MaterialType = irr_driver->getShader(ES_SPHERE_MAP);
}
else
{
@ -1058,6 +696,12 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
}
}
if (m_graphical_effect == GE_SPHERE_MAP)
{
if (irr_driver->isGLSL())
{
m->MaterialType = irr_driver->getShader(ES_SPHERE_MAP);
}
else
{
m->MaterialType = video::EMT_SPHERE_MAP;
@ -1072,7 +716,8 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
modes++;
}
}
#if !LIGHTMAP_VISUALISATION
}
if (m_lightmap)
{
m->MaterialType = video::EMT_LIGHTMAP;
@ -1083,7 +728,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
m->MaterialType = video::EMT_LIGHTMAP_ADD;
modes++;
}
#endif
if (m_add)
{
//m->MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
@ -1102,8 +747,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
if (m_graphical_effect == GE_NORMAL_MAP)
{
IVideoDriver* video_driver = irr_driver->getVideoDriver();
if (UserConfigParams::m_pixel_shaders &&
irr_driver->isGLSL())
if (irr_driver->isGLSL())
{
ITexture* tex = irr_driver->getTexture(m_normal_map_tex);
if (m_is_heightmap)
@ -1121,37 +765,9 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
with_lightmap = true;
}
if (with_lightmap)
{
if (m_shaders[SHADER_NORMAL_MAP_WITH_LIGHTMAP] == NULL)
{
m_shaders[SHADER_NORMAL_MAP_WITH_LIGHTMAP] =
new NormalMapProvider(true);
}
}
else
{
if (m_shaders[SHADER_NORMAL_MAP] == NULL)
{
m_shaders[SHADER_NORMAL_MAP] = new NormalMapProvider(false);
}
}
const char* vertex_shader = "normalmap.vert";
const char* pixel_shader = "normalmap.frag";
// Material and shaders
IGPUProgrammingServices* gpu =
video_driver->getGPUProgrammingServices();
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir() + vertex_shader).c_str(),
"main", video::EVST_VS_2_0,
(file_manager->getShaderDir() + pixel_shader).c_str(),
"main", video::EPST_PS_2_0,
m_shaders[with_lightmap ? SHADER_NORMAL_MAP_WITH_LIGHTMAP
: SHADER_NORMAL_MAP],
video::EMT_SOLID_2_LAYER );
m->MaterialType = (E_MATERIAL_TYPE)material_type;
m->MaterialType = irr_driver->getShader(
with_lightmap ? ES_NORMAL_MAP_LIGHTMAP : ES_NORMAL_MAP );
m->Lighting = false;
m->ZWriteEnable = true;
@ -1201,64 +817,20 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
}
m->setTexture(5, tex);
if (m_splatting_lightmap.size() > 0)
{
tex = irr_driver->getTexture(m_splatting_lightmap);
}
m->setTexture(6, tex);
if (m_splatting_lightmap.size() > 0)
{
if (m_shaders[SHADER_SPLATTING_LIGHTMAP] == NULL)
{
m_shaders[SHADER_SPLATTING_LIGHTMAP] =
new SplattingProvider(true);
}
}
else
{
if (m_shaders[SHADER_SPLATTING] == NULL)
{
m_shaders[SHADER_SPLATTING] = new SplattingProvider(false);
}
}
// Material and shaders
IGPUProgrammingServices* gpu =
irr_driver->getVideoDriver()->getGPUProgrammingServices();
if (m_splatting_lightmap.size() > 0)
{
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir()
+ "splatting_lightmap.vert").c_str(),
"main",video::EVST_VS_2_0,
(file_manager->getShaderDir()
+ "splatting_lightmap.frag").c_str(),
"main",video::EPST_PS_2_0,
m_shaders[SHADER_SPLATTING_LIGHTMAP],
video::EMT_SOLID );
m->MaterialType = (E_MATERIAL_TYPE)material_type;
}
else
{
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir()
+ "splatting.vert").c_str(),
"main",video::EVST_VS_2_0,
(file_manager->getShaderDir()
+ "splatting.frag").c_str(),
"main",video::EPST_PS_2_0,
m_shaders[SHADER_SPLATTING], video::EMT_SOLID );
m->MaterialType = (E_MATERIAL_TYPE)material_type;
}
m->MaterialType = irr_driver->getShader(ES_SPLATTING);
}
else
{
m->MaterialType = video::EMT_SOLID;
}
}
if (m_graphical_effect == GE_CAUSTICS && irr_driver->isGLSL())
{
m->MaterialType = irr_driver->getShader(ES_CAUSTICS);
m->setTexture(1, irr_driver->getTexture((file_manager->getTextureDir() + "caustics.png").c_str()));
}
// Modify lightmap materials so that vertex colors are taken into account.
@ -1275,26 +847,14 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
if (m_graphical_effect == GE_BUBBLE && mb != NULL)
{
IVideoDriver* video_driver = irr_driver->getVideoDriver();
if (UserConfigParams::m_pixel_shaders &&
irr_driver->isGLSL())
if (irr_driver->isGLSL())
{
if (m_bubble_provider.find(mb) == m_bubble_provider.end())
{
m_bubble_provider[mb] = new BubbleEffectProvider();
}
BubbleEffectProvider * bubble = (BubbleEffectProvider *)
irr_driver->getCallback(ES_BUBBLES);
bubble->addBubble(mb);
// Material and shaders
IGPUProgrammingServices* gpu = video_driver->getGPUProgrammingServices();
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir() + "bubble.vert").c_str(),
"main", video::EVST_VS_2_0,
(file_manager->getShaderDir() + "bubble.frag").c_str(),
"main", video::EPST_PS_2_0,
m_bubble_provider[mb],
(m_alpha_blending ? video::EMT_TRANSPARENT_ALPHA_CHANNEL
: video::EMT_SOLID) );
m->MaterialType = (E_MATERIAL_TYPE)material_type;
m->MaterialType = irr_driver->getShader(ES_BUBBLES);
m->BlendOperation = video::EBO_ADD;
// alpha blending and bubble shading can work together so when both are enabled
// don't increment the 'modes' counter to not get the 'too many modes' warning
@ -1308,72 +868,40 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
if (m_graphical_effect == GE_WATER_SHADER)
{
IVideoDriver* video_driver = irr_driver->getVideoDriver();
if (UserConfigParams::m_pixel_shaders &&
irr_driver->isGLSL())
if (irr_driver->isGLSL())
{
if (m_shaders[SHADER_WATER] == NULL)
{
m_shaders[SHADER_WATER] =
new WaterShaderProvider(m_water_shader_speed_1,
m_water_shader_speed_2);
}
m->setTexture(1, irr_driver->getTexture(file_manager->getTextureFile("waternormals.jpg")));
m->setTexture(2, irr_driver->getTexture(file_manager->getTextureFile("waternormals2.jpg")));
bool fog = World::getWorld()->getTrack()->isFogEnabled();
const char* vertex_shader = (fog ? "water_fog.vert" : "water.vert");
const char* pixel_shader = (fog ? "water_fog.frag" : "water.frag");
((WaterShaderProvider *) irr_driver->getCallback(ES_WATER))->
setSpeed(m_water_shader_speed_1/100.0f, m_water_shader_speed_2/100.0f);
((WaterShaderProvider*)m_shaders[SHADER_WATER])->enableFog(fog);
// Material and shaders
IGPUProgrammingServices* gpu =
irr_driver->getVideoDriver()->getGPUProgrammingServices();
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir() + vertex_shader).c_str(),
"main", video::EVST_VS_2_0,
(file_manager->getShaderDir() + pixel_shader ).c_str(),
"main", video::EPST_PS_2_0,
m_shaders[SHADER_WATER],
video::EMT_TRANSPARENT_ALPHA_CHANNEL);
m->MaterialType = (E_MATERIAL_TYPE)material_type;
m->MaterialType = irr_driver->getShader(ES_WATER);
}
modes++;
}
if (m_graphical_effect == GE_GRASS)
{
IVideoDriver* video_driver = irr_driver->getVideoDriver();
if (UserConfigParams::m_pixel_shaders &&
if (UserConfigParams::m_weather_effects &&
irr_driver->isGLSL())
{
if (m_shaders[SHADER_GRASS] == NULL)
{
m_shaders[SHADER_GRASS] =
new GrassShaderProvider(m_grass_amplitude, m_grass_speed);
}
bool fog = World::getWorld()->getTrack()->isFogEnabled();
((GrassShaderProvider*)m_shaders[SHADER_GRASS])->enableFog(fog);
grass_shaders_times[grass_shaders_times_index] = (rand() % 500)/500.0f * M_PI * 2.0f;
// Only one grass speed & amplitude per map for now
((GrassShaderProvider *) irr_driver->getCallback(ES_GRASS))->
setSpeed(m_grass_speed);
((GrassShaderProvider *) irr_driver->getCallback(ES_GRASS))->
setAmplitude(m_grass_amplitude);
// Material and shaders
IGPUProgrammingServices* gpu =
irr_driver->getVideoDriver()->getGPUProgrammingServices();
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir() + "grass.vert").c_str(),
"main", video::EVST_VS_2_0,
(file_manager->getShaderDir() + "grass.frag").c_str(),
"main", video::EPST_PS_2_0,
m_shaders[SHADER_GRASS],
video::EMT_TRANSPARENT_ALPHA_CHANNEL,
grass_shaders_times_index);
m->MaterialType = (E_MATERIAL_TYPE)material_type;
if (m_alpha_testing)
{
m->MaterialType = irr_driver->getShader(ES_GRASS_REF);
}
else {
m->MaterialType = irr_driver->getShader(ES_GRASS);
m->BlendOperation = video::EBO_ADD;
}
grass_shaders_times_index++;
}
}
@ -1468,6 +996,10 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
void Material::adjustForFog(scene::ISceneNode* parent, video::SMaterial *m,
bool use_fog) const
{
// The new pipeline does fog as a post-process effect.
if (irr_driver->isGLSL())
return;
m->setFlag(video::EMF_FOG_ENABLE, m_fog && use_fog);
if (parent != NULL)
@ -1481,10 +1013,13 @@ void Material::adjustForFog(scene::ISceneNode* parent, video::SMaterial *m,
/** Callback from LOD nodes to create some effects */
void Material::onMadeVisible(scene::IMeshBuffer* who)
{
if (m_bubble_provider.find(who) != m_bubble_provider.end())
{
m_bubble_provider[who]->onMadeVisible();
}
if (!irr_driver->isGLSL()) return;
BubbleEffectProvider * bubble = (BubbleEffectProvider *)
irr_driver->getCallback(ES_BUBBLES);
if (bubble != NULL)
bubble->onMadeVisible(who);
}
//-----------------------------------------------------------------------------
@ -1492,20 +1027,24 @@ void Material::onMadeVisible(scene::IMeshBuffer* who)
/** Callback from LOD nodes to create some effects */
void Material::onHidden(scene::IMeshBuffer* who)
{
if (m_bubble_provider.find(who) != m_bubble_provider.end())
{
m_bubble_provider[who]->onHidden();
}
if (!irr_driver->isGLSL()) return;
BubbleEffectProvider * bubble = (BubbleEffectProvider *)
irr_driver->getCallback(ES_BUBBLES);
if (bubble != NULL)
bubble->onHidden(who);
}
//-----------------------------------------------------------------------------
void Material::isInitiallyHidden(scene::IMeshBuffer* who)
{
if (m_bubble_provider.find(who) != m_bubble_provider.end())
{
m_bubble_provider[who]->isInitiallyHidden();
}
if (!irr_driver->isGLSL()) return;
BubbleEffectProvider * bubble = (BubbleEffectProvider *)
irr_driver->getCallback(ES_BUBBLES);
if (bubble != NULL)
bubble->isInitiallyHidden(who);
}
//-----------------------------------------------------------------------------

View File

@ -1,6 +1,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2010-2013 Steve Baker, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -27,8 +28,6 @@
#include <IShaderConstantSetCallBack.h>
#define LIGHTMAP_VISUALISATION 0
namespace irr
{
@ -41,10 +40,6 @@ class XMLNode;
class SFXBase;
class ParticleKind;
class NormalMapProvider;
class SplattingProvider;
class BubbleEffectProvider;
/**
* \ingroup graphics
*/
@ -59,7 +54,8 @@ public:
GE_WATER_SHADER,
GE_SPHERE_MAP,
GE_SPLATTING,
GE_NORMAL_MAP};
GE_NORMAL_MAP,
GE_CAUSTICS};
enum ParticleConditions
{
@ -73,23 +69,12 @@ public:
{
NORMAL,
RESCUE,
PUSH_BACK
PUSH_BACK,
PUSH_SOCCER_BALL
};
private:
enum Shaders
{
SHADER_NORMAL_MAP,
SHADER_NORMAL_MAP_WITH_LIGHTMAP,
SHADER_SPLATTING,
SHADER_WATER,
SHADER_SPHERE_MAP,
SHADER_SPLATTING_LIGHTMAP,
SHADER_GRASS,
SHADER_COUNT
};
video::ITexture *m_texture;
unsigned int m_index;
std::string m_texname;
@ -232,13 +217,6 @@ private:
/** If m_splatting is true, indicates the fourth splatting texture */
std::string m_splatting_texture_4;
std::string m_splatting_lightmap;
std::vector<irr::video::IShaderConstantSetCallBack*> m_shaders;
/** Only used if bubble effect is enabled */
std::map<scene::IMeshBuffer*, BubbleEffectProvider*> m_bubble_provider;
bool m_deprecated;
void init (unsigned int index);
@ -253,7 +231,7 @@ public:
bool complain_if_not_found=true);
~Material ();
void setSFXSpeed(SFXBase *sfx, float speed) const;
void setSFXSpeed(SFXBase *sfx, float speed, bool should_be_paused) const;
void setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* mb);
void adjustForFog(scene::ISceneNode* parent, video::SMaterial *m, bool use_fog) const;

View File

@ -1,6 +1,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2004-2013 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2010-2013 Steve Baker, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -59,10 +60,6 @@ MaterialManager::~MaterialManager()
m_materials.clear();
} // ~MaterialManager
#if LIGHTMAP_VISUALISATION
std::set<scene::IMeshBuffer*> g_processed;
#endif
//-----------------------------------------------------------------------------
Material* MaterialManager::getMaterialFor(video::ITexture* t,

View File

@ -1,6 +1,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2004-2013 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2010-2013 Steve Baker, Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
// Copyright (C) 2009-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009 Joerg Henrichs
// Copyright (C) 2009-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -0,0 +1,200 @@
#ifndef AREAMAP_H
#define AREAMAP_H
static const unsigned char AreaMap33[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa5,
0x08, 0x04, 0x00, 0x00, 0x00, 0x97, 0x22, 0xf5, 0x51, 0x00, 0x00, 0x00,
0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
0x00, 0x02, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x87, 0x8f, 0xcc, 0xbf,
0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13,
0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00,
0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xdb, 0x06, 0x07, 0x09, 0x17, 0x12,
0x5f, 0x51, 0x45, 0x04, 0x00, 0x00, 0x08, 0x87, 0x49, 0x44, 0x41, 0x54,
0x78, 0xda, 0xed, 0x5d, 0x4b, 0x6e, 0xdb, 0x48, 0x14, 0x2c, 0x89, 0x2f,
0x4e, 0xe2, 0x09, 0x30, 0x9b, 0x38, 0x5b, 0xf9, 0x24, 0x73, 0xbb, 0xb9,
0x49, 0x6e, 0x32, 0x67, 0x98, 0x7d, 0xbc, 0xf2, 0xc2, 0x18, 0x78, 0x31,
0x81, 0xc6, 0xa6, 0xc4, 0xd7, 0xc3, 0x8f, 0x1a, 0x0d, 0x9a, 0x92, 0x5b,
0x64, 0x91, 0x7a, 0x1d, 0xa1, 0xab, 0x41, 0x28, 0x41, 0x80, 0x42, 0xd5,
0x63, 0x93, 0x32, 0x9c, 0x42, 0x35, 0xc0, 0x63, 0x03, 0x73, 0x6c, 0x60,
0x8f, 0x35, 0x78, 0xdc, 0xe3, 0x16, 0x2c, 0x78, 0x09, 0x57, 0x31, 0xca,
0x6f, 0xb8, 0xc3, 0x0d, 0x68, 0xd8, 0x4b, 0xb0, 0x1f, 0xe5, 0x2d, 0xbe,
0xe2, 0x77, 0x08, 0x48, 0xd8, 0x4b, 0xb0, 0x1f, 0xe5, 0x47, 0x7c, 0xa9,
0x7d, 0xfc, 0x86, 0x02, 0x06, 0x48, 0x46, 0x02, 0x64, 0x16, 0x8e, 0xcf,
0xb5, 0x8b, 0x17, 0x54, 0xd8, 0x42, 0x41, 0xc0, 0x5a, 0x82, 0xfd, 0x28,
0x0b, 0x7c, 0xac, 0x9d, 0xdc, 0x62, 0x07, 0xc5, 0x0b, 0xe1, 0xc4, 0x5c,
0x82, 0xfd, 0x28, 0xd7, 0xb8, 0xa9, 0x9d, 0x7c, 0xc2, 0x2b, 0xf6, 0x70,
0x78, 0x25, 0x9c, 0x98, 0x4b, 0xb0, 0x1f, 0xa5, 0x1c, 0x9c, 0xec, 0xa1,
0x50, 0x94, 0x70, 0x20, 0x60, 0x27, 0xc1, 0x7e, 0x94, 0x2b, 0x14, 0xf8,
0x50, 0xaf, 0xda, 0x4b, 0xeb, 0x04, 0x84, 0x13, 0x73, 0x09, 0xf6, 0xa3,
0x94, 0xd6, 0x47, 0x59, 0x3b, 0x51, 0x28, 0x1c, 0x76, 0x84, 0x13, 0x53,
0x09, 0xf6, 0xa3, 0x2c, 0xf0, 0xa1, 0xf5, 0xb2, 0xc7, 0xbe, 0xf5, 0xe1,
0xb0, 0x27, 0x9c, 0x98, 0x49, 0xb0, 0x1f, 0xe5, 0x1a, 0xd2, 0x38, 0xf1,
0x3e, 0x5a, 0x27, 0x20, 0x9c, 0x18, 0x4a, 0xb0, 0x1f, 0x65, 0xe7, 0x44,
0xda, 0x6d, 0x51, 0x1d, 0x9c, 0x38, 0x54, 0x84, 0x13, 0x13, 0x09, 0xf6,
0xa3, 0xf4, 0x4e, 0xe4, 0xe0, 0xc4, 0xfb, 0x00, 0xe1, 0xc4, 0x40, 0x82,
0xfd, 0x28, 0x81, 0x35, 0x8a, 0x6e, 0xb5, 0x3e, 0x2a, 0x54, 0x84, 0x13,
0x53, 0x09, 0xf6, 0xbb, 0xd2, 0x6f, 0x8a, 0xe0, 0x26, 0xf8, 0x70, 0xa8,
0xc0, 0x23, 0x7d, 0x09, 0x90, 0x79, 0x9c, 0xf4, 0x3c, 0x54, 0xa8, 0xda,
0x4f, 0x77, 0x58, 0x20, 0x9c, 0x18, 0x48, 0xb0, 0x1f, 0xa5, 0xf7, 0xb2,
0x46, 0xd8, 0x14, 0xda, 0xba, 0x00, 0xe1, 0xc4, 0x48, 0x82, 0xfd, 0x03,
0x1e, 0x9e, 0x30, 0x6d, 0x2f, 0x47, 0x6c, 0x8b, 0x5f, 0x4d, 0x02, 0x64,
0x36, 0x27, 0xc1, 0xc5, 0x3a, 0xf8, 0x68, 0x2e, 0x62, 0x5b, 0x18, 0x48,
0xb0, 0x1e, 0x25, 0x06, 0x9b, 0xa2, 0x7a, 0xe3, 0xc3, 0x2d, 0xe8, 0x84,
0x90, 0x90, 0xe6, 0xbb, 0xb2, 0xbf, 0x0a, 0x68, 0xbb, 0x0a, 0xb8, 0x76,
0x15, 0x40, 0xfb, 0xa9, 0x60, 0xc1, 0x4b, 0x48, 0xfb, 0x5d, 0x39, 0xd8,
0x14, 0x55, 0xf7, 0x19, 0x5e, 0x54, 0x07, 0x2f, 0x20, 0x9c, 0x18, 0x48,
0xb0, 0x7a, 0xc0, 0xfb, 0x4e, 0xb4, 0x59, 0xfe, 0x6f, 0xde, 0x05, 0xe1,
0x24, 0x79, 0x09, 0x32, 0xf3, 0x17, 0xa8, 0x77, 0x12, 0xf4, 0xf7, 0x9f,
0x2e, 0x47, 0x38, 0x31, 0x90, 0x60, 0xbd, 0x2b, 0x87, 0xab, 0xf0, 0x5e,
0x88, 0x6d, 0x91, 0xbc, 0x04, 0x99, 0xd7, 0xc5, 0x09, 0x2f, 0xae, 0xbd,
0xc2, 0x96, 0x70, 0x11, 0x27, 0x56, 0x12, 0xec, 0xbf, 0x76, 0x06, 0x4f,
0x58, 0x70, 0x13, 0x5e, 0x53, 0x7d, 0x17, 0x88, 0x38, 0xb1, 0x95, 0x60,
0xbf, 0x2b, 0x7b, 0x0e, 0x56, 0x6f, 0x36, 0x44, 0xe1, 0x5d, 0xb4, 0x9f,
0x8e, 0x70, 0x62, 0x20, 0xc1, 0xe0, 0x5d, 0x79, 0xf4, 0x09, 0x53, 0xac,
0xfb, 0xef, 0x7d, 0x62, 0x5b, 0x24, 0x2c, 0x41, 0xe6, 0x77, 0x32, 0xfc,
0x1a, 0xed, 0xd4, 0x7b, 0x3f, 0xde, 0x07, 0xe1, 0x24, 0x49, 0x09, 0x32,
0xf7, 0x4f, 0xc8, 0xde, 0x4b, 0xcf, 0x55, 0x70, 0xb1, 0x1e, 0xf8, 0x70,
0x70, 0xd7, 0x21, 0x61, 0x85, 0x0d, 0xee, 0xf1, 0x0d, 0xb7, 0xf8, 0x08,
0x41, 0x71, 0xb8, 0x9d, 0x61, 0x85, 0x37, 0x3a, 0xfc, 0xe7, 0xe0, 0x4f,
0x7f, 0x61, 0x45, 0x32, 0xfc, 0x09, 0x12, 0x9b, 0xcd, 0x03, 0xe9, 0x62,
0xf3, 0x9d, 0x65, 0x10, 0x3c, 0xe0, 0x09, 0x77, 0xf8, 0x8a, 0x2f, 0xf8,
0x5c, 0xd3, 0xdc, 0xb4, 0x44, 0x85, 0x27, 0xeb, 0x11, 0x22, 0x90, 0xf6,
0xc8, 0x57, 0xf8, 0x1b, 0x3f, 0x28, 0x06, 0x1a, 0xf7, 0x0f, 0x4f, 0x4f,
0x5b, 0xca, 0x05, 0xcf, 0x20, 0x00, 0xb6, 0x78, 0xc4, 0xb6, 0xcd, 0xd4,
0x75, 0x24, 0x1f, 0x5a, 0x1a, 0x69, 0x49, 0x8a, 0x37, 0x3f, 0x5d, 0xe0,
0x08, 0xe1, 0x37, 0xfc, 0xc0, 0x3f, 0x0c, 0xc3, 0x2c, 0x51, 0xd5, 0xed,
0xe3, 0x63, 0x49, 0x68, 0xe0, 0x19, 0x04, 0x0d, 0x4a, 0x3c, 0xd7, 0xd7,
0x0b, 0x6e, 0xf1, 0xa9, 0x26, 0xf9, 0xd0, 0xae, 0x8e, 0xa4, 0xe8, 0xd1,
0xd4, 0xd7, 0x60, 0x75, 0x39, 0xd1, 0x2d, 0xfe, 0x25, 0x18, 0x38, 0x78,
0x09, 0xe5, 0xf3, 0xf3, 0x7e, 0xb2, 0x06, 0x9e, 0x41, 0xd0, 0x61, 0x8f,
0x9f, 0xa8, 0xb0, 0xc3, 0x6b, 0x4d, 0x72, 0x53, 0x2f, 0x39, 0x90, 0x14,
0x07, 0x1a, 0xbf, 0x56, 0x43, 0xa2, 0x43, 0x4e, 0xb4, 0xc4, 0x7f, 0x93,
0x19, 0x58, 0x78, 0x09, 0xfb, 0x9f, 0x3f, 0xab, 0x89, 0x1a, 0x78, 0x06,
0x81, 0x47, 0x97, 0xf2, 0xdc, 0xd7, 0xeb, 0x23, 0xca, 0xf6, 0x7e, 0x88,
0x7f, 0x5f, 0xf4, 0x49, 0x06, 0xf7, 0xe5, 0x16, 0x3e, 0x27, 0xfa, 0x32,
0x8d, 0x61, 0xc6, 0xa8, 0x6a, 0xb5, 0xdd, 0xea, 0x24, 0x0d, 0x73, 0x30,
0x04, 0x68, 0xcd, 0xe4, 0xa0, 0x0d, 0x49, 0x4b, 0x25, 0x81, 0x24, 0xdc,
0x93, 0x01, 0xc9, 0xba, 0x97, 0x13, 0x2d, 0xa7, 0x30, 0xcc, 0x1a, 0x55,
0xd5, 0x97, 0x17, 0x9d, 0xa0, 0x81, 0x67, 0x90, 0x9e, 0x22, 0xc5, 0x2b,
0xb4, 0x59, 0x2d, 0x85, 0xbf, 0x1f, 0xd2, 0x12, 0x78, 0x8a, 0x21, 0x4d,
0x3f, 0x27, 0xba, 0x1b, 0xcf, 0x30, 0x73, 0x54, 0x55, 0x5f, 0x5f, 0x75,
0xb4, 0x06, 0x9e, 0x41, 0xd0, 0x87, 0xa2, 0x04, 0xd0, 0xd1, 0x54, 0x6d,
0xf8, 0xa6, 0x40, 0xd5, 0x11, 0x9c, 0x22, 0x19, 0xe4, 0x44, 0x77, 0x63,
0x19, 0x66, 0x8f, 0xaa, 0x6a, 0x59, 0xba, 0x91, 0x1a, 0x78, 0x06, 0xc1,
0x5b, 0x38, 0x94, 0x70, 0xf5, 0xf2, 0x34, 0xd2, 0x50, 0x44, 0xb6, 0xf7,
0xdb, 0x9c, 0xe8, 0x6e, 0x1c, 0xc3, 0x02, 0x51, 0x55, 0x57, 0x8f, 0x62,
0x94, 0x06, 0x9e, 0x41, 0x30, 0x84, 0xeb, 0x8d, 0x42, 0xfd, 0xff, 0xce,
0xfb, 0x3b, 0xe3, 0x29, 0x02, 0xd1, 0x91, 0x9c, 0xe8, 0x7e, 0x0c, 0xc3,
0x22, 0x51, 0x55, 0xb7, 0xdb, 0xb9, 0x11, 0x1a, 0x78, 0x06, 0xc1, 0x11,
0xb4, 0xa3, 0x00, 0x3c, 0x8d, 0x34, 0x34, 0xed, 0x52, 0xac, 0x9b, 0xab,
0x4f, 0x72, 0x22, 0x27, 0x5a, 0xa1, 0x3c, 0x97, 0x61, 0xa1, 0xa8, 0xaa,
0xdb, 0xef, 0xdd, 0xd9, 0x2e, 0x78, 0x06, 0xc1, 0x71, 0x74, 0xfb, 0xca,
0x2f, 0xf5, 0x2b, 0x50, 0x04, 0xa2, 0x13, 0x39, 0xd1, 0x12, 0xd5, 0xb9,
0x0c, 0x8b, 0x45, 0x55, 0x9b, 0x51, 0x9c, 0xa9, 0x81, 0x67, 0x10, 0x1c,
0x87, 0x8f, 0x7f, 0x79, 0x0a, 0xff, 0x59, 0x34, 0x57, 0x9f, 0xe2, 0x9d,
0x9c, 0xa8, 0x62, 0x77, 0x0e, 0xc3, 0x82, 0x51, 0x55, 0x57, 0x55, 0xee,
0x2c, 0x17, 0x3c, 0x83, 0x00, 0x91, 0x61, 0x06, 0x1a, 0x45, 0xd1, 0xfd,
0x8e, 0xaa, 0x4f, 0xf1, 0x4e, 0x4e, 0x74, 0x07, 0xc5, 0x3e, 0xce, 0xb0,
0x68, 0x54, 0xb5, 0x1d, 0x45, 0x5c, 0x03, 0xcf, 0x20, 0x40, 0x64, 0x98,
0x2d, 0x1b, 0x9c, 0x5f, 0x03, 0x8a, 0xf5, 0xbb, 0x39, 0xd1, 0x3d, 0x14,
0xbb, 0x18, 0xc3, 0x62, 0x51, 0xd5, 0x30, 0x8a, 0xa8, 0x0b, 0x9e, 0x41,
0x80, 0xe8, 0x30, 0x71, 0x94, 0xa2, 0x80, 0xeb, 0xde, 0x17, 0x91, 0x9c,
0xe8, 0x2e, 0xce, 0xb0, 0x78, 0x54, 0xd5, 0x55, 0x51, 0x0d, 0x3c, 0x83,
0x20, 0x8e, 0xaa, 0xa5, 0xf0, 0x44, 0x45, 0x77, 0x75, 0x44, 0xed, 0x67,
0x3c, 0x27, 0x1a, 0x67, 0x58, 0x3e, 0xaa, 0x1a, 0xd1, 0xc0, 0x33, 0x08,
0xce, 0x81, 0xbf, 0x23, 0x05, 0xd0, 0x11, 0xf4, 0x62, 0x0f, 0x91, 0x9c,
0x68, 0x9c, 0xe1, 0x42, 0x51, 0xd5, 0x88, 0x06, 0x96, 0x41, 0x80, 0x11,
0xc3, 0x0c, 0x34, 0xcd, 0xea, 0x48, 0xf4, 0x9c, 0x9c, 0x68, 0x84, 0xe1,
0x52, 0x51, 0xd5, 0x77, 0x34, 0xf0, 0x0c, 0x82, 0x73, 0x51, 0xf5, 0xee,
0x87, 0x27, 0x51, 0xac, 0xe3, 0x39, 0xd1, 0x18, 0xc3, 0x05, 0xa3, 0xaa,
0x27, 0x35, 0xf0, 0x0c, 0x82, 0xf3, 0x51, 0x21, 0x44, 0x1b, 0x3c, 0xf7,
0x1a, 0xee, 0xbc, 0x9c, 0x68, 0x84, 0xe1, 0x72, 0x51, 0xd5, 0x13, 0x1a,
0x78, 0x06, 0xc1, 0x18, 0x28, 0x02, 0x05, 0x0e, 0x44, 0xeb, 0xb1, 0x39,
0xd1, 0x21, 0xc3, 0x85, 0xa3, 0xaa, 0x47, 0x35, 0xf0, 0x0c, 0x82, 0x71,
0x50, 0x04, 0xb8, 0x6e, 0x11, 0x39, 0x51, 0xff, 0xaf, 0x97, 0x8e, 0xaa,
0x1e, 0xd1, 0xc0, 0x33, 0x08, 0x30, 0x71, 0x98, 0xce, 0xaf, 0xa9, 0x39,
0xd1, 0xc0, 0x60, 0x10, 0x55, 0x1d, 0x68, 0xe0, 0x19, 0x04, 0x98, 0x34,
0x4c, 0x47, 0xe7, 0x44, 0x9d, 0x71, 0x54, 0xd5, 0x6b, 0x20, 0x19, 0xd8,
0xa0, 0x8b, 0xf6, 0xee, 0xc7, 0xc4, 0x9c, 0x68, 0x60, 0x30, 0x8a, 0xaa,
0xf6, 0x34, 0xf0, 0x0c, 0x82, 0x69, 0xd0, 0xab, 0x88, 0xaa, 0xea, 0x9c,
0x0c, 0x82, 0xa9, 0xd0, 0xab, 0x88, 0xaa, 0xea, 0x7c, 0x0c, 0x42, 0xe8,
0xd7, 0xab, 0x88, 0xaa, 0xea, 0x5c, 0x0c, 0x02, 0x06, 0x7a, 0x15, 0x51,
0x55, 0x9d, 0x87, 0x41, 0xc0, 0x41, 0xe1, 0xe8, 0x9c, 0xa8, 0x33, 0x8f,
0xaa, 0x2a, 0x1c, 0xcf, 0x20, 0x60, 0xe1, 0xae, 0x22, 0xaa, 0xea, 0xc0,
0x33, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x83, 0x15, 0x5f, 0xaa,
0xfa, 0x7d, 0x73, 0xff, 0x60, 0x5c, 0xaa, 0x8a, 0x3f, 0xb0, 0x32, 0x77,
0x21, 0x7c, 0xa9, 0xea, 0xc3, 0xfd, 0xd3, 0xd3, 0xdd, 0x96, 0x61, 0xe0,
0xc1, 0x17, 0xbb, 0xf2, 0x2e, 0x84, 0x2f, 0x55, 0xc5, 0xb7, 0xed, 0xdd,
0xe3, 0xe3, 0xb6, 0x24, 0x18, 0x68, 0xf0, 0xc5, 0xae, 0xbc, 0x0b, 0x61,
0x4b, 0x55, 0xbb, 0x4a, 0xd3, 0x72, 0xfb, 0xfc, 0x5c, 0xee, 0x8d, 0x4a,
0x55, 0x43, 0xb1, 0xab, 0xa9, 0x0b, 0xe1, 0x4b, 0x55, 0xbb, 0x4a, 0xd3,
0x7d, 0xd9, 0xf4, 0x91, 0x1a, 0x95, 0xaa, 0x86, 0x62, 0x57, 0x43, 0x17,
0xc2, 0x97, 0xaa, 0xfa, 0x4a, 0xd3, 0xae, 0x8f, 0x74, 0x0a, 0x03, 0x0f,
0xa1, 0x8b, 0x5d, 0x79, 0x17, 0xc2, 0x97, 0xaa, 0x86, 0x4a, 0xd3, 0xa6,
0x8f, 0xd4, 0xe9, 0x78, 0x06, 0x1e, 0x7c, 0xb1, 0x2b, 0xef, 0x42, 0xe8,
0x52, 0xd5, 0x5e, 0xa5, 0xa9, 0xba, 0xa6, 0x8f, 0x74, 0x2c, 0x03, 0x0f,
0xbe, 0xd8, 0x95, 0x77, 0x21, 0x7c, 0xa9, 0x6a, 0xbf, 0xd2, 0x54, 0xb5,
0x2c, 0xe1, 0xc6, 0x31, 0xf0, 0xe0, 0x8b, 0x5d, 0x79, 0x17, 0x42, 0x97,
0xaa, 0x0e, 0x2a, 0x4d, 0x1d, 0x9a, 0x3e, 0xd2, 0x31, 0x0c, 0x3c, 0xf8,
0x62, 0x57, 0xde, 0x85, 0xf0, 0xa5, 0xaa, 0xc3, 0x4a, 0xd3, 0xae, 0x8f,
0x74, 0x04, 0x03, 0x0d, 0xbe, 0xd8, 0x95, 0x77, 0x21, 0x74, 0xa9, 0xea,
0xd1, 0x4a, 0xd3, 0xa6, 0x8f, 0x14, 0xee, 0x5c, 0x06, 0x1e, 0x7c, 0xb1,
0x2b, 0xef, 0x42, 0xe8, 0x52, 0xd5, 0x13, 0x95, 0xa6, 0x0e, 0x4d, 0x1f,
0xe9, 0x79, 0x0c, 0x3c, 0xf8, 0x62, 0x57, 0xde, 0x85, 0xd0, 0xa5, 0xaa,
0x27, 0x2b, 0x4d, 0xdb, 0xa2, 0x42, 0x77, 0x0e, 0x03, 0x0f, 0xbe, 0xd8,
0x95, 0x77, 0x21, 0x7c, 0xa9, 0xea, 0xe9, 0x4a, 0x53, 0x87, 0x46, 0x46,
0x9c, 0x81, 0x07, 0x5f, 0xec, 0xca, 0xbb, 0x10, 0xba, 0x54, 0xf5, 0x44,
0xa5, 0x69, 0x90, 0xe1, 0x5c, 0x8c, 0x81, 0x07, 0x5f, 0xec, 0xca, 0xbb,
0x10, 0xba, 0x54, 0x35, 0x52, 0x69, 0xda, 0x3c, 0x20, 0x31, 0x06, 0x1e,
0x7c, 0xb1, 0x2b, 0xef, 0x42, 0xf8, 0x52, 0xd5, 0x78, 0xa5, 0x69, 0x55,
0x45, 0x18, 0x48, 0x44, 0x25, 0x5c, 0xc4, 0x85, 0xf0, 0xa5, 0xaa, 0xf1,
0x4a, 0xd3, 0x46, 0x46, 0x84, 0x81, 0x44, 0x5c, 0xc2, 0xf2, 0x2e, 0x84,
0x2e, 0x55, 0x3d, 0xb3, 0xd2, 0xb4, 0xaa, 0x4e, 0x32, 0xcc, 0xf5, 0x80,
0x47, 0x24, 0x2c, 0xed, 0x42, 0xe8, 0x52, 0xd5, 0xb3, 0x2b, 0x4d, 0xab,
0x6a, 0xb9, 0x52, 0xd5, 0xb8, 0x84, 0xe5, 0x5d, 0x08, 0x5d, 0xaa, 0x3a,
0xa2, 0xd2, 0xb4, 0xaa, 0x16, 0x2c, 0x55, 0x8d, 0x4b, 0x58, 0xd8, 0x85,
0xd0, 0xa5, 0xaa, 0xa3, 0x2a, 0x4d, 0x55, 0x8f, 0x31, 0x5c, 0xb4, 0x55,
0x75, 0x31, 0x17, 0x42, 0x97, 0xaa, 0x8e, 0xac, 0x34, 0x55, 0x1d, 0x32,
0x5c, 0xb0, 0x55, 0x75, 0x41, 0x17, 0x42, 0x97, 0xaa, 0x8e, 0xae, 0x34,
0x55, 0x7d, 0xcb, 0x60, 0xd0, 0xaa, 0xba, 0x80, 0x0b, 0x99, 0x58, 0xaa,
0x4a, 0x55, 0x9a, 0xaa, 0x7a, 0x06, 0x93, 0x56, 0xd5, 0x85, 0x5c, 0x08,
0x5d, 0xaa, 0x3a, 0xa9, 0xd2, 0x54, 0xb5, 0xc7, 0x60, 0xd0, 0xaa, 0x3a,
0xbf, 0x0b, 0xc1, 0x24, 0x28, 0x5d, 0x69, 0xaa, 0xd6, 0xad, 0xaa, 0xb3,
0xbb, 0x10, 0x4c, 0x84, 0xd2, 0x95, 0xa6, 0x6a, 0xd9, 0xaa, 0xba, 0x80,
0x0b, 0xc1, 0x64, 0x28, 0x5d, 0x69, 0xaa, 0xb6, 0xad, 0xaa, 0x33, 0xbb,
0x10, 0x10, 0x50, 0xba, 0xd2, 0x54, 0x2d, 0x5b, 0x55, 0x67, 0x76, 0x21,
0x74, 0xa9, 0x2a, 0x59, 0x69, 0xaa, 0xea, 0x60, 0xdd, 0xaa, 0xca, 0xbb,
0x68, 0x5c, 0x08, 0x48, 0x38, 0xba, 0xd2, 0xd4, 0xd9, 0xb7, 0xaa, 0xce,
0xe2, 0x62, 0x05, 0x1a, 0x1b, 0xc3, 0xa8, 0x6a, 0xd0, 0xf0, 0x70, 0x0f,
0x63, 0x11, 0x02, 0x16, 0x49, 0x44, 0x55, 0xf9, 0xe3, 0xfb, 0x01, 0xfb,
0x51, 0x26, 0x11, 0x55, 0xe5, 0x8f, 0xef, 0xb7, 0x1f, 0x65, 0x22, 0x51,
0x55, 0xfe, 0xf8, 0xfe, 0x14, 0x46, 0x99, 0x44, 0x54, 0x95, 0x3f, 0xbe,
0x3f, 0x85, 0x51, 0x26, 0x11, 0x55, 0x25, 0x8e, 0xef, 0x4f, 0x68, 0x94,
0x49, 0x44, 0x55, 0xf9, 0xe3, 0xfb, 0x53, 0x18, 0x65, 0x12, 0x51, 0x55,
0xfe, 0xf8, 0xfe, 0x44, 0x46, 0x69, 0x1f, 0x55, 0x65, 0x8f, 0xef, 0x4f,
0x63, 0x94, 0x49, 0x44, 0x55, 0x89, 0xe3, 0xfb, 0xd3, 0x1a, 0xa5, 0x7d,
0x54, 0x95, 0x3f, 0xbe, 0x3f, 0x91, 0x51, 0xda, 0x47, 0x55, 0xf9, 0xe3,
0xfb, 0x13, 0x19, 0xa5, 0x7d, 0x54, 0x95, 0x39, 0xbe, 0x3f, 0xa9, 0x51,
0xda, 0x47, 0x55, 0x89, 0xe3, 0xfb, 0x59, 0x11, 0xf3, 0x8e, 0xd2, 0x3e,
0xaa, 0x4a, 0x1c, 0xdf, 0x9f, 0xd0, 0x28, 0x93, 0x88, 0xaa, 0xf2, 0xc7,
0xf7, 0xa7, 0x30, 0xca, 0x24, 0xa2, 0xaa, 0xdc, 0xf1, 0xfd, 0xa9, 0x8c,
0x32, 0x89, 0xa8, 0x2a, 0x7f, 0x7c, 0x7f, 0x4a, 0xa3, 0x4c, 0x3f, 0xaa,
0x1a, 0xc9, 0xaa, 0xda, 0x8f, 0x32, 0x89, 0xa8, 0x2a, 0x7f, 0x7c, 0x7f,
0x0a, 0xa3, 0x4c, 0x22, 0xaa, 0xca, 0x1f, 0xdf, 0x9f, 0xc8, 0x28, 0xed,
0xa3, 0xaa, 0xfc, 0xf1, 0xfd, 0x89, 0x8c, 0xd2, 0x3e, 0xaa, 0xca, 0x1f,
0xdf, 0x9f, 0xc2, 0x28, 0x7f, 0xc5, 0xa8, 0xaa, 0x22, 0x20, 0xa1, 0xaf,
0x9d, 0x5f, 0x33, 0xaa, 0xaa, 0x7e, 0x90, 0xf6, 0xa3, 0xfc, 0xf5, 0xa3,
0xaa, 0x8a, 0x99, 0x45, 0xc8, 0xc5, 0x73, 0xa2, 0xe9, 0x44, 0x55, 0x35,
0x8d, 0x07, 0xfc, 0x3a, 0xa2, 0xaa, 0x9a, 0xc6, 0xae, 0xbc, 0x8e, 0xa8,
0xaa, 0xa6, 0x31, 0xca, 0xeb, 0x88, 0xaa, 0x6a, 0x1a, 0xa3, 0xbc, 0x8e,
0xa8, 0xaa, 0xa6, 0x32, 0xca, 0x6b, 0x88, 0xaa, 0x6a, 0x1a, 0x5f, 0x3b,
0xd7, 0x11, 0x55, 0x75, 0xa0, 0xf1, 0x3f, 0x19, 0xc2, 0xb4, 0x90, 0x78,
0xb9, 0x76, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae,
0x42, 0x60, 0x82,
};
#endif

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Joerg Henrichs
// Copyright (C) 2006-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Joerg Henrichs
// Copyright (C) 2006-2013 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs, Marianne Gagnon
// Copyright (C) 2011-2013 Joerg Henrichs, Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -22,9 +22,12 @@
#include "graphics/material_manager.hpp"
#include "graphics/particle_kind.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/shaders.hpp"
#include "graphics/wind.hpp"
#include "io/file_manager.hpp"
#include "tracks/track.hpp"
#include "utils/constants.hpp"
#include "utils/helpers.hpp"
#include <SParticle.h>
#include <IParticleAffector.h>
@ -32,6 +35,7 @@
#include <IParticleSystemSceneNode.h>
#include <IParticleBoxEmitter.h>
#include <ISceneManager.h>
#include <algorithm>
class FadeAwayAffector : public scene::IParticleAffector
{
@ -173,6 +177,46 @@ public:
}
};
// ============================================================================
class WindAffector : public scene::IParticleAffector
{
/** (Squared) distance from camera at which a particle is completely faded out */
float m_speed;
float m_seed;
public:
WindAffector(float speed): m_speed(speed)
{
m_seed = (rand() % 1000) - 500;
}
// ------------------------------------------------------------------------
virtual void affect(u32 now, scene::SParticle* particlearray, u32 count)
{
const float time = irr_driver->getDevice()->getTimer()->getTime() / 10000.0f;
core::vector3df dir = irr_driver->getWind();
dir *= m_speed * std::min(noise2d(time, m_seed), -0.2f);
for (u32 n = 0; n < count; n++)
{
scene::SParticle& cur = particlearray[n];
cur.pos += dir;
} // for n<count
} // affect
// ------------------------------------------------------------------------
virtual scene::E_PARTICLE_AFFECTOR_TYPE getType() const
{
// FIXME: this method seems to make sense only for built-in affectors
return scene::EPAT_FADE_OUT;
}
}; // WindAffector
// ============================================================================
@ -498,6 +542,21 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
m_node->addAffector(scale_affector);
scale_affector->drop();
}
const float windspeed = type->getWindSpeed();
if (windspeed > 0.01f)
{
WindAffector *waf = new WindAffector(windspeed);
m_node->addAffector(waf);
waf->drop();
}
const bool flips = type->getFlips();
if (flips)
{
m_node->getMaterial(0).MaterialType = irr_driver->getShader(ES_SNOW);
m_node->getMaterial(0).BlendOperation = video::EBO_ADD;
}
}
} // setParticleType

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs, Marianne Gagnon
// Copyright (C) 2011-2013 Joerg Henrichs, Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs, Marianne Gagnon
// Copyright (C) 2011-2013 Joerg Henrichs, Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -54,6 +54,8 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
m_has_scale_affector = NULL;
m_scale_affector_factor_x = 0.0f;
m_scale_affector_factor_y = 0.0f;
m_wind_speed = 0;
m_flips = false;
// ----- Read XML file
@ -219,6 +221,14 @@ ParticleKind::ParticleKind(const std::string file) : m_min_start_color(255,255,2
m_material_file = material_manager->getLatestMaterial()->getTexFname();
}
// ------------------------------------------------------------------------
const XMLNode* wind = xml->getNode("wind");
if (wind != NULL)
{
wind->get("speed", &m_wind_speed);
wind->get("flips", &m_flips);
}
// ------------------------------------------------------------------------

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs, Marianne Gagnon
// Copyright (C) 2011-2013 Joerg Henrichs, Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -86,6 +86,11 @@ private:
int m_emission_decay_rate;
/** Wind. < 0.01 if disabled. */
float m_wind_speed;
bool m_flips;
std::string m_name;
std::string m_material_file;
@ -148,11 +153,14 @@ public:
int getEmissionDecayRate() const { return m_emission_decay_rate; }
bool hasScaleAffector() const { return m_has_scale_affector; }
float getScaleAffectorFactorX() const { return m_scale_affector_factor_x; }
float getScaleAffectorFactorY() const { return m_scale_affector_factor_y; };
float getWindSpeed() const { return m_wind_speed; }
bool getFlips() const { return m_flips; }
std::string getName() const { return m_name; }
};

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs, Marianne Gagnon
// Copyright (C) 2011-2013 Joerg Henrichs, Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Marianne Gagnon
// Copyright (C) 2011-2013 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License

View File

@ -1,6 +1,6 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Marianne Gagnon
// based on code Copyright (C) 2002-2010 Nikolaus Gebhardt
// Copyright (C) 2011-2013 Marianne Gagnon
// based on code Copyright 2002-2010 Nikolaus Gebhardt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -24,7 +24,7 @@
#include <IMeshSceneNode.h>
PerCameraNode::PerCameraNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id,
scene::ICameraSceneNode* camera, scene::IMesh* mesh)
scene::ICameraSceneNode* camera, scene::ISceneNode *node)
: IDummyTransformationSceneNode(parent, mgr, id)
{
#ifdef DEBUG
@ -33,7 +33,10 @@ PerCameraNode::PerCameraNode(scene::ISceneNode* parent, scene::ISceneManager* mg
#endif
m_camera = camera;
m_child = mgr->addMeshSceneNode(mesh, this);
node->setParent(this);
m_child = node;
//m_child = mgr->addCubeSceneNode(0.5f, this, -1, core::vector3df(0,0,0), core::vector3df(0,0,0), core::vector3df(3.0f,0.2f,3.0f));
//RelativeTransformationMatrix.setTranslation( core::vector3df(-0.5,-1,3) );

View File

@ -1,6 +1,6 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Marianne Gagnon
// based on code Copyright (C) 2002-2010 Nikolaus Gebhardt
// Copyright (C) 2011-2013 Marianne Gagnon
// based on code Copyright 2002-2010 Nikolaus Gebhardt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -54,7 +54,7 @@ private:
public:
PerCameraNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id,
scene::ICameraSceneNode* camera, scene::IMesh* mesh);
scene::ICameraSceneNode* camera, scene::ISceneNode* node);
virtual ~PerCameraNode();
//! returns the axis aligned bounding box of this node

View File

@ -1,6 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011-2013 the SuperTuxKart team
// Copyright (C) 2013 Joerg Henrichs
// Copyright (C) 2011-2013 the SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -20,69 +19,46 @@
#include "config/user_config.hpp"
#include "io/file_manager.hpp"
#include "graphics/callbacks.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/mlaa_areamap.hpp"
#include "graphics/shaders.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/kart_model.hpp"
#include "modes/world.hpp"
#include "race/race_manager.hpp"
#include "tracks/track.hpp"
#include "utils/log.hpp"
#include <IGPUProgrammingServices.h>
#include <IMaterialRendererServices.h>
#define MOTION_BLUR_FACTOR (1.0f/15.0f)
#define MOTION_BLUR_OFFSET 20.0f
#include <SViewFrustum.h>
using namespace video;
using namespace scene;
PostProcessing::PostProcessing(video::IVideoDriver* video_driver)
PostProcessing::PostProcessing(IVideoDriver* video_driver)
{
// Check if post-processing is supported on this hardware
m_supported = false;
if( irr_driver->isGLSL() )
{
m_supported = true;
}
//Check which texture dimensions are supported on this hardware
bool nonsquare = video_driver->queryFeature(video::EVDF_TEXTURE_NSQUARE);
bool nonpower = video_driver->queryFeature(video::EVDF_TEXTURE_NPOT);
if (!nonpower) {
Log::warn("PostProcessing",
"Only power of two textures are supported.");
}
if (!nonsquare) {
Log::warn("PostProcessing", "Only square textures are supported.");
}
// Initialization
if(m_supported)
m_material.Wireframe = false;
m_material.Lighting = false;
m_material.ZWriteEnable = false;
m_material.ZBuffer = ECFN_ALWAYS;
m_material.setFlag(EMF_TRILINEAR_FILTER, true);
for (u32 i = 0; i < MATERIAL_MAX_TEXTURES; ++i)
{
// Render target
core::dimension2du opt = video_driver->getScreenSize()
.getOptimalSize(!nonpower, !nonsquare);
m_render_target =
video_driver->addRenderTargetTexture(opt, "postprocess");
if(!m_render_target)
{
Log::warn("PostProcessing", "Couldn't create the render target "
"for post-processing, disabling it.");
UserConfigParams::m_postprocess_enabled = false;
m_material.TextureLayer[i].TextureWrapU =
m_material.TextureLayer[i].TextureWrapV = ETC_CLAMP_TO_EDGE;
}
// Material and shaders
IGPUProgrammingServices* gpu =
video_driver->getGPUProgrammingServices();
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
(file_manager->getShaderDir() + "motion_blur.vert").c_str(),
"main", video::EVST_VS_2_0,
(file_manager->getShaderDir() + "motion_blur.frag").c_str(),
"main", video::EPST_PS_2_0,
this, video::EMT_SOLID);
m_blur_material.MaterialType = (E_MATERIAL_TYPE)material_type;
m_blur_material.setTexture(0, m_render_target);
m_blur_material.Wireframe = false;
m_blur_material.Lighting = false;
m_blur_material.ZWriteEnable = false;
// Load the MLAA area map
io::IReadFile *areamap = irr_driver->getDevice()->getFileSystem()->
createMemoryReadFile((void *) AreaMap33, sizeof(AreaMap33),
"AreaMap33", false);
if (!areamap) Log::fatal("postprocessing", "Failed to load the areamap");
m_areamap = irr_driver->getVideoDriver()->getTexture(areamap);
areamap->drop();
}
} // PostProcessing
// ----------------------------------------------------------------------------
@ -97,12 +73,15 @@ PostProcessing::~PostProcessing()
*/
void PostProcessing::reset()
{
unsigned int n = Camera::getNumCameras();
const u32 n = Camera::getNumCameras();
m_boost_time.resize(n);
m_vertices.resize(n);
m_center.resize(n);
m_direction.resize(n);
MotionBlurProvider * const cb = (MotionBlurProvider *) irr_driver->
getCallback(ES_MOTIONBLUR);
for(unsigned int i=0; i<n; i++)
{
m_boost_time[i] = 0.0f;
@ -137,7 +116,7 @@ void PostProcessing::reset()
core::vector3df normal(0,0,1);
m_vertices[i].v0.Normal = m_vertices[i].v1.Normal =
m_vertices[i].v2.Normal = m_vertices[i].v3.Normal = normal;
video::SColor white(0xFF, 0xFF, 0xFF, 0xFF);
SColor white(0xFF, 0xFF, 0xFF, 0xFF);
m_vertices[i].v0.Color = m_vertices[i].v1.Color =
m_vertices[i].v2.Color = m_vertices[i].v3.Color = white;
@ -145,57 +124,51 @@ void PostProcessing::reset()
+m_vertices[i].v2.TCoords.X) * 0.5f;
// Center is around 20 percent from bottom of screen:
float tex_height = m_vertices[i].v1.TCoords.Y
const float tex_height = m_vertices[i].v1.TCoords.Y
- m_vertices[i].v0.TCoords.Y;
m_center[i].Y=m_vertices[i].v0.TCoords.Y + 0.2f*tex_height;
m_direction[i].X = m_center[i].X;
m_direction[i].Y = m_vertices[i].v0.TCoords.Y + 0.7f*tex_height;
setMotionBlurCenterY(i, 0.2f);
cb->setDirection(i, m_direction[i].X, m_direction[i].Y);
cb->setMaxHeight(i, m_vertices[i].v1.TCoords.Y);
} // for i <number of cameras
} // reset
// ----------------------------------------------------------------------------
/** Setup the render target. First determines if there is any need for post-
* processing, and if so, set up render to texture.
*/
void PostProcessing::beginCapture()
void PostProcessing::setMotionBlurCenterY(const u32 num, const float y)
{
if(!m_supported || !UserConfigParams::m_postprocess_enabled)
return;
MotionBlurProvider * const cb = (MotionBlurProvider *) irr_driver->
getCallback(ES_MOTIONBLUR);
bool any_boost = false;
for(unsigned int i=0; i<m_boost_time.size(); i++)
any_boost |= m_boost_time[i]>0.0f;
const float tex_height = m_vertices[num].v1.TCoords.Y - m_vertices[num].v0.TCoords.Y;
m_center[num].Y = m_vertices[num].v0.TCoords.Y + y * tex_height;
// Don't capture the input when we have no post-processing to add
// it will be faster and this ay we won't lose anti-aliasing
if(!any_boost)
{
m_used_pp_this_frame = false;
return;
}
cb->setCenter(num, m_center[num].X, m_center[num].Y);
}
m_used_pp_this_frame = true;
irr_driver->getVideoDriver()->setRenderTarget(m_render_target, true, true);
// ----------------------------------------------------------------------------
/** Setup some PP data.
*/
void PostProcessing::begin()
{
m_any_boost = false;
for (u32 i = 0; i < m_boost_time.size(); i++)
m_any_boost |= m_boost_time[i] > 0.01f;
} // beginCapture
// ----------------------------------------------------------------------------
/** Restore the framebuffer render target.
*/
void PostProcessing::endCapture()
{
if(!m_supported || !UserConfigParams::m_postprocess_enabled ||
!m_used_pp_this_frame)
return;
irr_driver->getVideoDriver()->setRenderTarget(video::ERT_FRAME_BUFFER,
true, true, 0);
} // endCapture
// ----------------------------------------------------------------------------
/** Set the boost amount according to the speed of the camera */
void PostProcessing::giveBoost(unsigned int camera_index)
{
if (irr_driver->isGLSL())
{
m_boost_time[camera_index] = 0.75f;
MotionBlurProvider * const cb = (MotionBlurProvider *)irr_driver->
getCallback(ES_MOTIONBLUR);
cb->setBoostTime(camera_index, m_boost_time[camera_index]);
}
} // giveBoost
// ----------------------------------------------------------------------------
@ -204,75 +177,590 @@ void PostProcessing::giveBoost(unsigned int camera_index)
*/
void PostProcessing::update(float dt)
{
for(unsigned int i=0; i<m_boost_time.size(); i++)
if (!irr_driver->isGLSL())
return;
MotionBlurProvider* const cb =
(MotionBlurProvider*) irr_driver->getCallback(ES_MOTIONBLUR);
if (cb == NULL) return;
for (unsigned int i=0; i<m_boost_time.size(); i++)
{
if (m_boost_time[i] > 0.0f)
{
m_boost_time[i] -= dt;
if (m_boost_time[i] < 0.0f) m_boost_time[i] = 0.0f;
}
cb->setBoostTime(i, m_boost_time[i]);
}
} // update
// ----------------------------------------------------------------------------
/** Render the post-processed scene, solids only, color to color, no stencil */
void PostProcessing::renderSolid(const u32 cam)
{
if (irr_driver->isGLSL()) return;
// Early out: do nothing if at all possible
if (UserConfigParams::m_ssao < 1 && !World::getWorld()->getTrack()->isFogEnabled())
return;
static u8 tick = 0;
IVideoDriver * const drv = irr_driver->getVideoDriver();
drv->setTransform(ETS_WORLD, core::IdentityMatrix);
drv->setTransform(ETS_VIEW, core::IdentityMatrix);
drv->setTransform(ETS_PROJECTION, core::IdentityMatrix);
GaussianBlurProvider * const gacb = (GaussianBlurProvider *) irr_driver->
getCallback(ES_GAUSSIAN3H);
const TypeRTT curssao = tick ? RTT_SSAO2 : RTT_SSAO1;
if (World::getWorld()->getTrack()->isFogEnabled())
{
m_material.MaterialType = irr_driver->getShader(ES_FOG);
m_material.setTexture(0, irr_driver->getRTT(RTT_DEPTH));
// Overlay
m_material.BlendOperation = EBO_ADD;
m_material.MaterialTypeParam = pack_textureBlendFunc(EBF_SRC_ALPHA, EBF_ONE_MINUS_SRC_ALPHA);
drv->setRenderTarget(irr_driver->getRTT(RTT_COLOR), false, false);
drawQuad(cam, m_material);
m_material.BlendOperation = EBO_NONE;
m_material.MaterialTypeParam = 0;
}
if (UserConfigParams::m_ssao == 1) // SSAO low
{
m_material.MaterialType = irr_driver->getShader(ES_SSAO);
m_material.setTexture(0, irr_driver->getRTT(RTT_NORMAL));
m_material.setTexture(1, irr_driver->getRTT(tick ? RTT_SSAO1 : RTT_SSAO2));
drv->setRenderTarget(irr_driver->getRTT(curssao), true, false,
SColor(255, 255, 255, 255));
drawQuad(cam, m_material);
// Blur it to reduce noise.
{
gacb->setResolution(UserConfigParams::m_width / 4,
UserConfigParams::m_height / 4);
m_material.MaterialType = irr_driver->getShader(ES_GAUSSIAN3V);
m_material.setTexture(0, irr_driver->getRTT(curssao));
drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER2), true, false);
drawQuad(cam, m_material);
m_material.MaterialType = irr_driver->getShader(ES_GAUSSIAN3H);
m_material.setTexture(0, irr_driver->getRTT(RTT_QUARTER2));
drv->setRenderTarget(irr_driver->getRTT(curssao), false, false);
drawQuad(cam, m_material);
}
// Overlay
m_material.MaterialType = EMT_ONETEXTURE_BLEND;
m_material.setTexture(0, irr_driver->getRTT(curssao));
m_material.setTexture(1, 0);
m_material.BlendOperation = EBO_ADD;
m_material.MaterialTypeParam = pack_textureBlendFunc(EBF_DST_COLOR, EBF_ZERO);
drv->setRenderTarget(irr_driver->getRTT(RTT_COLOR), false, false);
drawQuad(cam, m_material);
m_material.BlendOperation = EBO_NONE;
m_material.MaterialTypeParam = 0;
} else if (UserConfigParams::m_ssao == 2) // SSAO high
{
m_material.MaterialType = irr_driver->getShader(ES_SSAO);
m_material.setTexture(0, irr_driver->getRTT(RTT_NORMAL));
m_material.setTexture(1, irr_driver->getRTT(tick ? RTT_SSAO1 : RTT_SSAO2));
drv->setRenderTarget(irr_driver->getRTT(curssao), true, false,
SColor(255, 255, 255, 255));
drawQuad(cam, m_material);
// Blur it to reduce noise.
{
gacb->setResolution(UserConfigParams::m_width,
UserConfigParams::m_height);
m_material.MaterialType = irr_driver->getShader(ES_GAUSSIAN6V);
m_material.setTexture(0, irr_driver->getRTT(curssao));
drv->setRenderTarget(irr_driver->getRTT(RTT_TMP3), true, false);
drawQuad(cam, m_material);
m_material.MaterialType = irr_driver->getShader(ES_GAUSSIAN6H);
m_material.setTexture(0, irr_driver->getRTT(RTT_TMP3));
drv->setRenderTarget(irr_driver->getRTT(curssao), false, false);
drawQuad(cam, m_material);
}
// Overlay
m_material.MaterialType = EMT_ONETEXTURE_BLEND;
m_material.setTexture(0, irr_driver->getRTT(curssao));
m_material.setTexture(1, 0);
m_material.BlendOperation = EBO_ADD;
m_material.MaterialTypeParam = pack_textureBlendFunc(EBF_DST_COLOR, EBF_ZERO);
drv->setRenderTarget(irr_driver->getRTT(RTT_COLOR), false, false);
drawQuad(cam, m_material);
m_material.BlendOperation = EBO_NONE;
m_material.MaterialTypeParam = 0;
}
tick++;
tick %= 2;
}
// ----------------------------------------------------------------------------
/** Render the post-processed scene */
void PostProcessing::render()
{
if(!m_supported || !UserConfigParams::m_postprocess_enabled)
return;
if (!irr_driver->isGLSL()) return;
if (!m_used_pp_this_frame)
IVideoDriver * const drv = irr_driver->getVideoDriver();
drv->setTransform(ETS_WORLD, core::IdentityMatrix);
drv->setTransform(ETS_VIEW, core::IdentityMatrix);
drv->setTransform(ETS_PROJECTION, core::IdentityMatrix);
MotionBlurProvider * const mocb = (MotionBlurProvider *) irr_driver->
getCallback(ES_MOTIONBLUR);
GaussianBlurProvider * const gacb = (GaussianBlurProvider *) irr_driver->
getCallback(ES_GAUSSIAN3H);
const u32 cams = Camera::getNumCameras();
for(u32 cam = 0; cam < cams; cam++)
{
return;
scene::ICameraSceneNode * const camnode =
Camera::getCamera(cam)->getCameraSceneNode();
mocb->setCurrentCamera(cam);
ITexture *in = irr_driver->getRTT(RTT_COLOR);
ITexture *out = irr_driver->getRTT(RTT_TMP1);
// Each effect uses these as named, and sets them up for the next effect.
// This allows chaining effects where some may be disabled.
// As the original color shouldn't be touched, the first effect can't be disabled.
if (1) // bloom
{
// Blit the base to tmp1
m_material.MaterialType = EMT_SOLID;
m_material.setTexture(0, in);
drv->setRenderTarget(out, true, false);
drawQuad(cam, m_material);
const bool globalbloom = World::getWorld()->getTrack()->getBloom();
BloomPowerProvider * const bloomcb = (BloomPowerProvider *)
irr_driver->
getCallback(ES_BLOOM_POWER);
if (globalbloom)
{
const float threshold = World::getWorld()->getTrack()->getBloomThreshold();
((BloomProvider *) irr_driver->getCallback(ES_BLOOM))->setThreshold(threshold);
// Catch bright areas, and progressively minify
m_material.MaterialType = irr_driver->getShader(ES_BLOOM);
m_material.setTexture(0, in);
drv->setRenderTarget(irr_driver->getRTT(RTT_TMP3), true, false);
drawQuad(cam, m_material);
}
u16 indices[6] = {0, 1, 2, 3, 0, 2};
// Do we have any forced bloom nodes? If so, draw them now
const std::vector<IrrDriver::BloomData> &blooms = irr_driver->getForcedBloom();
const u32 bloomsize = blooms.size();
for(m_current_camera=0; m_current_camera<Camera::getNumCameras();
m_current_camera++)
if (!globalbloom && bloomsize)
drv->setRenderTarget(irr_driver->getRTT(RTT_TMP3), true, false);
if (globalbloom || bloomsize)
{
// Draw the fullscreen quad while applying the corresponding
// post-processing shaders
video::IVideoDriver* video_driver = irr_driver->getVideoDriver();
video_driver->setMaterial(m_blur_material);
video_driver->drawIndexedTriangleList(&(m_vertices[m_current_camera].v0),
4, &indices[0], 2);
// Clear the alpha to a suitable value, stencil
glClearColor(0, 0, 0, 0.1);
glColorMask(0, 0, 0, 1);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glClearColor(0, 0, 0, 0);
glColorMask(1, 1, 1, 1);
// The forced-bloom objects are drawn again, to know which pixels to pick.
// While it's more drawcalls, there's a cost to using four MRTs over three,
// and there shouldn't be many such objects in a track.
// The stencil is already in use for the glow. The alpha channel is best
// reserved for other use (specular, etc).
//
// They are drawn with depth and color writes off, giving 4x-8x drawing speed.
if (bloomsize)
{
const core::aabbox3df &cambox = camnode->
getViewFrustum()->
getBoundingBox();
irr_driver->getSceneManager()->setCurrentRendertime(ESNRP_SOLID);
SOverrideMaterial &overridemat = drv->getOverrideMaterial();
overridemat.EnablePasses = ESNRP_SOLID;
overridemat.EnableFlags = EMF_MATERIAL_TYPE | EMF_ZWRITE_ENABLE | EMF_COLOR_MASK;
overridemat.Enabled = true;
overridemat.Material.MaterialType = irr_driver->getShader(ES_BLOOM_POWER);
overridemat.Material.ZWriteEnable = false;
overridemat.Material.ColorMask = ECP_ALPHA;
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilFunc(GL_ALWAYS, 1, ~0);
glEnable(GL_STENCIL_TEST);
camnode->render();
for (u32 i = 0; i < bloomsize; i++)
{
scene::ISceneNode * const cur = blooms[i].node;
// Quick box-based culling
const core::aabbox3df nodebox = cur->getTransformedBoundingBox();
if (!nodebox.intersectsWithBox(cambox))
continue;
bloomcb->setPower(blooms[i].power);
cur->render();
}
// Second pass for transparents. No-op for solids.
irr_driver->getSceneManager()->setCurrentRendertime(ESNRP_TRANSPARENT);
for (u32 i = 0; i < bloomsize; i++)
{
scene::ISceneNode * const cur = blooms[i].node;
// Quick box-based culling
const core::aabbox3df nodebox = cur->getTransformedBoundingBox();
if (!nodebox.intersectsWithBox(cambox))
continue;
bloomcb->setPower(blooms[i].power);
cur->render();
}
overridemat.Enabled = 0;
overridemat.EnablePasses = 0;
// Ok, we have the stencil; now use it to blit from color to bloom tex
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 1, ~0);
m_material.MaterialType = EMT_SOLID;
m_material.setTexture(0, irr_driver->getRTT(RTT_COLOR));
// Just in case.
glColorMask(1, 1, 1, 0);
drv->setRenderTarget(irr_driver->getRTT(RTT_TMP3), false, false);
m_material.ColorMask = ECP_RGB;
drawQuad(cam, m_material);
m_material.ColorMask = ECP_ALL;
glColorMask(1, 1, 1, 1);
glDisable(GL_STENCIL_TEST);
} // end forced bloom
// To half
m_material.MaterialType = EMT_SOLID;
m_material.setTexture(0, irr_driver->getRTT(RTT_TMP3));
drv->setRenderTarget(irr_driver->getRTT(RTT_HALF1), true, false);
drawQuad(cam, m_material);
// To quarter
m_material.MaterialType = EMT_SOLID;
m_material.setTexture(0, irr_driver->getRTT(RTT_HALF1));
drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER1), true, false);
drawQuad(cam, m_material);
// To eighth
m_material.MaterialType = EMT_SOLID;
m_material.setTexture(0, irr_driver->getRTT(RTT_QUARTER1));
drv->setRenderTarget(irr_driver->getRTT(RTT_EIGHTH1), true, false);
drawQuad(cam, m_material);
// Blur it for distribution.
{
gacb->setResolution(UserConfigParams::m_width / 8,
UserConfigParams::m_height / 8);
m_material.MaterialType = irr_driver->getShader(ES_GAUSSIAN6V);
m_material.setTexture(0, irr_driver->getRTT(RTT_EIGHTH1));
drv->setRenderTarget(irr_driver->getRTT(RTT_EIGHTH2), true, false);
drawQuad(cam, m_material);
m_material.MaterialType = irr_driver->getShader(ES_GAUSSIAN6H);
m_material.setTexture(0, irr_driver->getRTT(RTT_EIGHTH2));
drv->setRenderTarget(irr_driver->getRTT(RTT_EIGHTH1), false, false);
drawQuad(cam, m_material);
}
// Additively blend on top of tmp1
m_material.BlendOperation = EBO_ADD;
m_material.MaterialType = irr_driver->getShader(ES_BLOOM_BLEND);
m_material.setTexture(0, irr_driver->getRTT(RTT_EIGHTH1));
drv->setRenderTarget(out, false, false);
drawQuad(cam, m_material);
m_material.BlendOperation = EBO_NONE;
} // end if bloom
in = irr_driver->getRTT(RTT_TMP1);
out = irr_driver->getRTT(RTT_TMP2);
}
if (World::getWorld()->getTrack()->hasGodRays() && m_sunpixels > 30) // god rays
{
// Grab the sky
drv->setRenderTarget(out, true, false);
irr_driver->getSceneManager()->drawAll(ESNRP_SKY_BOX);
// Set the sun's color
ColorizeProvider * const colcb = (ColorizeProvider *) irr_driver->getCallback(ES_COLORIZE);
const SColor col = World::getWorld()->getTrack()->getSunColor();
colcb->setColor(col.getRed() / 255.0f, col.getGreen() / 255.0f, col.getBlue() / 255.0f);
// The sun interposer
IMeshSceneNode * const sun = irr_driver->getSunInterposer();
sun->getMaterial(0).ColorMask = ECP_ALL;
irr_driver->getSceneManager()->drawAll(ESNRP_CAMERA);
irr_driver->getSceneManager()->setCurrentRendertime(ESNRP_SOLID);
sun->render();
sun->getMaterial(0).ColorMask = ECP_NONE;
// Fade to quarter
m_material.MaterialType = irr_driver->getShader(ES_GODFADE);
m_material.setTexture(0, out);
drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER1), false, false);
drawQuad(cam, m_material);
// Blur
{
gacb->setResolution(UserConfigParams::m_width / 4,
UserConfigParams::m_height / 4);
m_material.MaterialType = irr_driver->getShader(ES_GAUSSIAN3V);
m_material.setTexture(0, irr_driver->getRTT(RTT_QUARTER1));
drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER2), true, false);
drawQuad(cam, m_material);
m_material.MaterialType = irr_driver->getShader(ES_GAUSSIAN3H);
m_material.setTexture(0, irr_driver->getRTT(RTT_QUARTER2));
drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER1), false, false);
drawQuad(cam, m_material);
}
// Calculate the sun's position in texcoords
const core::vector3df pos = sun->getPosition();
float ndc[4];
core::matrix4 trans = camnode->getProjectionMatrix();
trans *= camnode->getViewMatrix();
trans.transformVect(ndc, pos);
const float texh = m_vertices[cam].v1.TCoords.Y - m_vertices[cam].v0.TCoords.Y;
const float texw = m_vertices[cam].v3.TCoords.X - m_vertices[cam].v0.TCoords.X;
const float sunx = ((ndc[0] / ndc[3]) * 0.5f + 0.5f) * texw;
const float suny = ((ndc[1] / ndc[3]) * 0.5f + 0.5f) * texh;
((GodRayProvider *) irr_driver->getCallback(ES_GODRAY))->
setSunPosition(sunx, suny);
// Rays please
m_material.MaterialType = irr_driver->getShader(ES_GODRAY);
m_material.setTexture(0, irr_driver->getRTT(RTT_QUARTER1));
drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER2), true, false);
drawQuad(cam, m_material);
// Blur
{
gacb->setResolution(UserConfigParams::m_width / 4,
UserConfigParams::m_height / 4);
m_material.MaterialType = irr_driver->getShader(ES_GAUSSIAN3V);
m_material.setTexture(0, irr_driver->getRTT(RTT_QUARTER2));
drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER1), true, false);
drawQuad(cam, m_material);
m_material.MaterialType = irr_driver->getShader(ES_GAUSSIAN3H);
m_material.setTexture(0, irr_driver->getRTT(RTT_QUARTER1));
drv->setRenderTarget(irr_driver->getRTT(RTT_QUARTER2), false, false);
drawQuad(cam, m_material);
}
// Overlay
m_material.MaterialType = EMT_TRANSPARENT_ADD_COLOR;
m_material.setTexture(0, irr_driver->getRTT(RTT_QUARTER2));
drv->setRenderTarget(in, false, false);
drawQuad(cam, m_material);
}
if (UserConfigParams::m_motionblur && m_any_boost) // motion blur
{
// Calculate the kart's Y position on screen
const core::vector3df pos =
Camera::getCamera(cam)->getKart()->getNode()->getPosition();
float ndc[4];
core::matrix4 trans = camnode->getProjectionMatrix();
trans *= camnode->getViewMatrix();
trans.transformVect(ndc, pos);
const float karty = (ndc[1] / ndc[3]) * 0.5f + 0.5f;
setMotionBlurCenterY(cam, karty);
m_material.MaterialType = irr_driver->getShader(ES_MOTIONBLUR);
m_material.setTexture(0, in);
drv->setRenderTarget(out, true, false);
drawQuad(cam, m_material);
ITexture *tmp = in;
in = out;
out = tmp;
}
if (irr_driver->getDisplacingNodes().size()) // Displacement
{
m_material.MaterialType = irr_driver->getShader(ES_PPDISPLACE);
m_material.setFlag(EMF_BILINEAR_FILTER, false);
m_material.setTexture(0, in);
m_material.setTexture(1, irr_driver->getRTT(RTT_DISPLACE));
drv->setRenderTarget(out, true, false);
drawQuad(cam, m_material);
m_material.setTexture(1, 0);
m_material.setFlag(EMF_BILINEAR_FILTER, true);
ITexture *tmp = in;
in = out;
out = tmp;
}
if (UserConfigParams::m_mlaa) // MLAA. Must be the last pp filter.
{
drv->setRenderTarget(out, false, false);
glEnable(GL_STENCIL_TEST);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 1, ~0);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
// Pass 1: color edge detection
m_material.setFlag(EMF_BILINEAR_FILTER, false);
m_material.setFlag(EMF_TRILINEAR_FILTER, false);
m_material.MaterialType = irr_driver->getShader(ES_MLAA_COLOR1);
m_material.setTexture(0, in);
drawQuad(cam, m_material);
m_material.setFlag(EMF_BILINEAR_FILTER, true);
m_material.setFlag(EMF_TRILINEAR_FILTER, true);
glStencilFunc(GL_EQUAL, 1, ~0);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Pass 2: blend weights
drv->setRenderTarget(irr_driver->getRTT(RTT_TMP3), true, false);
m_material.MaterialType = irr_driver->getShader(ES_MLAA_BLEND2);
m_material.setTexture(0, out);
m_material.setTexture(1, m_areamap);
m_material.TextureLayer[1].BilinearFilter = false;
m_material.TextureLayer[1].TrilinearFilter = false;
drawQuad(cam, m_material);
m_material.TextureLayer[1].BilinearFilter = true;
m_material.TextureLayer[1].TrilinearFilter = true;
m_material.setTexture(1, 0);
// Pass 3: gather
drv->setRenderTarget(in, false, false);
m_material.setFlag(EMF_BILINEAR_FILTER, false);
m_material.setFlag(EMF_TRILINEAR_FILTER, false);
m_material.MaterialType = irr_driver->getShader(ES_MLAA_NEIGH3);
m_material.setTexture(0, irr_driver->getRTT(RTT_TMP3));
m_material.setTexture(1, irr_driver->getRTT(RTT_COLOR));
drawQuad(cam, m_material);
m_material.setFlag(EMF_BILINEAR_FILTER, true);
m_material.setFlag(EMF_TRILINEAR_FILTER, true);
m_material.setTexture(1, 0);
// Done.
glDisable(GL_STENCIL_TEST);
}
// Final blit
if (irr_driver->getNormals())
{
m_material.MaterialType = irr_driver->getShader(ES_FLIP);
m_material.setTexture(0, irr_driver->getRTT(RTT_NORMAL));
} else if (irr_driver->getSSAOViz())
{
m_material.MaterialType = irr_driver->getShader(ES_FLIP);
m_material.setTexture(0, irr_driver->getRTT(RTT_SSAO1));
} else if (irr_driver->getShadowViz())
{
m_material.MaterialType = irr_driver->getShader(ES_FLIP);
m_material.setTexture(0, irr_driver->getRTT(RTT_SHADOW));
} else
{
m_material.MaterialType = irr_driver->getShader(ES_FLIP);
m_material.setTexture(0, in);
}
drv->setRenderTarget(ERT_FRAME_BUFFER, false, false);
drawQuad(cam, m_material);
}
} // render
// ----------------------------------------------------------------------------
/** Implement IShaderConstantsSetCallback. Shader constants setter for
* post-processing */
void PostProcessing::OnSetConstants(video::IMaterialRendererServices *services,
s32 user_data)
void PostProcessing::drawQuad(u32 cam, const SMaterial &mat)
{
// We need the maximum texture coordinates:
float max_tex_height = m_vertices[m_current_camera].v1.TCoords.Y;
services->setPixelShaderConstant("max_tex_height", &max_tex_height, 1);
const u16 indices[6] = {0, 1, 2, 3, 0, 2};
IVideoDriver * const drv = irr_driver->getVideoDriver();
// Scale the boost time to get a usable boost amount:
float boost_amount = m_boost_time[m_current_camera] * 0.7f;
drv->setTransform(ETS_WORLD, core::IdentityMatrix);
drv->setTransform(ETS_VIEW, core::IdentityMatrix);
drv->setTransform(ETS_PROJECTION, core::IdentityMatrix);
// Especially for single screen the top of the screen is less blurred
// in the fragment shader by multiplying the blurr factor by
// (max_tex_height - texcoords.t), where max_tex_height is the maximum
// texture coordinate (1.0 or 0.5). In split screen this factor is too
// small (half the value compared with non-split screen), so we
// multiply this by 2.
if(m_boost_time.size()>1)
boost_amount *= 2.0f;
services->setPixelShaderConstant("boost_amount", &boost_amount, 1);
services->setPixelShaderConstant("center",
&(m_center[m_current_camera].X), 2);
services->setPixelShaderConstant("direction",
&(m_direction[m_current_camera].X), 2);
// Use a radius of 0.15 when showing a single kart, otherwise (2-4 karts
// on splitscreen) use only 0.75.
float radius = Camera::getNumCameras()==1 ? 0.15f : 0.075f;
services->setPixelShaderConstant("mask_radius", &radius, 1);
const int texunit = 0;
services->setPixelShaderConstant("color_buffer", &texunit, 1);
} // OnSetConstants
drv->setMaterial(mat);
drv->drawIndexedTriangleList(&(m_vertices[cam].v0),
4, indices, 2);
}

View File

@ -1,6 +1,5 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011-2013 the SuperTuxKart team
// Copyright (C) 2013 Joerg Henrichs
// Copyright (C) 2011-2013 the SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -34,61 +33,58 @@ using namespace irr;
/** \brief Handles post processing, eg motion blur
* \ingroup graphics
*/
class PostProcessing : public video::IShaderConstantSetCallBack
class PostProcessing: public IReferenceCounted
{
private:
video::ITexture *m_render_target;
/** Material to be used when blurring is used. */
video::SMaterial m_blur_material;
bool m_supported;
video::SMaterial m_material;
/** Boost time, how long the boost should be displayed. This also
* affects the strength of the effect: longer boost time will
* have a stronger effect. */
std::vector<float> m_boost_time;
bool m_any_boost;
/** The center of blurring, in texture coordinates [0,1]).*/
std::vector<core::vector2df> m_center;
/** The center to which the blurring is aimed at, in [0,1]. */
std::vector<core::vector2df> m_direction;
/** True if any of the cameras is using post processing. */
bool m_used_pp_this_frame;
/** Currently active camera during post-processing, needed in the
* OnSetConstants callback. */
unsigned int m_current_camera;
struct Quad { video::S3DVertex v0, v1, v2, v3; };
/** The vertices for the rectangle used for each camera. This includes
* the vertex position, normal, and texture coordinate. */
std::vector<Quad> m_vertices;
video::ITexture *m_areamap;
u32 m_sunpixels;
void setMotionBlurCenterY(const u32 num, const float y);
public:
PostProcessing(video::IVideoDriver* video_driver);
virtual ~PostProcessing();
void reset();
/** Those should be called around the part where we render the scene to be post-processed */
void beginCapture();
void endCapture();
void begin();
void update(float dt);
/** Render the post-processed scene, solids only, color to color, no stencil */
void renderSolid(const u32 cam);
/** Render the post-processed scene */
void render();
/** Is the hardware able to use post-processing? */
inline bool isSupported() const {return m_supported;}
/** Draw the quad for this camera */
void drawQuad(u32 cam, const video::SMaterial &mat);
/** Use motion blur for a short time */
void giveBoost(unsigned int cam_index);
/** Implement IShaderConstantsSetCallback. Shader constants setter for post-processing */
virtual void OnSetConstants(video::IMaterialRendererServices *services, s32 user_data);
void setSunPixels(const u32 in) { m_sunpixels = in; }
};
#endif // HEADER_POST_PROCESSING_HPP

Some files were not shown because too many files have changed in this diff Show More