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

3234 lines
114 KiB
C++

//
// Filename: CustomShaderEffectVehicle.h
// Description: Takes care of all gta_vehicle shader variables (supports vehicle body colours);
// Written by: Andrzej
//
//
// 07/10/2005 - Andrzej: - initial;
// 02/11/2005 - Andrzej: - body colours support added;
// 29/01/2007 - Andrzej: - Specular2Color support added;
// 12/03/2007 - Andrzej: - editable shader values for Jo added:
// 22/06/2007 - Andrzej: - storing original Specular added;
// 02/09/2007 - Andrzej: - burnout texture support added (burnout texture replaces dirt texture);
// 10/09/2007 - Andrzej: - tyre deform control added;
// 20/09/2007 - Andrzej: - bodycolor5 added;
// 12/10/2007 - Andrzej: - Editable Tire Inner Radius stuff added (__BANK only);
//
//
//
#include "system/nelem.h"
#include "grcore/effect_config.h"
// Framework headers
//#include "fwmaths/maths.h"
#include "fwscene/stores/fragmentstore.h"
#include "fwsys/timer.h"
#include "fwdrawlist/drawlistmgr.h"
#include "streaming/streamingengine.h"
#include "streaming/streaming.h"
// Game headers:
#include "CustomShaderEffectVehicle.h"
#include "camera/CamInterface.h"
#include "control/replay/replay.h"
#include "control/replay/ReplayExtensions.h"
#include "debug/debug.h"
#include "debug/DebugGlobals.h" // gbDontDisplayDirtOnVehicles...
#include "game/weather.h" // g_weather
#include "scene/Entity.h"
#include "modelinfo/ModelInfo.h"
#include "modelinfo/VehicleModelInfo.h"
#include "modelinfo/VehicleModelInfoColors.h"
#include "physics/physics.h" // for CPhysics::GetGlassTxdSlot
#include "renderer/DrawLists/drawlist.h"
#include "renderer/Lights/lights.h"
#include "shaders/shaderlib.h"
#include "vfx/misc/Coronas.h"
#include "vehicles/Vehicle.h"
#include "vehicles/wheel.h"
#if !__FINAL
PARAM(novehicledirt, "Don't display vehicle dirt");
#endif
// #include "system/findsize.h"
// FindSize(CCustomShaderEffectVehicle); was 240 before license plate cleanup, now 156.
// FindSize(CCustomShaderEffectVehicleType); - 20 bytes.
//
//
// body colour remapping:
//
#define BODYCOLOR1 Vector3(2.0f, 1.0f, 1.0f)
#define BODYCOLOR2 Vector3(2.0f, 2.0f, 2.0f)
#define BODYCOLOR3 Vector3(2.0f, 3.0f, 3.0f)
#define BODYCOLOR4 Vector3(2.0f, 4.0f, 4.0f)
#define BODYCOLOR5 Vector3(2.0f, 5.0f, 5.0f) // special color for interiors
#define BODYCOLOR6 Vector3(2.0f, 6.0f, 6.0f) // special color for interiors
#define BODYCOLOR7 Vector3(2.0f, 7.0f, 7.0f) // special color for interiors
#define DEFAULT_DIRTMODWET (0.60f) // default dirt mod intensity when et
// --- Globals ------------------------------------------------------------------
#if CSE_VEHICLE_EDITABLEVALUES
bool CCustomShaderEffectVehicle::ms_bEVEnabled = FALSE;
float CCustomShaderEffectVehicle::ms_fEVSpecFalloff = 100.0f;
float CCustomShaderEffectVehicle::ms_fEVSpecFresnel = 0.75f;
float CCustomShaderEffectVehicle::ms_fEVSpecIntensity = 1.0f;
float CCustomShaderEffectVehicle::ms_fEVSpecTexTileUV = 1.0f;
float CCustomShaderEffectVehicle::ms_fEVSpec2Falloff = 5.0f;
float CCustomShaderEffectVehicle::ms_fEVSpec2Intensity = 0.0f;
bool CCustomShaderEffectVehicle::ms_bEVSpec2DirLerpOverride = FALSE;
float CCustomShaderEffectVehicle::ms_fEVSpec2DirLerp = 0.0f;
float CCustomShaderEffectVehicle::ms_fEVReflectivity = 0.45f;
float CCustomShaderEffectVehicle::ms_fEVBumpiness = 1.0f;
float CCustomShaderEffectVehicle::ms_fEVDiffuseTexTileUV = 8.0f;
float CCustomShaderEffectVehicle::ms_fEVEnvEffThickness = 25.0f;
float CCustomShaderEffectVehicle::ms_fEVEnvEffScale = 1.0f;
float CCustomShaderEffectVehicle::ms_fEVEnvEffTexTileUV = 8.0f;
bool CCustomShaderEffectVehicle::ms_fEVOverrideBodyColor = FALSE;
Vector3 CCustomShaderEffectVehicle::ms_fEVBodyColor = Vector3(1.0f, 0.5f, 1.0f);
bool CCustomShaderEffectVehicle::ms_fEVOverrideDiffuseColorTint= FALSE;
Vector3 CCustomShaderEffectVehicle::ms_fEVDiffuseColorTint = Vector3(1.0f, 0.0f, 0.0f);
float CCustomShaderEffectVehicle::ms_fEVDiffuseColorTintAlpha = 0.5f;
float CCustomShaderEffectVehicle::ms_fEVDirtLevel = 1.0f;
float CCustomShaderEffectVehicle::ms_fEVDirtModDry = 1.0f;
float CCustomShaderEffectVehicle::ms_fEVDirtModWet = DEFAULT_DIRTMODWET;
s32 CCustomShaderEffectVehicle::ms_fEVDirtOrBurnout = 1;
Vector3 CCustomShaderEffectVehicle::ms_fEVDirtColor = Vector3(59.0f/255.0f, 57.0f/255.0f, 52.0f/255.0f); // dirtColor RGB=(59,57,52)
// editable inner wheel radius stuff:
bool CCustomShaderEffectVehicle::ms_bEWREnabled = FALSE;
bool CCustomShaderEffectVehicle::ms_bEWRTyreEnabled = TRUE;
float CCustomShaderEffectVehicle::ms_fEWRInnerRadius = 1.500f;
// editables for sunglare:
bool CCustomShaderEffectVehicle::ms_bEVSunGlareEnabled = FALSE;
float CCustomShaderEffectVehicle::ms_fEVSunGlareDistMin = 65.0f;
float CCustomShaderEffectVehicle::ms_fEVSunGlareDistMax = 75.0f;
u32 CCustomShaderEffectVehicle::ms_nEVSunGlarePow = 1;
float CCustomShaderEffectVehicle::ms_fEVSunGlareSpriteSize = 0.55f;
float CCustomShaderEffectVehicle::ms_fEVSunGlareSpriteZShiftScale = 0.2f;
float CCustomShaderEffectVehicle::ms_fEVSunGlareHdrMult = 8.0f;
Vector4 CCustomShaderEffectVehicle::ms_fEVLetterIndex1 = Vector4(10, 21, 10, 23);
Vector4 CCustomShaderEffectVehicle::ms_fEVLetterIndex2 = Vector4(63, 63, 62, 0);
Vector2 CCustomShaderEffectVehicle::ms_fEVLetterSize = Vector2(1.0f / 16.0f, 1.0f / 4.0f);
Vector2 CCustomShaderEffectVehicle::ms_fEVNumLetters = Vector2(16.0f,4.0f);
Vector4 CCustomShaderEffectVehicle::ms_fEVLicensePlateFontExtents = Vector4(0.043f, 0.38f, 0.945f, 0.841f);
Vector4 CCustomShaderEffectVehicle::ms_fEVLicensePlateFontTint = Vector4(1.0f, 1.0f, 1.0f, 0.0f);
float CCustomShaderEffectVehicle::ms_fEVFontNormalScale = 1.0f;
float CCustomShaderEffectVehicle::ms_fEVDistMapCenterVal = 0.5f;
Vector4 CCustomShaderEffectVehicle::ms_fEVDistEpsilonScaleMin = Vector4(1.0f, 1.0f, 0.0f, 0.0f);
Vector3 CCustomShaderEffectVehicle::ms_fEVFontOutlineMinMaxDepthEnabled = Vector3(0.475f, 0.5, 0.0f);
Vector3 CCustomShaderEffectVehicle::ms_fEVFontOutlineColor = Vector3(0.0f, 0.0f, 0.0f);
float CCustomShaderEffectVehicle::ms_fEVBurnoutSpeed = 0.01f; // minimum increase step is 1/255
#endif //CSE_VEHICLE_EDITABLEVALUES...
#if __DEV
s32 CCustomShaderEffectVehicle::ms_nForceColorCars = 2;
#endif
#if USE_DISKBRAKEGLOW
#define DISKBRAKEGLOW_V2 0
#define DISKBRAKEGLOW_DEBUG_TEXT 0
#define DISKBRAKEGLOW_DEBUG_TEXT_FULLWHEELDETAIL 0
#define DISKBRAKEGLOW_DEBUG_SHADER 0
#if DISKBRAKEGLOW_V2
static dev_float g_fDiskBrake_MaxHeatingRate = 3.0f;
static dev_float g_fDiskBrake_CoolingRate = 0.15f;
static dev_float g_fDiskBrake_SpeedCap = 80.0f/3.6f; // From kmh-1 to ms-1
#else // DISKBRAKEGLOW_V2
static dev_float g_fDiskBrake_CoolingRate = 0.15f;
static dev_float g_fDiskBrake_TempMagicNumber = 1.5f;
static dev_float g_fDiskBrake_SpeedCap = 70.0f/3.6f; // From kmh-1 to ms-1
#endif // DISKBRAKEGLOW_V2
static dev_float g_fDiskBrake_EngineAge = 5.0f * 60.0f * 1000.0f;
#endif // USE_DISKBRAKEGLOW
//
// global burnout texture for vehicles:
//
//
#define VEHICLE_GENERIC_BURNOUT_TEXNAME "vehicle_generic_burnt_out"
#define VEHICLE_GENERIC_BURNOUT_INT_TEXNAME "vehicle_generic_burnt_int"
#define VEHICLE_GENERIC_BURNOUT_TRUCK_TEXNAME "vehicle_generic_burnt_out_truck"
// Default initialization to zero, which means NULL
grcTextureIndex CCustomShaderEffectVehicleType::ms_pBurnoutTexture;
grcTextureIndex CCustomShaderEffectVehicleType::ms_pBurnoutIntTexture;
grcTextureIndex CCustomShaderEffectVehicleType::ms_pBurnoutTruckTexture;
s32 CCustomShaderEffectVehicleType::ms_nBurnoutTruckTextureRef = 0;
#if VEHICLE_SUPPORT_PAINT_RAMP
#define VEHICLE_PAINT_RAMP_DISABLED_VALUE (-1.0f)
static strLocalIndex s_RampTxdId;
#if __BANK
static bool s_RampDiffuseEnabled = true;
static bool s_RampSpecularEnabled = true;
#endif
void CCustomShaderEffectVehicle::LoadRampTxd()
{
s_RampTxdId = g_TxdStore.FindSlot(strStreamingObjectName("vehicle_paint_ramps"));
if(s_RampTxdId.IsValid())
{
CStreaming::LoadObject(s_RampTxdId, g_TxdStore.GetStreamingModuleId());
g_TxdStore.AddRef(s_RampTxdId, REF_OTHER);
}
}
void CCustomShaderEffectVehicle::UnloadRampTxd()
{
if (s_RampTxdId.IsValid())
{
g_TxdStore.RemoveRef(s_RampTxdId, REF_OTHER);
s_RampTxdId = strLocalIndex();
}
}
fwTxd * CCustomShaderEffectVehicle::GetRampTxd()
{
fwTxd *result = s_RampTxdId.IsValid() ? g_TxdStore.Get(s_RampTxdId) : 0;
return result;
}
#if __BANK
static bool s_DebugRampTextureEnabled = false;
static char s_DebugRampTexturePath[256] = { "C:/Temp/vehicle_paint_ramp" };
static grcTexture* s_DebugRampTexture = 0;
static void ReloadDebugRampTexture()
{
if(s_DebugRampTextureEnabled)
{
sysMemStartTemp();
grcImage* img = grcImage::LoadDDS(s_DebugRampTexturePath);
if(!img)
{
img = grcImage::LoadJPEG(s_DebugRampTexturePath);
}
sysMemEndTemp();
if(img)
{
grcTextureFactory::TextureCreateParams params(grcTextureFactory::TextureCreateParams::VIDEO, grcTextureFactory::TextureCreateParams::TILED);
s_DebugRampTexture = grcTextureFactory::GetInstance().Create(img, &params);
sysMemStartTemp();
img->Release();
img = 0;
sysMemEndTemp();
}
}
}
#endif
#endif
//
//
//
//
CCustomShaderEffectVehicleType* CCustomShaderEffectVehicleType::Create(rmcDrawable *pDrawable, CVehicleModelInfo *pVehicleMI, grmShaderGroup *pClonedShaderGroup)
{
Assert(pDrawable);
// Initialize structure to all zero.
CCustomShaderEffectVehicleType *pType = rage_new CCustomShaderEffectVehicleType();
// BS#2551385: vehicle mods: use cloned shaderGroup (if exists) rather than drawable's original shaderGroup:
grmShaderGroup* shaderGroup = pClonedShaderGroup? pClonedShaderGroup : &pDrawable->GetShaderGroup();
const s32 shaderCount = shaderGroup->GetCount();
atArray<CCustomShaderEffectVehicleType::structDiffColEffect> tmpTabDiffCol(0, shaderCount); // temp table to gather all variable info's
atArray<CCustomShaderEffectVehicleType::structSpecColEffect> tmpTabSpecularCol(0, shaderCount);
atArray<CCustomShaderEffectVehicleType::structDirtTexEffect> tmpTabDirtTex(0, shaderCount);
atArray<CCustomShaderEffectVehicleType::structTex2Effect> tmpTabTex2(0, shaderCount);
pType->m_bHasBodyColor1 =
pType->m_bHasBodyColor2 =
pType->m_bHasBodyColor3 =
pType->m_bHasBodyColor4 =
pType->m_bHasBodyColor5 =
pType->m_bHasBodyColor6 =
pType->m_bHasBodyColor7 = false;
bool bFoundEmissiveMult = false;
pType->m_DefEmissiveMult = 1.0f;
if(pVehicleMI)
{
const u32 vehNameHash = pVehicleMI->GetModelNameHash();
if( (vehNameHash == 0xE7D2A16E) || // "shotaro"
(vehNameHash == 0x3AF76F4A) || // "voltic2"
(vehNameHash == 0xE6E967F8) || // "patriot2"
(vehNameHash == 0x93F09558) ) // "deathbike2"
{
// enable only for shotaro & voltic2:
Assert(pType->m_idVarEmissiveMult != grmsgvNONE);
}
else
{
// disable for everything else
pType->m_idVarEmissiveMult = grmsgvNONE;
}
}
else
{
// disable for everything else
pType->m_idVarEmissiveMult = grmsgvNONE;
}
for(s32 i=0; i<shaderCount; i++)
{
grmShader *pShader = shaderGroup->GetShaderPtr(i);
Assert(pShader);
// grcEffect *pEffect = &pShader->GetEffect();
u8 colorIdx = 255; // invalid value
// 1. DiffuseColor:
grcEffectVar idvarDifCol = pShader->LookupVar("DiffuseColor", FALSE);
if(idvarDifCol)
{
Vector3 diffCol;
pShader->GetVar(idvarDifCol, diffCol);
Assert((int)idvarDifCol < 256); // must fit into u8
Assert(i < 256); // must fit into u8
CCustomShaderEffectVehicleType::structDiffColEffect dcEffect;
dcEffect.idvarDiffColor = (u8)idvarDifCol;
#if VEHICLE_SUPPORT_PAINT_RAMP
dcEffect.idvarDiffuseRampTexture = (u8)pShader->LookupVar("DiffuseRampTexture", FALSE);
dcEffect.idvarSpecularRampTexture = (u8)pShader->LookupVar("SpecularRampTexture", FALSE);
dcEffect.idvarDiffuseSpecularRampEnabled = (u8)pShader->LookupVar("matDiffuseSpecularRampEnabled", FALSE);
#endif
dcEffect.shaderIdx = (u8)i;
// find color mapping
if(diffCol == BODYCOLOR1)
{
dcEffect.colorIdx = colorIdx = 0;
pType->m_bHasBodyColor1 = true;
tmpTabDiffCol.Append() = dcEffect;
}
else if(diffCol == BODYCOLOR2)
{
dcEffect.colorIdx = colorIdx = 1;
pType->m_bHasBodyColor2 = true;
tmpTabDiffCol.Append() = dcEffect;
}
else if(diffCol == BODYCOLOR3)
{
dcEffect.colorIdx = colorIdx = 2;
pType->m_bHasBodyColor3 = true;
tmpTabDiffCol.Append() = dcEffect;
}
else if(diffCol == BODYCOLOR4)
{
dcEffect.colorIdx = colorIdx = 3;
pType->m_bHasBodyColor4 = true;
tmpTabDiffCol.Append() = dcEffect;
}
else if(diffCol == BODYCOLOR5)
{
dcEffect.colorIdx = colorIdx = 4;
pType->m_bHasBodyColor5 = true;
tmpTabDiffCol.Append() = dcEffect;
}
else if(diffCol == BODYCOLOR6)
{
dcEffect.colorIdx = colorIdx = 5;
pType->m_bHasBodyColor6 = true;
tmpTabDiffCol.Append() = dcEffect;
}
else if(diffCol == BODYCOLOR7)
{
dcEffect.colorIdx = colorIdx = 6;
pType->m_bHasBodyColor7 = true;
tmpTabDiffCol.Append() = dcEffect;
}
}//if(idvarDifCol)...
// 2. Specular values: Intensity, Falloff and Fresnel:
grcEffectVar idvarSpecInt = pShader->LookupVar("SpecularColor", FALSE);
grcEffectVar idvarSpecFalloff = pShader->LookupVar("Specular", FALSE);
grcEffectVar idvarSpecFresnel = pShader->LookupVar("Fresnel", FALSE);
if(idvarSpecInt || idvarSpecFalloff || idvarSpecFresnel)
{
CCustomShaderEffectVehicleType::structSpecColEffect &dcEffect = tmpTabSpecularCol.Append();
dcEffect.idvarSpecInt =
dcEffect.idvarSpecFalloff =
dcEffect.idvarSpecFresnel = grcevNONE;
if(idvarSpecInt)
{
Assert((int)idvarSpecInt < 256); // must fit into u8
dcEffect.idvarSpecInt = (u8)idvarSpecInt;
float originalSpecInt=1.0f;
pShader->GetVar(idvarSpecInt, originalSpecInt);
dcEffect.origSpecInt = originalSpecInt;
}
if(idvarSpecFalloff)
{
Assert((int)idvarSpecFalloff < 256); // must fit into u8
dcEffect.idvarSpecFalloff = (u8)idvarSpecFalloff;
float originalSpecFalloff=1.0f;
pShader->GetVar(idvarSpecFalloff, originalSpecFalloff);
dcEffect.origSpecFalloff = originalSpecFalloff;
}
if(idvarSpecFresnel)
{
Assert((int)idvarSpecFresnel < 256); // must fit into u8
dcEffect.idvarSpecFresnel = (u8)idvarSpecFresnel;
float originalSpecFresnel=1.0f;
pShader->GetVar(idvarSpecFresnel, originalSpecFresnel);
dcEffect.origSpecFresnel = originalSpecFresnel;
}
Assert(i < 256); // must fit into u8
dcEffect.shaderIdx = (u8)i;
Assert((int)colorIdx < 256); // must fit into u8
dcEffect.colorIdx = (u8)colorIdx;
}
// 3. Dirt texture:
bool bDirtIsInterior = false;
grcEffectVar idvarDirtTex = pShader->LookupVar("DirtTex", FALSE);
if(!idvarDirtTex)
{ // replace main diffuse tex when dirt texture not present (interiors, wheels, etc.):
idvarDirtTex = pShader->LookupVar("DiffuseTex", FALSE);
bDirtIsInterior = true;
}
// don't setup burnout texture for badges & cutout:
if(idvarDirtTex)
{
const char *pShaderName = pShader->GetName();
if(pShaderName)
{
if( (!strcmp("vehicle_badges", pShaderName)) ||
(!strcmp("vehicle_cutout", pShaderName)) )
{
idvarDirtTex = grcevNONE;
}
}
}
// tentative "patch" for B*2275234, B*2137345 and B*2272964:
Assertf((int(idvarDirtTex) <= 255), "Vehicle: %s: idvarDirtTex is far too big!", pVehicleMI->GetModelName());
if(int(idvarDirtTex) > 255)
{
idvarDirtTex = grcevNONE;
}
if(idvarDirtTex)
{
CCustomShaderEffectVehicleType::structDirtTexEffect &dcEffect = tmpTabDirtTex.Append();
grcTexture *pOrigDirtTex=NULL;
pShader->GetVar(idvarDirtTex, pOrigDirtTex);
#if __ASSERT
if(pOrigDirtTex)
{ // make sure it's not texture reference:
Assert(pOrigDirtTex->GetResourceType()!=grcTexture::REFERENCE);
}
#endif //__ASSERT...
Assert((int)idvarDirtTex < 256); // must fit into u8
Assert(i < 256); // must fit into u8
strStreamingEngine::AddRefByPtr(pOrigDirtTex, REF_OTHER);
dcEffect.pOrigDirtTex = pOrigDirtTex;
dcEffect.idvarDirtTex = (u8)idvarDirtTex;
dcEffect.shaderIdx = (u8)i;
dcEffect.bIsInterior = bDirtIsInterior;
}
grcEffectVar idvarDirtCol = pShader->LookupVar("DirtColor", FALSE);
if(idvarDirtCol)
{
Vector3 origDirtCol;
pShader->GetVar(idvarDirtCol, origDirtCol);
pType->m_DefDirtColor.Setf(origDirtCol.x, origDirtCol.y, origDirtCol.z, 1.0f);
}
// 4. overlay texture:
grcEffectVar idvarTex2 = pShader->LookupVar("DiffuseTex2", FALSE);
if(idvarTex2)
{
CCustomShaderEffectVehicleType::structTex2Effect &dcEffect = tmpTabTex2.Append();
grcTexture *pOrigTex2=NULL;
pShader->GetVar(idvarTex2, pOrigTex2);
#if __ASSERT
if(pOrigTex2)
{ // make sure it's not texture reference:
Assert(pOrigTex2->GetResourceType()!=grcTexture::REFERENCE);
}
#endif //__ASSERT...
Assert((int)idvarTex2 < 256); // must fit into u8
Assert(i < 256); // must fit into u8
strStreamingEngine::AddRefByPtr(pOrigTex2, REF_OTHER);
dcEffect.pOrigTex2 = pOrigTex2;
dcEffect.idvarTex2 = (u8)idvarTex2;
dcEffect.shaderIdx = (u8)i;
}
if(pType->m_idVarEmissiveMult)
{
grcEffectVar idvarEmissiveMult = pShader->LookupVar("EmissiveMultiplier", FALSE);
if(idvarEmissiveMult)
{
float fEmissiveMult;
pShader->GetVar(idvarEmissiveMult, fEmissiveMult);
if(!bFoundEmissiveMult)
{
bFoundEmissiveMult = true;
pType->m_DefEmissiveMult = fEmissiveMult;
}
else
{
Assertf(pType->m_DefEmissiveMult == fEmissiveMult, "%s: EmissiveMultiplier (=%.2f) is not the same for all parts of the vehicle: found %.2f.",pVehicleMI->GetModelName(), pType->m_DefEmissiveMult, fEmissiveMult);
}
}
}
}// for(s32 i=0; i<shaderCount; i++)...
if(pVehicleMI && (!pVehicleMI->GetAllowBodyColorMapping()))
{
// block color mapping for scripts if requested
pType->m_bHasBodyColor1 =
pType->m_bHasBodyColor2 =
pType->m_bHasBodyColor3 =
pType->m_bHasBodyColor4 =
pType->m_bHasBodyColor5 =
pType->m_bHasBodyColor6 =
pType->m_bHasBodyColor7 = false;
}
pType->m_DiffColEffect = tmpTabDiffCol;
#if __ASSERT
extern char* CCustomShaderEffectBase_EntityName;
Assertf(pType->m_DiffColEffect.GetCount() > 0, "BS#124925: %s (drawable=%p, shaderGroup=%p): DiffColEffect array is empty! This vehicle's materials do not have a valid color variation. Andrzej would love to see this assert.", CCustomShaderEffectBase_EntityName, pDrawable, shaderGroup);
#endif
pType->m_SpecColEffect = tmpTabSpecularCol;
pType->m_DirtTexEffect = tmpTabDirtTex;
pType->m_Tex2Effect = tmpTabTex2;
// burnout truck texture setup:
// 1. vehshare_truck is dynamically streamed in and is usually parent to vehicle's main txd
// 2. normal vehicle txd dependency: vehicle_txd <- vehshare
// 3. truck txd structure dependency: vehicle_txd <- vehshare_truck <- vehshare
Assert(CSystem::IsThisThreadId(SYS_THREAD_UPDATE)); // truck burnout tex referencing allowed only on update thread
pType->m_bHasTruckTex = false;
if(false && pVehicleMI) // separate burnout tex for trucks has been blocked - they share burnout tex with everybody else now
{
const strLocalIndex txdIdx = strLocalIndex(pVehicleMI->GetAssetParentTxdIndex());
if(txdIdx != -1)
{
const strLocalIndex vehshareTxdIdx = strLocalIndex(pVehicleMI->GetCommonTxd()); // vehshare is always resident at index 0
Assert(vehshareTxdIdx != -1);
const strLocalIndex parentTxdIdx = g_TxdStore.GetParentTxdSlot(txdIdx);
// assume first level parent to be vehshare_truck:
if( (parentTxdIdx!=-1) && (parentTxdIdx!=vehshareTxdIdx) )
{
const strLocalIndex vehshareTruckTxdIdx = parentTxdIdx;
grcTexture *burnoutTruckTex = g_TxdStore.Get(vehshareTruckTxdIdx)->Lookup(VEHICLE_GENERIC_BURNOUT_TRUCK_TEXNAME);
Assert(burnoutTruckTex);
if(ms_nBurnoutTruckTextureRef)
{ // same ptr as previously fetched?
Assert(ms_pBurnoutTruckTexture == burnoutTruckTex);
}
else
{
// update static shared pointer with burnouttrucktex ptr:
ms_pBurnoutTruckTexture = burnoutTruckTex;
}
ms_nBurnoutTruckTextureRef++;
pType->m_bHasTruckTex = true;
}
}
}
return pType;
}// end of CCustomShaderEffectVehicle::Create()...
//
//
// Recreates Type structures using texture ptr:
// - m_DirtTexEffect;
//
bool CCustomShaderEffectVehicleType::Recreate(rmcDrawable *pDrawable, CVehicleModelInfo* /*pVehicleMI*/)
{
Assert(pDrawable);
grmShaderGroup* shaderGroup = &pDrawable->GetShaderGroup();
const s32 shaderCount = shaderGroup->GetCount();
atArray<CCustomShaderEffectVehicleType::structDirtTexEffect> tmpTabDirtTex(0, shaderCount);
for(s32 i=0; i<shaderCount; i++)
{
grmShader *pShader = shaderGroup->GetShaderPtr(i);
Assert(pShader);
// 3. Dirt texture:
bool bDirtIsInterior = false;
grcEffectVar idvarDirtTex = pShader->LookupVar("DirtTex", FALSE);
if(!idvarDirtTex)
{ // replace main diffuse tex when dirt texture not present (interiors, wheels, etc.):
idvarDirtTex = pShader->LookupVar("DiffuseTex", FALSE);
bDirtIsInterior = true;
}
// don't setup burnout texture for badges:
if(idvarDirtTex)
{
const char *pShaderName = pShader->GetName();
if(pShaderName && !strcmp("vehicle_badges", pShaderName))
{
idvarDirtTex = grcevNONE;
}
}
if(idvarDirtTex)
{
CCustomShaderEffectVehicleType::structDirtTexEffect &dcEffect = tmpTabDirtTex.Append();
grcTexture *pOrigDirtTex=NULL;
pShader->GetVar(idvarDirtTex, pOrigDirtTex);
#if __ASSERT
if(pOrigDirtTex)
{ // make sure it's not texture reference:
Assert(pOrigDirtTex->GetResourceType()!=grcTexture::REFERENCE);
}
#endif //__ASSERT...
Assert((int)idvarDirtTex < 256); // must fit into u8
Assert(i < 256); // must fit into u8
strStreamingEngine::AddRefByPtr(pOrigDirtTex, REF_OTHER);
dcEffect.pOrigDirtTex = pOrigDirtTex;
dcEffect.idvarDirtTex = (u8)idvarDirtTex;
dcEffect.shaderIdx = (u8)i;
dcEffect.bIsInterior = bDirtIsInterior;
}
}// for(s32 i=0; i<shaderCount; i++)...
bool bRecreate=true;
// check if new dirtTexEffect tab contains burnout textures
// (if yes, then drawable was NOT re-streamed (burnout textures are only set by CSE code)
// and CSEType doesn't need to be recreated):
Assert(this->m_DirtTexEffect.GetCount()==tmpTabDirtTex.GetCount());
const u32 count = tmpTabDirtTex.GetCount();
for(u32 i=0; i<count; i++)
{
CCustomShaderEffectVehicleType::structDirtTexEffect *newPtr = &tmpTabDirtTex[i];
#if __ASSERT
CCustomShaderEffectVehicleType::structDirtTexEffect *oldPtr = &this->m_DirtTexEffect[i];
Assert(oldPtr->idvarDirtTex == newPtr->idvarDirtTex);
Assert(oldPtr->shaderIdx == newPtr->shaderIdx);
Assert(oldPtr->bIsInterior == newPtr->bIsInterior);
#endif
grcTexture *burnoutTex = m_bHasTruckTex? CCustomShaderEffectVehicleType::ms_pBurnoutTruckTexture : CCustomShaderEffectVehicleType::ms_pBurnoutTexture;
burnoutTex = newPtr->bIsInterior? CCustomShaderEffectVehicleType::ms_pBurnoutIntTexture : burnoutTex;
if(newPtr->pOrigDirtTex == burnoutTex)
{
bRecreate = false; // burnout tex detected: drawable was NOT re-streamed
}
}
atArray<CCustomShaderEffectVehicleType::structDirtTexEffect> *const removeRefs = bRecreate? &this->m_DirtTexEffect : &tmpTabDirtTex;
for(u32 i=0; i<count; i++)
{
grcTexture *const pTex = (*removeRefs)[i].pOrigDirtTex;
(*removeRefs)[i].pOrigDirtTex = NULL;
strStreamingEngine::RemoveRefByPtr(pTex, REF_OTHER);
}
if(bRecreate)
{
this->m_DirtTexEffect = tmpTabDirtTex;
}
return(TRUE);
}// end of CCustomShaderEffectVehicleType::Recreate()...
//
// restores drawable's shaderVars values to their original (initial) state:
// - to be executed right before MasterCSE for modelInfo is destroyed;
// - note: uses RecordSetVar() API (directly modifies InstanceData memory without drawablespu, etc.);
// - that way if drawable is NOT reloaded from disk by streaming and directly reused for MasterCSE creation
// it makes it possible to correctly initialise/create given MasterCSE
// (which may rely on shaderVar values - e.g. CSEVehicle);
//
bool CCustomShaderEffectVehicleType::RestoreModelInfoDrawable(rmcDrawable *pDrawable)
{
Assert(pDrawable);
Assert(CSystem::IsThisThreadId(SYS_THREAD_UPDATE)); // allowed on Update Thread only
if(!pDrawable)
return(false);
grmShaderGroup* pShaderGroup = &pDrawable->GetShaderGroup();
Assert(pShaderGroup);
const u32 shaderCount = pShaderGroup->GetCount();
// restore "DiffuseColor":
const u32 count = m_DiffColEffect.GetCount();
if(count)
{
Vector3 defaultDiffuseCol[7] =
{
BODYCOLOR1, // 0
BODYCOLOR2, // 1
BODYCOLOR3, // 2
BODYCOLOR4, // 3
BODYCOLOR5, // 4
BODYCOLOR6, // 5
BODYCOLOR7 // 6
};
for(u32 i=0; i<count; i++)
{
CCustomShaderEffectVehicleType::structDiffColEffect *ptr = &m_DiffColEffect[i];
pShaderGroup->GetShader(ptr->shaderIdx).RecordSetVar((grcEffectVar)ptr->idvarDiffColor, defaultDiffuseCol[ptr->colorIdx]);
#if VEHICLE_SUPPORT_PAINT_RAMP
if(ptr->idvarDiffuseRampTexture)
{
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarDiffuseRampTexture, const_cast<grcTexture*>(grcTexture::NoneBlack));
}
if(ptr->idvarSpecularRampTexture)
{
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecularRampTexture, const_cast<grcTexture*>(grcTexture::NoneBlack));
}
if(ptr->idvarDiffuseSpecularRampEnabled)
{
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarDiffuseSpecularRampEnabled, VEHICLE_PAINT_RAMP_DISABLED_VALUE);
}
#endif
}
}
// restore original "SpecularColor":
const s32 specCount = m_SpecColEffect.GetCount();
for(u32 i=0; i<specCount; i++)
{
CCustomShaderEffectVehicleType::structSpecColEffect *ptr = &m_SpecColEffect[i];
if(ptr->idvarSpecInt)
pShaderGroup->GetShader(ptr->shaderIdx).RecordSetVar((grcEffectVar)ptr->idvarSpecInt, float(ptr->origSpecInt));
if(ptr->idvarSpecFalloff)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecFalloff, float(ptr->origSpecFalloff));
if(ptr->idvarSpecFresnel)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecFresnel, float(ptr->origSpecFresnel));
}
// restore original DirtTexture:
const u32 dirtTexCount = m_DirtTexEffect.GetCount();
for(u32 i=0; i<dirtTexCount; i++)
{
CCustomShaderEffectVehicleType::structDirtTexEffect *ptr = &m_DirtTexEffect[i];
#if __PPU
// Hack: manually clear FLAG_SET_FROM_SPU to shut up assert in RecordSetVar():
grcInstanceData& data = pShaderGroup->GetShader(ptr->shaderIdx).GetInstanceData();
data.Flags &= ~grcInstanceData::FLAG_SET_FROM_SPU;
#endif
pShaderGroup->GetShader(ptr->shaderIdx).RecordSetVar((grcEffectVar)ptr->idvarDirtTex, (grcTexture*)ptr->pOrigDirtTex);
}
for(u32 i=0; i<shaderCount; i++)
{
grmShader *pShader = pShaderGroup->GetShaderPtr(i);
Assert(pShader);
// restore DirtColor:
grcEffectVar idvarDirtCol = pShader->LookupVar("DirtColor", FALSE);
if(idvarDirtCol)
{
Vector3 origDirtCol(VEC3V_TO_VECTOR3(m_DefDirtColor.GetRGB()));
pShader->RecordSetVar(idvarDirtCol, origDirtCol);
}
// restore Emissive Multiplier:
if(m_idVarEmissiveMult)
{
grcEffectVar idvarEmissiveMult = pShader->LookupVar("EmissiveMultiplier", FALSE);
if(idvarEmissiveMult)
{
pShader->RecordSetVar(idvarEmissiveMult, m_DefEmissiveMult);
}
}
}
// restore overlay texture:
const u32 tex2Count = m_Tex2Effect.GetCount();
for(u32 i=0; i<tex2Count; i++)
{
CCustomShaderEffectVehicleType::structTex2Effect *ptr = &m_Tex2Effect[i];
#if __PPU
// Hack: manually clear FLAG_SET_FROM_SPU to shut up assert in RecordSetVar():
grcInstanceData& data = pShaderGroup->GetShader(ptr->shaderIdx).GetInstanceData();
data.Flags &= ~grcInstanceData::FLAG_SET_FROM_SPU;
#endif
pShaderGroup->GetShader(ptr->shaderIdx).RecordSetVar((grcEffectVar)ptr->idvarTex2, (grcTexture*)ptr->pOrigTex2);
}
return(true);
}// end of CCustomShaderEffectVehicle::RestoreDrawable()...
//
//
//
//
CCustomShaderEffectVehicleType::~CCustomShaderEffectVehicleType()
{
Assert(CSystem::IsThisThreadId(SYS_THREAD_UPDATE)); // truck burnout tex referencing allowed only on update thread
if(this->m_bHasTruckTex)
{
Assert(ms_pBurnoutTruckTexture); // must be valid
ms_nBurnoutTruckTextureRef--;
Assert(ms_nBurnoutTruckTextureRef>=0);
if(ms_nBurnoutTruckTextureRef==0)
{
ms_pBurnoutTruckTexture = NULL;
}
}
const u32 dirtTexCount = m_DirtTexEffect.GetCount();
for(u32 i=0; i<dirtTexCount; i++)
{
grcTexture *const pTex = this->m_DirtTexEffect[i].pOrigDirtTex;
this->m_DirtTexEffect[i].pOrigDirtTex = NULL;
strStreamingEngine::RemoveRefByPtr(pTex, REF_OTHER);
}
const u32 tex2Count = m_Tex2Effect.GetCount();
for(u32 i=0; i<tex2Count; i++)
{
grcTexture *const pTex2 = this->m_Tex2Effect[i].pOrigTex2;
this->m_Tex2Effect[i].pOrigTex2 = NULL;
strStreamingEngine::RemoveRefByPtr(pTex2, REF_OTHER);
}
}
//
//
//
//
inline u8 VehShaderGroupLookupVar(grmShaderGroup *pShaderGroup, const char *name, bool mustExist)
{
grmShaderGroupVar varID = pShaderGroup->LookupVar(name, mustExist);
Assert((int)varID < 256); // must fit into u8
return (u8)varID;
}
inline u8 VehEffectLookupGlobalVar(const char *name, bool mustExist)
{
grcEffectGlobalVar varID = grcEffect::LookupGlobalVar(name, mustExist);
Assert((int)varID < 256); // must fit into u8
return (u8)varID;
}
//
//
// initializes all instances of the effect class;
// to be called once, when "master" class is created;
//
bool CCustomShaderEffectVehicleType::Initialise(rmcDrawable *pDrawable)
{
return Initialise(pDrawable, NULL);
}
bool CCustomShaderEffectVehicleType::Initialise(rmcDrawable *pDrawable, grmShaderGroup *pClonedShaderGroup)
{
Assert(pDrawable);
// BS#2551385: vehicle mods: use cloned shaderGroup (if exists) rather than drawable's original shaderGroup:
grmShaderGroup* pShaderGroup= pClonedShaderGroup? pClonedShaderGroup : &pDrawable->GetShaderGroup();
Assert(pShaderGroup);
m_idVarDirtLevelMod = VehShaderGroupLookupVar(pShaderGroup, "DirtLevelMod", FALSE);
m_idVarDirtColor = VehShaderGroupLookupVar(pShaderGroup, "DirtColor", FALSE);
m_idVarSpec2Color = VehShaderGroupLookupVar(pShaderGroup, "Specular2Color", FALSE);
m_idVarDiffuse2Color = VehShaderGroupLookupVar(pShaderGroup, "DiffuseColor2", FALSE);
m_idVarDiffuseColorTint = VehShaderGroupLookupVar(pShaderGroup, "DiffuseColorTint", FALSE);
#if USE_DISKBRAKEGLOW
m_idVarDiskBrakeGlow = VehShaderGroupLookupVar(pShaderGroup, "DiskBrakeGlow",FALSE);
#endif
// headlights
m_idVarDimmer = VehShaderGroupLookupVar(pShaderGroup, "dimmerSetPacked", FALSE);
// tyre deformation on/off control:
m_idVarTyreDeformSwitchOn = VehEffectLookupGlobalVar("tyreDeformSwitchOn", TRUE);
// vehicle deformation
#if USE_GPU_VEHICLEDEFORMATION
m_idVarDamageSwitchOn = VehEffectLookupGlobalVar("switchOn", TRUE);
m_idVarDamageTex = VehShaderGroupLookupVar(pShaderGroup, "damagetexture", false);
m_idVarBoundRadius = VehShaderGroupLookupVar(pShaderGroup, "BoundRadius", false);
m_idVarDamageMult = VehShaderGroupLookupVar(pShaderGroup, "DamageMultiplier", false);
m_idVarOffset = VehShaderGroupLookupVar(pShaderGroup, "DamageTextureOffset", false);
m_idVarDamagedFrontWheelOffsets = VehShaderGroupLookupVar(pShaderGroup, "DamagedWheelOffsets", false);
#if __BANK
m_idVarDebugDamageMap = VehShaderGroupLookupVar(pShaderGroup, "bDebugDisplayDamageMap", false);
m_idVarDebugDamageMult = VehShaderGroupLookupVar(pShaderGroup, "bDebugDisplayDamageScale", false);
#endif
#endif
m_idVarDiffuseTex2 = VehShaderGroupLookupVar(pShaderGroup, "DiffuseTex2", false);
m_idVarDiffuseTex3 = VehShaderGroupLookupVar(pShaderGroup, "DiffuseTex3", false);
m_idVarTrackAnimUV = VehShaderGroupLookupVar(pShaderGroup, "TrackAnimUV0", FALSE);
m_idVarTrack2AnimUV = VehShaderGroupLookupVar(pShaderGroup, "Track2AnimUV0", FALSE);
m_idVarTrackAmmoAnimUV = VehShaderGroupLookupVar(pShaderGroup, "TrackAmmoAnimUV0", FALSE);
m_idVarEnvEffScale = VehShaderGroupLookupVar(pShaderGroup, "envEffScale0", FALSE);
m_idVarEmissiveMult = VehShaderGroupLookupVar(pShaderGroup, "EmissiveMultiplier", false);
// Just spew how much space it *would* take...
// pShaderGroup->Clone(NULL);
// Displayf("...and the rest of the object is %u bytes",Size());
m_idLicensePlateBgTex = VehShaderGroupLookupVar(pShaderGroup, "PlateBgTex", false);
m_idLicensePlateBgNormTex = VehShaderGroupLookupVar(pShaderGroup, "PlateBgBumpTex", false);
m_idLicensePlateFontColor = VehShaderGroupLookupVar(pShaderGroup, "LicensePlateFontTint", false);
m_idLicensePlateText1 = VehShaderGroupLookupVar(pShaderGroup, "LetterIndex1", false);
m_idLicensePlateText2 = VehShaderGroupLookupVar(pShaderGroup, "LetterIndex2", false);
m_idLicensePlateFontOutlineColor = VehShaderGroupLookupVar(pShaderGroup, "FontOutlineColor", false);
m_idLicensePlateFontExtents = VehShaderGroupLookupVar(pShaderGroup, "LicensePlateFontExtents", false);
m_idLicensePlateFontOutlineMinMaxDepth_Enabled = VehShaderGroupLookupVar(pShaderGroup, "FontOutlineMinMaxDepthEnabled", false);
m_idLicensePlateMaxLettersOnPlate = VehShaderGroupLookupVar(pShaderGroup, "LicensePlateMaxLetters", false);
#if USE_DISKBRAKEGLOW
m_varDiskBrakeGlow = 0.0f;
#endif // USE_DISKBRAKEGLOW
m_bIsHighDetail = false;
return(TRUE);
}// end of Initialise()...
//
//
//
//
CCustomShaderEffectBase* CCustomShaderEffectVehicleType::CreateInstance(CEntity* pEntity)
{
CCustomShaderEffectVehicle *pNewShaderEffect = rage_new CCustomShaderEffectVehicle();
CVehicleModelInfo *pVMI = (CVehicleModelInfo*)(pEntity->GetBaseModelInfo());
Assert(pVMI);
for (int i=0; i<NUMBER_OF_RENDER_THREADS; i++)
{
pNewShaderEffect->m_pType[i] = this;
}
pNewShaderEffect->m_vDamagedFrontWheelOffsets[0] = Vector4(0.0f, 0.0f, 0.0f, 0.0f);
pNewShaderEffect->m_vDamagedFrontWheelOffsets[1] = Vector4(0.0f, 0.0f, 0.0f, 0.0f);
pNewShaderEffect->SetDirtLevel(0.0f);
pNewShaderEffect->SetDirtColor(this->GetDefaultDirtColor());
pNewShaderEffect->SetBurnoutLevel(0.0f);
for(s32 i=0; i<7; i++)
{
pNewShaderEffect->m_varDifCol[i] = Color32(0,0,0);
pNewShaderEffect->m_varMetallicID[i] = (u8)CVehicleModelColor::EVehicleModelColorMetallic_none;
}
pNewShaderEffect->SetSpec2Color(0,0,0);
pNewShaderEffect->SetSpec2DirLerp(0.0f);
pNewShaderEffect->SetDiffuseTint(pVMI->GetDiffuseTint());
pNewShaderEffect->m_bRenderScorched = FALSE;
pNewShaderEffect->m_pLiveryTexture = NULL;
pNewShaderEffect->m_liveryFragSlotIdx = strLocalIndex::INVALID_INDEX;
pNewShaderEffect->UpdateVehicleColors(pEntity);
pNewShaderEffect->m_bTyreDeformSwitchOn = false;
pNewShaderEffect->m_bBurstWheel = false;
pNewShaderEffect->m_bDamageSwitchOn = false;
pNewShaderEffect->m_pDamageTexture = NULL;
#if VEHICLE_SUPPORT_PAINT_RAMP
for(u32 i = 0; i < NELEM(pNewShaderEffect->m_pRampTextures); ++i)
{
pNewShaderEffect->m_pRampTextures[i] = 0;
}
#endif
pNewShaderEffect->m_bCustomPrimaryColor = false;
pNewShaderEffect->m_bCustomSecondaryColor = false;
pNewShaderEffect->m_bIsBrokenOffPart = false;
pNewShaderEffect->m_bHasLiveryMod = false;
pNewShaderEffect->m_uvTrackAnim = Vector2(0.0f,0.0f);
pNewShaderEffect->m_uvTrack2Anim = Vector2(0.0f,0.0f);
pNewShaderEffect->m_uvTrackAmmoAnim = Vector2(0.0f,0.0f);
pNewShaderEffect->m_fUserEmissiveMultiplier = 1.0f;
for(u32 i=0; i<(4*CVehicleLightSwitch::LW_LIGHTVECTORS+1); i++)
{
pNewShaderEffect->m_fLightDimmer[i] = 1.0f;
}
float envEff1=0.0f;
const float envEffScaleMin = pVMI->GetEnvEffScaleMin();
const float envEffScaleMax = pVMI->GetEnvEffScaleMax();
if(envEffScaleMin < envEffScaleMax)
envEff1 = g_DrawRand.GetRanged(envEffScaleMin, envEffScaleMax);
else
envEff1 = envEffScaleMin; // do not rand() if min==max
float envEff2=0.0f;
const float envEffScaleMin2 = pVMI->GetEnvEffScaleMin2();
const float envEffScaleMax2 = pVMI->GetEnvEffScaleMax2();
if(envEffScaleMin2 < envEffScaleMax2)
envEff2 = g_DrawRand.GetRanged(envEffScaleMin2, envEffScaleMax2);
else
envEff2 = envEffScaleMin2; // do not rand() if min==max
pNewShaderEffect->SetEnvEffScale(g_DrawRand.GetBool()? envEff1 : envEff2); // equally select from 1st or 2nd range
pNewShaderEffect->m_pLicensePlateDiffuseTex = NULL;
pNewShaderEffect->m_pLicensePlateNormalTex = NULL;
int seed = 1;
if(pEntity->GetIsTypeVehicle())
seed = static_cast<CVehicle*>(pEntity)->GetRandomSeed();
pNewShaderEffect->GenerateLicensePlateText(seed);
pNewShaderEffect->AddKnownRefs();
//The license plate textures to use should be driven later by script. (Same as the livery stuff) However, since this functionality is
//new, this is not currently set up. So I have added the code block below to set the license plate textures to the default textures. (If
//a default is defined.) This way, the license plates will draw correctly in the mean time, and as a proof of concept, any instance of a
//vehicle can be spawned with a different license plate texture just by changing the default texture index in Rag and spawning a new instance.
//
//Once this is hooked up through code, it may make sense to remove this functionality completely. However, if a we do that and script misses a
//call to set the plate background texture, the resulting visual may or may not look very strange and completely incorrect depending on what is
//drawn before it. So perhaps to identify this easily, in all __BANK or !__FINAL builds we could have some default error texture to make any
//problems very obvious. If we go with this method, this code block should probably be moved to the Initialise() function.
//
//IMPORTANT Note: This code *must* come after the AddKnownRefs() call, or the game may assert and become unstable. -AJG
pNewShaderEffect->SelectLicensePlateByProbability(pEntity);
InitialiseClothDrawable(pEntity);
pNewShaderEffect->SetDamageTex(const_cast<grcTexture*>(grcTexture::NoneBlack));
return(pNewShaderEffect);
}
//
//
// initializes vehicle cloth drawable:
//
rmcDrawable* CCustomShaderEffectVehicleType::InitialiseClothDrawable(CEntity *pEntity) const
{
// initialize vehicle cloth drawable instance (only for SD vehicle):
fragInst* pFragInst = pEntity->GetFragInst();
if(pFragInst && pEntity->m_nFlags.bIsFrag && (!this->GetIsHighDetail()))
{
// Search for a cloth drawable
rmcDrawable *pClothDrawable = NULL;
fragCacheEntry *cacheEntry = pFragInst->GetCacheEntry();
if(cacheEntry)
{
fragHierarchyInst* hierInst = cacheEntry->GetHierInst();
Assertf( hierInst,"No HierInst on a cached frag" );
environmentCloth* pEnvCloth = hierInst->envCloth;
if( pEnvCloth )
{
pClothDrawable = pEnvCloth->GetDrawable();
}
}
if(pClothDrawable)
{
grmShaderGroup *pClothShaderGroup = &pClothDrawable->GetShaderGroup();
if(pClothShaderGroup->GetShaderGroupVarCount()==0)
{
CCustomShaderEffectVehicleType *pClothCseType = CCustomShaderEffectVehicleType::Create(pClothDrawable, NULL, NULL);
if(!pClothCseType->Initialise(pClothDrawable))
{
Assertf(FALSE, "Error initialising CustomShaderEffect!");
}
// check if clothCSE matches SD vehicleCSE:
#if __ASSERT
#define ASSERT_COMPARE_VAR0(VAR) Assertf(this->VAR == pClothCseType->VAR, "Value of "#VAR" doesn't match for vehicle SD CSE and vehicle cloth !");
#define ASSERT_COMPARE_VAR(VAR) Assertf(this->VAR == pClothCseType->VAR, "Value of "#VAR" doesn't match for vehicle's SD CSE (=%d) and vehicle's cloth CSE (=%d)!",this->VAR,pClothCseType->VAR);
ASSERT_COMPARE_VAR0(m_DefDirtColor);
ASSERT_COMPARE_VAR(m_idVarDiffuse2Color);
ASSERT_COMPARE_VAR(m_idVarDirtLevelMod);
ASSERT_COMPARE_VAR(m_idVarDirtColor);
ASSERT_COMPARE_VAR(m_idVarDiffuseColorTint);
ASSERT_COMPARE_VAR(m_idVarDiffuseTex2);
ASSERT_COMPARE_VAR(m_idVarDiffuseTex3);
ASSERT_COMPARE_VAR(m_idVarTyreDeformSwitchOn);
ASSERT_COMPARE_VAR(m_idVarTrackAnimUV);
ASSERT_COMPARE_VAR(m_idVarTrack2AnimUV);
ASSERT_COMPARE_VAR(m_idVarTrackAmmoAnimUV);
ASSERT_COMPARE_VAR(m_idVarEnvEffScale);
ASSERT_COMPARE_VAR(m_idLicensePlateBgTex);
ASSERT_COMPARE_VAR(m_idLicensePlateBgNormTex);
ASSERT_COMPARE_VAR(m_idLicensePlateFontColor);
ASSERT_COMPARE_VAR(m_idLicensePlateText1);
ASSERT_COMPARE_VAR(m_idLicensePlateText2);
ASSERT_COMPARE_VAR(m_idLicensePlateFontOutlineColor);
ASSERT_COMPARE_VAR(m_idLicensePlateFontExtents);
ASSERT_COMPARE_VAR(m_idLicensePlateFontOutlineMinMaxDepth_Enabled);
ASSERT_COMPARE_VAR(m_idLicensePlateMaxLettersOnPlate);
ASSERT_COMPARE_VAR(m_idVarDimmer);
#if USE_GPU_VEHICLEDEFORMATION
ASSERT_COMPARE_VAR(m_idVarDamageSwitchOn);
ASSERT_COMPARE_VAR(m_idVarBoundRadius);
ASSERT_COMPARE_VAR(m_idVarDamageMult);
ASSERT_COMPARE_VAR(m_idVarDamageTex);
#endif
#if USE_DISKBRAKEGLOW
ASSERT_COMPARE_VAR(m_idVarDiskBrakeGlow);
#endif
ASSERT_COMPARE_VAR(m_bHasTruckTex);
ASSERT_COMPARE_VAR(m_bIsHighDetail);
ASSERT_COMPARE_VAR(m_bHasBodyColor1);
ASSERT_COMPARE_VAR(m_bHasBodyColor2);
ASSERT_COMPARE_VAR(m_bHasBodyColor3);
ASSERT_COMPARE_VAR(m_bHasBodyColor4);
ASSERT_COMPARE_VAR(m_bHasBodyColor5);
ASSERT_COMPARE_VAR(m_bHasBodyColor6);
ASSERT_COMPARE_VAR(m_bHasBodyColor7);
ASSERT_COMPARE_VAR(m_DiffColEffect.GetCount());
ASSERT_COMPARE_VAR(m_SpecColEffect.GetCount());
ASSERT_COMPARE_VAR(m_DirtTexEffect.GetCount());
ASSERT_COMPARE_VAR(m_Tex2Effect.GetCount());
#undef ASSERT_COMPARE_VAR0
#undef ASSERT_COMPARE_VAR
#endif //__ASSERT...
delete pClothCseType;
pClothCseType = NULL;
return(pClothDrawable);
}
}
}// vehicle cloth drawable instance...
return(NULL);
}
//
//
//
//
grcTexture* CCustomShaderEffectVehicleType::GetDirtTexture(u32 shaderIdx) const
{
const u32 dirtTexCount = m_DirtTexEffect.GetCount();
for(u32 i=0; i<dirtTexCount; i++)
{
const CCustomShaderEffectVehicleType::structDirtTexEffect *ptr = &m_DirtTexEffect[i];
if(ptr->shaderIdx == shaderIdx)
{
return (grcTexture*)ptr->pOrigDirtTex;
}
}
return(NULL);
}
//
//
//
//
CCustomShaderEffectVehicle::CCustomShaderEffectVehicle() : CCustomShaderEffectBase(sizeof(*this), CSE_VEHICLE)
{
m_nLicensePlateTexIdx =
m_nLiveryIdx =
m_nLivery2Idx = -1;
m_pLicensePlateDiffuseTex = NULL;
m_pLicensePlateNormalTex = NULL;
m_bCustomPrimaryColor = false;
m_bCustomSecondaryColor = false; //ensure this is properly initialized
memset(m_LicensePlateText,0,sizeof(m_LicensePlateText));
}
//
//
//
//
CCustomShaderEffectVehicle::~CCustomShaderEffectVehicle()
{
RemoveKnownRefs();
// m_pType is cleaned up in ShutdownMaster
}
//
//
//
//
void CCustomShaderEffectVehicle::CopySettings(CCustomShaderEffectVehicle *src, CEntity* /*pEntity*/)
{
sysMemCpy(m_fLightDimmer, src->m_fLightDimmer, sizeof(m_fLightDimmer));
this->m_fBoundRadius = src->m_fBoundRadius;
this->m_fDamageMultiplier = src->m_fDamageMultiplier;
sysMemCpy(this->m_vDamagedFrontWheelOffsets, src->m_vDamagedFrontWheelOffsets, sizeof(src->m_vDamagedFrontWheelOffsets));
sysMemCpy(this->m_varDifCol, src->m_varDifCol, sizeof(src->m_varDifCol));
this->m_varSpec2Color_DirLerp = src->m_varSpec2Color_DirLerp;
this->m_varDiffColorTint = src->m_varDiffColorTint;
this->m_varDirtColor_DirtLevel = src->m_varDirtColor_DirtLevel;
sysMemCpy(this->m_varMetallicID, src->m_varMetallicID, sizeof(src->m_varMetallicID));
this->m_pDamageTexture = src->m_pDamageTexture;
#if VEHICLE_SUPPORT_PAINT_RAMP
for(u32 i = 0; i < NELEM(this->m_pRampTextures); ++i)
{
this->m_pRampTextures[i] = src->m_pRampTextures[i];
}
#endif
// grcTextureIndex m_pLiveryTexture;
this->m_liveryFragSlotIdx = src->m_liveryFragSlotIdx;
this->m_nLiveryIdx = src->m_nLiveryIdx;
this->m_nLivery2Idx = src->m_nLivery2Idx;
this->m_bCustomPrimaryColor = src->m_bCustomPrimaryColor;
this->m_bCustomSecondaryColor = src->m_bCustomSecondaryColor;
this->m_bIsBrokenOffPart = src->m_bIsBrokenOffPart;
this->m_bHasLiveryMod = src->m_bHasLiveryMod;
this->m_uvTrackAnim = src->m_uvTrackAnim;
this->m_uvTrack2Anim = src->m_uvTrack2Anim;
this->m_uvTrackAmmoAnim = src->m_uvTrackAmmoAnim;
this->m_fUserEmissiveMultiplier = src->m_fUserEmissiveMultiplier;
SetLicensePlateTexIndex(src->m_nLicensePlateTexIdx);
// grcTextureIndex m_pLicensePlateDiffuseTex;
// grcTextureIndex m_pLicensePlateNormalTex;
sysMemCpy(this->m_LicensePlateText, src->m_LicensePlateText, sizeof(src->m_LicensePlateText));
sysMemCpy(this->m_wheelBurstSideRatios, src->m_wheelBurstSideRatios, sizeof(src->m_wheelBurstSideRatios));
#if USE_DISKBRAKEGLOW
m_varDiskBrakeGlow = src->m_varDiskBrakeGlow;
#endif
this->m_varEnvEffScale = src->m_varEnvEffScale;
this->m_varBurnoutLevel = src->m_varBurnoutLevel;
this->m_bRenderScorched = src->m_bRenderScorched;
this->m_bTyreDeformSwitchOn = src->m_bTyreDeformSwitchOn;
this->m_bBurstWheel = src->m_bBurstWheel;
this->m_bDamageSwitchOn = src->m_bDamageSwitchOn;
}
//
//
//
//
void CCustomShaderEffectVehicle::Update(fwEntity* pEntityBase)
{
CEntity* pEntity = static_cast<CEntity*>(pEntityBase);
Assert(pEntity);
if(pEntity->GetIsTypeVehicle())
{
CVehicle *pVehicle = static_cast<CVehicle*>(pEntity);
// dirt test:
// const float time = float(fwTimer::GetTimeInMilliseconds()) * 0.001f;
// this->SetDirtLevel(rage::Sinf(time)*0.5f + 0.5f);
this->SetDirtLevel(pVehicle->GetBodyDirtLevel() / 15.0f);
this->SetDirtColor(pVehicle->GetBodyDirtColor());
this->m_bHasLiveryMod = pVehicle->GetVariationInstance().GetNumModsForType(VMT_LIVERY_MOD, pVehicle) > 0;
#if !__FINAL
if(gbDontDisplayDirtOnVehicles || PARAM_novehicledirt.Get())
this->SetDirtLevel(0.0f);
#endif //__DEV...
if(pVehicle->m_nPhysicalFlags.bRenderScorched) // vehicle burntout/exploded?
{
this->m_bRenderScorched = TRUE;
float fBurnoutLevelInc =
#if CSE_VEHICLE_EDITABLEVALUES
ms_fEVBurnoutSpeed;
#else
0.01f;
#endif
#if GTA_REPLAY
if(CReplayMgr::IsReplayInControlOfWorld())
{
ReplayVehicleExtension* pExt = ReplayVehicleExtension::GetExtension(pVehicle);
if(pExt && pExt->GetIncScorch() == false)
{
fBurnoutLevelInc = 0.0f; // Don't increment scorch...replay is in control
}
}
#endif // GTA_REPLAY
this->SetBurnoutLevel(GetBurnoutLevel()+fBurnoutLevelInc);
this->SetDirtLevel(1.0f);
this->UpdateVehicleColors(pVehicle);
}
else
{
this->m_bRenderScorched = FALSE;
this->SetBurnoutLevel(0.0f);
}
Color32 newWindowTint = GetDiffuseTint();
if (pVehicle->GetVariationInstance().GetKitIndex() != INVALID_VEHICLE_KIT_INDEX && pVehicle->GetVariationInstance().GetWindowTint() != 0xff)
{
newWindowTint = CVehicleModelInfo::GetVehicleColours()->GetVehicleWindowColor(pVehicle->GetVariationInstance().GetWindowTint());
}
SetDiffuseTint(newWindowTint);
const tcKeyframeUncompressed& currKeyframe = g_timeCycle.GetCurrUpdateKeyframe();
this->SetSpec2DirLerp(currKeyframe.GetVar(TCVAR_LIGHT_VEHICLE_SECOND_SPEC_OVERRIDE));
#if USE_DISKBRAKEGLOW
if( GetCseType()->m_idVarDiskBrakeGlow )
{
// That's our current temperature
float wheelTemperature = m_varDiskBrakeGlow;
// Update glow level if needed
if( pVehicle->GetHasGlowingBrakes() )
{
const float engineOn = (float)(fwTimer::GetTimeInMilliseconds() - pVehicle->m_EngineSwitchedOnTime);
// Gather linear speed and brake force from the wheels
const int numWheels = pVehicle->GetNumWheels();
#if DISKBRAKEGLOW_DEBUG_TEXT_FULLWHEELDETAIL
float wheelBrakes[20];
float wheelSpeed[20];
float wheelAngleVel[20];
float wheelSlipRatio[20];
#endif // DISKBRAKEGLOW_DEBUG_TEXT
float accumWheelSpeed = 0.0f;
float accumBrakeForce = 0.0f;
for(int i=0;i<numWheels;i++)
{
const CWheel *wheel = pVehicle->GetWheel(i);
if( wheel )
{
accumWheelSpeed += wheel->GetGroundSpeed();
accumBrakeForce += wheel->GetBrakeForce();
#if DISKBRAKEGLOW_DEBUG_TEXT_FULLWHEELDETAIL
wheelBrakes[i] = wheel->GetBrakeForce();
wheelSpeed[i] = wheel->GetGroundSpeed();
wheelAngleVel[i] = wheel->GetRotSpeed();
wheelSlipRatio[i] = wheel->GetRotSlipRatio();
#endif // DISKBRAKEGLOW_DEBUG_TEXT_FULLWHEELDETAIL
}
}
const float fnumWheels = (float)numWheels;
accumBrakeForce /= fnumWheels;
accumWheelSpeed /= fnumWheels;
#if DISKBRAKEGLOW_DEBUG_TEXT
{
char msg[1024];
static int StartX = 100;
static int StartY = 10;
int y = StartY;
sprintf(msg,"breakped %f",pVehicle->GetBrake());
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
sprintf(msg,"HandBreak %d",pVehicle->GetHandBrake());
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
sprintf(msg,"BrakeForce %f",accumBrakeForce);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
sprintf(msg,"WheelSpeed %f",accumWheelSpeed);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
sprintf(msg,"SpeedCap %f",g_fDiskBrake_SpeedCap);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
sprintf(msg,"MagicNumber %f",g_fDiskBrake_TempMagicNumber);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
sprintf(msg,"EngineOn %f",engineOn);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
const float EngineAge = rage::Clamp((engineOn - g_fDiskBrake_EngineAge) * (1.0f / g_fDiskBrake_EngineAge),0.0f,1.0f);
sprintf(msg,"EngineAge %f",EngineAge);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
#if DISKBRAKEGLOW_V2
const float nWheelSpeed = rage::Max(0.0f,(accumWheelSpeed - g_fDiskBrake_SpeedCap) * (1.0f / g_fDiskBrake_SpeedCap));
const float sWheelSpeed = rage::square(nWheelSpeed);
const float nHeatingRate = g_fDiskBrake_MaxHeatingRate * nWheelSpeed;
const float sHeatingRate = g_fDiskBrake_MaxHeatingRate * sWheelSpeed;
const float heatingRate = rage::Lerp(accumBrakeForce,nHeatingRate,sHeatingRate);
#else // DISKBRAKEGLOW_V2
const float heatingRate = (accumWheelSpeed / g_fDiskBrake_TempMagicNumber) * accumBrakeForce;
#endif // DISKBRAKEGLOW_V2
sprintf(msg,"heatingRate %f",heatingRate);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
sprintf(msg,"WheelTemp %f",wheelTemperature);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
static float maxwheelTemperature = 0.0f;
static float minwheelTemperature = FLT_MAX;
if( wheelTemperature > maxwheelTemperature )
{
maxwheelTemperature = wheelTemperature;
}
if( wheelTemperature < minwheelTemperature )
{
minwheelTemperature = wheelTemperature;
}
sprintf(msg,"minwheelTemperature %f",minwheelTemperature);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
sprintf(msg,"maxwheelTemperature %f",maxwheelTemperature);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
#if DISKBRAKEGLOW_DEBUG_TEXT_FULLWHEELDETAIL
for(int i=0;i<numWheels;i++)
{
const CWheel *wheel = pVehicle->GetWheel(i);
if( wheel )
{
sprintf(msg,"Wheel Speed %d:%f",i,wheelSpeed[i]);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
sprintf(msg,"Wheel Break %d:%f",i,wheelBrakes[i]);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
sprintf(msg,"wheelAngleVel %d:%f",i,wheelAngleVel[i]);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
sprintf(msg,"wheelSlipRatio %d:%f",i,wheelSlipRatio[i]);
grcDebugDraw::PrintToScreenCoors(msg,StartX,y);
y++;
}
}
#endif // DISKBRAKEGLOW_DEBUG_TEXT_FULLWHEELDETAIL
}
#endif // DISKBRAKEGLOW_DEBUG_TEXT
// Scale the disk "temperature" (actually 0 to 1) based on the vehicle's behaviour
const float timestep = fwTimer::GetTimeStep();
if( (pVehicle->GetBrake() > 0.05f) &&
(false == pVehicle->GetHandBrake()) &&
(accumBrakeForce > 0.0f) &&
(accumWheelSpeed > g_fDiskBrake_SpeedCap) )
{
#if DISKBRAKEGLOW_V2
const float nWheelSpeed = rage::Max(0.0f,(accumWheelSpeed - g_fDiskBrake_SpeedCap) * (1.0f / g_fDiskBrake_SpeedCap));
const float sWheelSpeed = rage::square(nWheelSpeed);
const float nHeatingRate = g_fDiskBrake_MaxHeatingRate * nWheelSpeed;
const float sHeatingRate = g_fDiskBrake_MaxHeatingRate * sWheelSpeed;
const float heatingRate = rage::Lerp(accumBrakeForce,nHeatingRate,sHeatingRate);
#else // DISKBRAKEGLOW_V2
const float heatingRate = (accumWheelSpeed / g_fDiskBrake_TempMagicNumber) * accumBrakeForce;
#endif // DISKBRAKEGLOW_V2
const float EngineAge = rage::Clamp((engineOn - g_fDiskBrake_EngineAge) * (1.0f / g_fDiskBrake_EngineAge),0.0f,1.0f);
wheelTemperature = rage::Min(0.5f,wheelTemperature + (timestep * heatingRate * EngineAge));
}
else
{
wheelTemperature = rage::Max(0.0f,wheelTemperature - (timestep * g_fDiskBrake_CoolingRate));
}
}
else
{
wheelTemperature = 0.0f;
}
#if DISKBRAKEGLOW_DEBUG_SHADER
static float frequency = 1500.0f;
static float maxLum = 1.0f;
wheelTemperature = rage::Abs((rage::Sinf(((float)fwTimer::GetTimeInMilliseconds()/frequency)*PI) * maxLum));
#endif // DISKBRAKEGLOW_DEBUG_SHADER
m_varDiskBrakeGlow = wheelTemperature;
}
#endif // USE_DISKBRAKEGLOW
// debug test tank track anim:
#if 0
static dev_bool gbDbgTrackAnim = TRUE;
static dev_float gbDbgTrackAnimAddRight = -0.01f;
static dev_float gbDbgTrackAnimAddLeft = 0.01f;
if(gbDbgTrackAnim)
{
if(m_idVarTrackAnimUV)
{
Vector2 a;
a.x = gbDbgTrackAnimAddRight;
a.y = gbDbgTrackAnimAddLeft;
this->TrackUVAnimAdd( a );
}
}
#endif //#if 0...
// calculate sun glare factor:
#if CSE_VEHICLE_EDITABLEVALUES
if(ms_bEVSunGlareEnabled)
#else
if(0)
#endif
{
float glare_s = 1.0f;
const Vector3& cameraPos = camInterface::GetPos();
const Vector3& cameraFront = camInterface::GetFront();
const Vector3 vehiclePos = VEC3V_TO_VECTOR3(pEntity->GetTransform().GetPosition());
// distance factor:
#if CSE_VEHICLE_EDITABLEVALUES
const float glareMinDist = ms_fEVSunGlareDistMin;
const float glareMaxDist = ms_fEVSunGlareDistMax;
#else
const float glareMinDist = 65.0f;
const float glareMaxDist = 75.0f;
#endif
const Vector3 distV(cameraPos - vehiclePos);
const float dist2 = distV.Mag2();
glare_s *= 1.0f - rage::Clamp((glareMaxDist*glareMaxDist-dist2)/(glareMaxDist*glareMaxDist-glareMinDist*glareMinDist), 0.0f, 1.0f);
const CLightSource &dirLight = Lights::GetRenderDirectionalLight();
// "only during day" factor:
glare_s *= rage::Clamp(dirLight.GetIntensity()-2.0f, 0.0f, 1.0f);
// view/sun angle factor:
Vector3 surface_worldNormal(cameraPos - vehiclePos); // fake "normal"
surface_worldNormal.Normalize();
Vector3 surfaceToEyeDirection(-cameraFront);
surfaceToEyeDirection.Normalize();
Vector3 halfVector = surfaceToEyeDirection - dirLight.GetDirection();
halfVector.Normalize();
float glareSpec = rage::Clamp(surface_worldNormal.Dot(halfVector), 0.0f, 1.0f);
#if CSE_VEHICLE_EDITABLEVALUES
const u32 powCount = ms_nEVSunGlarePow;
#else
const u32 powCount = 32;
#endif
float glareSpecFactor = 1.0f;
for(u32 i=0; i<powCount; i++)
{
glareSpecFactor *= glareSpec;
}
glare_s *= glareSpecFactor;
glare_s = rage::Clamp(glare_s, 0.0f, 1.0f);
// SunGlareFx v2:
if(glare_s > 0.0f)
{
Vector3 boundCentre;
const float boundRadius = pVehicle->GetBoundCentreAndRadius(boundCentre);
Vector3 coronaPos = boundCentre;
#if CSE_VEHICLE_EDITABLEVALUES
const float spriteZShiftScale = ms_fEVSunGlareSpriteZShiftScale;
#else
const float spriteZShiftScale = 0.2f;
#endif
coronaPos.z += boundRadius*spriteZShiftScale; // shift glare sprite a little upwards to cover windscreen, etc.
#if CSE_VEHICLE_EDITABLEVALUES
const float coronaSizeMult = ms_fEVSunGlareSpriteSize;
#else
const float coronaSizeMult = 0.55f;
#endif
const float coronaSize = boundRadius * coronaSizeMult * glare_s;
u32 colorInt = u32(255.0f*glare_s);
Color32 coronaColor(colorInt,colorInt,colorInt,colorInt);
#if CSE_VEHICLE_EDITABLEVALUES
const float coronaHdrIntensityMult = ms_fEVSunGlareHdrMult;
#else
const float coronaHdrIntensityMult = 8.0f;
#endif
const float coronaHdrIntensity = coronaHdrIntensityMult * glare_s * glare_s;
const float zBias = boundRadius*1.5f;
g_coronas.Register(RCC_VEC3V(coronaPos),
coronaSize,
coronaColor,
coronaHdrIntensity,
zBias,
Vec3V(V_ZERO),
1.0f,
CORONAS_DEF_DIR_LIGHT_CONE_ANGLE_INNER,
CORONAS_DEF_DIR_LIGHT_CONE_ANGLE_OUTER,
CORONA_DONT_REFLECT);
}
}
// update tyre burst/side ratios:
this->m_bBurstWheel = false;
const u32 numWheels = pVehicle->GetNumWheels();
if(numWheels)
{
float aBurstRatios[NUM_VEH_CWHEELS_MAX];
float aSideRatios[NUM_VEH_CWHEELS_MAX];
sysMemSet(aBurstRatios, 0x00, sizeof(aBurstRatios));
sysMemSet(aSideRatios, 0x00, sizeof(aSideRatios));
for(int i=0; i<numWheels; i++)
{
CWheel* pWheel = pVehicle->GetWheel(i);
if(pWheel->GetTyreHealth() < TYRE_HEALTH_DEFAULT)
{
aBurstRatios[pWheel->GetHierarchyId() - VEH_WHEEL_LF] = pWheel->GetTyreBurstRatio();
aSideRatios[pWheel->GetHierarchyId() - VEH_WHEEL_LF] = pWheel->GetTyreBurstSideRatio();
this->m_bBurstWheel = true;
}
}
// if any tyres are burst remap burst/side ratios to <0;255> (format directly used by DLC):
if(this->m_bBurstWheel)
{
for(int i=0; i<NUM_VEH_CWHEELS_MAX; i++)
{
m_wheelBurstSideRatios[i][0] = (u8)(rage::Clamp(aBurstRatios[i], 0.0f, 1.0f) * 255.0f);
m_wheelBurstSideRatios[i][1] = (u8)(rage::Clamp(0.5f * (aSideRatios[i] + 1.0f), 0.0f, 1.0f) * 255.0f);
}
}
}// if(pVehicle->GetNumWheels())...
}//if(pEntity->GetIsTypeVehicle())...
else
{
// Assuming this is a wheel that's broken off
this->m_bBurstWheel = GetEnableTyreDeform();
if(this->m_bBurstWheel)
{
for(int i = 0; i < NUM_VEH_CWHEELS_MAX; i++)
{
m_wheelBurstSideRatios[i][0] = 255;
m_wheelBurstSideRatios[i][1] = 127;
}
}
}
}// end of Update()...
#if VEHICLE_SUPPORT_PAINT_RAMP
static grcTexture* GetVehicleColourRampTexture(CVehicleModelInfoVarGlobal* pVehColours, s32 col)
{
grcTexture* result = 0;
fwTxd *rampTxd = CCustomShaderEffectVehicle::GetRampTxd();
const char *rampTextureName = pVehColours->GetVehicleColourRampTextureName(col);
if (rampTextureName && rampTextureName[0] && Verifyf(rampTxd, "Missing ramp Txd"))
{
u32 rampHash = fwTxd::ComputeHash(rampTextureName);
result = rampTxd->Lookup(rampHash);
Assert(result);
}
return result;
}
#endif
//
//
//
//
bool CCustomShaderEffectVehicle::UpdateVehicleColors(CEntity *pEntity)
{
// needs to be at a multiple of 16
AlignedCompileTimeAssert(OffsetOf(CCustomShaderEffectVehicle,m_fLightDimmer), 16);
Assert(pEntity);
// might not be a vehicle (fragments break off vehicles as CObjects but still point to the vehicle model info)
// need to work out how to pass the parent vehicle through to these objects
CRGBA cols[7];
float fBodyColorScale = 1.0f;
u8 metallicId[7];
#if VEHICLE_SUPPORT_PAINT_RAMP
grcTexture* ramps[NELEM(m_pRampTextures)] = {};
#endif
cols[4] = CRGBA(255,255,255,255); // default interior color
metallicId[4] = (u8)CVehicleModelColor::EVehicleModelColorMetallic_none;
CCustomShaderEffectVehicleType *pType = GetCseTypeInternal();
bool bColorChanged = false;
if(pEntity->GetIsTypeVehicle())
{
CVehicle *pVehicle = static_cast<CVehicle*>(pEntity);
CVehicleModelInfoVarGlobal* pVehColours = CVehicleModelInfo::GetVehicleColours();
Assert(pVehColours);
cols[0] = pVehColours->GetVehicleColour(pVehicle->GetBodyColour1());
cols[1] = pVehColours->GetVehicleColour(pVehicle->GetBodyColour2());
cols[2] = pVehColours->GetVehicleColour(pVehicle->GetBodyColour3());
cols[3] = pVehColours->GetVehicleColour(pVehicle->GetBodyColour4());
cols[5] = pVehColours->GetVehicleColour(pVehicle->GetBodyColour5()); // color5 mapped to bodycolor6
cols[6] = pVehColours->GetVehicleColour(pVehicle->GetBodyColour6()); // color6 mapped to bodycolor7
metallicId[0] = pVehColours->GetVehicleColourMetallicID(pVehicle->GetBodyColour1());
metallicId[1] = pVehColours->GetVehicleColourMetallicID(pVehicle->GetBodyColour2());
metallicId[2] = pVehColours->GetVehicleColourMetallicID(pVehicle->GetBodyColour3());
metallicId[3] = pVehColours->GetVehicleColourMetallicID(pVehicle->GetBodyColour4());
metallicId[5] = pVehColours->GetVehicleColourMetallicID(pVehicle->GetBodyColour5()); // color5 mapped to bodycolor6
metallicId[6] = pVehColours->GetVehicleColourMetallicID(pVehicle->GetBodyColour6()); // color6 mapped to bodycolor7
#if VEHICLE_SUPPORT_PAINT_RAMP
ramps[0] = GetVehicleColourRampTexture(pVehColours, pVehicle->GetBodyColour1());
ramps[1] = GetVehicleColourRampTexture(pVehColours, pVehicle->GetBodyColour2());
ramps[2] = GetVehicleColourRampTexture(pVehColours, pVehicle->GetBodyColour3());
ramps[3] = GetVehicleColourRampTexture(pVehColours, pVehicle->GetBodyColour4());
#endif
if(pVehicle->m_nPhysicalFlags.bRenderScorched)
{
// vehicle burntout/exploded:
this->m_bRenderScorched = TRUE;
// fBodyColorScale = 0.1f;
// default interior (bodycolor5) color:
cols[4] = CRGBA(128,128,128);
}
if( pType->m_idVarDiffuseTex2 )
{
CVehicleModelInfo *modelInfo = pVehicle->GetVehicleModelInfo();
Assert(modelInfo);
if( modelInfo->GetVehicleFlag(CVehicleModelInfoFlags::FLAG_HAS_LIVERY) )
{
Assertf(modelInfo->GetLiveriesCount() >0, "%s:Livery flag but no liveries ?", modelInfo->GetModelName());
if(m_nLiveryIdx != -1) // livery ID to use has already by decided
{
u32 liveryHash = modelInfo->GetLiveryHash(m_nLiveryIdx);
Assertf(liveryHash != 0xFFFFFFFF, "Invalid livery texture on vehicle '%s'", modelInfo->GetModelName());
grcTexture* liveryTex = NULL;
//if (m_pType->GetIsHighDetail())
//{
// s32 hdTxdIdx = modelInfo->GetHDTxdIndex();
// fwTxd* hdTxd = g_TxdStore.Get(hdTxdIdx);
// Assert(hdTxd);
//
// if (hdTxd)
// liveryTex = hdTxd->Lookup(liveryHash);
//}
if (!liveryTex)
{
strLocalIndex txdIdx = strLocalIndex(modelInfo->GetAssetParentTxdIndex());
fwTxd* txd = g_TxdStore.Get(txdIdx);
if (AssertVerify(txd))
liveryTex = txd->Lookup(liveryHash);
}
m_pLiveryTexture = liveryTex;
Assert(m_pLiveryTexture);
}
else
{
if( modelInfo->GetVehicleFlag(CVehicleModelInfoFlags::FLAG_LIVERY_MATCH_EXTRA) ) // Match extras to livery
{
m_nLiveryIdx = -1;
int extraIdx = -1;
if( pVehicle->m_nDisableExtras ) // anything turned on ?
{
for(int i=0; i<(VEH_LAST_EXTRA - VEH_EXTRA_1); i++)
{
if( !(pVehicle->m_nDisableExtras &BIT(i)) )
{
// Enabled
extraIdx = i;
break;
}
}
m_nLiveryIdx = extraIdx;
}
if( m_nLiveryIdx == -1 )
{
if( extraIdx == -1 )
{ // extra with no matching textures, hence just use the last texture (supposedly blank)
m_nLiveryIdx = modelInfo->GetLiveriesCount()-1;
}
else
{ // No extras, just pick a random one
m_nLiveryIdx = fwRandom::GetRandomNumberInRange(0, modelInfo->GetLiveriesCount());
}
}
else
{ // One extra : are we using the matching or the last texture (blank)
bool noLivery = (0 != (fwRandom::GetRandomNumberInRange(0, 3) & 1));
if( noLivery )
{
m_nLiveryIdx = modelInfo->GetLiveriesCount()-1;
}
}
u32 liveryHash = modelInfo->GetLiveryHash(m_nLiveryIdx);
Assertf(liveryHash != 0xFFFFFFFF, "Invalid livery texture on vehicle '%s'", modelInfo->GetModelName());
strLocalIndex txdIdx = strLocalIndex(modelInfo->GetAssetParentTxdIndex());
fwTxd *txd = g_TxdStore.Get(txdIdx);
if (AssertVerify(txd))
{
grcTexture *liveryTex = txd->Lookup(liveryHash);
m_pLiveryTexture = liveryTex;
Assert(m_pLiveryTexture);
}
}
else
{
m_nLiveryIdx = fwRandom::GetRandomNumberInRange(0, modelInfo->GetLiveriesCount());
u32 liveryHash = modelInfo->GetLiveryHash(m_nLiveryIdx);
Assertf(liveryHash != 0xFFFFFFFF, "Invalid livery texture on vehicle '%s'", modelInfo->GetModelName());
strLocalIndex txdIdx = strLocalIndex(modelInfo->GetAssetParentTxdIndex());
fwTxd *txd = g_TxdStore.Get(txdIdx);
if (AssertVerify(txd))
{
grcTexture *liveryTex = txd->Lookup(liveryHash);
m_pLiveryTexture = liveryTex;
Assert(m_pLiveryTexture);
}
}
}
}
else
{
m_pLiveryTexture = NULL;
}
}// if(pType->m_idVarDiffuseTex2)...
if( pType->m_idVarDiffuseTex3 )
{
CVehicleModelInfo *modelInfo = pVehicle->GetVehicleModelInfo();
Assert(modelInfo);
if( modelInfo->GetVehicleFlag(CVehicleModelInfoFlags::FLAG_HAS_LIVERY) )
{
Assertf(modelInfo->GetLiveries2Count() >0, "%s:Livery flag but no liveries2 ?", modelInfo->GetModelName());
if(m_nLivery2Idx != -1) // livery ID to use has already by decided
{
u32 livery2Hash = modelInfo->GetLivery2Hash(m_nLivery2Idx);
Assertf(livery2Hash != 0xFFFFFFFF, "Invalid livery2 texture on vehicle '%s'", modelInfo->GetModelName());
grcTexture* livery2Tex = NULL;
if (!livery2Tex)
{
strLocalIndex txdIdx = strLocalIndex(modelInfo->GetAssetParentTxdIndex());
fwTxd* txd = g_TxdStore.Get(txdIdx);
if (AssertVerify(txd))
livery2Tex = txd->Lookup(livery2Hash);
}
m_pLivery2Texture = livery2Tex;
Assert(m_pLivery2Texture);
}
else
{
if( modelInfo->GetVehicleFlag(CVehicleModelInfoFlags::FLAG_LIVERY_MATCH_EXTRA) ) // Match extras to livery
{
m_nLivery2Idx = -1;
int extraIdx = -1;
if( pVehicle->m_nDisableExtras ) // anything turned on ?
{
for(int i=0; i<(VEH_LAST_EXTRA - VEH_EXTRA_1); i++)
{
if( !(pVehicle->m_nDisableExtras &BIT(i)) )
{
// Enabled
extraIdx = i;
break;
}
}
m_nLivery2Idx = extraIdx;
}
if( m_nLivery2Idx == -1 )
{
if( extraIdx == -1 )
{ // extra with no matching textures, hence just use the last texture (supposedly blank)
m_nLivery2Idx = modelInfo->GetLiveries2Count()-1;
}
else
{ // No extras, just pick a random one
m_nLivery2Idx = fwRandom::GetRandomNumberInRange(0, modelInfo->GetLiveries2Count());
}
}
else
{ // One extra : are we using the matching or the last texture (blank)
bool noLivery = (0 != (fwRandom::GetRandomNumberInRange(0, 3) & 1));
if( noLivery )
{
m_nLivery2Idx = modelInfo->GetLiveries2Count()-1;
}
}
u32 livery2Hash = modelInfo->GetLivery2Hash(m_nLivery2Idx);
Assertf(livery2Hash != 0xFFFFFFFF, "Invalid livery2 texture on vehicle '%s'", modelInfo->GetModelName());
strLocalIndex txdIdx = strLocalIndex(modelInfo->GetAssetParentTxdIndex());
fwTxd *txd = g_TxdStore.Get(txdIdx);
if (AssertVerify(txd))
{
grcTexture *livery2Tex = txd->Lookup(livery2Hash);
m_pLivery2Texture = livery2Tex;
Assert(m_pLivery2Texture);
}
}
else
{
m_nLivery2Idx = fwRandom::GetRandomNumberInRange(0, modelInfo->GetLiveries2Count());
u32 livery2Hash = modelInfo->GetLivery2Hash(m_nLivery2Idx);
Assertf(livery2Hash != 0xFFFFFFFF, "Invalid livery2 texture on vehicle '%s'", modelInfo->GetModelName());
strLocalIndex txdIdx = strLocalIndex(modelInfo->GetAssetParentTxdIndex());
fwTxd *txd = g_TxdStore.Get(txdIdx);
if (AssertVerify(txd))
{
grcTexture *livery2Tex = txd->Lookup(livery2Hash);
m_pLivery2Texture = livery2Tex;
Assert(m_pLivery2Texture);
}
}
}
}
else
{
m_pLivery2Texture = NULL;
}
}// if(pType->m_idVarDiffuseTex3)...
}
else
{
cols[0] = cols[1] = cols[2] = cols[3] = cols[5] = cols[6] = CRGBA(150, 150,150, 255);
metallicId[0] = metallicId[1] = metallicId[2] = metallicId[3] = metallicId[5] = metallicId[6] = (u8)CVehicleModelColor::EVehicleModelColorMetallic_none;
}
Color32 primaryColor = m_varDifCol[0];
Color32 secondaryColor = m_varDifCol[1];
for(s32 i=0; i<7; i++)
{
if(i==4) // skip bodycolor5 as it's interior hardcoded color
continue;
Color32 newColor = Color32(cols[i].GetRedf()*fBodyColorScale, cols[i].GetGreenf()*fBodyColorScale, cols[i].GetBluef()*fBodyColorScale);
if(newColor != this->m_varDifCol[i])
{
bColorChanged = true;
}
this->m_varDifCol[i] = newColor;
this->m_varMetallicID[i] = metallicId[i];
}
#if VEHICLE_SUPPORT_PAINT_RAMP
for(u32 i = 0; i < NELEM(ramps); ++i)
{
if(ramps[i] != m_pRampTextures[i])
{
bColorChanged = true;
}
this->m_pRampTextures[i] = ramps[i];
}
#endif
// Restore custom colors
if( m_bCustomPrimaryColor )
m_varDifCol[0] = primaryColor;
if( m_bCustomSecondaryColor )
m_varDifCol[1] = secondaryColor;
// and interior color with no body color scale:
this->m_varDifCol[4] = cols[4];
this->m_varMetallicID[4] = metallicId[4];
// this is specular color:
this->SetSpec2Color(cols[2].GetRed(), cols[2].GetGreen(), cols[2].GetBlue());
return bColorChanged;
}// end of UpdateVehicleColors()...
void CCustomShaderEffectVehicle::SetCustomPrimaryColor(Color32 col)
{
m_varDifCol[0] = col;
m_bCustomPrimaryColor = true;
}
Color32 CCustomShaderEffectVehicle::GetCustomPrimaryColor()
{
return m_varDifCol[0];
}
void CCustomShaderEffectVehicle::SetCustomSecondaryColor(Color32 col)
{
m_varDifCol[1] = col;
m_bCustomSecondaryColor = true;
}
Color32 CCustomShaderEffectVehicle::GetCustomSecondaryColor()
{
return m_varDifCol[1];
}
void CCustomShaderEffectVehicle::SetRed()
{
m_varDifCol[0] =
m_varDifCol[1] =
m_varDifCol[2] =
m_varDifCol[3] =
m_varDifCol[4] =
m_varDifCol[5] =
m_varDifCol[6] = Color32(255,0,0);
m_varMetallicID[0] =
m_varMetallicID[1] =
m_varMetallicID[2] =
m_varMetallicID[3] =
m_varMetallicID[4] =
m_varMetallicID[5] =
m_varMetallicID[6] = (u8)CVehicleModelColor::EVehicleModelColorMetallic_none;
}
void CCustomShaderEffectVehicle::SetGreen()
{
m_varDifCol[0] =
m_varDifCol[1] =
m_varDifCol[2] =
m_varDifCol[3] =
m_varDifCol[4] =
m_varDifCol[5] =
m_varDifCol[6] = Color32(0,255,0);
m_varMetallicID[0] =
m_varMetallicID[1] =
m_varMetallicID[2] =
m_varMetallicID[3] =
m_varMetallicID[4] =
m_varMetallicID[5] =
m_varMetallicID[6] = (u8)CVehicleModelColor::EVehicleModelColorMetallic_none;
}
void CCustomShaderEffectVehicle::SetBlue()
{
m_varDifCol[0] =
m_varDifCol[1] =
m_varDifCol[2] =
m_varDifCol[3] =
m_varDifCol[4] =
m_varDifCol[5] =
m_varDifCol[6] = Color32(0,0,255);
m_varMetallicID[0] =
m_varMetallicID[1] =
m_varMetallicID[2] =
m_varMetallicID[3] =
m_varMetallicID[4] =
m_varMetallicID[5] =
m_varMetallicID[6] = (u8)CVehicleModelColor::EVehicleModelColorMetallic_none;
}
//
//
//
//
void CCustomShaderEffectVehicle::AddToDrawList(u32 modelIndex, bool bExecute)
{
DLC(CCustomShaderEffectDC, (*this, modelIndex, bExecute, GetCseTypeInternal()));
}
//
//
//
// special version of SetShaderVariables() method for JohnW's multicore renderer
// as we don't have entities there, but only drawables;
//
void CCustomShaderEffectVehicle::SetShaderVariables(rmcDrawable* pDrawable)
{
SetShaderVariables(pDrawable, Vector3(0.0, 0.0, 0.0));
}
void CCustomShaderEffectVehicle::SetShaderVariables(rmcDrawable* pDrawable, Vector3 boneOffset, bool isBrokenOffPart)
{
// rmcDrawable* pDrawable = NULL;
// if (GetIsHighDetail()){
// CVehicleModelInfo* pVMI = static_cast<CVehicleModelInfo*>(m_pBaseModelInfo);
// if (pVMI->GetHDFragType()){
// pDrawable = pVMI->GetHDFragType()->GetCommonDrawable();
// } else {
// return;
// }
// } else {
// Assert(m_pBaseModelInfo);
// pDrawable = m_pBaseModelInfo->GetDrawable();
// Assert(pDrawable);
// }
if(!pDrawable)
return;
#if __BANK
if(DRAWLISTMGR->IsExecutingDebugOverlayDrawList())
return;
#endif
CCustomShaderEffectVehicleType *pType = GetCseTypeInternal();
grmShaderGroup* pShaderGroup = &pDrawable->GetShaderGroup();
// setup shaders for vehicle deformation
// Do this before the early out for the shadow pass so its setup correctly for shadows.
#if USE_GPU_VEHICLEDEFORMATION
if(pType->m_idVarDamageSwitchOn)
{
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarDamageSwitchOn, GTASHADERVARBOOL(m_bDamageSwitchOn));
// no need to set other vars if damage isn't switched on
if(m_bDamageSwitchOn)
{
if(m_pDamageTexture && pType->m_idVarDamageTex && pType->m_idVarBoundRadius && pType->m_idVarDamageMult && pType->m_idVarDamagedFrontWheelOffsets && pType->m_idVarOffset BANK_ONLY( && pType->m_idVarDebugDamageMap && pType->m_idVarDebugDamageMult))
{
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDamageTex, m_pDamageTexture);
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarBoundRadius, m_fBoundRadius);
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDamageMult, m_fDamageMultiplier);
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDamagedFrontWheelOffsets, m_vDamagedFrontWheelOffsets, 2);
#if __BANK
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDebugDamageMap, CVehicleDeformation::ms_bDisplayDamageMap);
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDebugDamageMult, CVehicleDeformation::ms_bDisplayDamageMult);
#endif
#if __BANK
boneOffset += Vector3(CVehicleDeformation::m_DamageTextureOffset_X, CVehicleDeformation::m_DamageTextureOffset_Y, CVehicleDeformation::m_DamageTextureOffset_Z);
#endif
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarOffset, boneOffset);
}
else
{ // disable damage if invalid settings
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarDamageSwitchOn, false);
if(pType->m_idVarDamageTex)
{
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDamageTex, const_cast<grcTexture*>(grcTexture::NoneBlack));
}
}
}
else
{
if(pType->m_idVarDamageTex)
{
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDamageTex, m_pDamageTexture ? m_pDamageTexture : const_cast<grcTexture*>(grcTexture::NoneBlack));
}
}
}
else
{
if(pType->m_idVarDamageTex)
{
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDamageTex, m_pDamageTexture ? m_pDamageTexture : const_cast<grcTexture*>(grcTexture::NoneBlack));
}
}
#endif //USE_GPU_VEHICLEDEFORMATION...
// tyre deform on/off control:
if(pType->m_idVarTyreDeformSwitchOn)
{
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarTyreDeformSwitchOn, GTASHADERVARBOOL(m_bTyreDeformSwitchOn));
#if CSE_VEHICLE_EDITABLEVALUES
// editable inner wheel radius stuff:
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarTyreDeformSwitchOn, GTASHADERVARBOOL(m_bTyreDeformSwitchOn || GetEWREnabled()));
#endif
}
if(grmModel::GetForceShader())
return;
const u32 dirtTexCount = pType->m_DirtTexEffect.GetCount();
if(m_bRenderScorched)
{
// Dirt texture (replaced with burnout when vehicle scorched):
for(u32 i=0; i<dirtTexCount; i++)
{
CCustomShaderEffectVehicleType::structDirtTexEffect *ptr = &pType->m_DirtTexEffect[i];
Assert(!GetCseType()->m_bHasTruckTex || CCustomShaderEffectVehicleType::ms_pBurnoutTruckTexture); // truck expects a valid burnout texture
grcTexture *burnoutTex = GetCseType()->m_bHasTruckTex? CCustomShaderEffectVehicleType::ms_pBurnoutTruckTexture : CCustomShaderEffectVehicleType::ms_pBurnoutTexture;
burnoutTex = ptr->bIsInterior? CCustomShaderEffectVehicleType::ms_pBurnoutIntTexture : burnoutTex;
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarDirtTex, (grcTexture*)burnoutTex);
}
// burnout vehicle: full dirt level + darker dirt + dirtOrBurnout=0 (nonDirtSpecIntScale (for non dirt shaders) to 0)
if(pType->m_idVarDirtLevelMod)
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDirtLevelMod, Vector4(GetBurnoutLevel(), 0.25f, /*dirtOrBurnout*/0.0f, 0.10f));
}
else
{ // restore original dirt texture:
for(u32 i=0; i<dirtTexCount; i++)
{
CCustomShaderEffectVehicleType::structDirtTexEffect *ptr = &pType->m_DirtTexEffect[i];
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarDirtTex, (grcTexture*)ptr->pOrigDirtTex);
}
const float dirtModulator = rage::Lerp(rage::Clamp(g_weather.GetWetness(),0.0f,1.0f), 1.0f, DEFAULT_DIRTMODWET);
if(pType->m_idVarDirtLevelMod)
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDirtLevelMod, Vector4(this->GetDirtLevel(), dirtModulator, /*dirtOrBurnout*/1.0f, 1.0f));
}
if(DRAWLISTMGR->IsExecutingShadowDrawList())
return;
if(pType->m_idVarDirtColor)
{
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDirtColor, this->GetDirtColor());
}
if(pType->m_idVarSpec2Color)
{
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarSpec2Color, this->GetSpec2Color()); // rgb=spec2Color, a=spec2DirLerp
}
#if USE_DISKBRAKEGLOW
if( pType->m_idVarDiskBrakeGlow )
{
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDiskBrakeGlow,m_varDiskBrakeGlow);
}
#endif
// setup shader for headlights
if(pType->m_idVarDimmer)
{
float lightValues[4*CVehicleLightSwitch::LW_LIGHTVECTORS] = {0.0f};
const float dayNightFade = CVehicle::GetDayNightFade();
for (u32 i=0; i < CVehicleLightSwitch::LW_LIGHTCOUNT; ++i)
{
lightValues[i] = isBrokenOffPart ? CVehicle::GetLightOffValue(i, dayNightFade) : m_fLightDimmer[i];
}
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDimmer, (Vector4*)lightValues, CVehicleLightSwitch::LW_LIGHTVECTORS);
}
// SpecularColor:
const s32 specCount = pType->m_SpecColEffect.GetCount();
if(false && m_bRenderScorched)
{
static dev_bool bEnableSpecularBurnout=true;
for(s32 i=0; i<specCount; i++)
{
CCustomShaderEffectVehicleType::structSpecColEffect *ptr = &pType->m_SpecColEffect[i];
if(bEnableSpecularBurnout)
{
if(ptr->idvarSpecInt)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecInt, float(ptr->origSpecInt));
if(ptr->idvarSpecFalloff)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecFalloff, float(ptr->origSpecFalloff));
if(ptr->idvarSpecFresnel)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecFresnel, float(ptr->origSpecFresnel));
}
else
{
if(ptr->idvarSpecInt)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecInt, 0.0f);
}
}
}
else
{
for(s32 i=0; i<specCount; i++)
{
CCustomShaderEffectVehicleType::structSpecColEffect *ptr = &pType->m_SpecColEffect[i];
if((ptr->colorIdx != 255) && (m_varMetallicID[ptr->colorIdx] != (u8)CVehicleModelColor::EVehicleModelColorMetallic_none))
{ // setup metallic settings:
CVehicleMetallicSetting *metallicSet = CVehicleModelInfo::GetVehicleColours()->GetMetallicSetting( m_varMetallicID[ptr->colorIdx] );
Assert(metallicSet);
if(ptr->idvarSpecInt)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecInt, metallicSet->m_specInt);
if(ptr->idvarSpecFalloff)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecFalloff, metallicSet->m_specFalloff);
if(ptr->idvarSpecFresnel)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecFresnel, metallicSet->m_specFresnel);
}
else
{ // restore original specular colors:
if(ptr->idvarSpecInt)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecInt, float(ptr->origSpecInt));
if(ptr->idvarSpecFalloff)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecFalloff, float(ptr->origSpecFalloff));
if(ptr->idvarSpecFresnel)
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecFresnel, float(ptr->origSpecFresnel));
}
}
}
// overlay color:
if(pType->m_idVarDiffuse2Color)
{
if(m_bRenderScorched)
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDiffuse2Color, Vector4(0.75f, 0.75f, 0.75f, 1.0f));
else
pShaderGroup->SetVarByRef((grmShaderGroupVar)pType->m_idVarDiffuse2Color, VECTOR4_IDENTITY);
}
// diffuse tint color (used mainly for vehicle glass):
if(pType->m_idVarDiffuseColorTint)
{
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDiffuseColorTint, m_varDiffColorTint);
}
if(pType->m_idVarDiffuseTex2)
{
if (m_bHasLiveryMod)
{
grcTexture *pLiveryModTex = (grcTexture*)grcTexture::NoneBlackTransparent;
if (m_liveryFragSlotIdx != strLocalIndex::INVALID_INDEX)
{
if (g_FragmentStore.GetSlot(m_liveryFragSlotIdx)->m_pObject != NULL)
{
grmShaderGroup *pFragShaderGroup = g_FragmentStore.Get(m_liveryFragSlotIdx)->GetCommonDrawable()->GetShaderGroupPtr();
fwTxd const* pTxd = pFragShaderGroup ? pFragShaderGroup->GetTexDict() : NULL; // frag's internal txd
Assertf(pTxd,"livery mod %s, does not have a .txd embedded in the mod frag", g_FragmentStore.GetName(m_liveryFragSlotIdx));
if (pTxd && pTxd->GetCount() > 0)
{
pLiveryModTex = pTxd->GetEntry(0);
}
}
}
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDiffuseTex2, pLiveryModTex);
}
else if(m_pLiveryTexture)
{
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDiffuseTex2, m_pLiveryTexture);
}
else
{
// restore original overlay texture(s):
const u32 tex2Count = pType->m_Tex2Effect.GetCount();
for(u32 i=0; i<tex2Count; i++)
{
CCustomShaderEffectVehicleType::structTex2Effect *ptr = &pType->m_Tex2Effect[i];
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarTex2, (grcTexture*)ptr->pOrigTex2);
}
}
}
if(pType->m_idVarDiffuseTex3 && m_pLivery2Texture)
{
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarDiffuseTex3, m_pLivery2Texture);
}
const u32 count = pType->m_DiffColEffect.GetCount();
#if __ASSERT
Assertf(count > 0, "BS#124925: DiffColEffect array is empty! Andrzej would love to see this assert.");
#endif
if(count)
{
for(u32 i=0; i<count; i++)
{
CCustomShaderEffectVehicleType::structDiffColEffect *ptr = &pType->m_DiffColEffect[i];
#if __DEV
if(ms_nForceColorCars==0)
{
pShaderGroup->GetShader(ptr->shaderIdx).SetVarByRef((grcEffectVar)ptr->idvarDiffColor, ORIGIN);
}
else if(ms_nForceColorCars==1)
{
pShaderGroup->GetShader(ptr->shaderIdx).SetVarByRef((grcEffectVar)ptr->idvarDiffColor, VEC3_IDENTITY);
}
else
#endif // __DEV
{
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarDiffColor, m_varDifCol[ptr->colorIdx]);
}
#if VEHICLE_SUPPORT_PAINT_RAMP
grcTexture* diffuseRampTex = 0;
grcTexture* specularRampTex = 0;
if(ptr->colorIdx < NELEM(m_pRampTextures))
{
diffuseRampTex = m_pRampTextures[ptr->colorIdx];
specularRampTex = m_pRampTextures[2]; // Albert: 2=BodyColor3=Specular
#if __BANK
if(s_DebugRampTextureEnabled)
{
diffuseRampTex = s_DebugRampTexture;
specularRampTex = s_DebugRampTexture;
}
if(!s_RampDiffuseEnabled)
{
diffuseRampTex = 0;
}
if(!s_RampSpecularEnabled)
{
specularRampTex = 0;
}
#endif
}
#if __DEV
if(ms_nForceColorCars==0 || ms_nForceColorCars==1)
{
diffuseRampTex = 0;
specularRampTex = 0;
}
#endif
if (ptr->idvarDiffuseRampTexture)
{
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarDiffuseRampTexture, diffuseRampTex ? diffuseRampTex : const_cast<grcTexture*>(grcTexture::NoneBlack));
}
if (ptr->idvarSpecularRampTexture)
{
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarSpecularRampTexture, specularRampTex ? specularRampTex : const_cast<grcTexture*>(grcTexture::NoneBlack));
}
if (ptr->idvarDiffuseSpecularRampEnabled)
{
float rampEnabled = specularRampTex ? 2.0f : 1.0f;
rampEnabled = diffuseRampTex ? rampEnabled : -rampEnabled;
pShaderGroup->GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarDiffuseSpecularRampEnabled, rampEnabled);
}
#endif
}
}
// track UV anim for tank:
if(pType->m_idVarTrackAnimUV)
{
Vector4 uv4(m_uvTrackAnim.x, m_uvTrackAnim.y, 0.0f, 0.0f);
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarTrackAnimUV, uv4);
}
// track UV anim for tank:
if(pType->m_idVarTrack2AnimUV)
{
Vector4 uv4(m_uvTrack2Anim.x, m_uvTrack2Anim.y, 0.0f, 0.0f);
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarTrack2AnimUV, uv4);
}
// track UV anim for ammo:
if(pType->m_idVarTrackAmmoAnimUV)
{
Vector4 uv4(m_uvTrackAmmoAnim.x, m_uvTrackAmmoAnim.y, 0.0f, 0.0f);
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarTrackAmmoAnimUV, uv4);
}
// emissive control:
if(pType->m_idVarEmissiveMult)
{
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarEmissiveMult, m_fUserEmissiveMultiplier * pType->m_DefEmissiveMult);
}
// enveff scale:
if(pType->m_idVarEnvEffScale)
{
float envEffScale = GetEnvEffScale();
Vector2 envEffScaleV2(envEffScale, envEffScale/1000.0f);
pShaderGroup->SetVar((grmShaderGroupVar)pType->m_idVarEnvEffScale, envEffScaleV2);
}
//Set the license plate shader vars
const CVehicleModelInfoPlates *plates = &CVehicleModelInfo::GetVehicleColours()->GetLicensePlateData();
if(plates && m_nLicensePlateTexIdx >= 0)
{
//Find the right textures to set to license plate.
const CVehicleModelInfoPlates::TextureArray &textures = plates->GetTextureArray();
if(m_pLicensePlateDiffuseTex && pType->m_idLicensePlateBgTex != grmsgvNONE)
pShaderGroup->SetVar(static_cast<grmShaderGroupVar>(pType->m_idLicensePlateBgTex), m_pLicensePlateDiffuseTex);
if(m_pLicensePlateNormalTex && pType->m_idLicensePlateBgNormTex != grmsgvNONE)
pShaderGroup->SetVar(static_cast<grmShaderGroupVar>(pType->m_idLicensePlateBgNormTex), m_pLicensePlateNormalTex);
if(pType->m_idLicensePlateFontColor != grmsgvNONE)
pShaderGroup->SetVar(static_cast<grmShaderGroupVar>(pType->m_idLicensePlateFontColor), textures[m_nLicensePlateTexIdx].GetFontColor());
if(pType->m_idLicensePlateText1 != grmsgvNONE)
pShaderGroup->SetVar(static_cast<grmShaderGroupVar>(pType->m_idLicensePlateText1), Vector4(m_LicensePlateText[0],m_LicensePlateText[1],m_LicensePlateText[2],m_LicensePlateText[3]));
if(pType->m_idLicensePlateText2 != grmsgvNONE)
pShaderGroup->SetVar(static_cast<grmShaderGroupVar>(pType->m_idLicensePlateText2), Vector4(m_LicensePlateText[4],m_LicensePlateText[5],m_LicensePlateText[6],m_LicensePlateText[7]));
if(pType->m_idLicensePlateFontOutlineColor != grmsgvNONE)
pShaderGroup->SetVar(static_cast<grmShaderGroupVar>(pType->m_idLicensePlateFontOutlineColor), textures[m_nLicensePlateTexIdx].GetFontOutlineColor());
if(pType->m_idLicensePlateFontExtents != grmsgvNONE)
pShaderGroup->SetVar(static_cast<grmShaderGroupVar>(pType->m_idLicensePlateFontExtents), textures[m_nLicensePlateTexIdx].GetFontExtents());
if(pType->m_idLicensePlateFontOutlineMinMaxDepth_Enabled != grmsgvNONE)
{
const Vector2 &outlineMinMaxDepth = textures[m_nLicensePlateTexIdx].GetFontOutlineMinMaxDepth();
Vector4 enabled(outlineMinMaxDepth.x, outlineMinMaxDepth.y, (textures[m_nLicensePlateTexIdx].IsFontOutlineEnabled() ? 1.0f : 0.0f), 0.0f);
pShaderGroup->SetVar(static_cast<grmShaderGroupVar>(pType->m_idLicensePlateFontOutlineMinMaxDepth_Enabled), enabled);
}
if(pType->m_idLicensePlateMaxLettersOnPlate != grmsgvNONE)
pShaderGroup->SetVar(static_cast<grmShaderGroupVar>(pType->m_idLicensePlateMaxLettersOnPlate), textures[m_nLicensePlateTexIdx].GetMaxLettersOnPlate());
}
#if CSE_VEHICLE_EDITABLEVALUES
this->SetEditableShaderValues(pShaderGroup, pDrawable);
#endif
}// end of SetShaderVariables()...
//
//
// this is called from CVehicleModelInfo::SetupCommonData():
//
void CCustomShaderEffectVehicle::SetupBurnoutTexture(s32 txdSlot)
{
if (txdSlot == -1)
{
CCustomShaderEffectVehicleType::ms_pBurnoutTexture = NULL;
CCustomShaderEffectVehicleType::ms_pBurnoutIntTexture = NULL;
}
else
{
const fwTxd *burnoutTxd = g_TxdStore.Get(strLocalIndex(txdSlot));
if (Verifyf(burnoutTxd, "vehicle burnout txd slot %d (%s) was NULL", txdSlot, g_TxdStore.GetName(strLocalIndex(txdSlot))))
{
grcTexture *burnout = burnoutTxd->Lookup(VEHICLE_GENERIC_BURNOUT_TEXNAME);
CCustomShaderEffectVehicleType::ms_pBurnoutTexture = burnout;
Assert(CCustomShaderEffectVehicleType::ms_pBurnoutTexture);
grcTexture *burnoutInt = burnoutTxd->Lookup(VEHICLE_GENERIC_BURNOUT_INT_TEXNAME);
CCustomShaderEffectVehicleType::ms_pBurnoutIntTexture = burnoutInt;
Assert(CCustomShaderEffectVehicleType::ms_pBurnoutIntTexture);
}
}
}// end of SetupBurnoutTexture()...
//
//
//
//
void CCustomShaderEffectVehicle::SelectLicensePlateByProbability(CEntity *pEntity)
{
if(Verifyf(pEntity, "Null entity passed in to SelectLicensePlateByProbability()!"))
{
int defaultTexIdx = CVehicleModelInfo::GetVehicleColours()->GetLicensePlateData().GetDefaultTextureIndex();
CVehicle* pVehicle = static_cast<CVehicle*>(pEntity);
CVehicleModelInfo *modelInfo = pVehicle->GetVehicleModelInfo();
if(Verifyf(modelInfo, "Got invalid model info! (pEntity = 0x%p | modelIndex = %d)", pEntity, pEntity->GetModelIndex()) && modelInfo->GetModelType() == MI_TYPE_VEHICLE)
{
defaultTexIdx = modelInfo->SelectLicensePlateTextureIndex();
}
SetLicensePlateTexIndex(defaultTexIdx);
}
}
void CCustomShaderEffectVehicle::SetLicensePlateText(const char *str)
{
//Convert text to char array indices.
const CVehicleModelInfoPlates *plates = &CVehicleModelInfo::GetVehicleColours()->GetLicensePlateData();
u8 *strIndices = m_LicensePlateText;
bool endOfStr = false;
// B*1325679 - Can you add the required number of spaces when the name is shorter than the 8 characters it is.
// 8 chars max, not zero terminated if max?
int length;
for(length=0; length<LICENCE_PLATE_LETTERS_MAX; length++)
{
if( str[length] == 0 )
break;
}
int lead = (LICENCE_PLATE_LETTERS_MAX - length)>>1;
for(u32 i=0; i<LICENCE_PLATE_LETTERS_MAX; i++)
{
endOfStr = endOfStr || i>=(length + lead);
if(endOfStr || i<lead)
{
strIndices[i] = plates->GetFontSpaceOffset();
}
else
{
char c = str[i - lead];
if(c >= '0' && c <= '9')
{
strIndices[i] = plates->GetFontNumericOffset() + (c - '0');
}
else if(c >= 'A' && c <= 'Z')
{
strIndices[i] = plates->GetFontAlphabeticOffset() + (c - 'A');
}
else if(c >= 'a' && c <= 'z')
{
strIndices[i] = plates->GetFontAlphabeticOffset() + (c - 'a');
}
else if(c == ' ')
{
strIndices[i] = plates->GetFontSpaceOffset();
}
else
{
//All the rest go here...
strIndices[i] = plates->GetFontRandomCharOffset() + (c % plates->GetFontNumRandomChar());
}
}
//Make sure the index is with-in the proper range
#if __ASSERT
static u8 sMaxGlyphs = 64;
Assertf(strIndices[i] < sMaxGlyphs, "Invalid font glyph index value: %i", static_cast<int>(strIndices[i]));
#endif
}
}
static char sDecodedLicenseText[ CCustomShaderEffectVehicle::LICENCE_PLATE_LETTERS_MAX+1 ];
CompileTimeAssert(sizeof(sDecodedLicenseText) > CCustomShaderEffectVehicle::LICENCE_PLATE_LETTERS_MAX);
const char* CCustomShaderEffectVehicle::GetLicensePlateText() const
{
const CVehicleModelInfoPlates *plates = &CVehicleModelInfo::GetVehicleColours()->GetLicensePlateData();
int inIDX = 0;
int outIDX = 0;
while(inIDX < LICENCE_PLATE_LETTERS_MAX)
{
if (m_LicensePlateText[inIDX] >= plates->GetFontRandomCharOffset())
{
// we can't convert back the random characters unfortunately
sDecodedLicenseText[outIDX++] = ' ';
}
else if (m_LicensePlateText[inIDX] >= plates->GetFontAlphabeticOffset())
{
sDecodedLicenseText[outIDX++] = 'A' + (m_LicensePlateText[inIDX] - plates->GetFontAlphabeticOffset());
}
else if (m_LicensePlateText[inIDX] >= plates->GetFontNumericOffset())
{
sDecodedLicenseText[outIDX++] = '0' + (m_LicensePlateText[inIDX] - plates->GetFontNumericOffset());
}
else if (m_LicensePlateText[inIDX] == 0)
{
sDecodedLicenseText[outIDX++] = 0;
break;
}
inIDX++;
}
for(int i = outIDX; i<=LICENCE_PLATE_LETTERS_MAX; i++)
{
sDecodedLicenseText[i] = 0;
}
return sDecodedLicenseText;
}
void CCustomShaderEffectVehicle::GenerateLicensePlateText(u32 seed)
{
// California legal is 1ABC234 since early 80s
// We'll use 12ABC345
mthRandom rnd(seed);
char tag[9];
tag[0] = static_cast<char>(rnd.GetRanged('0','9'));
tag[1] = static_cast<char>(rnd.GetRanged('0','9'));
tag[2] = static_cast<char>(rnd.GetRanged('A','Z'));
tag[3] = static_cast<char>(rnd.GetRanged('A','Z'));
tag[4] = static_cast<char>(rnd.GetRanged('A','Z'));
tag[5] = static_cast<char>(rnd.GetRanged('0','9'));
tag[6] = static_cast<char>(rnd.GetRanged('0','9'));
tag[7] = static_cast<char>(rnd.GetRanged('0','9'));
tag[8] = '\0';
SetLicensePlateText(tag);
}
void CCustomShaderEffectVehicle::SetLicensePlateTexIndex(s32 index)
{
const CVehicleModelInfoPlates *plates = &CVehicleModelInfo::GetVehicleColours()->GetLicensePlateData();
if(Verifyf(index >= -1 && index < plates->GetTextureArray().size(),
"Invalid index license plate texture index requested: %d. Max number of known plate textures = %d",
index, plates->GetTextureArray().size() ))
{
if(m_nLicensePlateTexIdx != index)
{
//Update the license plate index
m_nLicensePlateTexIdx = index;
if(m_nLicensePlateTexIdx >= 0)
{
//Find the right textures to set to license plate.
const CVehicleModelInfoPlates::TextureArray &textures = plates->GetTextureArray();
u32 diffuseHash = textures[m_nLicensePlateTexIdx].GetDiffuseMapStrHash().GetHash();
u32 normalHash = textures[m_nLicensePlateTexIdx].GetNormalMapStrHash().GetHash();
grcTexture *diffuseMap = NULL;
grcTexture *normalMap = NULL;
strLocalIndex txdIdx = strLocalIndex(CVehicleModelInfo::GetCommonTxd());
fwTxd *txd = g_TxdStore.Get(txdIdx);
if(Verifyf(txd, "Encountered a NULL texture dictionary while trying to iterate the loaded global vehicle texture dictionaries!"))
{
if(!diffuseMap)
diffuseMap = txd->Lookup(diffuseHash);
if(!normalMap)
normalMap = txd->Lookup(normalHash);
}
//Update our texture pointers to point to new license plate background textures.
Assertf(diffuseMap, "SetLicensePlateTexIndex was unable to find the requested diffuse texture (%s <hash=0x%x>) for license plate background texture set index %d.",
(textures[m_nLicensePlateTexIdx].GetDiffuseMapStrHash().GetCStr() ? textures[m_nLicensePlateTexIdx].GetDiffuseMapStrHash().GetCStr() : "<Unknown Hash>"),
textures[m_nLicensePlateTexIdx].GetDiffuseMapStrHash().GetHash(), m_nLicensePlateTexIdx);
Assertf(normalMap, "SetLicensePlateTexIndex was unable to find the requested normal texture (%s <hash=0x%x>) for license plate background texture set index %d.",
(textures[m_nLicensePlateTexIdx].GetNormalMapStrHash().GetCStr() ? textures[m_nLicensePlateTexIdx].GetNormalMapStrHash().GetCStr() : "<Unknown Hash>"),
textures[m_nLicensePlateTexIdx].GetNormalMapStrHash().GetHash(), m_nLicensePlateTexIdx);
m_pLicensePlateDiffuseTex = diffuseMap;
m_pLicensePlateNormalTex = normalMap;
}
}
}
}
inline float wrapOverOne(float a)
{
if(a > 1.0f)
{
float ipart;
a = rage::Modf(a, &ipart);
}
return(a);
}
inline float wrapBelowZero(float a)
{
if(a < 0.0f)
{
float ipart;
a = rage::Modf(a, &ipart);
a += 1.0f;
}
return(a);
}
//
// tanks tracks:
// adds given amount of U shift to overall UV anim:
//
void CCustomShaderEffectVehicle::TrackUVAnimAdd(const Vector2& a)
{
this->m_uvTrackAnim.x += a.x; // right shift
this->m_uvTrackAnim.y += a.y; // left shift
// wrap to <0; 1.0f>
m_uvTrackAnim.x = wrapOverOne(m_uvTrackAnim.x);
m_uvTrackAnim.y = wrapOverOne(m_uvTrackAnim.y);
m_uvTrackAnim.x = wrapBelowZero(m_uvTrackAnim.x);
m_uvTrackAnim.y = wrapBelowZero(m_uvTrackAnim.y);
}
void CCustomShaderEffectVehicle::Track2UVAnimAdd(const Vector2& a)
{
this->m_uvTrack2Anim.x += a.x; // right shift
this->m_uvTrack2Anim.y += a.y; // left shift
// wrap to <0; 1.0f>
m_uvTrack2Anim.x = wrapOverOne(m_uvTrack2Anim.x);
m_uvTrack2Anim.y = wrapOverOne(m_uvTrack2Anim.y);
m_uvTrack2Anim.x = wrapBelowZero(m_uvTrack2Anim.x);
m_uvTrack2Anim.y = wrapBelowZero(m_uvTrack2Anim.y);
}
void CCustomShaderEffectVehicle::TrackAmmoUVAnimAdd(const Vector2& a)
{
this->m_uvTrackAmmoAnim.x += a.x; // right shift
this->m_uvTrackAmmoAnim.y += a.y; // left shift
// wrap to <0; 1.0f>
m_uvTrackAmmoAnim.x = wrapOverOne(m_uvTrackAmmoAnim.x);
m_uvTrackAmmoAnim.y = wrapOverOne(m_uvTrackAmmoAnim.y);
m_uvTrackAmmoAnim.x = wrapBelowZero(m_uvTrackAmmoAnim.x);
m_uvTrackAmmoAnim.y = wrapBelowZero(m_uvTrackAmmoAnim.y);
}
const u32 g_vehicleGlassVarHashDiffuseTex = ATSTRINGHASH("DiffuseTex", 0xC8E8C282);
const u32 g_vehicleGlassVarHashDirtTex = ATSTRINGHASH("DirtTex", 0xA6F4CF58);
const u32 g_vehicleGlassVarHashSpecularTex = ATSTRINGHASH("SpecularTex", 0xC6F46E79);
const u32 g_vehicleGlassVarHashSpecularMapIntensityMask = ATSTRINGHASH("SpecularMapIntensityMask", 0x92DB11FB);
const u32 g_vehicleGlassVarHashEnvEffTexTileUV = ATSTRINGHASH("envEffTexTileUV", 0xDAC8F5E7);
const u32 g_vehicleGlassVarHashEnvEffThickness = ATSTRINGHASH("envEffThickness", 0xA114F369);
const u32 g_vehicleGlassVarHashDirtLevelMod = ATSTRINGHASH("DirtLevelMod", 0xEC247F19);
const u32 g_vehicleGlassVarHashDirtColor = ATSTRINGHASH("DirtColor", 0x44546346);
const u32 g_vehicleGlassVarHashDiffuseColorTint = ATSTRINGHASH("DiffuseColorTint", 0xE297F9DA);
const u32 g_vehicleGlassVarHashEnvEffScale0 = ATSTRINGHASH("envEffScale0", 0xC788FA2A);
void CVehicleGlassShaderData::GetStandardShaderVariables(const grmShader* pShader)
{
Assertf(strcmp(pShader->GetName(), "vehicle_vehglass") == 0, "CVehicleGlassShaderData::GetStandardShaderVariables called on shader \"%s\"", pShader->GetName());
const grcEffectVar idVarDiffuseTex = pShader->LookupVarByHash(g_vehicleGlassVarHashDiffuseTex);
const grcEffectVar idVarDirtTex = pShader->LookupVarByHash(g_vehicleGlassVarHashDirtTex);
const grcEffectVar idVarSpecularTex = pShader->LookupVarByHash(g_vehicleGlassVarHashSpecularTex);
const grcEffectVar idVarSpecularMapIntensityMask = pShader->LookupVarByHash(g_vehicleGlassVarHashSpecularMapIntensityMask);
const grcEffectVar idVarEnvEffTexTileUV = pShader->LookupVarByHash(g_vehicleGlassVarHashEnvEffTexTileUV);
const grcEffectVar idVarEnvEffThickness = pShader->LookupVarByHash(g_vehicleGlassVarHashEnvEffThickness);
const grcEffectVar idVarDirtLevelMod = pShader->LookupVarByHash(g_vehicleGlassVarHashDirtLevelMod);
const grcEffectVar idVarDirtColor = pShader->LookupVarByHash(g_vehicleGlassVarHashDirtColor);
const grcEffectVar idVarDiffuseColorTint = pShader->LookupVarByHash(g_vehicleGlassVarHashDiffuseColorTint);
const grcEffectVar idVarEnvEffScale0 = pShader->LookupVarByHash(g_vehicleGlassVarHashEnvEffScale0);
grcTexture* pDiffuseTex = NULL;
grcTexture* pDirtTex = NULL;
grcTexture* pSpecularTex = NULL;
pShader->GetVar(idVarDiffuseTex , pDiffuseTex);
pShader->GetVar(idVarDirtTex , pDirtTex);
pShader->GetVar(idVarSpecularTex, pSpecularTex);
m_DiffuseTex = pDiffuseTex;
m_DirtTex = pDirtTex;
m_SpecularTex = pSpecularTex;
pShader->GetVar(idVarSpecularMapIntensityMask, m_SpecularMapIntensityMask);
pShader->GetVar(idVarEnvEffTexTileUV , m_EnvEffTexTileUV);
pShader->GetVar(idVarEnvEffThickness , m_EnvEffThickness);
pShader->GetVar(idVarDirtLevelMod , m_DirtLevelMod);
pShader->GetVar(idVarDirtColor , m_DirtColor);
pShader->GetVar(idVarDiffuseColorTint , m_DiffuseColorTint);
pShader->GetVar(idVarEnvEffScale0 , m_EnvEffScale0);
#if USE_GPU_VEHICLEDEFORMATION
m_bDamageOn = false;
m_pDamageTex = NULL; // Set this to NULL in case we can't get the damage texture from the custom shader
#endif // USE_GPU_VEHICLEDEFORMATION
}
void CVehicleGlassShaderData::GetCustomShaderVariables(const CCustomShaderEffectVehicle* pCSE)
{
m_DirtLevelMod = pCSE->m_bRenderScorched ? Vector4(1.0f, 0.25f, 0.0f, 0.0f) : Vector4(pCSE->GetDirtLevel(), 1.0f, 1.0f, 1.0f);
m_DirtColor = VEC4V_TO_VECTOR4(pCSE->GetDirtColor().GetRGBA());
m_DiffuseColorTint = VEC4V_TO_VECTOR4(pCSE->GetDiffuseTint().GetRGBA());
m_EnvEffScale0 = Vector2(pCSE->GetEnvEffScale(), pCSE->GetEnvEffScale()/1000.0f);
#if CSE_VEHICLE_EDITABLEVALUES
// Overwrite the shader value with the override value
if (CCustomShaderEffectVehicle::GetEVOverrideDiffuseColorTint())
{
CCustomShaderEffectVehicle::GetEVDiffuseColorTint(m_DiffuseColorTint);
}
#endif // CSE_VEHICLE_EDITABLEVALUES
}
void CVehicleGlassShaderData::GetDirtTexture(const CCustomShaderEffectVehicle* pCSE, int shaderIndex ASSERT_ONLY(, const char* vehicleModelName))
{
const CCustomShaderEffectVehicleType* pType = pCSE->GetCseType();
m_DirtTex = pType->GetDirtTexture(shaderIndex);
Assertf(m_DirtTex, "%s: m_DirtTex is NULL", vehicleModelName);
}
#if USE_GPU_VEHICLEDEFORMATION
void CVehicleGlassShaderData::GetDamageShaderVariables(const CCustomShaderEffectVehicle* pCSE)
{
m_bDamageOn = pCSE->GetEnableDamage();
if(m_bDamageOn)
{
m_pDamageTex = pCSE->GetDamageTex();
m_fBoundRadius = pCSE->GetBoundRadius();
m_fDamageMultiplier = pCSE->GetDamageMultiplier();
}
else
{
m_pDamageTex = NULL;
}
}
#endif // USE_GPU_VEHICLEDEFORMATION
void CVehicleGlassShader::Create(grmShader* pShader)
{
Assertf(strcmp(pShader->GetName(), "vehicle_vehglass_crack") == 0, "CVehicleGlassShader::Create called on shader \"%s\"", pShader->GetName());
m_shader = pShader;
m_idVarDiffuseTex = pShader->LookupVarByHash(g_vehicleGlassVarHashDiffuseTex);
m_idVarDirtTex = pShader->LookupVarByHash(g_vehicleGlassVarHashDirtTex);
m_idVarSpecularTex = pShader->LookupVarByHash(g_vehicleGlassVarHashSpecularTex);
m_idVarSpecularMapIntensityMask = pShader->LookupVarByHash(g_vehicleGlassVarHashSpecularMapIntensityMask);
m_idVarEnvEffTexTileUV = pShader->LookupVarByHash(g_vehicleGlassVarHashEnvEffTexTileUV);
m_idVarEnvEffThickness = pShader->LookupVarByHash(g_vehicleGlassVarHashEnvEffThickness);
m_idVarDirtLevelMod = pShader->LookupVarByHash(g_vehicleGlassVarHashDirtLevelMod);
m_idVarDirtColor = pShader->LookupVarByHash(g_vehicleGlassVarHashDirtColor);
m_idVarDiffuseColorTint = pShader->LookupVarByHash(g_vehicleGlassVarHashDiffuseColorTint);
m_idVarEnvEffScale0 = pShader->LookupVarByHash(g_vehicleGlassVarHashEnvEffScale0);
m_idVarCrackTexture = pShader->LookupVar("vehglassCrackTexture");
m_idVarCrackTextureParams = pShader->LookupVar("vehglassCrackTextureParams");
#if USE_GPU_VEHICLEDEFORMATION
m_idVarDamageSwitchOn = grcEffect::LookupGlobalVar("switchOn");
m_idVarDamageTex = m_shader->LookupVar("damagetexture");
m_idVarBoundRadius = m_shader->LookupVar("BoundRadius");
m_idVarDamageMult = m_shader->LookupVar("DamageMultiplier");
m_idVarOffset = m_shader->LookupVar("DamageTextureOffset");
#endif // USE_GPU_VEHICLEDEFORMATION
}
void CVehicleGlassShader::Shutdown()
{
Assertf(m_shader, "Create not called, or Shutdown called twice");
delete m_shader;
ASSERT_ONLY(m_shader = NULL;)
}
void CVehicleGlassShader::SetShaderVariables(const CVehicleGlassShaderData& data) const
{
m_shader->SetVar(m_idVarDiffuseTex , data.m_DiffuseTex);
m_shader->SetVar(m_idVarDirtTex , data.m_DirtTex);
m_shader->SetVar(m_idVarSpecularTex , data.m_SpecularTex);
m_shader->SetVar(m_idVarSpecularMapIntensityMask, data.m_SpecularMapIntensityMask);
m_shader->SetVar(m_idVarEnvEffTexTileUV , data.m_EnvEffTexTileUV);
m_shader->SetVar(m_idVarEnvEffThickness , data.m_EnvEffThickness);
m_shader->SetVar(m_idVarDirtLevelMod , data.m_DirtLevelMod);
m_shader->SetVar(m_idVarDirtColor , data.m_DirtColor);
m_shader->SetVar(m_idVarDiffuseColorTint , data.m_DiffuseColorTint);
m_shader->SetVar(m_idVarEnvEffScale0 , data.m_EnvEffScale0);
#if USE_GPU_VEHICLEDEFORMATION
if (data.m_bDamageOn && data.m_pDamageTex != NULL)
{
grcEffect::SetGlobalVar((grcEffectGlobalVar)m_idVarDamageSwitchOn, true);
m_shader->SetVar(m_idVarBoundRadius, data.m_fBoundRadius);
m_shader->SetVar(m_idVarDamageMult, data.m_fDamageMultiplier);
m_shader->SetVar(m_idVarDamageTex, data.m_pDamageTex);
m_shader->SetVar(m_idVarOffset, Vector3(0.0, 0.0, 0.0));
}
else
{
grcEffect::SetGlobalVar((grcEffectGlobalVar)m_idVarDamageSwitchOn, false);
m_shader->SetVar(m_idVarDamageTex, const_cast<grcTexture*>(grcTexture::NoneBlack));
}
#endif // USE_GPU_VEHICLEDEFORMATION
}
void CVehicleGlassShader::SetTintVariable(const Vector4& diffuseColorTint) const
{
m_shader->SetVar(m_idVarDiffuseColorTint, diffuseColorTint);
}
void CVehicleGlassShader::ClearShaderVariables() const
{
m_shader->SetVar(m_idVarDiffuseTex , (grcTexture*)NULL);
m_shader->SetVar(m_idVarDirtTex , (grcTexture*)NULL);
m_shader->SetVar(m_idVarSpecularTex , (grcTexture*)NULL);
#if USE_GPU_VEHICLEDEFORMATION
grcEffect::SetGlobalVar((grcEffectGlobalVar)m_idVarDamageSwitchOn, false);
m_shader->SetVar(m_idVarDamageTex , (grcTexture*)NULL);
#endif // USE_GPU_VEHICLEDEFORMATION
}
void CVehicleGlassShader::SetCrackTextureParams(grcTexture* crackTexture, float amount, float scale, float bumpAmount, float bumpiness, Vec4V_In tint) const
{
if (m_idVarCrackTexture != grcevNONE)
{
m_shader->SetVar(m_idVarCrackTexture, (amount > 0.0f) ? crackTexture : grcTexture::None);
}
if (m_idVarCrackTextureParams != grcevNONE)
{
const Vec4V params[] =
{
Vec4V(amount, scale, bumpAmount, bumpiness),
tint
};
m_shader->SetVar(m_idVarCrackTextureParams, params, NELEM(params));
}
}
#if CSE_VEHICLE_EDITABLEVALUES
//
//
//
//
void CCustomShaderEffectVehicle::SetEditableShaderValues(grmShaderGroup *pShaderGroup, rmcDrawable* pDrawable)
{
Assert(pShaderGroup);
if(ms_bEVSpec2DirLerpOverride)
{
Color32 spec2Color = this->GetSpec2Color();
Vector4 spec2ColorV4(spec2Color.GetRedf(), spec2Color.GetGreenf(), spec2Color.GetBluef(), ms_fEVSpec2DirLerp);
SetVector4ShaderGroupVar(pShaderGroup, "Specular2Color", spec2ColorV4);
}
if(!ms_bEVEnabled)
return;
#if 0
// old way of doing things:
if(m_idVarEVSpecFalloff)
pShaderGroup->SetVar(m_idVarEVSpecFalloff, ms_fEVSpecFalloff);
if(m_idVarEVSpecIntensity)
pShaderGroup->SetVar(m_idVarEVSpecIntensity, ms_fEVSpecIntensity);
if(m_idVarEVSpec2Falloff)
pShaderGroup->SetVar(m_idVarEVSpec2Falloff, ms_fEVSpec2Falloff);
// etc., etc.
#endif //#if 0...
// ... and the new way of setting editable shader variables:
SetFloatShaderGroupVar(pShaderGroup, "Fresnel", ms_fEVSpecFresnel);
SetFloatShaderGroupVar(pShaderGroup, "Specular", ms_fEVSpecFalloff);
SetFloatShaderGroupVar(pShaderGroup, "SpecularColor", ms_fEVSpecIntensity);
SetFloatShaderGroupVar(pShaderGroup, "SpecTexTileUV", ms_fEVSpecTexTileUV);
SetFloatShaderGroupVar(pShaderGroup, "Specular2Factor", ms_fEVSpec2Falloff);
SetFloatShaderGroupVar(pShaderGroup, "specular2ColorIntensity", ms_fEVSpec2Intensity);
Color32 spec2Color = this->GetSpec2Color();
Vector4 spec2ColorV4(spec2Color.GetRedf(), spec2Color.GetGreenf(), spec2Color.GetBluef(), ms_fEVSpec2DirLerp);
SetVector4ShaderGroupVar(pShaderGroup, "Specular2Color", spec2ColorV4);
SetFloatShaderGroupVar(pShaderGroup, "Reflectivity", ms_fEVReflectivity);
SetFloatShaderGroupVar(pShaderGroup, "Bumpiness", ms_fEVBumpiness);
SetFloatShaderGroupVar(pShaderGroup, "DiffuseTexTileUV", ms_fEVDiffuseTexTileUV);
const float dirtModulator = rage::Lerp(rage::Clamp(g_weather.GetWetness(),0.0f,1.0f), ms_fEVDirtModDry, ms_fEVDirtModWet);
SetVector4ShaderGroupVar(pShaderGroup, "DirtLevelMod", Vector4(ms_fEVDirtLevel,dirtModulator,(float)ms_fEVDirtOrBurnout,1.0f));
SetVector3ShaderGroupVar(pShaderGroup, "DirtColor", ms_fEVDirtColor);
SetFloatShaderGroupVar(pShaderGroup, "envEffThickness0", ms_fEVEnvEffThickness);
SetVector2ShaderGroupVar(pShaderGroup, "envEffScale0", Vector2(ms_fEVEnvEffScale, ms_fEVEnvEffScale / 1000.0f));
SetFloatShaderGroupVar(pShaderGroup, "envEffTexTileUV", ms_fEVEnvEffTexTileUV);
SetVector4ShaderGroupVar(pShaderGroup, "LetterIndex1", ms_fEVLetterIndex1);
SetVector4ShaderGroupVar(pShaderGroup, "LetterIndex2", ms_fEVLetterIndex2);
SetVector2ShaderGroupVar(pShaderGroup, "LetterSize", ms_fEVLetterSize);
SetVector2ShaderGroupVar(pShaderGroup, "NumLetters", ms_fEVNumLetters);
SetVector4ShaderGroupVar(pShaderGroup, "LicensePlateFontExtents", ms_fEVLicensePlateFontExtents);
SetVector4ShaderGroupVar(pShaderGroup, "LicensePlateFontTint", ms_fEVLicensePlateFontTint);
SetFloatShaderGroupVar(pShaderGroup, "FontNormalScale", ms_fEVFontNormalScale);
SetFloatShaderGroupVar(pShaderGroup, "DistMapCenterVal", ms_fEVDistMapCenterVal);
SetVector4ShaderGroupVar(pShaderGroup, "DistEpsilonScaleMin", ms_fEVDistEpsilonScaleMin);
SetVector3ShaderGroupVar(pShaderGroup, "FontOutlineMinMaxDepthEnabled", ms_fEVFontOutlineMinMaxDepthEnabled);
SetVector3ShaderGroupVar(pShaderGroup, "FontOutlineColor", ms_fEVFontOutlineColor);
if(ms_fEVOverrideDiffuseColorTint)
{
SetVector4ShaderGroupVar(pShaderGroup, "DiffuseColorTint", Vector4(ms_fEVDiffuseColorTint.x, ms_fEVDiffuseColorTint.y, ms_fEVDiffuseColorTint.z, ms_fEVDiffuseColorTintAlpha) );
}
// set body color 0:
CCustomShaderEffectVehicleType::structDiffColEffect *ptr = &GetCseTypeInternal()->m_DiffColEffect[0];
if(ms_fEVOverrideBodyColor)
{
pDrawable->GetShaderGroup().GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarDiffColor, ms_fEVBodyColor);
}
else
{
pDrawable->GetShaderGroup().GetShader(ptr->shaderIdx).SetVar((grcEffectVar)ptr->idvarDiffColor, m_varDifCol[ptr->colorIdx]);
}
}// end of SetEditableShaderValues()...
//
//
//
//
bool CCustomShaderEffectVehicle::InitWidgets(bkBank& bank)
{
// debug widgets:
bank.PushGroup("Vehicle Editable Inner Tyre Radius", false);
bank.AddToggle("Enable", &ms_bEWREnabled);
bank.AddToggle("Tyre rendering enable", &ms_bEWRTyreEnabled);
bank.AddSlider("Inner radius (divide it by 10 for real value)", &ms_fEWRInnerRadius, 0.0f, 50.0f, 0.001f);
bank.PopGroup();
bank.PushGroup("Vehicle Editable Shaders Values", false);
bank.AddToggle("Enable", &ms_bEVEnabled);
bank.AddSlider("Specular falloff", &ms_fEVSpecFalloff, 0.0f, 512.0f, 0.1f);
bank.AddSlider("Specular Fresnel", &ms_fEVSpecFresnel, 0.0f, 1.0f, 0.01f);
bank.AddSlider("Specular intensity", &ms_fEVSpecIntensity, 0.0f, 1.0f, 0.01f);
bank.AddSlider("Spec Texture TileUV", &ms_fEVSpecTexTileUV, 1.0f, 32.0f, 0.1f);
bank.AddSlider("Specular 2 falloff", &ms_fEVSpec2Falloff, 0.0f, 512.0f, 0.1f);
bank.AddSlider("Specular 2 intensity", &ms_fEVSpec2Intensity, 0.0f, 3.0f, 0.1f);
bank.AddSlider("Specular 2 dir (0=GlobalDirLight, 1=Up)", &ms_fEVSpec2DirLerp, 0.0f, 1.0f, 0.01f);
bank.AddSlider("Reflectivity", &ms_fEVReflectivity, 0, 100.0f, 0.1f);
bank.AddSlider("Bumpiness", &ms_fEVBumpiness, 0, 10.0f, 0.01f);
bank.AddToggle("Override Body Color", &ms_fEVOverrideBodyColor);
bank.AddColor("Body Color 0", &ms_fEVBodyColor);
bank.AddToggle("Override Diffuse Color Tint", &ms_fEVOverrideDiffuseColorTint);
bank.AddColor("Diffuse Tint RGB", &ms_fEVDiffuseColorTint);
bank.AddSlider("Diffuse Tint Alpha", &ms_fEVDiffuseColorTintAlpha, 0.0f, 1.0f, 0.01f);
bank.AddSlider("Diffuse Texture TileUV", &ms_fEVDiffuseTexTileUV, 1.0f, 32.0f, 0.1f);
bank.AddSlider("Dirt Level", &ms_fEVDirtLevel, 0.0f, 1.0f, 0.1f);
bank.AddSlider("Dirt Color Intensity (Dry)", &ms_fEVDirtModDry, 0.0f, 1.0f, 0.1f);
bank.AddSlider("Dirt Color Intensity (Wet)", &ms_fEVDirtModWet, 0.0f, 1.0f, 0.1f);
bank.AddSlider("Mode: Dirt (1) / Burnout (0)", &ms_fEVDirtOrBurnout, 0, 1, 1);
bank.AddColor("Dirt Color", &ms_fEVDirtColor);
bank.AddSlider("EnvEff: Scale", &ms_fEVEnvEffScale, 0.0f, 1.0f, 0.1f);
bank.AddSlider("EnvEff: Thickness", &ms_fEVEnvEffThickness, 0.0f, 100.0f, 0.1f);
bank.AddSlider("EnvEff: Texture TileUV", &ms_fEVEnvEffTexTileUV, 1.0f, 32.0f, 0.1f);
bank.PushGroup("2nd Spec Direction");
bank.AddToggle("Override", &ms_bEVSpec2DirLerpOverride);
bank.AddSlider("Spec 2 direction (0=GlobalDirLight, 1=Up)", &ms_fEVSpec2DirLerp, 0.0f, 1.0f, 0.01f);
bank.PopGroup();
bank.PushGroup("Plate:", false);
bank.AddSlider("LetterIndex1", &ms_fEVLetterIndex1, 0.0f, 255.0f, 1.0f);
bank.AddSlider("LetterIndex2", &ms_fEVLetterIndex2, 0.0f, 255.0f, 1.0f);
bank.AddSlider("LetterSize", &ms_fEVLetterSize, 0.0f, 1.0f, 0.1f);
bank.AddSlider("NumLetters", &ms_fEVNumLetters, 0.0f, 255.0f, 1.0f);
bank.AddSlider("LicensePlateFontExtents", &ms_fEVLicensePlateFontExtents, 0.0f, 1.0f,0.1f);
bank.AddColor( "LicensePlateFontTint", &ms_fEVLicensePlateFontTint);
bank.AddSlider("FontNormalScale", &ms_fEVFontNormalScale, 0.0f, 100.0f, 0.1f);
bank.AddSlider("DistMapCenterVal", &ms_fEVDistMapCenterVal, 0.0f, 1.0f, 0.1f);
bank.AddSlider("DistEpsilonScaleMin", &ms_fEVDistEpsilonScaleMin, 0.0f, 50.0f, 1.0f);
bank.AddSlider("FontOutlineMinMaxDepthEnabled", &ms_fEVFontOutlineMinMaxDepthEnabled, 0.0f, 1.0f, 0.1f);
bank.AddColor( "FontOutlineColor", &ms_fEVFontOutlineColor);
bank.PopGroup();
bank.PopGroup();
bank.PushGroup("Vehicle Burnout VFX", false);
bank.AddSlider("Burnout VFX speed", &ms_fEVBurnoutSpeed, 1.0f/255.0f, 1.0f, 1.0f/255.0f);
bank.PopGroup();
bank.PushGroup("Vehicle Sun Glare Fx", false);
bank.AddToggle("Enable", &ms_bEVSunGlareEnabled);
bank.AddSlider("Fade min distance", &ms_fEVSunGlareDistMin, 0.0f, 100.0f, 0.1f);
bank.AddSlider("Fade max distance", &ms_fEVSunGlareDistMax, 0.0f, 100.0f, 0.1f);
bank.AddSlider("Sun glare spec power", &ms_nEVSunGlarePow, 1, 96, 1);
bank.AddSlider("Sprite size", &ms_fEVSunGlareSpriteSize, 0.0f, 2.0f, 0.01f);
bank.AddSlider("Sprite Z shift scale", &ms_fEVSunGlareSpriteZShiftScale, 0.0f, 1.0f, 0.05f);
bank.AddSlider("Sprite intensity", &ms_fEVSunGlareHdrMult, 0.0f, 16.0f, 0.1f);
bank.PopGroup();
#if VEHICLE_SUPPORT_PAINT_RAMP
bank.PushGroup("Vehicle Chameleon Paint");
bank.AddToggle("Enable Debug Ramp", &s_DebugRampTextureEnabled, ReloadDebugRampTexture);
bank.AddText("Debug Ramp Path", &s_DebugRampTexturePath[0], sizeof(s_DebugRampTexturePath) - 1, false, ReloadDebugRampTexture);
bank.AddButton("Reload Debug Ramp", ReloadDebugRampTexture);
bank.AddToggle("Diffuse Ramp Enabled", &s_RampDiffuseEnabled);
bank.AddToggle("Specular Ramp Enabled", &s_RampSpecularEnabled);
bank.PopGroup();
#endif
return(TRUE);
}// end of InitWidgets()...
#endif //CSE_VEHICLE_EDITABLEVALUES...