This commit is contained in:
Arthur-D 2014-10-22 22:14:20 +02:00
commit e7ef83aea8
88 changed files with 2184 additions and 1457 deletions

View File

@ -10,7 +10,7 @@
* Added Tutorial
* Added new Supertux difficulty
* New bubblegum shield weapon
* New Speeodmeter and nitro meter
* New Speedometer and nitro meter
* Add ability to filter addons
* Updated nitro models
* Add ability to save and resume Grand Prix

View File

@ -33,6 +33,12 @@
<label height="100%" I18N="In the ui settings" text="Display FPS"/>
</div>
<div width="75%" height="fit" layout="horizontal-row" >
<checkbox id="show-login"/>
<spacer width="20" height="100%" />
<label height="100%" I18N="In the ui settings" text="Always show login screen"/>
</div>
<div width="75%" height="fit" layout="horizontal-row" >
<checkbox id="enable-internet"/>
<spacer width="20" height="100%" />
@ -40,9 +46,10 @@
</div>
<div width="75%" height="fit" layout="horizontal-row" >
<checkbox id="show-login"/>
<checkbox id="enable-hw-report"/>
<spacer width="20" height="100%" />
<label height="100%" I18N="In the ui settings" text="Always show login screen"/>
<label id="label-hw-report" height="100%" I18N="In the ui settings"
text="Allow STK to send anonymous HW statistics"/>
</div>
<spacer height="18" width="4"/>

View File

@ -2,7 +2,7 @@
<stkgui>
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row" >
<header id="title" width="80%" text="Race Setup" align="center" text_align="center" />
<header id="title" width="100%" text="Race Setup" align="center" text_align="center" />
<spacer height="2%" width="1"/>

View File

@ -15,13 +15,15 @@
<spacer height="15" width="10"/>
<div width="90%" align="center" layout="vertical-row" height="fit">
<div width="100%" height="fit" layout="horizontal-row" >
<label width="40%" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
<checkbox width="fit" id="online" I18N="In the login screen" text_align="left"/>
<spacer width="10"/>
<label proportion="1" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<label width="40%" id="label_remember" height="100%" text_align="left"
I18N="In the login screen" text="Remember password"/>
<checkbox width="fit" id="remember-user" I18N="In the login screen" text_align="left"/>
<spacer width="10"/>
<label proportion="1" id="label_remember" height="100%" text_align="left"
I18N="In the login screen" text="Remember password"/>
</div>
<!-- Disable guest accounts for now
<div width="100%" height="fit" layout="horizontal-row" >

View File

@ -24,13 +24,15 @@
<spacer height="15" width="10"/>
<div width="90%" align="center" layout="vertical-row" height="fit">
<div width="100%" height="fit" layout="horizontal-row" >
<label width="40%" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
<checkbox width="fit" id="online" I18N="In the login screen" text_align="left"/>
<spacer width="10"/>
<label proportion="1" height="100%" text_align="left" I18N="In the login screen" text="Online"/>
</div>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="label_remember" width="40%" height="100%" text_align="left"
I18N="In the login screen" text="Remember password"/>
<checkbox width="fit" id="remember-user" I18N="In the login screen" text_align="left"/>
<spacer width="10"/>
<label id="label_remember" proportion="1" height="100%" text_align="left"
I18N="In the login screen" text="Remember password"/>
</div>
<!-- Disable guest accounts for now
<div width="100%" height="fit" layout="horizontal-row" >

View File

@ -50,7 +50,9 @@ void main(void)
sampleDirection = (InverseViewMatrix * vec4(sampleDirection, 0.)).xyz;
float specval = texture(ntex, uv).z;
float lodval = 16 * (1. - ((log2(specval) - 1.) / 10.));
// From http://graphics.cs.williams.edu/papers/EnvMipReport2013/
int texSize = textureSize(tex, 0).x;
float lodval = log2(texSize * sqrt(3)) - .5 * log2(specval + 1);
vec4 specular = textureLod(tex, sampleDirection, lodval);
Spec = max(specular, vec4(0.));
}

View File

@ -0,0 +1,30 @@
#if __VERSION__ >= 330
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 Normal;
layout(location = 2) in vec4 Color;
layout(location = 3) in vec2 Texcoord;
layout(location = 4) in vec2 SecondTexcoord;
layout(location = 5) in vec3 Tangent;
layout(location = 6) in vec3 Bitangent;
#else
in vec3 Position;
in vec3 Normal;
in vec4 Color;
in vec2 Texcoord;
in vec2 SecondTexcoord;
in vec3 Tangent;
in vec3 Bitangent;
#endif
out vec2 uv;
out vec4 color;
void main(void)
{
color = Color.zyxw;
vec3 P = Position / vec3(screen, 1.);
P = 2. * P - 1.;
P.y *= -1;
gl_Position = vec4(P, 1.);
uv = Texcoord;
}

View File

@ -30,13 +30,16 @@
class DummySFX : public SFXBase
{
public:
DummySFX(SFXBuffer* buffer, bool positional, float gain) {}
DummySFX(SFXBuffer* buffer, bool positional,
float gain) {}
virtual ~DummySFX() {}
/** Late creation, if SFX was initially disabled */
virtual bool init() { return true; }
virtual bool init() { return true; }
virtual bool isLooped() { return false; }
virtual void updatePlayingSFX(float dt) {}
virtual void setLoop(bool status) {}
virtual void reallySetLoop(bool status) {}
virtual void setPosition(const Vec3 &p) {}
virtual void reallySetPosition(const Vec3 &p) {}
virtual void play() {}
@ -52,10 +55,11 @@ public:
virtual void reallySetSpeed(float factor) {}
virtual void setVolume(float gain) {}
virtual void reallySetVolume(float gain) {}
virtual void setMasterVolume(float gain) {}
virtual void reallySetMasterVolumeNow(float gain) {}
virtual SFXStatus getStatus() { return SFX_STOPPED; }
virtual void onSoundEnabledBack() {}
virtual void setRolloff(float rolloff) {}
virtual bool isPlaying() { return false; }
virtual const SFXBuffer* getBuffer() const { return NULL; }
}; // DummySFX

View File

@ -46,35 +46,38 @@ public:
enum SFXStatus
{
SFX_UNKNOWN = -1, SFX_STOPPED = 0, SFX_PAUSED = 1, SFX_PLAYING = 2,
SFX_INITIAL = 3
SFX_NOT_INITIALISED = 3
};
virtual ~SFXBase() {}
/** Late creation, if SFX was initially disabled */
virtual bool init() = 0;
virtual void setPosition(const Vec3 &p) = 0;
virtual void reallySetPosition(const Vec3 &p) = 0;
virtual void setLoop(bool status) = 0;
virtual bool isPlaying() = 0;
virtual void play() = 0;
virtual void reallyPlayNow() = 0;
virtual void stop() = 0;
virtual void reallyStopNow() = 0;
virtual void pause() = 0;
virtual void reallyPauseNow() = 0;
virtual void resume() = 0;
virtual void reallyResumeNow() = 0;
virtual void deleteSFX() = 0;
virtual void setSpeed(float factor) = 0;
virtual void reallySetSpeed(float factor) = 0;
virtual void setVolume(float gain) = 0;
virtual void reallySetVolume(float gain) = 0;
virtual void setMasterVolume(float gain) = 0;
virtual void onSoundEnabledBack() = 0;
virtual void setRolloff(float rolloff) = 0;
virtual const SFXBuffer* getBuffer() const = 0;
virtual SFXStatus getStatus() = 0;
virtual bool init() = 0;
virtual bool isLooped() = 0;
virtual void updatePlayingSFX(float dt) = 0;
virtual void setPosition(const Vec3 &p) = 0;
virtual void reallySetPosition(const Vec3 &p) = 0;
virtual void setLoop(bool status) = 0;
virtual void reallySetLoop(bool status) = 0;
virtual void play() = 0;
virtual void reallyPlayNow() = 0;
virtual void stop() = 0;
virtual void reallyStopNow() = 0;
virtual void pause() = 0;
virtual void reallyPauseNow() = 0;
virtual void resume() = 0;
virtual void reallyResumeNow() = 0;
virtual void deleteSFX() = 0;
virtual void setSpeed(float factor) = 0;
virtual void reallySetSpeed(float factor) = 0;
virtual void setVolume(float gain) = 0;
virtual void reallySetVolume(float gain) = 0;
virtual void setMasterVolume(float gain) = 0;
virtual void reallySetMasterVolumeNow(float gain) = 0;
virtual void onSoundEnabledBack() = 0;
virtual void setRolloff(float rolloff) = 0;
virtual const SFXBuffer* getBuffer() const = 0;
virtual SFXStatus getStatus() = 0;
}; // SFXBase

View File

@ -74,7 +74,10 @@ SFXManager::SFXManager()
m_initialized = music_manager->initialized();
m_master_gain = UserConfigParams::m_sfx_volume;
// Init position, since it can be used before positionListener is called.
m_position = Vec3(0,0,0);
// No need to use lock here, since the thread will be created later.
m_listener_position.getData() = Vec3(0, 0, 0);
m_listener_front = Vec3(0, 0, 1);
m_listener_up = Vec3(0, 1, 0);
loadSfx();
@ -98,13 +101,11 @@ SFXManager::SFXManager()
delete m_thread_id.getData();
m_thread_id.unlock();
m_thread_id.setAtomic(0);
Log::error("HTTP Manager", "Could not create thread, error=%d.",
Log::error("SFXManager", "Could not create thread, error=%d.",
errno);
}
pthread_attr_destroy(&attr);
if (!sfxAllowed()) return;
setMasterSFXVolume( UserConfigParams::m_sfx_volume );
m_sfx_commands.lock();
m_sfx_commands.getData().clear();
@ -208,10 +209,25 @@ void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p)
void SFXManager::queueCommand(SFXCommand *command)
{
m_sfx_commands.lock();
if(m_sfx_commands.getData().size() > 20*race_manager->getNumberOfKarts()+20)
{
if(command->m_command==SFX_POSITION || command->m_command==SFX_LOOP ||
command->m_command==SFX_PLAY || command->m_command==SFX_SPEED )
{
delete command;
static int count_messages = 0;
if(count_messages < 5)
{
Log::warn("SFXManager", "Throttling sfx - queue size %d",
m_sfx_commands.getData().size());
count_messages++;
}
m_sfx_commands.unlock();
return;
} // if throttling
}
m_sfx_commands.getData().push_back(command);
m_sfx_commands.unlock();
// Wake up the sfx thread
pthread_cond_signal(&m_cond_request);
} // queueCommand
//----------------------------------------------------------------------------
@ -220,7 +236,9 @@ void SFXManager::queueCommand(SFXCommand *command)
*/
void SFXManager::stopThread()
{
queue(SFX_EXIT, NULL);
queue(SFX_EXIT);
// Make sure the thread wakes up.
pthread_cond_signal(&m_cond_request);
} // stopThread
//----------------------------------------------------------------------------
@ -251,31 +269,36 @@ void* SFXManager::mainLoop(void *obj)
pthread_cond_wait(&me->m_cond_request, me->m_sfx_commands.getMutex());
empty = me->m_sfx_commands.getData().empty();
}
SFXCommand *current = me->m_sfx_commands.getData().front();
me->m_sfx_commands.getData().erase(me->m_sfx_commands.getData().begin());
if (current->m_command == SFX_EXIT)
break;
me->m_sfx_commands.unlock();
switch(current->m_command)
{
case SFX_PLAY: current->m_sfx->reallyPlayNow(); break;
case SFX_STOP: current->m_sfx->reallyStopNow(); break;
case SFX_PAUSE: current->m_sfx->reallyPauseNow(); break;
case SFX_RESUME: current->m_sfx->reallyResumeNow(); break;
case SFX_SPEED: current->m_sfx->reallySetSpeed(
case SFX_PLAY: current->m_sfx->reallyPlayNow(); break;
case SFX_STOP: current->m_sfx->reallyStopNow(); break;
case SFX_PAUSE: current->m_sfx->reallyPauseNow(); break;
case SFX_RESUME: current->m_sfx->reallyResumeNow(); break;
case SFX_SPEED: current->m_sfx->reallySetSpeed(
current->m_parameter.getX()); break;
case SFX_POSITION: current->m_sfx->reallySetPosition(
current->m_parameter); break;
case SFX_VOLUME: current->m_sfx->reallySetVolume(
case SFX_VOLUME: current->m_sfx->reallySetVolume(
current->m_parameter.getX()); break;
case SFX_DELETE: {
current->m_sfx->reallyStopNow();
me->deleteSFX(current->m_sfx);
break;
}
case SFX_MASTER_VOLUME:
current->m_sfx->reallySetMasterVolumeNow(
current->m_parameter.getX()); break;
case SFX_LOOP: current->m_sfx->reallySetLoop(
current->m_parameter.getX()!=0); break;
case SFX_DELETE: {
me->deleteSFX(current->m_sfx); break;
}
case SFX_PAUSE_ALL: me->reallyPauseAllNow(); break;
case SFX_RESUME_ALL: me->reallyResumeAllNow(); break;
case SFX_LISTENER: me->reallyPositionListenerNow(); break;
case SFX_UPDATE: me->reallyUpdateNow(current); break;
default: assert("Not yet supported.");
}
delete current;
@ -298,7 +321,7 @@ void* SFXManager::mainLoop(void *obj)
* resumes all sound effects.
* \param on If sound is switched on or off.
*/
void SFXManager::soundToggled(const bool on)
void SFXManager::toggleSound(const bool on)
{
// When activating SFX, load all buffers
if (on)
@ -310,7 +333,7 @@ void SFXManager::soundToggled(const bool on)
buffer->load();
}
resumeAll();
reallyResumeAllNow();
m_all_sfx.lock();
const int sfx_amount = (int)m_all_sfx.getData().size();
for (int n=0; n<sfx_amount; n++)
@ -321,9 +344,20 @@ void SFXManager::soundToggled(const bool on)
}
else
{
// First stop all sfx that are not looped
const int sfx_amount = (int)m_all_sfx.getData().size();
m_all_sfx.lock();
for (int i=0; i<sfx_amount; i++)
{
if(!m_all_sfx.getData()[i]->isLooped())
{
m_all_sfx.getData()[i]->reallyStopNow();
}
}
m_all_sfx.unlock();
pauseAll();
}
}
} // toggleSound
//----------------------------------------------------------------------------
/** Returns if sfx can be played. This means sfx are enabled and
@ -423,7 +457,7 @@ SFXBuffer* SFXManager::addSingleSfx(const std::string &sfx_name,
}
if (UserConfigParams::logMisc())
Log::debug("SFXManager", "Loading SFX %s\n", sfx_file.c_str());
Log::debug("SFXManager", "Loading SFX %s", sfx_file.c_str());
if (load && buffer->load()) return buffer;
@ -443,7 +477,7 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
if (node->get("filename", &filename) == 0)
{
Log::error("SFXManager",
"/!\\ The 'filename' attribute is mandatory in the SFX XML file!\n");
"The 'filename' attribute is mandatory in the SFX XML file!");
return NULL;
}
@ -452,7 +486,7 @@ SFXBuffer* SFXManager::loadSingleSfx(const XMLNode* node,
if(m_all_sfx_types.find(sfx_name)!=m_all_sfx_types.end())
{
Log::error("SFXManager",
"There is already a sfx named '%s' installed - new one is ignored.\n",
"There is already a sfx named '%s' installed - new one is ignored.",
sfx_name.c_str());
return NULL;
}
@ -507,8 +541,6 @@ SFXBase* SFXManager::createSoundSource(SFXBuffer* buffer,
m_all_sfx.getData().push_back(sfx);
m_all_sfx.unlock();
}
else
printf("");
return sfx;
} // createSoundSource
@ -522,7 +554,7 @@ SFXBase* SFXManager::createSoundSource(const std::string &name,
{
Log::error("SFXManager",
"SFXManager::createSoundSource could not find the "
"requested sound effect : '%s'\n", name.c_str());
"requested sound effect : '%s'.", name.c_str());
return NULL;
}
@ -560,6 +592,38 @@ void SFXManager::deleteSFXMapping(const std::string &name)
} // deleteSFXMapping
//----------------------------------------------------------------------------
/** Make sures that the sfx thread is started at least one per frame. It also
* adds an update command for the music manager.
* \param dt Time step size.
*/
void SFXManager::update(float dt)
{
queue(SFX_UPDATE, NULL, dt);
// Wake up the sfx thread to handle all queued up audio commands.
pthread_cond_signal(&m_cond_request);
} // update
//----------------------------------------------------------------------------
/** Updates the status of all playing sfx (to test if they are finished).
* This function is executed once per thread (triggered by the
*/
void SFXManager::reallyUpdateNow(SFXCommand *current)
{
assert(current->m_command==SFX_UPDATE);
float dt = current->m_parameter.getX();
music_manager->update(dt);
m_all_sfx.lock();
for (std::vector<SFXBase*>::iterator i = m_all_sfx.getData().begin();
i != m_all_sfx.getData().end(); i++)
{
if((*i)->getStatus()==SFXBase::SFX_PLAYING)
(*i)->updatePlayingSFX(dt);
} // for i in m_all_sfx
m_all_sfx.unlock();
} // reallyUpdateNow
//----------------------------------------------------------------------------
/** Delete a sound effect object, and removes it from the internal list of
* all SFXs. This call deletes the object, and removes it from the list of
@ -581,45 +645,63 @@ void SFXManager::deleteSFX(SFXBase *sfx)
Log::warn("SFXManager",
"SFXManager::deleteSFX : Warning: sfx '%s' %lx not found in list.",
sfx->getBuffer()->getFileName().c_str(), sfx);
m_all_sfx.unlock();
return;
}
m_all_sfx.getData().erase(i);
delete sfx;
m_all_sfx.unlock();
delete sfx;
} // deleteSFX
//----------------------------------------------------------------------------
/** Pauses all looping SFXs. Non-looping SFX will be finished, since it's
* otherwise not possible to determine which SFX must be resumed (i.e. were
* actually playing at the time pause was called).
*/
void SFXManager::pauseAll()
{
if (!sfxAllowed()) return;
queue(SFX_PAUSE_ALL);
} // pauseAll
//----------------------------------------------------------------------------
/** Pauses all looping SFXs. Non-looping SFX will be finished, since it's
* otherwise not possible to determine which SFX must be resumed (i.e. were
* actually playing at the time pause was called.
*/
void SFXManager::pauseAll()
void SFXManager::reallyPauseAllNow()
{
m_all_sfx.lock();
for (std::vector<SFXBase*>::iterator i= m_all_sfx.getData().begin();
i!=m_all_sfx.getData().end(); i++)
{
(*i)->pause();
(*i)->reallyPauseNow();
} // for i in m_all_sfx
m_all_sfx.unlock();
} // pauseAll
//----------------------------------------------------------------------------
/**
* Resumes all paused SFXs. If sound is disabled, does nothing.
/** Resumes all paused SFXs. If sound is disabled, does nothing.
*/
void SFXManager::resumeAll()
{
// ignore unpausing if sound is disabled
if (!sfxAllowed()) return;
queue(SFX_RESUME_ALL);
} // resumeAll
//----------------------------------------------------------------------------
/** Resumes all paused SFXs. If sound is disabled, does nothing.
*/
void SFXManager::reallyResumeAllNow()
{
m_all_sfx.lock();
for (std::vector<SFXBase*>::iterator i =m_all_sfx.getData().begin();
i!=m_all_sfx.getData().end(); i++)
{
(*i)->resume();
(*i)->reallyResumeNow();
} // for i in m_all_sfx
m_all_sfx.unlock();
} // resumeAll
@ -702,28 +784,51 @@ const std::string SFXManager::getErrorString(int err)
/** Sets the position and orientation of the listener.
* \param position Position of the listener.
* \param front Which way the listener is facing.
* \param up The up direction of the listener.
*/
void SFXManager::positionListener(const Vec3 &position, const Vec3 &front)
void SFXManager::positionListener(const Vec3 &position, const Vec3 &front,
const Vec3 &up)
{
m_listener_position.lock();
m_listener_position.getData() = position;
m_listener_front = front;
m_listener_up = up;
m_listener_position.unlock();
queue(SFX_LISTENER);
} // positionListener
//-----------------------------------------------------------------------------
/** Sets the position and orientation of the listener.
* \param position Position of the listener.
* \param front Which way the listener is facing.
*/
void SFXManager::reallyPositionListenerNow()
{
#if HAVE_OGGVORBIS
if (!UserConfigParams::m_sfx || !m_initialized) return;
m_position = position;
m_listener_position.lock();
{
//forward vector
m_listenerVec[0] = front.getX();
m_listenerVec[1] = front.getY();
m_listenerVec[2] = front.getZ();
//forward vector
float orientation[6];
orientation[0] = m_listener_front.getX();
orientation[1] = m_listener_front.getY();
orientation[2] = -m_listener_front.getZ();
//up vector
m_listenerVec[3] = 0;
m_listenerVec[4] = 0;
m_listenerVec[5] = 1;
//up vector
orientation[3] = m_listener_up.getX();
orientation[4] = m_listener_up.getY();
orientation[5] = -m_listener_up.getZ();
const Vec3 &pos = m_listener_position.getData();
alListener3f(AL_POSITION, pos.getX(), pos.getY(), -pos.getZ());
alListenerfv(AL_ORIENTATION, orientation);
}
m_listener_position.unlock();
alListener3f(AL_POSITION, position.getX(), position.getY(), position.getZ());
alListenerfv(AL_ORIENTATION, m_listenerVec);
#endif
}
} // reallyPositionListenerNow
//-----------------------------------------------------------------------------
/** Positional sound is cool, but creating a new object just to play a simple

View File

@ -65,11 +65,17 @@ public:
SFX_PLAY = 1,
SFX_STOP,
SFX_PAUSE,
SFX_PAUSE_ALL,
SFX_RESUME,
SFX_RESUME_ALL,
SFX_DELETE,
SFX_SPEED,
SFX_POSITION,
SFX_VOLUME,
SFX_MASTER_VOLUME,
SFX_LOOP,
SFX_LISTENER,
SFX_UPDATE,
SFX_EXIT,
}; // SFXCommands
@ -129,8 +135,17 @@ private:
} // SFXCommand(Vec3)
}; // SFXCommand
// ========================================================================
/** Listener position */
Vec3 m_position;
/** The position of the listener. Its lock will be used to
* access m_listener_{position,front, up}. */
Synchronised<Vec3> m_listener_position;
/** The direction the listener is facing. */
Vec3 m_listener_front;
/** Up vector of the listener. */
Vec3 m_listener_up;
/** The buffers and info for all sound effects. These are shared among all
* instances of SFXOpenal. */
@ -145,9 +160,6 @@ private:
/** To play non-positional sounds without having to create a new object for each */
std::map<std::string, SFXBase*> m_quick_sounds;
/** listener vector (position vector + up vector) */
float m_listenerVec[6];
/** If the sfx manager has been initialised. */
bool m_initialized;
@ -167,10 +179,12 @@ private:
static void* mainLoop(void *obj);
void deleteSFX(SFXBase *sfx);
void queueCommand(SFXCommand *command);
void reallyPositionListenerNow();
public:
static void create();
static void destroy();
void queue(SFXCommands command, SFXBase *sfx);
void queue(SFXCommands command, SFXBase *sfx=NULL);
void queue(SFXCommands command, SFXBase *sfx, float f);
void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p);
// ------------------------------------------------------------------------
@ -196,14 +210,18 @@ public:
const bool load = true);
SFXBase* createSoundSource(SFXBuffer* info,
const bool addToSFXList=true,
const bool add_to_SFX_list=true,
const bool owns_buffer=false);
SFXBase* createSoundSource(const std::string &name,
const bool addToSFXList=true);
void deleteSFXMapping(const std::string &name);
void pauseAll();
void reallyPauseAllNow();
void resumeAll();
void reallyResumeAllNow();
void update(float dt);
void reallyUpdateNow(SFXCommand *current);
bool soundExist(const std::string &name);
void setMasterSFXVolume(float gain);
float getMasterSFXVolume() const { return m_master_gain; }
@ -211,11 +229,12 @@ public:
static bool checkError(const std::string &context);
static const std::string getErrorString(int err);
void positionListener(const Vec3 &position, const Vec3 &front);
void positionListener(const Vec3 &position,
const Vec3 &front, const Vec3 &up);
SFXBase* quickSound(const std::string &soundName);
/** Called when sound was muted/unmuted */
void soundToggled(const bool newValue);
void toggleSound(const bool newValue);
// ------------------------------------------------------------------------
/** Prints the list of currently loaded sounds to stdout. Useful to
@ -224,7 +243,7 @@ public:
// ------------------------------------------------------------------------
/** Returns the current position of the listener. */
Vec3 getListenerPos() const { return m_position; }
Vec3 getListenerPos() const { return m_listener_position.getData(); }
};

View File

@ -1,7 +1,8 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006-2013 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2009-2013 Marianne Gagnon
// Copyright (C) 2014 Joerg Henrichs
// Copyright (C) 2006-2014 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2009-2014 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@ -37,19 +38,20 @@
#include <stdio.h>
#include <string>
SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain, bool owns_buffer) : SFXBase()
SFXOpenAL::SFXOpenAL(SFXBuffer* buffer, bool positional, float gain,
bool owns_buffer)
: SFXBase()
{
m_sound_buffer = buffer;
m_sound_source = 0;
m_status = SFX_UNKNOWN;
m_is_playing = false;
m_status = SFX_NOT_INITIALISED;
m_positional = positional;
m_defaultGain = gain;
m_default_gain = gain;
m_loop = false;
m_gain = -1.0f;
m_master_gain = 1.0f;
m_owns_buffer = owns_buffer;
m_end_time = -1.0f;
m_play_time = 0.0f;
// Don't initialise anything else if the sfx manager was not correctly
// initialised. First of all the initialisation will not work, and it
@ -78,11 +80,15 @@ SFXOpenAL::~SFXOpenAL()
} // ~SFXOpenAL
//-----------------------------------------------------------------------------
/** Initialises the sfx.
*/
bool SFXOpenAL::init()
{
m_status = SFX_UNKNOWN;
alGenSources(1, &m_sound_source );
if (!SFXManager::checkError("generating a source")) return false;
if (!SFXManager::checkError("generating a source"))
return false;
assert( alIsBuffer(m_sound_buffer->getBufferID()) );
assert( alIsSource(m_sound_source) );
@ -101,7 +107,7 @@ bool SFXOpenAL::init()
if (m_gain < 0.0f)
{
alSourcef (m_sound_source, AL_GAIN, m_defaultGain * m_master_gain);
alSourcef (m_sound_source, AL_GAIN, m_default_gain * m_master_gain);
}
else
{
@ -113,27 +119,26 @@ bool SFXOpenAL::init()
alSourcei(m_sound_source, AL_LOOPING, m_loop ? AL_TRUE : AL_FALSE);
if(SFXManager::checkError("setting up the source"))
m_status = SFX_INITIAL;
if(!SFXManager::checkError("setting up the source"))
return false;
return m_status==SFX_INITIAL;
m_status = SFX_STOPPED;
return true;
} // init
// ------------------------------------------------------------------------
/** Returns the status of this sfx. */
SFXBase::SFXStatus SFXOpenAL::getStatus()
/** Updates the status of a playing sfx. If the sound has been played long
* enough, mark it to be finished. This avoid (a potentially costly)
* call to openal.
* \param dt Time step size.
*/
void SFXOpenAL::updatePlayingSFX(float dt)
{
if(m_status==SFX_PLAYING)
{
if(m_loop) return SFX_PLAYING;
if(World::getWorld() && World::getWorld()->getTime() > m_end_time)
{
m_status = SFX_STOPPED;
return m_status;
}
}
return m_status;
} // getStatus;
assert(m_status==SFX_PLAYING);
m_play_time += dt;
if(!m_loop && m_play_time > m_sound_buffer->getDuration())
m_status = SFX_STOPPED;
} // updatePlayingSFX
//-----------------------------------------------------------------------------
/** Queues up a change of the pitch of a sound effect to the sfx manager.
@ -141,7 +146,7 @@ SFXBase::SFXStatus SFXOpenAL::getStatus()
*/
void SFXOpenAL::setSpeed(float factor)
{
if(m_status==SFX_UNKNOWN) return;
if(m_status==SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
assert(!isnan(factor));
SFXManager::get()->queue(SFXManager::SFX_SPEED, this, factor);
} // setSpeed
@ -152,7 +157,13 @@ void SFXOpenAL::setSpeed(float factor)
*/
void SFXOpenAL::reallySetSpeed(float factor)
{
if(m_status==SFX_UNKNOWN) return;
if(m_status==SFX_NOT_INITIALISED)
{
init();
if(m_status==SFX_UNKNOWN)
return;
}
//OpenAL only accepts pitches in the range of 0.5 to 2.0
if(factor > 2.0f)
{
@ -171,7 +182,7 @@ void SFXOpenAL::reallySetSpeed(float factor)
*/
void SFXOpenAL::setVolume(float gain)
{
if(m_status==SFX_UNKNOWN) return;
if(m_status==SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
assert(!isnan(gain)) ;
SFXManager::get()->queue(SFXManager::SFX_VOLUME, this, gain);
} // setVolume
@ -182,60 +193,97 @@ void SFXOpenAL::setVolume(float gain)
*/
void SFXOpenAL::reallySetVolume(float gain)
{
if(m_status==SFX_UNKNOWN) return;
m_gain = m_defaultGain * gain;
m_gain = m_default_gain * gain;
if(m_status==SFX_UNKNOWN) return;
if(m_status==SFX_NOT_INITIALISED)
{
init();
if(m_status==SFX_UNKNOWN)
return;
}
alSourcef(m_sound_source, AL_GAIN, m_gain * m_master_gain);
} // reallySetVolume
//-----------------------------------------------------------------------------
/** Schedules setting of the master volume.
* \param gain Gain value.
*/
void SFXOpenAL::setMasterVolume(float gain)
{
// This needs to be called even if sfx are disabled atm, so only exit
// in case that the sfx could not be loaded in the first place.
if(m_status==SFX_UNKNOWN) return;
SFXManager::get()->queue(SFXManager::SFX_MASTER_VOLUME, this, gain);
} // setMasterVolume
//-----------------------------------------------------------------------------
/** Sets the master volume.
* \param gain Master volume.
*/
void SFXOpenAL::reallySetMasterVolumeNow(float gain)
{
m_master_gain = gain;
if(m_status==SFX_UNKNOWN) return;
if(m_status==SFX_UNKNOWN || m_status == SFX_NOT_INITIALISED) return;
alSourcef(m_sound_source, AL_GAIN,
(m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
(m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
SFXManager::checkError("setting volume");
} //setMasterVolume
} // reallySetMasterVolumeNow
//-----------------------------------------------------------------------------
/** Loops this sound effect.
*/
void SFXOpenAL::setLoop(bool status)
{
// Set the flag (even if sfx are disabled), so that the right settings
// are available on restart.
m_loop = status;
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
SFXManager::get()->queue(SFXManager::SFX_LOOP, this, status ? 1.0f : 0.0f);
} // setLoop
if(m_status==SFX_UNKNOWN) return;
//-----------------------------------------------------------------------------
/** Loops this sound effect.
*/
void SFXOpenAL::reallySetLoop(bool status)
{
if(m_status==SFX_NOT_INITIALISED)
{
init();
if(m_status==SFX_UNKNOWN)
return;
}
alSourcei(m_sound_source, AL_LOOPING, status ? AL_TRUE : AL_FALSE);
SFXManager::checkError("looping");
} // loop
} // reallySetLoop
//-----------------------------------------------------------------------------
/** Queues a stop for this effect to the sound manager.
*/
void SFXOpenAL::stop()
{
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
SFXManager::get()->queue(SFXManager::SFX_STOP, this);
} // stop
//-----------------------------------------------------------------------------
/** The sfx manager thread executes a stop for this sfx.
*/
void SFXOpenAL::reallyStopNow()
{
if(m_status==SFX_UNKNOWN) return;
m_is_playing = false;
m_status = SFX_STOPPED;
m_loop = false;
alSourcei(m_sound_source, AL_LOOPING, AL_FALSE);
alSourceStop(m_sound_source);
SFXManager::checkError("stoping");
if(m_status==SFX_PLAYING || m_status==SFX_PAUSED)
{
m_status = SFX_STOPPED;
m_loop = false;
alSourcei(m_sound_source, AL_LOOPING, AL_FALSE);
alSourceStop(m_sound_source);
SFXManager::checkError("stoping");
}
} // reallyStopNow
//-----------------------------------------------------------------------------
@ -252,7 +300,9 @@ void SFXOpenAL::pause()
*/
void SFXOpenAL::reallyPauseNow()
{
if(m_status==SFX_UNKNOWN) return;
// Need to be tested again here, since this function can be called
// from pauseAll, and we have to make sure to only pause playing sfx.
if (m_status != SFX_PLAYING || !SFXManager::get()->sfxAllowed()) return;
m_status = SFX_PAUSED;
alSourcePause(m_sound_source);
SFXManager::checkError("pausing");
@ -263,6 +313,7 @@ void SFXOpenAL::reallyPauseNow()
*/
void SFXOpenAL::resume()
{
if (m_status != SFX_PLAYING || !SFXManager::get()->sfxAllowed()) return;
SFXManager::get()->queue(SFXManager::SFX_RESUME, this);
} // resume
@ -271,13 +322,11 @@ void SFXOpenAL::resume()
*/
void SFXOpenAL::reallyResumeNow()
{
if (m_status==SFX_UNKNOWN)
if(m_status==SFX_NOT_INITIALISED)
{
// lazily create OpenAL source when needed
init();
// creation of OpenAL source failed, giving up
if (m_status==SFX_UNKNOWN) return;
if(m_status==SFX_UNKNOWN)
return;
}
if(m_status==SFX_PAUSED)
@ -288,6 +337,98 @@ void SFXOpenAL::reallyResumeNow()
}
} // reallyResumeNow
//-----------------------------------------------------------------------------
/** This actually queues up the sfx in the sfx manager. It will be started
* from a separate thread later (in this frame).
*/
void SFXOpenAL::play()
{
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
if(m_status==SFX_STOPPED)
m_play_time = 0.0f;
// Technically the sfx is only playing after the sfx thread starts it,
// but it is important to set this here since stk might decide to
// delete a sfx if it has finished playing (i.e. is in stopped state)
// - which can happen if the sfx thread had no time to actually start
// it yet.
m_status = SFX_PLAYING;
SFXManager::get()->queue(SFXManager::SFX_PLAY, this);
} // play
//-----------------------------------------------------------------------------
/** Plays this sound effect.
*/
void SFXOpenAL::reallyPlayNow()
{
if (!SFXManager::get()->sfxAllowed()) return;
if (m_status==SFX_NOT_INITIALISED)
{
// lazily create OpenAL source when needed
init();
// creation of OpenAL source failed, giving up
if (m_status==SFX_UNKNOWN) return;
}
alSourcePlay(m_sound_source);
SFXManager::checkError("playing");
} // reallyPlayNow
//-----------------------------------------------------------------------------
/** Sets the position where this sound effects is played.
* \param position Position of the sound effect.
*/
void SFXOpenAL::setPosition(const Vec3 &position)
{
if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return;
SFXManager::get()->queue(SFXManager::SFX_POSITION, this, position);
} // setPosition
//-----------------------------------------------------------------------------
/** Sets the position where this sound effects is played.
* \param position Position of the sound effect.
*/
void SFXOpenAL::reallySetPosition(const Vec3 &position)
{
if(m_status==SFX_NOT_INITIALISED)
{
init();
if(m_status==SFX_UNKNOWN)
return;
}
if (!m_positional)
{
// in multiplayer, all sounds are positional, so in this case don't
// bug users with an error message if (note that 0 players is also
// possible, in cutscenes)
if (race_manager->getNumLocalPlayers() < 2)
{
Log::warn("SFX", "Position called on non-positional SFX");
}
return;
}
alSource3f(m_sound_source, AL_POSITION, position.getX(),
position.getY(), -position.getZ());
if (SFXManager::get()->getListenerPos().distance(position)
> m_sound_buffer->getMaxDist())
{
alSourcef(m_sound_source, AL_GAIN, 0);
}
else
{
alSourcef(m_sound_source, AL_GAIN,
(m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
}
SFXManager::checkError("positioning");
} // reallySetPosition
//-----------------------------------------------------------------------------
/** Queues up a delete request for this object. This is necessary to avoid
* a crash if the sfx manager thread might be delayed and access this object
@ -298,118 +439,20 @@ void SFXOpenAL::deleteSFX()
SFXManager::get()->queue(SFXManager::SFX_DELETE, this);
} // deleteSFX
//-----------------------------------------------------------------------------
/** This actually queues up the sfx in the sfx manager. It will be started
* from a separate thread later (in this frame).
*/
void SFXOpenAL::play()
{
// Technically the sfx is only playing after the sfx thread starts it,
// but for STK this is correct since we don't want to start the same
// sfx twice.
m_is_playing = true;
SFXManager::get()->queue(SFXManager::SFX_PLAY, this);
} // play
//-----------------------------------------------------------------------------
/** Plays this sound effect.
*/
void SFXOpenAL::reallyPlayNow()
{
if (!SFXManager::get()->sfxAllowed()) return;
if (m_status==SFX_UNKNOWN)
{
// lazily create OpenAL source when needed
init();
// creation of OpenAL source failed, giving up
if (m_status==SFX_UNKNOWN) return;
}
alSourcePlay(m_sound_source);
m_status = SFX_PLAYING;
SFXManager::checkError("playing");
// At non-race time the end time is not important
if(World::getWorld())
m_end_time = World::getWorld()->getTime()+m_sound_buffer->getDuration();
else
m_end_time = 1.0f;
} // reallyPlayNow
//-----------------------------------------------------------------------------
/** Returns true if the sound effect is currently playing.
*/
bool SFXOpenAL::isPlaying()
{
return m_is_playing;
} // isPlaying
//-----------------------------------------------------------------------------
/** Sets the position where this sound effects is played.
* \param position Position of the sound effect.
*/
void SFXOpenAL::setPosition(const Vec3 &position)
{
if (m_status == SFX_UNKNOWN) return;
SFXManager::get()->queue(SFXManager::SFX_POSITION, this, position);
} // setPosition
//-----------------------------------------------------------------------------
/** Sets the position where this sound effects is played.
* \param position Position of the sound effect.
*/
void SFXOpenAL::reallySetPosition(const Vec3 &position)
{
if(!UserConfigParams::m_sfx)
return;
if (m_status==SFX_UNKNOWN)
{
Log::warn("SFX", "Position called on non-ok SFX <%s>",
m_sound_buffer->getFileName().c_str());
return;
}
if (!m_positional)
{
// in multiplayer, all sounds are positional, so in this case don't bug users with
// an error message if (race_manager->getNumLocalPlayers() > 1)
// (note that 0 players is also possible, in cutscenes)
if (race_manager->getNumLocalPlayers() < 2)
{
Log::warn("SFX", "Position called on non-positional SFX");
}
return;
}
alSource3f(m_sound_source, AL_POSITION,
(float)position.getX(), (float)position.getY(), (float)position.getZ());
if (SFXManager::get()->getListenerPos().distance(position) > m_sound_buffer->getMaxDist())
{
alSourcef(m_sound_source, AL_GAIN, 0);
}
else
{
alSourcef(m_sound_source, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
}
SFXManager::checkError("positioning");
} // reallySetPosition
//-----------------------------------------------------------------------------
void SFXOpenAL::onSoundEnabledBack()
{
if (m_loop)
{
if (m_status==SFX_UNKNOWN) init();
if (m_status==SFX_NOT_INITIALISED) init();
if (m_status!=SFX_UNKNOWN)
{
alSourcef(m_sound_source, AL_GAIN, 0);
play();
pause();
alSourcef(m_sound_source, AL_GAIN, (m_gain < 0.0f ? m_defaultGain : m_gain) * m_master_gain);
alSourcef(m_sound_source, AL_GAIN,
(m_gain < 0.0f ? m_default_gain : m_gain) * m_master_gain);
}
}
} // onSoundEnabledBack

View File

@ -48,8 +48,11 @@ private:
/** The status of this SFX. */
SFXStatus m_status;
/** If the sfx is positional. */
bool m_positional;
float m_defaultGain;
/** Default gain value. */
float m_default_gain;
/** The OpenAL source contains this info, but if audio is disabled initially then
the sound source won't be created and we'll be left with no clue when enabling
@ -62,9 +65,6 @@ private:
the sound source won't be created and we'll be left with no clue when enabling
sounds later. */
float m_gain;
/** True when the sfx is currently playing. */
bool m_is_playing;
/** The master gain set in user preferences */
float m_master_gain;
@ -72,20 +72,20 @@ private:
/** If this sfx should also free the sound buffer. */
bool m_owns_buffer;
/** Time at which a sfx ends playing. Used to avoid frequently getting
* the openl status (which can slow down stk). */
float m_end_time;
/** How long the sfx has been playing. */
float m_play_time;
public:
SFXOpenAL(SFXBuffer* buffer, bool positional, float gain,
bool owns_buffer = false);
virtual ~SFXOpenAL();
virtual void updatePlayingSFX(float dt);
virtual bool init();
virtual void play();
virtual void reallyPlayNow();
virtual void setLoop(bool status);
virtual bool isPlaying();
virtual void reallySetLoop(bool status);
virtual void stop();
virtual void reallyStopNow();
virtual void pause();
@ -100,9 +100,15 @@ public:
virtual void setVolume(float gain);
virtual void reallySetVolume(float gain);
virtual void setMasterVolume(float gain);
virtual void reallySetMasterVolumeNow(float gain);
virtual void onSoundEnabledBack();
virtual void setRolloff(float rolloff);
virtual SFXStatus getStatus();
// ------------------------------------------------------------------------
/** Returns if this sfx is looped or not. */
virtual bool isLooped() { return m_loop; }
// ------------------------------------------------------------------------
/** Returns the status of this sfx. */
virtual SFXStatus getStatus() { return m_status; }
// ------------------------------------------------------------------------
/** Returns the buffer associated with this sfx. */

View File

@ -257,6 +257,9 @@ const std::string& getOSVersion()
*/
void reportHardwareStats()
{
if(!UserConfigParams::m_hw_report_enable)
return;
// Version of the hw report, which is stored in the DB. If new fields
// are added, increase this version. Each STK installation will report
// its configuration only once (per version number). So if the version

View File

@ -68,6 +68,7 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
RaceManager::Difficulty difficulty,
int player_karts,
int last_track,
int reverse_type,
const std::vector<RaceManager::KartStatus> &kart_list)
: m_savedgp_group("SavedGP",
"Represents the saved state of a GP"),
@ -75,7 +76,8 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
m_gp_id(gp_id.c_str(), "gp_id", &m_savedgp_group),
m_difficulty((int)difficulty,"difficulty", &m_savedgp_group),
m_player_karts(player_karts,"player_karts", &m_savedgp_group),
m_next_track(last_track,"last_track", &m_savedgp_group)
m_next_track(last_track,"last_track", &m_savedgp_group),
m_reverse_type(reverse_type,"reverse_type", &m_savedgp_group)
{
for(unsigned int i =0; i < kart_list.size(); i++)
{
@ -94,18 +96,20 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
SavedGrandPrix::SavedGrandPrix(const XMLNode* node)
: m_savedgp_group("SavedGP",
"Represents the saved state of a GP"),
m_player_id(0, "player_id", &m_savedgp_group),
m_gp_id("-", "gp_id", &m_savedgp_group),
m_difficulty(0,"difficulty", &m_savedgp_group),
m_player_id (0, "player_id", &m_savedgp_group),
m_gp_id ("-", "gp_id", &m_savedgp_group),
m_difficulty (0,"difficulty", &m_savedgp_group),
m_player_karts(0,"player_karts", &m_savedgp_group),
m_next_track(0,"last_track", &m_savedgp_group)
m_next_track (0,"last_track", &m_savedgp_group),
m_reverse_type(0,"reverse_type", &m_savedgp_group)
{
//m_player_group.findYourDataInAChildOf(node);
m_player_id.findYourDataInAnAttributeOf(node);
m_gp_id.findYourDataInAnAttributeOf(node);
m_difficulty.findYourDataInAnAttributeOf(node);
m_player_id. findYourDataInAnAttributeOf(node);
m_gp_id. findYourDataInAnAttributeOf(node);
m_difficulty. findYourDataInAnAttributeOf(node);
m_player_karts.findYourDataInAnAttributeOf(node);
m_next_track.findYourDataInAnAttributeOf(node);
m_next_track. findYourDataInAnAttributeOf(node);
m_reverse_type.findYourDataInAnAttributeOf(node);
std::vector<XMLNode*> karts;
node->getNodes("Kart", karts);
@ -140,35 +144,41 @@ void SavedGrandPrix::setKarts(const std::vector<RaceManager::KartStatus> &kart_l
}
} // setKarts
/* compares two KartStatus-objects for std::sort in the next function */
bool cmp__l(RaceManager::KartStatus first, RaceManager::KartStatus second)
{
return (first.m_score > second.m_score);
}
//------------------------------------------------------------------------------
void SavedGrandPrix::loadKarts(std::vector<RaceManager::KartStatus> & kart_list)
{
//Fix aikarts
int aikarts = 0;
for(unsigned 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)
if(m_karts[i].m_local_player_id == -1) // AI kart
{
//AI kart found
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_score = m_karts[i].m_score;
kart_list[aikarts].m_overall_time = m_karts[i].m_overall_time;
aikarts++;
}
else
{
//Get correct player
// Get correct player
for(unsigned int x = kart_list.size()-m_player_karts;
x < kart_list.size(); x++)
{
if(kart_list[x].m_local_player_id == m_karts[i].m_local_player_id)
{
kart_list[x].m_score = m_karts[i].m_score;
kart_list[x].m_score = m_karts[i].m_score;
kart_list[x].m_overall_time = m_karts[i].m_overall_time;
} // if kart_list[x].m_local_player_id == m_karts[i].,_local
} // for x
} // if m_local_player_id == -1
} // for i
std::sort(kart_list.begin(), kart_list.end(), cmp__l);
} // loadKarts

View File

@ -19,11 +19,13 @@
#ifndef HEADER_SAVED_GRAND_PRIX_HPP
#define HEADER_SAVED_GRAND_PRIX_HPP
#include <string>
#include "config/user_config.hpp"
#include "race/race_manager.hpp"
#include "utils/ptr_vector.hpp"
#include <algorithm>
#include <string>
class RaceManager;
// ============================================================================
@ -74,6 +76,9 @@ protected:
/** Index of the next to run track. */
IntUserConfigParam m_next_track;
/** GPReverseType of the GP as int */
IntUserConfigParam m_reverse_type;
PtrVector<SavedGPKart> m_karts;
public:
@ -86,6 +91,7 @@ public:
RaceManager::Difficulty difficulty,
int player_karts,
int last_track,
int reverse_type,
const std::vector<RaceManager::KartStatus> &kart_list);
/**
@ -120,6 +126,10 @@ public:
/** Returns the index of the last track finished when this GP was saved. */
int getNextTrack() const { return m_next_track; }
// ------------------------------------------------------------------------
/** Returns the reverse Type. */
int getReverseType() const { return m_reverse_type; }
// ------------------------------------------------------------------------
/** Sets the index of the last track finished. */
void setNextTrack(int next_track) { m_next_track = next_track; }
@ -135,29 +145,22 @@ public:
// ------------------------------------------------------------------------
/** Finds the right SavedGrandPrix given the specified data, or
* NULL if no matching GP was found.
*/
* NULL if no matching GP was found. */
static SavedGrandPrix* getSavedGP(unsigned int player,
const std::string &gpid,
int difficulty, int total_karts,
int player_karts)
const std::string &gpid,
const unsigned int number_of_players)
{
for (unsigned int n=0; n<UserConfigParams::m_saved_grand_prix_list.size(); n++)
{
SavedGrandPrix* gp = &UserConfigParams::m_saved_grand_prix_list[n];
if ((gp->getGPID() == gpid) &&
(gp->getPlayerID() == player) &&
(gp->getDifficulty() == difficulty) &&
(gp->getTotalKarts() == total_karts) &&
(gp->getPlayerKarts() == player_karts)){
if (gp->getGPID() == gpid &&
gp->getPlayerID() == player &&
gp->getPlayerKarts() == (int)number_of_players)
return gp;
} // if
} // for n
}
return NULL;
} // getSavedGP
// ------------------------------------------------------------------------
}; // class SavedGrandPrix
#endif

View File

@ -698,6 +698,12 @@ namespace UserConfigParams
&m_hw_report_group,
"The server used for reporting statistics to."));
PARAM_PREFIX BoolUserConfigParam m_hw_report_enable
PARAM_DEFAULT( BoolUserConfigParam( true,
"hw-report-enabled",
&m_hw_report_group,
"If HW reports are enabled."));
// ---- User management
PARAM_PREFIX BoolUserConfigParam m_always_show_login_screen

338
src/graphics/2dutils.cpp Normal file
View File

@ -0,0 +1,338 @@
#include "2dutils.hpp"
#include "glwrap.hpp"
#include "utils/cpp2011.hpp"
#include "../../lib/irrlicht/source/Irrlicht/COpenGLTexture.h"
static void drawTexColoredQuad(const video::ITexture *texture, const video::SColor *col, float width, float height,
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
float tex_width, float tex_height)
{
unsigned colors[] = {
col[0].getRed(), col[0].getGreen(), col[0].getBlue(), col[0].getAlpha(),
col[1].getRed(), col[1].getGreen(), col[1].getBlue(), col[1].getAlpha(),
col[2].getRed(), col[2].getGreen(), col[2].getBlue(), col[2].getAlpha(),
col[3].getRed(), col[3].getGreen(), col[3].getBlue(), col[3].getAlpha(),
};
glBindBuffer(GL_ARRAY_BUFFER, UIShader::ColoredTextureRectShader::getInstance()->colorvbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(unsigned), colors);
glUseProgram(UIShader::ColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(UIShader::ColoredTextureRectShader::getInstance()->vao);
UIShader::ColoredTextureRectShader::getInstance()->SetTextureUnits(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName());
UIShader::ColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGetError();
}
static
void drawTexQuad(GLuint texture, float width, float height,
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
float tex_width, float tex_height)
{
glUseProgram(UIShader::TextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::TextureRectShader::getInstance()->SetTextureUnits(texture);
UIShader::TextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y),
core::vector2df(tex_width, tex_height));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGetError();
}
static void
getSize(unsigned texture_width, unsigned texture_height, bool textureisRTT,
const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect,
float &width, float &height,
float &center_pos_x, float &center_pos_y,
float &tex_width, float &tex_height,
float &tex_center_pos_x, float &tex_center_pos_y
)
{
core::dimension2d<u32> frame_size =
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
const int screen_w = frame_size.Width;
const int screen_h = frame_size.Height;
center_pos_x = float(destRect.UpperLeftCorner.X + destRect.LowerRightCorner.X);
center_pos_x /= screen_w;
center_pos_x -= 1.;
center_pos_y = float(destRect.UpperLeftCorner.Y + destRect.LowerRightCorner.Y);
center_pos_y /= screen_h;
center_pos_y = float(1.f - center_pos_y);
width = float(destRect.LowerRightCorner.X - destRect.UpperLeftCorner.X);
width /= screen_w;
height = float(destRect.LowerRightCorner.Y - destRect.UpperLeftCorner.Y);
height /= screen_h;
tex_center_pos_x = float(sourceRect.UpperLeftCorner.X + sourceRect.LowerRightCorner.X);
tex_center_pos_x /= texture_width * 2.f;
tex_center_pos_y = float(sourceRect.UpperLeftCorner.Y + sourceRect.LowerRightCorner.Y);
tex_center_pos_y /= texture_height * 2.f;
tex_width = float(sourceRect.LowerRightCorner.X - sourceRect.UpperLeftCorner.X);
tex_width /= texture_width * 2.f;
tex_height = float(sourceRect.LowerRightCorner.Y - sourceRect.UpperLeftCorner.Y);
tex_height /= texture_height * 2.f;
if (textureisRTT)
tex_height = -tex_height;
const f32 invW = 1.f / static_cast<f32>(texture_width);
const f32 invH = 1.f / static_cast<f32>(texture_height);
const core::rect<f32> tcoords(
sourceRect.UpperLeftCorner.X * invW,
sourceRect.UpperLeftCorner.Y * invH,
sourceRect.LowerRightCorner.X * invW,
sourceRect.LowerRightCorner.Y *invH);
}
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor &colors, bool useAlphaChannelOfTexture)
{
if (!irr_driver->isGLSL()) {
video::SColor duplicatedArray[4] = {
colors, colors, colors, colors
};
draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
return;
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clipRect)
{
if (!clipRect->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
clipRect->getWidth(), clipRect->getHeight());
}
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName());
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height), colors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
if (clipRect)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor &colors, bool useAlphaChannelOfTexture)
{
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize((int)texture_w, (int)texture_h, true,
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(texture);
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height),
colors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor* const colors, bool useAlphaChannelOfTexture)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DImage(texture, destRect, sourceRect, clipRect, colors, useAlphaChannelOfTexture);
return;
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clipRect)
{
if (!clipRect->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
clipRect->getWidth(), clipRect->getHeight());
}
if (colors)
drawTexColoredQuad(texture, colors, width, height, center_pos_x, center_pos_y,
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
else
drawTexQuad(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName(), width, height, center_pos_x, center_pos_y,
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
if (clipRect)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}
void draw2DVertexPrimitiveList(video::ITexture *tex, const void* vertices,
u32 vertexCount, const void* indexList, u32 primitiveCount,
video::E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, video::E_INDEX_TYPE iType)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType);
return;
}
GLuint tmpvao, tmpvbo, tmpibo;
primitiveCount += 2;
glGenVertexArrays(1, &tmpvao);
glBindVertexArray(tmpvao);
glGenBuffers(1, &tmpvbo);
glBindBuffer(GL_ARRAY_BUFFER, tmpvbo);
glBufferData(GL_ARRAY_BUFFER, vertexCount * getVertexPitchFromType(vType), vertices, GL_STREAM_DRAW);
glGenBuffers(1, &tmpibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tmpibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, primitiveCount * sizeof(u16), indexList, GL_STREAM_DRAW);
VertexUtils::bindVertexArrayAttrib(vType);
glUseProgram(UIShader::Primitive2DList::getInstance()->Program);
UIShader::Primitive2DList::getInstance()->setUniforms();
const video::SOverrideMaterial &m = irr_driver->getVideoDriver()->getOverrideMaterial();
compressTexture(tex, false);
UIShader::Primitive2DList::getInstance()->SetTextureUnits(getTextureGLuint(tex));
glDrawElements(GL_TRIANGLE_FAN, primitiveCount, GL_UNSIGNED_SHORT, 0);
glDeleteVertexArrays(1, &tmpvao);
glDeleteBuffers(1, &tmpvbo);
glDeleteBuffers(1, &tmpibo);
}
void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position,
const core::rect<s32>* clip)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip);
return;
}
core::dimension2d<u32> frame_size =
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
const int screen_w = frame_size.Width;
const int screen_h = frame_size.Height;
float center_pos_x = float(position.UpperLeftCorner.X + position.LowerRightCorner.X);
center_pos_x /= screen_w;
center_pos_x -= 1;
float center_pos_y = float(position.UpperLeftCorner.Y + position.LowerRightCorner.Y);
center_pos_y /= screen_h;
center_pos_y = 1 - center_pos_y;
float width = float(position.LowerRightCorner.X - position.UpperLeftCorner.X);
width /= screen_w;
float height = float(position.LowerRightCorner.Y - position.UpperLeftCorner.Y);
height /= screen_h;
if (color.getAlpha() < 255)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clip)
{
if (!clip->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clip->UpperLeftCorner.X, renderTargetSize.Height - clip->LowerRightCorner.Y,
clip->getWidth(), clip->getHeight());
}
glUseProgram(UIShader::ColoredRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::ColoredRectShader::getInstance()->setUniforms(core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), color);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
if (clip)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}

33
src/graphics/2dutils.hpp Normal file
View File

@ -0,0 +1,33 @@
#ifndef UTILS2D_HPP
#define UTILS2D_HPP
#include "gl_headers.hpp"
#include <rect.h>
#include <SColor.h>
#include <S3DVertex.h>
#include <SVertexIndex.h>
#include <EPrimitiveTypes.h>
#include <ITexture.h>
#include <irrTypes.h>
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
const irr::core::rect<irr::s32>& destRect,
const irr::core::rect<irr::s32>& sourceRect, const irr::core::rect<irr::s32>* clipRect,
const irr::video::SColor &colors, bool useAlphaChannelOfTexture);
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<irr::s32>& destRect,
const irr::core::rect<irr::s32>& sourceRect, const irr::core::rect<irr::s32>* clipRect,
const irr::video::SColor &color, bool useAlphaChannelOfTexture);
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<irr::s32>& destRect,
const irr::core::rect<irr::s32>& sourceRect, const irr::core::rect<irr::s32>* clipRect,
const irr::video::SColor* const colors, bool useAlphaChannelOfTexture);
void draw2DVertexPrimitiveList(irr::video::ITexture *t, const void* vertices,
irr::u32 vertexCount, const void* indexList, irr::u32 primitiveCount,
irr::video::E_VERTEX_TYPE vType = irr::video::EVT_STANDARD, irr::scene::E_PRIMITIVE_TYPE pType = irr::scene::EPT_TRIANGLES, irr::video::E_INDEX_TYPE iType = irr::video::EIT_16BIT);
void GL32_draw2DRectangle(irr::video::SColor color, const irr::core::rect<irr::s32>& position,
const irr::core::rect<irr::s32>* clip = 0);
#endif

View File

@ -372,7 +372,9 @@ void Camera::smoothMoveCamera(float dt)
if (race_manager->getNumLocalPlayers() < 2)
{
SFXManager::get()->positionListener(current_position, current_target - current_position);
SFXManager::get()->positionListener(current_position,
current_target - current_position,
Vec3(0,1,0));
}
} // smoothMoveCamera
@ -578,7 +580,8 @@ void Camera::positionCamera(float dt, float above_kart, float cam_angle,
if (race_manager->getNumLocalPlayers() < 2)
{
SFXManager::get()->positionListener(m_camera->getPosition(),
wanted_target - m_camera->getPosition());
wanted_target - m_camera->getPosition(),
Vec3(0, 1, 0));
}
}

View File

@ -6,9 +6,6 @@
#include "utils/profiler.hpp"
#include "utils/cpp2011.hpp"
#include "../../lib/irrlicht/source/Irrlicht/COpenGLTexture.h"
#include <fstream>
#include <string>
#include <sstream>
@ -122,159 +119,6 @@ void initGL()
#endif
}
static std::string LoadHeader()
{
std::string result;
std::ifstream Stream(file_manager->getAsset("shaders/header.txt").c_str(), std::ios::in);
if (Stream.is_open())
{
std::string Line = "";
while (getline(Stream, Line))
result += "\n" + Line;
Stream.close();
}
return result;
}
// Mostly from shader tutorial
GLuint LoadShader(const char * file, unsigned type)
{
GLuint Id = glCreateShader(type);
char versionString[20];
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
std::string Code = versionString;
if (irr_driver->hasVSLayerExtension())
Code += "#extension GL_AMD_vertex_shader_layer : enable\n";
if (UserConfigParams::m_azdo)
Code += "#extension GL_ARB_bindless_texture : enable\n";
else
{
Code += "#extension GL_ARB_bindless_texture : disable\n";
Code += "#undef GL_ARB_bindless_texture\n";
}
std::ifstream Stream(file, std::ios::in);
Code += "//" + std::string(file) + "\n";
if (irr_driver->needUBOWorkaround())
Code += "#define UBO_DISABLED\n";
if (irr_driver->hasVSLayerExtension())
Code += "#define VSLayer\n";
if (irr_driver->needsRGBBindlessWorkaround())
Code += "#define SRGBBindlessFix\n";
Code += LoadHeader();
if (Stream.is_open())
{
std::string Line = "";
while (getline(Stream, Line))
Code += "\n" + Line;
Stream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
Log::info("GLWrap", "Compiling shader : %s", file);
char const * SourcePointer = Code.c_str();
int length = (int)strlen(SourcePointer);
glShaderSource(Id, 1, &SourcePointer, &length);
glCompileShader(Id);
glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
if (Result == GL_FALSE)
{
Log::error("GLWrap", "Error in shader %s", file);
glGetShaderiv(Id, GL_INFO_LOG_LENGTH, &InfoLogLength);
if(InfoLogLength<0)
InfoLogLength = 1024;
char *ErrorMessage = new char[InfoLogLength];
ErrorMessage[0]=0;
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
glGetError();
return Id;
}
void setAttribute(AttributeType Tp, GLuint ProgramID)
{
switch (Tp)
{
case OBJECT:
glBindAttribLocation(ProgramID, 0, "Position");
glBindAttribLocation(ProgramID, 1, "Normal");
glBindAttribLocation(ProgramID, 2, "Color");
glBindAttribLocation(ProgramID, 3, "Texcoord");
glBindAttribLocation(ProgramID, 4, "SecondTexcoord");
glBindAttribLocation(ProgramID, 5, "Tangent");
glBindAttribLocation(ProgramID, 6, "Bitangent");
glBindAttribLocation(ProgramID, 7, "Origin");
glBindAttribLocation(ProgramID, 8, "Orientation");
glBindAttribLocation(ProgramID, 9, "Scale");
break;
case PARTICLES_SIM:
glBindAttribLocation(ProgramID, 0, "particle_position");
glBindAttribLocation(ProgramID, 1, "lifetime");
glBindAttribLocation(ProgramID, 2, "particle_velocity");
glBindAttribLocation(ProgramID, 3, "size");
glBindAttribLocation(ProgramID, 4, "particle_position_initial");
glBindAttribLocation(ProgramID, 5, "lifetime_initial");
glBindAttribLocation(ProgramID, 6, "particle_velocity_initial");
glBindAttribLocation(ProgramID, 7, "size_initial");
break;
case PARTICLES_RENDERING:
glBindAttribLocation(ProgramID, 1, "lifetime");
glBindAttribLocation(ProgramID, 2, "size");
glBindAttribLocation(ProgramID, 4, "quadcorner");
glBindAttribLocation(ProgramID, 5, "rotationvec");
glBindAttribLocation(ProgramID, 6, "anglespeed");
break;
}
}
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
{
GLuint Program = glCreateProgram();
loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
if (irr_driver->getGLSLVersion() < 330)
setAttribute(PARTICLES_SIM, Program);
glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(Program);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(Program, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE)
{
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(Program, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
glGetError();
return Program;
}
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF)
{
glActiveTexture(GL_TEXTURE0 + TextureUnit);
glBindTexture(GL_TEXTURE_2D, TextureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
int aniso = UserConfigParams::m_anisotropic;
if (aniso == 0) aniso = 1;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, allowAF ? (float)aniso : 1.0f);
glGetError();
}
ScopedGPUTimer::ScopedGPUTimer(GPUTimer &t) : timer(t)
{
if (!UserConfigParams::m_profiler_enabled) return;
@ -417,304 +261,6 @@ void draw3DLine(const core::vector3df& start,
glGetError();
}
static void drawTexColoredQuad(const video::ITexture *texture, const video::SColor *col, float width, float height,
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
float tex_width, float tex_height)
{
unsigned colors[] = {
col[0].getRed(), col[0].getGreen(), col[0].getBlue(), col[0].getAlpha(),
col[1].getRed(), col[1].getGreen(), col[1].getBlue(), col[1].getAlpha(),
col[2].getRed(), col[2].getGreen(), col[2].getBlue(), col[2].getAlpha(),
col[3].getRed(), col[3].getGreen(), col[3].getBlue(), col[3].getAlpha(),
};
glBindBuffer(GL_ARRAY_BUFFER, UIShader::ColoredTextureRectShader::getInstance()->colorvbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, 16 * sizeof(unsigned), colors);
glUseProgram(UIShader::ColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(UIShader::ColoredTextureRectShader::getInstance()->vao);
UIShader::ColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName()));
UIShader::ColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGetError();
}
static
void drawTexQuad(GLuint texture, float width, float height,
float center_pos_x, float center_pos_y, float tex_center_pos_x, float tex_center_pos_y,
float tex_width, float tex_height)
{
glUseProgram(UIShader::TextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::TextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(texture));
UIShader::TextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y),
core::vector2df(tex_width, tex_height));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGetError();
}
static void
getSize(unsigned texture_width, unsigned texture_height, bool textureisRTT,
const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect,
float &width, float &height,
float &center_pos_x, float &center_pos_y,
float &tex_width, float &tex_height,
float &tex_center_pos_x, float &tex_center_pos_y
)
{
core::dimension2d<u32> frame_size =
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
const int screen_w = frame_size.Width;
const int screen_h = frame_size.Height;
center_pos_x = float(destRect.UpperLeftCorner.X + destRect.LowerRightCorner.X);
center_pos_x /= screen_w;
center_pos_x -= 1.;
center_pos_y = float(destRect.UpperLeftCorner.Y + destRect.LowerRightCorner.Y);
center_pos_y /= screen_h;
center_pos_y = float(1.f - center_pos_y);
width = float(destRect.LowerRightCorner.X - destRect.UpperLeftCorner.X);
width /= screen_w;
height = float(destRect.LowerRightCorner.Y - destRect.UpperLeftCorner.Y);
height /= screen_h;
tex_center_pos_x = float(sourceRect.UpperLeftCorner.X + sourceRect.LowerRightCorner.X);
tex_center_pos_x /= texture_width * 2.f;
tex_center_pos_y = float(sourceRect.UpperLeftCorner.Y + sourceRect.LowerRightCorner.Y);
tex_center_pos_y /= texture_height * 2.f;
tex_width = float(sourceRect.LowerRightCorner.X - sourceRect.UpperLeftCorner.X);
tex_width /= texture_width * 2.f;
tex_height = float(sourceRect.LowerRightCorner.Y - sourceRect.UpperLeftCorner.Y);
tex_height /= texture_height * 2.f;
if (textureisRTT)
tex_height = -tex_height;
const f32 invW = 1.f / static_cast<f32>(texture_width);
const f32 invH = 1.f / static_cast<f32>(texture_height);
const core::rect<f32> tcoords(
sourceRect.UpperLeftCorner.X * invW,
sourceRect.UpperLeftCorner.Y * invH,
sourceRect.LowerRightCorner.X * invW,
sourceRect.LowerRightCorner.Y *invH);
}
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor &colors, bool useAlphaChannelOfTexture)
{
if (!irr_driver->isGLSL()) {
video::SColor duplicatedArray[4] = {
colors, colors, colors, colors
};
draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
return;
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clipRect)
{
if (!clipRect->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
clipRect->getWidth(), clipRect->getHeight());
}
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName()));
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height), colors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
if (clipRect)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor &colors, bool useAlphaChannelOfTexture)
{
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize((int)texture_w, (int)texture_h, true,
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(texture));
UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height),
core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height),
colors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor* const colors, bool useAlphaChannelOfTexture)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DImage(texture, destRect, sourceRect, clipRect, colors, useAlphaChannelOfTexture);
return;
}
float width, height,
center_pos_x, center_pos_y,
tex_width, tex_height,
tex_center_pos_x, tex_center_pos_y;
getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
destRect, sourceRect, width, height, center_pos_x, center_pos_y,
tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);
if (useAlphaChannelOfTexture)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clipRect)
{
if (!clipRect->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
clipRect->getWidth(), clipRect->getHeight());
}
if (colors)
drawTexColoredQuad(texture, colors, width, height, center_pos_x, center_pos_y,
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
else
drawTexQuad(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName(), width, height, center_pos_x, center_pos_y,
tex_center_pos_x, tex_center_pos_y, tex_width, tex_height);
if (clipRect)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}
void GL32_draw2DRectangle(video::SColor color, const core::rect<s32>& position,
const core::rect<s32>* clip)
{
if (!irr_driver->isGLSL())
{
irr_driver->getVideoDriver()->draw2DRectangle(color, position, clip);
return;
}
core::dimension2d<u32> frame_size =
irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
const int screen_w = frame_size.Width;
const int screen_h = frame_size.Height;
float center_pos_x = float(position.UpperLeftCorner.X + position.LowerRightCorner.X);
center_pos_x /= screen_w;
center_pos_x -= 1;
float center_pos_y = float(position.UpperLeftCorner.Y + position.LowerRightCorner.Y);
center_pos_y /= screen_h;
center_pos_y = 1 - center_pos_y;
float width = float(position.LowerRightCorner.X - position.UpperLeftCorner.X);
width /= screen_w;
float height = float(position.LowerRightCorner.Y - position.UpperLeftCorner.Y);
height /= screen_h;
if (color.getAlpha() < 255)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
if (clip)
{
if (!clip->isValid())
return;
glEnable(GL_SCISSOR_TEST);
const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
glScissor(clip->UpperLeftCorner.X, renderTargetSize.Height - clip->LowerRightCorner.Y,
clip->getWidth(), clip->getHeight());
}
glUseProgram(UIShader::ColoredRectShader::getInstance()->Program);
glBindVertexArray(SharedObject::UIVAO);
UIShader::ColoredRectShader::getInstance()->setUniforms(core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), color);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
if (clip)
glDisable(GL_SCISSOR_TEST);
glUseProgram(0);
glGetError();
}
bool hasGLExtension(const char* extension)
{
if (glGetStringi != NULL)

View File

@ -15,78 +15,7 @@ namespace HardwareStats
}
void initGL();
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
video::ITexture* getUnicolorTexture(const video::SColor &c);
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF = false);
GLuint LoadShader(const char * file, unsigned type);
template<typename ... Types>
void loadAndAttach(GLint ProgramID)
{
return;
}
template<typename ... Types>
void loadAndAttach(GLint ProgramID, GLint ShaderType, const char *filepath, Types ... args)
{
GLint ShaderID = LoadShader(filepath, ShaderType);
glAttachShader(ProgramID, ShaderID);
glDeleteShader(ShaderID);
loadAndAttach(ProgramID, args...);
}
template<typename ...Types>
void printFileList()
{
return;
}
template<typename ...Types>
void printFileList(GLint ShaderType, const char *filepath, Types ... args)
{
Log::error("GLWrapp", filepath);
printFileList(args...);
}
enum AttributeType
{
OBJECT,
PARTICLES_SIM,
PARTICLES_RENDERING,
};
void setAttribute(AttributeType Tp, GLuint ProgramID);
template<typename ... Types>
GLint LoadProgram(AttributeType Tp, Types ... args)
{
GLint ProgramID = glCreateProgram();
loadAndAttach(ProgramID, args...);
if (irr_driver->getGLSLVersion() < 330)
setAttribute(Tp, ProgramID);
glLinkProgram(ProgramID);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE) {
Log::error("GLWrapp", "Error when linking these shaders :");
printFileList(args...);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrapp", ErrorMessage);
delete[] ErrorMessage;
}
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
return ProgramID;
}
class GPUTimer;
@ -132,30 +61,74 @@ public:
void BlitToDefault(size_t, size_t, size_t, size_t);
};
// core::rect<s32> needs these includes
#include <rect.h>
class VertexUtils
{
public:
static void bindVertexArrayAttrib(enum video::E_VERTEX_TYPE tp)
{
switch (tp)
{
case video::EVT_STANDARD:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
break;
case video::EVT_2TCOORDS:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
// SecondTexcoord
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)36);
break;
case video::EVT_TANGENTS:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitchFromType(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)28);
// Tangent
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)36);
// Bitangent
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitchFromType(tp), (GLvoid*)48);
break;
}
}
};
#include "utils/vec3.hpp"
#include "texturemanager.hpp"
void draw3DLine(const core::vector3df& start,
const core::vector3df& end, irr::video::SColor color);
void draw2DImageFromRTT(GLuint texture, size_t texture_w, size_t texture_h,
const core::rect<s32>& destRect,
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
const video::SColor &colors, bool useAlphaChannelOfTexture);
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<s32>& destRect,
const irr::core::rect<s32>& sourceRect, const irr::core::rect<s32>* clipRect,
const irr::video::SColor &color, bool useAlphaChannelOfTexture);
void draw2DImage(const irr::video::ITexture* texture, const irr::core::rect<s32>& destRect,
const irr::core::rect<s32>& sourceRect, const irr::core::rect<s32>* clipRect,
const irr::video::SColor* const colors, bool useAlphaChannelOfTexture);
void GL32_draw2DRectangle(irr::video::SColor color, const irr::core::rect<s32>& position,
const irr::core::rect<s32>* clip = 0);
bool hasGLExtension(const char* extension);
const std::string getGLExtensions();
void getGLLimits(HardwareStats::Json *json);

View File

@ -350,7 +350,7 @@ void ParticleSystemProxy::drawFlip()
glBlendFunc(GL_ONE, GL_ONE);
glUseProgram(ParticleShader::FlipParticleRender::getInstance()->Program);
ParticleShader::FlipParticleRender::getInstance()->SetTextureUnits(std::vector<GLuint>{ texture, irr_driver->getDepthStencilTexture() });
ParticleShader::FlipParticleRender::getInstance()->SetTextureUnits(texture, irr_driver->getDepthStencilTexture());
ParticleShader::FlipParticleRender::getInstance()->setUniforms();
glBindVertexArray(current_rendering_vao);
@ -365,7 +365,7 @@ void ParticleSystemProxy::drawNotFlip()
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(ParticleShader::SimpleParticleRender::getInstance()->Program);
ParticleShader::SimpleParticleRender::getInstance()->SetTextureUnits(std::vector<GLuint>{ texture, irr_driver->getDepthStencilTexture() });
ParticleShader::SimpleParticleRender::getInstance()->SetTextureUnits(texture, irr_driver->getDepthStencilTexture());
video::SColorf ColorFrom = video::SColorf(getColorFrom()[0], getColorFrom()[1], getColorFrom()[2]);
video::SColorf ColorTo = video::SColorf(getColorTo()[0], getColorTo()[1], getColorTo()[2]);

View File

@ -65,6 +65,5 @@ void HitSFX::setPlayerKartHit()
bool HitSFX::updateAndDelete(float dt)
{
SFXBase::SFXStatus status = m_sfx->getStatus();
if(status==SFXBase::SFX_INITIAL) return false;
return status!= SFXBase::SFX_PLAYING;
} // updateAndDelete

View File

@ -22,6 +22,7 @@
#include "graphics/callbacks.hpp"
#include "graphics/camera.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/2dutils.hpp"
#include "graphics/hardware_skinning.hpp"
#include "graphics/lens_flare.hpp"
#include "graphics/light.hpp"

View File

@ -22,6 +22,8 @@
#include <IMeshBuffer.h>
#include "utils/log.hpp"
#include "graphics/irr_driver.hpp"
#include "modes/world.hpp"
#include "tracks/track.hpp"
void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
@ -325,7 +327,8 @@ bool MeshTools::isNormalMap(scene::IMeshBuffer* mb)
{
if (!irr_driver->isGLSL())
return false;
return (mb->getMaterial().MaterialType == irr_driver->getShader(ES_NORMAL_MAP));
return (mb->getMaterial().MaterialType == irr_driver->getShader(ES_NORMAL_MAP) &&
mb->getVertexType() != video::EVT_TANGENTS);
}
// Copied from irrlicht
@ -385,28 +388,28 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, bool(*predic
{
switch (vType)
{
case video::EVT_STANDARD:
{
const video::S3DVertex* v =
(const video::S3DVertex*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
case video::EVT_STANDARD:
{
const video::S3DVertex* v =
(const video::S3DVertex*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
break;
case video::EVT_2TCOORDS:
{
const video::S3DVertex2TCoords* v =
(const video::S3DVertex2TCoords*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
case video::EVT_2TCOORDS:
{
const video::S3DVertex2TCoords* v =
(const video::S3DVertex2TCoords*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
break;
case video::EVT_TANGENTS:
{
const video::S3DVertexTangents* v =
(const video::S3DVertexTangents*)original->getVertices();
vNew = v[idx[i]];
}
case video::EVT_TANGENTS:
{
const video::S3DVertexTangents* v =
(const video::S3DVertexTangents*)original->getVertices();
vNew = v[idx[i]];
}
break;
}
core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
@ -435,8 +438,28 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, bool(*predic
if (calculateTangents)
recalculateTangents(clone, recalculateNormals, smooth, angleWeighted);
int mbcount = clone->getMeshBufferCount();
for (int i = 0; i < mbcount; i++)
{
scene::IMeshBuffer* mb = clone->getMeshBuffer(i);
for (int t = 0; t < video::MATERIAL_MAX_TEXTURES; t++)
{
video::ITexture* texture = mb->getMaterial().TextureLayer[t].Texture;
if (texture != NULL)
texture->grab();
}
}
scene::IMeshCache* meshCache = irr_driver->getSceneManager()->getMeshCache();
io::SNamedPath path = meshCache->getMeshName(mesh);
irr_driver->removeMeshFromCache(mesh);
scene::SAnimatedMesh* amesh = new scene::SAnimatedMesh(clone);
meshCache->addMesh(path, amesh);
World::getWorld()->getTrack()->addCachedMesh(amesh);
return clone;
}

View File

@ -217,7 +217,7 @@ static void DrawFullScreenEffect(Args...args)
static
void renderBloom(GLuint in)
{
FullScreenShader::BloomShader::getInstance()->SetTextureUnits(createVector<GLuint>(in));
FullScreenShader::BloomShader::getInstance()->SetTextureUnits(in);
DrawFullScreenEffect<FullScreenShader::BloomShader>();
}
@ -231,7 +231,7 @@ void PostProcessing::renderEnvMap(const float *bSHCoeff, const float *gSHCoeff,
glUseProgram(FullScreenShader::EnvMapShader::getInstance()->Program);
glBindVertexArray(SharedObject::FullScreenQuadVAO);
FullScreenShader::EnvMapShader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), skybox));
FullScreenShader::EnvMapShader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), skybox);
core::matrix4 TVM = irr_driver->getViewMatrix().getTransposed();
FullScreenShader::EnvMapShader::getInstance()->setUniforms(TVM, std::vector<float>(bSHCoeff, bSHCoeff + 9), std::vector<float>(gSHCoeff, gSHCoeff + 9), std::vector<float>(rSHCoeff, rSHCoeff + 9));
@ -264,8 +264,8 @@ void PostProcessing::renderGI(const core::matrix4 &RHMatrix, const core::vector3
core::matrix4 InvRHMatrix;
RHMatrix.getInverse(InvRHMatrix);
glDisable(GL_DEPTH_TEST);
FullScreenShader::GlobalIlluminationReconstructionShader::getInstance()->SetTextureUnits(createVector<GLuint>(
irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), shr, shg, shb));
FullScreenShader::GlobalIlluminationReconstructionShader::getInstance()->SetTextureUnits(
irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), shr, shg, shb);
DrawFullScreenEffect<FullScreenShader::GlobalIlluminationReconstructionShader>(RHMatrix, InvRHMatrix, rh_extend);
}
@ -278,7 +278,7 @@ void PostProcessing::renderSunlight()
glBlendFunc(GL_ONE, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
FullScreenShader::SunLightShader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture()));
FullScreenShader::SunLightShader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture());
DrawFullScreenEffect<FullScreenShader::SunLightShader>(cb->getPosition(), video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue()));
}
@ -291,7 +291,7 @@ void PostProcessing::renderShadowedSunlight(const std::vector<core::matrix4> &su
glBlendFunc(GL_ONE, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
FullScreenShader::ShadowedSunLightShader::getInstance()->SetTextureUnits(createVector<GLuint>( irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), depthtex ));
FullScreenShader::ShadowedSunLightShader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), depthtex);
DrawFullScreenEffect<FullScreenShader::ShadowedSunLightShader>(cb->getPosition(), video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue()));
}
@ -303,13 +303,13 @@ void PostProcessing::renderGaussian3Blur(FrameBuffer &in_fbo, FrameBuffer &auxil
{
auxiliary.Bind();
FullScreenShader::Gaussian3VBlurShader::getInstance()->SetTextureUnits(createVector<GLuint>(in_fbo.getRTT()[0]));
FullScreenShader::Gaussian3VBlurShader::getInstance()->SetTextureUnits(in_fbo.getRTT()[0]);
DrawFullScreenEffect<FullScreenShader::Gaussian3VBlurShader>(core::vector2df(inv_width, inv_height));
}
{
in_fbo.Bind();
FullScreenShader::Gaussian3HBlurShader::getInstance()->SetTextureUnits(createVector<GLuint>(auxiliary.getRTT()[0]));
FullScreenShader::Gaussian3HBlurShader::getInstance()->SetTextureUnits(auxiliary.getRTT()[0]);
DrawFullScreenEffect<FullScreenShader::Gaussian3HBlurShader>(core::vector2df(inv_width, inv_height));
}
}
@ -321,13 +321,13 @@ void PostProcessing::renderGaussian6Blur(FrameBuffer &in_fbo, FrameBuffer &auxil
{
auxiliary.Bind();
FullScreenShader::Gaussian6VBlurShader::getInstance()->SetTextureUnits(createVector<GLuint>(in_fbo.getRTT()[0]));
FullScreenShader::Gaussian6VBlurShader::getInstance()->SetTextureUnits(in_fbo.getRTT()[0]);
DrawFullScreenEffect<FullScreenShader::Gaussian6VBlurShader>(core::vector2df(inv_width, inv_height));
}
{
in_fbo.Bind();
FullScreenShader::Gaussian6HBlurShader::getInstance()->SetTextureUnits(createVector<GLuint>(auxiliary.getRTT()[0]));
FullScreenShader::Gaussian6HBlurShader::getInstance()->SetTextureUnits(auxiliary.getRTT()[0]);
DrawFullScreenEffect<FullScreenShader::Gaussian6HBlurShader>(core::vector2df(inv_width, inv_height));
}
}
@ -342,14 +342,14 @@ void PostProcessing::renderGaussian17TapBlur(FrameBuffer &in_fbo, FrameBuffer &a
if (!irr_driver->hasARBComputeShaders())
{
auxiliary.Bind();
FullScreenShader::Gaussian17TapHShader::getInstance()->SetTextureUnits(createVector<GLuint>(in_fbo.getRTT()[0], irr_driver->getFBO(FBO_LINEAR_DEPTH).getRTT()[0]));
FullScreenShader::Gaussian17TapHShader::getInstance()->SetTextureUnits(in_fbo.getRTT()[0], irr_driver->getFBO(FBO_LINEAR_DEPTH).getRTT()[0]);
DrawFullScreenEffect<FullScreenShader::Gaussian17TapHShader>(core::vector2df(inv_width, inv_height));
}
else
{
glUseProgram(FullScreenShader::ComputeGaussian17TapHShader::getInstance()->Program);
glBindSampler(FullScreenShader::ComputeGaussian17TapHShader::getInstance()->TU_dest, 0);
FullScreenShader::ComputeGaussian17TapHShader::getInstance()->SetTextureUnits({ in_fbo.getRTT()[0], irr_driver->getFBO(FBO_LINEAR_DEPTH).getRTT()[0] });
FullScreenShader::ComputeGaussian17TapHShader::getInstance()->SetTextureUnits(in_fbo.getRTT()[0], irr_driver->getFBO(FBO_LINEAR_DEPTH).getRTT()[0]);
glBindImageTexture(FullScreenShader::ComputeGaussian17TapHShader::getInstance()->TU_dest, auxiliary.getRTT()[0], 0, false, 0, GL_WRITE_ONLY, GL_R16F);
FullScreenShader::ComputeGaussian17TapHShader::getInstance()->setUniforms(core::vector2df(inv_width, inv_height));
glDispatchCompute((int)in_fbo.getWidth() / 8 + 1, (int)in_fbo.getHeight() / 8 + 1, 1);
@ -362,14 +362,14 @@ void PostProcessing::renderGaussian17TapBlur(FrameBuffer &in_fbo, FrameBuffer &a
{
in_fbo.Bind();
FullScreenShader::Gaussian17TapVShader::getInstance()->SetTextureUnits(createVector<GLuint>(auxiliary.getRTT()[0], irr_driver->getFBO(FBO_LINEAR_DEPTH).getRTT()[0]));
FullScreenShader::Gaussian17TapVShader::getInstance()->SetTextureUnits(auxiliary.getRTT()[0], irr_driver->getFBO(FBO_LINEAR_DEPTH).getRTT()[0]);
DrawFullScreenEffect<FullScreenShader::Gaussian17TapVShader>(core::vector2df(inv_width, inv_height));
}
else
{
glUseProgram(FullScreenShader::ComputeGaussian17TapVShader::getInstance()->Program);
glBindSampler(FullScreenShader::ComputeGaussian17TapVShader::getInstance()->TU_dest, 0);
FullScreenShader::ComputeGaussian17TapVShader::getInstance()->SetTextureUnits({ auxiliary.getRTT()[0], irr_driver->getFBO(FBO_LINEAR_DEPTH).getRTT()[0] });
FullScreenShader::ComputeGaussian17TapVShader::getInstance()->SetTextureUnits(auxiliary.getRTT()[0], irr_driver->getFBO(FBO_LINEAR_DEPTH).getRTT()[0]);
glBindImageTexture(FullScreenShader::ComputeGaussian17TapVShader::getInstance()->TU_dest, in_fbo.getRTT()[0], 0, false, 0, GL_WRITE_ONLY, GL_R16F);
FullScreenShader::ComputeGaussian17TapVShader::getInstance()->setUniforms(core::vector2df(inv_width, inv_height));
glDispatchCompute((int)in_fbo.getWidth() / 8 + 1, (int)in_fbo.getHeight() / 8 + 1, 1);
@ -384,7 +384,7 @@ void PostProcessing::renderPassThrough(GLuint tex)
glUseProgram(FullScreenShader::PassThroughShader::getInstance()->Program);
glBindVertexArray(FullScreenShader::PassThroughShader::getInstance()->vao);
FullScreenShader::PassThroughShader::getInstance()->SetTextureUnits(createVector<GLuint>(tex));
FullScreenShader::PassThroughShader::getInstance()->SetTextureUnits(tex);
FullScreenShader::PassThroughShader::getInstance()->setUniforms();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@ -409,7 +409,7 @@ void PostProcessing::renderGlow(unsigned tex)
glUseProgram(FullScreenShader::GlowShader::getInstance()->Program);
glBindVertexArray(FullScreenShader::GlowShader::getInstance()->vao);
FullScreenShader::GlowShader::getInstance()->SetTextureUnits(createVector<GLuint>(tex));
FullScreenShader::GlowShader::getInstance()->SetTextureUnits(tex);
FullScreenShader::GlowShader::getInstance()->setUniforms();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@ -422,11 +422,11 @@ void PostProcessing::renderSSAO()
// Generate linear depth buffer
irr_driver->getFBO(FBO_LINEAR_DEPTH).Bind();
FullScreenShader::LinearizeDepthShader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getDepthStencilTexture()));
FullScreenShader::LinearizeDepthShader::getInstance()->SetTextureUnits(irr_driver->getDepthStencilTexture());
DrawFullScreenEffect<FullScreenShader::LinearizeDepthShader>(irr_driver->getSceneManager()->getActiveCamera()->getNearValue(), irr_driver->getSceneManager()->getActiveCamera()->getFarValue());
irr_driver->getFBO(FBO_SSAO).Bind();
FullScreenShader::SSAOShader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getRenderTargetTexture(RTT_LINEAR_DEPTH)));
FullScreenShader::SSAOShader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_LINEAR_DEPTH));
glGenerateMipmap(GL_TEXTURE_2D);
DrawFullScreenEffect<FullScreenShader::SSAOShader>(irr_driver->getSSAORadius(), irr_driver->getSSAOK(), irr_driver->getSSAOSigma());
@ -454,7 +454,7 @@ void PostProcessing::renderFog()
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
FullScreenShader::FogShader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getDepthStencilTexture()));
FullScreenShader::FogShader::getInstance()->SetTextureUnits(irr_driver->getDepthStencilTexture());
DrawFullScreenEffect<FullScreenShader::FogShader>(fogmax, startH, endH, start, end, col);
glEnable(GL_DEPTH_TEST);
@ -487,7 +487,7 @@ void PostProcessing::renderMotionBlur(unsigned cam, FrameBuffer &in_fbo, FrameBu
out_fbo.Bind();
glClear(GL_COLOR_BUFFER_BIT);
FullScreenShader::MotionBlurShader::getInstance()->SetTextureUnits(createVector<GLuint>(in_fbo.getRTT()[0], irr_driver->getDepthStencilTexture()));
FullScreenShader::MotionBlurShader::getInstance()->SetTextureUnits(in_fbo.getRTT()[0], irr_driver->getDepthStencilTexture());
DrawFullScreenEffect<FullScreenShader::MotionBlurShader>(
// Todo : use a previousPVMatrix per cam, not global
irr_driver->getPreviousPVMatrix(),
@ -500,7 +500,7 @@ static void renderGodFade(GLuint tex, const SColor &col)
{
glUseProgram(FullScreenShader::GodFadeShader::getInstance()->Program);
glBindVertexArray(FullScreenShader::GodFadeShader::getInstance()->vao);
FullScreenShader::GodFadeShader::getInstance()->SetTextureUnits(createVector<GLuint>(tex));
FullScreenShader::GodFadeShader::getInstance()->SetTextureUnits(tex);
FullScreenShader::GodFadeShader::getInstance()->setUniforms(col);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@ -510,7 +510,7 @@ static void renderGodRay(GLuint tex, const core::vector2df &sunpos)
{
glUseProgram(FullScreenShader::GodRayShader::getInstance()->Program);
glBindVertexArray(FullScreenShader::GodRayShader::getInstance()->vao);
FullScreenShader::GodRayShader::getInstance()->SetTextureUnits(createVector<GLuint>(tex));
FullScreenShader::GodRayShader::getInstance()->SetTextureUnits(tex);
FullScreenShader::GodRayShader::getInstance()->setUniforms(sunpos);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@ -519,14 +519,14 @@ static void renderGodRay(GLuint tex, const core::vector2df &sunpos)
static void toneMap(FrameBuffer &fbo, GLuint rtt)
{
fbo.Bind();
FullScreenShader::ToneMapShader::getInstance()->SetTextureUnits(createVector<GLuint>(rtt));
FullScreenShader::ToneMapShader::getInstance()->SetTextureUnits(rtt);
DrawFullScreenEffect<FullScreenShader::ToneMapShader>();
}
static void renderDoF(FrameBuffer &fbo, GLuint rtt)
{
fbo.Bind();
FullScreenShader::DepthOfFieldShader::getInstance()->SetTextureUnits(createVector<GLuint>(rtt, irr_driver->getDepthStencilTexture()));
FullScreenShader::DepthOfFieldShader::getInstance()->SetTextureUnits(rtt, irr_driver->getDepthStencilTexture());
DrawFullScreenEffect<FullScreenShader::DepthOfFieldShader>();
}
@ -543,7 +543,7 @@ void PostProcessing::applyMLAA()
// Pass 1: color edge detection
glUseProgram(FullScreenShader::MLAAColorEdgeDetectionSHader::getInstance()->Program);
FullScreenShader::MLAAColorEdgeDetectionSHader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getRenderTargetTexture(RTT_MLAA_COLORS)));
FullScreenShader::MLAAColorEdgeDetectionSHader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_MLAA_COLORS));
FullScreenShader::MLAAColorEdgeDetectionSHader::getInstance()->setUniforms(PIXEL_SIZE);
glBindVertexArray(FullScreenShader::MLAAColorEdgeDetectionSHader::getInstance()->vao);
@ -557,7 +557,7 @@ void PostProcessing::applyMLAA()
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(FullScreenShader::MLAABlendWeightSHader::getInstance()->Program);
FullScreenShader::MLAABlendWeightSHader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getRenderTargetTexture(RTT_MLAA_TMP), getTextureGLuint(m_areamap)));
FullScreenShader::MLAABlendWeightSHader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_MLAA_TMP), getTextureGLuint(m_areamap));
FullScreenShader::MLAABlendWeightSHader::getInstance()->setUniforms(PIXEL_SIZE);
glBindVertexArray(FullScreenShader::MLAABlendWeightSHader::getInstance()->vao);
@ -570,7 +570,7 @@ void PostProcessing::applyMLAA()
irr_driver->getFBO(FBO_MLAA_COLORS).Bind();
glUseProgram(FullScreenShader::MLAAGatherSHader::getInstance()->Program);
FullScreenShader::MLAAGatherSHader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getRenderTargetTexture(RTT_MLAA_BLEND), irr_driver->getRenderTargetTexture(RTT_MLAA_TMP)));
FullScreenShader::MLAAGatherSHader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_MLAA_BLEND), irr_driver->getRenderTargetTexture(RTT_MLAA_TMP));
FullScreenShader::MLAAGatherSHader::getInstance()->setUniforms(PIXEL_SIZE);
glBindVertexArray(FullScreenShader::MLAAGatherSHader::getInstance()->vao);
@ -704,8 +704,8 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, boo
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
FullScreenShader::BloomBlendShader::getInstance()->SetTextureUnits(createVector<GLuint>(
irr_driver->getRenderTargetTexture(RTT_BLOOM_128), irr_driver->getRenderTargetTexture(RTT_BLOOM_256), irr_driver->getRenderTargetTexture(RTT_BLOOM_512) ));
FullScreenShader::BloomBlendShader::getInstance()->SetTextureUnits(
irr_driver->getRenderTargetTexture(RTT_BLOOM_128), irr_driver->getRenderTargetTexture(RTT_BLOOM_256), irr_driver->getRenderTargetTexture(RTT_BLOOM_512));
DrawFullScreenEffect<FullScreenShader::BloomBlendShader>();
glDisable(GL_BLEND);

View File

@ -63,140 +63,202 @@ struct DefaultMaterial
{
typedef MeshShader::InstancedObjectPass1Shader InstancedFirstPassShader;
typedef MeshShader::InstancedObjectPass2Shader InstancedSecondPassShader;
typedef MeshShader::InstancedShadowShader InstancedShadowPassShader;
typedef MeshShader::InstancedRSMShader InstancedRSMShader;
typedef ListInstancedMatDefault InstancedList;
typedef MeshShader::ObjectPass1Shader FirstPassShader;
typedef MeshShader::ObjectPass2Shader SecondPassShader;
typedef MeshShader::ShadowShader ShadowPassShader;
typedef MeshShader::RSMShader RSMShader;
typedef ListMatDefault List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD;
static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_SOLID;
static const enum InstanceType Instance = InstanceTypeDualTex;
static const std::vector<size_t> FirstPassTextures;
static const std::vector<size_t> SecondPassTextures;
static const STK::Tuple<size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
};
const std::vector<size_t> DefaultMaterial::FirstPassTextures = { 1 };
const std::vector<size_t> DefaultMaterial::SecondPassTextures = { 0, 1 };
const STK::Tuple<size_t> DefaultMaterial::FirstPassTextures = STK::Tuple<size_t>(1);
const STK::Tuple<size_t, size_t> DefaultMaterial::SecondPassTextures = STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<> DefaultMaterial::ShadowTextures;
const STK::Tuple<size_t> DefaultMaterial::RSMTextures = STK::Tuple<size_t>(0);
struct AlphaRef
{
typedef MeshShader::InstancedObjectRefPass1Shader InstancedFirstPassShader;
typedef MeshShader::InstancedObjectRefPass2Shader InstancedSecondPassShader;
typedef MeshShader::InstancedRefShadowShader InstancedShadowPassShader;
typedef MeshShader::InstancedRSMShader InstancedRSMShader;
typedef ListInstancedMatAlphaRef InstancedList;
typedef MeshShader::ObjectRefPass1Shader FirstPassShader;
typedef MeshShader::ObjectRefPass2Shader SecondPassShader;
typedef MeshShader::RefShadowShader ShadowPassShader;
typedef MeshShader::RSMShader RSMShader;
typedef ListMatAlphaRef List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD;
static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_ALPHA_TEST;
static const enum InstanceType Instance = InstanceTypeDualTex;
static const std::vector<size_t> FirstPassTextures;
static const std::vector<size_t> SecondPassTextures;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t> SecondPassTextures;
static const STK::Tuple<size_t> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
};
const std::vector<size_t> AlphaRef::FirstPassTextures = { 0, 1 };
const std::vector<size_t> AlphaRef::SecondPassTextures = { 0, 1 };
const STK::Tuple<size_t, size_t> AlphaRef::FirstPassTextures = STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t, size_t> AlphaRef::SecondPassTextures = STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t> AlphaRef::ShadowTextures = STK::Tuple<size_t>(0);
const STK::Tuple<size_t> AlphaRef::RSMTextures = STK::Tuple<size_t>(0);
struct SphereMap
{
typedef MeshShader::InstancedObjectPass1Shader InstancedFirstPassShader;
typedef MeshShader::InstancedSphereMapShader InstancedSecondPassShader;
typedef MeshShader::InstancedShadowShader InstancedShadowPassShader;
typedef MeshShader::InstancedRSMShader InstancedRSMShader;
typedef ListInstancedMatSphereMap InstancedList;
typedef MeshShader::ObjectPass1Shader FirstPassShader;
typedef MeshShader::SphereMapShader SecondPassShader;
typedef MeshShader::ShadowShader ShadowPassShader;
typedef MeshShader::RSMShader RSMShader;
typedef ListMatSphereMap List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD;
static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_SPHERE_MAP;
static const enum InstanceType Instance = InstanceTypeDualTex;
static const std::vector<size_t> FirstPassTextures;
static const std::vector<size_t> SecondPassTextures;
static const STK::Tuple<size_t> FirstPassTextures;
static const STK::Tuple<size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
};
const std::vector<size_t> SphereMap::FirstPassTextures = { 1 };
const std::vector<size_t> SphereMap::SecondPassTextures = { 0 };
const STK::Tuple<size_t> SphereMap::FirstPassTextures = STK::Tuple<size_t>(1);
const STK::Tuple<size_t> SphereMap::SecondPassTextures = STK::Tuple<size_t>(0);
const STK::Tuple<> SphereMap::ShadowTextures;
const STK::Tuple<size_t> SphereMap::RSMTextures = STK::Tuple<size_t>(0);
struct UnlitMat
{
typedef MeshShader::InstancedObjectRefPass1Shader InstancedFirstPassShader;
typedef MeshShader::InstancedObjectUnlitShader InstancedSecondPassShader;
typedef MeshShader::InstancedRefShadowShader InstancedShadowPassShader;
typedef MeshShader::InstancedRSMShader InstancedRSMShader;
typedef ListInstancedMatUnlit InstancedList;
typedef MeshShader::ObjectRefPass1Shader FirstPassShader;
typedef MeshShader::ObjectUnlitShader SecondPassShader;
typedef MeshShader::RefShadowShader ShadowPassShader;
typedef MeshShader::RSMShader RSMShader;
typedef ListMatUnlit List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD;
static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_SOLID_UNLIT;
static const enum InstanceType Instance = InstanceTypeDualTex;
static const std::vector<size_t> FirstPassTextures;
static const std::vector<size_t> SecondPassTextures;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t> SecondPassTextures;
static const STK::Tuple<size_t> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
};
const std::vector<size_t> UnlitMat::FirstPassTextures = { 0, 1 };
const std::vector<size_t> UnlitMat::SecondPassTextures = { 0 };
const STK::Tuple<size_t, size_t> UnlitMat::FirstPassTextures = STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t> UnlitMat::SecondPassTextures = STK::Tuple<size_t>(0);
const STK::Tuple<size_t> UnlitMat::ShadowTextures = STK::Tuple<size_t>(0);
const STK::Tuple<size_t> UnlitMat::RSMTextures = STK::Tuple<size_t>(0);
struct GrassMat
{
typedef MeshShader::InstancedGrassPass1Shader InstancedFirstPassShader;
typedef MeshShader::InstancedGrassPass2Shader InstancedSecondPassShader;
typedef MeshShader::InstancedGrassShadowShader InstancedShadowPassShader;
typedef MeshShader::InstancedRSMShader InstancedRSMShader;
typedef ListInstancedMatGrass InstancedList;
typedef MeshShader::GrassPass1Shader FirstPassShader;
typedef MeshShader::GrassPass2Shader SecondPassShader;
typedef MeshShader::GrassShadowShader ShadowPassShader;
typedef MeshShader::RSMShader RSMShader;
typedef ListMatGrass List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD;
static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_VEGETATION;
static const enum InstanceType Instance = InstanceTypeDualTex;
static const std::vector<size_t> FirstPassTextures;
static const std::vector<size_t> SecondPassTextures;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t> SecondPassTextures;
static const STK::Tuple<size_t> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
};
const std::vector<size_t> GrassMat::FirstPassTextures = { 0, 1 };
const std::vector<size_t> GrassMat::SecondPassTextures = { 0, 1 };
const STK::Tuple<size_t, size_t> GrassMat::FirstPassTextures = STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t, size_t> GrassMat::SecondPassTextures = STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t> GrassMat::ShadowTextures = STK::Tuple<size_t>(0);
const STK::Tuple<size_t> GrassMat::RSMTextures = STK::Tuple<size_t>(0);
struct NormalMat
{
typedef MeshShader::InstancedNormalMapShader InstancedFirstPassShader;
typedef MeshShader::InstancedObjectPass2Shader InstancedSecondPassShader;
typedef MeshShader::InstancedShadowShader InstancedShadowPassShader;
typedef MeshShader::InstancedRSMShader InstancedRSMShader;
typedef ListInstancedMatNormalMap InstancedList;
typedef MeshShader::NormalMapShader FirstPassShader;
typedef MeshShader::ObjectPass2Shader SecondPassShader;
typedef MeshShader::ShadowShader ShadowPassShader;
typedef MeshShader::RSMShader RSMShader;
typedef ListMatNormalMap List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_TANGENTS;
static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_NORMAL_MAP;
static const enum InstanceType Instance = InstanceTypeThreeTex;
static const std::vector<size_t> FirstPassTextures;
static const std::vector<size_t> SecondPassTextures;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
};
const std::vector<size_t> NormalMat::FirstPassTextures = { 2, 1 };
const std::vector<size_t> NormalMat::SecondPassTextures = { 0, 1 };
const STK::Tuple<size_t, size_t> NormalMat::FirstPassTextures = STK::Tuple<size_t, size_t>(2, 1);
const STK::Tuple<size_t, size_t> NormalMat::SecondPassTextures = STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<> NormalMat::ShadowTextures;
const STK::Tuple<size_t> NormalMat::RSMTextures = STK::Tuple<size_t>(0);
struct DetailMat
{
typedef MeshShader::InstancedObjectPass1Shader InstancedFirstPassShader;
typedef MeshShader::InstancedDetailledObjectPass2Shader InstancedSecondPassShader;
typedef MeshShader::InstancedShadowShader InstancedShadowPassShader;
typedef MeshShader::InstancedRSMShader InstancedRSMShader;
typedef ListInstancedMatDetails InstancedList;
typedef MeshShader::ObjectPass1Shader FirstPassShader;
typedef MeshShader::DetailledObjectPass2Shader SecondPassShader;
typedef MeshShader::ShadowShader ShadowPassShader;
typedef MeshShader::RSMShader RSMShader;
typedef ListMatDetails List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_2TCOORDS;
static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_DETAIL_MAP;
static const enum InstanceType Instance = InstanceTypeThreeTex;
static const std::vector<size_t> FirstPassTextures;
static const std::vector<size_t> SecondPassTextures;
static const STK::Tuple<size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
};
const std::vector<size_t> DetailMat::FirstPassTextures = { 1 };
const std::vector<size_t> DetailMat::SecondPassTextures = { 0, 2, 1 };
const STK::Tuple<size_t> DetailMat::FirstPassTextures = STK::Tuple<size_t>(1);
const STK::Tuple<size_t, size_t, size_t> DetailMat::SecondPassTextures = STK::Tuple<size_t, size_t, size_t>(0, 2, 1);
const STK::Tuple<> DetailMat::ShadowTextures;
const STK::Tuple<size_t> DetailMat::RSMTextures = STK::Tuple<size_t>(0);
struct SplattingMat
{
typedef MeshShader::ObjectPass1Shader FirstPassShader;
typedef MeshShader::SplattingShader SecondPassShader;
typedef MeshShader::ShadowShader ShadowPassShader;
typedef MeshShader::SplattingRSMShader RSMShader;
typedef ListMatSplatting List;
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_2TCOORDS;
static const std::vector<size_t> FirstPassTextures;
static const std::vector<size_t> SecondPassTextures;
static const STK::Tuple<size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t, size_t, size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t, size_t, size_t, size_t, size_t> RSMTextures;
};
const std::vector<size_t> SplattingMat::FirstPassTextures = { 6 };
const std::vector<size_t> SplattingMat::SecondPassTextures = { 1, 2, 3, 4, 5 };
const STK::Tuple<size_t> SplattingMat::FirstPassTextures = STK::Tuple<size_t>(6);
const STK::Tuple<size_t, size_t, size_t, size_t, size_t> SplattingMat::SecondPassTextures = STK::Tuple<size_t, size_t, size_t, size_t, size_t>(1, 2, 3, 4, 5);
const STK::Tuple<> SplattingMat::ShadowTextures;
const STK::Tuple<size_t, size_t, size_t, size_t, size_t> SplattingMat::RSMTextures = STK::Tuple<size_t, size_t, size_t, size_t, size_t>(1, 2, 3, 4, 5);
namespace RenderGeometry
{
@ -280,11 +342,72 @@ struct custom_unroll_args<N, List...>
}
};
template<typename T, int N>
struct TexExpander_impl
{
template<typename...TupleArgs, typename... Args>
static void ExpandTex(GLMesh &mesh, const STK::Tuple<TupleArgs...> &TexSwizzle, Args... args)
{
size_t idx = STK::tuple_get<sizeof...(TupleArgs) - N>(TexSwizzle);
TexExpander_impl<T, N - 1>::template ExpandTex(mesh, TexSwizzle, args..., getTextureGLuint(mesh.textures[idx]));
}
};
template<typename T>
struct TexExpander_impl<T, 0>
{
template<typename...TupleArgs, typename... Args>
static void ExpandTex(GLMesh &mesh, const STK::Tuple<TupleArgs...> &TexSwizzle, Args... args)
{
T::getInstance()->SetTextureUnits(args...);
}
};
template<typename T>
struct TexExpander
{
template<typename...TupleArgs, typename... Args>
static void ExpandTex(GLMesh &mesh, const STK::Tuple<TupleArgs...> &TexSwizzle, Args... args)
{
TexExpander_impl<T, sizeof...(TupleArgs)>::ExpandTex(mesh, TexSwizzle, args...);
}
};
template<typename T, int N>
struct HandleExpander_impl
{
template<typename...TupleArgs, typename... Args>
static void Expand(uint64_t *TextureHandles, const STK::Tuple<TupleArgs...> &TexSwizzle, Args... args)
{
size_t idx = STK::tuple_get<sizeof...(TupleArgs)-N>(TexSwizzle);
HandleExpander_impl<T, N - 1>::template Expand(TextureHandles, TexSwizzle, args..., TextureHandles[idx]);
}
};
template<typename T>
struct HandleExpander_impl<T, 0>
{
template<typename...TupleArgs, typename... Args>
static void Expand(uint64_t *TextureHandles, const STK::Tuple<TupleArgs...> &TexSwizzle, Args... args)
{
T::getInstance()->SetTextureHandles(args...);
}
};
template<typename T>
struct HandleExpander
{
template<typename...TupleArgs, typename... Args>
static void Expand(uint64_t *TextureHandles, const STK::Tuple<TupleArgs...> &TexSwizzle, Args... args)
{
HandleExpander_impl<T, sizeof...(TupleArgs)>::Expand(TextureHandles, TexSwizzle, args...);
}
};
template<typename T, int ...List>
void renderMeshes1stPass()
{
const std::vector<size_t> &TexUnits = T::FirstPassTextures;
auto &meshes = T::List::getInstance()->SolidPass;
glUseProgram(T::FirstPassShader::getInstance()->Program);
if (irr_driver->hasARB_base_instance())
@ -296,13 +419,6 @@ void renderMeshes1stPass()
GLMesh &mesh = *(STK::tuple_get<0>(meshes.at(i)));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh.vao);
for (unsigned j = 0; j < TexUnits.size(); j++)
{
if (UserConfigParams::m_azdo)
Handles.push_back(mesh.TextureHandles[TexUnits[j]]);
else
Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j]]));
}
if (mesh.VAOType != T::VertexType)
{
#ifdef DEBUG
@ -312,9 +428,9 @@ void renderMeshes1stPass()
}
if (UserConfigParams::m_azdo)
T::FirstPassShader::getInstance()->SetTextureHandles(Handles);
HandleExpander<typename T::FirstPassShader>::template Expand(mesh.TextureHandles, T::FirstPassTextures);
else
T::FirstPassShader::getInstance()->SetTextureUnits(Textures);
TexExpander<typename T::FirstPassShader>::template ExpandTex(mesh, T::FirstPassTextures);
custom_unroll_args<List...>::template exec(T::FirstPassShader::getInstance(), meshes.at(i));
}
}
@ -322,7 +438,6 @@ void renderMeshes1stPass()
template<typename T, typename...Args>
void renderInstancedMeshes1stPass(Args...args)
{
const std::vector<size_t> &TexUnits = T::FirstPassTextures;
std::vector<GLMesh *> &meshes = T::InstancedList::getInstance()->SolidPass;
glUseProgram(T::InstancedFirstPassShader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, T::Instance));
@ -335,9 +450,7 @@ void renderInstancedMeshes1stPass(Args...args)
Log::error("RenderGeometry", "Wrong instanced vertex format (hint : %s)",
mesh->textures[0]->getName().getPath().c_str());
#endif
for (unsigned j = 0; j < TexUnits.size(); j++)
Textures.push_back(getTextureGLuint(mesh->textures[TexUnits[j]]));
T::InstancedFirstPassShader::getInstance()->SetTextureUnits(Textures);
TexExpander<typename T::InstancedFirstPassShader>::template ExpandTex(*mesh, T::FirstPassTextures);
T::InstancedFirstPassShader::getInstance()->setUniforms(args...);
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((SolidPassCmd::getInstance()->Offset[T::MaterialType] + i) * sizeof(DrawElementsIndirectCommand)));
@ -412,25 +525,15 @@ template<typename T, int...List>
void renderMeshes2ndPass( const std::vector<uint64_t> &Prefilled_Handle,
const std::vector<GLuint> &Prefilled_Tex)
{
const std::vector<size_t> &TexUnits = T::SecondPassTextures;
auto &meshes = T::List::getInstance()->SolidPass;
glUseProgram(T::SecondPassShader::getInstance()->Program);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getVAO(T::VertexType));
for (unsigned i = 0; i < meshes.size(); i++)
{
std::vector<uint64_t> Handles(Prefilled_Handle);
std::vector<GLuint> Textures(Prefilled_Tex);
GLMesh &mesh = *(STK::tuple_get<0>(meshes.at(i)));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh.vao);
for (unsigned j = 0; j < TexUnits.size(); j++)
{
if (UserConfigParams::m_azdo)
Handles.push_back(mesh.TextureHandles[TexUnits[j]]);
else
Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j]]));
}
if (mesh.VAOType != T::VertexType)
{
@ -441,9 +544,9 @@ void renderMeshes2ndPass( const std::vector<uint64_t> &Prefilled_Handle,
}
if (UserConfigParams::m_azdo)
T::SecondPassShader::getInstance()->SetTextureHandles(Handles);
HandleExpander<typename T::SecondPassShader>::template Expand(mesh.TextureHandles, T::SecondPassTextures, Prefilled_Handle[0], Prefilled_Handle[1], Prefilled_Handle[2]);
else
T::SecondPassShader::getInstance()->SetTextureUnits(Textures);
TexExpander<typename T::SecondPassShader>::template ExpandTex(mesh, T::SecondPassTextures, Prefilled_Tex[0], Prefilled_Tex[1], Prefilled_Tex[2]);
custom_unroll_args<List...>::template exec(T::SecondPassShader::getInstance(), meshes.at(i));
}
}
@ -452,29 +555,27 @@ template<typename T, typename...Args>
void renderInstancedMeshes2ndPass(const std::vector<GLuint> &Prefilled_tex, Args...args)
{
std::vector<GLMesh *> &meshes = T::InstancedList::getInstance()->SolidPass;
const std::vector<size_t> &TexUnits = T::SecondPassTextures;
glUseProgram(T::InstancedSecondPassShader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, T::Instance));
for (unsigned i = 0; i < meshes.size(); i++)
{
GLMesh *mesh = meshes[i];
std::vector<GLuint> Textures(Prefilled_tex);
for (unsigned j = 0; j < TexUnits.size(); j++)
Textures.push_back(getTextureGLuint(mesh->textures[TexUnits[j]]));
T::InstancedSecondPassShader::getInstance()->SetTextureUnits(Textures);
TexExpander<typename T::InstancedSecondPassShader>::template ExpandTex(*mesh, T::SecondPassTextures, Prefilled_tex[0], Prefilled_tex[1], Prefilled_tex[2]);
T::InstancedSecondPassShader::getInstance()->setUniforms(args...);
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((SolidPassCmd::getInstance()->Offset[T::MaterialType] + i) * sizeof(DrawElementsIndirectCommand)));
}
}
template<typename T, typename...Args>
void multidraw2ndPass(const std::vector<uint64_t> &Handles, Args... args)
{
glUseProgram(T::InstancedSecondPassShader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, T::Instance));
uint64_t nulltex[10] = {};
if (SolidPassCmd::getInstance()->Size[T::MaterialType])
{
T::InstancedSecondPassShader::getInstance()->SetTextureHandles(Handles);
HandleExpander<typename T::InstancedSecondPassShader>::template Expand(nulltex, T::SecondPassTextures, Handles[0], Handles[1], Handles[2]);
T::InstancedSecondPassShader::getInstance()->setUniforms(args...);
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT,
(const void*)(SolidPassCmd::getInstance()->Offset[T::MaterialType] * sizeof(DrawElementsIndirectCommand)),
@ -535,11 +636,25 @@ void IrrDriver::renderSolidSecondPass()
multidraw2ndPass<AlphaRef>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0, 0));
multidraw2ndPass<SphereMap>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
multidraw2ndPass<UnlitMat>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
multidraw2ndPass<GrassMat>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, DepthHandle, 0, 0), windDir, cb->getPosition());
multidraw2ndPass<NormalMat>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0, 0));
multidraw2ndPass<DetailMat>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0, 0, 0));
// template does not work with template due to extra depth texture
{
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
glUseProgram(GrassMat::InstancedSecondPassShader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(GrassMat::VertexType, GrassMat::Instance));
uint64_t nulltex[10] = {};
if (SolidPassCmd::getInstance()->Size[GrassMat::MaterialType])
{
HandleExpander<GrassMat::InstancedSecondPassShader>::Expand(nulltex, GrassMat::SecondPassTextures, DiffuseHandle, SpecularHandle, SSAOHandle, DepthHandle);
GrassMat::InstancedSecondPassShader::getInstance()->setUniforms(windDir, cb->getPosition());
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT,
(const void*)(SolidPassCmd::getInstance()->Offset[GrassMat::MaterialType] * sizeof(DrawElementsIndirectCommand)),
(int)SolidPassCmd::getInstance()->Size[GrassMat::MaterialType],
(int)sizeof(DrawElementsIndirectCommand));
}
}
}
else if (irr_driver->hasARB_draw_indirect())
{
@ -547,12 +662,23 @@ void IrrDriver::renderSolidSecondPass()
renderInstancedMeshes2ndPass<AlphaRef>(DiffSpecSSAOTex);
renderInstancedMeshes2ndPass<UnlitMat>(DiffSpecSSAOTex);
renderInstancedMeshes2ndPass<SphereMap>(DiffSpecSSAOTex);
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
DiffSpecSSAOTex.push_back(irr_driver->getDepthStencilTexture());
renderInstancedMeshes2ndPass<GrassMat>(DiffSpecSSAOTex, windDir, cb->getPosition());
DiffSpecSSAOTex.pop_back();
renderInstancedMeshes2ndPass<DetailMat>(DiffSpecSSAOTex);
renderInstancedMeshes2ndPass<NormalMat>(DiffSpecSSAOTex);
// template does not work with template due to extra depth texture
{
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
std::vector<GLMesh *> &meshes = GrassMat::InstancedList::getInstance()->SolidPass;
glUseProgram(GrassMat::InstancedSecondPassShader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(GrassMat::VertexType, GrassMat::Instance));
for (unsigned i = 0; i < meshes.size(); i++)
{
GLMesh *mesh = meshes[i];
TexExpander<GrassMat::InstancedSecondPassShader>::ExpandTex(*mesh, GrassMat::SecondPassTextures, DiffSpecSSAOTex[0], DiffSpecSSAOTex[1], DiffSpecSSAOTex[2], irr_driver->getDepthStencilTexture());
GrassMat::InstancedSecondPassShader::getInstance()->setUniforms(windDir, cb->getPosition());
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((SolidPassCmd::getInstance()->Offset[GrassMat::MaterialType] + i) * sizeof(DrawElementsIndirectCommand)));
}
}
}
}
}
@ -597,28 +723,9 @@ void renderTransparenPass(const std::vector<TexUnit> &TexUnits, std::vector<STK:
glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType));
for (unsigned i = 0; i < meshes->size(); i++)
{
std::vector<uint64_t> Handles;
std::vector<GLuint> Textures;
GLMesh &mesh = *(STK::tuple_get<0>(meshes->at(i)));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh.vao);
for (unsigned j = 0; j < TexUnits.size(); j++)
{
if (!mesh.textures[TexUnits[j].m_id])
mesh.textures[TexUnits[j].m_id] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[TexUnits[j].m_id], TexUnits[j].m_premul_alpha);
if (UserConfigParams::m_azdo)
{
if (!mesh.TextureHandles[TexUnits[j].m_id])
mesh.TextureHandles[TexUnits[j].m_id] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[TexUnits[j].m_id]), Shader::getInstance()->SamplersId[Handles.size()]);
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[TexUnits[j].m_id]))
glMakeTextureHandleResidentARB(mesh.TextureHandles[TexUnits[j].m_id]);
Handles.push_back(mesh.TextureHandles[TexUnits[j].m_id]);
}
else
Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j].m_id]));
}
if (mesh.VAOType != VertexType)
{
#ifdef DEBUG
@ -628,9 +735,9 @@ void renderTransparenPass(const std::vector<TexUnit> &TexUnits, std::vector<STK:
}
if (UserConfigParams::m_azdo)
Shader::getInstance()->SetTextureHandles(Handles);
Shader::getInstance()->SetTextureHandles(mesh.TextureHandles[0]);
else
Shader::getInstance()->SetTextureUnits(Textures);
Shader::getInstance()->SetTextureUnits(getTextureGLuint(mesh.textures[0]));
custom_unroll_args<List...>::template exec(Shader::getInstance(), meshes->at(i));
}
}
@ -741,10 +848,10 @@ void IrrDriver::renderTransparent()
size_t count = mesh.IndexCount;
// Render the effect
MeshShader::DisplaceShader::getInstance()->SetTextureUnits(
createVector<GLuint>(getTextureGLuint(displaceTex),
irr_driver->getRenderTargetTexture(RTT_COLOR),
irr_driver->getRenderTargetTexture(RTT_TMP1),
getTextureGLuint(mesh.textures[0])));
getTextureGLuint(displaceTex),
irr_driver->getRenderTargetTexture(RTT_COLOR),
irr_driver->getRenderTargetTexture(RTT_TMP1),
getTextureGLuint(mesh.textures[0]));
glUseProgram(MeshShader::DisplaceShader::getInstance()->Program);
MeshShader::DisplaceShader::getInstance()->setUniforms(AbsoluteTransformation,
core::vector2df(cb->getDirX(), cb->getDirY()),
@ -795,67 +902,55 @@ struct shadow_custom_unroll_args<N, List...>
}
};
template<typename T, enum video::E_VERTEX_TYPE VertexType, int...List, typename... Args>
void renderShadow(const std::vector<GLuint> TextureUnits, unsigned cascade, const std::vector<STK::Tuple<Args...> > &t)
template<typename T, int...List>
void renderShadow(unsigned cascade)
{
glUseProgram(T::getInstance()->Program);
auto &t = T::List::getInstance()->Shadows[cascade];
glUseProgram(T::ShadowPassShader::getInstance()->Program);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType));
glBindVertexArray(VAOManager::getInstance()->getVAO(T::VertexType));
for (unsigned i = 0; i < t.size(); i++)
{
std::vector<uint64_t> Handles;
std::vector<GLuint> Textures;
GLMesh *mesh = STK::tuple_get<0>(t.at(i));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh->vao);
for (unsigned j = 0; j < TextureUnits.size(); j++)
{
compressTexture(mesh->textures[TextureUnits[j]], true);
if (UserConfigParams::m_azdo)
Handles.push_back(mesh->TextureHandles[TextureUnits[j]]);
else
Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]]));
}
if (UserConfigParams::m_azdo)
T::getInstance()->SetTextureHandles(Handles);
HandleExpander<typename T::ShadowPassShader>::template Expand(mesh->TextureHandles, T::ShadowTextures);
else
T::getInstance()->SetTextureUnits(Textures);
shadow_custom_unroll_args<List...>::template exec<T>(T::getInstance(), cascade, t.at(i));
TexExpander<typename T::ShadowPassShader>::template ExpandTex(*mesh, T::ShadowTextures);
shadow_custom_unroll_args<List...>::template exec<typename T::ShadowPassShader>(T::ShadowPassShader::getInstance(), cascade, t.at(i));
}
}
template<typename Shader, Material::ShaderType Mat, video::E_VERTEX_TYPE VT, typename...Args>
void renderInstancedShadow(const std::vector<GLuint> TextureUnits, unsigned cascade, const std::vector<GLMesh *> &t, Args ...args)
template<typename T, typename...Args>
void renderInstancedShadow(unsigned cascade, Args ...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeShadow));
glUseProgram(T::InstancedShadowPassShader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, InstanceTypeShadow));
std::vector<GLMesh *> &t = T::InstancedList::getInstance()->Shadows[cascade];
for (unsigned i = 0; i < t.size(); i++)
{
std::vector<uint64_t> Handles;
std::vector<GLuint> Textures;
GLMesh *mesh = t[i];
for (unsigned j = 0; j < TextureUnits.size(); j++)
Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]]));
Shader::getInstance()->SetTextureUnits(Textures);
Shader::getInstance()->setUniforms(cascade, args...);
size_t tmp = ShadowPassCmd::getInstance()->Offset[cascade][Mat] + i;
TexExpander<typename T::InstancedShadowPassShader>::template ExpandTex(*mesh, T::ShadowTextures);
T::InstancedShadowPassShader::getInstance()->setUniforms(cascade, args...);
size_t tmp = ShadowPassCmd::getInstance()->Offset[cascade][T::MaterialType] + i;
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((tmp) * sizeof(DrawElementsIndirectCommand)));
}
}
template<typename Shader, Material::ShaderType Mat, video::E_VERTEX_TYPE VT, typename...Args>
template<typename T, typename...Args>
static void multidrawShadow(unsigned i, Args ...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeShadow));
if (ShadowPassCmd::getInstance()->Size[i][Mat])
glUseProgram(T::InstancedShadowPassShader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, InstanceTypeShadow));
if (ShadowPassCmd::getInstance()->Size[i][T::MaterialType])
{
Shader::getInstance()->setUniforms(i, args...);
T::InstancedShadowPassShader::getInstance()->setUniforms(i, args...);
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT,
(const void*)(ShadowPassCmd::getInstance()->Offset[i][Mat] * sizeof(DrawElementsIndirectCommand)),
(int)ShadowPassCmd::getInstance()->Size[i][Mat], sizeof(DrawElementsIndirectCommand));
(const void*)(ShadowPassCmd::getInstance()->Offset[i][T::MaterialType] * sizeof(DrawElementsIndirectCommand)),
(int)ShadowPassCmd::getInstance()->Size[i][T::MaterialType], sizeof(DrawElementsIndirectCommand));
}
}
@ -875,37 +970,36 @@ void IrrDriver::renderShadows()
for (unsigned cascade = 0; cascade < 4; cascade++)
{
ScopedGPUTimer Timer(getGPUTimer(Q_SHADOWS_CASCADE0 + cascade));
std::vector<GLuint> noTexUnits;
renderShadow<MeshShader::ShadowShader, video::EVT_STANDARD, 1>(noTexUnits, cascade, ListMatDefault::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::ShadowShader, video::EVT_STANDARD, 1>(noTexUnits, cascade, ListMatSphereMap::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::ShadowShader, video::EVT_2TCOORDS, 1>(noTexUnits, cascade, ListMatDetails::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::ShadowShader, video::EVT_2TCOORDS, 1>(noTexUnits, cascade, ListMatSplatting::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::ShadowShader, video::EVT_TANGENTS, 1>(noTexUnits, cascade, ListMatNormalMap::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::RefShadowShader, video::EVT_STANDARD, 1>(std::vector<GLuint>{ 0 }, cascade, ListMatAlphaRef::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::RefShadowShader, video::EVT_STANDARD, 1>(std::vector<GLuint>{ 0 }, cascade, ListMatUnlit::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::GrassShadowShader, video::EVT_STANDARD, 3, 1>(std::vector<GLuint>{ 0 }, cascade, ListMatGrass::getInstance()->Shadows[cascade]);
renderShadow<DefaultMaterial, 1>(cascade);
renderShadow<SphereMap, 1>(cascade);
renderShadow<DetailMat, 1>(cascade);
renderShadow<SplattingMat, 1>(cascade);
renderShadow<NormalMat, 1>(cascade);
renderShadow<AlphaRef, 1>(cascade);
renderShadow<UnlitMat, 1>(cascade);
renderShadow<GrassMat, 3, 1>(cascade);
if (irr_driver->hasARB_draw_indirect())
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, ShadowPassCmd::getInstance()->drawindirectcmd);
if (UserConfigParams::m_azdo)
{
multidrawShadow<MeshShader::InstancedShadowShader, Material::SHADERTYPE_SOLID, video::EVT_STANDARD>(cascade);
multidrawShadow<MeshShader::InstancedShadowShader, Material::SHADERTYPE_DETAIL_MAP, video::EVT_2TCOORDS>(cascade);
multidrawShadow<MeshShader::InstancedShadowShader, Material::SHADERTYPE_NORMAL_MAP, video::EVT_TANGENTS>(cascade);
multidrawShadow<MeshShader::InstancedRefShadowShader, Material::SHADERTYPE_ALPHA_TEST, video::EVT_STANDARD>(cascade);
multidrawShadow<MeshShader::InstancedRefShadowShader, Material::SHADERTYPE_SOLID_UNLIT, video::EVT_STANDARD>(cascade);
multidrawShadow<MeshShader::InstancedGrassShadowShader, Material::SHADERTYPE_VEGETATION, video::EVT_STANDARD>(cascade, windDir);
multidrawShadow<DefaultMaterial>(cascade);
multidrawShadow<DetailMat>(cascade);
multidrawShadow<NormalMat>(cascade);
multidrawShadow<AlphaRef>(cascade);
multidrawShadow<UnlitMat>(cascade);
multidrawShadow<GrassMat>(cascade, windDir);
}
else if (irr_driver->hasARB_draw_indirect())
{
renderInstancedShadow<MeshShader::InstancedShadowShader, Material::SHADERTYPE_SOLID, video::EVT_STANDARD>(noTexUnits, cascade, ListInstancedMatDefault::getInstance()->Shadows[cascade]);
renderInstancedShadow<MeshShader::InstancedShadowShader, Material::SHADERTYPE_DETAIL_MAP, video::EVT_2TCOORDS>(noTexUnits, cascade, ListInstancedMatDetails::getInstance()->Shadows[cascade]);
renderInstancedShadow<MeshShader::InstancedRefShadowShader, Material::SHADERTYPE_ALPHA_TEST, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, cascade, ListInstancedMatAlphaRef::getInstance()->Shadows[cascade]);
renderInstancedShadow<MeshShader::InstancedRefShadowShader, Material::SHADERTYPE_SOLID_UNLIT, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, cascade, ListInstancedMatUnlit::getInstance()->Shadows[cascade]);
renderInstancedShadow<MeshShader::InstancedGrassShadowShader, Material::SHADERTYPE_VEGETATION, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, cascade, ListInstancedMatGrass::getInstance()->Shadows[cascade], windDir);
renderInstancedShadow<MeshShader::InstancedShadowShader, Material::SHADERTYPE_NORMAL_MAP, video::EVT_TANGENTS>(noTexUnits, cascade, ListInstancedMatNormalMap::getInstance()->Shadows[cascade]);
renderInstancedShadow<DefaultMaterial>(cascade);
renderInstancedShadow<DetailMat>(cascade);
renderInstancedShadow<AlphaRef>(cascade);
renderInstancedShadow<UnlitMat>(cascade);
renderInstancedShadow<GrassMat>(cascade, windDir);
renderInstancedShadow<NormalMat>(cascade);
}
}
@ -937,56 +1031,55 @@ struct rsm_custom_unroll_args<N, List...>
}
};
template<typename T, enum video::E_VERTEX_TYPE VertexType, int... Selector, typename... Args>
void drawRSM(const core::matrix4 & rsm_matrix, const std::vector<GLuint> &TextureUnits, const std::vector<STK::Tuple<Args...> > &t)
template<typename T, int... Selector>
void drawRSM(const core::matrix4 & rsm_matrix)
{
glUseProgram(T::getInstance()->Program);
glUseProgram(T::RSMShader::getInstance()->Program);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType));
glBindVertexArray(VAOManager::getInstance()->getVAO(T::VertexType));
auto t = T::List::getInstance()->RSM;
for (unsigned i = 0; i < t.size(); i++)
{
std::vector<GLuint> Textures;
GLMesh *mesh = STK::tuple_get<0>(t.at(i));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh->vao);
for (unsigned j = 0; j < TextureUnits.size(); j++)
Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]]));
T::getInstance()->SetTextureUnits(Textures);
rsm_custom_unroll_args<Selector...>::template exec<T>(rsm_matrix, t.at(i));
if (UserConfigParams::m_azdo)
HandleExpander<typename T::RSMShader>::template Expand(mesh->TextureHandles, T::RSMTextures);
else
TexExpander<typename T::RSMShader>::template ExpandTex(*mesh, T::RSMTextures);
rsm_custom_unroll_args<Selector...>::template exec<typename T::RSMShader>(rsm_matrix, t.at(i));
}
}
template<typename Shader, Material::ShaderType Mat, video::E_VERTEX_TYPE VT, typename...Args>
void renderRSMShadow(const std::vector<GLuint> TextureUnits, const std::vector<GLMesh *> &t, Args ...args)
template<typename T, typename...Args>
void renderRSMShadow(Args ...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeRSM));
glUseProgram(T::InstancedRSMShader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, InstanceTypeRSM));
auto t = T::InstancedList::getInstance()->RSM;
for (unsigned i = 0; i < t.size(); i++)
{
std::vector<uint64_t> Handles;
std::vector<GLuint> Textures;
GLMesh *mesh = t[i];
for (unsigned j = 0; j < TextureUnits.size(); j++)
Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]]));
Shader::getInstance()->SetTextureUnits(Textures);
Shader::getInstance()->setUniforms(args...);
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((RSMPassCmd::getInstance()->Offset[Mat] + i)* sizeof(DrawElementsIndirectCommand)));
TexExpander<typename T::InstancedRSMShader>::template ExpandTex(*mesh, T::RSMTextures);
T::InstancedRSMShader::getInstance()->setUniforms(args...);
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((RSMPassCmd::getInstance()->Offset[T::MaterialType] + i)* sizeof(DrawElementsIndirectCommand)));
}
}
template<typename Shader, Material::ShaderType Mat, enum video::E_VERTEX_TYPE VertexType, typename... Args>
template<typename T, typename... Args>
void multidrawRSM(Args...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VertexType, InstanceTypeRSM));
if (RSMPassCmd::getInstance()->Size[Mat])
glUseProgram(T::InstancedRSMShader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, InstanceTypeRSM));
if (RSMPassCmd::getInstance()->Size[T::MaterialType])
{
Shader::getInstance()->setUniforms(args...);
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT,
(const void*)(RSMPassCmd::getInstance()->Offset[Mat] * sizeof(DrawElementsIndirectCommand)),
(int)RSMPassCmd::getInstance()->Size[Mat], sizeof(DrawElementsIndirectCommand));
T::InstancedRSMShader::getInstance()->setUniforms(args...);
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT,
(const void*)(RSMPassCmd::getInstance()->Offset[T::MaterialType] * sizeof(DrawElementsIndirectCommand)),
(int)RSMPassCmd::getInstance()->Size[T::MaterialType], sizeof(DrawElementsIndirectCommand));
}
}
@ -996,30 +1089,30 @@ void IrrDriver::renderRSM()
m_rtts->getRSM().Bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawRSM<MeshShader::RSMShader, video::EVT_STANDARD, 3, 1>(rsm_matrix, std::vector<GLuint>{ 0 }, ListMatDefault::getInstance()->RSM);
drawRSM<MeshShader::RSMShader, video::EVT_STANDARD, 3, 1>(rsm_matrix, std::vector<GLuint>{ 0 }, ListMatAlphaRef::getInstance()->RSM);
drawRSM<MeshShader::RSMShader, video::EVT_TANGENTS, 3, 1>(rsm_matrix, std::vector<GLuint>{ 0 }, ListMatNormalMap::getInstance()->RSM);
drawRSM<MeshShader::RSMShader, video::EVT_STANDARD, 3, 1>(rsm_matrix, std::vector<GLuint>{ 0 }, ListMatUnlit::getInstance()->RSM);
drawRSM<MeshShader::RSMShader, video::EVT_2TCOORDS, 3, 1>(rsm_matrix, std::vector<GLuint>{ 0 }, ListMatDetails::getInstance()->RSM);
drawRSM<MeshShader::SplattingRSMShader, video::EVT_2TCOORDS, 1>(rsm_matrix, createVector<GLuint>(1, 2, 3, 4, 5), ListMatSplatting::getInstance()->RSM);
drawRSM<DefaultMaterial, 3, 1>(rsm_matrix);
drawRSM<AlphaRef, 3, 1>(rsm_matrix);
drawRSM<NormalMat, 3, 1>(rsm_matrix);
drawRSM<UnlitMat, 3, 1>(rsm_matrix);
drawRSM<DetailMat, 3, 1>(rsm_matrix);
drawRSM<SplattingMat, 1>(rsm_matrix);
if (irr_driver->hasARB_draw_indirect())
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, RSMPassCmd::getInstance()->drawindirectcmd);
if (UserConfigParams::m_azdo)
{
multidrawRSM<MeshShader::InstancedRSMShader, Material::SHADERTYPE_SOLID, video::EVT_STANDARD>(rsm_matrix);
multidrawRSM<MeshShader::InstancedRSMShader, Material::SHADERTYPE_NORMAL_MAP, video::EVT_TANGENTS>(rsm_matrix);
multidrawRSM<MeshShader::InstancedRSMShader, Material::SHADERTYPE_ALPHA_TEST, video::EVT_STANDARD>(rsm_matrix);
multidrawRSM<MeshShader::InstancedRSMShader, Material::SHADERTYPE_SOLID_UNLIT, video::EVT_STANDARD>(rsm_matrix);
multidrawRSM<MeshShader::InstancedRSMShader, Material::SHADERTYPE_DETAIL_MAP, video::EVT_2TCOORDS>(rsm_matrix);
multidrawRSM<DefaultMaterial>(rsm_matrix);
multidrawRSM<NormalMat>(rsm_matrix);
multidrawRSM<AlphaRef>(rsm_matrix);
multidrawRSM<UnlitMat>(rsm_matrix);
multidrawRSM<DetailMat>(rsm_matrix);
}
else if (irr_driver->hasARB_draw_indirect())
{
renderRSMShadow<MeshShader::InstancedRSMShader, Material::SHADERTYPE_SOLID, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, ListInstancedMatDefault::getInstance()->RSM, rsm_matrix);
renderRSMShadow<MeshShader::InstancedRSMShader, Material::SHADERTYPE_ALPHA_TEST, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, ListInstancedMatAlphaRef::getInstance()->RSM, rsm_matrix);
renderRSMShadow<MeshShader::InstancedRSMShader, Material::SHADERTYPE_SOLID_UNLIT, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, ListInstancedMatUnlit::getInstance()->RSM, rsm_matrix);
renderRSMShadow<MeshShader::InstancedRSMShader, Material::SHADERTYPE_NORMAL_MAP, video::EVT_TANGENTS>(std::vector < GLuint > { 0 }, ListInstancedMatNormalMap::getInstance()->RSM, rsm_matrix);
renderRSMShadow<MeshShader::InstancedRSMShader, Material::SHADERTYPE_DETAIL_MAP, video::EVT_2TCOORDS>(std::vector < GLuint > { 0 }, ListInstancedMatDetails::getInstance()->RSM, rsm_matrix);
renderRSMShadow<DefaultMaterial>(rsm_matrix);
renderRSMShadow<AlphaRef>(rsm_matrix);
renderRSMShadow<UnlitMat>(rsm_matrix);
renderRSMShadow<NormalMat>(rsm_matrix);
renderRSMShadow<DetailMat>(rsm_matrix);
}
}

View File

@ -29,7 +29,7 @@ static void renderPointLights(unsigned count)
glBindBuffer(GL_ARRAY_BUFFER, LightShader::PointLightShader::getInstance()->vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(LightShader::PointLightInfo), PointLightsInfo);
LightShader::PointLightShader::getInstance()->SetTextureUnits(createVector<GLuint>(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture()));
LightShader::PointLightShader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture());
LightShader::PointLightShader::getInstance()->setUniforms();
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, count);
@ -120,7 +120,7 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
{
glUseProgram(FullScreenShader::NVWorkaroundRadianceHintsConstructionShader::getInstance()->Program);
FullScreenShader::NVWorkaroundRadianceHintsConstructionShader::getInstance()->SetTextureUnits(
createVector<GLuint>(m_rtts->getRSM().getRTT()[0], m_rtts->getRSM().getRTT()[1], m_rtts->getRSM().getDepthTexture()));
m_rtts->getRSM().getRTT()[0], m_rtts->getRSM().getRTT()[1], m_rtts->getRSM().getDepthTexture());
for (unsigned i = 0; i < 32; i++)
{
FullScreenShader::NVWorkaroundRadianceHintsConstructionShader::getInstance()->setUniforms(rsm_matrix, rh_matrix, rh_extend, i, video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue()));
@ -131,11 +131,9 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
{
glUseProgram(FullScreenShader::RadianceHintsConstructionShader::getInstance()->Program);
FullScreenShader::RadianceHintsConstructionShader::getInstance()->SetTextureUnits(
createVector<GLuint>(
m_rtts->getRSM().getRTT()[0],
m_rtts->getRSM().getRTT()[1],
m_rtts->getRSM().getDepthTexture()
)
);
FullScreenShader::RadianceHintsConstructionShader::getInstance()->setUniforms(rsm_matrix, rh_matrix, rh_extend, video::SColorf(cb->getRed(), cb->getGreen(), cb->getBlue()));
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 32);

View File

@ -541,7 +541,7 @@ void IrrDriver::renderSkybox(const scene::ICameraSceneNode *camera)
glUseProgram(MeshShader::SkyboxShader::getInstance()->Program);
MeshShader::SkyboxShader::getInstance()->setUniforms(transform);
MeshShader::SkyboxShader::getInstance()->SetTextureUnits(createVector<GLuint>(SkyboxCubeMap));
MeshShader::SkyboxShader::getInstance()->SetTextureUnits(SkyboxCubeMap);
glDrawElements(GL_TRIANGLES, 6 * 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);

View File

@ -123,6 +123,145 @@ Shaders::Shaders()
loadShaders();
}
// Shader loading related hook
static std::string LoadHeader()
{
std::string result;
std::ifstream Stream(file_manager->getAsset("shaders/header.txt").c_str(), std::ios::in);
if (Stream.is_open())
{
std::string Line = "";
while (getline(Stream, Line))
result += "\n" + Line;
Stream.close();
}
return result;
}
// Mostly from shader tutorial
GLuint LoadShader(const char * file, unsigned type)
{
GLuint Id = glCreateShader(type);
char versionString[20];
sprintf(versionString, "#version %d\n", irr_driver->getGLSLVersion());
std::string Code = versionString;
if (irr_driver->hasVSLayerExtension())
Code += "#extension GL_AMD_vertex_shader_layer : enable\n";
if (UserConfigParams::m_azdo)
Code += "#extension GL_ARB_bindless_texture : enable\n";
else
{
Code += "#extension GL_ARB_bindless_texture : disable\n";
Code += "#undef GL_ARB_bindless_texture\n";
}
std::ifstream Stream(file, std::ios::in);
Code += "//" + std::string(file) + "\n";
if (irr_driver->needUBOWorkaround())
Code += "#define UBO_DISABLED\n";
if (irr_driver->hasVSLayerExtension())
Code += "#define VSLayer\n";
if (irr_driver->needsRGBBindlessWorkaround())
Code += "#define SRGBBindlessFix\n";
Code += LoadHeader();
if (Stream.is_open())
{
std::string Line = "";
while (getline(Stream, Line))
Code += "\n" + Line;
Stream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
Log::info("GLWrap", "Compiling shader : %s", file);
char const * SourcePointer = Code.c_str();
int length = (int)strlen(SourcePointer);
glShaderSource(Id, 1, &SourcePointer, &length);
glCompileShader(Id);
glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
if (Result == GL_FALSE)
{
Log::error("GLWrap", "Error in shader %s", file);
glGetShaderiv(Id, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength<0)
InfoLogLength = 1024;
char *ErrorMessage = new char[InfoLogLength];
ErrorMessage[0] = 0;
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
glGetError();
return Id;
}
void setAttribute(AttributeType Tp, GLuint ProgramID)
{
switch (Tp)
{
case OBJECT:
glBindAttribLocation(ProgramID, 0, "Position");
glBindAttribLocation(ProgramID, 1, "Normal");
glBindAttribLocation(ProgramID, 2, "Color");
glBindAttribLocation(ProgramID, 3, "Texcoord");
glBindAttribLocation(ProgramID, 4, "SecondTexcoord");
glBindAttribLocation(ProgramID, 5, "Tangent");
glBindAttribLocation(ProgramID, 6, "Bitangent");
glBindAttribLocation(ProgramID, 7, "Origin");
glBindAttribLocation(ProgramID, 8, "Orientation");
glBindAttribLocation(ProgramID, 9, "Scale");
break;
case PARTICLES_SIM:
glBindAttribLocation(ProgramID, 0, "particle_position");
glBindAttribLocation(ProgramID, 1, "lifetime");
glBindAttribLocation(ProgramID, 2, "particle_velocity");
glBindAttribLocation(ProgramID, 3, "size");
glBindAttribLocation(ProgramID, 4, "particle_position_initial");
glBindAttribLocation(ProgramID, 5, "lifetime_initial");
glBindAttribLocation(ProgramID, 6, "particle_velocity_initial");
glBindAttribLocation(ProgramID, 7, "size_initial");
break;
case PARTICLES_RENDERING:
glBindAttribLocation(ProgramID, 1, "lifetime");
glBindAttribLocation(ProgramID, 2, "size");
glBindAttribLocation(ProgramID, 4, "quadcorner");
glBindAttribLocation(ProgramID, 5, "rotationvec");
glBindAttribLocation(ProgramID, 6, "anglespeed");
break;
}
}
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount)
{
GLuint Program = glCreateProgram();
loadAndAttach(Program, GL_VERTEX_SHADER, vertex_file_path);
if (irr_driver->getGLSLVersion() < 330)
setAttribute(PARTICLES_SIM, Program);
glTransformFeedbackVaryings(Program, varyingscount, varyings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(Program);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(Program, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE)
{
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(Program, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrap", ErrorMessage);
delete[] ErrorMessage;
}
glGetError();
return Program;
}
GLuint quad_vbo, tri_vbo;
GLuint SharedObject::FullScreenQuadVAO = 0;
@ -1749,6 +1888,16 @@ namespace FullScreenShader
namespace UIShader
{
Primitive2DList::Primitive2DList()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/primitive2dlist.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/transparent.frag").c_str());
AssignUniforms();
AssignSamplerNames(Program, 0, "tex");
}
TextureRectShader::TextureRectShader()
{
Program = LoadProgram(OBJECT,

View File

@ -580,6 +580,13 @@ public:
namespace UIShader
{
class Primitive2DList : public ShaderHelperSingleton<Primitive2DList>, public TextureRead < Bilinear_Filtered >
{
public:
Primitive2DList();
};
class TextureRectShader : public ShaderHelperSingleton<TextureRectShader, core::vector2df, core::vector2df, core::vector2df, core::vector2df>, public TextureRead<Bilinear_Filtered>
{
public:

View File

@ -12,6 +12,77 @@ bool needsUBO();
unsigned getGLSLVersion();
GLuint LoadShader(const char * file, unsigned type);
GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount);
template<typename ... Types>
void loadAndAttach(GLint ProgramID)
{
return;
}
template<typename ... Types>
void loadAndAttach(GLint ProgramID, GLint ShaderType, const char *filepath, Types ... args)
{
GLint ShaderID = LoadShader(filepath, ShaderType);
glAttachShader(ProgramID, ShaderID);
glDeleteShader(ShaderID);
loadAndAttach(ProgramID, args...);
}
template<typename ...Types>
void printFileList()
{
return;
}
template<typename ...Types>
void printFileList(GLint ShaderType, const char *filepath, Types ... args)
{
Log::error("GLWrapp", filepath);
printFileList(args...);
}
enum AttributeType
{
OBJECT,
PARTICLES_SIM,
PARTICLES_RENDERING,
};
void setAttribute(AttributeType Tp, GLuint ProgramID);
template<typename ... Types>
GLint LoadProgram(AttributeType Tp, Types ... args)
{
GLint ProgramID = glCreateProgram();
loadAndAttach(ProgramID, args...);
if (getGLSLVersion() < 330)
setAttribute(Tp, ProgramID);
glLinkProgram(ProgramID);
GLint Result = GL_FALSE;
int InfoLogLength;
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
if (Result == GL_FALSE) {
Log::error("GLWrapp", "Error when linking these shaders :");
printFileList(args...);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
char *ErrorMessage = new char[InfoLogLength];
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, ErrorMessage);
Log::error("GLWrapp", ErrorMessage);
delete[] ErrorMessage;
}
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
{
Log::warn("IrrDriver", "GLWrap : OpenGL error %i\n", glErr);
}
return ProgramID;
}
struct UniformHelper
{
template<unsigned N = 0>
@ -167,7 +238,8 @@ struct CreateSamplers<>
template<>
struct BindTexture<>
{
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
template<int N>
static void exec(const std::vector<unsigned> &TU)
{}
};
@ -189,10 +261,11 @@ void BindTextureNearest(unsigned TU, unsigned tid);
template<SamplerType...tp>
struct BindTexture<Nearest_Filtered, tp...>
{
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
template<int N, typename...Args>
static void exec(const std::vector<unsigned> &TU, GLuint TexId, Args... args)
{
BindTextureNearest(TU[N], TexId[N]);
BindTexture<tp...>::exec(TU, TexId, N + 1);
BindTextureNearest(TU[N], TexId);
BindTexture<tp...>::template exec<N + 1>(TU, args...);
}
};
@ -218,16 +291,17 @@ struct CreateSamplers<Neared_Clamped_Filtered, tp...>
template<SamplerType...tp>
struct BindTexture<Neared_Clamped_Filtered, tp...>
{
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
template<int N, typename...Args>
static void exec(const std::vector<unsigned> &TU, GLuint TexId, Args... args)
{
glActiveTexture(GL_TEXTURE0 + TU[N]);
glBindTexture(GL_TEXTURE_2D, TexId[N]);
glBindTexture(GL_TEXTURE_2D, TexId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
BindTexture<tp...>::exec(TU, TexId, N + 1);
BindTexture<tp...>::template exec<N + 1>(TU, args...);
}
};
@ -249,10 +323,11 @@ void BindTextureBilinear(unsigned TU, unsigned tex);
template<SamplerType...tp>
struct BindTexture<Bilinear_Filtered, tp...>
{
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
template<int N, typename...Args>
static void exec(const std::vector<unsigned> &TU, GLuint TexId, Args... args)
{
BindTextureBilinear(TU[N], TexId[N]);
BindTexture<tp...>::exec(TU, TexId, N + 1);
BindTextureBilinear(TU[N], TexId);
BindTexture<tp...>::template exec<N + 1>(TU, args...);
}
};
@ -274,10 +349,11 @@ void BindTextureBilinearClamped(unsigned TU, unsigned tex);
template<SamplerType...tp>
struct BindTexture<Bilinear_Clamped_Filtered, tp...>
{
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
template<int N, typename...Args>
static void exec(const std::vector<unsigned> &TU, GLuint TexId, Args... args)
{
BindTextureBilinearClamped(TU[N], TexId[N]);
BindTexture<tp...>::exec(TU, TexId, N + 1);
BindTextureBilinearClamped(TU[N], TexId);
BindTexture<tp...>::template exec<N + 1>(TU, args...);
}
};
@ -299,10 +375,11 @@ void BindTextureSemiTrilinear(unsigned TU, unsigned tex);
template<SamplerType...tp>
struct BindTexture<Semi_trilinear, tp...>
{
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
template<int N, typename...Args>
static void exec(const std::vector<unsigned> &TU, GLuint TexId, Args... args)
{
BindTextureSemiTrilinear(TU[N], TexId[N]);
BindTexture<tp...>::exec(TU, TexId, N + 1);
BindTextureSemiTrilinear(TU[N], TexId);
BindTexture<tp...>::template exec<N + 1>(TU, args...);
}
};
@ -337,20 +414,22 @@ void BindCubemapTrilinear(unsigned TU, unsigned tex);
template<SamplerType...tp>
struct BindTexture<Trilinear_cubemap, tp...>
{
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
template<int N, typename...Args>
static void exec(const std::vector<unsigned> &TU, GLuint TexId, Args... args)
{
BindCubemapTrilinear(TU[N], TexId[N]);
BindTexture<tp...>::exec(TU, TexId, N + 1);
BindCubemapTrilinear(TU[N], TexId);
BindTexture<tp...>::template exec<N + 1>(TU, args...);
}
};
template<SamplerType...tp>
struct BindTexture<Trilinear_Anisotropic_Filtered, tp...>
{
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
template<int N, typename...Args>
static void exec(const std::vector<unsigned> &TU, GLuint TexId, Args... args)
{
BindTextureTrilinearAnisotropic(TU[N], TexId[N]);
BindTexture<tp...>::exec(TU, TexId, N + 1);
BindTextureTrilinearAnisotropic(TU[N], TexId);
BindTexture<tp...>::template exec<N + 1>(TU, args...);
}
};
@ -370,10 +449,11 @@ void BindTextureVolume(unsigned TU, unsigned tex);
template<SamplerType...tp>
struct BindTexture<Volume_Linear_Filtered, tp...>
{
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
template<int N, typename...Args>
static void exec(const std::vector<unsigned> &TU, GLuint TexId, Args... args)
{
BindTextureVolume(TU[N], TexId[N]);
BindTexture<tp...>::exec(TU, TexId, N + 1);
BindTextureVolume(TU[N], TexId);
BindTexture<tp...>::template exec<N + 1>(TU, args...);
}
};
@ -395,10 +475,11 @@ void BindTextureShadow(unsigned TU, unsigned tex);
template<SamplerType...tp>
struct BindTexture<Shadow_Sampler, tp...>
{
static void exec(const std::vector<unsigned> &TU, const std::vector<unsigned> &TexId, unsigned N)
template <int N, typename...Args>
static void exec(const std::vector<unsigned> &TU, GLuint TexId, Args... args)
{
BindTextureShadow(TU[N], TexId[N]);
BindTexture<tp...>::exec(TU, TexId, N + 1);
BindTextureShadow(TU[N], TexId);
BindTexture<tp...>::template exec<N + 1>(TU, args...);
}
};
@ -436,21 +517,44 @@ protected:
glUseProgram(0);
}
template<int N>
void SetTextureUnits_impl()
{
static_assert(N == sizeof...(tp), "Not enough texture set");
}
template<int N, typename... TexIds>
void SetTextureUnits_impl(GLuint texid, TexIds... args)
{
setTextureSampler(TextureType[N], TextureUnits[N], texid, SamplersId[N]);
SetTextureUnits_impl<N + 1>(args...);
}
template<int N>
void SetTextureHandles_impl()
{
static_assert(N == sizeof...(tp), "Not enough handle set");
}
template<int N, typename... HandlesId>
void SetTextureHandles_impl(uint64_t handle, HandlesId... args)
{
if (handle)
glUniformHandleui64ARB(TextureLocation[N], handle);
SetTextureHandles_impl<N + 1>(args...);
}
public:
std::vector<GLuint> SamplersId;
void SetTextureUnits(const std::vector<GLuint> &args)
template<typename... TexIds>
void SetTextureUnits(TexIds... args)
{
if (args.size() != sizeof...(tp))
abort();
if (getGLSLVersion() >= 330)
{
for (unsigned i = 0; i < args.size(); i++)
{
setTextureSampler(TextureType[i], TextureUnits[i], args[i], SamplersId[i]);
}
}
SetTextureUnits_impl<0>(args...);
else
BindTexture<tp...>::exec(TextureUnits, args, 0);
BindTexture<tp...>::template exec<0>(TextureUnits, args...);
}
~TextureRead()
@ -459,14 +563,10 @@ public:
glDeleteSamplers(1, &SamplersId[i]);
}
void SetTextureHandles(const std::vector<uint64_t> &args)
template<typename... HandlesId>
void SetTextureHandles(HandlesId... ids)
{
assert(args.size() == TextureLocation.size() && "Wrong Handle count");
for (unsigned i = 0; i < args.size(); i++)
{
if (args[i])
glUniformHandleui64ARB(TextureLocation[i], args[i]);
}
SetTextureHandles_impl<0>(ids...);
}
};
#endif

View File

@ -149,6 +149,8 @@ void STKAnimatedMesh::updateGL()
Material::ShaderType MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType(), material, material2);
InitTextures(mesh, MatType);
}
else
InitTexturesTransparent(mesh);
if (irr_driver->hasARB_base_instance())
{

View File

@ -52,7 +52,7 @@ void STKBillboard::render()
compressTexture(tex, true, true);
GLuint texid = getTextureGLuint(tex);
glUseProgram(MeshShader::BillboardShader::getInstance()->Program);
MeshShader::BillboardShader::getInstance()->SetTextureUnits(createVector<GLuint>(texid));
MeshShader::BillboardShader::getInstance()->SetTextureUnits(texid);
MeshShader::BillboardShader::getInstance()->setUniforms(irr_driver->getViewMatrix(), irr_driver->getProjMatrix(), pos, Size);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);

View File

@ -349,4 +349,21 @@ void InitTextures(GLMesh &mesh, Material::ShaderType Mat)
SetTexture(mesh, 6, false, getShaderTypeName(Mat));
break;
}
}
void InitTexturesTransparent(GLMesh &mesh)
{
if (!mesh.textures[0])
{
Log::fatal("STKMesh", "Missing texture for material transparent");
return;
}
compressTexture(mesh.textures[0], true);
if (UserConfigParams::m_azdo)
{
if (!mesh.TextureHandles[0])
mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::ObjectPass1Shader::getInstance()->SamplersId[0]);
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0]))
glMakeTextureHandleResidentARB(mesh.TextureHandles[0]);
}
}

View File

@ -179,5 +179,6 @@ Material::ShaderType MaterialTypeToMeshMaterial(video::E_MATERIAL_TYPE MaterialT
TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE, f32 MaterialTypeParam, Material* material);
void InitTextures(GLMesh &mesh, Material::ShaderType);
void InitTexturesTransparent(GLMesh &mesh);
#endif // STKMESH_H

View File

@ -189,6 +189,8 @@ void STKMeshSceneNode::updateGL()
if (!immediate_draw)
InitTextures(mesh, MatType);
}
else if (!immediate_draw)
InitTexturesTransparent(mesh);
if (!immediate_draw && irr_driver->hasARB_base_instance())
{
@ -268,10 +270,10 @@ void STKMeshSceneNode::render()
mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]);
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0]))
glMakeTextureHandleResidentARB(mesh.TextureHandles[0]);
MeshShader::ObjectPass1Shader::getInstance()->SetTextureHandles(createVector<uint64_t>(mesh.TextureHandles[0]));
MeshShader::ObjectPass1Shader::getInstance()->SetTextureHandles(mesh.TextureHandles[0]);
}
else
MeshShader::ObjectPass1Shader::getInstance()->SetTextureUnits(std::vector < GLuint > { getTextureGLuint(mesh.textures[0]) });
MeshShader::ObjectPass1Shader::getInstance()->SetTextureUnits(getTextureGLuint(mesh.textures[0]));
MeshShader::ObjectPass1Shader::getInstance()->setUniforms(AbsoluteTransformation, invmodel);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
@ -318,15 +320,19 @@ void STKMeshSceneNode::render()
mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]);
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0]))
glMakeTextureHandleResidentARB(mesh.TextureHandles[0]);
MeshShader::ObjectPass2Shader::getInstance()->SetTextureHandles(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, mesh.TextureHandles[0]));
if (!mesh.TextureHandles[1])
mesh.TextureHandles[1] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[1]), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]);
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[1]))
glMakeTextureHandleResidentARB(mesh.TextureHandles[1]);
MeshShader::ObjectPass2Shader::getInstance()->SetTextureHandles(DiffuseHandle, SpecularHandle, SSAOHandle, mesh.TextureHandles[0], mesh.TextureHandles[1]);
}
else
MeshShader::ObjectPass2Shader::getInstance()->SetTextureUnits(createVector<GLuint>(
MeshShader::ObjectPass2Shader::getInstance()->SetTextureUnits(
irr_driver->getRenderTargetTexture(RTT_DIFFUSE),
irr_driver->getRenderTargetTexture(RTT_SPECULAR),
irr_driver->getRenderTargetTexture(RTT_HALF1_R),
getTextureGLuint(mesh.textures[0]),
getTextureGLuint(mesh.textures[1])));
getTextureGLuint(mesh.textures[1]));
MeshShader::ObjectPass2Shader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
@ -395,10 +401,10 @@ void STKMeshSceneNode::render()
mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]);
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0]))
glMakeTextureHandleResidentARB(mesh.TextureHandles[0]);
MeshShader::TransparentFogShader::getInstance()->SetTextureHandles(createVector<uint64_t>(mesh.TextureHandles[0]));
MeshShader::TransparentFogShader::getInstance()->SetTextureHandles(mesh.TextureHandles[0]);
}
else
MeshShader::TransparentFogShader::getInstance()->SetTextureUnits(std::vector<GLuint>{ getTextureGLuint(mesh.textures[0]) });
MeshShader::TransparentFogShader::getInstance()->SetTextureUnits(getTextureGLuint(mesh.textures[0]));
MeshShader::TransparentFogShader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix, fogmax, startH, endH, start, end, col);
assert(mesh.vao);
@ -425,10 +431,10 @@ void STKMeshSceneNode::render()
mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[0]), MeshShader::TransparentShader::getInstance()->SamplersId[0]);
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0]))
glMakeTextureHandleResidentARB(mesh.TextureHandles[0]);
MeshShader::TransparentShader::getInstance()->SetTextureHandles(createVector<uint64_t>(mesh.TextureHandles[0]));
MeshShader::TransparentShader::getInstance()->SetTextureHandles(mesh.TextureHandles[0]);
}
else
MeshShader::TransparentShader::getInstance()->SetTextureUnits(std::vector<GLuint>{ getTextureGLuint(mesh.textures[0]) });
MeshShader::TransparentShader::getInstance()->SetTextureUnits(getTextureGLuint(mesh.textures[0]));
MeshShader::TransparentShader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix);
assert(mesh.vao);

View File

@ -1,6 +1,7 @@
#include "vaomanager.hpp"
#include "irr_driver.hpp"
#include "stkmesh.hpp"
#include "glwrap.hpp"
VAOManager::VAOManager()
{
@ -121,61 +122,8 @@ void VAOManager::regenerateVAO(enum VTXTYPE tp)
glGenVertexArrays(1, &vao[tp]);
glBindVertexArray(vao[tp]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
switch (tp)
{
case VTXTYPE_COUNT: break; // avoid compiler warning
case VTXTYPE_STANDARD:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
break;
case VTXTYPE_TCOORD:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
// SecondTexcoord
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
break;
case VTXTYPE_TANGENT:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
// Tangent
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
// Bitangent
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)48);
break;
}
VertexUtils::bindVertexArrayAttrib(getVertexType(tp));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
glBindVertexArray(0);
@ -319,6 +267,20 @@ VAOManager::VTXTYPE VAOManager::getVTXTYPE(video::E_VERTEX_TYPE type)
}
};
irr::video::E_VERTEX_TYPE VAOManager::getVertexType(enum VTXTYPE tp)
{
switch (tp)
{
default:
case VTXTYPE_STANDARD:
return video::EVT_STANDARD;
case VTXTYPE_TCOORD:
return video::EVT_2TCOORDS;
case VTXTYPE_TANGENT:
return video::EVT_TANGENTS;
}
}
void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp)
{
size_t old_vtx_cnt = last_vertex[tp];

View File

@ -154,6 +154,7 @@ class VAOManager : public Singleton<VAOManager>
void regenerateInstancedVAO();
size_t getVertexPitch(enum VTXTYPE) const;
VTXTYPE getVTXTYPE(irr::video::E_VERTEX_TYPE type);
irr::video::E_VERTEX_TYPE getVertexType(enum VTXTYPE tp);
void append(irr::scene::IMeshBuffer *, VTXTYPE tp);
public:
VAOManager();

View File

@ -9,7 +9,7 @@
#include "IVideoDriver.h"
#include "ITexture.h"
#include <cassert>
#include "graphics/glwrap.hpp"
#include "graphics/2dutils.hpp"
namespace irr
{

View File

@ -657,7 +657,7 @@ namespace GUIEngine
#include "guiengine/engine.hpp"
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/2dutils.hpp"
#include "input/input_manager.hpp"
#include "io/file_manager.hpp"
#include "guiengine/event_handler.hpp"

View File

@ -184,6 +184,15 @@ bool EventHandler::OnEvent (const SEvent &event)
// FIXME? it may be a bit unclean that all input events go trough
// the gui module
const EventPropagation blockPropagation = input_manager->input(event);
if (event.EventType == EET_KEY_INPUT_EVENT &&
event.KeyInput.Key == irr::KEY_TAB)
{
// block all tab events, if we let them go, irrlicht will try
// to apply its own focus code
return true; // EVENT_BLOCK
}
return blockPropagation == EVENT_BLOCK;
}
else if (event.EventType == EET_LOG_TEXT_EVENT)

View File

@ -13,7 +13,7 @@
#include "guiengine/engine.hpp"
#include "io/file_manager.hpp"
#include "utils/translation.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/2dutils.hpp"
namespace irr
{

View File

@ -23,7 +23,7 @@
#include <algorithm>
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/2dutils.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/modaldialog.hpp"
#include "guiengine/scalable_font.hpp"

View File

@ -12,8 +12,7 @@
//#include "os.h"
#include "Keycodes.h"
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/2dutils.hpp"
#include "utils/translation.hpp"
#include "utils/time.hpp"

View File

@ -757,9 +757,9 @@ void DynamicRibbonWidget::onRibbonWidgetFocus(RibbonWidget* emitter, const int p
#pragma mark Setters / Actions
#endif
void DynamicRibbonWidget::scroll(const int x_delta)
void DynamicRibbonWidget::scroll(int x_delta, bool evenIfDeactivated)
{
if (m_deactivated) return;
if (m_deactivated && !evenIfDeactivated) return;
// Refuse to scroll when everything is visible
if ((int)m_items.size() <= m_row_amount*m_col_amount) return;
@ -1081,11 +1081,11 @@ bool DynamicRibbonWidget::setSelection(int item_id, const int playerID,
while (!findItemInRows(name.c_str(), &row, &id))
{
// if we get here it means the item is scrolled out. Try to find it.
scroll(1);
scroll(1, evenIfDeactivated);
if (iterations > 50)
{
Log::fatal("DynamicRibbonWidget::setSelection", "Cannot find item %d (%s)", item_id, name.c_str());
Log::error("DynamicRibbonWidget::setSelection", "Cannot find item %d (%s)", item_id, name.c_str());
return false;
}

View File

@ -159,7 +159,7 @@ namespace GUIEngine
void buildInternalStructure();
/** Call this to scroll within a scrollable ribbon */
void scroll(const int x_delta);
void scroll(int x_delta, bool evenIfDeactivated = false);
/** Used for combo ribbons, to contain the ID of the currently selected item for each player */
int m_selected_item[MAX_PLAYER_COUNT];

View File

@ -1436,21 +1436,14 @@ void Kart::handleMaterialSFX(const Material *material)
m_previous_terrain_sound->setLoop(false);
const std::string &s = material->getSFXName();
if (s != "")
// In multiplayer mode sounds are NOT positional, because we have
// multiple listeners. This would make the sounds of all AIs be
// audible at all times. So silence AI karts.
if (s.size()!=0 && (race_manager->getNumPlayers()==1 ||
m_controller->isPlayerController() ) )
{
m_terrain_sound = SFXManager::get()->createSoundSource(s);
// In multiplayer mode sounds are NOT positional, because we have
// multiple listeners. This would make the sounds of all AIs be
// audible at all times. So silence AI karts.
if (race_manager->getNumLocalPlayers() > 1)
{
if (!m_controller->isPlayerController())
{
m_terrain_sound->setVolume( 0.0f );
}
}
m_terrain_sound->play();
m_terrain_sound->setLoop(true);
}
@ -2017,10 +2010,10 @@ void Kart::updatePhysics(float dt)
m_skidding->getSkidState() == Skidding::SKID_ACCUMULATE_RIGHT ) &&
m_skidding->getGraphicalJumpOffset()==0)
{
if(!m_skid_sound->isPlaying() && !isWheeless())
if(m_skid_sound->getStatus()!=SFXBase::SFX_PLAYING && !isWheeless())
m_skid_sound->play();
}
else if(m_skid_sound->isPlaying())
else if(m_skid_sound->getStatus()==SFXBase::SFX_PLAYING)
{
m_skid_sound->stop();
}

View File

@ -622,9 +622,9 @@ void KartModel::loadWheelInfo(const XMLNode &node,
// stk_config file is read (which has no model information).
if(m_model_filename!="")
{
Log::error("Kart_Model", "Missing wheel information '%s' for model"
Log::error("Kart_Model", "Missing wheel information '%s' for model "
"'%s'.", wheel_name.c_str(), m_model_filename.c_str());
Log::error("Kart_Model", "This can be ignored, but the wheels will"
Log::error("Kart_Model", "This can be ignored, but the wheels will "
"not rotate.");
}
return;

View File

@ -1150,12 +1150,13 @@ void askForInternetPermission()
}; // ConfirmServer
new MessageDialog(_("SuperTuxKart may connect to a server "
"to download add-ons and notify you of updates. Would you "
"like this feature to be enabled? (To change this setting "
"to download add-ons and notify you of updates. We also collect "
"anonymous hardware statistics to help with the development of STK. "
"Would you like this feature to be enabled? (To change this setting "
"at a later time, go to options, select tab "
"'User Interface', and edit \"Allow STK to connect to the "
"Internet\")."),
MessageDialog::MESSAGE_DIALOG_CONFIRM,
"Internet\" and \"Allow STK to send anonymous HW statistics\")."),
MessageDialog::MESSAGE_DIALOG_YESNO,
new ConfirmServer(), true);
}
@ -1302,6 +1303,8 @@ int main(int argc, char *argv[] )
}
}
// Note that on the very first run of STK internet status is set to
// "not asked", so the report will only be sent in the next run.
if(UserConfigParams::m_internet_status==Online::RequestManager::IPERM_ALLOWED)
{
HardwareStats::reportHardwareStats();

View File

@ -21,7 +21,7 @@
#include <assert.h>
#include "audio/music_manager.hpp"
#include "audio/sfx_manager.hpp"
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
@ -138,7 +138,6 @@ void MainLoop::run()
if (!m_abort && !ProfileWorld::isNoGraphics())
{
PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00);
music_manager->update(dt);
input_manager->update(dt);
#ifdef ENABLE_WIIUSE
@ -152,6 +151,13 @@ void MainLoop::run()
irr_driver->update(dt);
PROFILER_POP_CPU_MARKER();
// Update sfx and music after graphics, so that graphics code
// can use as many threads as possible without interfering
// with audia
PROFILER_PUSH_CPU_MARKER("Music/input/GUI", 0x7F, 0x00, 0x00);
SFXManager::get()->update(dt);
PROFILER_POP_CPU_MARKER();
PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F);
ProtocolManager::getInstance()->update();
PROFILER_POP_CPU_MARKER();

View File

@ -309,7 +309,8 @@ void CutsceneWorld::update(float dt)
SFXManager::get()->positionListener(m_camera->getAbsolutePosition(),
m_camera->getTarget() -
m_camera->getAbsolutePosition());
m_camera->getAbsolutePosition(),
Vec3(0,1,0));
break;
}

View File

@ -436,6 +436,11 @@ void SoccerWorld::initKartList()
for(unsigned int n=0; n<kart_amount; n++)
{
SoccerTeam team = race_manager->getLocalKartInfo(n).getSoccerTeam();
#ifdef DEBUG
// In debug mode it's possible to play soccer with a single player
// (in artist debug mode). Avoid overwriting memory in this case.
if(team==SOCCER_TEAM_NONE) team=SOCCER_TEAM_RED;
#endif
m_karts[n]->setPosition(team_cur_position[team]);
team_cur_position[team]++;
} // next kart

View File

@ -39,8 +39,6 @@ WorldStatus::WorldStatus()
m_start_sound = SFXManager::get()->createSoundSource("start_race");
m_track_intro_sound = SFXManager::get()->createSoundSource("track_intro");
music_manager->stopMusic();
m_play_racestart_sounds = true;
IrrlichtDevice *device = irr_driver->getDevice();

View File

@ -70,6 +70,7 @@ void GrandPrixData::createRandomGP(const unsigned int number_of_tracks,
m_name = "Random Grand Prix";
m_editable = false;
m_group = GP_NONE;
m_reverse_type = use_reverse;
if(new_tracks)
{
@ -155,6 +156,7 @@ void GrandPrixData::changeTrackNumber(const unsigned int number_of_tracks,
*/
void GrandPrixData::changeReverse(const GrandPrixData::GPReverseType use_reverse)
{
m_reverse_type = use_reverse;
for (unsigned int i = 0; i < m_tracks.size(); i++)
{
if (use_reverse == GP_NO_REVERSE)

View File

@ -94,6 +94,9 @@ public:
GP_DEFAULT_REVERSE = 3
}; // GPReverseType
private:
GPReverseType m_reverse_type;
public:
#if (defined(WIN32) || defined(_WIN32)) && !defined(__MINGW32__)
# pragma warning(disable:4290)
@ -145,22 +148,25 @@ public:
// ------------------------------------------------------------------------
/** @return the (potentially translated) user-visible name of the Grand
* Prix (apply fribidi as needed) */
irr::core::stringw getName() const { return _LTR(m_name.c_str()); }
irr::core::stringw getName() const { return _LTR(m_name.c_str()); }
// ------------------------------------------------------------------------
/** @return the internal indentifier of the Grand Prix (not translated) */
const std::string& getId() const { return m_id; }
const std::string& getId() const { return m_id; }
// ------------------------------------------------------------------------
/** Returns true if this GP is a random GP. */
bool isRandomGP() const { return m_id=="random"; }
bool isRandomGP() const { return m_id=="random"; }
// ------------------------------------------------------------------------
/** Returns the filename of the grand prix xml file. */
const std::string& getFilename() const { return m_filename; }
const std::string& getFilename() const { return m_filename; }
// ------------------------------------------------------------------------
/** Returns the group. */
enum GPGroupType getGroup() const { return m_group; }
enum GPGroupType getGroup() const { return m_group; }
// ------------------------------------------------------------------------
enum GPReverseType getReverseType()
const { return m_reverse_type; }
}; // GrandPrixData
#endif

View File

@ -279,15 +279,42 @@ void RaceManager::computeRandomKartList()
void RaceManager::startNew(bool from_overworld)
{
m_started_from_overworld = from_overworld;
m_saved_gp = NULL; // There will be checks for this being NULL done later
if(m_major_mode==MAJOR_MODE_GRAND_PRIX)
if (m_major_mode==MAJOR_MODE_GRAND_PRIX)
{
// GP: get tracks, laps and reverse info from grand prix
m_tracks = m_grand_prix.getTrackNames();
m_num_laps = m_grand_prix.getLaps();
m_reverse_track = m_grand_prix.getReverse();
// We look if Player 1 has a saved version of this GP.
m_saved_gp = SavedGrandPrix::getSavedGP(
StateManager::get()
->getActivePlayerProfile(0)
->getUniqueID(),
m_grand_prix.getId(),
m_player_karts.size());
// Saved GP only in offline mode
if (m_continue_saved_gp && !NetworkWorld::getInstance<NetworkWorld>()->isRunning())
{
if (m_saved_gp == NULL)
{
Log::error("Race Manager", "Can not continue Grand Prix '%s'"
"because it could not exist",
m_grand_prix.getId().c_str());
m_continue_saved_gp = false; // simple and working
}
else
{
setNumKarts(m_saved_gp->getTotalKarts());
setupPlayerKartInfo();
m_grand_prix.changeReverse((GrandPrixData::GPReverseType)m_saved_gp->getReverseType());
m_reverse_track = m_grand_prix.getReverse();
}
}
}
//assert(m_player_karts.size() > 0);
// command line parameters: negative numbers=all karts
if(m_num_karts < 0 ) m_num_karts = stk_config->m_max_karts;
@ -308,8 +335,8 @@ void RaceManager::startNew(bool from_overworld)
race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER
? -1
: 0;
const unsigned int ai_kart_count = (unsigned int) m_ai_kart_list.size();
for(unsigned int i=0; i<ai_kart_count; i++)
const unsigned int ai_kart_count = m_ai_kart_list.size();
for(unsigned int i = 0; i < ai_kart_count; i++)
{
m_kart_status.push_back(KartStatus(m_ai_kart_list[i], i, -1, -1,
init_gp_rank, KT_AI));
@ -323,7 +350,7 @@ void RaceManager::startNew(bool from_overworld)
// Then the players, which start behind the AI karts
// -------------------------------------------------
for(unsigned int i=0; i<(unsigned int)m_player_karts.size(); i++)
for(unsigned int i = 0; i < m_player_karts.size(); i++)
{
KartType kt= m_player_karts[i].isNetworkPlayer() ? KT_NETWORK_PLAYER : KT_PLAYER;
m_kart_status.push_back(KartStatus(m_player_karts[i].getKartName(), i,
@ -340,34 +367,20 @@ void RaceManager::startNew(bool from_overworld)
}
m_track_number = 0;
if(m_major_mode==MAJOR_MODE_GRAND_PRIX &&
!NetworkWorld::getInstance<NetworkWorld>()->isRunning()) // offline mode only
if (m_major_mode == MAJOR_MODE_GRAND_PRIX)
{
//We look if Player 1 has a saved version of this GP.
// =================================================
SavedGrandPrix* gp = SavedGrandPrix::getSavedGP( StateManager::get()
->getActivePlayerProfile(0)
->getUniqueID(),
m_grand_prix.getId(),
m_difficulty,
m_num_karts,
(int)m_player_karts.size());
// Start the race with the appropriate track
// =========================================
if(gp != NULL)
if (m_continue_saved_gp)
{
if (m_continue_saved_gp)
{
m_track_number = gp->getNextTrack();
gp->loadKarts(m_kart_status);
}
else
{
gp->remove();
}
m_track_number = m_saved_gp->getNextTrack();
m_saved_gp->loadKarts(m_kart_status);
}
else if (m_saved_gp != NULL)
{
m_saved_gp->remove();
m_saved_gp = NULL;
}
}
startNextRace();
} // startNew
@ -482,7 +495,6 @@ void RaceManager::startNextRace()
} // startNextRace
//-----------------------------------------------------------------------------
void RaceManager::next()
{
World::deleteWorld();
@ -493,38 +505,18 @@ void RaceManager::next()
{
if(m_major_mode==MAJOR_MODE_GRAND_PRIX && !NetworkWorld::getInstance()->isRunning())
{
//Saving GP state
//We look if Player 1 has already saved this GP.
SavedGrandPrix* gp =
SavedGrandPrix::getSavedGP(StateManager::get()
->getActivePlayerProfile(0)
->getUniqueID(),
m_grand_prix.getId(),
m_difficulty,
m_num_karts,
(int)m_player_karts.size());
if(gp != NULL)
// Saving GP state
// If Player 1 has already saved a GP, we adapt it
if(m_saved_gp != NULL)
{
//if so addept it
gp->setKarts(m_kart_status);
gp->setNextTrack(m_track_number);
m_saved_gp->setKarts(m_kart_status);
m_saved_gp->setNextTrack(m_track_number);
user_config->saveConfig();
}
else
{
//create a new entry
UserConfigParams::m_saved_grand_prix_list.push_back(
new SavedGrandPrix(
StateManager::get()->getActivePlayerProfile(0)
->getUniqueID(),
m_grand_prix.getId(),
m_difficulty,
(int)m_player_karts.size(),
m_track_number,
m_kart_status
)
);
saveGP();
}
user_config->saveConfig();
}
startNextRace();
}
@ -534,6 +526,24 @@ void RaceManager::next()
}
} // next
//-----------------------------------------------------------------------------
void RaceManager::saveGP()
{
UserConfigParams::m_saved_grand_prix_list.push_back(
new SavedGrandPrix(
StateManager::get()->getActivePlayerProfile(0)
->getUniqueID(),
m_grand_prix.getId(),
m_difficulty,
(int)m_player_karts.size(),
m_track_number,
m_grand_prix.getReverseType(),
m_kart_status
)
);
user_config->saveConfig();
}
//-----------------------------------------------------------------------------
/** This class is only used in computeGPRanks, but the C++ standard
@ -630,16 +640,8 @@ void RaceManager::exitRace(bool delete_world)
PlayerManager::getCurrentPlayer()->grandPrixFinished();
if(m_major_mode==MAJOR_MODE_GRAND_PRIX&& !NetworkWorld::getInstance()->isRunning())
{
//Delete saved GP
SavedGrandPrix* gp =
SavedGrandPrix::getSavedGP(StateManager::get()
->getActivePlayerProfile(0)
->getUniqueID(),
m_grand_prix.getId(),
m_difficulty,
m_num_karts,
(int)m_player_karts.size());
if(gp != NULL) gp->remove();
if(m_saved_gp != NULL)
m_saved_gp->remove();
}
StateManager::get()->resetAndGoToScreen( MainMenuScreen::getInstance() );
@ -717,6 +719,7 @@ void RaceManager::exitRace(bool delete_world)
if (delete_world) World::deleteWorld();
m_saved_gp = NULL;
m_track_number = 0;
} // exitRace
@ -766,7 +769,6 @@ void RaceManager::startGP(const GrandPrixData &gp, bool from_overworld,
{
StateManager::get()->enterGameState();
setGrandPrix(gp);
setCoinTarget( 0 ); // Might still be set from a previous challenge
race_manager->setupPlayerKartInfo();
m_continue_saved_gp = continue_saved_gp;

View File

@ -36,6 +36,7 @@
#include "utils/vec3.hpp"
class AbstractKart;
class SavedGrandPrix;
class Track;
static const std::string IDENT_STD ("STANDARD" );
@ -326,6 +327,7 @@ private:
std::vector<std::string> m_ai_kart_list;
int m_track_number;
GrandPrixData m_grand_prix;
SavedGrandPrix* m_saved_gp;
int m_num_karts;
unsigned int m_num_finished_karts;
unsigned int m_num_finished_players;
@ -410,11 +412,13 @@ public:
*/
void setDifficulty(Difficulty diff);
// ------------------------------------------------------------------------
void setCoinTarget(int num) { m_coin_target = num; }
// ------------------------------------------------------------------------
void setGrandPrix(const GrandPrixData &gp)
{
m_grand_prix = gp;
m_coin_target = 0;
setCoinTarget(0);
}
// ------------------------------------------------------------------------
void setAIKartOverride(const std::string& kart)
@ -453,8 +457,6 @@ public:
m_ai_superpower = SUPERPOWER_NONE;
}
// ------------------------------------------------------------------------
void setCoinTarget(int num) { m_coin_target = num; }
// ------------------------------------------------------------------------
void setTimeTarget(float num) { m_has_time_target = true;
m_time_target = num; }
/** \} */
@ -683,8 +685,11 @@ public:
* \brief Higher-level method to start a GP without having to care about
* the exact startup sequence
*/
void startGP(const GrandPrixData &gp, bool from_overworld,
bool continue_saved_gp);
void startGP(const GrandPrixData &gp, bool from_overworld,
bool continue_saved_gp);
/** Saves the current GP to the config */
void saveGP();
/**
* \brief Higher-level method to start a GP without having to care about

View File

@ -19,8 +19,7 @@
#include "config/user_config.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/scalable_font.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/2dutils.hpp"
#include "states_screens/cutscene_gui.hpp"
// -----------------------------------------------------------------------------

View File

@ -203,8 +203,6 @@ void GPInfoDialog::addButtons()
->getActivePlayerProfile(0)
->getUniqueID(),
m_gp.getId(),
race_manager->getDifficulty(),
race_manager->getNumberOfKarts(),
race_manager->getNumLocalPlayers());
okBtn->m_properties[PROP_ID] = "start";

View File

@ -95,6 +95,14 @@ void MessageDialog::doInit(MessageDialogType type,
cancelbtn->setText(_("OK"));
cancelbtn->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
}
else if (type == MessageDialog::MESSAGE_DIALOG_YESNO)
{
ButtonWidget* yesbtn = getWidget<ButtonWidget>("confirm");
ButtonWidget* cancelbtn = getWidget<ButtonWidget>("cancel");
cancelbtn->setText(_("No"));
}
else if (type == MessageDialog::MESSAGE_DIALOG_OK_CANCEL)
{
// In case of a OK_CANCEL dialog, change the text from 'Yes' to 'Ok'

View File

@ -62,7 +62,7 @@ public:
};
enum MessageDialogType { MESSAGE_DIALOG_OK, MESSAGE_DIALOG_CONFIRM,
MESSAGE_DIALOG_OK_CANCEL };
MESSAGE_DIALOG_OK_CANCEL, MESSAGE_DIALOG_YESNO };
private:

View File

@ -479,8 +479,9 @@ void UserInfoDialog::onUpdate(float dt)
// It's unsafe to delete from inside the event handler so we do it here
if (m_self_destroy)
{
bool enter_profile = m_enter_profile;
ModalDialog::dismiss();
if (m_enter_profile)
if (enter_profile)
StateManager::get()->replaceTopMostScreen(OnlineProfileAchievements::getInstance());
return;
}

View File

@ -85,7 +85,11 @@ bool EditTrackScreen::getResult() const
// -----------------------------------------------------------------------------
void EditTrackScreen::loadedFromFile()
{
static const int MAX_LABEL_LENGTH = 35;
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
assert(tracks_widget != NULL);
tracks_widget->setMaxLabelLength(MAX_LABEL_LENGTH);
}
// -----------------------------------------------------------------------------

View File

@ -81,7 +81,7 @@ void GPInfoScreen::loadedFromFile()
// Only init the number of tracks here, this way the previously selected
// number of tracks will be the default.
m_num_tracks_spinner->setValue(1);
m_ai_kart_spinner = getWidget<SpinnerWidget>("ai-spinner");
} // loadedFromFile
@ -97,14 +97,14 @@ void GPInfoScreen::setGP(const std::string &gp_ident)
{
// Doesn't matter what kind of GP we create, it just gets the
// right id ("random").
m_gp.createRandomGP(1, "standard",
m_gp.createRandomGP(1, "standard",
m_reverse_spinner ? getReverse()
: GrandPrixData::GP_NO_REVERSE);
}
} // setGP
// ----------------------------------------------------------------------------
/** Converts the currently selected reverse status into a value of type
/** Converts the currently selected reverse status into a value of type
* GPReverseType .
*/
GrandPrixData::GPReverseType GPInfoScreen::getReverse() const
@ -130,8 +130,6 @@ void GPInfoScreen::beforeAddingWidget()
SavedGrandPrix* saved_gp = SavedGrandPrix::getSavedGP(
StateManager::get()->getActivePlayerProfile(0)->getUniqueID(),
m_gp.getId(),
race_manager->getDifficulty(),
race_manager->getNumberOfKarts(),
race_manager->getNumLocalPlayers());
RibbonWidget* ribbonButtons = getWidget<RibbonWidget>("buttons");
@ -194,10 +192,10 @@ void GPInfoScreen::init()
else
m_group_name = stringc(m_group_spinner->getStringValue().c_str()).c_str();
// If there are more tracks selected atm as in the group (which can
// If there are more tracks selected atm as in the group (which can
// happen if the group has been changed since last time this screen
// was shown), adjust it:
int max_num_tracks = m_group_name=="all"
int max_num_tracks = m_group_name=="all"
? track_manager->getNumberOfRaceTracks()
: (int)track_manager->getTracksInGroup(m_group_name).size();
m_num_tracks_spinner->setMax(max_num_tracks);
@ -207,7 +205,7 @@ void GPInfoScreen::init()
}
// Now create the random GP:
m_gp.createRandomGP(m_num_tracks_spinner->getValue(),
m_gp.createRandomGP(m_num_tracks_spinner->getValue(),
m_group_name, getReverse(), true);
}
else
@ -215,7 +213,7 @@ void GPInfoScreen::init()
getWidget<LabelWidget>("name")->setText(m_gp.getName(), false);
m_gp.checkConsistency();
}
// Number of AIs
// -------------
const bool has_AI = race_manager->hasAI();
@ -288,7 +286,7 @@ void GPInfoScreen::addScreenshot()
m_screenshot_widget->m_h = screenshot_div->m_h;
// Temporary icon, will replace it just after
// Temporary icon, will replace it just after
// (but it will be shown if the given icon is not found)
m_screenshot_widget->m_properties[PROP_ICON] = "gui/main_help.png";
m_screenshot_widget->add();
@ -336,7 +334,7 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name,
// the current track. The current value in the Number-of-tracks-spinner
// has to be updated, since otherwise the displayed (and used) value
// can be bigger than the maximum. (Might be a TODO to fix this)
int max_num_tracks = m_group_name=="all"
int max_num_tracks = m_group_name=="all"
? track_manager->getNumberOfRaceTracks()
: (int)track_manager->getTracksInGroup(m_group_name).size();
m_num_tracks_spinner->setMax(max_num_tracks);
@ -344,7 +342,7 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name,
m_num_tracks_spinner->setValue(max_num_tracks);
// Create a new (i.e. with new tracks) random gp, since the old
// tracks might not all belong to the newly selected group.
m_gp.createRandomGP(m_num_tracks_spinner->getValue(), m_group_name,
getReverse(), /*new_tracks*/true);
addTracks();
@ -359,11 +357,6 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name,
const int num_ai = m_ai_kart_spinner->getValue();
race_manager->setNumKarts( race_manager->getNumLocalPlayers() + num_ai );
UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers() + num_ai;
//Redraw scene because available buttons depend on current settings
getWidget<RibbonWidget>("buttons")->setSelection(0, PLAYER_ID_GAME_MASTER);
reshowCurrentScreen();
m_ai_kart_spinner->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
}
else if(name=="back")
{

View File

@ -62,7 +62,15 @@ void GrandPrixEditorScreen::beforeAddingWidget()
// -----------------------------------------------------------------------------
void GrandPrixEditorScreen::loadedFromFile()
{
static const int MAX_LABEL_LENGTH = 35;
DynamicRibbonWidget* gplist_widget = getWidget<DynamicRibbonWidget>("gplist");
assert (gplist_widget != NULL);
gplist_widget->setMaxLabelLength(MAX_LABEL_LENGTH);
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
assert(tracks_widget != NULL);
tracks_widget->setMaxLabelLength(MAX_LABEL_LENGTH);
}
// -----------------------------------------------------------------------------

View File

@ -17,6 +17,7 @@
#include "states_screens/online_profile_base.hpp"
#include "config/player_manager.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/scalable_font.hpp"
#include "guiengine/screen.hpp"
@ -71,6 +72,8 @@ void OnlineProfileBase::beforeAddingWidget()
m_visiting_profile = ProfileManager::get()->getVisitingProfile();
if (!m_visiting_profile || !m_visiting_profile->isCurrentUser())
m_settings_tab->setVisible(false);
else
m_settings_tab->setVisible(true);
// If not logged in, don't show profile or friends
if (!m_visiting_profile)
@ -103,6 +106,19 @@ void OnlineProfileBase::init()
} // init
// -----------------------------------------------------------------------------
bool OnlineProfileBase::onEscapePressed()
{
//return to main menu if it's your profile
if (!m_visiting_profile || m_visiting_profile->isCurrentUser())
return true;
//return to your profile if it's another profile
ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId());
StateManager::get()->replaceTopMostScreen(OnlineProfileAchievements::getInstance());
return false;
} // onEscapePressed
// -----------------------------------------------------------------------------
/** Called when an event occurs (i.e. user clicks on something).
*/

View File

@ -62,6 +62,8 @@ public:
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void init() OVERRIDE;
virtual bool onEscapePressed() OVERRIDE;
virtual void beforeAddingWidget() OVERRIDE;
};

View File

@ -163,7 +163,7 @@ void OptionsScreenAudio::eventCallback(Widget* widget, const std::string& name,
CheckBoxWidget* w = dynamic_cast<CheckBoxWidget*>(widget);
UserConfigParams::m_sfx = w->getState();
SFXManager::get()->soundToggled(UserConfigParams::m_sfx);
SFXManager::get()->toggleSound(UserConfigParams::m_sfx);
if (UserConfigParams::m_sfx)
{

View File

@ -21,12 +21,14 @@
#include "audio/music_manager.hpp"
#include "audio/sfx_manager.hpp"
#include "audio/sfx_base.hpp"
#include "config/hardware_stats.hpp"
#include "config/user_config.hpp"
#include "guiengine/scalable_font.hpp"
#include "guiengine/screen.hpp"
#include "guiengine/widgets/button_widget.hpp"
#include "guiengine/widgets/check_box_widget.hpp"
#include "guiengine/widgets/dynamic_ribbon_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "guiengine/widgets/spinner_widget.hpp"
#include "guiengine/widget.hpp"
@ -130,6 +132,23 @@ void OptionsScreenUI::init()
assert( news != NULL );
news->setState( UserConfigParams::m_internet_status
==RequestManager::IPERM_ALLOWED );
CheckBoxWidget* stats = getWidget<CheckBoxWidget>("enable-hw-report");
assert( stats != NULL );
LabelWidget *stats_label = getWidget<LabelWidget>("label-hw-report");
assert( stats_label );
stats->setState(UserConfigParams::m_hw_report_enable);
if(news->getState())
{
stats_label->setVisible(true);
stats->setVisible(true);
stats->setState(UserConfigParams::m_hw_report_enable);
}
else
{
stats_label->setVisible(false);
stats->setVisible(false);
}
CheckBoxWidget* show_login = getWidget<CheckBoxWidget>("show-login");
assert( show_login!= NULL );
@ -251,8 +270,28 @@ void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, con
// If internet gets enabled, re-initialise the addon manager (which
// happens in a separate thread) so that news.xml etc can be
// downloaded if necessary.
CheckBoxWidget *stats = getWidget<CheckBoxWidget>("enable-hw-report");
LabelWidget *stats_label = getWidget<LabelWidget>("label-hw-report");
if(internet->getState())
{
NewsManager::get()->init(false);
stats->setVisible(true);
stats_label->setVisible(true);
stats->setState(UserConfigParams::m_hw_report_enable);
}
else
{
stats->setVisible(false);
stats_label->setVisible(false);
}
}
else if (name=="enable-hw-report")
{
CheckBoxWidget* stats = getWidget<CheckBoxWidget>("enable-hw-report");
UserConfigParams::m_hw_report_enable = stats->getState();
if(stats->getState())
HardwareStats::reportHardwareStats();
}
else if (name=="show-login")
{

View File

@ -26,8 +26,8 @@ using namespace irr;
#include "challenges/unlock_manager.hpp"
#include "config/user_config.hpp"
#include "graphics/camera.hpp"
#include "graphics/2dutils.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/modaldialog.hpp"
@ -506,7 +506,7 @@ void RaceGUI::drawEnergyMeter(int x, int y, const AbstractKart *kart,
m.setTexture(0, m_gauge_goal);
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
irr_driver->getVideoDriver()->setMaterial(m);
irr_driver->getVideoDriver()->draw2DVertexPrimitiveList(vertices, count,
draw2DVertexPrimitiveList(m_gauge_goal, vertices, count,
index, count-2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN);
}
@ -594,7 +594,7 @@ void RaceGUI::drawEnergyMeter(int x, int y, const AbstractKart *kart,
m.setTexture(0, m_gauge_full);
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
irr_driver->getVideoDriver()->setMaterial(m);
irr_driver->getVideoDriver()->draw2DVertexPrimitiveList(vertices, count,
draw2DVertexPrimitiveList(m.getTexture(0), vertices, count,
index, count-2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN);
}
@ -800,7 +800,7 @@ void RaceGUI::drawSpeedEnergyRank(const AbstractKart* kart,
m.setTexture(0, m_speed_bar_icon->getTexture());
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
irr_driver->getVideoDriver()->setMaterial(m);
irr_driver->getVideoDriver()->draw2DVertexPrimitiveList(vertices, count,
draw2DVertexPrimitiveList(m_speed_bar_icon->getTexture(), vertices, count,
index, count-2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN);
} // drawSpeedEnergyRank

View File

@ -23,7 +23,7 @@
#include "audio/music_manager.hpp"
#include "config/user_config.hpp"
#include "graphics/camera.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/2dutils.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"

View File

@ -24,8 +24,8 @@
#include "config/player_manager.hpp"
#include "config/user_config.hpp"
#include "graphics/camera.hpp"
#include "graphics/2dutils.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/modaldialog.hpp"

View File

@ -24,7 +24,7 @@
#include "challenges/unlock_manager.hpp"
#include "config/player_manager.hpp"
#include "config/user_config.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/2dutils.hpp"
#include "graphics/material.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/modaldialog.hpp"
@ -393,6 +393,7 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
void RaceResultGUI::onConfirm()
{
race_manager->saveGP(); // Save the aborted GP
GUIEngine::ModalDialog::dismiss();
cleanupGPProgress();
StateManager::get()->popMenu();

View File

@ -201,7 +201,7 @@ void StateManager::onGameStateChange(GameState new_state)
{
irr_driver->showPointer();
input_manager->setMode(InputManager::MENU);
SFXManager::get()->positionListener( Vec3(0,0,0), Vec3(0,1,0) );
SFXManager::get()->positionListener( Vec3(0,0,0), Vec3(0,1,0), Vec3(0, 1, 0) );
if (new_state == MENU)
{

View File

@ -163,10 +163,13 @@ void BaseUserScreen::selectUser(int index)
m_players->setSelection(StringUtils::toString(index), PLAYER_ID_GAME_MASTER,
/*focusIt*/ true);
m_username_tb->setText(profile->getLastOnlineName());
// Delete a password that might have been typed for another user
m_password_tb->setText("");
// Last game was not online, so make the offline settings the default
// (i.e. unckeck online checkbox, and make entry fields invisible).
if (!profile->wasOnlineLastTime() || profile->getLastOnlineName() == "")
{
m_online_cb->setState(false);
@ -177,7 +180,6 @@ void BaseUserScreen::selectUser(int index)
// Now last use was with online --> Display the saved data
m_online_cb->setState(true);
makeEntryFieldsVisible();
m_username_tb->setText(profile->getLastOnlineName());
getWidget<CheckBoxWidget>("remember-user")->setState(
profile->rememberPassword());
if(profile->getLastOnlineName().size()>0)
@ -212,11 +214,15 @@ void BaseUserScreen::makeEntryFieldsVisible()
getWidget<LabelWidget>("label_remember")->setVisible(online);
getWidget<CheckBoxWidget>("remember-user")->setVisible(online);
PlayerProfile *player = getSelectedPlayer();
// Don't show the password fields if the player wants to be online
// and either is the current player (no need to enter a password then)
// or has a saved session.
// and either is the current player and logged in (no need to enter a
// password then) or has a saved session.
if(player && online &&
(player->hasSavedSession() || player==PlayerManager::getCurrentPlayer()))
(player->hasSavedSession() ||
(player==PlayerManager::getCurrentPlayer() && player->isLoggedIn() )
)
)
{
// If we show the online login fields, but the player has a
// saved session, don't show the password field.
@ -227,14 +233,6 @@ void BaseUserScreen::makeEntryFieldsVisible()
{
getWidget<LabelWidget>("label_password")->setVisible(online);
m_password_tb->setVisible(online);
if(player && player->hasSavedSession())
{
// Even though this field is invisible we need to set
// the name, otherwise in update a change of user name
// will be detected, causing a clearing of this player
// (which then removes the associated online user name).
m_username_tb->setText(player->getLastOnlineName());
}
}
} // makeEntryFieldsVisible
@ -442,17 +440,6 @@ void BaseUserScreen::onUpdate(float dt)
m_info_widget->setText(StringUtils::loadingDots(message.c_str()),
false );
}
PlayerProfile *player = getSelectedPlayer();
if(player)
{
// If the player changes the online name, clear the saved session
// flag, and make the password field visible again.
if (m_username_tb->getText()!=player->getLastOnlineName())
{
player->clearSession();
makeEntryFieldsVisible();
}
}
} // onUpdate
// ----------------------------------------------------------------------------

View File

@ -122,3 +122,17 @@ scene::IMesh* ModelDefinitionLoader::getFirstMeshFor(const std::string& name)
{
return irr_driver->getMesh(m_lod_groups[name][0].m_model_file);
}
// ----------------------------------------------------------------------------
void ModelDefinitionLoader::cleanLibraryNodesAfterLoad()
{
for (std::map<std::string, XMLNode*>::iterator it = m_library_nodes.begin();
it != m_library_nodes.end(); it++)
{
delete it->second;
file_manager->popTextureSearchPath();
file_manager->popModelSearchPath();
}
}

View File

@ -23,6 +23,7 @@ class LODNode;
class Track;
class STKInstancedSceneNode;
#include <cassert>
#include <map>
#include <vector>
#include <string>
@ -68,12 +69,13 @@ struct ModelDefinition
}
};
/** Utility class to load level-of-detail nodes and instaincing nodes
/** Utility class to load level-of-detail nodes and library nodes
* \ingroup tracks
*/
class ModelDefinitionLoader
{
private:
std::map<std::string, XMLNode*> m_library_nodes;
std::map< std::string, std::vector< ModelDefinition > > m_lod_groups;
std::map< std::string, STKInstancedSceneNode* > m_instancing_nodes;
Track* m_track;
@ -86,8 +88,25 @@ public:
void clear();
scene::IMesh* getFirstMeshFor(const std::string& name);
std::map<std::string, XMLNode*>& getLibraryNodes()
{
return m_library_nodes;
}
void cleanLibraryNodesAfterLoad();
bool containsLibraryNode(const std::string& name) const
{
return m_library_nodes.find(name) != m_library_nodes.end();
}
void addToLibrary(const std::string& name, XMLNode* xml)
{
assert(xml != NULL);
m_library_nodes[name] = xml;
}
}; // ModelDefinitionLoader
#endif // HEADER_LOD_NODE_LOADER_HPP

View File

@ -1104,6 +1104,13 @@ void QuadGraph::makeMiniMap(const core::dimension2du &dimension,
*newRttMinimap = frame_buffer;
World::getWorld()->setClearbackBufferColor(oldClearColor);
World::getWorld()->forceFogDisabled(false);
irr_driver->getSceneManager()->clear();
VAOManager::kill();
irr_driver->clearGlowingNodes();
irr_driver->clearLights();
irr_driver->clearForcedBloom();
irr_driver->clearBackgroundNodes();
} // makeMiniMap
//-----------------------------------------------------------------------------

View File

@ -1738,18 +1738,9 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
}
}
std::map<std::string, XMLNode*> library_nodes;
loadObjects(root, path, model_def_loader, true, NULL, library_nodes);
loadObjects(root, path, model_def_loader, true, NULL);
// Cleanup library nodes
for (std::map<std::string, XMLNode*>::iterator it = library_nodes.begin();
it != library_nodes.end(); it++)
{
delete it->second;
file_manager->popTextureSearchPath();
file_manager->popModelSearchPath();
}
model_def_loader.cleanLibraryNodesAfterLoad();
// Init all track objects
m_track_object_manager->init();
@ -1914,8 +1905,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
//-----------------------------------------------------------------------------
void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefinitionLoader& model_def_loader,
bool create_lod_definitions, scene::ISceneNode* parent,
std::map<std::string, XMLNode*>& library_nodes)
bool create_lod_definitions, scene::ISceneNode* parent)
{
unsigned int start_position_counter = 0;
@ -1927,75 +1917,10 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefin
// The track object was already converted before the loop, and the
// default start was already used, too - so ignore those.
if (name == "track" || name == "default-start") continue;
if (name == "object")
if (name == "object" || name == "library")
{
m_track_object_manager->add(*node, parent, model_def_loader);
}
else if (name == "library")
{
std::string name;
node->get("name", &name);
core::vector3df xyz;
node->get("xyz", &xyz);
core::vector3df hpr;
node->get("hpr", &hpr);
core::vector3df scale;
node->get("scale", &scale);
XMLNode* libroot;
std::string lib_path =
file_manager->getAsset(FileManager::LIBRARY, name)+"/";
bool create_lod_definitions = true;
if (library_nodes.find(name) == library_nodes.end())
{
std::string lib_node_path = lib_path+"node.xml";
libroot = file_manager->createXMLTree(lib_node_path);
if (libroot == NULL)
{
Log::error("Track", "Cannot find library '%s'", lib_node_path.c_str());
continue;
}
file_manager->pushTextureSearchPath(lib_path + "/");
file_manager->pushModelSearchPath (lib_path);
material_manager->pushTempMaterial(lib_path + "/materials.xml");
library_nodes[name] = libroot;
// Load LOD groups
const XMLNode *lod_xml_node = libroot->getNode("lod");
if (lod_xml_node != NULL)
{
for (unsigned int i = 0; i < lod_xml_node->getNumNodes(); i++)
{
const XMLNode* lod_group_xml = lod_xml_node->getNode(i);
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
{
model_def_loader.addModelDefinition(lod_group_xml->getNode(j));
}
}
}
}
else
{
libroot = library_nodes[name];
create_lod_definitions = false; // LOD definitions are already created, don't create them again
}
scene::ISceneNode* parent = irr_driver->getSceneManager()->addEmptySceneNode();
#ifdef DEBUG
parent->setName(("libnode_" + name).c_str());
#endif
parent->setPosition(xyz);
parent->setRotation(hpr);
parent->setScale(scale);
parent->updateAbsolutePosition();
loadObjects(libroot, lib_path, model_def_loader, create_lod_definitions, parent, library_nodes);
//m_all_nodes.push_back(parent);
}
else if (name == "water")
{
createWater(*node);

View File

@ -412,9 +412,6 @@ private:
std::vector<MusicInformation*>& m_music );
void loadCurves(const XMLNode &node);
void handleSky(const XMLNode &root, const std::string &filename);
void loadObjects(const XMLNode* root, const std::string& path, ModelDefinitionLoader& lod_loader,
bool create_lod_definitions, scene::ISceneNode* parent,
std::map<std::string, XMLNode*>& library_nodes);
public:
@ -472,6 +469,9 @@ public:
/** Returns true if this track has easter eggs. */
bool hasEasterEggs() const { return m_has_easter_eggs; }
// ------------------------------------------------------------------------
void loadObjects(const XMLNode* root, const std::string& path, ModelDefinitionLoader& lod_loader,
bool create_lod_definitions, scene::ISceneNode* parent);
// ------------------------------------------------------------------------
bool isSoccer () const { return m_is_soccer; }
// ------------------------------------------------------------------------
void loadTrackModel (World* parent,

View File

@ -132,6 +132,10 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
m_type = "light";
m_presentation = new TrackObjectPresentationLight(xml_node, parent);
}
else if (xml_node.getName() == "library")
{
m_presentation = new TrackObjectPresentationLibraryNode(xml_node, model_def_loader);
}
else if (type == "sfx-emitter")
{
// FIXME: at this time sound emitters are just disabled in multiplayer

View File

@ -148,6 +148,77 @@ TrackObjectPresentationEmpty::~TrackObjectPresentationEmpty()
// ----------------------------------------------------------------------------
TrackObjectPresentationLibraryNode::TrackObjectPresentationLibraryNode(
const XMLNode& xml_node,
ModelDefinitionLoader& model_def_loader) :
TrackObjectPresentationSceneNode(xml_node)
{
std::string name;
xml_node.get("name", &name);
m_node = irr_driver->getSceneManager()->addEmptySceneNode();
#ifdef DEBUG
m_node->setName(("libnode_" + name).c_str());
#endif
XMLNode* libroot;
std::string lib_path =
file_manager->getAsset(FileManager::LIBRARY, name) + "/";
bool create_lod_definitions = true;
if (!model_def_loader.containsLibraryNode(name))
{
std::string lib_node_path = lib_path + "node.xml";
libroot = file_manager->createXMLTree(lib_node_path);
if (libroot == NULL)
{
Log::error("TrackObjectPresentationLibraryNode", "Cannot find library '%s'", lib_node_path.c_str());
return;
}
file_manager->pushTextureSearchPath(lib_path + "/");
file_manager->pushModelSearchPath(lib_path);
material_manager->pushTempMaterial(lib_path + "/materials.xml");
model_def_loader.addToLibrary(name, libroot);
// Load LOD groups
const XMLNode *lod_xml_node = libroot->getNode("lod");
if (lod_xml_node != NULL)
{
for (unsigned int i = 0; i < lod_xml_node->getNumNodes(); i++)
{
const XMLNode* lod_group_xml = lod_xml_node->getNode(i);
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
{
model_def_loader.addModelDefinition(lod_group_xml->getNode(j));
}
}
}
}
else
{
libroot = model_def_loader.getLibraryNodes()[name];
assert(libroot != NULL);
create_lod_definitions = false; // LOD definitions are already created, don't create them again
}
m_node->setPosition(m_init_xyz);
m_node->setRotation(m_init_hpr);
m_node->setScale(m_init_scale);
m_node->updateAbsolutePosition();
assert(libroot != NULL);
World::getWorld()->getTrack()->loadObjects(libroot, lib_path, model_def_loader,
create_lod_definitions, m_node);
}
TrackObjectPresentationLibraryNode::~TrackObjectPresentationLibraryNode()
{
irr_driver->removeNode(m_node);
}
// ----------------------------------------------------------------------------
TrackObjectPresentationLOD::TrackObjectPresentationLOD(const XMLNode& xml_node,
scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader) :
TrackObjectPresentationSceneNode(xml_node)
@ -411,7 +482,8 @@ TrackObjectPresentationSound::TrackObjectPresentationSound(const XMLNode& xml_no
xml_node.get("max_dist", &max_dist );
// first try track dir, then global dir
std::string soundfile = file_manager->getAsset(FileManager::MODEL,sound);
std::string soundfile = World::getWorld()->getTrack()->getTrackFile(sound);
//std::string soundfile = file_manager->getAsset(FileManager::MODEL,sound);
if (!file_manager->fileExists(soundfile))
{
soundfile = file_manager->getAsset(FileManager::SFX, sound);

View File

@ -152,6 +152,18 @@ public:
virtual ~TrackObjectPresentationEmpty();
};
/**
* \ingroup tracks
* A track object representation that is a library node
*/
class TrackObjectPresentationLibraryNode : public TrackObjectPresentationSceneNode
{
public:
TrackObjectPresentationLibraryNode(const XMLNode& xml_node,
ModelDefinitionLoader& model_def_loader);
virtual ~TrackObjectPresentationLibraryNode();
};
/**
* \ingroup tracks

View File

@ -16,8 +16,8 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "profiler.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/2dutils.hpp"
#include "guiengine/event_handler.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/scalable_font.hpp"

View File

@ -81,7 +81,7 @@ namespace STK {
template<typename... T>
struct TupleSize
{
int value;
const int value;
TupleSize()
{
value = sizeof...(T);

92
tools/ibl.py Normal file
View File

@ -0,0 +1,92 @@
import Image as img
import numpy as np
import pylab as pl
n = 3
GridI, GridJ = np.meshgrid(np.linspace(-1, 1, n), np.linspace(-1, 1, n))
img = np.ones((n,n))
# constant factor of Ylm
c00 = 0.282095
c1minus1 = 0.488603
c10 = 0.488603
c11 = 0.488603
c2minus2 = 1.092548
c2minus1 = 1.092548
c21 = 1.092548
c20 = 0.315392
c22 = 0.546274
def computeYmlOnGrid(Xgrid, Ygrid, Zgrid):
"compute Yml from Y00 to Y22 on Xgrid/Ygrid/Zgrid"
norm = np.sqrt(Xgrid * Xgrid + Ygrid * Ygrid + Zgrid * Zgrid)
Xg = Xgrid / norm
Yg = Ygrid / norm
Zg = Zgrid / norm
Y00 = c00
Y1minus1 = c1minus1 * Yg
Y10 = c10 * Zg
Y11 = c11 * Xg
Y2minus2 = c2minus2 * Xg * Yg
Y2minus1 = c2minus1 * Yg * Zg
Y21= c21 * Xg * Zg
Y20 = c20 * (3 * Zg * Zg - 1)
Y22 = c22 * (Xg * Xg - Yg * Yg)
return (Y00, Y1minus1, Y10, Y11, Y2minus2, Y2minus1, Y20, Y21, Y22)
# From http://www.rorydriscoll.com/2012/01/15/cubemap-texel-solid-angle/
def areaToPoint(x, y):
return np.arctan2(x * y, np.sqrt(x * x + y * y + 1))
def getSolidAngleGrid(Xgrid, Ygrid):
"Compute solid angles using Xgrid/Ygrid/Zgrid texel position"
(step, _) = np.shape(Xgrid)
x0 = Xgrid - (1. / step)
x1 = Xgrid + (1. / step)
y0 = Ygrid - (1. / step)
y1 = Ygrid + (1. / step)
return areaToPoint(x0,y0) - areaToPoint(x1, y0) - areaToPoint(x0, y1) + areaToPoint(x1, y1)
def computeCoefficients():
"Compute coefficient SH00 to SH22 for monochromatic img"
FaceGrid = [(np.ones((n,n)), -GridI, -GridJ), #GL_TEXTURE_CUBE_MAP_POSITIVE_X
(-1 * np.ones((n,n)), -GridI, GridJ), #GL_TEXTURE_CUBE_MAP_NEGATIVE_X
(GridJ, np.ones((n,n)), GridI), #GL_TEXTURE_CUBE_MAP_POSITIVE_Y
(GridJ, -1 * np.ones((n,n)), -GridI), #GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
(GridJ, GridI, np.ones((n,n))), #GL_TEXTURE_CUBE_MAP_POSITIVE_Z
(GridJ, -GridI, -1 * np.ones((n,n)))] #GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
incomingIrradiance = getSolidAngleGrid(GridI, GridJ)
SH00 = 0
SH1minus1 = 0
SH10 = 0
SH11 = 0
SH2minus2 = 0
SH2minus1 = 0
SH20 = 0
SH21 = 0
SH22 = 0
for (Xgrid, Ygrid, Zgrid) in FaceGrid:
(Y00, Y1minus1, Y10, Y11, Y2minus2, Y2minus1, Y20, Y21, Y22) = computeYmlOnGrid(Xgrid, Ygrid, Zgrid)
SH00 += np.sum(Y00 * incomingIrradiance * img)
SH1minus1 += np.sum(Y1minus1 * incomingIrradiance * img)
SH10 += np.sum(Y10 * incomingIrradiance * img)
SH11 += np.sum(Y11 * incomingIrradiance * img)
SH2minus2 += np.sum(Y2minus2 * incomingIrradiance * img)
SH2minus1 += np.sum(Y2minus1 * incomingIrradiance * img)
SH20 += np.sum(Y20 * incomingIrradiance * img)
SH21 += np.sum(Y21 * incomingIrradiance * img)
SH22 += np.sum(Y22 * incomingIrradiance * img)
return (SH00, SH1minus1, SH10, SH2minus2, SH2minus1, SH20, SH21, SH22)
print(computeCoefficients())
#res = []
#for (Xd, Yd, Zd) in FaceGrid:
# res.append(computeYmlOnGrid(Xd, Yd, Zd))
#I = img.open("C:/Users/vljn_000/Documents/GitHub/stk-assets/textures/ants.png")
#m = np.array(I)
#print(type(m))
#pl.imshow(m)