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

2011 lines
78 KiB
C++

//
// Filename: CustomShaderEffectPed.cpp
// Description: Class for controlling bone damage display in ped shaders;
// Written by: Andrzej
//
// 10/08/2005 - Andrzej: - initial;
// 30/09/2005 - Andrzej: - update to Rage WR146;
// 06/04/2006 - Andrzej: - added support for CLONE_EFFECTS=0;
// 02/04/2009 - Andrzej: - added support for ped_enveff (snow scale);
// 30/06/2010 - Andrzej: - added support for ped_fat (fat scale);
//
//
//
// Rage headers
#include "grmodel\ShaderFx.h"
#include "grmodel\Geometry.h"
#include "grcore\effect_config.h" // edge
#include "grcore/texturereference.h"
#include "creature/creature.h"
#include "creature/componentshadervars.h"
#include "creature/componentblendshapes.h"
#include "grblendshapes/manager.h"
#include "pheffects/wind.h"
#include "rmcore/drawable.h"
#include "fwdrawlist/drawlistmgr.h"
// Game headers
#include "camera\viewports\viewportmanager.h"
#include "debug\debug.h"
#include "scene\Entity.h"
#include "modelinfo\PedModelInfo.h"
#include "peds\Ped.h"
#include "peds/PopCycle.h"
#include "peds\rendering\PedDamage.h"
#include "peds\rendering\PedOverlay.h"
#include "peds\rendering\pedVariationPack.h"
#include "vehicleAi\task\TaskVehicleAnimation.h"
#include "renderer/Water.h"
#include "renderer/Mirrors.h"
#include "renderer\RenderPhases/RenderPhaseFX.h"
#include "renderer\Deferred\DeferredLighting.h"
#include "vfx\Systems\VfxFire.h"
#include "CustomShaderEffectPed.h"
#include "camera/cutscene/CutsceneDirector.h"
#include "Cutscene/CutSceneCameraEntity.h"
#include "camera\CamInterface.h"
#include "timecycle\TimeCycle.h"
#include "Vfx\Misc\Fire.h"
#include "vehicles/vehicle.h"
#include "ShaderHairSort.h"
#include "shader_source/Peds/ped_common_values.h"
#if __BANK
#include "peds/rendering/PedVariationDebug.h"
#include "shaders/ShaderEdit.h"
#endif
#include "system/findsize.h"
// FindSize(CCustomShaderEffectBase); // 16
// FindSize(CCustomShaderEffectPed);
// 2512, zoiks!
// 2368 with texture registry.
// 1968 with u16 blend weight.
// 816 with bone array nobody uses removed?
// 656 with wrinkle maps packed from floats to u8's
// 640 with proper separation of "type" and "per instance" data (sigh)
// 224 by basically disabling blendshape weights; code is supposed to know when creating instance whether it needs blendshapes or not.
// 176 by deleting unused textures, rearranging by size, and doing ped color scale entirely based on config bools
// 192 by packing 4xfloat vars into packed 4xubytes
// 208 with extra 2 wrinkle masks
// 224 with um override params
#if !PGHANDLEINDEX_IS_A_PGHANDLE && !GRCTEXTUREHANDLE_IS_PGREF// PGHANDLEINDEX_IS_A_PGHANDLE is going to bloat things, but don't really care by how much
CompileTimeAssertSize(CCustomShaderEffectPed,272,320);
#endif
#define PED_DEFAULT_WIND_MOTION_AMP_X (5.0f)
#define PED_DEFAULT_WIND_MOTION_AMP_Y (3.0f)
#define PED_DEFAULT_WIND_MOTION_FREQ (0.8f)
#define PED_DEFAULT_WIND_RESPONSE_VEL_MIN (1.0f)
#define PED_DEFAULT_WIND_RESPONSE_VEL_MAX (100.0f)
#define PED_DEFAULT_WIND_FLUTTER_INTENSITY (4.0f)
#if CSE_PED_EDITABLEVALUES
bool CCustomShaderEffectPed::ms_bEVEnabled = false;
float CCustomShaderEffectPed::ms_fEVSpecFalloff = 250.0f;
float CCustomShaderEffectPed::ms_fEVSpecIntensity = 1.0f;
float CCustomShaderEffectPed::ms_fEVSpecFresnel = 0.950f;
float CCustomShaderEffectPed::ms_fEVReflectivity = 0.45f;
float CCustomShaderEffectPed::ms_fEVBumpiness = 0.75f;
float CCustomShaderEffectPed::ms_fEVBurnoutLevelSpeed = 0.02f;
float CCustomShaderEffectPed::ms_fEVDetailIntensity = 0.1f;;
float CCustomShaderEffectPed::ms_fEVDetailBumpIntensity = 0.750f;
float CCustomShaderEffectPed::ms_fEVDetailScale = 60.0f;
float CCustomShaderEffectPed::ms_fEVEnvEffScale = 0.0f;
float CCustomShaderEffectPed::ms_fEVEnvEffCpvAdd = 0.0f;
float CCustomShaderEffectPed::ms_fEVEnvEffThickness = 25.0f;
Color32 CCustomShaderEffectPed::ms_fEVEnvEffColorMod = Color32(255,255,255,255);
float CCustomShaderEffectPed::ms_fEVEnvEffZoneScale = 0.0f;
u32 CCustomShaderEffectPed::ms_fEVEnvEffZoneColorModR = 255;
u32 CCustomShaderEffectPed::ms_fEVEnvEffZoneColorModG = 255;
u32 CCustomShaderEffectPed::ms_fEVEnvEffZoneColorModB = 255;
float CCustomShaderEffectPed::ms_fEVFatScale = 0.0f;
float CCustomShaderEffectPed::ms_fEVFatThickness = 25.0f;
float CCustomShaderEffectPed::ms_fEVSweatScale = 0.0f;
float CCustomShaderEffectPed::ms_fEVNormalBlend = 0.0f;
float CCustomShaderEffectPed::ms_fEVStubbleStrength = 0.8f;
float CCustomShaderEffectPed::ms_fEVStubbleIndex = 10.0f;
float CCustomShaderEffectPed::ms_fEVStubbleTile = 1.f;
Vector4 CCustomShaderEffectPed::ms_fEVUmGlobalParams = Vector4(0.0025f, 0.0025f, 7.000f, 7.000f);
bool CCustomShaderEffectPed::ms_bEVUseUmGlobalOverrideValues = false;
Vector4 CCustomShaderEffectPed::ms_fEVUmGlobalOverrideParams = Vector4(1.0f, 1.0f, 1.0f, 1.0f);
bool CCustomShaderEffectPed::ms_bEVWindMotionEnabled = true;
float CCustomShaderEffectPed::ms_fEVWindMotionAmpX = PED_DEFAULT_WIND_MOTION_AMP_X;
float CCustomShaderEffectPed::ms_fEVWindMotionAmpY = PED_DEFAULT_WIND_MOTION_AMP_Y;
float CCustomShaderEffectPed::ms_fEVWindMotionFreq = PED_DEFAULT_WIND_MOTION_FREQ;
bool CCustomShaderEffectPed::ms_bEVWindResponseEnabled = true;
float CCustomShaderEffectPed::ms_fEVWindResponseVelMin = PED_DEFAULT_WIND_RESPONSE_VEL_MIN;
float CCustomShaderEffectPed::ms_fEVWindResponseVelMax = PED_DEFAULT_WIND_RESPONSE_VEL_MAX;
float CCustomShaderEffectPed::ms_fEVWindFlutterIntensity = PED_DEFAULT_WIND_FLUTTER_INTENSITY;
Vector2 CCustomShaderEffectPed::ms_fEVAnisotropicSpecularIntensity = Vector2(0.1f, 0.15f);
Vector2 CCustomShaderEffectPed::ms_fEVAnisotropicSpecularExponent = Vector2(16.0f, 32.0f);
Color32 CCustomShaderEffectPed::ms_fEVAnisotropicSpecularColour = Color32(25, 25, 25, 255);
Vector4 CCustomShaderEffectPed::ms_fEVSpecularNoiseMapUVScaleFactor = Vector4(2.0f, 1.0f, 3.0f, 1.0f);
float CCustomShaderEffectPed::ms_fEVAnisotropicAlphaBias = 1.0f;
#define SHADER_SETTINGS_FNAME "x:\\ped_shader_settings.txt"
extern char* GetPedVariationMgrDrawableName(); // defined in PedVariationMgr.cpp
extern s32 GetPedVariationMgrDrawableNameLen(); // defined in PedVariationMgr.cpp
#endif //CSE_PED_EDITABLEVALUES...
Vector4 CCustomShaderEffectPed::ms_fEVWetClothesAdjust = Vector3(0.35f, 8.0f, 0.35f, 0.1f);
Vector4 CCustomShaderEffectPed::ms_fEVWetClothesAdjustMoreWet = Vector3(0.656f, 16.1f, 0.40f, 0.205f);
Vector4 CCustomShaderEffectPed::ms_fEVWetClothesAdjustLessWet = Vector3(0.157f, 8.8f, 0.1f, 0.104f);
static BankBool g_UsePedShaderVarCaching = true;
bool CCustomShaderEffectPed::ms_EnableShaderVarCaching[NUMBER_OF_RENDER_THREADS] = { false };
CCustomShaderEffectPed::CCachedCSEPedShaderVars CCustomShaderEffectPed::ms_CachedCSEPedShaderVars[NUMBER_OF_RENDER_THREADS];
Vector2 CCustomShaderEffectPed::ms_DetailFadeOut[2] = { Vector2(1.7f,1.8f), // std
Vector2(20.0f,21.f) // burnout
};
static s8 s_wrinkleTrans[] =
{
0, // PV_COMP_HEAD = 0,
-1, // PV_COMP_BERD,
-1, // PV_COMP_HAIR,
1, // PV_COMP_UPPR,
2, // PV_COMP_LOWR,
3, // PV_COMP_HAND,
-1, // PV_COMP_FEET,
-1, // PV_COMP_TEEF,
-1, // PV_COMP_ACCS,
-1, // PV_COMP_TASK,
-1, // PV_COMP_DECL,
-1, // PV_COMP_JBIB,
-1 // PV_MAX_COMP
};
#if __BANK
bool CCustomShaderEffectPed::ms_bBlendshapeForceAll = false;
bool CCustomShaderEffectPed::ms_bBlendshapeForceSpecific = false;
int CCustomShaderEffectPed::ms_nBlendshapeForceSpecificIdx = 0;
float CCustomShaderEffectPed::ms_fBlendshapeForceSpecificBlend= 1.0f;
bool CCustomShaderEffectPed::ms_wrinkleEnableOverride = false;
bool CCustomShaderEffectPed::ms_wrinkleEnableSliders = false;
Vector4 CCustomShaderEffectPed::ms_wrinkleMaskStrengths[6] = {0};
int CCustomShaderEffectPed::ms_wrinkleDebugComponent = 0;
atArray<const char*> CCustomShaderEffectPed::ms_wrinkleDebugComponentStrings;
bool g_useOptimisedCutsceneTechnique = true;
#endif // __BANK
#if __ASSERT
static s32 s_ComponentID = 0;
char* CCustomShaderEffectPed_EntityName = NULL; // entity name for debugging purposes only:
static void ASSERTMSG_DETAILED(u8 assertCondition, const char *varName, s32 componentID)
{
if(assertCondition)
return; // nothing to do?
const char* componentName;
switch(componentID)
{
case(PV_COMP_HEAD): componentName="head"; break;
case(PV_COMP_UPPR): componentName="uppr"; break;
case(PV_COMP_LOWR): componentName="lowr"; break;
case(PV_COMP_HAND): componentName="hand"; break;
case(PV_COMP_FEET): componentName="feet"; break;
case(PV_COMP_HAIR): componentName="hair"; break;
default: componentName="unknown";break;
}
Assertf(assertCondition, "Object '%s', component %d ('%s'): %s variable not found!",CCustomShaderEffectPed_EntityName,s_ComponentID,componentName,varName);
}
#endif // __ASSERT...
//
//
//
//
inline u8 PedShaderGroupLookupVar(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 PedEffectLookupGlobalVar(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 CCustomShaderEffectPedType::Initialise(rmcDrawable *pDrawable)
{
Assert(pDrawable);
// make sure array indices are correct:
Assert(PV_COMP_HEAD < PV_COMP_UPPR);
Assert(PV_COMP_UPPR < PV_COMP_LOWR);
Assert(PV_COMP_LOWR < PV_MAX_COMP);
grmShaderGroup *pShaderGroup = &pDrawable->GetShaderGroup();
Assert(pShaderGroup);
// find indices to variables changed by this class, etc.
#if __ASSERT
#define GET_SHADER_VAR_INDEX(I, NAME, PRINTASSERT) { I = PedShaderGroupLookupVar(pShaderGroup,NAME, FALSE); if(PRINTASSERT) ASSERTMSG_DETAILED(I, NAME, s_ComponentID); }
#else
#define GET_SHADER_VAR_INDEX(I, NAME, PRINTASSERT) { I = PedShaderGroupLookupVar(pShaderGroup,NAME, FALSE); if(PRINTASSERT) { Assert(I); } }
#endif
GET_SHADER_VAR_INDEX(m_idVarDiffuseTex, "DiffuseTex", TRUE);
GET_SHADER_VAR_INDEX(m_idVarNormalTex, "BumpTex", TRUE);
GET_SHADER_VAR_INDEX(m_idVarSpecularTex, "SpecularTex", TRUE);
m_idVarMaterialColorScale = PedEffectLookupGlobalVar("MaterialColorScale", TRUE);
m_idVarWetClothesData = PedEffectLookupGlobalVar("WetClothesData", TRUE);
m_idVarPedBloodTarget = PedEffectLookupGlobalVar("pedBloodTarget", TRUE);
m_idVarPedTattooTarget = PedEffectLookupGlobalVar("pedTattooTarget", TRUE);
m_idVarPedDamageData = PedEffectLookupGlobalVar("PedDamageData", TRUE);
m_idVarPedDamageColors = PedEffectLookupGlobalVar("pedDamageColors", FALSE); // depends on USE_VARIABLE_BLOOD_COLORS=1 in ped_common.fxh
m_idVarWetnessAdjust = PedEffectLookupGlobalVar("WetnessAdjust", TRUE);
m_idVarAlphaToCoverageScale = PedEffectLookupGlobalVar("AlphaToCoverageScale", FALSE);
m_idVarDiffuseTexPal = PedEffectLookupGlobalVar("DiffuseTexPal", TRUE);
m_idVarDiffuseTexPalSelector = PedEffectLookupGlobalVar("DiffuseTexPaletteSelector", TRUE);
m_idVarEnvEffFatSweatScale = PedEffectLookupGlobalVar("envEffFatSweatScale0", TRUE);
m_idVarEnvEffColorModCpvAdd = PedEffectLookupGlobalVar("envEffColorModCpvAdd0", TRUE);
#if __XENON
m_idVarClothParentMatrix = PedShaderGroupLookupVar(pShaderGroup, "clothParentMatrix", TRUE);
#endif // __XENON
#if __WIN32PC || RSG_DURANGO || RSG_ORBIS
m_idVarClothParentMatrix = PedEffectLookupGlobalVar("clothParentMatrix", TRUE);
m_idVarClothVertices = PedEffectLookupGlobalVar("clothVertices", FALSE); // optional
#endif
m_idVarWrinkleMaskStrengths0 = PedEffectLookupGlobalVar("WrinkleMaskStrengths0", TRUE);
m_idVarWrinkleMaskStrengths1 = PedEffectLookupGlobalVar("WrinkleMaskStrengths1", TRUE);
m_idVarWrinkleMaskStrengths2 = PedEffectLookupGlobalVar("WrinkleMaskStrengths2", TRUE);
m_idVarWrinkleMaskStrengths3 = PedEffectLookupGlobalVar("WrinkleMaskStrengths3", TRUE);
m_idVarWrinkleMaskStrengths4 = PedEffectLookupGlobalVar("WrinkleMaskStrengths4", TRUE);
m_idVarWrinkleMaskStrengths5 = PedEffectLookupGlobalVar("WrinkleMaskStrengths5", TRUE);
m_idVarStubbleGrowthDetailScale = PedEffectLookupGlobalVar("StubbleGrowth", TRUE);
m_idVarUmGlobalOverrideParams = PedEffectLookupGlobalVar("umPedGlobalOverrideParams0", TRUE);
m_bIsPaletteShader = bool(pShaderGroup->LookupShader("ped_palette") != 0);
m_bIsFurShader = bool(pShaderGroup->LookupShader("ped_fur") != 0);
#undef GET_SHADER_VAR_INDEX
return(TRUE);
}// end of CCustomShaderEffectPedType::Initialise()...
//
//
//
//
CCustomShaderEffectBase* CCustomShaderEffectPedType::CreateInstance(CEntity* UNUSED_PARAM(pEntity))
{
// TODO - figure out how to determine this at instantiation time.
bool hasWeights = false;
u32 size = sizeof(CCustomShaderEffectPed) + (hasWeights? sizeof(CCustomShaderEffectPed::ComponentBlendWeights) : 0);
CCustomShaderEffectPed *pNewShaderEffect = rage_placement_new(rage_alignof_new(CCustomShaderEffectPed) u8[size]) CCustomShaderEffectPed(size);
if (hasWeights)
{
pNewShaderEffect->m_bHasBlendshapes = TRUE;
CCustomShaderEffectPed::ComponentBlendWeights *blendWeights = (CCustomShaderEffectPed::ComponentBlendWeights*)(pNewShaderEffect + 1);
blendWeights[0].m_Exists = false; // MAX_PED_COMPONENTS
blendWeights[0].m_Processed = false; // MAX_PED_COMPONENTS
}
pNewShaderEffect->m_pType = this;
// everything else is initialized by the ctor already
return(pNewShaderEffect);
}
//
// name: CCustomShaderEffectPed::AreShadersValid
// description: Return if drawable has valid shaders for this shader effect
//
#if __DEV
bool CCustomShaderEffectPedType::AreShadersValid(rmcDrawable* pDrawable)
{
bool bShadersOK = TRUE;
Assert(pDrawable);
if(!pDrawable)
return(FALSE);
grmShaderGroup *pShaderGroup = &pDrawable->GetShaderGroup();
Assert(pShaderGroup);
if(!pShaderGroup)
return(FALSE);
const s32 shaderCount = pShaderGroup->GetCount();
Assert(shaderCount >= 1);
for(s32 j=0; j<shaderCount; j++)
{
grmShader *pShader = &pShaderGroup->GetShader(j);
Assert(pShader);
const char *pShaderName = pShader->GetName();
if( ::strcmpi(pShaderName, "ped") &&
::strcmpi(pShaderName, "ped_alpha") &&
::strcmpi(pShaderName, "ped_cloth") &&
::strcmpi(pShaderName, "ped_decal") &&
::strcmpi(pShaderName, "ped_decal_decoration") &&
::strcmpi(pShaderName, "ped_decal_exp") &&
::strcmpi(pShaderName, "ped_decal_medals") &&
::strcmpi(pShaderName, "ped_decal_nodiff") &&
::strcmpi(pShaderName, "ped_default") &&
::strcmpi(pShaderName, "ped_default_cloth") &&
::strcmpi(pShaderName, "ped_default_enveff") &&
::strcmpi(pShaderName, "ped_default_palette") &&
::strcmpi(pShaderName, "ped_emissive") &&
::strcmpi(pShaderName, "ped_enveff") &&
::strcmpi(pShaderName, "ped_fur") &&
::strcmpi(pShaderName, "ped_hair_cutout_alpha") &&
::strcmpi(pShaderName, "ped_hair_cutout_alpha_cloth") &&
::strcmpi(pShaderName, "ped_hair_spiked") &&
::strcmpi(pShaderName, "ped_hair_spiked_enveff") &&
::strcmpi(pShaderName, "ped_hair_spiked_mask") &&
::strcmpi(pShaderName, "ped_palette") &&
::strcmpi(pShaderName, "ped_stubble") &&
::strcmpi(pShaderName, "ped_wrinkle") &&
::strcmpi(pShaderName, "ped_wrinkle_cloth") &&
::strcmpi(pShaderName, "ped_wrinkle_cs") &&
::strcmpi(pShaderName, "default") )
{
// bad shader found!
bShadersOK = FALSE;
break;
}
}
return(bShadersOK);
}
#endif //__DEV...
//
//
//
//
CCustomShaderEffectPed::CCustomShaderEffectPed(u32 size) : CCustomShaderEffectBase(size, CSE_PED)
{
for(s32 i=0; i<MAX_PED_COMPONENTS;i++)
{
m_varhDiffuseTex[i] = 0;
m_varhDiffuseTexPal[i] = 0;
m_varDiffuseTexPalSelector[i] = 0;
m_varhNormalTex[i] = 0;
m_varhSpecularTex[i] = 0;
}
m_secondHairPalSelector = 0;
this->SetEnvEffScale(0.0f);
this->SetFatScale(0.0f);
this->SetStubbleGrowth(0.0f);
this->SetSweatScale(0.0f);
this->SetEnvEffColorModulator(255,255,255);
this->SetEnvEffCpvAdd(0.0f);
SetUmGlobalOverrideParams(1.0f, 1.0f, 1.0f, 1.0f);
m_varWetClothesData.Set(-2,-2,0,0);
m_bRenderBurnout = FALSE;
m_bRenderVehBurnout = FALSE;
this->SetBurnoutLevel(0.0f);
this->SetEmissiveScale(1.0f);
m_bRenderDead = FALSE;
m_bTriggeredSmokeFx = FALSE;
m_bHasBlendshapes = FALSE;
m_bCustomEnvEffScale = FALSE;
m_varHeat = 255;
m_PedBloodTarget = NULL;
m_PedTattooTarget = NULL;
m_PedTattooTargetOverride = NULL;
m_PedDamageData.Set(0,0,0,0);
m_usePedDamageInMirror = false;
sysMemSet(m_wrinkleMaskStrengths, 0x00, sizeof(m_wrinkleMaskStrengths));
// these need to be the same!
CompileTimeAssert(MAX_PED_COMPONENTS == PV_MAX_COMP);
m_pType = NULL;
}
//
//
//
//
CCustomShaderEffectPed::~CCustomShaderEffectPed()
{
for (int i=0; i<MAX_PED_COMPONENTS; i++)
ClearTextures(i);
}
//
//
//
//
void CCustomShaderEffectPed::InitClass()
{
InvalidateShaderVarCache();
}
//
//
//
//
void CCustomShaderEffectPed::InvalidateShaderVarCache()
{
for(int i=0; i<NUMBER_OF_RENDER_THREADS; i++)
{
ms_CachedCSEPedShaderVars[i].PedBloodTarget = 0;
ms_CachedCSEPedShaderVars[i].PedTattooTarget = 0;
ms_CachedCSEPedShaderVars[i].DiffuseTexPal = 0;
ms_CachedCSEPedShaderVars[i].DiffuseTexPalSelector = 0;
ms_CachedCSEPedShaderVars[i].MaterialColorScale[0] = Vec4V(V_ZERO);
ms_CachedCSEPedShaderVars[i].MaterialColorScale[1] = Vec4V(V_ZERO);
ms_CachedCSEPedShaderVars[i].WetClothesData = Vec4V(V_ZERO);
ms_CachedCSEPedShaderVars[i].WetnessAdjust = Vec4V(V_ZERO);
ms_CachedCSEPedShaderVars[i].PedDamageData = Vec4V(V_ZERO);
ms_CachedCSEPedShaderVars[i].EnvEffFatSweatScale = Vec4V(V_ZERO);
ms_CachedCSEPedShaderVars[i].EnvEffColorMod_CpvAdd = Vec4V(V_ZERO);
ms_CachedCSEPedShaderVars[i].PedDamageColors[0] =
ms_CachedCSEPedShaderVars[i].PedDamageColors[1] =
ms_CachedCSEPedShaderVars[i].PedDamageColors[2] = Vec4V(V_ZERO);
ms_CachedCSEPedShaderVars[i].WrinkleMaskStrenghts[0] =
ms_CachedCSEPedShaderVars[i].WrinkleMaskStrenghts[1] =
ms_CachedCSEPedShaderVars[i].WrinkleMaskStrenghts[2] =
ms_CachedCSEPedShaderVars[i].WrinkleMaskStrenghts[3] =
ms_CachedCSEPedShaderVars[i].WrinkleMaskStrenghts[4] =
ms_CachedCSEPedShaderVars[i].WrinkleMaskStrenghts[5] = Vec4V(V_ZERO);
ms_CachedCSEPedShaderVars[i].StubbleGrowthDetScale = Vec2V(V_ZERO);
ms_CachedCSEPedShaderVars[i].umGlobalOverrideParams.x.SetFloat16_Zero();
ms_CachedCSEPedShaderVars[i].umGlobalOverrideParams.y.SetFloat16_Zero();
ms_CachedCSEPedShaderVars[i].umGlobalOverrideParams.z.SetFloat16_Zero();
ms_CachedCSEPedShaderVars[i].umGlobalOverrideParams.w.SetFloat16_Zero();
}
}
//
// special version for PedVariationMgr:
// it's called from CPedVariationInfo::GetShaderEffectType()
//
CCustomShaderEffectBaseType* CCustomShaderEffectPed::SetupForDrawableComponent(rmcDrawable* pDrawable, s32 ASSERT_ONLY(componentID), CCustomShaderEffectBaseType *pShaderEffectType)
{
Assert(componentID >= 0);
Assert(componentID < MAX_PED_COMPONENTS);
#if __ASSERT
s_ComponentID = componentID; // save component ID for Initialise() below
#endif
if(!pShaderEffectType) // create shader effect only once
{
pShaderEffectType = CCustomShaderEffectBaseType::SetupForDrawable(pDrawable, MI_TYPE_PED, NULL);
}
else
{ // hack for Rage:
// call for variables look-up routines at least once per Drawable to initialize internal ShaderGroup var arrays:
CCustomShaderEffectBaseType *pTempShaderEffectType = CCustomShaderEffectBaseType::SetupForDrawable(pDrawable, MI_TYPE_PED, NULL);
if(pTempShaderEffectType)
{
Assert(pShaderEffectType);
CCustomShaderEffectPedType* pTempPedEffectType = static_cast<CCustomShaderEffectPedType*>(pTempShaderEffectType);
CCustomShaderEffectPedType* pPedEffectType = static_cast<CCustomShaderEffectPedType*>(pShaderEffectType);
// safety check whether shaderGroupVars match for both ped component drawables:
#define ASSERT_COMPARE_VAR(VARNAME) Assertf((static_cast<CCustomShaderEffectPedType*>(pTempShaderEffectType))->VARNAME == (static_cast<CCustomShaderEffectPedType*>(pShaderEffectType))->VARNAME, "CSE Ped: Incompatible shaderGroupVar "#VARNAME" found for ped component %d.",componentID);
ASSERT_COMPARE_VAR(m_idVarDiffuseTex);
ASSERT_COMPARE_VAR(m_idVarDiffuseTexPal);
ASSERT_COMPARE_VAR(m_idVarDiffuseTexPalSelector);
ASSERT_COMPARE_VAR(m_idVarWrinkleMaskStrengths0);
ASSERT_COMPARE_VAR(m_idVarWrinkleMaskStrengths1);
ASSERT_COMPARE_VAR(m_idVarWrinkleMaskStrengths2);
ASSERT_COMPARE_VAR(m_idVarWrinkleMaskStrengths3);
ASSERT_COMPARE_VAR(m_idVarWrinkleMaskStrengths4);
ASSERT_COMPARE_VAR(m_idVarWrinkleMaskStrengths5);
ASSERT_COMPARE_VAR(m_idVarMaterialColorScale);
ASSERT_COMPARE_VAR(m_idVarEnvEffFatSweatScale);
ASSERT_COMPARE_VAR(m_idVarEnvEffColorModCpvAdd);
ASSERT_COMPARE_VAR(m_idVarWetClothesData);
ASSERT_COMPARE_VAR(m_idVarWetnessAdjust);
ASSERT_COMPARE_VAR(m_idVarPedBloodTarget);
ASSERT_COMPARE_VAR(m_idVarPedTattooTarget);
ASSERT_COMPARE_VAR(m_idVarPedDamageData);
ASSERT_COMPARE_VAR(m_idVarPedDamageColors);
ASSERT_COMPARE_VAR(m_idVarStubbleGrowthDetailScale);
ASSERT_COMPARE_VAR(m_idVarUmGlobalOverrideParams);
#if __XENON || __WIN32PC || RSG_DURANGO || RSG_ORBIS
ASSERT_COMPARE_VAR(m_idVarClothParentMatrix);
#endif
#if __WIN32PC || RSG_DURANGO || RSG_ORBIS
ASSERT_COMPARE_VAR(m_idVarClothVertices);
#endif
ASSERT_COMPARE_VAR(m_idVarNormalTex);
ASSERT_COMPARE_VAR(m_idVarSpecularTex);
#undef ASSERT_COMPARE_VAR
// the fur and skin bits just need to be turned on if any part of the model has that shader on it
pPedEffectType->m_bIsFurShader |= pTempPedEffectType->m_bIsFurShader;
pTempShaderEffectType->RemoveRef();
pTempShaderEffectType = NULL;
}
}
return(pShaderEffectType);
}
u32 CCustomShaderEffectPed::AddDataForPrototype(void * address)
{
u32 size = 0;
DrawListAddress drawListOffset;
CopyOffShader(this, this->Size(), drawListOffset, false, m_pType);
drawListOffset = gDCBuffer->LookupSharedData(DL_MEMTYPE_SHADER, GetSharedDataOffset());
*static_cast<DrawListAddress*>(address) = drawListOffset;
size += sizeof(DrawListAddress);
return size;
}
u8 PackToU8( float v){
Assert( v>=0. && v<=1.);
return (u8)(v*255.);
}
//
//
//
//
void CCustomShaderEffectPed::Update(fwEntity* pEntityBase)
{
CEntity* pEntity = static_cast<CEntity*>(pEntityBase);
Assert (pEntity);
//Don't update the shader for special cutscene peds
CPed* pPed=NULL;
CPedModelInfo* pModelInfo=NULL;
if(pEntity->GetIsTypePed())
{
pPed = (CPed*)pEntity;
pModelInfo = pPed->GetPedModelInfo();
}
else
{
#if __DEV
CBaseModelInfo* pMI = pEntity->GetBaseModelInfo();
Assert(pMI);
Assertf(false, "Entity shouldn't use this CSE Ped: %s (type:%d)",pMI->GetModelName(),pEntity->GetType());
#endif //__DEV
Assertf(false,"Unhandled entity type in CCustomShaderEffectPed::Update");
return;
}
//
//
// check if ped should be rendered burnout:
//
this->SetWetClothesData(Vector4(-2,-2,0,0));
if(pPed)
{
fwDynamicEntityComponent *pedDynComp = pPed->GetDynamicComponent();
this->m_bRenderVehBurnout = FALSE; // this should be false if we're not in a vehicle or we are but it's not on fire...
if(pPed->GetPedConfigFlag( CPED_CONFIG_FLAG_InVehicle ) && pPed->GetMyVehicle() && pPed->IsInjured())
{
CVehicle *pVehicle = static_cast<CVehicle*>(pPed->GetMyVehicle());
if(pVehicle->m_nPhysicalFlags.bRenderScorched)
{
this->m_bRenderVehBurnout = TRUE;
}
}
if(pPed->m_nPhysicalFlags.bRenderScorched)
{
if (pPed->IsNetworkClone())
{
this->m_bRenderBurnout = TRUE;
}
else
{
if( m_bRenderBurnout == FALSE && pPed->IsDead())
{
// apply burnt damage pack first time through only
PEDDAMAGEMANAGER.AddPedDamagePack(pPed, ATSTRINGHASH("Burnt_Ped_0",0xde3cdfba), 0.0f, 1.0f);
}
// mark burnt out if he's both scorched and dead
this->m_bRenderBurnout = pPed->IsDead();
}
}
this->m_bRenderDead = FALSE;
if(this->m_bRenderBurnout)
{ // is ped dead & was on fire?
if(pPed->IsDead())
{
this->m_bRenderDead = TRUE;
// B*3038261 : We need to render the helmet when you are burning
if( !pPed->GetPedConfigFlag(CPED_CONFIG_FLAG_HasHelmet) )
pPed->GetPedDrawHandler().GetPropData().SetSkipRender(true); // clear ped props if ped is burnout
if (m_bTriggeredSmokeFx==FALSE)
{
g_vfxFire.TriggerPtFxPedFireSmoulder(pPed);
m_bTriggeredSmokeFx = TRUE;
}
}
}
else if(this->m_bRenderVehBurnout)
{
// B*3038261 : We need to render the helmet when you are burning
if(pPed->IsDead() && !pPed->GetPedConfigFlag(CPED_CONFIG_FLAG_HasHelmet))
{
pPed->GetPedDrawHandler().GetPropData().SetSkipRender(true); // clear ped props if ped is burnout
}
}
else if(pPed->IsClothingWet())
{
this->m_varWetClothesData = pPed->GetWetClothingData();
}
if(this->m_bRenderBurnout || this->m_bRenderVehBurnout)
{
const float fBurnoutLevelInc =
#if CSE_PED_EDITABLEVALUES
ms_fEVBurnoutLevelSpeed;
#else
0.02f;
#endif
this->SetBurnoutLevel(GetBurnoutLevel()+fBurnoutLevelInc);
}
else
{
this->SetBurnoutLevel(0.0f);
}
m_varHeat = (u8)(CCustomShaderEffectPed::GetPedHeat(pPed, pModelInfo->GetThermalBehaviour()));
crCreature* creature = pedDynComp->GetCreature();
UpdateExpression(creature, pedDynComp->GetTargetManager());
this->SetStubbleGrowth(pPed->GetCurrentStubbleGrowth());
const float fWindyClothingScale = pPed->GetWindyClothingScale();
if(fWindyClothingScale > 0.0f)
{
const float umOverride = Lerp(fWindyClothingScale, 1.0f, 21.0f);
this->SetUmGlobalOverrideParams(umOverride, umOverride, 1.0f, 1.0f);
}
else
{
//if nothing is affecting micromovement then allow wind to do it
bool bApplyWinUm = true;
if(pPed->IsLocalPlayer())
{
// is player inside vehicle?
if(pPed->IsInFirstPersonVehicleCamera() && pPed->GetIsInVehicle())
{
bApplyWinUm = false; // disable wind um if in FPP inside vehicle
CVehicle *pPedVehicle = pPed->GetVehiclePedInside();
if(pPedVehicle && pPedVehicle->GetVehicleType()==VEHICLE_TYPE_CAR)
{
enum { MID_TORNADO4 = 0x86CF7CDD }; // "tornado4"
// FPP player driving roofless car or one with open roof?
if(pPedVehicle->DoesVehicleHaveAConvertibleRoofAnimation())
{
// convertible cars with lowered roof:
const s32 roofState = pPedVehicle->GetConvertibleRoofState();
bApplyWinUm = (roofState==CTaskVehicleConvertibleRoof::STATE_LOWERED) ||
(roofState==CTaskVehicleConvertibleRoof::STATE_LOWERING) ||
(roofState==CTaskVehicleConvertibleRoof::STATE_ROOF_STUCK_LOWERED);
}
else if(pPedVehicle->GetVehicleModelInfo()->GetVehicleFlag(CVehicleModelInfoFlags::FLAG_EXTRAS_CONVERTIBLE))
{
// cars with removable roof as an extra:
bApplyWinUm = !pPedVehicle->CarHasRoof(false);
}
else if(pPedVehicle->GetBaseModelInfo()->GetModelNameHash()==MID_TORNADO4)
{
bApplyWinUm = true;
}
}
}
}// if(IsLocalPlayer())...
if(bApplyWinUm)
{
//initial flutter intensity is zero as we dont have an ambient micromovement like plants and trees
float flutterIntentity = 0.0f;
#if CSE_PED_EDITABLEVALUES
if (ms_bEVWindResponseEnabled && (ms_fEVWindFlutterIntensity > 0.0f))
#endif
{
Vec3V wind;
//Using global velocity as ped causes disturbances in local velocity
//const Vec3V entityPos = pEntity->GetTransform().GetPosition();
//WIND.GetLocalVelocity(entityPos, wind);
WIND.GetGlobalVelocity(WIND_TYPE_AIR, wind);
float windVel = Mag(wind).Getf();
const float windVelMin = BANK_SWITCH(ms_fEVWindResponseVelMin, PED_DEFAULT_WIND_RESPONSE_VEL_MIN);
const float windVelMax = BANK_SWITCH(ms_fEVWindResponseVelMax, PED_DEFAULT_WIND_RESPONSE_VEL_MAX);
// Calculate wind response in [0.0, 1.0f]
const float windResponse = Clamp<float>((windVel - windVelMin)/(windVelMax - windVelMin), 0.0f, 1.0f);
//Flutter Intensity is used for scaling the amplitude of the micromovement
flutterIntentity += windResponse * BANK_SWITCH(ms_fEVWindFlutterIntensity, PED_DEFAULT_WIND_FLUTTER_INTENSITY);
}
//set override params based on some parameters
// Higher winds causes higher amplitude and higher frequency (looks like cloth flutter)
this->SetUmGlobalOverrideParams(
BANK_SWITCH(ms_fEVWindMotionAmpX, PED_DEFAULT_WIND_MOTION_AMP_X ) BANK_ONLY(*(ms_bEVWindMotionEnabled? 1.0f : 0.0f)) * flutterIntentity,
BANK_SWITCH(ms_fEVWindMotionAmpY, PED_DEFAULT_WIND_MOTION_AMP_Y ) BANK_ONLY(*(ms_bEVWindMotionEnabled? 1.0f : 0.0f)) * flutterIntentity,
BANK_SWITCH(ms_fEVWindMotionFreq, PED_DEFAULT_WIND_MOTION_FREQ),
BANK_SWITCH(ms_fEVWindMotionFreq, PED_DEFAULT_WIND_MOTION_FREQ)
);
}// if(bApplyWinUm)...
else
{
this->SetUmGlobalOverrideParams(0.0f, 0.0f, 0.0f, 0.0f);
}
}
UpdatePedDamage(pPed);
SetEnvEffColorModulator(pPed->GetDirtColor());
if(!m_bCustomEnvEffScale)
{
SetEnvEffScale(pPed->GetDirtScale());
}
if(IsFurShader())
{
if(pPed->GetIsInVehicle())
{
m_vLocalWind[0] = m_vLocalWind[1] = m_vLocalWind[2] = 0;
}
else
{
// cache the local wind vector in the shader
const Vec3V entityPos = pEntity->GetTransform().GetPosition();
Vec3V localWind;
WIND.GetLocalVelocity(entityPos, localWind);
m_vLocalWind[0] = s16(localWind.GetXf() * (1<<PED_WIND_FIXED_POINT));
m_vLocalWind[1] = s16(localWind.GetYf() * (1<<PED_WIND_FIXED_POINT));
m_vLocalWind[2] = s16(localWind.GetZf() * (1<<PED_WIND_FIXED_POINT));
}
}
SetSweatScale(pPed->GetSweatScale());
// calculate detail scale
const grcViewport *viewport = gVpMan.GetUpdateGameGrcViewport();
const Vec3V camPos = viewport->GetCameraMtx().d();
const Vector3 pos = pPed->GetPreviousPosition();
const Vec3V vpos = VECTOR3_TO_VEC3V(pos);
float distToCamera = Dist(camPos, vpos).Getf();
Vector2 fadeOut = this->m_bRenderBurnout? ms_DetailFadeOut[1] : ms_DetailFadeOut[0];
float detailScale = 1.0f - Clamp( (distToCamera - fadeOut.x)/(fadeOut.y - fadeOut.x), 0.0f, 1.0f);
m_PedDetailScale = PackToU8(detailScale);
bool cutScenePlaying = camInterface::GetCutsceneDirector().IsCutScenePlaying();
m_useCutsceneTech = cutScenePlaying BANK_ONLY(&& g_useOptimisedCutsceneTechnique );
}// if(pPed)...
}// end of Update()...
//
//
//
//
void CCustomShaderEffectPed::EnableShaderVarCaching(bool value)
{
ms_EnableShaderVarCaching[g_RenderThreadIndex] = value && g_UsePedShaderVarCaching;
if(ms_EnableShaderVarCaching[g_RenderThreadIndex])
{
//InvalidateShaderVarCache(); // not necessary due to as CPedVariationStream/Pack::RenderPed() uses var caching
}
}
inline Vector4 ToVector4(u8 packed[4])
{
const float scale = 1.0f / 255;
return Vector4(packed[0] * scale, packed[1] * scale, packed[2] * scale, packed[3] * scale);
}
inline Vec4V ToVec4V(u8 packed[4])
{
const ScalarV vScale(1.0f / 255.0f);
return Vec4V((float)packed[0], (float)packed[1], (float)packed[2], (float)packed[3]) * vScale;
}
inline void FromVector4(u8 packed[4],const Vector4 &from)
{
packed[0] = u8(from.x * 255);
packed[1] = u8(from.y * 255);
packed[2] = u8(from.z * 255);
packed[3] = u8(from.w * 255);
}
#define m_ComponentBlendWeights ((ComponentBlendWeights*)(this+1))
//
//
//
//
//
void CCustomShaderEffectPed::UpdateExpression(crCreature* pCreature, grbTargetManager* ENABLE_BLENDSHAPES_ONLY(pManager))
{
#if ENABLE_BLENDSHAPES
bool blendShapeExistence[1 /*MAX_PED_COMPONENTS*/] = {0};
if (pManager)
{
m_Manager = pManager;
}
#endif // ENABLE_BLENDSHAPES
if (pCreature)
{
const int numComponents = pCreature->GetNumComponents();
for (int i = 0; i < numComponents; ++i)
{
crCreatureComponent* component = pCreature->GetComponentByIndex(i);
if (component->GetType() == crCreatureComponent::kCreatureComponentTypeShaderVars)
{
crCreatureComponentShaderVars* shaderVarComponent = static_cast<crCreatureComponentShaderVars*>(component);
const u32 sWrinkleWeightHash = ATSTRINGHASH("WrinkleWeights", 0x0f09864d6);
const u32 sFatPedShaderHash = ATSTRINGHASH("FatStrength", 0x03b4cfb00);
//const u32 sNormalMapBlendHash = ATSTRINGHASH("NormalMapBlend", 0x0310e4a57);
const u32 numPairs = shaderVarComponent->GetNumShaderVarDofPairs();
for(u32 n=0; n<numPairs; ++n)
{
u8 track;
u16 id;
fwShaderVarComponentData data;
float value;
shaderVarComponent->GetShaderVarDofPair(n, track, id, data.m_Packed, value);
if(data.unpack.m_Hash == sWrinkleWeightHash)
{
const int componentWr = s_wrinkleTrans[data.unpack.m_PedCompId];
if(componentWr >= 0)
{
const int wrinkleMask = data.unpack.m_MaskId;
const int idx = data.unpack.m_Component;
const float fVal = FPClamp(value, 0.f, 1.f);
const int iVal = (int)(fVal * 255.0f);
Assert((iVal & 0xffffff00) == 0);
Assert(componentWr<4);
Assert(wrinkleMask<6);
Assert(idx<4);
Assign(m_wrinkleMaskStrengths[componentWr][wrinkleMask][idx], (u8)iVal);
#if __BANK
if (!ms_wrinkleEnableSliders)
{
ms_wrinkleMaskStrengths[wrinkleMask] = ToVector4(m_wrinkleMaskStrengths[componentWr][wrinkleMask]);
}
#endif // __BANK
}
}
else if(data.unpack.m_Hash == sFatPedShaderHash)
{
SetFatScale(value);
}
}
}
#if ENABLE_BLENDSHAPES
else if (pManager && component->GetType() == crCreatureComponent::kCreatureComponentTypeBlendShapes)
{
crCreatureComponentBlendShapes* blendshapeComponent = static_cast<crCreatureComponentBlendShapes*>(component);
const int numBlendWeights = blendshapeComponent->GetBlendWeightCount();
int component = PV_COMP_HEAD; // blendshapeComponent->GetComponentType(); todo
if (!m_bHasBlendshapes)
Errorf("CCustomShaderEffectPed allocated without blend weights, cannot update");
else
{
ComponentBlendWeights *componentBlendWeights = (ComponentBlendWeights*)(this + 1);
if (!componentBlendWeights[component].m_BlendWeights.GetCount())
{
componentBlendWeights[component].m_BlendWeights.Resize(numBlendWeights);
Displayf("********* setting ped blend weight array size to %u",numBlendWeights);
}
blendShapeExistence[component] = true;
componentBlendWeights[component].m_Exists = true;
for (int j = 0 ; j < numBlendWeights; ++j)
{
const crCreatureComponentBlendShapes::BlendWeight& blendweight = blendshapeComponent->GetBlendWeight(j);
componentBlendWeights[component].m_BlendWeights[j].m_Id = blendweight.m_Id;
int iWeight = (int)(blendweight.m_Weight * 32768.0f);
componentBlendWeights[component].m_BlendWeights[j].m_FixedWeight = u16(iWeight<0?0:iWeight>65535?65536:iWeight);
}
}
}
#endif // ENABLE_BLENDSHAPES
}
}
#if __BANK
const int componentWr = ms_wrinkleDebugComponent;
if (ms_wrinkleEnableSliders && componentWr >= 0 && componentWr <= 2)
{
FromVector4(m_wrinkleMaskStrengths[componentWr][0], ms_wrinkleMaskStrengths[0]);
FromVector4(m_wrinkleMaskStrengths[componentWr][1], ms_wrinkleMaskStrengths[1]);
FromVector4(m_wrinkleMaskStrengths[componentWr][2], ms_wrinkleMaskStrengths[2]);
FromVector4(m_wrinkleMaskStrengths[componentWr][3], ms_wrinkleMaskStrengths[3]);
FromVector4(m_wrinkleMaskStrengths[componentWr][4], ms_wrinkleMaskStrengths[4]);
FromVector4(m_wrinkleMaskStrengths[componentWr][5], ms_wrinkleMaskStrengths[5]);
}
#endif // __BANK
#if ENABLE_BLENDSHAPES
for (int i = 0; i < 1 /*MAX_PED_COMPONENTS*/; ++i)
{
if (blendShapeExistence[i] == false && m_bHasBlendshapes)
{
m_ComponentBlendWeights[i].m_BlendWeights.Reset();
}
}
#endif // ENABLE_BLENDSHAPES
}
void CCustomShaderEffectPed::AddToDrawList(u32 modelIndex, bool bExecute)
{
DLC(CCustomShaderEffectDC, (*this, modelIndex, bExecute, m_pType));
}
//
//
//
//
void CCustomShaderEffectPed::SetShaderVariables(rmcDrawable*)
{
//
// note:
// this method is not called from CDynamic\Entity::Render()
// instead, PedVariationMgr_SetShaderVariables() is called from CPedVariationMgr::RenderCompositePed()
//
Assert(0);
}// end of SetShadersVariables()...
// helper function for masking off un-marked areas
float CalcPedDamageEnable(float maskIn, int component)
{
// shortcut - no blood/decal
if( maskIn == 0.0f )
{
return 0.0f;
}
// store signbit for later
float signBit = Sign(maskIn);
/// zone mask values
//kDamageZoneTorso=1,
//kDamageZoneHead=2,
//kDamageZoneLeftArm=4,
//kDamageZoneRightArm=8,
//kDamageZoneLeftLeg=16,
//kDamageZoneRightLeg=32,
// we combine zone mask with component mask
u16 originalMask = static_cast<u16>(signBit*maskIn);
static u16 componentMasks[PV_MAX_COMP] = { 1|2, // PV_COMP_HEAD
2, // PV_COMP_BERD
2, // PV_COMP_HAIR
1|2|4|8|16|32, // PV_COMP_UPPR
1|16|32, // PV_COMP_LOWR
4|8, // PV_COMP_HAND
16|32, // PV_COMP_FEET
2, // PV_COMP_TEEF
0xff, // PV_COMP_ACCS
0xff, // PV_COMP_TASK
0xff, // PV_COMP_DECL
0xff }; // PV_COMP_JBIB
return static_cast<float>(componentMasks[component] & originalMask)*signBit;
}
//
//
// called from CPedVariationMgr::RenderCompositePed():
//
#if __XENON || __WIN32PC || RSG_DURANGO || RSG_ORBIS
void CCustomShaderEffectPed::PedVariationMgr_SetShaderVariables(rmcDrawable *pDrawable, s32 componentID, const Matrix34 *pClothParentMatrix )
#else
void CCustomShaderEffectPed::PedVariationMgr_SetShaderVariables(rmcDrawable *pDrawable, s32 componentID )
#endif
{
Assert(pDrawable);
Assert(componentID >= 0);
Assert(componentID < PV_MAX_COMP);
if(!pDrawable)
return;
if(grmModel::GetForceShader())
return;
#if __BANK
if(DRAWLISTMGR->IsExecutingDebugOverlayDrawList())
return;
#endif
grmShaderGroup& shaderGroup = pDrawable->GetShaderGroup();
Assert(shaderGroup.GetShaderGroupVarCount() > 0);
CCustomShaderEffectPedType *pType = m_pType;
// find the mask for this component
float revisedPedDamageDataX = CalcPedDamageEnable(m_PedDamageData.GetX(), componentID);
// set the cutsceneFlag per component for possible cheap technique
if (m_useCutsceneTech && DRAWLISTMGR->IsExecutingGBufDrawList())
{
if(revisedPedDamageDataX == 0.0f)
DeferredLighting::PushCutscenePedTechnique();
}
if(m_varhDiffuseTex[componentID] BANK_ONLY(&& !g_ShaderEdit::GetInstance().IsTextureDebugOn()))
{
#if __BANK
if (CPedVariationDebug::GetDisableDiffuse() && CPedVariationDebug::GetGreyDebugTexture())
{
shaderGroup.SetVar((grmShaderGroupVar)pType->m_idVarDiffuseTex, CPedVariationDebug::GetGreyDebugTexture());
}
else
#endif
{
shaderGroup.SetVar((grmShaderGroupVar)pType->m_idVarDiffuseTex, m_varhDiffuseTex[componentID]);
}
}
if(m_varhNormalTex[componentID])
{
shaderGroup.SetVar((grmShaderGroupVar)pType->m_idVarNormalTex, m_varhNormalTex[componentID]);
}
if(m_varhSpecularTex[componentID])
{
shaderGroup.SetVar((grmShaderGroupVar)pType->m_idVarSpecularTex, m_varhSpecularTex[componentID]);
}
if((!ms_EnableShaderVarCaching[g_RenderThreadIndex]) || (ms_CachedCSEPedShaderVars[g_RenderThreadIndex].umGlobalOverrideParams != m_umGlobalOverrideParams))
{
Assert(pType->m_idVarUmGlobalOverrideParams);
const Vec4V umOverrideParamsV4(
m_umGlobalOverrideParams.x.GetFloat32_FromFloat16(),
m_umGlobalOverrideParams.y.GetFloat32_FromFloat16(),
m_umGlobalOverrideParams.z.GetFloat32_FromFloat16(),
m_umGlobalOverrideParams.w.GetFloat32_FromFloat16());
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].umGlobalOverrideParams = m_umGlobalOverrideParams;
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarUmGlobalOverrideParams, umOverrideParamsV4);
}
#if __WIN32PC || RSG_DURANGO || RSG_ORBIS
if(pClothParentMatrix)
{
Assert(pType->m_idVarClothParentMatrix);
Mat44V *pMatrix44 = (Mat44V*)pClothParentMatrix;
pMatrix44->SetM30f(0.0f);
pMatrix44->SetM31f(0.0f);
pMatrix44->SetM32f(0.0f);
pMatrix44->SetM33f(1.0f);
grcEffect::SetGlobalVar((rage::grcEffectGlobalVar)pType->m_idVarClothParentMatrix,pMatrix44,1);
}
#endif // __WIN32PC || RSG_DURANGO || RSG_ORBIS
const float fEnvEffScale = this->GetEnvEffScale();
const float fFatScale = this->GetFatScale();
const Vec4V envEffFatSweatScale(
fEnvEffScale,
fEnvEffScale * (1.0f/1000.0f),
fFatScale * (1.0f/1000.0f),
this->GetSweatScale()
);
if((!ms_EnableShaderVarCaching[g_RenderThreadIndex]) || (!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].EnvEffFatSweatScale, envEffFatSweatScale)))
{
Assert(pType->m_idVarEnvEffFatSweatScale);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].EnvEffFatSweatScale = envEffFatSweatScale;
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarEnvEffFatSweatScale, envEffFatSweatScale);
}
const float pedDetailScale = (float)m_PedDetailScale / 255.0f;
if(DRAWLISTMGR->IsExecutingShadowDrawList())
{
// do nothing
}
else
{
if((!ms_EnableShaderVarCaching[g_RenderThreadIndex]) || (ms_CachedCSEPedShaderVars[g_RenderThreadIndex].DiffuseTexPal != m_varhDiffuseTexPal[componentID]))
{
Assert(pType->m_idVarDiffuseTexPal);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].DiffuseTexPal = m_varhDiffuseTexPal[componentID];
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarDiffuseTexPal, m_varhDiffuseTexPal[componentID]);
}
if((!ms_EnableShaderVarCaching[g_RenderThreadIndex]) || (ms_CachedCSEPedShaderVars[g_RenderThreadIndex].DiffuseTexPalSelector != m_varDiffuseTexPalSelector[componentID]))
{
Assert(pType->m_idVarDiffuseTexPalSelector);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].DiffuseTexPalSelector = m_varDiffuseTexPalSelector[componentID];
// convert palette selector to UV coordinate:
// uv = (paletteSelector + 0.5f) / 8.0f; // palette row select: 0-7
const float divider = 1.0f / (GetDiffuseTexturePalLarge(componentID) ? PED_COLOR_VARIATION_TEXTURE_PAL_ROWNUM_LARGE : PED_COLOR_VARIATION_TEXTURE_PAL_ROWNUM);
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarDiffuseTexPalSelector, (float(GetDiffuseTexturePalSelector(componentID))+0.5f) * divider);
}
const Vec4V vEnvEffColorMod_CpvAdd(GetEnvEffColorModulator().GetRGB(), ScalarV(GetEnvEffCpvAdd()));
if((!ms_EnableShaderVarCaching[g_RenderThreadIndex]) || (!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].EnvEffColorMod_CpvAdd, vEnvEffColorMod_CpvAdd)))
{
Assert(pType->m_idVarEnvEffColorModCpvAdd);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].EnvEffColorMod_CpvAdd = vEnvEffColorMod_CpvAdd;
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarEnvEffColorModCpvAdd, vEnvEffColorMod_CpvAdd);
}
#if __XENON
if(pClothParentMatrix)
{
Assert(pType->m_idVarClothParentMatrix);
shaderGroup.SetVar((grmShaderGroupVar)pType->m_idVarClothParentMatrix, pClothParentMatrix, 1);
}
#endif // __XENON
//#if __WIN32PC || RSG_DURANGO || RSG_ORBIS
// if(pClothParentMatrix)
// {
// Assert(pType->m_idVarClothParentMatrix);
// grcEffect::SetGlobalVar((rage::grcEffectGlobalVar)pType->m_idVarClothParentMatrix,(Mat44V*)pClothParentMatrix,1);
// }
//#endif // __WIN32PC || RSG_DURANGO || RSG_ORBIS
Assert(pType->m_idVarWrinkleMaskStrengths0);
const int componentWr = s_wrinkleTrans[componentID];
if(componentWr >= 0)
{
Vec4V values[6];
values[0] = ToVec4V(m_wrinkleMaskStrengths[componentWr][0]);
values[1] = ToVec4V(m_wrinkleMaskStrengths[componentWr][1]);
values[2] = ToVec4V(m_wrinkleMaskStrengths[componentWr][2]);
values[3] = ToVec4V(m_wrinkleMaskStrengths[componentWr][3]);
values[4] = ToVec4V(m_wrinkleMaskStrengths[componentWr][4]);
values[5] = ToVec4V(m_wrinkleMaskStrengths[componentWr][5]);
const bool bSetShaderVars = (!ms_EnableShaderVarCaching[g_RenderThreadIndex]) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[0], values[0])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[1], values[1])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[2], values[2])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[3], values[3])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[4], values[4])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[5], values[5])) ;
if(bSetShaderVars)
{
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[0] = values[0];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[1] = values[1];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[2] = values[2];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[3] = values[3];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[4] = values[4];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[5] = values[5];
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarWrinkleMaskStrengths0, values, 6);
}
}
else
{
const Vec4V values[6] = { Vec4V(V_ZERO), Vec4V(V_ZERO), Vec4V(V_ZERO), Vec4V(V_ZERO), Vec4V(V_ZERO), Vec4V(V_ZERO) };
const bool bSetShaderVars = (!ms_EnableShaderVarCaching[g_RenderThreadIndex]) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[0], values[0])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[1], values[1])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[2], values[2])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[3], values[3])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[4], values[4])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[5], values[5])) ;
if(bSetShaderVars)
{
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[0] = values[0];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[1] = values[1];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[2] = values[2];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[3] = values[3];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[4] = values[4];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WrinkleMaskStrenghts[5] = values[5];
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarWrinkleMaskStrengths0, values, 6);
}
}
#if ENABLE_BLENDSHAPES
if (m_Manager && componentID == PV_COMP_HEAD && m_bHasBlendshapes && m_ComponentBlendWeights[componentID].m_Exists && !m_ComponentBlendWeights[componentID].m_Processed)
{
SetupBlendshapeWeights(pDrawable, componentID);
m_ComponentBlendWeights[componentID].m_Processed = true;
}
#endif // ENABLE_BLENDSHAPES
const Vec2V vStubbleGrowthDetScale(1.0f-GetStubbleGrowth(), pedDetailScale);
if((!ms_EnableShaderVarCaching[g_RenderThreadIndex]) || (!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].StubbleGrowthDetScale, vStubbleGrowthDetScale)))
{
Assert(pType->m_idVarStubbleGrowthDetailScale);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].StubbleGrowthDetScale = vStubbleGrowthDetScale;
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarStubbleGrowthDetailScale, vStubbleGrowthDetScale);
}
if(componentID == PV_COMP_HAIR)
{
Assert(pType->m_idVarStubbleGrowthDetailScale);
// convert palette selector to UV coordinate:
const float divider = 1.0f / (GetDiffuseTexturePalLarge(componentID) ? PED_COLOR_VARIATION_TEXTURE_PAL_ROWNUM_LARGE : PED_COLOR_VARIATION_TEXTURE_PAL_ROWNUM);
Vec2V vec;
vec.SetX(((float)m_secondHairPalSelector + 0.5f) * divider);
vec.SetY(pedDetailScale);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].StubbleGrowthDetScale = vec; // nuke the cache for the stubble so we don't end up using this value
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarStubbleGrowthDetailScale, vec);
}
const ScalarV vHeat((float)m_varHeat/255.0f);
const ScalarV vEmissiveScale(GetEmissiveScale());
const Vec4V pedNormal(ScalarV(1.0f), vEmissiveScale, ScalarV(1.0f), vHeat);
const Vec4V pedNormal2(V_ONE);
const Vec4V pedVehBurnout(ScalarV(0.05f),Vec2V(V_ZERO), vHeat);
const Vec4V pedVehBurnout2(V_ZERO);
const Vec4V pedDead(ScalarV(0.20f),Vec2V(V_ZERO), vHeat);
const Vec4V pedDead2(V_ZERO);
const ScalarV burnLevel(this->GetBurnoutLevel());
const Vec4V vColorScale0 = m_bRenderDead? Lerp(burnLevel,pedNormal,pedDead) : m_bRenderVehBurnout? Lerp(burnLevel,pedNormal,pedVehBurnout) : pedNormal;
const Vec4V vColorScale1 = m_bRenderDead? Lerp(burnLevel,pedNormal2,pedDead2) : m_bRenderVehBurnout? Lerp(burnLevel,pedNormal2,pedVehBurnout2) : pedNormal2;
if( (!ms_EnableShaderVarCaching[g_RenderThreadIndex]) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].MaterialColorScale[0], vColorScale0)) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].MaterialColorScale[1], vColorScale1)) )
{
Assert(pType->m_idVarMaterialColorScale);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].MaterialColorScale[0] = vColorScale0;
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].MaterialColorScale[1] = vColorScale1;
Vec4V vColorScaleAll[2] = {vColorScale0, vColorScale1};
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarMaterialColorScale, &vColorScaleAll[0], 2);
}
const Vec4V vWetClothesData = RCC_VEC4V(m_varWetClothesData);
if((!ms_EnableShaderVarCaching[g_RenderThreadIndex]) || (!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WetClothesData, vWetClothesData)))
{
Assert(pType->m_idVarWetClothesData);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WetClothesData = vWetClothesData;
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarWetClothesData, vWetClothesData);
}
// if we are in the GBUF or Hud passes we should set the Data Data And samplers
bool bIsGbufPass = DRAWLISTMGR->IsExecutingGBufDrawList();
bool bIsHUDPass = DRAWLISTMGR->IsExecutingHudDrawList();
bool bIsMirrorPass = m_usePedDamageInMirror && DRAWLISTMGR->IsExecutingMirrorReflectionDrawList();
if (bIsHUDPass || bIsGbufPass || bIsMirrorPass)
{
// outside of GBUF pass, s15 is used for shadows, so don't mess with it
if(bIsGbufPass || bIsHUDPass)
{
if((!ms_EnableShaderVarCaching[g_RenderThreadIndex]) || (ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedBloodTarget != m_PedBloodTarget))
{
Assert(pType->m_idVarPedBloodTarget);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedBloodTarget = m_PedBloodTarget;
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarPedBloodTarget, m_PedBloodTarget);
}
}
// check whether there's a decal component that needs to override the ped tattoo target
if (componentID == PV_COMP_DECL && m_PedTattooTargetOverride != NULL)
{
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedTattooTarget = m_PedTattooTargetOverride;
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarPedTattooTarget, m_PedTattooTargetOverride);
shaderGroup.SetVar((grmShaderGroupVar)pType->m_idVarDiffuseTex, grcTexture::NoneBlack);
shaderGroup.SetVar((grmShaderGroupVar)pType->m_idVarNormalTex, grcTexture::NoneWhite);
shaderGroup.SetVar((grmShaderGroupVar)pType->m_idVarSpecularTex, grcTexture::NoneBlack);
}
// we can set tattoo global sampler, since it's in s14 and that is not used by the shadows
else if (bIsMirrorPass)
{
// skip the cache for now, since I don't have a grcTextureHandle, just a plan old grctexture.
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarPedTattooTarget, (m_PedDamageData.x!=0.0f) ? CPedDamageSetBase::GetMirrorDecorationTarget() : NULL);
}
else if((!ms_EnableShaderVarCaching[g_RenderThreadIndex]) || (ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedTattooTarget != m_PedTattooTarget))
{
Assert(pType->m_idVarPedTattooTarget);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedTattooTarget = m_PedTattooTarget;
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarPedTattooTarget, m_PedTattooTarget);
}
}
else if(DRAWLISTMGR->IsExecutingMirrorReflectionDrawList() && !m_usePedDamageInMirror)
{
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarPedTattooTarget, grcTexture::NoneBlack);
}
Vec4V vPedDamageData;
if (bIsHUDPass || bIsGbufPass || bIsMirrorPass)
{
vPedDamageData = RCC_VEC4V(m_PedDamageData); // only set the blood damage data for the gbuffer and hud passes (for UI peds)
// if the tattoo target has been overridden, force ped damage on
if (componentID == PV_COMP_DECL && m_PedTattooTargetOverride != NULL)
{
#if __XENON
vPedDamageData.SetX(ScalarV(0xFF));
#else
vPedDamageData.SetX(ScalarV(V_ONE));
#endif
}
else
{
#if __XENON
vPedDamageData.SetX(revisedPedDamageDataX);
#else
vPedDamageData.SetX(Sign(revisedPedDamageDataX));
#endif
if (bIsMirrorPass)
{
// need to update the damage data since thge target is different.
CPedDamageSetBase::AdjustPedDataForMirror(vPedDamageData);
}
}
}
else
vPedDamageData = Vec4V(V_ZERO); // for all other passes, make sure this is off, so shaders access the in valid render targets
if((!ms_EnableShaderVarCaching[g_RenderThreadIndex]) || (!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedDamageData, vPedDamageData)))
{
Assert(pType->m_idVarPedDamageData);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedDamageData = vPedDamageData;
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarPedDamageData, vPedDamageData);
}
const Vec4V wetnessAdjustOverWater = Vec4V(0.35f, 8.0f, 0.35f, 0.1f);
const Vec4V wetnessAdjustUnderWater = wetnessAdjustOverWater * Vec4V(V_X_AXIS_WONE);
const Vec4V wetnessAdjust = (Water::IsCameraUnderwater()) ? wetnessAdjustUnderWater : wetnessAdjustOverWater;
if((!ms_EnableShaderVarCaching[g_RenderThreadIndex]) || (!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WetnessAdjust, wetnessAdjust)))
{
Assert(pType->m_idVarWetnessAdjust);
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].WetnessAdjust = wetnessAdjust;
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarWetnessAdjust, wetnessAdjust);
}
#if DEVICE_MSAA
if (!GRCDEVICE.GetMSAA())
#endif
{
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarAlphaToCoverageScale, 0.0f);
}
// NOTE: this could go away if we ever pick a fixed set of colors or we make them globals
if(pType->m_idVarPedDamageColors)
{
Vec4V* pPedDamageColors = (Vec4V*)CPedDamageManager::GetInstance().GetPedDamageColors();
const bool bSetShaderVars = (!ms_EnableShaderVarCaching[g_RenderThreadIndex]) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedDamageColors[0], pPedDamageColors[0])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedDamageColors[1], pPedDamageColors[1])) ||
(!IsEqualAll(ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedDamageColors[2], pPedDamageColors[2])) ;
if(bSetShaderVars)
{
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedDamageColors[0] = pPedDamageColors[0];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedDamageColors[1] = pPedDamageColors[1];
ms_CachedCSEPedShaderVars[g_RenderThreadIndex].PedDamageColors[2] = pPedDamageColors[2];
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarPedDamageColors, pPedDamageColors, 3);
}
}
}//if(!DRAWLISTMGR->IsExecutingShadowDrawList())...
#if CSE_PED_EDITABLEVALUES
ms_fEVEnvEffZoneScale = this->GetEnvEffScale();
ms_fEVEnvEffZoneColorModR = this->GetEnvEffColorModulator().GetRed();
ms_fEVEnvEffZoneColorModG = this->GetEnvEffColorModulator().GetGreen();
ms_fEVEnvEffZoneColorModB = this->GetEnvEffColorModulator().GetBlue();
CCustomShaderEffectPed::SetEditableShaderValues(&shaderGroup, pDrawable, pType, pedDetailScale);
#endif //CSE_PED_EDITABLEVALUES...
}// end of PedVariation_SetShaderVariables()...
void CCustomShaderEffectPed::PedVariationMgr_SetWetnessAdjust(int wetness)
{
Assert(m_pType->m_idVarWetnessAdjust);
Vector4 wetnessAdjust;
if(wetness == -1)
wetnessAdjust = ms_fEVWetClothesAdjustLessWet;
else if(wetness == 1)
wetnessAdjust = ms_fEVWetClothesAdjustMoreWet;
else
wetnessAdjust = ms_fEVWetClothesAdjust;
wetnessAdjust = (Water::IsCameraUnderwater()) ? wetnessAdjust * Vector4(1.0f, 0.0f, 0.0f, 1.0f) : wetnessAdjust;
grcEffect::SetGlobalVar((grcEffectGlobalVar)m_pType->m_idVarWetnessAdjust, VECTOR4_TO_VEC4V(wetnessAdjust));
}
#if RSG_PC || RSG_DURANGO || RSG_ORBIS
void CCustomShaderEffectPed::PedVariationMgr_SetShaderClothVertices(rmcDrawable *UNUSED_PARAM(pDrawable), u32 numVertices, const Vec3V *pClothVertices )
{
Assertf(numVertices <= DX11_CLOTH_MAX_VERTICES, "CCustomShaderEffectPed::PedVariationMgr_SetShaderClothVertices()...Ped cloth has too many vertices.");
CCustomShaderEffectPedType *pType = m_pType;
if(pType && pType->m_idVarClothVertices)
{
grcEffect::SetGlobalVar((rage::grcEffectGlobalVar)pType->m_idVarClothVertices,pClothVertices,numVertices);
}
}
#endif // RSG_PC || RSG_DURANGO || RSG_ORBIS
#if ENABLE_BLENDSHAPES
//
//
//
//
void CCustomShaderEffectPed::SetupBlendshapeWeights(rmcDrawable *pDrawable, s32 componentID)
{
Assert(m_Manager);
atFixedArray<BlendWeight,MAX_PED_BLEND_WEIGHTS>& blendWeights = m_ComponentBlendWeights[componentID].m_BlendWeights;
const int numBlendWeights = blendWeights.GetCount();
m_Manager->PrepareBlendShapeOffsets();
m_Manager->ResetBlendShapeOffsets();
for(int idx=0; idx<numBlendWeights; ++idx)
{
BlendWeight& blendWeight = blendWeights[idx];
float currentWeight = blendWeight.m_FixedWeight * (1.0f / 32768.0f);
#if __BANK
if (ms_bBlendshapeForceAll || (ms_bBlendshapeForceSpecific && (ms_nBlendshapeForceSpecificIdx == idx)))
{
currentWeight = ms_fBlendshapeForceSpecificBlend;
}
#endif // __BANK
m_Manager->BlendTarget(blendWeight.m_Id, currentWeight);
}
m_Manager->ReleaseBlendShapeOffsets();
m_Manager->SwapBuffers();
pDrawable->ApplyBlendShapeOffsets(*m_Manager);
}
#endif // ENABLE_BLENDSHAPES
void CCustomShaderEffectPed::ClearShaderVars(rmcDrawable *pDrawable, s32 componentID)
{
Assert(pDrawable);
if(grmModel::GetForceShader())
return;
#if __BANK
if(DRAWLISTMGR->IsExecutingDebugOverlayDrawList())
return;
if (g_ShaderEdit::GetInstance().IsTextureDebugOn())
return;
#endif
if(DRAWLISTMGR->IsExecutingGBufDrawList())
DeferredLighting::PopCutscenePedTechnique();
grmShaderGroup& shaderGroup = pDrawable->GetShaderGroup();
if (!Verifyf(shaderGroup.GetShaderGroupVarCount() > 0, "No shader vars on ped drawable for component %d, was there a diffuse missing?", componentID))
return;
CCustomShaderEffectPedType *pType = m_pType;
shaderGroup.SetVar((grmShaderGroupVar)pType->m_idVarDiffuseTex, (grcTexture*)NULL);
if(m_varhNormalTex[componentID])
{
shaderGroup.SetVar((grmShaderGroupVar)pType->m_idVarNormalTex, (grcTexture*)NULL);
}
if(m_varhSpecularTex[componentID])
{
shaderGroup.SetVar((grmShaderGroupVar)pType->m_idVarSpecularTex, (grcTexture*)NULL);
}
}
void CCustomShaderEffectPed::ClearGlobalShaderVars()
{
if(DRAWLISTMGR->IsExecutingShadowDrawList())
return;
CCustomShaderEffectPedType *pType = m_pType;
Assert(pType->m_idVarDiffuseTexPal);
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarDiffuseTexPal, (grcTexture*)NULL);
if(DRAWLISTMGR->IsExecutingGBufDrawList())
{
Assert(pType->m_idVarPedBloodTarget);
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarPedBloodTarget, (grcTexture*)NULL);
Assert(pType->m_idVarPedTattooTarget);
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarPedTattooTarget, (grcTexture*)NULL);
}
}
float CCustomShaderEffectPed::GetPedHeat(CPed *ped, u32 thermalBehaviour)
{
const u32 coldMeatOffset = 2000;
const u32 currentTime = fwTimer::GetTimeInMilliseconds();
float heat = 1.0f;
if( ped->IsDead() && currentTime - ped->GetTimeOfDeath() >= coldMeatOffset)
{
const float coldMeatTiming = 10000.0f;
const float msSinceDead = (float)(fwTimer::GetTimeInMilliseconds() - (ped->GetTimeOfDeath() + coldMeatOffset));
heat = 1.0f - Clamp(msSinceDead/coldMeatTiming,0.0f,1.0f);
}
// a value of zero means no override
float heatScaleOverride = Clamp(ped->GetHeatScaleOverride(), SEETHROUGH_HEAT_SCALE_COLD, SEETHROUGH_HEAT_SCALE_WARM);
const float heatScale = (heatScaleOverride==0.0f) ? RenderPhaseSeeThrough::GetHeatScale(thermalBehaviour) * 255.0f : heatScaleOverride * 255.0f;
return heat * heatScale;
}
// um global override params:
void CCustomShaderEffectPed::SetUmGlobalOverrideParams(float scaleH, float scaleV, float argFreqH, float argFreqV)
{
m_umGlobalOverrideParams.x.SetFloat16_FromFloat32(scaleH);
m_umGlobalOverrideParams.y.SetFloat16_FromFloat32(scaleV);
m_umGlobalOverrideParams.z.SetFloat16_FromFloat32(argFreqH);
m_umGlobalOverrideParams.w.SetFloat16_FromFloat32(argFreqV);
}
// um global override params:
void CCustomShaderEffectPed::SetUmGlobalOverrideParams(float s)
{
Float16 s16(s);
m_umGlobalOverrideParams.x =
m_umGlobalOverrideParams.y =
m_umGlobalOverrideParams.z =
m_umGlobalOverrideParams.w = s16;
}
void CCustomShaderEffectPed::GetUmGlobalOverrideParams(float *pScaleH, float *pScaleV, float *pArgFreqH, float *pArgFreqV)
{
if(pScaleH)
{
*pScaleH = m_umGlobalOverrideParams.x.GetFloat32_FromFloat16();
}
if(pScaleV)
{
*pScaleV = m_umGlobalOverrideParams.y.GetFloat32_FromFloat16();
}
if(pArgFreqH)
{
*pArgFreqH = m_umGlobalOverrideParams.z.GetFloat32_FromFloat16();
}
if(pArgFreqV)
{
*pArgFreqV = m_umGlobalOverrideParams.w.GetFloat32_FromFloat16();
}
}
void CCustomShaderEffectPed::UpdatePedDamage(const CPed * pPed)
{
grcTexture* pBloodTarget;
grcTexture* pTattooTarget;
CPedDamageManager::GetInstance().GetRenderData(pPed->GetDamageSetID(), pPed->GetCompressedDamageSetID(), pBloodTarget, pTattooTarget, m_PedDamageData);
m_PedBloodTarget = pBloodTarget;
m_PedTattooTarget = pTattooTarget;
m_PedTattooTargetOverride = NULL;
m_usePedDamageInMirror = (pPed->IsLocalPlayer() || CPedDamageManager::GetInstance().WasPedDamageClonedFromLocalPlayer(pPed->GetDamageSetID())) && (m_PedDamageData.x!=0.0f) && CMirrors::GetIsMirrorVisible(true) && !Water::IsUsingMirrorWaterSurface();
// We only want to set the tattoo target override (used for crew emblem decals) if the ped actually
// has a component using one
const CPedVariationData& pedVarData = pPed->GetPedDrawHandler().GetVarData();
if (pPed->GetEnableCrewEmblem() && pedVarData.IsCurrVarDecalDecoration())
{
grcTexture* pCrewEmblemDecal = NULL;
// is crew logo overrided by script?
if(pedVarData.GetOverrideCrewLogoTxdHash() && pedVarData.GetOverrideCrewLogoTexHash())
{
strLocalIndex txdId = strLocalIndex(g_TxdStore.FindSlot(pedVarData.GetOverrideCrewLogoTxdHash()));
if(Verifyf(txdId != -1, "Invalid / non streamed txd! Connected with use of OVERRIDE_PED_CREW_LOGO_TEXTURE() script command!"))
{
if (g_TxdStore.IsValidSlot(txdId))
{
fwTxd* pTxd = g_TxdStore.Get(txdId);
if (Verifyf(pTxd, "Invalid txd pointer! Connected with use of OVERRIDE_PED_CREW_LOGO_TEXTURE() script command!"))
{
pCrewEmblemDecal = pTxd->Lookup(pedVarData.GetOverrideCrewLogoTexHash());
Assertf(pCrewEmblemDecal, "Invalid crew emblem override texture! Connected with use of OVERRIDE_PED_CREW_LOGO_TEXTURE() script command!");
if(pCrewEmblemDecal)
{
m_PedTattooTargetOverride = pCrewEmblemDecal;
}
}// if(pTxd)...
} // if(g_TxdStore.IsValidSlot(txdId))...
}// if(txdId != -1)...
}
else if(PEDDECORATIONMGR.GetCrewEmblemDecal(pPed, pCrewEmblemDecal))
{
m_PedTattooTargetOverride = pCrewEmblemDecal;
}
}
}
#if CSE_PED_EDITABLEVALUES
//
//
//
//
void CCustomShaderEffectPed::SetEditableShaderValues(grmShaderGroup *pShaderGroup, rmcDrawable* UNUSED_PARAM(pDrawable), CCustomShaderEffectPedType* pType, float pedDetailScale)
{
Assert(pShaderGroup);
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_idVarHairSpecularFactor2)
pShaderGroup->SetVar(m_idVarHairSpecularFactor2,ms_fEVHairSpecularFactor2);
// etc. etc.
#endif
// ...and the new way:
SetFloatShaderGroupVar(pShaderGroup, "Specular", ms_fEVSpecFalloff);
SetFloatShaderGroupVar(pShaderGroup, "SpecularColor", ms_fEVSpecIntensity);
SetFloatShaderGroupVar(pShaderGroup, "Reflectivity", ms_fEVReflectivity);
SetFloatShaderGroupVar(pShaderGroup, "Fresnel", ms_fEVSpecFresnel);
SetFloatShaderGroupVar(pShaderGroup, "Bumpiness", ms_fEVBumpiness);
SetVector3ShaderGroupVar(pShaderGroup, "detailSettings", Vector3(ms_fEVDetailIntensity, ms_fEVDetailBumpIntensity, ms_fEVDetailScale));
if(pType)
{
Assert(pType->m_idVarEnvEffFatSweatScale);
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarEnvEffFatSweatScale, Vec4V(ms_fEVEnvEffScale, ms_fEVEnvEffScale / 1000.0f, ms_fEVFatScale / 1000.0f, ms_fEVSweatScale));
Assert(pType->m_idVarEnvEffColorModCpvAdd);
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarEnvEffColorModCpvAdd, Vec4V(ms_fEVEnvEffColorMod.GetRGB(),ScalarV(ms_fEVEnvEffCpvAdd)));
Assert(pType->m_idVarStubbleGrowthDetailScale);
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarStubbleGrowthDetailScale, Vec2V(1.0f-ms_fEVStubbleStrength, pedDetailScale));
if(ms_bEVUseUmGlobalOverrideValues)
{
Assert(pType->m_idVarUmGlobalOverrideParams);
grcEffect::SetGlobalVar((grcEffectGlobalVar)pType->m_idVarUmGlobalOverrideParams, VECTOR4_TO_VEC4V(ms_fEVUmGlobalOverrideParams));
}
}
SetVector2ShaderGroupVar(pShaderGroup, "envEffFatThickness0", Vector2(ms_fEVEnvEffThickness, ms_fEVFatThickness));
SetFloatShaderGroupVar(pShaderGroup, "normalMapBlendRatio", ms_fEVNormalBlend);
SetVector4ShaderGroupVar(pShaderGroup, "umGlobalParams0", ms_fEVUmGlobalParams);
SetVector2ShaderGroupVar(pShaderGroup, "anisotropicSpecularIntensity", ms_fEVAnisotropicSpecularIntensity);
SetVector2ShaderGroupVar(pShaderGroup, "anisotropicSpecularExponent", ms_fEVAnisotropicSpecularExponent);
SetVector4ShaderGroupVar(pShaderGroup, "anisotropicSpecularColour", VEC4V_TO_VECTOR4(ms_fEVAnisotropicSpecularColour.GetRGBA()));
SetVector4ShaderGroupVar(pShaderGroup, "specularNoiseMapUVScaleFactor",ms_fEVSpecularNoiseMapUVScaleFactor);
SetFloatShaderGroupVar(pShaderGroup, "anisotropicAlphaBias", ms_fEVAnisotropicAlphaBias );
SetVector2ShaderGroupVar( pShaderGroup, "StubbleControl", Vector2(ms_fEVStubbleIndex, ms_fEVStubbleTile));
}// end of SetEditableShaderValues()...
static
void _SaveDataCB()
{
CCustomShaderEffectPed::SaveCurrentShaderSettingsToFile();
}
//
//
//
//
bool CCustomShaderEffectPed::InitWidgets(bkBank& bank)
{
bank.AddToggle("Use ped shaders var caching", &g_UsePedShaderVarCaching);
bank.AddToggle("Use cutscene techniques", &g_useOptimisedCutsceneTechnique);
// debug widgets:
bank.PushGroup("Ped Editable Shaders Values", false);
bank.AddToggle("Enable", &ms_bEVEnabled);
bank.AddSlider("Specular falloff", &ms_fEVSpecFalloff, 0.0f, 500.0f, 0.1f);
bank.AddSlider("Specular intensity", &ms_fEVSpecIntensity, 0.0f, 1.0f, 0.01f);
bank.AddSlider("Specular Fresnel", &ms_fEVSpecFresnel, 0.0f, 1.0f, 0.01f);
bank.AddSlider("Reflectivity", &ms_fEVReflectivity, -10.0f, 10.0f, 0.1f);
bank.AddSlider("Bumpiness", &ms_fEVBumpiness, 0.0f, 10.0f, 0.01f);
bank.AddSlider("BurnoutFX Speed", &ms_fEVBurnoutLevelSpeed,0.0f,1.0f, 0.005f);
bank.AddSlider("Detail Intensity", &ms_fEVDetailIntensity, 0.0f, 100.0f, 0.001f);
bank.AddSlider("Detail Bump Intensity", &ms_fEVDetailBumpIntensity, 0.0f, 100.0f, 0.001f);
bank.AddSlider("Detail Scale", &ms_fEVDetailScale, 0.0f, 100.0f, 0.001f);
bank.AddSlider("EnvEff: Scale", &ms_fEVEnvEffScale, 0.0f, 1.0f, 0.1f);
bank.AddSlider("EnvEff: CPV Add", &ms_fEVEnvEffCpvAdd, 0.0f, 1.0f, 0.1f);
bank.AddSlider("EnvEff: Thickness", &ms_fEVEnvEffThickness, 0.0f, 100.0f, 0.1f);
bank.AddColor("EnvEff: Color Modulator",&ms_fEVEnvEffColorMod);
bank.PushGroup("EnvEff: Zone values (read only)", false);
bank.AddSlider("Scale", &ms_fEVEnvEffZoneScale, 0.0f, 1.0f, 0.1f);
bank.AddSlider("Color Modulator R", &ms_fEVEnvEffZoneColorModR, 0, 255, 1);
bank.AddSlider("Color Modulator G", &ms_fEVEnvEffZoneColorModG, 0, 255, 1);
bank.AddSlider("Color Modulator B", &ms_fEVEnvEffZoneColorModB, 0, 255, 1);
bank.PopGroup();
bank.AddSlider("Fat: Scale", &ms_fEVFatScale, 0.0f, 1.0f, 0.1f);
bank.AddSlider("Fat: Thickness", &ms_fEVFatThickness, 0.0f, 100.0f, 0.1f);
bank.AddSlider("Normal Map: Blend", &ms_fEVNormalBlend, 0.0f, 1.0f, 0.1f);
bank.AddSlider("Stubble Strength", &ms_fEVStubbleStrength, 0.0f,1.0f,0.01f);
bank.AddSlider("Stubble Index", &ms_fEVStubbleIndex, 0.0f,16.0f,1.f);
bank.AddSlider("Stubble Tile", &ms_fEVStubbleTile, 0.0f,100.0f,0.001f);
bank.PushGroup("uMovements", true);
bank.AddSlider("Global ScaleH", (float*)&ms_fEVUmGlobalParams.x, 0.0f, 0.1f, 0.001f);
bank.AddSlider("Global ScaleV", (float*)&ms_fEVUmGlobalParams.y, 0.0f, 0.1f, 0.001f);
bank.AddSlider("Global ArgFreqH", (float*)&ms_fEVUmGlobalParams.z, 0.0f, 10.0f, 0.001f);
bank.AddSlider("Global ArgFreqV", (float*)&ms_fEVUmGlobalParams.w, 0.0f, 10.0f, 0.001f);
bank.AddSeparator();
bank.AddToggle("Use Global Override Values", &ms_bEVUseUmGlobalOverrideValues);
bank.AddSlider("Global Override ScaleH", (float*)&ms_fEVUmGlobalOverrideParams.x, 0.0f, 10.0f, 0.001f);
bank.AddSlider("Global Override ScaleV", (float*)&ms_fEVUmGlobalOverrideParams.y, 0.0f, 10.0f, 0.001f);
bank.AddSlider("Global Override ArgFreqH", (float*)&ms_fEVUmGlobalOverrideParams.z, 0.0f, 10.0f, 0.001f);
bank.AddSlider("Global Override ArgFreqV", (float*)&ms_fEVUmGlobalOverrideParams.w, 0.0f, 10.0f, 0.001f);
bank.PopGroup();
bank.PushGroup("Wind Movement", true);
bank.AddTitle("Motion determines how wind should affect the ped mesh");
bank.AddTitle("Changing these slider will change the way the vertices move on the ped (more of a wave pattern)");
bank.AddToggle("Motion Enabled", &ms_bEVWindMotionEnabled, NullCB, "Determines if wind should affect the Ped's Mesh");
bank.AddSlider("Motion Amp X", &ms_fEVWindMotionAmpX, 0.0f, 256.0f, 1.0f/256.0f, NullCB, "Scaler to control Horizontal size of movement (amplitude)");
bank.AddSlider("Motion Amp Y", &ms_fEVWindMotionAmpY, 0.0f, 256.0f, 1.0f/256.0f, NullCB, "Scaler to control Vertical size of movement (amplitude)");
bank.AddSlider("Motion Freq", &ms_fEVWindMotionFreq, 0.0f, 256.0f, 1.0f/256.0f, NullCB, "Scaler to control Frequency");
bank.AddSeparator();
bank.AddTitle("Response determines the amount of wind to affect the ped mesh");
bank.AddTitle("Vel min/max determines the curve for the wind factor (between 0-1)");
bank.AddToggle("Wind Response Enabled", &ms_bEVWindResponseEnabled, NullCB, "Determines if wind response should be enabled");
bank.AddSlider("Min Wind Speed for cloth movement", &ms_fEVWindResponseVelMin, 0.0f, 100.0f, 1.0f/256.0f);
bank.AddSlider("Max Wind Speed for cloth movement", &ms_fEVWindResponseVelMax, 0.0f, 100.0f, 1.0f/256.0f);
bank.AddSlider("Wind Flutter Intensity", &ms_fEVWindFlutterIntensity,0.0f, 100.0f, 1.0f/256.0f, NullCB, "Determines amplitude(size) of movement");
bank.PopGroup();
bank.PushGroup("Aniso Hair");
bank.AddSlider("Aniso Intensities", &ms_fEVAnisotropicSpecularIntensity.x, 0.0f,0.2f,0.01f);
bank.AddSlider("Aniso Intensities", &ms_fEVAnisotropicSpecularIntensity.y, 0.0f,0.2f,0.01f);
bank.AddSlider("Aniso Exponents", &ms_fEVAnisotropicSpecularExponent.x, 0.001f,100.0f,0.01f);
bank.AddSlider("Aniso Exponents", &ms_fEVAnisotropicSpecularExponent.y, 0.001f,100.0f,0.01f);
bank.AddColor("2nd Aniso Colour", &ms_fEVAnisotropicSpecularColour);
bank.AddSlider("Aniso UV scales", &ms_fEVSpecularNoiseMapUVScaleFactor.x, 0.01f,10.0f,0.01f);
bank.AddSlider("Aniso UV scales", &ms_fEVSpecularNoiseMapUVScaleFactor.y, 0.01f,10.0f,0.01f);
bank.AddSlider("Aniso UV scales", &ms_fEVSpecularNoiseMapUVScaleFactor.z, 0.01f,10.0f,0.01f);
bank.AddSlider("Aniso UV scales", &ms_fEVSpecularNoiseMapUVScaleFactor.w, 0.01f,10.0f,0.01f);
bank.AddSlider("Aniso Alpha Bias", &ms_fEVAnisotropicAlphaBias, 0.0f,1.0f,0.01f);
bank.PopGroup();
bank.AddSlider("Sweat: Scale", &ms_fEVSweatScale, 0.0f, 1.0f, 0.1f);
bank.AddSlider("Wet Cloth Diffuse Adjust", &ms_fEVWetClothesAdjust.x, 0.0f,1.0f,0.01f);
bank.AddSlider("Wet Specular Exponent Adjust", &ms_fEVWetClothesAdjust.y, 0.0f,100.0f,0.01f);
bank.AddSlider("Wet Specular Intensity Adjust", &ms_fEVWetClothesAdjust.z, 0.0f,100.0f,0.01f);
bank.AddSlider("Wet Fade range", &ms_fEVWetClothesAdjust.w, 0.0f,0.3f,0.01f);
bank.AddSlider("More Wet Cloth Diffuse Adjust", &ms_fEVWetClothesAdjustMoreWet.x, 0.0f,1.0f,0.01f);
bank.AddSlider("More Wet Specular Exponent Adjust", &ms_fEVWetClothesAdjustMoreWet.y, 0.0f,100.0f,0.01f);
bank.AddSlider("More Wet Specular Intensity Adjust",&ms_fEVWetClothesAdjustMoreWet.z, 0.0f,100.0f,0.01f);
bank.AddSlider("More Wet Fade range", &ms_fEVWetClothesAdjustMoreWet.w, 0.0f,0.3f,0.01f);
bank.AddSlider("Less Wet Cloth Diffuse Adjust", &ms_fEVWetClothesAdjustLessWet.x, 0.0f,1.0f,0.01f);
bank.AddSlider("Less Wet Specular Exponent Adjust", &ms_fEVWetClothesAdjustLessWet.y, 0.0f,100.0f,0.01f);
bank.AddSlider("Less Wet Specular Intensity Adjust",&ms_fEVWetClothesAdjustLessWet.z, 0.0f,100.0f,0.01f);
bank.AddSlider("Less Wet Fade range", &ms_fEVWetClothesAdjustLessWet.w, 0.0f,0.3f,0.01f);
// have the hair system init some widgets too
CShaderHairSort::InitWidgets(bank);
bank.AddText("Current drawable name:", GetPedVariationMgrDrawableName(), GetPedVariationMgrDrawableNameLen(), true);
bank.AddButton("Save settings for current drawable to '" SHADER_SETTINGS_FNAME "'.", _SaveDataCB, "Saves current shader settings to a file.");
bank.PopGroup();
bank.PushGroup("Ped Blendshapes", false);
bank.AddToggle("Force all weights", &ms_bBlendshapeForceAll, NullCB, "");
bank.AddToggle("Force specific weight", &ms_bBlendshapeForceSpecific, NullCB, "");
bank.AddSlider("Weight index", &ms_nBlendshapeForceSpecificIdx, 0, 100, 1, NullCB, "");
bank.AddSlider("Weight value", &ms_fBlendshapeForceSpecificBlend, 0.0f, 100.0f, 0.1f, NullCB, "");
bank.PopGroup();
bank.PushGroup("Ped Detail");
bank.AddSlider("Fade Range Start", &ms_DetailFadeOut[0].x, 0.0f, 64.0f, 1.0f/256.0f);
bank.AddSlider("Fade Range End", &ms_DetailFadeOut[0].y, 0.0f, 64.0f, 1.0f/256.0f);
bank.AddSlider("Burnout: Fade Range Start", &ms_DetailFadeOut[1].x, 0.0f, 64.0f, 1.0f/256.0f);
bank.AddSlider("Burnout: Fade Range End", &ms_DetailFadeOut[1].y, 0.0f, 64.0f, 1.0f/256.0f);
bank.PopGroup();
return(TRUE);
}// end of InitWidgets()...
//
//
//
//
bool CCustomShaderEffectPed::SaveCurrentShaderSettingsToFile()
{
char buf[2048];
FileHandle fd = CFileMgr::OpenFileForAppending(SHADER_SETTINGS_FNAME);
if(fd == INVALID_FILE_HANDLE)
{ // new file opened:
fd = CFileMgr::OpenFileForWriting(SHADER_SETTINGS_FNAME);
if(fd == INVALID_FILE_HANDLE)
return(FALSE);
::sprintf(buf, "#(\n"); // opening global bracket
CFileMgr::Write(fd, buf, istrlen(buf));
}
else
{ // appending to existing file:
s32 currPos = CFileMgr::Tell(fd);
CFileMgr::Seek(fd, currPos-3); // eat up closing global bracket '\n)\n'
::sprintf(buf, ",\n"); // attach to global array
CFileMgr::Write(fd, buf, istrlen(buf));
}
::sprintf(buf, "#(\n"); // opening local bracket
CFileMgr::Write(fd, buf, istrlen(buf));
::sprintf(buf,
"#(\"ped_name\", \"%s\"),\n"
"#(\"drawable_name\", \"%s\"),\n"
""
"#(\"specular falloff\", %.5f),\n"
"#(\"specular intensity\", %.5f),\n"
"#(\"specular fresnel\", %.5f),\n"
"#(\"bumpiness\", %.5f),\n"
""
"#(\"detail inten bump scale\", [%.5f, %.5f, %.5f]),\n"
"#(\"EnvEfFatMaxThick\", [%.5f, %.5f]),\n"
""
"#(\"Stubble Growth\", %.5f),\n"
"#(\"Index,Tiling\", [%.5f, %.5f]),\n"
""
"#(\"wind:sclhv/frqhv\", [%.5f, %.5f, %.5f, %.5f]),\n"
""
"#(\"aniso intensities\", [%.5f, %.5f]),\n"
"#(\"aniso exponents\", [%.5f, %.5f]),\n"
"#(\"2nd aniso colour\", [%.5f, %.5f, %.5f, %.5f]),\n"
"#(\"aniso uv scales\", [%.5f, %.5f, %.5f, %.5f]),\n"
"#(\"aniso alpha bias\", %.5f)\n"
"#(\"wet clothes adjust\", [%.5f, %.5f, %.5f, %.5f]),\n"
"#(\"more wet clothes adjust\", [%.5f, %.5f, %.5f, %.5f]),\n"
"#(\"less wet clothes adjust\", [%.5f, %.5f, %.5f, %.5f]),\n"
""
,
CPedVariationDebug::pedNames[CPedVariationDebug::currPedNameSelection+1],
GetPedVariationMgrDrawableName(),
ms_fEVSpecFalloff,
ms_fEVSpecIntensity,
ms_fEVSpecFresnel,
ms_fEVBumpiness,
ms_fEVDetailIntensity,
ms_fEVDetailBumpIntensity,
ms_fEVDetailScale,
ms_fEVEnvEffThickness, ms_fEVFatThickness,
ms_fEVStubbleStrength,
ms_fEVStubbleIndex, ms_fEVStubbleTile,
ms_fEVUmGlobalParams.x, ms_fEVUmGlobalParams.y, ms_fEVUmGlobalParams.z, ms_fEVUmGlobalParams.w,
ms_fEVAnisotropicSpecularIntensity.x, ms_fEVAnisotropicSpecularIntensity.y,
ms_fEVAnisotropicSpecularExponent.x, ms_fEVAnisotropicSpecularExponent.y,
ms_fEVAnisotropicSpecularColour.GetRedf(), ms_fEVAnisotropicSpecularColour.GetGreenf(), ms_fEVAnisotropicSpecularColour.GetBluef(), ms_fEVAnisotropicSpecularColour.GetAlphaf(),
ms_fEVSpecularNoiseMapUVScaleFactor.x, ms_fEVSpecularNoiseMapUVScaleFactor.y, ms_fEVSpecularNoiseMapUVScaleFactor.z, ms_fEVSpecularNoiseMapUVScaleFactor.w,
ms_fEVAnisotropicAlphaBias,
ms_fEVWetClothesAdjust.x,ms_fEVWetClothesAdjust.y,ms_fEVWetClothesAdjust.z,ms_fEVWetClothesAdjust.w,
ms_fEVWetClothesAdjustMoreWet.x,ms_fEVWetClothesAdjustMoreWet.y,ms_fEVWetClothesAdjustMoreWet.z,ms_fEVWetClothesAdjustMoreWet.w,
ms_fEVWetClothesAdjustLessWet.x,ms_fEVWetClothesAdjustLessWet.y,ms_fEVWetClothesAdjustLessWet.z,ms_fEVWetClothesAdjustLessWet.w
);
CFileMgr::Write(fd, buf, istrlen(buf));
::sprintf(buf, ")\n"); // closing local bracket
CFileMgr::Write(fd, buf, istrlen(buf));
::sprintf(buf, ")\n"); // closing global bracket
CFileMgr::Write(fd, buf, istrlen(buf));
CFileMgr::CloseFile(fd);
fd = INVALID_FILE_HANDLE;
return(TRUE);
}
#endif //CSE_PED_EDITABLEVALUES...