Files
GTASource/game/vfx/gpuparticles/PtFxGPUSystems.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

700 lines
27 KiB
C++

///////////////////////////////////////////////////////////////////////////////
//
// FILE: PtFxGPUSystems.h
// BY : Mark Nicholson
// FOR : Rockstar North
// ON : 23 November 2009
// WHAT:
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// INCLUDES
///////////////////////////////////////////////////////////////////////////////
#include "PtFxGPUSystems.h"
// rage
#include "grmodel/shader.h"
// framework
#include "fwscene/stores/txdstore.h"
#include "vfx/channel.h"
#include "vfx/vfxutil.h"
#include "vfx/vfxwidget.h"
// game
#include "Game/Weather.h"
#include "cutscene/CutSceneManagerNew.h"
#include "camera/viewports/ViewportManager.h"
#include "Peds/Ped.h"
#include "Renderer/RenderPhases/RenderPhaseHeightMap.h"
#include "Renderer/PostProcessFX.h"
#include "renderer/rendertargets.h"
#include "Timecycle/TimeCycleConfig.h"
#include "Vfx/Systems/VfxWeather.h"
#include "Vfx/GPUParticles/PtFxGPUManager.h"
#include "Vfx/VfxHelper.h"
#include "TimeCycle/TimeCycle.h"
///////////////////////////////////////////////////////////////////////////////
// OPTIMISATIONS - TURN ON IN OPTIMISATIONS.H
///////////////////////////////////////////////////////////////////////////////
VFX_PTFX_OPTIMISATIONS()
//OPTIMISATIONS_OFF()
///////////////////////////////////////////////////////////////////////////////
// DEFINES
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// GLOBAL VARIABLES
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// CODE
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// CLASS CPtFxGPULitShaderVars
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Set
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPULitShaderVars::Set (grmShader* pShader, float lightIntensityMult)
{
pShader->SetVar(m_lightIntensityMultId, lightIntensityMult);
}
///////////////////////////////////////////////////////////////////////////////
// SetupShader
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPULitShaderVars::SetupShader (grmShader* pShader)
{
m_lightIntensityMultId = pShader->LookupVar("LightIntensityMult");
}
///////////////////////////////////////////////////////////////////////////////
// CLASS CPtFxGPUSystem
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Shutdown
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUSystem::Shutdown ()
{
// unload the texture dictionaries
for (u32 i=0; i<m_numSettings; i++)
{
// release the texture dictionary
vfxUtil::ShutdownTxd("fxweather");
}
// reset the number of gpu fx settings
m_numSettings = 0;
delete m_pPtxGpu;
m_pPtxGpu = NULL;
}
///////////////////////////////////////////////////////////////////////////////
// PreRender
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUSystem::PreRender (grcViewport& viewport, float deltaTime, bool resetParticles)
{
// set the gpu particle system's gravity and wind influence
m_pPtxGpu->SetGravity(m_currGravity);
m_pPtxGpu->SetWindInfluence(m_currWindInfluence);
// Check if camera water depth is greather than zero to figure if we are underwater
bool isUnderwaterThisFrame = CVfxHelper::GetGameCamWaterDepth()>0.0f;
// Set the gpu particle height collision render targets
// When we are underwater, we don't care about collision anymore so we can use a blank texture
const grcRenderTarget* pRT = CRenderPhaseHeight::GetPtFxGPUCollisionMap()->GetRenderTargetRT();
// Set a texture which contains "far" depth.
const grcTexture *pHeightMap = (isUnderwaterThisFrame || pRT == NULL) ? grcTexture::NoneWhite : pRT;
m_pPtxGpu->GetUpdateShader()->SetHeightMap(pHeightMap);
#if RAIN_UPDATE_CPU_HEIGHTMAP
const grcTexture *pHeightMapStag = NULL;
if(ptxgpuBase::CpuRainUpdateEnabled())
{
CRenderPhaseHeight *const renderPhaseHeight = CRenderPhaseHeight::GetPtFxGPUCollisionMap();
if (AssertVerify(renderPhaseHeight && renderPhaseHeight->m_currentStagingRenderTarget < renderPhaseHeight->m_numStagingRenderTargets))
{
const s32 currStagIdx = (renderPhaseHeight->m_currentStagingRenderTarget+1) % (renderPhaseHeight->m_numStagingRenderTargets);
const grcTexture *pHeightMapStag0 = renderPhaseHeight->m_stagingRenderTex[currStagIdx];
pHeightMapStag = ((isUnderwaterThisFrame || pHeightMapStag0 == NULL) ? NULL : pHeightMapStag0);
m_pPtxGpu->GetUpdateShader()->SetHeightMapSrc(pHeightMapStag);
}
}
#endif //RAIN_UPDATE_CPU_HEIGHTMAP
// This matrix will transform every position to XY at zero and Z at one (0 on PC, Durango and Orbis) which effectively disables collisions.
static const Matrix44 disableCollisionMat = Matrix44(
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
m_pPtxGpu->GetUpdateShader()->SetHeightMapTransformMtx(isUnderwaterThisFrame ? disableCollisionMat : CRenderPhaseHeight::GetPtFxGPUCollisionMap()->GetHeightTransformMtx());
PTXGPU_USE_WIND_DISTURBANCE_ONLY(m_pPtxGpu->GetUpdateShader()->SetWindDisturbanceTextures(m_pPtxGpu->ms_pWindDisturbanceTexture[0], m_pPtxGpu->ms_pWindDisturbanceTexture[1]);)
// Camera cut related stuff
bool hasCut = false;
if(CutSceneManager::GetInstance()->IsCutscenePlayingBack())
{
const camFrame& curFrame = gVpMan.GetCurrentGameViewportFrame();
hasCut = curFrame.GetFlags().IsFlagSet(camFrame::Flag_HasCutPosition) || curFrame.GetFlags().IsFlagSet(camFrame::Flag_HasCutOrientation);
}
// update the gpu particle system
WindType_e windType = WIND_TYPE_AIR;
if (isUnderwaterThisFrame)
{
windType = WIND_TYPE_WATER;
}
m_pPtxGpu->Update(&viewport, deltaTime, windType, m_currLevel, hasCut ? 0.0f : 1.0f, resetParticles);
// tidy up
m_pPtxGpu->GetUpdateShader()->SetHeightMap(NULL);
#if RAIN_UPDATE_CPU_HEIGHTMAP
if(ptxgpuBase::CpuRainUpdateEnabled())
{
m_pPtxGpu->GetUpdateShader()->UnSetHeightMapSrc(pHeightMapStag);
}
#endif
PTXGPU_USE_WIND_DISTURBANCE_ONLY(m_pPtxGpu->GetUpdateShader()->SetWindDisturbanceTextures(NULL, NULL);)
}
///////////////////////////////////////////////////////////////////////////////
// GlobalPreUpdate
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUSystem::GlobalPreUpdate()
{
PTXGPU_USE_WIND_DISTURBANCE_ONLY(ptxgpuBase::UpdateWindDisturbanceTextures();)
}
///////////////////////////////////////////////////////////////////////////////
// UpdateWindDisturbanceTextures
///////////////////////////////////////////////////////////////////////////////
#if PTXGPU_USE_WIND_DISTURBANCE
void CPtFxGPUSystem::UpdateWindDisturbanceTextures()
{
ptxgpuBase::UpdateWindDisturbanceTextures();
}
#endif // PTXGPU_USE_WIND_DISTURBANCE
///////////////////////////////////////////////////////////////////////////////
// CLASS CPtFxGPUDropSystem
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Init
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUDropSystem::Init (unsigned int systemId, int numParticles, const char* updateShaderName, const char* updateShaderTechnique, const char* renderShaderName, const char* renderShaderTechnique, bool bUseSoft, grcRenderTarget* pParentTarget /*= NULL*/)
{
ptfxAssertf(m_pPtxGpu==NULL, "initialisation error");
m_pPtxGpu = rage_new ptxgpuDrop;
ptxgpuDropUpdateShader *pUpdateShader = rage_new ptxgpuDropUpdateShader(systemId,updateShaderName);
ptxgpuDropRenderShader *pRenderShader = rage_new ptxgpuDropRenderShader(renderShaderName);
pUpdateShader->SetTechnique(updateShaderTechnique);
pRenderShader->SetTechnique(renderShaderTechnique);
m_useSoft = bUseSoft;
// init the gpu particle systems with the shader and set some techniques
m_pPtxGpu->Init(systemId, numParticles, pUpdateShader, pRenderShader, pParentTarget);
m_currFxIndex = -1;
}
///////////////////////////////////////////////////////////////////////////////
// Load
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUDropSystem::LoadFromXmlFile(const CWeatherGpuFxFromXmlFile& WeatherGpuFxFromXmlFile)
{
ptfxAssertf(m_numSettings < PTFXGPU_FINAL_MAX_SETTINGS, "CPtFxGPUDropSystem::LoadFromXmlFile - too many GPU fx types - %s will be ingnored on non-beta builds", WeatherGpuFxFromXmlFile.m_Name.c_str());
if (m_numSettings<PTFXGPU_MAX_SETTINGS)
{
m_gpuDropSettings[m_numSettings].m_hashValue = atHashValue(WeatherGpuFxFromXmlFile.m_Name);
#if !__FINAL
strcpy(m_gpuDropSettings[m_numSettings].m_name, WeatherGpuFxFromXmlFile.m_Name.c_str());
#endif
m_gpuDropSettings[m_numSettings].m_driveType = WeatherGpuFxFromXmlFile.m_driveType;
m_gpuDropSettings[m_numSettings].m_windInfluence = WeatherGpuFxFromXmlFile.m_windInfluence;
m_gpuDropSettings[m_numSettings].m_gravity = WeatherGpuFxFromXmlFile.m_gravity;
// load in the gpu particle settings
m_gpuDropSettings[m_numSettings].m_dropEmitterSettings.Load(WeatherGpuFxFromXmlFile.m_emitterSettingsName);
m_gpuDropSettings[m_numSettings].m_dropRenderSettings.Load(WeatherGpuFxFromXmlFile.m_renderSettingsName);
// set up the texture dictionary
strLocalIndex txdSlot = strLocalIndex(vfxUtil::InitTxd("fxweather"));
// load in the gpu particle textures
m_gpuDropSettings[m_numSettings].m_dropRenderSettings.pTexture = g_TxdStore.Get(txdSlot)->Lookup(WeatherGpuFxFromXmlFile.m_diffuseName);
ptfxAssertf(m_gpuDropSettings[m_numSettings].m_dropRenderSettings.pTexture, "diffuse texture not found");
m_gpuDropSettings[m_numSettings].m_dropRenderSettings.pDistotionTexture = const_cast<grcTexture*>( grcTexture::NoneBlack );
if(WeatherGpuFxFromXmlFile.m_distortionTexture.GetLength() > 0)
{
m_gpuDropSettings[m_numSettings].m_dropRenderSettings.pDistotionTexture = g_TxdStore.Get(txdSlot)->Lookup(WeatherGpuFxFromXmlFile.m_distortionTexture);
ptfxAssertf(m_gpuDropSettings[m_numSettings].m_dropRenderSettings.pDistotionTexture != NULL, "distorion texture not found");
if(!m_gpuDropSettings[m_numSettings].m_dropRenderSettings.pDistotionTexture)
{
m_gpuDropSettings[m_numSettings].m_dropRenderSettings.pDistotionTexture = const_cast<grcTexture*>( grcTexture::NoneBlack );
}
}
m_numSettings++;
}
else
{
ptfxAssertf(0, "CPtFxGPUDropSystem::LoadFromXmlFile - too many GPU fx types - ignoring %s", WeatherGpuFxFromXmlFile.m_Name.c_str());
}
}
///////////////////////////////////////////////////////////////////////////////
// Update
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUDropSystem::Update (s32 prevGpuFxIndex, s32 nextGpuFxIndex, float weatherInterp, float maxVfxRegionLevel, float currVfxRegionLevel)
{
// early out if the indices are incorrect, only -1 and [0, PTFXGPU_MAX_SETTINGS) are correct
if (prevGpuFxIndex < -1 || prevGpuFxIndex >= PTFXGPU_MAX_SETTINGS ||
nextGpuFxIndex < -1 || nextGpuFxIndex >= PTFXGPU_MAX_SETTINGS)
{
return;
}
// update the current state
if ((prevGpuFxIndex!=-1 && m_gpuDropSettings[prevGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_RAIN)) ||
(nextGpuFxIndex!=-1 && m_gpuDropSettings[nextGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_RAIN)))
{
if(m_pPtxGpu->IsMistInstance())
{
// Force the mist to start only when the rain gets strong enough
static const float fMistThresh = 0.5f;
m_currLevel = Max(g_vfxWeather.GetCurrRain() - fMistThresh, 0.0f);
m_currLevel /= (1.0f - fMistThresh);
}
else
{
m_currLevel = g_vfxWeather.GetCurrRain();
}
}
else if ((prevGpuFxIndex!=-1 && m_gpuDropSettings[prevGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_SNOW)) ||
(nextGpuFxIndex!=-1 && m_gpuDropSettings[nextGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_SNOW)))
{
if(m_pPtxGpu->IsGroundInstance())
{
m_currLevel = g_vfxWeather.GetCurrSnowMist();
}
else
{
m_currLevel = g_vfxWeather.GetCurrSnow();
}
}
else if ((prevGpuFxIndex!=-1 && m_gpuDropSettings[prevGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_REGION)) ||
(nextGpuFxIndex!=-1 && m_gpuDropSettings[nextGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_REGION)))
{
m_currLevel = maxVfxRegionLevel;
}
else if ((prevGpuFxIndex!=-1 && m_gpuDropSettings[prevGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_UNDERWATER)) ||
(nextGpuFxIndex!=-1 && m_gpuDropSettings[nextGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_UNDERWATER)))
{
m_currLevel = 1.0f;
}
else if ((prevGpuFxIndex!=-1 && m_gpuDropSettings[prevGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_NONE)) ||
(nextGpuFxIndex!=-1 && m_gpuDropSettings[nextGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_NONE)))
{
m_currLevel = 1.0f;
}
//Override settings here in case if it is set
if(m_useOverrideSettings)
{
m_currLevel = m_overrideCurrLevel;
}
if (prevGpuFxIndex==-1 && nextGpuFxIndex==-1)
{
m_currLevel = 0.0f;
m_currFxIndex = -1;
}
else if (prevGpuFxIndex==-1)
{
ptfxAssertf(nextGpuFxIndex>=0 && nextGpuFxIndex<(s32)m_numSettings, "next GPU index is out of range");
m_currDropEmitterSettings = m_gpuDropSettings[nextGpuFxIndex].m_dropEmitterSettings;
m_currDropRenderSettings = m_gpuDropSettings[nextGpuFxIndex].m_dropRenderSettings;
m_currWindInfluence = m_gpuDropSettings[nextGpuFxIndex].m_windInfluence;
m_currGravity = m_gpuDropSettings[nextGpuFxIndex].m_gravity;
m_currFxIndex = nextGpuFxIndex;
}
else if (nextGpuFxIndex==-1)
{
ptfxAssertf(prevGpuFxIndex>=0 && prevGpuFxIndex<(s32)m_numSettings, "previous GPU index is out of range");
m_currDropEmitterSettings = m_gpuDropSettings[prevGpuFxIndex].m_dropEmitterSettings;
m_currDropRenderSettings = m_gpuDropSettings[prevGpuFxIndex].m_dropRenderSettings;
m_currWindInfluence = m_gpuDropSettings[prevGpuFxIndex].m_windInfluence;
m_currGravity = m_gpuDropSettings[prevGpuFxIndex].m_gravity;
m_currFxIndex = prevGpuFxIndex;
}
else
{
ptfxAssertf(prevGpuFxIndex>=0 && prevGpuFxIndex<(s32)m_numSettings, "previous GPU index is out of range");
ptfxAssertf(nextGpuFxIndex>=0 && nextGpuFxIndex<(s32)m_numSettings, "next GPU index is out of range");
if (prevGpuFxIndex==nextGpuFxIndex)
{
m_currDropEmitterSettings = m_gpuDropSettings[prevGpuFxIndex].m_dropEmitterSettings;
m_currDropRenderSettings = m_gpuDropSettings[prevGpuFxIndex].m_dropRenderSettings;
m_currWindInfluence = m_gpuDropSettings[prevGpuFxIndex].m_windInfluence;
m_currGravity = m_gpuDropSettings[prevGpuFxIndex].m_gravity;
m_currFxIndex = prevGpuFxIndex;
}
else
{
if (ptfxVerifyf(m_gpuDropSettings[prevGpuFxIndex].m_driveType == m_gpuDropSettings[nextGpuFxIndex].m_driveType, "trying to interpolate between 2 GPU effects of different types"))
{
m_currDropEmitterSettings.Interpolate(m_gpuDropSettings[prevGpuFxIndex].m_dropEmitterSettings, m_gpuDropSettings[nextGpuFxIndex].m_dropEmitterSettings, weatherInterp);
m_currDropRenderSettings.Interpolate(m_gpuDropSettings[prevGpuFxIndex].m_dropRenderSettings, m_gpuDropSettings[nextGpuFxIndex].m_dropRenderSettings, weatherInterp);
m_currWindInfluence = m_gpuDropSettings[prevGpuFxIndex].m_windInfluence + ((m_gpuDropSettings[nextGpuFxIndex].m_windInfluence - m_gpuDropSettings[prevGpuFxIndex].m_windInfluence)*weatherInterp);
m_currGravity = m_gpuDropSettings[prevGpuFxIndex].m_gravity + ((m_gpuDropSettings[nextGpuFxIndex].m_gravity - m_gpuDropSettings[prevGpuFxIndex].m_gravity)*weatherInterp);
m_currFxIndex = prevGpuFxIndex; // We use prev here, since that's where stuff like texture is coming from.
}
else
{
m_currDropEmitterSettings = m_gpuDropSettings[nextGpuFxIndex].m_dropEmitterSettings;
m_currDropRenderSettings = m_gpuDropSettings[nextGpuFxIndex].m_dropRenderSettings;
m_currWindInfluence = m_gpuDropSettings[nextGpuFxIndex].m_windInfluence;
m_currGravity = m_gpuDropSettings[nextGpuFxIndex].m_gravity;
m_currFxIndex = nextGpuFxIndex;
}
}
}
if ((prevGpuFxIndex!=-1 && m_gpuDropSettings[prevGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_REGION)) ||
(nextGpuFxIndex!=-1 && m_gpuDropSettings[nextGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_REGION)))
{
m_currDropRenderSettings.colour.w *= currVfxRegionLevel;
}
// hack for when it's raining and a slowdown special ability is active
CPed* pPed = CGameWorld::FindLocalPlayer();
if (pPed && pPed->GetSpecialAbility() && pPed->GetSpecialAbility()->IsActive() &&
(pPed->GetSpecialAbility()->GetType()==SAT_CAR_SLOWDOWN || pPed->GetSpecialAbility()->GetType()==SAT_BULLET_TIME))
{
if ((prevGpuFxIndex!=-1 && m_gpuDropSettings[prevGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_RAIN)) ||
(nextGpuFxIndex!=-1 && m_gpuDropSettings[nextGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_RAIN)))
{
if (!m_pPtxGpu->IsMistInstance() && !m_pPtxGpu->IsGroundInstance())
{
Vector4 currSizeMinMax = m_currDropRenderSettings.sizeMinMax;
m_currDropRenderSettings.sizeMinMax = Vector4(currSizeMinMax.x*GPUPTFX_SLOWDOWN_ABILITY_RAIN_DROP_WIDTH_SCALE,
currSizeMinMax.y*GPUPTFX_SLOWDOWN_ABILITY_RAIN_DROP_HEIGHT_SCALE,
currSizeMinMax.z*GPUPTFX_SLOWDOWN_ABILITY_RAIN_DROP_WIDTH_SCALE,
currSizeMinMax.w*GPUPTFX_SLOWDOWN_ABILITY_RAIN_DROP_HEIGHT_SCALE);
}
}
}
if(m_useOverrideSettings)
{
m_currDropEmitterSettings.boxCentreOffset = RCC_VECTOR3(m_overrideBoxOffset);
m_currDropEmitterSettings.boxSize = RCC_VECTOR3(m_overrideBoxSize);
}
}
///////////////////////////////////////////////////////////////////////////////
// Interpolate
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUDropSystem::Interpolate(s32 thirdGpuFxIndex, float weatherInterp)
{
// update the current state
if (m_gpuDropSettings[thirdGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_RAIN))
{
m_currLevel = g_vfxWeather.GetCurrRain();
}
else if (m_gpuDropSettings[thirdGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_SNOW))
{
m_currLevel = g_vfxWeather.GetCurrSnow();
}
else if (m_gpuDropSettings[thirdGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_NONE))
{
m_currLevel = 1.0f; // underwater - always on
}
if(m_useOverrideSettings)
{
m_currLevel = m_overrideCurrLevel;
}
if( m_currFxIndex == -1 || m_currFxIndex == thirdGpuFxIndex )
{ // not trully interpolating...
m_currDropEmitterSettings = m_gpuDropSettings[thirdGpuFxIndex].m_dropEmitterSettings;
m_currDropRenderSettings = m_gpuDropSettings[thirdGpuFxIndex].m_dropRenderSettings;
m_currWindInfluence = m_gpuDropSettings[thirdGpuFxIndex].m_windInfluence;
m_currGravity = m_gpuDropSettings[thirdGpuFxIndex].m_gravity;
m_currFxIndex = thirdGpuFxIndex;
}
else
{
m_currDropEmitterSettings.Interpolate(m_gpuDropSettings[thirdGpuFxIndex].m_dropEmitterSettings, weatherInterp);
m_currDropRenderSettings.Interpolate(m_gpuDropSettings[thirdGpuFxIndex].m_dropRenderSettings, weatherInterp);
float tmp = m_currWindInfluence;
m_currWindInfluence = tmp + ((m_gpuDropSettings[thirdGpuFxIndex].m_windInfluence - tmp)*weatherInterp);
tmp = m_currGravity;
m_currGravity = tmp + ((m_gpuDropSettings[thirdGpuFxIndex].m_gravity - tmp)*weatherInterp);
}
if(m_useOverrideSettings)
{
m_currDropEmitterSettings.boxCentreOffset = RCC_VECTOR3(m_overrideBoxOffset);
m_currDropEmitterSettings.boxSize = RCC_VECTOR3(m_overrideBoxSize);
}
}
///////////////////////////////////////////////////////////////////////////////
// PreRender
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUDropSystem::PreRender (grcViewport& viewport, float deltaTime, bool resetParticles)
{
// check if gpu particles are active
if (m_currLevel>0.0f)
{
// set up the emitter
((ptxgpuDrop*)m_pPtxGpu)->SetEmitterSettings(m_currDropEmitterSettings);
CPtFxGPUSystem::PreRender(viewport, deltaTime, resetParticles);
}
}
///////////////////////////////////////////////////////////////////////////////
// Render
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUDropSystem::Render (grcViewport& viewport, ptxRenderSetup* pRenderSetup, Vec3V_In vCamVel, float camPosZ, float groundPosZ BANK_ONLY(, Vec4V_In vCamAngleLimits))
{
// check if gpu particles are active
if (m_currLevel>0.0f)
{
// render the gpu particles
Matrix44 cam = RCC_MATRIX44(viewport.GetCameraMtx44());
Vector3 boxForward = -cam.c.GetVector3() * Vector3(1.0f, 1.0f, 0.0f);
boxForward.Normalize();
Vector3 boxCentrePos = cam.d.GetVector3() + boxForward * 10.0f;
Vector3 boxWidth(35.0f, 35.0f, 25.0f);
Lights::UseLightsInArea(spdAABB(VECTOR3_TO_VEC3V(boxCentrePos - boxWidth), VECTOR3_TO_VEC3V(boxCentrePos + boxWidth)), false, true, false, true);
const bool bHasDistortion = HasDistortion();
if ( m_currDropRenderSettingsRT.backgroundDistortionBlurLevel > -1 )
{
m_currDropRenderSettingsRT.pBackBufferTexture = PostFX::GetDownSampledBackBuffer(bHasDistortion ? m_currDropRenderSettingsRT.backgroundDistortionBlurLevel : 0);
}
else
{
m_currDropRenderSettingsRT.pBackBufferTexture = const_cast<grcTexture*>( grcTexture::NoneBlack );
}
if (g_visualSettings.GetV<float>(atHashValue("rain.useLitShader"), 1.0f))
{
float lightIntensityMult = g_timeCycle.GetCurrRenderKeyframe().GetVar(TCVAR_GPUPTFX_LIGHT_INTENSITY_MULT);
m_currDropRenderSettingsRT.lightIntensityMultiplier = lightIntensityMult;
}
((ptxgpuDrop*)m_pPtxGpu)->SetRenderSettings(m_currDropRenderSettingsRT);
//Lets figure out the pass
bool bUseAnimatedTextures = (m_currDropRenderSettingsRT.textureAnimRateScaleOverLifeStart2End2.x > 0);
bool bUseABBlend = ((m_currDropRenderSettingsRT.textureRowsColsStartEnd.z != m_currDropRenderSettingsRT.textureAnimRateScaleOverLifeStart2End2.z) ||
(m_currDropRenderSettingsRT.textureRowsColsStartEnd.w != m_currDropRenderSettingsRT.textureAnimRateScaleOverLifeStart2End2.w)) ;
const int pass = BIT(0) * bUseAnimatedTextures + BIT(1) * bUseABBlend + BIT(2) * bHasDistortion;
m_pPtxGpu->GetRenderShader()->SetPass(pass);
((ptxgpuDrop*)m_pPtxGpu)->Render(&viewport, vCamVel, m_currDropEmitterSettings.lifeMinMax.y, camPosZ, groundPosZ, pRenderSetup, Min(m_currLevel*1.5f, 1.0f) BANK_ONLY(, vCamAngleLimits));
m_pPtxGpu->GetRenderShader()->SetPass(0);
}
}
///////////////////////////////////////////////////////////////////////////////
// GetSettingIndex
///////////////////////////////////////////////////////////////////////////////
s32 CPtFxGPUDropSystem::GetSettingIndex (atHashValue hashValue)
{
for (u32 i=0; i<m_numSettings; i++)
{
if (m_gpuDropSettings[i].m_hashValue == hashValue)
{
return i;
}
}
return -1;
}
///////////////////////////////////////////////////////////////////////////////
// GetEmitterBounds
///////////////////////////////////////////////////////////////////////////////
bool CPtFxGPUDropSystem::GetEmitterBounds (Mat44V_ConstRef camMatrix, Vec3V_Ref emitterMin, Vec3V_Ref emitterMax)
{
if (m_currLevel>0.0f)
{
((ptxgpuDrop*)m_pPtxGpu)->GetEmitterBounds(camMatrix, emitterMin, emitterMax);
return true;
}
return false;
}
#if __BANK
///////////////////////////////////////////////////////////////////////////////
// InitWidgets
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUDropSystem::InitWidgets ()
{
bkBank* pVfxBank = vfxWidget::GetBank();
pVfxBank->AddTitle("INFO");
pVfxBank->AddSlider("Num Settings", &m_numSettings, 0, PTFXGPU_MAX_SETTINGS, 0);
pVfxBank->AddSlider("Curr Level", &m_currLevel, -100.0f, 100.0f, 0.0f);
pVfxBank->AddSlider("Curr Wind Influence", &m_currWindInfluence, -100.0f, 100.0f, 0.0f);
pVfxBank->AddSlider("Curr Gravity", &m_currGravity, -100.0f, 100.0f, 0.0f);
m_pPtxGpu->AddWidgets(*pVfxBank);
for (u32 i=0; i<m_numSettings; i++)
{
char txt[64];
#if !__FINAL
sprintf(txt, "Emitter Settings - %s", m_gpuDropSettings[i].m_name);
#else
sprintf(txt, "Emitter Settings - %d", i);
#endif
pVfxBank->PushGroup(txt, false);
m_gpuDropSettings[i].m_dropEmitterSettings.AddWidgets(*pVfxBank, true);
pVfxBank->PopGroup();
#if !__FINAL
sprintf(txt, "Render Settings - %s", m_gpuDropSettings[i].m_name);
#else
sprintf(txt, "Render Settings - %d", i);
#endif
pVfxBank->PushGroup(txt, false);
m_gpuDropSettings[i].m_dropRenderSettings.AddWidgets(*pVfxBank, true);
pVfxBank->PopGroup();
}
}
void CPtFxGPUDropSystem::RenderDebug(const grcViewport& viewport, const Color32& color)
{
if (m_currLevel>0.0f)
{
((ptxgpuDrop*)m_pPtxGpu)->RenderDebug(viewport, color);
}
}
///////////////////////////////////////////////////////////////////////////////
// DebugUpdateRenderSettings
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUDropSystem::DebugUpdateRenderSettings (s32 prevGpuFxIndex, s32 nextGpuFxIndex, float weatherInterp, float currVfxRegionLevel)
{
//This function just updates the render settings while the game is paused. It makes it easier for artists to tune the settings in real time without unpausing the game
if (prevGpuFxIndex==-1 && nextGpuFxIndex==-1)
{
//Do nothing as state does not change
}
else if (prevGpuFxIndex==-1)
{
ptfxAssertf(nextGpuFxIndex>=0 && nextGpuFxIndex<(s32)m_numSettings, "next GPU index is out of range");
m_currDropRenderSettings = m_gpuDropSettings[nextGpuFxIndex].m_dropRenderSettings;
}
else if (nextGpuFxIndex==-1)
{
ptfxAssertf(prevGpuFxIndex>=0 && prevGpuFxIndex<(s32)m_numSettings, "previous GPU index is out of range");
m_currDropRenderSettings = m_gpuDropSettings[prevGpuFxIndex].m_dropRenderSettings;
}
else
{
ptfxAssertf(prevGpuFxIndex>=0 && prevGpuFxIndex<(s32)m_numSettings, "previous GPU index is out of range");
ptfxAssertf(nextGpuFxIndex>=0 && nextGpuFxIndex<(s32)m_numSettings, "next GPU index is out of range");
if (prevGpuFxIndex==nextGpuFxIndex)
{
m_currDropRenderSettings = m_gpuDropSettings[prevGpuFxIndex].m_dropRenderSettings;
}
else
{
ptfxAssertf(m_gpuDropSettings[prevGpuFxIndex].m_driveType == m_gpuDropSettings[nextGpuFxIndex].m_driveType, "trying to interpolate between 2 GPU effects of different types");
m_currDropRenderSettings.Interpolate(m_gpuDropSettings[prevGpuFxIndex].m_dropRenderSettings, m_gpuDropSettings[nextGpuFxIndex].m_dropRenderSettings, weatherInterp);
}
}
if ((prevGpuFxIndex!=-1 && m_gpuDropSettings[prevGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_REGION)) ||
(nextGpuFxIndex!=-1 && m_gpuDropSettings[nextGpuFxIndex].m_driveType==(u32)(DRIVE_TYPE_REGION)))
{
m_currDropRenderSettings.colour.w *= currVfxRegionLevel;
}
}
#endif // __BANK
///////////////////////////////////////////////////////////////////////////////
// PauseSimulation
///////////////////////////////////////////////////////////////////////////////
void CPtFxGPUDropSystem::PauseSimulation()
{
m_pPtxGpu->PauseSimulation();
}