Files
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

424 lines
15 KiB
C++

//
// filename: RenderPhaseStdNY.cpp
// description:
//
// --- Include Files ------------------------------------------------------------
#include "RenderPhaseStdNY.h"
// C headers
// Rage headers
#include "grcore/allocscope.h"
#include "grcore/debugdraw.h"
#include "grcore/quads.h"
#include "grcore/fastquad.h"
#include "profile\profiler.h"
#include "profile/timebars.h"
// Game headers
#include "camera/viewports/ViewportManager.h"
#include "camera/viewports/Viewport.h"
#include "control/replay/Replay.h"
#include "frontend/BusySpinner.h"
#include "FrontEnd/HudTools.h"
#include "FrontEnd/WarningScreen.h"
#include "Renderer\occlusion.h"
#include "renderer/PostProcessFX.h"
#include "renderer/Water.h"
#include "renderer\renderListGroup.h"
#include "renderer/ScreenshotManager.h"
#include "frontend/Credits.h"
#include "Frontend\MobilePhone.h"
#include "Frontend\PauseMenu.h"
#include "game\clock.h"
#include "SaveLoad/savegame_photo_manager.h"
#include "Scene\scene.h"
#include "Script\script.h"
#include "Vfx\VisualEffects.h"
#if RSG_XENON
#include "grcore/wrapper_d3d.h"
#endif
#if __PPU
#include "Renderer/PostProcessFX.h"
#endif // __PPU
// --- Defines ------------------------------------------------------------------
// --- Constants ----------------------------------------------------------------
// --- Structure/Class Definitions ----------------------------------------------
// --- Globals ------------------------------------------------------------------
EXT_PF_GROUP(RenderPhase);
// --- Static Globals -----------------------------------------------------------
// --- Static class members -----------------------------------------------------
// --- Code ---------------------------------------------------------------------
// ************************
// **** FRONTEND PHASE ****
// ************************
CRenderPhaseFrontEnd::CRenderPhaseFrontEnd(CViewport* pGameViewport)
: CRenderPhase(pGameViewport, "FrontEnd", DL_RENDERPHASE_FRONTEND, 0.0f, false)
{
}
void CRenderPhaseFrontEnd::UpdateViewport()
{
CRenderPhase::UpdateViewport();
// Update viewport
CViewport *pVp = GetViewport();
// Then make sure it is an ortho version.
if (pVp->GetGrcViewport().IsPerspective())
{
grcWindow win = pVp->GetGrcViewport().GetUnclippedWindow();
grcViewport t; // DW - this is done so that the constructor is called, it seems to be required to make the 2D rendering safe.
GetGrcViewport() = t;
GetGrcViewport().SetWindow(win.GetX(),win.GetY(),win.GetWidth(),win.GetHeight());
GetGrcViewport().Ortho(0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f);
}
}
//----------------------------------------------------
// build and execute the drawlist for this renderphase
void CRenderPhaseFrontEnd::BuildDrawList()
{
DrawListPrologue();
DLC(dlCmdSetCurrentViewport, (&GetGrcViewport()));
DLC_Add(CRenderTargets::LockUIRenderTargets);
if (!CWarningScreen::IsActive() || CWarningScreen::AllowSpinner()) // dont render a standalone busy spinner when we have a warningscreen active - fixes 1570349, 1571137
{
if (CBusySpinner::CanRender()) // fix for 1673887 - only add the spinner DLC if the movie is still fully active at this stage
{
DLC_Add(CBusySpinner::Render);
}
}
DLC_Add(CRenderTargets::UnlockUIRenderTargets, false);
PS3_ONLY(DLC_Add(CRenderTargets::Rescale);)
DLC(dlCmdSetCurrentViewportToNULL, ());
DrawListEpilogue();
}
// ***************************
// **** Phone Model PHASE ****
// ***************************
int CRenderPhasePhoneModel::ms_scissorRect[4];
int CRenderPhasePhoneModel::ms_prevScissorRect[4];
#if __BANK
bool CRenderPhasePhoneModel::ms_bDrawScissorRect = false;
#endif
//
// name: CRenderPhaseRadar::CRenderPhasePhoneModel
// description: Constructor for phone model render phase
CRenderPhasePhoneModel::CRenderPhasePhoneModel(CViewport* pGameViewport)
: CRenderPhase(pGameViewport, "Phone Model", DL_RENDERPHASE_PHONE, 0.0f, true)
{
}
#if __XENON
static D3DRECT gPhoneDrawRect;
#endif
GRC_ALLOC_SCOPE_DECLARE_GLOBAL(static, s_CRenderPhasePhoneModel_AllocScope)
void CRenderPhasePhoneModel::PhoneAAPrologue(const Vector3& phonePos, float phoneScale, float phoneRadius)
{
GRC_ALLOC_SCOPE_PUSH(s_CRenderPhasePhoneModel_AllocScope)
// nothing is bound at this point, on next-gen at least
//CRenderTargets::UnlockUIRenderTargets();
Vector3 rotation;
EulerAngleOrder rotationOrder;
CPhoneMgr::GetRotation(rotation, rotationOrder);
const float scale = phoneScale;
Vector3 position = phonePos;
// compute phone min/max bounding rect
grcViewport vp;
#if USE_INVERTED_PROJECTION_ONLY
vp.SetInvertZInProjectionMatrix(true,false);
#endif // USE_INVERTED_PROJECTION_ONLY
SetupPhoneViewport(&vp, position);
Matrix34 M;
CScriptEulers::MatrixFromEulers(M, Vector3(-DEG2RAD(90.0f), 0.0f, 0.0f), rotationOrder);
M.Scale(scale, scale, scale);
M.d = Vector3(0.0f, 0.0f, position.z);
vp.SetWorldMtx(MATRIX34_TO_MAT34V(M));
const float radius = phoneRadius;
const Vector3 pTL = -Vector3(radius,0.0f,radius);
const Vector3 pBR = Vector3(radius,0.0f,radius);
float x0, y0, x1, y1;
vp.Transform(VECTOR3_TO_VEC3V(pTL), x0, y0);
vp.Transform(VECTOR3_TO_VEC3V(pBR), x1, y1);
const int deviceWidth = VideoResManager::GetUIWidth();
const int deviceHeight = VideoResManager::GetUIHeight();
const float vpW = (float)vp.GetWidth();
const float vpH = (float)vp.GetHeight();
x0 = x0*(float)(deviceWidth)/vpW;
y0 = y0*(float)(deviceHeight)/vpH;
x1 = x1*(float)(deviceWidth)/vpW;
y1 = y1*(float)(deviceHeight)/vpH;
Vec2V vmin = Vec2V(Min(x0, x1), Min(y0, y1));
Vec2V vmax = Vec2V(Max(x0, x1), Max(y0, y1));
#if __BANK
if (ms_bDrawScissorRect)
{
Vec2V vdims = Vec2V(1.0f/(float)deviceWidth, 1.0f/(float)deviceHeight);
grcDebugDraw::RectAxisAligned(vmin*vdims, vmax*vdims, Color32(0xffff0000), false);
}
#endif
ms_scissorRect[0] = Clamp((int)(vmin.GetXf()) - 1,0,deviceWidth-1);
ms_scissorRect[1] = Clamp((int)(vmin.GetYf()) - 1,0,deviceHeight-1);
ms_scissorRect[2] = Max(Clamp((int)(vmax.GetXf()-vmin.GetXf()) + 2,0,Min((int)deviceWidth - ms_scissorRect[0], deviceWidth)), 1);
ms_scissorRect[3] = Max(Clamp((int)(vmax.GetYf()-vmin.GetYf()) + 2,0,Min((int)deviceHeight - ms_scissorRect[1], deviceHeight)), 1);
#if SUPPORT_MULTI_MONITOR
// cut around the central monitor borders
const GridMonitor& mon = GRCDEVICE.GetMonitorConfig().getLandscapeMonitor();
ms_scissorRect[0] = Max(ms_scissorRect[0], (int)mon.uLeft);
ms_scissorRect[1] = Max(ms_scissorRect[1], (int)mon.uTop);
ms_scissorRect[2] = Min(ms_scissorRect[2], Max(0, (int)mon.uRight - ms_scissorRect[0]));
ms_scissorRect[3] = Min(ms_scissorRect[3], Max(0, (int)mon.uBottom - ms_scissorRect[1]));
#endif //SUPPORT_MULTI_MONITOR
//ms_scissorRect[2] = Min(ms_scissorRect[2], ms_scissorRect[2]-ms_scissorRect[3]);
//ms_scissorRect[3] = Min(ms_scissorRect[3], ms_scissorRect[2]-ms_scissorRect[1]));
#if __XENON
// resolve a copy of whatever we've rendered so far, we're about to reuse
// the edram region where this lives
grcRenderTarget* pBBCopy = CRenderTargets::GetBackBufferCopy();
D3DRECT srcRect = { Max((((int)vmin.GetXf()-GPU_RESOLVE_ALIGNMENT-1)/GPU_RESOLVE_ALIGNMENT)*GPU_RESOLVE_ALIGNMENT, 0),
Max((((int)vmin.GetYf()-GPU_RESOLVE_ALIGNMENT-1)/GPU_RESOLVE_ALIGNMENT)*GPU_RESOLVE_ALIGNMENT, 0),
Min((((int)vmax.GetXf()+GPU_RESOLVE_ALIGNMENT-1)/GPU_RESOLVE_ALIGNMENT)*GPU_RESOLVE_ALIGNMENT, deviceWidth),
Min((((int)vmax.GetYf()+GPU_RESOLVE_ALIGNMENT-1)/GPU_RESOLVE_ALIGNMENT)*GPU_RESOLVE_ALIGNMENT, deviceHeight) };
srcRect.x2 = Max((int)srcRect.x2, 1);
srcRect.y2 = Max((int)srcRect.y2, 1);
D3DPOINT dstPoint = { srcRect.x1, srcRect.y1 };
CHECK_HRESULT( GRCDEVICE.GetCurrent()->Resolve( D3DRESOLVE_RENDERTARGET0 | D3DRESOLVE_ALLFRAGMENTS, &srcRect, pBBCopy->GetTexturePtr(), &dstPoint, 0, 0, NULL, 0.0f, 0L, NULL ) );
gPhoneDrawRect = srcRect;
ms_scissorRect[0] = Min((int)srcRect.x1, deviceWidth-2);
ms_scissorRect[1] = Min((int)srcRect.y1, deviceHeight-2);
ms_scissorRect[2] = Max((int)(srcRect.x2-ms_scissorRect[0]), 2);
ms_scissorRect[3] = Max((int)(srcRect.y2-ms_scissorRect[1]), 2);
#endif //__XENON
#if __D3D11 || RSG_ORBIS
grcRenderTarget *colorRT = CRenderTargets::GetOffscreenBuffer2();
#else
grcRenderTarget *colorRT = CRenderTargets::GetOffscreenBuffer1();
#endif
grcRenderTarget *depthRT = CRenderTargets::GetUIDepthBuffer();
grcTextureFactory::GetInstance().LockRenderTarget(0, colorRT, depthRT);
#if __XENON
// cache current scissor rect
GRCDEVICE.GetScissor(ms_prevScissorRect[0], ms_prevScissorRect[1], ms_prevScissorRect[2], ms_prevScissorRect[3]);
ms_prevScissorRect[2] = Min(ms_prevScissorRect[2], GRCDEVICE.GetWidth());
ms_prevScissorRect[3] = Min(ms_prevScissorRect[3], GRCDEVICE.GetHeight());
#endif
// GRCDEVICE.ClearRect(srcRect.x1, srcRect.y1, Max((int)(srcRect.x2-srcRect.x1), 1), Max((int)(srcRect.y2-srcRect.y1), 1), true, Color32(0x00000000), true, grcDepthFarthest, true, 0x0);
// GRCDEVICE.SetScissor(srcRect.x1, srcRect.y1, Max((int)(srcRect.x2-srcRect.x1), 1), Max((int)(srcRect.y2-srcRect.y1), 1));
GRCDEVICE.SetScissor(ms_scissorRect[0], ms_scissorRect[1], ms_scissorRect[2], ms_scissorRect[3]);
#if __D3D11 || RSG_ORBIS
// use the fastest clear path for MSAA, relying on stencil for culling pixels out
float depth = USE_INVERTED_PROJECTION_ONLY ? grcDepthClosest : grcDepthFarthest;
GRCDEVICE.Clear(true, Color32(0x00000000), true, depth, true, 0x0);
#else
GRCDEVICE.ClearRect(ms_scissorRect[0], ms_scissorRect[1], ms_scissorRect[2], ms_scissorRect[3], true, Color32(0x00000000), true, grcDepthFarthest, true, 0x0);
#endif
}
void CRenderPhasePhoneModel::PhoneAAEpilogue()
{
#if __D3D11 || RSG_ORBIS
grcRenderTarget *colorRT = CRenderTargets::GetOffscreenBuffer2();
#else
grcRenderTarget *colorRT = CRenderTargets::GetOffscreenBuffer1();
#endif
CSprite2d::CustomShaderType blitMode = CSprite2d::CS_BLIT_AAAlpha;
grcResolveFlags flags;
#if __XENON
flags.NeedResolve = false;
D3DRECT srcRect = gPhoneDrawRect;
D3DPOINT dstPoint = { srcRect.x1, srcRect.y1 };
CHECK_HRESULT( GRCDEVICE.GetCurrent()->Resolve( D3DRESOLVE_RENDERTARGET0 | D3DRESOLVE_ALLFRAGMENTS, &srcRect, colorRT->GetTexturePtr(), &dstPoint, 0, 0, NULL, 0.0f, 0L, NULL ) );
#endif //__XENON
grcTextureFactory::GetInstance().UnlockRenderTarget(0, &flags);
#if DEVICE_MSAA
if (GRCDEVICE.GetMSAA())
{
# if DEVICE_EQAA
eqaa::ResolveArea area(ms_scissorRect[0], ms_scissorRect[1], ms_scissorRect[2], ms_scissorRect[3]);
# endif
CRenderTargets::ResolveOffscreenBuffer2();
colorRT = CRenderTargets::GetOffscreenBuffer2_Resolved();
blitMode = CSprite2d::CS_BLIT; //it's already AA
}
#endif // DEVICE_MSAA
CRenderTargets::LockUIRenderTargets();
GRCDEVICE.SetScissor(ms_scissorRect[0], ms_scissorRect[1], ms_scissorRect[2], ms_scissorRect[3]);
float depth = USE_INVERTED_PROJECTION_ONLY ? grcDepthClosest : grcDepthFarthest;
GRCDEVICE.Clear(false, Color32(0x00000000), true, depth, true, 0);
#if __XENON
// blit backbuffer back
grcStateBlock::SetBlendState(grcStateBlock::BS_Default);
grcStateBlock::SetDepthStencilState(grcStateBlock::DSS_IgnoreDepth);
grcStateBlock::SetRasterizerState(grcStateBlock::RS_Default);
CSprite2d copyTarget;
const Vector2 TexSizeBB(1.0f/float(CRenderTargets::GetBackBufferCopy()->GetWidth()), 1.0f/float(CRenderTargets::GetBackBufferCopy()->GetHeight()));
copyTarget.SetTexelSize(TexSizeBB);
copyTarget.BeginCustomList(CSprite2d::CS_BLIT_NOFILTERING, CRenderTargets::GetBackBufferCopy());
grcDrawSingleQuadf(-1.0, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f+TexSizeBB.x,0.0f+TexSizeBB.y,1.0f+TexSizeBB.x,1.0f+TexSizeBB.y,Color32(255,255,255,255));
copyTarget.EndCustomList();
#endif
grcStateBlock::SetBlendState(grcStateBlock::BS_CompositeAlpha);
grcStateBlock::SetDepthStencilState(grcStateBlock::DSS_IgnoreDepth);
grcStateBlock::SetRasterizerState(grcStateBlock::RS_Default);
const int deviceWidth = VideoResManager::GetUIWidth();
const int deviceHeight = VideoResManager::GetUIHeight();
// the AA pass is going to create some feathering along the edges, so tighten the scissor rect to avoid blitting those pixels back
GRCDEVICE.SetScissor(Min(ms_scissorRect[0]+2, deviceWidth-1), Min(ms_scissorRect[1]+2, deviceHeight-1), Max(ms_scissorRect[2]-2, 1), Max(ms_scissorRect[3]-2, 1));
CSprite2d UIAASprite;
UIAASprite.SetGeneralParams(Vector4(1.0f, 1.0f, 1.0f, 1.0f), Vector4(0.0f, 0.0f, 0.0f, 0.0f));
const Vector2 TexSize(1.0f/float(colorRT->GetWidth()), 1.0f/float(colorRT->GetHeight()));
UIAASprite.SetTexelSize(TexSize);
UIAASprite.BeginCustomList(blitMode, colorRT);
grcDrawSingleQuadf(-1.0f,1.0f,1.0f,-1.0f,0.1f,0.0f,0.0f,1.0f,1.0f,Color32(0xffffffff));
UIAASprite.EndCustomList();
#if __XENON
// Restore whatever was set before rendering the phone
GRCDEVICE.SetScissor(ms_prevScissorRect[0], ms_prevScissorRect[1], ms_prevScissorRect[2], ms_prevScissorRect[3]);
#else
GRCDEVICE.SetScissor(0, 0, colorRT->GetWidth(), colorRT->GetHeight());
#endif
GRC_ALLOC_SCOPE_POP(s_CRenderPhasePhoneModel_AllocScope)
}
//----------------------------------------------------
// set ups viewport
void CRenderPhasePhoneModel::SetupPhoneViewport(grcViewport* vp, Vector3& phonePos)
{
float aspect = CHudTools::GetAspectRatio();
#if SUPPORT_MULTI_MONITOR
const GridMonitor &mon = GRCDEVICE.GetMonitorConfig().getCentralMonitor();
if (GRCDEVICE.GetMonitorConfig().isMultihead() && !mon.bLandscape)
{
// not sure why, but this works
aspect = mon.fPhysicalAspect;
}
#endif //SUPPORT_MULTI_MONITOR
vp->Perspective(70.0f, aspect, 0.01f, 400.0f);
// Calculate shear X and Y to have the phone at the required position
// but with a vanishing point positioned at the centre of the phone.
float winX,winY;
vp->Transform(RCC_VEC3V(phonePos),winX,winY);
const float height = (float)vp->GetHeight();
const float width = (float)vp->GetWidth();
const float normX = winX/width;
const float normY = winY/height;
const float spaceX = -(normX*2.0f - 1.0f);
const float spaceY = normY*2.0f - 1.0f;
vp->SetPerspectiveShear(spaceX * CHudTools::GetAspectRatioMultiplier(), spaceY);
}
//----------------------------------------------------
// build and execute the drawlist for this renderphase
void CRenderPhasePhoneModel::BuildDrawList()
{
#if __PS3
// if (CHighQualityScreenshot::IsProcessingScreenshot())
if (CPhotoManager::IsProcessingScreenshot())
return;
#endif // __PS3
if (CPauseMenu::IsActive()) // don't render mobile phone when frontend is active
return;
if (!GetViewport()->IsActive())
return;
if (CPhoneMgr::CamGetState())
return;
if (CPhoneMgr::IsDisplayed() == false)
return;
DrawListPrologue();
#if RSG_PC
DLC_Add(CShaderLib::SetStereoParams,Vector4(0,0,1,0));
#endif
DLC_Add(CShaderLib::SetUseFogRay, false);
DLC_Add(CShaderLib::SetFogRayTexture);
if (CPhoneMgr::UseAATechnique())
{
DLC_Add(PhoneAAPrologue, *CPhoneMgr::GetPosition(), CPhoneMgr::GetScale(), CPhoneMgr::GetRadius());
CPhoneMgr::Render(CPhoneMgr::DRAWPHONE_BODY_ONLY);
DLC_Add(PhoneAAEpilogue);
CPhoneMgr::Render(CPhoneMgr::DRAWPHONE_SCREEN_ONLY);
}
else
{
DLC_Add(CRenderTargets::LockUIRenderTargets);
float depth = USE_INVERTED_PROJECTION_ONLY ? grcDepthClosest : grcDepthFarthest;
DLC ( dlCmdClearRenderTarget, (false, Color32(0x00000000), true, depth, true, 0));
CPhoneMgr::Render(CPhoneMgr::DRAWPHONE_ALL);
}
DLC(dlCmdSetCurrentViewportToNULL, ());
DLC_Add(CRenderTargets::UnlockUIRenderTargets, false);
DLC_Add(CShaderLib::SetUseFogRay, true);
#if RSG_PC
DLC_Add(CShaderLib::SetStereoParams,Vector4(0,0,0,0));
#endif
DrawListEpilogue();
}