Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Client/core/Graphics/CRenderItemManager.TextureReplace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void CRenderItemManager::RemoveClientEntityRefs(CClientEntityBase* pClientEntity
SShaderItemLayers* CRenderItemManager::GetAppliedShaderForD3DData(CD3DDUMMY* pD3DData)
{
// Save texture usage for later
MapInsert(m_FrameTextureUsage, pD3DData);
MapInsert(m_FrameTextureUsage, m_pRenderWare->ResolveD3DData(pD3DData));

return m_pRenderWare->GetAppliedShaderForD3DData(pD3DData);
}
Expand Down
9 changes: 9 additions & 0 deletions Client/game_sa/CPointLightsSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
#include "StdInc.h"
#include "CPointLightsSA.h"
#include "CEntitySA.h"
#include "CRenderWareSA.h"
#include "CGameSA.h"

extern CGameSA* pGame;

using CHeli_SearchLightCone_t = void(__cdecl*)(int handleId, CVector startPos, CVector endPos, float radius1, float unknownConstant, int unkown1,
bool renderSpot, CVector* unkown3, CVector* unkown4, CVector* unknown5, int unknown6, float radius2);
Expand Down Expand Up @@ -119,6 +123,11 @@ static void CSearchLight_RenderShadow(char type, void* texture, CVector* pos, fl
// Get original color intensity multiplier
float colorIntensity = static_cast<float>(intensity) / 128.0f;

// The game draws the spot with the texture of the street lamp light pools, so a shader could not address
// one without the other. Give the searchlights a texture of their own.
if (RwTexture* pSpotTexture = pGame->GetRenderWareSA()->GetSearchLightSpotTexture())
texture = pSpotTexture;

// CShadows::StoreShadowToBeRendered
((void(__cdecl*)(char, void*, CVector*, float, float, float, float, std::int16_t, unsigned char, unsigned char, unsigned char, float, bool, float, void*,
bool))0x707390)(type, texture, pos, x1, y1, x2, y2, intensity, static_cast<unsigned char>(searchLightColor.R * colorIntensity),
Expand Down
7 changes: 7 additions & 0 deletions Client/game_sa/CRadarSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ CMarker* CRadarSA::GetFreeMarker()
return Markers[Index];
}

CMarker* CRadarSA::GetMarker(int iIndex)
{
if (iIndex < 0 || iIndex >= MAX_MARKERS)
return nullptr;
return Markers[iIndex];
}

void CRadarSA::DrawAreaOnRadar(float fX1, float fY1, float fX2, float fY2, const SharedUtil::SColor color)
{
// Convert color to required abgr at the last moment
Expand Down
1 change: 1 addition & 0 deletions Client/game_sa/CRadarSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ class CRadarSA : public CRadar
~CRadarSA();
CMarker* CreateMarker(CVector* vecPosition);
CMarker* GetFreeMarker();
CMarker* GetMarker(int iIndex);
void DrawAreaOnRadar(float fX1, float fY1, float fX2, float fY2, const SharedUtil::SColor color);
};
99 changes: 93 additions & 6 deletions Client/game_sa/CRenderWareSA.ShaderSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "CGameSA.h"
#include "CRenderWareSA.ShaderMatching.h"
#include "CRenderWareSA.ShaderSupport.h"
#include "gamesa_renderware.h"

extern CCoreInterface* g_pCore;
extern CGameSA* pGame;
Expand All @@ -25,6 +26,8 @@ extern CGameSA* pGame;
#define ADDR_CClothesBuilder_ConstructTextures_End 0x05A6520
#define ADDR_CVehicle_DoHeadLightBeam_RenderPrimitive 0x06E13CD
#define ADDR_CHeli_SearchLightCone_RenderPrimitive 0x06C62AD
#define VAR_CShadows_gpShadowExplosionTex 0x0C403F4
#define FAKE_NAME_SEARCHLIGHT_SPOT "shad_searchlight"
#define ADDR_CWaterCannon_Render_RenderPrimitive 0x072956B

enum
Expand All @@ -36,7 +39,9 @@ enum
RT_3DNI,
};

int CRenderWareSA::ms_iRenderingType = 0;
int CRenderWareSA::ms_iRenderingType = 0;
CD3DDUMMY* CRenderWareSA::ms_pNoTextureD3DData = FAKE_D3DTEXTURE_NO_TEXTURE;
RwTexture* CRenderWareSA::ms_pSearchLightSpotTexture = nullptr;

////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -428,6 +433,82 @@ void CRenderWareSA::SetRenderingClientEntity(CClientEntityBase* pClientEntity, u
m_iRenderingEntityType = iTypeMask;
}

////////////////////////////////////////////////////////////////
//
// CRenderWareSA::GetSearchLightSpotTexture
//
// The ground spot of a searchlight is drawn by CShadows with the same texture as the
// light pools of street lamps. Give the searchlights a copy of that texture under a
// name of their own, so a shader can address the spots without touching the lamps
// while the spots look exactly as they do in the game.
//
////////////////////////////////////////////////////////////////
RwTexture* CRenderWareSA::GetSearchLightSpotTexture()
{
if (ms_pSearchLightSpotTexture)
return ms_pSearchLightSpotTexture;

RwTexture* pSource = *reinterpret_cast<RwTexture**>(VAR_CShadows_gpShadowExplosionTex);
if (!pSource || !pSource->raster || !pSource->raster->renderResource)
return nullptr;

// Read the game texture as plain BGRA rows (the pixels manager also decompresses DXT)
CPixelsManagerInterface* pPixelsManager = g_pCore->GetGraphics()->GetPixelsManager();
CPixels sourcePixels;
uint uiWidth = 0, uiHeight = 0;
if (!pPixelsManager->GetTexturePixels(reinterpret_cast<IDirect3DBaseTexture9*>(pSource->raster->renderResource), sourcePixels) ||
!pPixelsManager->GetPixelsSize(sourcePixels, uiWidth, uiHeight) || uiWidth == 0 || uiHeight == 0)
return nullptr;

RwRaster* pRaster = RwRasterCreate(uiWidth, uiHeight, 32, RASTER_TYPE_TEXTURE | RASTER_FORMAT_8888);
if (!pRaster)
return nullptr;

if (!RwRasterLock(pRaster, 0, RASTER_LOCK_WRITE) || !pRaster->pixels)
{
RwRasterDestroy(pRaster);
return nullptr;
}

// The sdk struct calls it numLevels, but RenderWare keeps the row stride of the locked raster there
const uint uiSourcePitch = uiWidth * sizeof(DWORD);
int iStride = pRaster->numLevels;
if (iStride <= 0)
iStride = uiSourcePitch;
for (uint y = 0; y < uiHeight; y++)
memcpy(pRaster->pixels + y * iStride, sourcePixels.GetData() + y * uiSourcePitch, uiSourcePitch);
RwRasterUnlock(pRaster);

RwTexture* pTexture = RwTextureCreate(pRaster);
if (!pTexture)
{
RwRasterDestroy(pRaster);
return nullptr;
}
strncpy(pTexture->name, FAKE_NAME_SEARCHLIGHT_SPOT, RW_TEXTURE_NAME_LENGTH - 1);
pTexture->flags = pSource->flags;
ms_pSearchLightSpotTexture = pTexture;

// Make it known to the texture replacer under its own name
OnTextureStreamIn(CreateTexInfo(pTexture, FAKE_NAME_SEARCHLIGHT_SPOT, reinterpret_cast<CD3DDUMMY*>(pRaster->renderResource)));
return pTexture;
}

////////////////////////////////////////////////////////////////
//
// CRenderWareSA::ResolveD3DData
//
// Draws without a texture are keyed by a fake texture ('unnamed', or 'searchlight' for
// the helicopter searchlight cones) when doing a 3d model like render
//
////////////////////////////////////////////////////////////////
CD3DDUMMY* CRenderWareSA::ResolveD3DData(CD3DDUMMY* pD3DData)
{
if (pD3DData == nullptr && CRenderWareSA::ms_iRenderingType == RT_NONE)
return CRenderWareSA::ms_pNoTextureD3DData;
return pD3DData;
}

////////////////////////////////////////////////////////////////
//
// CRenderWareSA::GetAppliedShaderForD3DData
Expand All @@ -439,11 +520,7 @@ SShaderItemLayers* CRenderWareSA::GetAppliedShaderForD3DData(CD3DDUMMY* pD3DData
{
m_uiReplacementRequestCounter++;

// If rendering with no texture, and doing an 3d model like render, use the 'unnamed' texinfo
if (pD3DData == NULL && CRenderWareSA::ms_iRenderingType == RT_NONE)
pD3DData = FAKE_D3DTEXTURE_NO_TEXTURE;

STexInfo* pTexInfo = MapFindRef(m_D3DDataTexInfoMap, pD3DData);
STexInfo* pTexInfo = MapFindRef(m_D3DDataTexInfoMap, ResolveD3DData(pD3DData));

if (!pTexInfo)
return NULL;
Expand Down Expand Up @@ -602,6 +679,12 @@ void CRenderWareSA::Initialize()
STexInfo* pTexInfo = CreateTexInfo(FAKE_RWTEXTURE_NO_TEXTURE, FAKE_NAME_NO_TEXTURE, FAKE_D3DTEXTURE_NO_TEXTURE);
OnTextureStreamIn(pTexInfo);
}
if (!MapContains(m_D3DDataTexInfoMap, FAKE_D3DTEXTURE_SEARCHLIGHT))
{
// Helicopter searchlight cones draw without a texture too, give them a name of their own
STexInfo* pTexInfo = CreateTexInfo(FAKE_RWTEXTURE_SEARCHLIGHT, FAKE_NAME_SEARCHLIGHT, FAKE_D3DTEXTURE_SEARCHLIGHT);
OnTextureStreamIn(pTexInfo);
}
}

////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -768,6 +851,9 @@ __declspec(noinline) void OnMY_RwIm3DRenderIndexedPrimitive_Pre(DWORD dwAddrCall
dwAddrCalledFrom == ADDR_CWaterCannon_Render_RenderPrimitive)
{
CRenderWareSA::ms_iRenderingType = RT_NONE; // Treat these items like world models
// The searchlight cones get a texture name of their own, so a shader can target them without every other untextured draw
if (dwAddrCalledFrom == ADDR_CHeli_SearchLightCone_RenderPrimitive)
CRenderWareSA::ms_pNoTextureD3DData = FAKE_D3DTEXTURE_SEARCHLIGHT;
}
else
{
Expand All @@ -778,6 +864,7 @@ __declspec(noinline) void OnMY_RwIm3DRenderIndexedPrimitive_Pre(DWORD dwAddrCall
__declspec(noinline) void OnMY_RwIm3DRenderIndexedPrimitive_Post(DWORD dwAddrCalledFrom)
{
CRenderWareSA::ms_iRenderingType = RT_NONE;
CRenderWareSA::ms_pNoTextureD3DData = FAKE_D3DTEXTURE_NO_TEXTURE;
}

// Hook info
Expand Down
3 changes: 3 additions & 0 deletions Client/game_sa/CRenderWareSA.ShaderSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#define FAKE_D3DTEXTURE_NO_TEXTURE ((CD3DDUMMY*)-9)
#define FAKE_RWTEXTURE_NO_TEXTURE ((RwTexture*)-10)
#define FAKE_NAME_NO_TEXTURE "unnamed"
#define FAKE_D3DTEXTURE_SEARCHLIGHT ((CD3DDUMMY*)-11)
#define FAKE_RWTEXTURE_SEARCHLIGHT ((RwTexture*)-12)
#define FAKE_NAME_SEARCHLIGHT "searchlight"

class CMatchChannel;
class CMatchChannelManager;
Expand Down
4 changes: 4 additions & 0 deletions Client/game_sa/CRenderWareSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class CRenderWareSA : public CRenderWare
const char* GetTextureName(CD3DDUMMY* pD3DData);
void SetRenderingClientEntity(CClientEntityBase* pClientEntity, ushort usModelId, int iTypeMask);
SShaderItemLayers* GetAppliedShaderForD3DData(CD3DDUMMY* pD3DData);
CD3DDUMMY* ResolveD3DData(CD3DDUMMY* pD3DData);
void AppendAdditiveMatch(CSHADERDUMMY* pShaderData, CClientEntityBase* pClientEntity, const char* strTextureNameMatch, float fShaderPriority,
bool bShaderLayered, int iTypeMask, uint uiShaderCreateTime, bool bShaderUsesVertexShader, bool bAppendLayers);
void AppendSubtractiveMatch(CSHADERDUMMY* pShaderData, CClientEntityBase* pClientEntity, const char* strTextureNameMatch);
Expand Down Expand Up @@ -167,4 +168,7 @@ class CRenderWareSA : public CRenderWare
bool m_bGTAVertexShadersEnabled;
std::set<RwTexture*> m_SpecialTextures;
static int ms_iRenderingType;
static CD3DDUMMY* ms_pNoTextureD3DData; // Fake texture used for draws without a texture
static RwTexture* ms_pSearchLightSpotTexture;
RwTexture* GetSearchLightSpotTexture();
};
2 changes: 2 additions & 0 deletions Client/game_sa/gamesa_renderware.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ typedef int(__cdecl* rwD3D9NativeTextureRead_t)(RwStream* stream, RwTexture** te
typedef RwRaster*(__cdecl* RwRasterUnlock_t)(RwRaster* raster);
typedef RwRaster*(__cdecl* RwRasterLock_t)(RwRaster* raster, unsigned char level, int lockmode);
typedef RwRaster*(__cdecl* RwRasterCreate_t)(int width, int height, int depth, int flags);
typedef int(__cdecl* RwRasterDestroy_t)(RwRaster* raster);
typedef RwTexture*(__cdecl* RwTextureCreate_t)(RwRaster* raster);
typedef RpMaterial*(__cdecl* RpMaterialSetTexture_t)(RpMaterial* mat, RwTexture* tex);
typedef RpHAnimHierarchy*(__cdecl* GetAnimHierarchyFromClump_t)(RpClump*);
Expand Down Expand Up @@ -188,6 +189,7 @@ RWFUNC(RwTextureDestroy_t RwTextureDestroy, (RwTextureDestroy_t)0xDEAD)
RWFUNC(RwRasterUnlock_t RwRasterUnlock, (RwRasterUnlock_t)0xDEAD)
RWFUNC(RwRasterLock_t RwRasterLock, (RwRasterLock_t)0xDEAD)
RWFUNC(RwRasterCreate_t RwRasterCreate, (RwRasterCreate_t)0xDEAD)
RWFUNC(RwRasterDestroy_t RwRasterDestroy, (RwRasterDestroy_t)0xDEAD)
RWFUNC(RwTextureCreate_t RwTextureCreate, (RwTextureCreate_t)0xDEAD)
RWFUNC(RpMaterialSetTexture_t RpMaterialSetTexture, (RpMaterialSetTexture_t)0xDEAD)
RWFUNC(GetAnimHierarchyFromClump_t GetAnimHierarchyFromClump, (GetAnimHierarchyFromClump_t)0xDEAD)
Expand Down
1 change: 1 addition & 0 deletions Client/game_sa/gamesa_renderware.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ void InitRwFunctions()
RwRasterUnlock = (RwRasterUnlock_t)0x007FAEC0;
RwRasterLock = (RwRasterLock_t)0x007FB2D0;
RwRasterCreate = (RwRasterCreate_t)0x007FB230;
RwRasterDestroy = (RwRasterDestroy_t)0x007FB020;
RwTextureCreate = (RwTextureCreate_t)0x007F37C0;
RpMaterialSetTexture = (RpMaterialSetTexture_t)0x0074DBC0;
GetAnimHierarchyFromClump = (GetAnimHierarchyFromClump_t)0x734B10;
Expand Down
2 changes: 2 additions & 0 deletions Client/mods/deathmatch/logic/CClient3DMarker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ CClient3DMarker::CClient3DMarker(CClientMarker* pThis)
m_dwType = static_cast<DWORD>(T3DMarkerType::MARKER3D_CYLINDER2);
m_pMarker = NULL;
m_ulIdentifier = (DWORD)this;
g_pClientGame->GetManager()->GetMarkerManager()->RegisterIdentifier(m_ulIdentifier, pThis);
}

CClient3DMarker::~CClient3DMarker()
{
g_pClientGame->GetManager()->GetMarkerManager()->UnregisterIdentifier(m_ulIdentifier);
}

unsigned long CClient3DMarker::Get3DMarkerType()
Expand Down
6 changes: 6 additions & 0 deletions Client/mods/deathmatch/logic/CClientCheckpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ CClientCheckpoint::CClientCheckpoint(CClientMarker* pThis)
// Init
m_pThis = pThis;
m_pCheckpoint = NULL;
m_dwIdentifier = 0;
m_bStreamedIn = false;
m_bVisible = true;
m_uiIcon = CClientCheckpoint::ICON_NONE;
Expand All @@ -37,6 +38,8 @@ CClientCheckpoint::~CClientCheckpoint()
{
// Eventually destroy the checkpoint
Destroy();
if (m_dwIdentifier)
g_pClientGame->GetManager()->GetMarkerManager()->UnregisterIdentifier(m_dwIdentifier);
CClientEntityRefManager::RemoveEntityRefs(0, &m_pThis, NULL);
}

Expand Down Expand Up @@ -350,12 +353,15 @@ void CClientCheckpoint::Create(unsigned long ulIdentifier)
if (ulIdentifier == 0)
{
s_ulIdentifier++;
if (m_dwIdentifier)
g_pClientGame->GetManager()->GetMarkerManager()->UnregisterIdentifier(m_dwIdentifier);
m_dwIdentifier = s_ulIdentifier;
}
else
{
m_dwIdentifier = ulIdentifier;
}
g_pClientGame->GetManager()->GetMarkerManager()->RegisterIdentifier(m_dwIdentifier, m_pThis);

// Create it
m_pCheckpoint =
Expand Down
2 changes: 2 additions & 0 deletions Client/mods/deathmatch/logic/CClientCorona.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ CClientCorona::CClientCorona(CClientMarker* pThis)
// Pick an unique identifier
static unsigned long ulIdentifier = 0xFFFFFFFF;
m_ulIdentifier = --ulIdentifier;
g_pClientGame->GetManager()->GetMarkerManager()->RegisterIdentifier(m_ulIdentifier, pThis);
}

CClientCorona::~CClientCorona()
Expand All @@ -38,6 +39,7 @@ CClientCorona::~CClientCorona()
{
pCorona->Disable();
}
g_pClientGame->GetManager()->GetMarkerManager()->UnregisterIdentifier(m_ulIdentifier);
CClientEntityRefManager::RemoveEntityRefs(0, &m_pThis, NULL);
}

Expand Down
Loading
Loading