1487 lines
47 KiB
C++
1487 lines
47 KiB
C++
//
|
|
// Filename: CustomShaderEffectGrass.cpp
|
|
// Description: Class for controlling grass shader variables
|
|
//
|
|
//
|
|
|
|
#include "CustomShaderEffectGrass.h"
|
|
|
|
// Rage headers
|
|
#include "fwdrawlist/drawlistmgr.h"
|
|
#include "grmodel/ShaderFx.h"
|
|
#include "grmodel/Geometry.h"
|
|
#include "grcore/texturereference.h"
|
|
#include "rmcore/drawable.h"
|
|
|
|
// Game headers
|
|
#include "camera/CamInterface.h"
|
|
#include "camera/Cinematic/CinematicDirector.h"
|
|
#include "debug/debug.h"
|
|
#include "game/ModelIndices.h"
|
|
#include "objects/Object.h"
|
|
#include "objects/ProceduralInfo.h"
|
|
#include "Peds/ped.h"
|
|
#include "renderer/render_channel.h"
|
|
#include "renderer/PlantsGrassRenderer.h"
|
|
#include "shader_source/Vegetation/Grass/grass_regs.h"
|
|
#include "scene/Entity.h"
|
|
#include "scene/EntityBatch.h"
|
|
#include "scene/world/GameWorld.h"
|
|
#include "script/script_channel.h"
|
|
#include "vehicles/Vehicle.h"
|
|
#include "vehicles/Automobile.h"
|
|
#include "shaders/ShaderLib.h"
|
|
#include "renderer/DrawLists/drawlist.h"
|
|
#include "renderer/RenderPhases/RenderPhaseCascadeShadows.h"
|
|
|
|
#if HACK_RDR3
|
|
#include "renderer/Entities/TrailMapRenderer.h"
|
|
#endif
|
|
|
|
#include "../shader_source/Lighting/Shadows/cascadeshadows_common.fxh"
|
|
|
|
RENDER_OPTIMISATIONS();
|
|
|
|
static dev_float PLAYER_COLL_RADIUS0 = 0.75f; // radius of influence
|
|
|
|
namespace CSEGrassStatic
|
|
{
|
|
// script vehicle:
|
|
bool sm_ScrVehEnabled = false;
|
|
spdAABB sm_ScrVehAABB(Vec3V(V_FLT_MAX), -Vec3V(V_FLT_MAX)); //Initialize as invalid AABB.
|
|
Vec3V sm_ScrVehB(V_ZERO_WONE);
|
|
Vec3V sm_ScrVehM(V_ZERO_WONE);
|
|
float sm_ScrVehRadius = 0.0f;
|
|
float sm_ScrVehGroundZ = 0.0f;
|
|
|
|
BankBool sm_ScrVehDebugDraw = false;
|
|
BankBool sm_ScrVehAllowEntityIntersection = true;
|
|
|
|
void ClearScriptVehicle()
|
|
{
|
|
sm_ScrVehAABB.Invalidate();
|
|
sm_ScrVehEnabled = false;
|
|
sm_ScrVehB = Vec3V(V_ZERO_WONE);
|
|
sm_ScrVehM = Vec3V(V_ZERO_WONE);
|
|
sm_ScrVehRadius = 0.0f;
|
|
sm_ScrVehGroundZ = 0.0f;
|
|
}
|
|
|
|
float ProbeForMinGroundPos(const spdAABB &aabb, ScalarV groundZ = ScalarV(V_FLT_MAX))
|
|
{
|
|
static dev_float fMinGroundAdjust = 0.0f;
|
|
|
|
Vec3V boxMin = aabb.GetMin();
|
|
Vec3V boxMax = aabb.GetMax();
|
|
ScalarV probeDistance = (boxMax.GetZ() - boxMin.GetZ()) * ScalarV(V_NEGSIXTEEN);
|
|
rage::atRangeArray<Vec3V, 4> probePos((Vec3V(V_ZERO_WONE)));
|
|
probePos[0] = rage::GetFromTwo<Vec::X1, Vec::Y1, Vec::Z2>(boxMin, boxMax);
|
|
probePos[1] = rage::GetFromTwo<Vec::X1, Vec::Y2, Vec::Z2>(boxMin, boxMax);
|
|
probePos[2] = boxMax; //rage::GetFromTwo<Vec::X2, Vec::Y2, Vec::Z2>(boxMin, boxMax);
|
|
probePos[3] = rage::GetFromTwo<Vec::X2, Vec::Y1, Vec::Z2>(boxMin, boxMax);
|
|
|
|
//Make sure script ground Z is the minimum for the AABB.
|
|
ScalarV minGroundZ(groundZ);
|
|
for(u32 i = 0; i < 4; ++i)
|
|
{
|
|
WorldProbe::CShapeTestProbeDesc probeDesc;
|
|
WorldProbe::CShapeTestHitPoint probeIsect;
|
|
WorldProbe::CShapeTestResults probeResult(probeIsect);
|
|
probeDesc.SetStartAndEnd(VEC3V_TO_VECTOR3(probePos[i]), VEC3V_TO_VECTOR3(probePos[i] + (Vec3V(V_UP_AXIS_WZERO) * probeDistance)));
|
|
probeDesc.SetResultsStructure(&probeResult);
|
|
probeDesc.SetStateIncludeFlags(phLevelBase::STATE_FLAG_FIXED);
|
|
probeDesc.SetIncludeFlags(ArchetypeFlags::GTA_ALL_MAP_TYPES);
|
|
probeDesc.SetContext(WorldProbe::ENotSpecified);
|
|
|
|
if(WorldProbe::GetShapeTestManager()->SubmitTest(probeDesc))
|
|
minGroundZ = Min(probeResult[0].GetHitPositionV().GetZ(), minGroundZ);
|
|
}
|
|
//scriptAssertf(groundZ != ScalarV(V_FLT_MAX), "None of the grass flattening AABB probes successfully found a ground intersection, and no value was provided!");
|
|
|
|
return minGroundZ.Getf() + fMinGroundAdjust;
|
|
}
|
|
|
|
void SetScriptVehicle(const spdSphere &sphere, Vec3V_In look, ScalarV_In groundZ = ScalarV(V_FLT_MAX))
|
|
{
|
|
scriptAssertf(!sm_ScrVehEnabled, "Grass Flatten AABB already set. Setting again without clearing will overwrite previous entry.");
|
|
sm_ScrVehEnabled = true;
|
|
|
|
sm_ScrVehAABB.Invalidate();
|
|
sm_ScrVehAABB.GrowSphere(sphere);
|
|
|
|
if(IsEqualAll(look, Vec3V(V_ZERO)))
|
|
{
|
|
#if RSG_DURANGO
|
|
// hack for B*4230572 (XB1: Grass can be seen clipping through lift when entering facility):
|
|
sm_ScrVehM = Vec3V(V_ZERO);
|
|
sm_ScrVehB = sphere.GetCenter();
|
|
sm_ScrVehRadius = sphere.GetRadiusf() * 2.0f;
|
|
#else
|
|
sm_ScrVehM = NormalizeSafe(look, Vec3V(V_FLT_MAX)) * sphere.GetRadius();
|
|
sm_ScrVehB = sphere.GetCenter() - (sm_ScrVehM * ScalarV(V_HALF));
|
|
sm_ScrVehRadius = sphere.GetRadiusf();
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
sm_ScrVehM = Normalize(look) * sphere.GetRadius();
|
|
sm_ScrVehB = sphere.GetCenter() - (sm_ScrVehM * ScalarV(V_HALF));
|
|
sm_ScrVehRadius = sphere.GetRadiusf();
|
|
}
|
|
|
|
|
|
sm_ScrVehGroundZ = ProbeForMinGroundPos(sm_ScrVehAABB, groundZ);
|
|
}
|
|
|
|
void SetScriptVehicle(const spdAABB &aabb, Vec3V_In look, ScalarV_In groundZ = ScalarV(V_FLT_MAX))
|
|
{
|
|
scriptAssertf(!sm_ScrVehEnabled, "Grass Flatten AABB already set. Setting again without clearing will overwrite previous entry.");
|
|
sm_ScrVehEnabled = true;
|
|
sm_ScrVehAABB = aabb;
|
|
|
|
if(IsEqualAll(look, Vec3V(V_ZERO)))
|
|
{
|
|
#if RSG_DURANGO
|
|
// hack for B*4230572 (XB1: Grass can be seen clipping through lift when entering facility):
|
|
sm_ScrVehM = Vec3V(V_ZERO);
|
|
sm_ScrVehB = aabb.GetCenter();
|
|
#else
|
|
sm_ScrVehM = NormalizeSafe(look, Vec3V(V_FLT_MAX)) * aabb.GetExtent();
|
|
sm_ScrVehB = aabb.GetCenter() - (sm_ScrVehM * ScalarV(V_HALF));
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
sm_ScrVehM = Normalize(look) * aabb.GetExtent();
|
|
sm_ScrVehB = aabb.GetCenter() - (sm_ScrVehM * ScalarV(V_HALF));
|
|
}
|
|
|
|
|
|
sm_ScrVehRadius = Mag(sm_ScrVehM).Getf();
|
|
sm_ScrVehGroundZ = ProbeForMinGroundPos(sm_ScrVehAABB, groundZ);
|
|
}
|
|
|
|
bool IntersectsScriptVehicleAABB(fwEntity *entity)
|
|
{
|
|
if(entity && sm_ScrVehEnabled && sm_ScrVehAllowEntityIntersection)
|
|
{
|
|
spdAABB aabb;
|
|
entity->GetAABB(aabb);
|
|
return aabb.IntersectsAABB(sm_ScrVehAABB);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
namespace EBStatic
|
|
{
|
|
#if __BANK
|
|
extern BankFloat sDebugDrawGrassTerrainNormalConeLength;
|
|
extern BankFloat sDebugDrawGrassTerrainNormalConeRadius;
|
|
extern BankBool sDebugDrawGrassTerrainNormalConeCap;
|
|
#endif
|
|
#if RSG_PC
|
|
extern u32 sPerfSkipInstance;
|
|
extern bool bPerfForceSkipInstance;
|
|
#endif //RSG_PC...
|
|
}
|
|
|
|
namespace CSEGrassBankStatic
|
|
{
|
|
BankBool sm_bEnableMicroMovements= true;
|
|
BankBool sm_bEnableWinBending = true;
|
|
BankBool sm_bOverrideAO = false;
|
|
BankFloat sm_fGlobalA0 = GRASS_GLOBAL_AO;
|
|
BankBool sm_bAlphaOverdraw = false;
|
|
|
|
#if __BANK
|
|
Vec3V sm_ScrVehCreateAABBMin(V_ZERO_WONE);
|
|
Vec3V sm_ScrVehCreateAABBMax(V_ZERO_WONE);
|
|
Vec4V sm_ScrVehCreateSphere(V_ZERO_WONE);
|
|
Vec3V sm_ScrVehCreateLook(V_Y_AXIS_WONE);
|
|
|
|
void ScriptVehicleClearFromRag()
|
|
{
|
|
CSEGrassStatic::ClearScriptVehicle();
|
|
}
|
|
|
|
void ScriptVehicleCreateFromAABB()
|
|
{
|
|
sm_ScrVehCreateLook = Normalize(sm_ScrVehCreateLook);
|
|
ScriptVehicleClearFromRag();
|
|
CSEGrassStatic::SetScriptVehicle(spdAABB(sm_ScrVehCreateAABBMin, sm_ScrVehCreateAABBMax), sm_ScrVehCreateLook);
|
|
}
|
|
|
|
void ScriptVehicleCreateFromSphere()
|
|
{
|
|
sm_ScrVehCreateLook = Normalize(sm_ScrVehCreateLook);
|
|
ScriptVehicleClearFromRag();
|
|
CSEGrassStatic::SetScriptVehicle(spdSphere(sm_ScrVehCreateSphere), sm_ScrVehCreateLook);
|
|
}
|
|
|
|
void ScriptVehicleCreate_GetAABBFromPed()
|
|
{
|
|
if(CPed *player = CGameWorld::FindLocalPlayer())
|
|
{
|
|
spdAABB aabb;
|
|
player->GetAABB(aabb);
|
|
sm_ScrVehCreateAABBMin = aabb.GetMin();
|
|
sm_ScrVehCreateAABBMax = aabb.GetMax();
|
|
|
|
sm_ScrVehCreateLook = player->GetTransform().GetB();
|
|
}
|
|
}
|
|
|
|
void ScriptVehicleCreate_GetSphereFromPed()
|
|
{
|
|
if(CPed *player = CGameWorld::FindLocalPlayer())
|
|
{
|
|
sm_ScrVehCreateLook = player->GetTransform().GetB();
|
|
|
|
spdAABB aabb;
|
|
player->GetAABB(aabb);
|
|
ScalarV radius = Mag(Normalize(sm_ScrVehCreateLook) * aabb.GetExtent());
|
|
sm_ScrVehCreateSphere = Vec4V(player->GetTransform().GetPosition(), radius);
|
|
}
|
|
}
|
|
|
|
void ScriptVehicleCreate_CreateFromPedAABB()
|
|
{
|
|
ScriptVehicleCreate_GetAABBFromPed();
|
|
ScriptVehicleCreateFromAABB();
|
|
}
|
|
|
|
void ScriptVehicleCreate_CreateFromPedSphere()
|
|
{
|
|
ScriptVehicleCreate_GetSphereFromPed();
|
|
ScriptVehicleCreateFromSphere();
|
|
}
|
|
|
|
void AddWidgets(bkBank &bank)
|
|
{
|
|
bank.PushGroup("CSEGrass");
|
|
{
|
|
bank.AddToggle("Enable MicroMovements", &sm_bEnableMicroMovements);
|
|
bank.AddToggle("Enable Wind Bending", &sm_bEnableWinBending);
|
|
bank.AddToggle("Alpha Overdraw", &sm_bAlphaOverdraw);
|
|
bank.PushGroup("Global AO");
|
|
bank.AddToggle("Enable Edit", &sm_bOverrideAO);
|
|
bank.AddSlider("Global AO", &sm_fGlobalA0, 0.0f, 1.0f, 0.01f);
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Script Vehicle");
|
|
{
|
|
bank.AddToggle("Debug Draw", &CSEGrassStatic::sm_ScrVehDebugDraw);
|
|
bank.AddToggle("Allow culling entities intersecting Script Vehicle AABB", &CSEGrassStatic::sm_ScrVehAllowEntityIntersection);
|
|
|
|
bank.PushGroup("Debug Create");
|
|
{
|
|
bank.AddTitle("Debug widgets to simulate script command to create invisible script vehicle.");
|
|
bank.AddVector("AABB Min", &sm_ScrVehCreateAABBMin, -FLT_MAX / 1000.0f, FLT_MAX / 1000.0f, 0.1f);
|
|
bank.AddVector("AABB Max", &sm_ScrVehCreateAABBMax, -FLT_MAX / 1000.0f, FLT_MAX / 1000.0f, 0.1f);
|
|
bank.AddTitle("");
|
|
bank.AddVector("Sphere", &sm_ScrVehCreateSphere, -FLT_MAX / 1000.0f, FLT_MAX / 1000.0f, 0.1f);
|
|
bank.AddTitle("");
|
|
bank.AddVector("Look", &sm_ScrVehCreateLook, -1.0f, 1.0f, 0.1f);
|
|
bank.AddTitle("");
|
|
bank.AddButton("Create Script Vehicle From Ped AABB", &ScriptVehicleCreate_CreateFromPedAABB);
|
|
bank.AddButton("Create Script Vehicle From Ped Sphere", &ScriptVehicleCreate_CreateFromPedSphere);
|
|
bank.AddTitle("");
|
|
bank.AddButton("Create Script Vehicle From AABB", &ScriptVehicleCreateFromAABB);
|
|
bank.AddButton("Create Script Vehicle From Sphere", &ScriptVehicleCreateFromSphere);
|
|
bank.AddButton("Clear Script Vehicle", &ScriptVehicleClearFromRag);
|
|
bank.AddTitle("");
|
|
bank.AddButton("Get Ped AABB", &ScriptVehicleCreate_GetAABBFromPed);
|
|
bank.AddButton("Get Ped Sphere", &ScriptVehicleCreate_GetSphereFromPed);
|
|
}
|
|
bank.PopGroup();
|
|
|
|
bank.PushGroup("Vars");
|
|
{
|
|
bank.AddToggle("Enable Script Vehicle", &CSEGrassStatic::sm_ScrVehEnabled);
|
|
bank.AddVector("Vec B", &CSEGrassStatic::sm_ScrVehB, -FLT_MAX / 1000.0f, FLT_MAX / 1000.0f, 0.1f);
|
|
bank.AddVector("Vec M", &CSEGrassStatic::sm_ScrVehM, -FLT_MAX / 1000.0f, FLT_MAX / 1000.0f, 0.1f);
|
|
bank.AddSlider("Radius", &CSEGrassStatic::sm_ScrVehRadius, 0.0f, FLT_MAX / 1000.0f, 0.1f);
|
|
bank.AddSlider("GroundZ", &CSEGrassStatic::sm_ScrVehGroundZ, -FLT_MAX / 1000.0f, FLT_MAX / 1000.0f, 0.1f);
|
|
}
|
|
bank.PopGroup();
|
|
}
|
|
bank.PopGroup();
|
|
}
|
|
bank.PopGroup();
|
|
}
|
|
|
|
void RenderDebug()
|
|
{
|
|
if(CSEGrassStatic::sm_ScrVehEnabled && CSEGrassStatic::sm_ScrVehDebugDraw)
|
|
{
|
|
static Color32 sYellow = Color32(1.0f, 1.0f, 0.0f, 1.0f);
|
|
static Color32 sBlue = Color32(0.0f, 0.0f, 1.0f, 1.0f);
|
|
|
|
//Draw AABB
|
|
grcDebugDraw::BoxAxisAligned(CSEGrassStatic::sm_ScrVehAABB.GetMin(), CSEGrassStatic::sm_ScrVehAABB.GetMax(), sYellow, false);
|
|
|
|
//Draw B+M vec.
|
|
Vec3V v1 = CSEGrassStatic::sm_ScrVehB;
|
|
Vec3V v2 = CSEGrassStatic::sm_ScrVehB + CSEGrassStatic::sm_ScrVehM;
|
|
grcDebugDraw::Line(v1, v2, sBlue);
|
|
|
|
ScalarV coneLen(EBStatic::sDebugDrawGrassTerrainNormalConeLength / 2.0f); //0.3 / 2.0f);
|
|
Vec3V c1 = v2 + (CSEGrassStatic::sm_ScrVehM * coneLen);
|
|
Vec3V c2 = v2 - (CSEGrassStatic::sm_ScrVehM * coneLen);
|
|
grcDebugDraw::Cone(c1, c2, EBStatic::sDebugDrawGrassTerrainNormalConeRadius, sBlue, EBStatic::sDebugDrawGrassTerrainNormalConeCap); //0.07, sBlue, true);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
inline u8 LookupGroupVar(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 LookupGlobalVar(const char *name, bool mustExist)
|
|
{
|
|
grcEffectGlobalVar varID = grcEffect::LookupGlobalVar(name, mustExist);
|
|
Assert((int)varID < 256); // must fit into u8
|
|
return static_cast<u8>(varID);
|
|
}
|
|
|
|
//
|
|
//
|
|
// initializes all instances of the effect class;
|
|
// to be called once, when "master" class is created;
|
|
//
|
|
bool CCustomShaderEffectGrassType::Initialise(rmcDrawable *pDrawable)
|
|
{
|
|
Assert(pDrawable);
|
|
|
|
grmShaderGroup *pShaderGroup = &pDrawable->GetShaderGroup();
|
|
|
|
//Initialize CS shader params
|
|
{
|
|
m_CSVars.m_idVarInstanceBuffer = pShaderGroup->LookupVar("InstanceBuffer", false);
|
|
m_CSVars.m_idVarRawInstBuffer = pShaderGroup->LookupVar("RawInstanceBuffer", false);
|
|
m_CSVars.m_idVarUseCSOutputBuffer = pShaderGroup->LookupVar("gUseComputeShaderOutputBuffer", false);
|
|
|
|
m_CSVars.m_idAabbMin = pShaderGroup->LookupVar("vecBatchAabbMin0");
|
|
m_CSVars.m_idAabbDelta = pShaderGroup->LookupVar("vecBatchAabbDelta0");
|
|
m_CSVars.m_idScaleRange = pShaderGroup->LookupVar("gScaleRange");
|
|
|
|
//Find compute shader index
|
|
for(int i = 0; i < pShaderGroup->GetCount(); ++i)
|
|
{
|
|
grmShader &shader = pShaderGroup->GetShader(i);
|
|
if(shader.LookupTechnique("BatchCull", false) != grcetNONE)
|
|
{
|
|
m_CSVars.m_ShaderIndex = i;
|
|
for(int i = 0; i < m_CSVars.m_idVarAppendInstBuffer.size(); ++i)
|
|
{
|
|
char buff[32];
|
|
formatf(buff, "VisibleInstanceBuffer%d", i);
|
|
m_CSVars.m_idVarAppendInstBuffer[i] = shader.LookupVar(buff);
|
|
}
|
|
DURANGO_ONLY(GRASS_BATCH_CS_DYNAMIC_BUFFERS_ONLY(m_CSVars.m_idIndirectArgs = shader.LookupVar("IndirectArgs")));
|
|
m_CSVars.m_idInstCullParams = shader.LookupVar("gInstCullParams");
|
|
m_CSVars.m_idNumClipPlanes = shader.LookupVar("gNumClipPlanes");
|
|
m_CSVars.m_idClipPlanes = shader.LookupVar("gClipPlanes");
|
|
|
|
m_CSVars.m_idCameraPosition = shader.LookupVar("gCameraPosition");
|
|
m_CSVars.m_idLodInstantTransition = shader.LookupVar("gLodInstantTransition");
|
|
#if RSG_DURANGO || RSG_PC
|
|
m_CSVars.m_idGrassSkipInstance = shader.LookupVar("gGrassSkipInstance",false);
|
|
#endif // RSG_DURANGO || RSG_PC...
|
|
m_CSVars.m_idLodThresholds = shader.LookupVar("gLodThresholds");
|
|
m_CSVars.m_idCrossFadeDistance = shader.LookupVar("gCrossFadeDistance");
|
|
|
|
m_CSVars.m_idIsShadowPass = shader.LookupVar("gIsShadowPass");
|
|
m_CSVars.m_idLodFadeControlRange = shader.LookupVar("gLodFadeControlRange");
|
|
DURANGO_ONLY(m_CSVars.m_idIndirectCountPerLod = shader.LookupVar("gIndirectCountPerLod"));
|
|
break;
|
|
}
|
|
}
|
|
|
|
m_CSVars.UpdateValidity();
|
|
}
|
|
|
|
m_idOrientToTerrain = LookupGroupVar(pShaderGroup, "gOrientToTerrain", false);
|
|
m_idPlayerPos = LookupGroupVar(pShaderGroup, "vecPlayerPos0", false);
|
|
|
|
m_idWindBending = LookupGroupVar(pShaderGroup, "gWindBendingGlobals", false);
|
|
m_idLodFadeInstRange = LookupGroupVar(pShaderGroup, "gLodFadeInstRange", false);
|
|
|
|
#if ENABLE_TRAIL_MAP
|
|
m_idTrailMapTexture = LookupGroupVar(pShaderGroup, "trailMapTexture0", false);
|
|
m_idMapSizeWorldSpace = LookupGroupVar(pShaderGroup, "mapSizeWorldSpace", false);
|
|
#endif
|
|
|
|
//Do we want to set any of these?
|
|
//groundPolyVertPos0
|
|
//gStippleThreshold
|
|
|
|
m_idCollParams = LookupGroupVar(pShaderGroup, "vecCollParams0", false);
|
|
|
|
//Micromovement Params
|
|
m_idFadeAlphaDistUmTimer = LookupGroupVar(pShaderGroup, "fadeAlphaDistUmTimer0", false);
|
|
|
|
m_idFakedGrassNormal = LookupGroupVar(pShaderGroup, "fakedGrassNormal0", false);
|
|
|
|
m_idDebugSwitches = LookupGroupVar(pShaderGroup, "bDebugSwitches0", false);
|
|
|
|
for(u32 i=0; i<NUM_COL_VEH; i++)
|
|
{
|
|
char var_name[128];
|
|
|
|
formatf(var_name, "bVehColl%dEnabled0", i); // bVehColl0Enabled0
|
|
m_idVarVehCollEnabled[i]= LookupGlobalVar(var_name, false);
|
|
|
|
formatf(var_name, "vecVehColl%dB0", i); // vecVehColl0B0
|
|
m_idVarVehCollB0[i] = LookupGroupVar(pShaderGroup, var_name, false);
|
|
|
|
formatf(var_name, "vecVehColl%dM0", i); // vecVehColl0M0
|
|
m_idVarVehCollM0[i] = LookupGroupVar(pShaderGroup, var_name, false);
|
|
|
|
formatf(var_name, "vecVehColl%dR0", i); // "vecVehColl0R0"
|
|
m_idVarVehCollR0[i] = LookupGroupVar(pShaderGroup, var_name, false);
|
|
}
|
|
|
|
#if DEVICE_MSAA
|
|
m_idAlphaToCoverageScale = LookupGroupVar(pShaderGroup, "gAlphaToCoverageScale", false);
|
|
#endif
|
|
|
|
static dev_float maxVehCollisionDist = 25.0f; // 25m distance
|
|
m_fMaxVehicleCollisionDist = maxVehCollisionDist;
|
|
|
|
return(TRUE);
|
|
}// end of CCustomShaderEffectGrass::Initialise()...
|
|
|
|
CCustomShaderEffectGrassType::~CCustomShaderEffectGrassType()
|
|
{
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
CCustomShaderEffectBase* CCustomShaderEffectGrassType::CreateInstance(CEntity* pEntity)
|
|
{
|
|
CCustomShaderEffectGrass *pNewShaderEffect = rage_new CCustomShaderEffectGrass;
|
|
pNewShaderEffect->m_pType = this;
|
|
|
|
float phaseShift = 0.0f;
|
|
spdAABB aabb;
|
|
Vec3V scaleRange(1.0f, 1.0f, 0.0f);
|
|
float orientToTerrain = 0.0f;
|
|
Vec3V lodFadeInstRange(V_ONE_WZERO);
|
|
if(pEntity)
|
|
{
|
|
// calculate localized micro-movement phase shift based on xy coords of the tree:
|
|
const Vec3V entityPos = pEntity->GetTransform().GetPosition();
|
|
const u32 phaseShiftX = u32( Abs(entityPos.GetXf()*10.0f) )&0x7f;
|
|
const u32 phaseShiftY = u32( Abs(entityPos.GetYf()*10.0f) )&0x7f;
|
|
phaseShift = float(phaseShiftX+phaseShiftY)/255.0f - 1.0f;
|
|
|
|
pEntity->GetAABB(aabb);
|
|
|
|
if(Verifyf(pEntity->GetIsTypeGrassInstanceList(), "WARNING: Entity type (%s) is not of type Grass Batch!", pEntity->GetModelName()))
|
|
{
|
|
CGrassBatch *eb = static_cast<CGrassBatch *>(pEntity);
|
|
scaleRange = eb->GetInstanceList()->m_ScaleRange;
|
|
orientToTerrain = eb->GetInstanceList()->m_OrientToTerrain;
|
|
lodFadeInstRange = eb->GetInstanceList()->ComputeLodInstFadeRange(ScalarV(eb->GetDistanceToCamera()));
|
|
}
|
|
}
|
|
pNewShaderEffect->m_umPhaseShift = phaseShift;
|
|
|
|
pNewShaderEffect->m_AabbMin = aabb.GetMin();
|
|
pNewShaderEffect->m_AabbDelta = aabb.GetMax() - aabb.GetMin();
|
|
pNewShaderEffect->m_scaleRange = scaleRange;
|
|
|
|
//Set W components of Vec3V vars to 0 so x64 build doesn't complain about setting shader vars to QNAN.
|
|
pNewShaderEffect->m_AabbMin.SetWZero();
|
|
pNewShaderEffect->m_AabbDelta.SetWZero();
|
|
pNewShaderEffect->m_scaleRange.SetWZero();
|
|
|
|
pNewShaderEffect->m_LodFadeInstRange = lodFadeInstRange;
|
|
|
|
pNewShaderEffect->m_orientToTerrain = orientToTerrain;
|
|
|
|
for(u32 i=0; i<CCustomShaderEffectGrassType::NUM_COL_VEH; i++)
|
|
{
|
|
pNewShaderEffect->m_bVehCollisionEnabled[i] = false;
|
|
}
|
|
|
|
//TODO - AJG-12.28.2012: Remove & Fixed in tools! (Might already be fixed in migration.)
|
|
if(!pEntity->GetLodData().IsTree())
|
|
{
|
|
//If we reach here, scan task will not be able to identify this entity as a tree! Thus, it will not be rendered with all
|
|
//other trees and will get SSA applied if SSA for cutouts is enabled. This is a temp hack to fix the issue.
|
|
#if !__GAMETOOL
|
|
//Let the user know this problem was found and fixed up.
|
|
//Note: This currently happens quite a bit in some scenes and currently there's nothing that can be done. (Waiting to see if migration fixed the issue.)
|
|
// So instead of asserting, I just output a warning.
|
|
// If this is still a problem post-migration, we'll need to find a real solution. (And may want to change this to an assert with the steps to fix)
|
|
renderWarningf( "WARNING! Found a grass entity that's not marked as a tree! This would likely cause it to draw as SSA if SSA is enabled, "
|
|
"or otherwise just not as part of the tree pass.\n\t\t\t\t Fixing up the entity and BaseModelInfo so this is properly identified as a tree.\n"
|
|
"\t\t\t\t Entity Name:\t%s", pEntity->GetModelName() ? pEntity->GetModelName() : "<NULL>");
|
|
#endif // !__GAMETOOL
|
|
//Set the entity flag properly and also fix the base model info which sets this flag so future instances of this type should not have the same problem.
|
|
pEntity->GetLodData().SetIsTree(true);
|
|
|
|
if(CBaseModelInfo *baseModelInfo = pEntity->GetBaseModelInfo())
|
|
baseModelInfo->SetIsTree(true);
|
|
}
|
|
|
|
return(pNewShaderEffect);
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
CCustomShaderEffectGrass::CCustomShaderEffectGrass() : CCustomShaderEffectBase(sizeof(*this), CSE_GRASS)
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
CCustomShaderEffectGrass::~CCustomShaderEffectGrass()
|
|
{
|
|
}
|
|
|
|
|
|
void CCustomShaderEffectGrass::AddToDrawList(u32 modelIndex, bool bExecute)
|
|
{
|
|
DLC(CCustomShaderEffectDC, (*this, modelIndex, bExecute, m_pType));
|
|
}
|
|
|
|
void CCustomShaderEffectGrass::AddToDrawListAfterDraw()
|
|
{
|
|
}
|
|
|
|
namespace CSEGrassStatic
|
|
{
|
|
DECLARE_MTR_THREAD grcRasterizerStateHandle sPrevRSBlock = grcStateBlock::RS_Invalid;
|
|
void CacheRSBlock()
|
|
{
|
|
Assert(sysThreadType::IsRenderThread());
|
|
Assertf(sPrevRSBlock == grcStateBlock::RS_Invalid, "WARNING! CSEGrassStatic::CacheRSBlock() is trying to push a state block before popping the previously pushed block.");
|
|
sPrevRSBlock = grcStateBlock::RS_Active;
|
|
}
|
|
|
|
void RestoreCachedRSBlock()
|
|
{
|
|
Assert(sysThreadType::IsRenderThread());
|
|
Assertf(sPrevRSBlock != grcStateBlock::RS_Invalid, "WARNING! CSEGrassStatic::RestoreCachedRSBlock() is trying to restore an invalid state block. Make sure a matching CacheRSBlock "
|
|
"was called 1st and that RestoreCachedRSBlock was not called multiple times in a row without a call to CacheRSBlock in between.");
|
|
grcStateBlock::SetRasterizerState(sPrevRSBlock);
|
|
sPrevRSBlock = grcStateBlock::RS_Invalid;
|
|
}
|
|
}
|
|
|
|
void CCustomShaderEffectGrass::AddBatchRenderStateToDrawList() const
|
|
{
|
|
//Setup tree render states
|
|
const bool isShadowDrawList = static_cast<CDrawListMgr *>(gDrawListMgr)->IsBuildingShadowDrawList();
|
|
|
|
if(isShadowDrawList)
|
|
{
|
|
DLC_Add(&CRenderPhaseCascadeShadowsInterface::SetRasterizerState, CSM_RS_TWO_SIDED);
|
|
}
|
|
else
|
|
{
|
|
DLC_Add(&CSEGrassStatic::CacheRSBlock);
|
|
DLC_Add(&CShaderLib::SetFacingBackwards, false);
|
|
DLC_Add(&CShaderLib::SetDisableFaceCulling);
|
|
}
|
|
}
|
|
|
|
void CCustomShaderEffectGrass::AddBatchRenderStateToDrawListAfterDraw() const
|
|
{
|
|
//Restore render states
|
|
const bool isShadowDrawList = static_cast<CDrawListMgr *>(gDrawListMgr)->IsBuildingShadowDrawList();
|
|
if(isShadowDrawList)
|
|
{
|
|
DLC_Add(&CRenderPhaseCascadeShadowsInterface::RestoreRasterizerState);
|
|
}
|
|
else
|
|
{
|
|
DLC_Add(&CSEGrassStatic::RestoreCachedRSBlock);
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
void CCustomShaderEffectGrass::Update(fwEntity* pEntity)
|
|
{
|
|
Assert(pEntity);
|
|
|
|
#if RSG_PC
|
|
// IB grass density settings tied to shader settings:
|
|
if(BANK_SWITCH( (!EBStatic::bPerfForceSkipInstance), true))
|
|
{
|
|
const u32 skipIdx = MIN(u32(CSettingsManager::GetInstance().GetSettings().m_graphics.m_ShaderQuality), (u32)CSettings::High);
|
|
const u32 skipMask[3] = {1, 3, 15}; // Low, Medium, High
|
|
EBStatic::sPerfSkipInstance = skipMask[skipIdx];
|
|
}
|
|
#endif //RSG_PC...
|
|
|
|
|
|
// enable players collision only if he is close enough to the tree:
|
|
// const Vec3V entityPos = pEntity->GetTransform().GetPosition();
|
|
const Vec3V playerPos = VECTOR3_TO_VEC3V(CGameWorld::FindLocalPlayerCoors());
|
|
|
|
//Compute Fade Ranges
|
|
if(pEntity && pEntity->GetType() == ENTITY_TYPE_GRASS_INSTANCE_LIST)
|
|
{
|
|
CGrassBatch *eb = static_cast<CGrassBatch *>(pEntity);
|
|
m_LodFadeInstRange = eb->GetInstanceList()->ComputeLodInstFadeRange(ScalarV(eb->GetDistanceToCamera()));
|
|
}
|
|
|
|
// player collision:
|
|
m_collPlayerScaleSqr = PLAYER_COLL_RADIUS0*PLAYER_COLL_RADIUS0;
|
|
|
|
CPed* pPlayerPed = CGameWorld::FindLocalPlayer();
|
|
if(pPlayerPed)
|
|
{
|
|
if(pPlayerPed->GetPedType() == PEDTYPE_ANIMAL)
|
|
{
|
|
static dev_float peyoteScale = 0.001f;
|
|
m_collPlayerScaleSqr = peyoteScale*peyoteScale;
|
|
}
|
|
}
|
|
|
|
|
|
if(m_pType->IsVehicleDeformable())
|
|
{
|
|
// find 4 nearest vehicles to camera:
|
|
|
|
bool bCameraVehicleFPV = false; // camera in First Person View in vehicle?
|
|
#if FPS_MODE_SUPPORTED
|
|
bCameraVehicleFPV = camInterface::GetCinematicDirector().IsRenderingAnyInVehicleFirstPersonCinematicCamera();
|
|
#endif
|
|
|
|
// enable players collision only if he is close enough to the tree:
|
|
const float maxVehCollisionDist = m_pType->GetMaxVehicleCollisionDist();
|
|
|
|
CVehicle* pVehicles[CCustomShaderEffectGrassType::NUM_COL_VEH] = {NULL, NULL, NULL, NULL };
|
|
float fVehicleDist[CCustomShaderEffectGrassType::NUM_COL_VEH] = {999999.0f, 999999.0f, 999999.0f, 999999.0f }; // vehicle dist sqr to camera
|
|
|
|
//Grab the spatial array.
|
|
const CSpatialArray& rSpatialArray = CVehicle::GetSpatialArray();
|
|
static const int sMaxResults = 20;
|
|
CSpatialArray::FindResult result[sMaxResults];
|
|
int iFound = rSpatialArray.FindInSphere(/*entityPos*/playerPos, maxVehCollisionDist, &result[0], sMaxResults);
|
|
|
|
int iEmptySlot = 0;
|
|
//Iterate over the results.
|
|
for(int iVeh = 0; iVeh < iFound; ++iVeh)
|
|
{
|
|
CVehicle* pVehicle = CVehicle::GetVehicleFromSpatialArrayNode(result[iVeh].m_Node);
|
|
const VehicleType vehType = pVehicle->GetVehicleType();
|
|
|
|
// disable vehicle collision for helis and planes:
|
|
pVehicle = ((vehType==VEHICLE_TYPE_HELI) || (vehType==VEHICLE_TYPE_PLANE) || (vehType==VEHICLE_TYPE_BLIMP))? NULL : pVehicle;
|
|
|
|
if(bCameraVehicleFPV)
|
|
{
|
|
// BS#2057861: FPV in vehicle - always enable grass collision
|
|
}
|
|
else
|
|
{
|
|
if(pVehicle && (pVehicle->IsUpsideDown() || pVehicle->IsOnItsSide()))
|
|
{
|
|
pVehicle = NULL; // no grass collision if vehicle is not firmly on the ground
|
|
}
|
|
|
|
// BS#2509157: check if lowrider hydraulics car is bouncing:
|
|
bool bIsCarHydraulicsBouncing = false;
|
|
if(pVehicle && pVehicle->InheritsFromAutomobile())
|
|
{
|
|
CAutomobile *pCar = (CAutomobile*)pVehicle;
|
|
if(pCar && (pVehicle->m_nVehicleFlags.bPlayerModifiedHydraulics || pCar->m_nAutomobileFlags.bHydraulicsBounceRaising || pCar->m_nAutomobileFlags.bHydraulicsBounceLanding || pCar->m_nAutomobileFlags.bHydraulicsJump))
|
|
{
|
|
bIsCarHydraulicsBouncing = true;
|
|
}
|
|
}
|
|
|
|
const u32 modelNameHash = pVehicle? pVehicle->GetBaseModelInfo()->GetModelNameHash() : 0;
|
|
|
|
// BS#4036767 - Deluxo - Changing from driving to flying/floating affects grass collision
|
|
bool bIsHooveringDeluxo = false;
|
|
if(pVehicle && modelNameHash==MID_DELUXO)
|
|
{
|
|
bIsHooveringDeluxo = pVehicle->HoveringCloseToGround();
|
|
}
|
|
|
|
if(bIsCarHydraulicsBouncing)
|
|
{
|
|
// do nothing - vehicle is bouncing via hydraulics
|
|
}
|
|
else if(pVehicle && modelNameHash==MID_BLAZER5)
|
|
{
|
|
// do nothing - special case for blazer5
|
|
}
|
|
else if(bIsHooveringDeluxo)
|
|
{
|
|
// do nothing - deluxo is hoovering close to the ground
|
|
}
|
|
else if(pVehicle && (pVehicle->GetNumContactWheels() < pVehicle->GetNumWheels()))
|
|
{
|
|
pVehicle = NULL; // no grass collision if vehicle is not firmly on the ground
|
|
}
|
|
|
|
// B*2491123: disable collision for attached vehicles:
|
|
if(pVehicle && pVehicle->GetIsAttached())
|
|
{
|
|
CPhysical* pAttachParent = (CPhysical*)pVehicle->GetAttachParent();
|
|
if(pAttachParent)
|
|
{
|
|
pVehicle = NULL; // no grass collision for attached vehicles
|
|
}
|
|
}
|
|
}
|
|
|
|
if(pVehicle)
|
|
{ // [HACK GTAV] BS#1105797: disable grass collision for dump:
|
|
// [HACK GTAV] BS#1945307: disable grass collision for monster;
|
|
// [HACK GTAV] BS#1998362: disable grass collision for trailers;
|
|
const u32 uModelNameHash = pVehicle->GetBaseModelInfo()->GetModelNameHash();
|
|
pVehicle = (uModelNameHash==MID_DUMP)? NULL : pVehicle;
|
|
pVehicle = (uModelNameHash==MID_MONSTER)? NULL : pVehicle;
|
|
pVehicle = (uModelNameHash==MID_TRAILERS)? NULL : pVehicle;
|
|
pVehicle = (uModelNameHash==MID_TRAILERS2)? NULL : pVehicle;
|
|
pVehicle = (uModelNameHash==MID_TRAILERS3)? NULL : pVehicle;
|
|
pVehicle = (uModelNameHash==MID_TRAILERLOGS)? NULL : pVehicle;
|
|
}
|
|
|
|
if(pVehicle)
|
|
{
|
|
const float distSqr = result[iVeh].m_DistanceSq;
|
|
|
|
if(iEmptySlot < CCustomShaderEffectGrassType::NUM_COL_VEH)
|
|
{
|
|
fVehicleDist[iEmptySlot] = distSqr;
|
|
pVehicles[iEmptySlot] = pVehicle;
|
|
iEmptySlot++;
|
|
continue;
|
|
}
|
|
|
|
// find vehicle's index which is most far away from the camera:
|
|
u32 fari = 0;
|
|
float farDist = fVehicleDist[0];
|
|
for(u32 i=1; i<CCustomShaderEffectGrassType::NUM_COL_VEH; i++)
|
|
{
|
|
if( fVehicleDist[i] > farDist )
|
|
{
|
|
farDist = fVehicleDist[i];
|
|
fari = i;
|
|
}
|
|
}
|
|
Assert(fari < CCustomShaderEffectGrassType::NUM_COL_VEH);
|
|
|
|
// dist2 smaller than furthest found?
|
|
if( distSqr < farDist )
|
|
{
|
|
fVehicleDist[fari] = distSqr;
|
|
pVehicles[fari] = pVehicle;
|
|
}
|
|
}// if(pVehicle)...
|
|
}
|
|
|
|
spdAABB batchAABB;
|
|
pEntity->GetAABB(batchAABB);
|
|
const bool hasScriptVehicle = CSEGrassStatic::sm_ScrVehEnabled && (batchAABB.IntersectsAABB(CSEGrassStatic::sm_ScrVehAABB) || batchAABB.IntersectsSphere(spdSphere(Vec4V(CSEGrassStatic::sm_ScrVehAABB.GetCenter(), ScalarV(CSEGrassStatic::sm_ScrVehRadius)))));
|
|
const u32 maxShaderVehicles = hasScriptVehicle ? CCustomShaderEffectGrassType::NUM_COL_VEH - 1 : CCustomShaderEffectGrassType::NUM_COL_VEH;
|
|
for(u32 v=0; v<maxShaderVehicles; v++)
|
|
{
|
|
CVehicle *pVehicle = pVehicles[v];
|
|
if( pVehicle )
|
|
{
|
|
// grab unmodified (e.g. by opened cardoors, etc.) vehicle's bbox:
|
|
const Vector3 bboxmin = pVehicle->GetBaseModelInfo()->GetBoundingBoxMin(); //pVehicle->GetBoundingBoxMin();
|
|
const Vector3 bboxmax = pVehicle->GetBaseModelInfo()->GetBoundingBoxMax(); //pVehicle->GetBoundingBoxMax();
|
|
|
|
// two points: on the front and back of the car:
|
|
float middleX = bboxmin.x + (bboxmax.x - bboxmin.x)*0.5f;
|
|
float middleZ = bboxmin.z + (bboxmax.z - bboxmin.z)*0.5f;
|
|
|
|
static dev_float radiusPerc = 1.05f; // how much make bounding shape "shorter" to fit better around vehicle
|
|
|
|
const u32 vehNameHash = pVehicle->GetBaseModelInfo()->GetModelNameHash();
|
|
|
|
// front/rear Y shift overrides:
|
|
float frontShiftY = 0.0f;
|
|
float rearShiftY = 0.0f;
|
|
float sideShift = 0.0f;
|
|
|
|
// BS#1777745: bodhi2: magic shift grass collision is not producing "halo" at the rear of vehicle:
|
|
if(vehNameHash == MID_BODHI2)
|
|
{
|
|
rearShiftY = -0.7f;
|
|
}
|
|
|
|
// BS#1918403: Bulldozer flattens grass without being touched when bucket is up;
|
|
if(vehNameHash == MID_BULLDOZER)
|
|
{
|
|
rearShiftY = -0.8f;
|
|
|
|
// loop through gadgets until we found the digger arm
|
|
for(int i = 0; i < pVehicle->GetNumberOfVehicleGadgets(); i++)
|
|
{
|
|
CVehicleGadget *pVehicleGadget = pVehicle->GetVehicleGadget(i);
|
|
if(pVehicleGadget->GetType() == VGT_DIGGER_ARM)
|
|
{
|
|
CVehicleGadgetDiggerArm *pDiggerArm = static_cast<CVehicleGadgetDiggerArm*>(pVehicleGadget);
|
|
Assert(pDiggerArm);
|
|
|
|
if(pDiggerArm)
|
|
{
|
|
const float fArmPosRatio = pDiggerArm->GetJointPositionRatio();
|
|
|
|
static dev_float minPosRatio = 0.00f;
|
|
static dev_float maxPosRatio = 0.36f;
|
|
float fArmLerpRatio = Clamp((fArmPosRatio-minPosRatio)/(maxPosRatio-minPosRatio), 0.0f, 1.0f);
|
|
frontShiftY = Lerp(fArmLerpRatio, -0.25f, 1.9f);
|
|
}
|
|
}
|
|
}
|
|
}// if(vehNameHash == MID_BULLDOZER)...
|
|
|
|
|
|
// BS#1992186: granger side adjustments;
|
|
if(vehNameHash == MID_GRANGER)
|
|
{
|
|
sideShift = 0.42f;
|
|
}
|
|
else if(vehNameHash == MID_GRANGER2)
|
|
{
|
|
sideShift = 0.50f;
|
|
}
|
|
// BS#1992186: riot side adjustments;
|
|
else if(vehNameHash == MID_RIOT)
|
|
{
|
|
sideShift = 0.40f;
|
|
}
|
|
// BS#1925880: zentorno side adjustments;
|
|
else if(vehNameHash == MID_ZENTORNO)
|
|
{
|
|
sideShift = 0.40f;
|
|
}
|
|
// BS#2278312: rhino front/rear adjustments:
|
|
else if(vehNameHash == MID_RHINO)
|
|
{
|
|
frontShiftY = 2.6f;
|
|
rearShiftY = -0.3f;
|
|
}
|
|
// BS#2333618: T20 side adjustments:
|
|
else if(vehNameHash == MID_T20)
|
|
{
|
|
sideShift = 0.45f;
|
|
}
|
|
// BS#3120202: Large Area around Phantom2 is cleared when driving off-road:
|
|
else if(vehNameHash == MID_PHANTOM2)
|
|
{
|
|
frontShiftY = 3.0f;
|
|
sideShift = 0.75f;
|
|
}
|
|
// BS#3334666 - GP1 - Large area cleared around vehicle
|
|
else if(vehNameHash == MID_INFERNUS2)
|
|
{
|
|
sideShift = 0.40f;
|
|
}
|
|
// BS#3334666 - GP1 - Large area cleared around vehicle
|
|
else if(vehNameHash == MID_GP1)
|
|
{
|
|
sideShift = 0.80f;
|
|
}
|
|
// BS#3477152 - XA-21 - Large area cleared around the vehicle
|
|
else if(vehNameHash == MID_XA21)
|
|
{
|
|
sideShift = 0.70f;
|
|
}
|
|
// BS#3888877 - Visione - Excessive collision of vegetation
|
|
else if(vehNameHash == MID_VISIONE)
|
|
{
|
|
sideShift = 0.50f;
|
|
}
|
|
// BS#4028275 - Riot2 - Excess grass & vegeatation clearance
|
|
else if(vehNameHash == MID_RIOT2)
|
|
{
|
|
sideShift = 0.6f;
|
|
rearShiftY = -0.4f;
|
|
}
|
|
// BS#4068209 - Barrage - Too much foliage cleared behind the vehicle
|
|
else if(vehNameHash == MID_BARRAGE)
|
|
{
|
|
frontShiftY = 0.4f;
|
|
rearShiftY = -1.0f;
|
|
sideShift = 0.3f;
|
|
}
|
|
// BS#4176577 - Chernobog - Area for flattening grass is too big
|
|
else if(vehNameHash == MID_CHERNOBOG)
|
|
{
|
|
frontShiftY = 1.0f;
|
|
rearShiftY = -0.5f;
|
|
sideShift = 0.6f;
|
|
}
|
|
// BS#4194918 - Khanjali - Grass flattening area is larger than vehicle
|
|
else if(vehNameHash == MID_KHANJALI)
|
|
{
|
|
frontShiftY = 1.0f;
|
|
rearShiftY = -0.4f;
|
|
sideShift = 0.3f;
|
|
}
|
|
// BS#198885 - Autarch - Grass collision bounds:
|
|
else if(vehNameHash == MID_AUTARCH)
|
|
{
|
|
sideShift = 0.5f;
|
|
rearShiftY = -0.2f;
|
|
}
|
|
// BS#4623613 - Excessive clearing of foliage around Mule4:
|
|
else if(vehNameHash == MID_MULE4)
|
|
{
|
|
frontShiftY = 0.5f;
|
|
rearShiftY = -0.4f;
|
|
sideShift = 0.85f;
|
|
}
|
|
// BS#4623697 - Pounder2 - Excessive clearing of foliage;
|
|
else if(vehNameHash == MID_POUNDER2)
|
|
{
|
|
frontShiftY = 0.5f;
|
|
sideShift = 0.8f;
|
|
}
|
|
// BS#4702207 - pbus2 has too large area that flattens grass
|
|
else if(vehNameHash == MID_PBUS2)
|
|
{
|
|
frontShiftY = 1.0f;
|
|
rearShiftY = -3.1f;
|
|
sideShift = 1.3f;
|
|
}
|
|
// BS#5459805 - Monster3 - Foliage grass flatten area is very large on this vehicle.
|
|
else if(vehNameHash == MID_MONSTER3 || vehNameHash == MID_MONSTER4 || vehNameHash == MID_MONSTER5)
|
|
{
|
|
frontShiftY = 3.2f;
|
|
rearShiftY = -0.5f;
|
|
sideShift = 0.5f;
|
|
}
|
|
// BS#5388815 - Bruiser - Vehicle has a large foliage flatten area
|
|
else if(vehNameHash == MID_BRUISER || vehNameHash == MID_BRUISER2 || vehNameHash == MID_BRUISER3)
|
|
{
|
|
frontShiftY = 1.2f;
|
|
rearShiftY = -1.0f;
|
|
sideShift = 0.7f;
|
|
}
|
|
// BS#5354204 - Scarab - Excessive foliage suppression
|
|
else if(vehNameHash == MID_SCARAB || vehNameHash == MID_SCARAB2 || vehNameHash == MID_SCARAB3)
|
|
{
|
|
frontShiftY = 1.4f;
|
|
rearShiftY = -0.3f;
|
|
sideShift = 0.4f;
|
|
}
|
|
// BS#5350080 - Deveste - Vegetation cleared quite far
|
|
else if(vehNameHash == MID_DEVESTE)
|
|
{
|
|
frontShiftY = -0.05f;
|
|
rearShiftY = 0.0f;
|
|
sideShift = 0.4f;
|
|
}
|
|
// BS#5415156 - ZR380 - Area that flattens grass is too big
|
|
else if(vehNameHash == MID_ZR380 || vehNameHash == MID_ZR3802 || vehNameHash == MID_ZR3803)
|
|
{
|
|
frontShiftY = 0.6f;
|
|
rearShiftY = -0.2f;
|
|
sideShift = 0.35f;
|
|
}
|
|
// BS#5423756 - Cerberus - Vehicle has a large foliage flatten area
|
|
else if (vehNameHash == MID_CERBERUS || vehNameHash == MID_CERBERUS2 || vehNameHash == MID_CERBERUS3)
|
|
{
|
|
frontShiftY = 1.6f;
|
|
rearShiftY = -1.0f;
|
|
sideShift = 0.6f;
|
|
}
|
|
// BS#5459616 - Slamvan4 - Foliage suppression too large
|
|
else if(vehNameHash == MID_SLAMVAN4 || vehNameHash == MID_SLAMVAN5 || vehNameHash == MID_SLAMVAN6)
|
|
{
|
|
frontShiftY = 0.35f;
|
|
rearShiftY = -0.75f;
|
|
sideShift = 0.1f;
|
|
}
|
|
// BS#5476478 - Dominator5 - excess foliage collision
|
|
else if(vehNameHash == MID_DOMINATOR3)
|
|
{
|
|
rearShiftY = -0.2f;
|
|
sideShift = 0.2f;
|
|
}
|
|
else if(vehNameHash == MID_DOMINATOR4 || vehNameHash == MID_DOMINATOR5 || vehNameHash == MID_DOMINATOR6)
|
|
{
|
|
frontShiftY = 0.85f;
|
|
rearShiftY = 0.1f;
|
|
sideShift = 0.25f;
|
|
}
|
|
// BS#5457801 - Vehicles with Scoop Mods have large foliage flatten around it
|
|
else if(vehNameHash == MID_BRUTUS || vehNameHash == MID_BRUTUS2 || vehNameHash == MID_BRUTUS3)
|
|
{
|
|
frontShiftY = 1.3f;
|
|
rearShiftY = -0.5f;
|
|
sideShift = 0.3f;
|
|
}
|
|
else if(vehNameHash == MID_IMPALER2 || vehNameHash == MID_IMPALER3 || vehNameHash == MID_IMPALER4)
|
|
{
|
|
frontShiftY = 0.7f;
|
|
rearShiftY = -0.1f;
|
|
sideShift = 0.2f;
|
|
}
|
|
else if(vehNameHash == MID_IMPERATOR || vehNameHash == MID_IMPERATOR3)
|
|
{
|
|
frontShiftY = 0.7f;
|
|
rearShiftY = -0.35f;
|
|
sideShift = 0.3f;
|
|
}
|
|
else if(vehNameHash == MID_IMPERATOR2)
|
|
{
|
|
frontShiftY = 0.4f;
|
|
rearShiftY = -0.35f;
|
|
sideShift = 0.3f;
|
|
}
|
|
else if(vehNameHash == MID_ISSI4 || vehNameHash == MID_ISSI5 || vehNameHash == MID_ISSI6)
|
|
{
|
|
frontShiftY = 0.8f;
|
|
rearShiftY = -0.1f;
|
|
sideShift = 0.3f;
|
|
}
|
|
else if(vehNameHash == MID_DEATHBIKE || vehNameHash == MID_DEATHBIKE2 || vehNameHash == MID_DEATHBIKE3)
|
|
{
|
|
sideShift = 0.4f;
|
|
}
|
|
else if(vehNameHash == MID_EMERUS)
|
|
{
|
|
rearShiftY = -0.3f;
|
|
sideShift = 0.15f;
|
|
}
|
|
else if(vehNameHash == MID_NEO)
|
|
{
|
|
sideShift = 0.3f;
|
|
}
|
|
else if(vehNameHash == MID_KRIEGER)
|
|
{
|
|
rearShiftY = -0.2f;
|
|
sideShift = 0.1f;
|
|
}
|
|
else if(vehNameHash == MID_S80)
|
|
{
|
|
frontShiftY = -0.1f;
|
|
rearShiftY = -0.2f;
|
|
}
|
|
else if(vehNameHash == MID_IMORGON)
|
|
{
|
|
frontShiftY = -0.05f;
|
|
rearShiftY = -0.15f;
|
|
sideShift = 0.1f;
|
|
}
|
|
else if(vehNameHash == MID_FORMULA)
|
|
{
|
|
frontShiftY = -0.3f;
|
|
sideShift = 0.2f;
|
|
}
|
|
else if(vehNameHash == MID_REBLA)
|
|
{
|
|
sideShift = 0.1f;
|
|
}
|
|
else if(vehNameHash == MID_POLBUFFALO)
|
|
{
|
|
frontShiftY = -0.08f;
|
|
rearShiftY = 0.05f;
|
|
sideShift = 0.05f;
|
|
}
|
|
else if(vehNameHash == MID_YOUGA3)
|
|
{
|
|
frontShiftY = 0.3f;
|
|
rearShiftY = 0.1f;
|
|
sideShift = 0.1f;
|
|
}
|
|
else if(vehNameHash == MID_YOUGA4)
|
|
{
|
|
frontShiftY = 0.3f;
|
|
rearShiftY = -0.2f;
|
|
sideShift = 0.4f;
|
|
}
|
|
else if(vehNameHash == MID_OPENWHEEL1)
|
|
{
|
|
frontShiftY = -0.05f;
|
|
rearShiftY = -0.2f;
|
|
sideShift = 0.2f;
|
|
}
|
|
else if(vehNameHash == MID_VERUS)
|
|
{
|
|
frontShiftY = 0.15f;
|
|
rearShiftY = -0.3f;
|
|
sideShift = 0.1f;
|
|
}
|
|
else if(vehNameHash == MID_IGNUS)
|
|
{
|
|
rearShiftY = -0.2f;
|
|
sideShift = 0.2f;
|
|
}
|
|
else if(vehNameHash == MID_DEITY)
|
|
{
|
|
sideShift = 0.15f;
|
|
}
|
|
else if(vehNameHash == MID_ZENO)
|
|
{
|
|
sideShift = 0.75f;
|
|
}
|
|
else if(vehNameHash == MID_COMET7)
|
|
{
|
|
sideShift = 0.15f;
|
|
}
|
|
else if(vehNameHash == MID_BALLER7)
|
|
{
|
|
sideShift = 0.15f;
|
|
}
|
|
else if(vehNameHash == MID_PATRIOT3)
|
|
{
|
|
sideShift = 0.3f;
|
|
}
|
|
else if(vehNameHash == MID_TORERO2)
|
|
{
|
|
rearShiftY = -0.1f;
|
|
sideShift = 0.4f;
|
|
}
|
|
else if(vehNameHash == MID_CORSITA)
|
|
{
|
|
frontShiftY = 0.1f;
|
|
rearShiftY = -0.2f;
|
|
sideShift = 1.05f;
|
|
}
|
|
else if(vehNameHash == MID_KANJOSJ)
|
|
{
|
|
frontShiftY = 0.2f;
|
|
sideShift = 0.2f;
|
|
}
|
|
else if(vehNameHash == MID_WEEVIL2)
|
|
{
|
|
frontShiftY = 0.3f;
|
|
rearShiftY = -0.5f;
|
|
sideShift = 0.4f;
|
|
}
|
|
|
|
static dev_bool bOverrideFrontShiftY=false;
|
|
if(bOverrideFrontShiftY)
|
|
{
|
|
static dev_float frontShiftYOverride = 1.9f;
|
|
frontShiftY = frontShiftYOverride;
|
|
}
|
|
|
|
static dev_bool bOverrideRearShiftY=false;
|
|
if(bOverrideRearShiftY)
|
|
{
|
|
static dev_float rearShiftYOverride = -0.7f;
|
|
rearShiftY = rearShiftYOverride;
|
|
}
|
|
|
|
static dev_bool bOverrideSideShift=false;
|
|
if(bOverrideSideShift)
|
|
{
|
|
static dev_float sideShiftOverride = 0.2f;
|
|
sideShift = sideShiftOverride;
|
|
}
|
|
|
|
float Radius = (bboxmax.x - bboxmin.x)*0.5f - sideShift; // radius
|
|
Vector3 ptb(middleX, bboxmax.y - Radius*radiusPerc - frontShiftY, middleZ);
|
|
Vector3 pta(middleX, bboxmin.y + Radius*radiusPerc - rearShiftY, middleZ);
|
|
|
|
|
|
// first point on segment:
|
|
Vector3 ptB = pVehicle->TransformIntoWorldSpace(ptb);
|
|
// last point on segment:
|
|
Vector3 ptA = pVehicle->TransformIntoWorldSpace(pta);
|
|
// segment vector:
|
|
Vector3 vecM = ptA - ptB;
|
|
|
|
// detect groundZ pos (from wheel hit pos):
|
|
Vector3 wheelHitPos(0,0,100000);
|
|
const s32 numWheels = pVehicle->GetNumWheels();
|
|
for(s32 i=0; i<numWheels; i++)
|
|
{
|
|
if(pVehicle->GetWheel(i))
|
|
{
|
|
// select wheelHitPos with lowest Z (to allow for steep slopes - see BS#978552, BS#1725071):
|
|
Vector3 wheelPos = pVehicle->GetWheel(i)->GetHitPos();
|
|
if(wheelPos.z < wheelHitPos.z)
|
|
{
|
|
wheelHitPos = wheelPos;
|
|
}
|
|
}
|
|
}
|
|
|
|
static dev_bool bOverrideZ = FALSE;
|
|
static float overrideZ = 398.44f; // test for testbed
|
|
float groundZ = bOverrideZ? overrideZ : wheelHitPos.z;
|
|
|
|
static dev_float tweakRadiusScale = 1.0f; // v1 collision
|
|
SetGlobalVehCollisionParams(v, TRUE, ptB, vecM, Radius*tweakRadiusScale, groundZ, VEHCOL_DIST_LIMIT);
|
|
}
|
|
else
|
|
{
|
|
SetGlobalVehCollisionParams(v, FALSE, Vector3(0,0,0), Vector3(0,0,0), 0, 0, 0);
|
|
}
|
|
}// for(u32 v=0; v<CCustomShaderEffectGrassType::NUM_COL_VEH; v++)...
|
|
|
|
if(hasScriptVehicle)
|
|
{
|
|
static dev_float scrVehColDistLimit = 25.0f; // set limit to 25m for script controlled collision
|
|
SetGlobalVehCollisionParams(CCustomShaderEffectGrassType::NUM_COL_VEH - 1, true, VEC3V_TO_VECTOR3(CSEGrassStatic::sm_ScrVehB), VEC3V_TO_VECTOR3(CSEGrassStatic::sm_ScrVehM), CSEGrassStatic::sm_ScrVehRadius, CSEGrassStatic::sm_ScrVehGroundZ, scrVehColDistLimit);
|
|
}
|
|
}//m_pType->IsVehicleDeformable()...
|
|
|
|
}// end of Update()...
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
void CCustomShaderEffectGrass::SetGlobalVehCollisionParams(u32 n, bool bEnable, const Vector3& vecB, const Vector3& vecM, float radius, float groundZ, float vehColDistLimit)
|
|
{
|
|
Assert(CSystem::IsThisThreadId(SYS_THREAD_UPDATE));
|
|
Assert(n<CCustomShaderEffectGrassType::NUM_COL_VEH);
|
|
|
|
m_bVehCollisionEnabled[n] = bEnable;
|
|
|
|
Vector4 &vehCollisionB = m_vecVehCollisionB[n];
|
|
vehCollisionB.x = vecB.x;
|
|
vehCollisionB.y = vecB.y;
|
|
vehCollisionB.z = vecB.z;
|
|
vehCollisionB.w = vehColDistLimit;
|
|
|
|
Vector2 vecM2;
|
|
vecM2.x = vecM.x;
|
|
vecM2.y = vecM.y;
|
|
float dotMM = vecM2.Dot(vecM2);
|
|
|
|
Vector4 &vehCollisionM = m_vecVehCollisionM[n];
|
|
vehCollisionM.x = vecM.x;
|
|
vehCollisionM.y = vecM.y;
|
|
vehCollisionM.z = vecM.z;
|
|
vehCollisionM.w = (dotMM>0.0f)? (1.0f/dotMM) : (0.0f);
|
|
|
|
Vector4 &vehCollisionR = m_vecVehCollisionR[n];
|
|
vehCollisionR.x = radius;
|
|
vehCollisionR.y = radius * radius;
|
|
vehCollisionR.z = (radius>0.0f)? (1.0f/(radius * radius)) : (0.0f);
|
|
vehCollisionR.w = groundZ;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
void CCustomShaderEffectGrass::SetShaderVariables(rmcDrawable* pDrawable)
|
|
{
|
|
if(!pDrawable)
|
|
return;
|
|
|
|
if(grmModel::GetForceShader())
|
|
return;
|
|
|
|
grmShaderGroup *shaderGroup = &pDrawable->GetShaderGroup();
|
|
|
|
if(m_pType->m_CSVars.m_idAabbMin)
|
|
{
|
|
shaderGroup->SetVar(static_cast<grmShaderGroupVar>(m_pType->m_CSVars.m_idAabbMin), m_AabbMin);
|
|
}
|
|
|
|
if(m_pType->m_CSVars.m_idAabbDelta)
|
|
{
|
|
shaderGroup->SetVar(static_cast<grmShaderGroupVar>(m_pType->m_CSVars.m_idAabbDelta), m_AabbDelta);
|
|
}
|
|
|
|
if(m_pType->m_idOrientToTerrain)
|
|
{
|
|
shaderGroup->SetVar(static_cast<grmShaderGroupVar>(m_pType->m_idOrientToTerrain), m_orientToTerrain);
|
|
}
|
|
|
|
if(m_pType->m_idPlayerPos)
|
|
{
|
|
Vec4V playerPos(VECTOR3_TO_VEC3V(CGrassRenderer::GetGlobalPlayerPos()), LoadScalar32IntoScalarV(m_orientToTerrain));
|
|
shaderGroup->SetVar(static_cast<grmShaderGroupVar>(m_pType->m_idPlayerPos), playerPos);
|
|
}
|
|
|
|
if(m_pType->m_CSVars.m_idScaleRange)
|
|
{
|
|
shaderGroup->SetVar(static_cast<grmShaderGroupVar>(m_pType->m_CSVars.m_idScaleRange), m_scaleRange);
|
|
}
|
|
|
|
if(m_pType->m_idWindBending)
|
|
{
|
|
Vector2 globalWindBending;
|
|
CGrassRenderer::GetGlobalWindBending(globalWindBending);
|
|
Vec4V windBending((CSEGrassBankStatic::sm_bEnableWinBending ? globalWindBending.x : 0.0f), (CSEGrassBankStatic::sm_bEnableWinBending ? globalWindBending.y : 0.0f), 0.0f, 0.0f);
|
|
shaderGroup->SetVar(static_cast<grmShaderGroupVar>(m_pType->m_idWindBending), windBending);
|
|
}
|
|
|
|
if(m_pType->m_idLodFadeInstRange)
|
|
{
|
|
Vec2V range = m_LodFadeInstRange.GetXY();
|
|
//NOTE: NG fades from the back rather than the front... so need to compute the scale differently...
|
|
#if __D3D11 || RSG_ORBIS
|
|
ScalarV numInst = m_LodFadeInstRange.GetZ();
|
|
range = Vec2V(numInst) - range;
|
|
Vec3V shaderFadeInstRange(range, SelectFT(IsGreaterThan(range.GetX(), range.GetY()), ScalarV(V_NEGONE), ScalarV(V_ONE) / (range.GetY() - range.GetX())));
|
|
#else
|
|
Vec3V shaderFadeInstRange(range, SelectFT(IsLessThan(range.GetX(), range.GetY()), ScalarV(V_ONE), ScalarV(V_ONE) / (range.GetY() - range.GetX())));
|
|
#endif
|
|
shaderGroup->SetVar(static_cast<grmShaderGroupVar>(m_pType->m_idLodFadeInstRange), shaderFadeInstRange);
|
|
}
|
|
|
|
#if ENABLE_TRAIL_MAP
|
|
if(m_pType->m_idTrailMapTexture)
|
|
{
|
|
shaderGroup->SetVar(static_cast<grmShaderGroupVar>(m_pType->m_idTrailMapTexture), g_TrailMapRenderer.GetTrailMap()); // The map
|
|
}
|
|
|
|
if(m_pType->m_idMapSizeWorldSpace)
|
|
{
|
|
Vec4V mapSizeWorldSpace(g_TrailMapRenderer.GetTrailMapWorldSpaceWidth(), g_TrailMapRenderer.GetTrailMapWorldSpaceWidth(), 0.0f, 0.0f);
|
|
shaderGroup->SetVar(static_cast<grmShaderGroupVar>(m_pType->m_idMapSizeWorldSpace), mapSizeWorldSpace);
|
|
}
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Micromovement Params
|
|
|
|
if(m_pType->m_idFadeAlphaDistUmTimer)
|
|
{
|
|
//Don't care much about lod alpha fade at the moment, so turn it off.
|
|
float alphaFadeLODDist0 = 0.0f; //In grass code, was: (f) / (f - c)
|
|
float alphaFadeLODDist1 = 1.0f; //In grass code, was: (-1.0) / (f - c)
|
|
float umTimer = CSEGrassBankStatic::sm_bEnableMicroMovements ? static_cast<float>(2.0 * PI * (static_cast<double>(fwTimer::GetTimeInMilliseconds()) / 1000.0)) : 0.0f;
|
|
shaderGroup->SetVar(static_cast<grmShaderGroupVar>(m_pType->m_idFadeAlphaDistUmTimer), Vec4V(alphaFadeLODDist0, alphaFadeLODDist1, umTimer, 0.0f));
|
|
}
|
|
|
|
#if DEVICE_MSAA
|
|
if (m_pType->m_idAlphaToCoverageScale && !GRCDEVICE.GetMSAA())
|
|
{
|
|
shaderGroup->SetVar( static_cast<grmShaderGroupVar>(m_pType->m_idAlphaToCoverageScale), 1.0f );
|
|
}
|
|
//else: leave artist-tuned value
|
|
#endif
|
|
|
|
// player collision:
|
|
if(m_pType->m_idCollParams)
|
|
{
|
|
const Vector2 vecPlayerColl(m_collPlayerScaleSqr, 1.0f/m_collPlayerScaleSqr);
|
|
shaderGroup->SetVar((grmShaderGroupVar)(m_pType->m_idCollParams), vecPlayerColl);
|
|
}
|
|
|
|
// vehicle collision:
|
|
if(m_pType->IsVehicleDeformable())
|
|
{
|
|
for(u32 i=0; i<CCustomShaderEffectGrassType::NUM_COL_VEH; i++)
|
|
{
|
|
if(m_pType->m_idVarVehCollEnabled[i])
|
|
{
|
|
grcEffect::SetGlobalVar((grcEffectGlobalVar)m_pType->m_idVarVehCollEnabled[i], m_bVehCollisionEnabled[i]);
|
|
}
|
|
|
|
if(m_bVehCollisionEnabled[i])
|
|
{
|
|
if(m_pType->m_idVarVehCollB0[i])
|
|
{
|
|
shaderGroup->SetVar((grmShaderGroupVar)m_pType->m_idVarVehCollB0[i], m_vecVehCollisionB[i]);
|
|
}
|
|
|
|
if(m_pType->m_idVarVehCollM0[i])
|
|
{
|
|
shaderGroup->SetVar((grmShaderGroupVar)m_pType->m_idVarVehCollM0[i], m_vecVehCollisionM[i]);
|
|
}
|
|
|
|
if(m_pType->m_idVarVehCollR0[i])
|
|
{
|
|
shaderGroup->SetVar((grmShaderGroupVar)m_pType->m_idVarVehCollR0[i], m_vecVehCollisionR[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(u32 i=0; i<CCustomShaderEffectGrassType::NUM_COL_VEH; i++)
|
|
{
|
|
if(m_pType->m_idVarVehCollEnabled[i])
|
|
{
|
|
grcEffect::SetGlobalVar((grcEffectGlobalVar)m_pType->m_idVarVehCollEnabled[i], false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#if __BANK
|
|
if(CSEGrassBankStatic::sm_bOverrideAO)
|
|
{
|
|
if(m_pType->m_idFakedGrassNormal)
|
|
{
|
|
Vec4V fakedNormal(0.0f, 0.0f, 0.0f, CSEGrassBankStatic::sm_fGlobalA0);
|
|
shaderGroup->SetVar(static_cast<grmShaderGroupVar>(m_pType->m_idFakedGrassNormal), fakedNormal);
|
|
}
|
|
}
|
|
|
|
if(m_pType->m_idDebugSwitches)
|
|
{
|
|
Vec4V debugSwitches(V_ZERO);
|
|
debugSwitches.SetX(CSEGrassBankStatic::sm_bAlphaOverdraw? 1.0f : 0.0f);
|
|
shaderGroup->SetVar((grmShaderGroupVar)m_pType->m_idDebugSwitches, debugSwitches);
|
|
}
|
|
#endif //__BANK...
|
|
}// end of SetShaderVariables()...
|
|
|
|
void CCustomShaderEffectGrass::ClearScriptVehicleFlatten()
|
|
{
|
|
CSEGrassStatic::ClearScriptVehicle();
|
|
}
|
|
|
|
void CCustomShaderEffectGrass::SetScriptVehicleFlatten(const spdAABB &aabb, Vec3V_In look, ScalarV_In groundZ)
|
|
{
|
|
CSEGrassStatic::SetScriptVehicle(aabb, look, groundZ);
|
|
}
|
|
|
|
void CCustomShaderEffectGrass::SetScriptVehicleFlatten(const spdSphere &sphere, Vec3V_In look, ScalarV_In groundZ)
|
|
{
|
|
CSEGrassStatic::SetScriptVehicle(sphere, look, groundZ);
|
|
}
|
|
|
|
bool CCustomShaderEffectGrass::IntersectsScriptFlattenAABB(fwEntity *pEntity)
|
|
{
|
|
return CSEGrassStatic::IntersectsScriptVehicleAABB(pEntity);
|
|
}
|
|
|
|
#if __BANK
|
|
void CCustomShaderEffectGrass::SetDbgAlphaOverdraw(bool enable)
|
|
{
|
|
CSEGrassBankStatic::sm_bAlphaOverdraw = enable;
|
|
}
|
|
|
|
void CCustomShaderEffectGrass::RenderDebug()
|
|
{
|
|
CSEGrassBankStatic::RenderDebug();
|
|
}
|
|
|
|
void CCustomShaderEffectGrass::AddWidgets(bkBank &bank)
|
|
{
|
|
CSEGrassBankStatic::AddWidgets(bank);
|
|
}
|
|
#endif //__BANK
|