Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

375 lines
18 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #ifndef PORTALRENDER_H
  8. #define PORTALRENDER_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "iviewrender.h"
  13. #include "view_shared.h"
  14. #include "viewrender.h"
  15. #include "shaderapi/ishaderapi.h"
  16. #define MAX_PORTAL_RECURSIVE_VIEWS 11 //maximum number of recursions we allow when drawing views through portals. Seeing as how 5 is extremely choppy under best conditions and is barely visible, 10 is a safe limit. Adding one because 0 tends to be the primary view in most arrays of this size
  17. class C_Prop_Portal;
  18. class CPortalRenderable
  19. {
  20. public:
  21. CPortalRenderable( void );
  22. virtual ~CPortalRenderable( void );
  23. //----------------------------------------------------------------------------
  24. //Stencil-based drawing helpers, these are ONLY used in stencil drawing mode
  25. //----------------------------------------------------------------------------
  26. virtual void DrawPreStencilMask( IMatRenderContext *pRenderContext ) { }; //Do whatever drawing you need before cutting the stencil hole
  27. virtual void DrawStencilMask( IMatRenderContext *pRenderContext ) { }; //Draw to wherever you should see through the portal. The mask will later be filled with the portal view.
  28. virtual void DrawPostStencilFixes( IMatRenderContext *pRenderContext ) { }; //After done drawing to the portal mask, we need to fix the depth buffer as well as fog. So draw your mesh again, writing to z and with the fog color alpha'd in by distance
  29. //----------------------------------------------------------------------------
  30. //Rendering of views beyond the portal
  31. //----------------------------------------------------------------------------
  32. virtual void RenderPortalViewToBackBuffer( CViewRender *pViewRender, const CViewSetup &cameraView ) { };
  33. virtual void RenderPortalViewToTexture( CViewRender *pViewRender, const CViewSetup &cameraView ) { };
  34. //----------------------------------------------------------------------------
  35. //Visibility through portals
  36. //----------------------------------------------------------------------------
  37. virtual bool DoesExitViewIntersectWaterPlane( float waterZ, int leafWaterDataID ) const { return false; };
  38. virtual SkyboxVisibility_t SkyBoxVisibleFromPortal( void ) { return SKYBOX_NOT_VISIBLE; };
  39. //-----------------------------------------------------------------------------
  40. //Fog workarounds
  41. //-----------------------------------------------------------------------------
  42. virtual const Vector& GetFogOrigin( void ) const { return vec3_origin; };
  43. virtual void ShiftFogForExitPortalView() const;
  44. virtual float GetPortalDistanceBias() const { return 0.0f; }
  45. //-----------------------------------------------------------------------------
  46. //Portal visibility testing
  47. //-----------------------------------------------------------------------------
  48. //Based on view, will the camera be able to see through the portal this frame? This will allow the stencil mask to start being tested for pixel visibility.
  49. virtual bool ShouldUpdatePortalView_BasedOnView( const CViewSetup &currentView, const CUtlVector<VPlane> &currentComplexFrustum ) { return false; };
  50. //Stencil mode only: You stated the portal was visible based on view, and this is how much of the screen your stencil mask took up last frame. Still want to draw this frame? Values less than zero indicate a lack of data from last frame
  51. virtual bool ShouldUpdatePortalView_BasedOnPixelVisibility( float fScreenFilledByStencilMaskLastFrame_Normalized ) { return (fScreenFilledByStencilMaskLastFrame_Normalized != 0.0f); }; // < 0 is unknown visibility, > 0 is known to be partially visible
  52. //-----------------------------------------------------------------------------
  53. // Misc
  54. //-----------------------------------------------------------------------------
  55. virtual CPortalRenderable* GetLinkedPortal() const { return NULL; };
  56. const VMatrix& MatrixThisToLinked() const;
  57. virtual bool ShouldUpdateDepthDoublerTexture( const CViewSetup &viewSetup ) { return false; };
  58. virtual void DrawPortal( IMatRenderContext *pRenderContext ) { }; //sort of like what you'd expect to happen in C_BaseAnimating::DrawModel() if portals were fully compatible with models
  59. virtual int BindPortalMaterial( IMatRenderContext *pRenderContext, int nPassIndex, bool *pAllowRingMeshOptimizationOut ) { Assert( 0 ); return 0; }
  60. virtual C_BaseEntity *PortalRenderable_GetPairedEntity( void ) { return NULL; }; //Pairing a portal with an entity is common but not required. Accessing that entity allows the CPortalRender system to better optimize.
  61. VMatrix m_matrixThisToLinked; //Always going to need a matrix
  62. // Poor man's RTTI
  63. FORCEINLINE bool IsPropPortal() const { return m_bIsPropPortal; }
  64. //-----------------------------------------------------------------------------
  65. //SFM related
  66. //-----------------------------------------------------------------------------
  67. bool m_bIsPlaybackPortal;
  68. virtual void HandlePortalPlaybackMessage( KeyValues *pKeyValues ) { };
  69. protected:
  70. CPortalRenderable *FindRecordedPortal( int nPortalId ); //routed through here to get friend access to CPortalRender
  71. //routed through here to get friend access to CViewRender
  72. void CopyToCurrentView( CViewRender *pViewRender, const CViewSetup &viewSetup );
  73. void ViewDrawScene_PortalStencil( CViewRender *pViewRender, const CViewSetup &viewIn, ViewCustomVisibility_t *pCustomVisibility );
  74. void Draw3dSkyboxworld_Portal( CViewRender *pViewRender, const CViewSetup &viewIn, int &nClearFlags, bool &bDrew3dSkybox, SkyboxVisibility_t &nSkyboxVisible, ITexture *pRenderTarget = NULL );
  75. void ViewDrawScene( CViewRender *pViewRender, bool bDrew3dSkybox, SkyboxVisibility_t nSkyboxVisible, const CViewSetup &viewIn, int nClearFlags, view_id_t viewID, bool bDrawViewModel = false, int baseDrawFlags = 0, ViewCustomVisibility_t *pCustomVisibility = NULL );
  76. void SetViewRecursionLevel( int iViewRecursionLevel );
  77. void SetRemainingViewDepth( int iRemainingViewDepth );
  78. void SetViewEntranceAndExitPortals( CPortalRenderable *pEntryPortal, CPortalRenderable *pExitPortal );
  79. bool m_bIsPropPortal;
  80. private:
  81. int m_iPortalViewIDNodeIndex; //each PortalViewIDNode_t has a child node link for each CPortalRenderable in CPortalRender::m_ActivePortals. This portal follows the same indexed link from each node
  82. // m_iPortalViewIDNodeIndex is the index into CPortalRender::m_AllPortals
  83. friend class CPortalRender;
  84. };
  85. //-----------------------------------------------------------------------------
  86. // inline state querying methods
  87. //-----------------------------------------------------------------------------
  88. inline const VMatrix& CPortalRenderable::MatrixThisToLinked() const
  89. {
  90. return m_matrixThisToLinked;
  91. }
  92. //-----------------------------------------------------------------------------
  93. // Portal rendering materials
  94. //-----------------------------------------------------------------------------
  95. struct PortalRenderingMaterials_t
  96. {
  97. CMaterialReference m_Wireframe;
  98. CMaterialReference m_WriteZ_Model;
  99. CMaterialReference m_TranslucentVertexColor;
  100. CMaterialReference m_PortalDepthDoubler;
  101. unsigned int m_nDepthDoubleViewMatrixVarCache;
  102. };
  103. struct PortalViewIDNode_t
  104. {
  105. CUtlVector<PortalViewIDNode_t *> ChildNodes; //links will only be non-null if they're useful (can see through the portal at that depth and view setup)
  106. int iPrimaryViewID;
  107. //skybox view id is always primary + 1
  108. //In stencil mode this wraps CPortalRenderable::DrawStencilMask() and gives previous frames' results to CPortalRenderable::RenderPortalViewToBackBuffer()
  109. //In texture mode there's no good spot to auto-wrap occlusion tests. So you'll need to wrap it yourself for that.
  110. OcclusionQueryObjectHandle_t occlusionQueryHandle;
  111. int iWindowPixelsAtQueryTime;
  112. int iOcclusionQueryPixelsRendered;
  113. float fScreenFilledByPortalSurfaceLastFrame_Normalized;
  114. };
  115. struct GhostPortalRenderInfo_t
  116. {
  117. C_Prop_Portal *m_pPortal;
  118. int m_nGhostPortalQuadIndex;
  119. IMaterial *m_pGhostMaterial;
  120. };
  121. struct ClampedPortalMeshRenderInfo_t
  122. {
  123. int nStartIndex;
  124. int nIndexCount;
  125. };
  126. //-----------------------------------------------------------------------------
  127. // Portal rendering management class
  128. //-----------------------------------------------------------------------------
  129. class CPortalRender : public CAutoGameSystem
  130. {
  131. public:
  132. CPortalRender();
  133. ~CPortalRender();
  134. // Inherited from IGameSystem
  135. virtual void LevelInitPreEntity();
  136. virtual void LevelShutdownPreEntity();
  137. // Are we currently rendering a portal?
  138. bool IsRenderingPortal() const;
  139. // Returns the current View IDs. Portal View IDs will change often (especially with recursive views) and should not be cached
  140. int GetCurrentViewId() const;
  141. int GetCurrentSkyboxViewId() const;
  142. // Returns view recursion level
  143. int GetViewRecursionLevel() const;
  144. float GetPixelVisilityForPortalSurface( const CPortalRenderable *pPortal ) const; //normalized for how many of the screen's possible pixels it takes up, less than zero indicates a lack of data from last frame
  145. // Returns the remaining number of portals to render within other portals
  146. // lets portals know that they should do "end of the line" kludges to cover up that portals don't go infinitely recursive
  147. int GetRemainingPortalViewDepth() const;
  148. inline CPortalRenderable *GetCurrentViewEntryPortal( void ) const { return m_pRenderingViewForPortal; }; //if rendering a portal view, this is the portal the current view enters into
  149. inline CPortalRenderable *GetCurrentViewExitPortal( void ) const { return m_pRenderingViewExitPortal; }; //if rendering a portal view, this is the portal the current view exits from
  150. //it's a good idea to force cheaper water when the ratio of performance gain to noticability is high
  151. //0 = force no reflection/refraction
  152. //1/2 = downgrade to simple/world reflections as seen in advanced video options
  153. //3 = no downgrade
  154. int ShouldForceCheaperWaterLevel() const;
  155. bool ShouldObeyStencilForClears() const;
  156. #ifdef _PS3
  157. void ReloadZcullMemory();
  158. #endif // _PS3
  159. //sometimes we have to tweak some systems to render water properly with portals
  160. void WaterRenderingHandler_PreReflection() const;
  161. void WaterRenderingHandler_PostReflection() const;
  162. void WaterRenderingHandler_PreRefraction() const;
  163. void WaterRenderingHandler_PostRefraction() const;
  164. // return value indicates that something was done, and render lists should be rebuilt afterwards
  165. bool DrawPortalsUsingStencils( CViewRender *pViewRender );
  166. bool DrawPortalsUsingStencils_Old( CViewRender *pViewRender );
  167. void OverlayPortalRenderTargets( float w, float h );
  168. void UpdateDepthDoublerTexture( const CViewSetup &viewSetup ); //our chance to update all depth doubler texture before the view model is added to the back buffer
  169. static bool DepthDoublerPIPDisableCheck( void ); //the depth doubler texture is unusable for a picture-in-picture view. Rather than sort out that ugly mess, just disable it for that case.
  170. void EnteredPortal( int nPlayerSlot, CPortalRenderable *pEnteredPortal ); //does a bit of internal maintenance whenever the player/camera has logically passed the portal threshold
  171. // adds, removes a portal to the set of renderable portals
  172. void AddPortal( CPortalRenderable *pPortal );
  173. void RemovePortal( CPortalRenderable *pPortal );
  174. // Methods to query about the exit portal associated with the currently rendering portal
  175. void ShiftFogForExitPortalView() const;
  176. float GetCurrentPortalDistanceBias() const;
  177. const Vector &GetExitPortalFogOrigin() const;
  178. SkyboxVisibility_t IsSkyboxVisibleFromExitPortal() const;
  179. bool DoesExitPortalViewIntersectWaterPlane( float waterZ, int leafWaterDataID ) const;
  180. void HandlePortalPlaybackMessage( KeyValues *pKeyValues );
  181. CPortalRenderable* FindRecordedPortal( IClientRenderable *pRenderable );
  182. CViewSetup m_RecursiveViewSetups[MAX_PORTAL_RECURSIVE_VIEWS]; //before we recurse into a view, we backup the view setup here for reference
  183. // tests if the parameter ID is being used by portal pixel vis queries
  184. bool IsPortalViewID( view_id_t id );
  185. inline CUtlVector<VPlane> &GetRecursiveViewComplexFrustums( int nIdx ) { return m_RecursiveViewComplexFrustums[ nIdx ]; }
  186. void DrawEarlyZPortals( CViewRender *pViewRender );
  187. private:
  188. struct RecordedPortalInfo_t
  189. {
  190. CPortalRenderable *m_pActivePortal;
  191. int m_nPortalId;
  192. IClientRenderable *m_pPlaybackRenderable;
  193. };
  194. PortalViewIDNode_t m_HeadPortalViewIDNode; //pseudo node. Primary view id will be VIEW_MAIN. The child links are what we really care about
  195. PortalViewIDNode_t* m_PortalViewIDNodeChain[MAX_PORTAL_RECURSIVE_VIEWS]; //the view id node chain we're following, 0 always being &m_HeadPortalViewIDNode (offsetting by 1 seems like it'd cause bugs in the long run)
  196. void UpdatePortalPixelVisibility( void ); //updates pixel visibility for portal surfaces
  197. // Handles a portal update message
  198. void HandlePortalUpdateMessage( KeyValues *pKeyValues );
  199. // Finds a recorded portal
  200. int FindRecordedPortalIndex( int nPortalId );
  201. CPortalRenderable* FindRecordedPortal( int nPortalId );
  202. void DrawPortalGhostLocations( IMatRenderContext *pRenderContext, IMesh *pPortalQuadMesh, const GhostPortalRenderInfo_t *pGhostPortalRenderInfos, int nPortalCount ) const;
  203. void RenderPortalEffects( IMatRenderContext *pRenderContext, IMesh *pPortalQuadMesh, const CUtlVector< CPortalRenderable* > &actualActivePortals,
  204. const CUtlVector< int > &actualActivePortalQuadVBIndex ) const;
  205. private:
  206. PortalRenderingMaterials_t m_Materials;
  207. int m_iViewRecursionLevel;
  208. int m_iRemainingPortalViewDepth; //let's portals know that they should do "end of the line" kludges to cover up that portals don't go infinitely recursive
  209. // Data that's only valid while inside DrawPortalsUsingStencil()
  210. CUtlStack<int> m_stencilValueStack;
  211. CUtlStack<int> m_parentPortalIdStack;
  212. ICachedPerFrameMeshData *m_pCachedPortalQuadMeshData;
  213. VertexFormat_t m_portalQuadMeshVertexFmt;
  214. CUtlVector< ClampedPortalMeshRenderInfo_t > m_clampedPortalMeshRenderInfos;
  215. CUtlVector< bool > m_portalIsOpening;
  216. CPortalRenderable *m_pRenderingViewForPortal; //the specific pointer for the portal that we're rending a view for
  217. CPortalRenderable *m_pRenderingViewExitPortal; //the specific pointer for the portal that our view exits from
  218. CUtlVector<CPortalRenderable *> m_AllPortals; //All portals currently in memory, active or not
  219. CUtlVector<CPortalRenderable *> m_ActivePortals;
  220. CUtlVector< RecordedPortalInfo_t > m_RecordedPortals;
  221. ShaderStencilState_t m_StencilState;
  222. CUtlVector<VPlane> m_RecursiveViewComplexFrustums[MAX_PORTAL_RECURSIVE_VIEWS];
  223. CUtlVector< GhostPortalRenderInfo_t > m_portalGhostRenderInfos;
  224. public:
  225. //frustums with more (or less) than 6 planes. Store each recursion level's custom frustum here so further recursions can be better optimized.
  226. //When going into further recursions, if you've failed to fill in a complex frustum, the standard frustum will be copied in.
  227. //So all parent levels are guaranteed to contain valid data
  228. PortalRenderingMaterials_t& m_MaterialsAccess;
  229. friend class CPortalRenderable;
  230. friend void OnRenderStart();
  231. };
  232. extern CPortalRender* g_pPortalRender;
  233. inline CPortalRenderable *CPortalRenderable::FindRecordedPortal( int nPortalId )
  234. {
  235. return g_pPortalRender->FindRecordedPortal( nPortalId );
  236. }
  237. typedef CPortalRenderable *(*PortalRenderableCreationFunc)( void );
  238. //only ever create global/static instances of this
  239. class CPortalRenderableCreator_AutoRegister
  240. {
  241. public:
  242. CPortalRenderableCreator_AutoRegister( const char *szType, PortalRenderableCreationFunc creationFunc )
  243. : m_szPortalType( szType ), m_creationFunc( creationFunc )
  244. {
  245. m_pNext = s_pRegisteredTypes;
  246. s_pRegisteredTypes = this;
  247. }
  248. private:
  249. const char *m_szPortalType;
  250. PortalRenderableCreationFunc m_creationFunc;
  251. const CPortalRenderableCreator_AutoRegister *m_pNext;
  252. static CPortalRenderableCreator_AutoRegister *s_pRegisteredTypes;
  253. friend class CPortalRender;
  254. };
  255. //-----------------------------------------------------------------------------
  256. // inline friend access redirects
  257. //-----------------------------------------------------------------------------
  258. inline void CPortalRenderable::CopyToCurrentView( CViewRender *pViewRender, const CViewSetup &viewSetup )
  259. {
  260. pViewRender->m_CurrentView = viewSetup;
  261. }
  262. inline void CPortalRenderable::ViewDrawScene_PortalStencil( CViewRender *pViewRender, const CViewSetup &viewIn, ViewCustomVisibility_t *pCustomVisibility )
  263. {
  264. pViewRender->ViewDrawScene_PortalStencil( viewIn, pCustomVisibility );
  265. }
  266. inline void CPortalRenderable::Draw3dSkyboxworld_Portal( CViewRender *pViewRender, const CViewSetup &viewIn, int &nClearFlags, bool &bDrew3dSkybox, SkyboxVisibility_t &nSkyboxVisible, ITexture *pRenderTarget )
  267. {
  268. pViewRender->Draw3dSkyboxworld_Portal( viewIn, nClearFlags, bDrew3dSkybox, nSkyboxVisible, pRenderTarget );
  269. }
  270. inline void CPortalRenderable::ViewDrawScene( CViewRender *pViewRender, bool bDrew3dSkybox, SkyboxVisibility_t nSkyboxVisible, const CViewSetup &viewIn, int nClearFlags, view_id_t viewID, bool bDrawViewModel, int baseDrawFlags, ViewCustomVisibility_t *pCustomVisibility )
  271. {
  272. pViewRender->ViewDrawScene( bDrew3dSkybox, nSkyboxVisible, viewIn, nClearFlags, viewID, bDrawViewModel, baseDrawFlags, pCustomVisibility );
  273. }
  274. inline void CPortalRenderable::SetViewRecursionLevel( int iViewRecursionLevel )
  275. {
  276. g_pPortalRender->m_iViewRecursionLevel = iViewRecursionLevel;
  277. }
  278. inline void CPortalRenderable::SetRemainingViewDepth( int iRemainingViewDepth )
  279. {
  280. g_pPortalRender->m_iRemainingPortalViewDepth = iRemainingViewDepth;
  281. }
  282. inline void CPortalRenderable::SetViewEntranceAndExitPortals( CPortalRenderable *pEntryPortal, CPortalRenderable *pExitPortal )
  283. {
  284. g_pPortalRender->m_pRenderingViewForPortal = pEntryPortal;
  285. g_pPortalRender->m_pRenderingViewExitPortal = pExitPortal;
  286. }
  287. #endif //#ifndef PORTALRENDER_H