//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== // // The copyright to the contents herein is the property of Valve, L.L.C. // The contents may be used and/or copied only with the written permission of // Valve, L.L.C., or in accordance with the terms and conditions stipulated in // the agreement/contract under which the contents have been supplied. // // $Header: $ // $NoKeywords: $ // // Render system unit test //============================================================================= #include "rendersystemtest.h" #include "inputsystem/iinputsystem.h" #include "materialsystem2/imaterialsystem2.h" #include "worldrenderer/iworldrenderermgr.h" #include "meshsystem/imeshsystem.h" #include "filesystem.h" #include "vstdlib/jobthread.h" #include "particles/particles.h" #include "dynamicdrawhelper.h" #include "tier0/vprof.h" #include "keyvalues.h" #include "scenesystem/iscenesystem.h" #include "icommandline.h" #include "inputsystem/iinputstacksystem.h" struct usercmd_t { float m_flForwardMove; float m_flRightMove; float m_flYawMove; float m_flPitchMove; uint32 m_nKeys; }; struct BoxVertex_t { Vector m_vPos; }; #define FKEY_FORWARD 0x00000001 #define FKEY_BACK 0x00000002 #define FKEY_LEFT 0x00000004 #define FKEY_RIGHT 0x00000008 #define FKEY_TURNLEFT 0x00000010 #define FKEY_TURNRIGHT 0x00000020 #define FKEY_TURNUP 0x00000040 #define FKEY_TURNDOWN 0x00000080 #define FKEY_SHOOTDECAL 0x00000100 #define FKEY_SHOOTPSYSTEM 0x00000200 #define FKEY_SHOOTSSYSTEM 0x00000400 #define FKEY_LIGHTELV 0x00000800 #define FKEY_LIGHTANG_POS 0x00001000 #define FKEY_LIGHTANG_NEG 0x00002000 #define FKEY_FAST 0x00004000 #define FKEY_ENABLE_VIS 0x00008000 #define FKEY_DISABLE_VIS 0x00010000 #define FKEY_DROP_FRUSTUM 0x00020000 #define FKEY_TOGGLE_AERIAL 0x00040000 #define FKEY_TOGGLE_BOUNCE 0x00080000 #define FKEY_TOGGLE_DIRECT 0x00100000 #define FKEY_TOGGLE_LIGHTING_ONLY 0x00200000 #define FKEY_SSAO 0x00400000 #define FKEY_BLUR_LIGHTING 0x00800000 #define FKEY_BLUR_SHADOWS 0x01000000 #define FKEY_FLASHLIGHT 0x02000000 #define FKEY_SHOOTDECAL2 0x04000000 #define FKEY_SHOOTWALLMONSTER 0x08000000 #define NUM_SHADOW_SPLITS 3 #define NUM_MULTI_SHADOWS 20 #define NUM_HIGH_RES_SHADOWS 4 #define SQRT_NUM_HIGH_RES_SHADOWS 2 #define NUM_LOW_RES_SHADOWS 16 #define SQRT_NUM_LOW_RES_SHADOWS 4 #define MAX_LIGHT_DISTANCE 2000.0f #define MAX_MESH_SYSTEM_MODELS 5 char *g_pRenderableList[ MAX_MESH_SYSTEM_MODELS ] = { "models/w_minigun_reference.dmx", "models/pm_heavy_reference.dmx", "models/w_bonesaw_reference.dmx", "models/w_guitar_reference.dmx", "models/w_harpahorn.dmx", }; int g_nCurrentModel = 0; struct DecalVertex_t { Vector m_vPos; Vector m_vDecalOrigin; Vector m_vDecalRight; Vector4D m_vDecalUpAndInfluence; }; struct SphereVertex_t { Vector m_vPos; }; struct QuadVertex_t { Vector m_vPos; Vector m_vEyeRay; }; struct ViewRelatedConstants_t { VMatrix m_mViewProjection; Vector4D m_vEyePt; Vector4D m_vEyeDir; Vector4D m_flFarPlane; }; struct LightingConstants_t { Vector4D m_vLightDir; Vector4D m_vLightColor; VMatrix m_mShadowMatrices[NUM_SHADOW_SPLITS]; }; struct DeferredLightingConstants_t { Vector4D m_vLightDir; Vector4D m_vLightColor; Vector4D m_vInvScreenExtents; Vector4D m_vEyePt; VMatrix m_mInvViewProj; VMatrix m_mShadowMatrix[NUM_SHADOW_SPLITS]; }; struct AerialPerspectiveConstants_t { Vector4D m_vLightDir; Vector4D m_vLightColor; Vector4D m_vInvScreenExtents; Vector4D m_vBm; Vector4D m_flG; Vector4D m_vNearAndFar; Vector4D m_vEyePt; VMatrix m_mInvViewProj; }; struct DecalScreenData_t { Vector4D m_vInvScreenExtents; VMatrix m_mInvViewProj; Vector4D m_vEyePt; Vector4D m_vEyeDir; }; struct BlurParams_t { Vector4D m_flBlurFalloff; Vector4D m_flSharpness; Vector4D m_flFarPlane; }; #define NUM_SSAO_SAMPLES 16 struct SampleSphereData_t { VMatrix m_mViewProj; Vector4D m_vRandSampleScale; Vector4D m_vSampleRadiusNBias; Vector4D m_vSphereSamples[ NUM_SSAO_SAMPLES ]; }; struct LightBufferData_t { Vector4D m_vInvScreenExtents; }; struct SkyVSCB_t { VMatrix m_mViewProj; Vector4D m_vSkyScale; }; struct SkyPSCB_t { Vector4D m_vLightDir; Vector4D m_vEyePt; Vector4D m_vLightColor; Vector4D m_vBm; Vector4D m_flG; }; struct PerParticleData_t { Vector4D m_vPosRadius; Vector4D m_vColor; }; struct SimulateWorkUnitWorldRender_t { CParticleCollection *m_pParticles; int m_nNumSystems; float m_flTimeStep; }; const int g_nNothingRenderedStencilRef = 0; const int g_nCanSeeSkyStencilRef = 1; const int g_nCannotSeeSkyStencilRef = 2; // Globalizing these so we can render nodes in parallel class CWorldRendererTest; CWorldRendererTest *g_pWorldRendererTest = NULL; enum RenderViewFlags_t { VIEW_PLAYER_CAMERA = 0x00000001, VIEW_LIGHT_SHADOW = 0x00000002, VIEW_REFLECTION = 0x00000004, VIEW_MONITOR = 0x00000008, VIEW_POST_PROCESS = 0x00000010, VIEW_LIGHTING = 0x00000020, VIEW_DECALS = 0x00000040 }; enum RenderTargetType_t { DS_SHADOW_DEPTH0 = 0x0, DS_SHADOW_DEPTH1, DS_SHADOW_DEPTH2, DS_SHADOW_DEPTH_MULTIPLE, RT_SHADOW_MULTIPLE_0, RT_SHADOW_MULTIPLE_1, RT_SHADOW_BLUR_TEMP, DS_DEPTH_HIGHRES, RT_VIEW_DEPTH_HIGHRES, RT_VIEW_NORMAL_HIGHRES, RT_VIEW_SPEC_HIGHRES, RT_LIGHTING_HIGHRES, // Alpha contains occlusion RT_SPECULAR_HIGHRES, DS_DEPTH_LOWRES, RT_VIEW_DEPTH_LOWRES, RT_VIEW_NORMAL_LOWRES, RT_LIGHTING_LOWRES, RT_LIGHTING_TEMP_LOWRES, MAX_RENDER_TARGET_TYPES }; char *g_pRenderTargetName[] = { {"DS_SHADOW_DEPTH0"}, {"DS_SHADOW_DEPTH1"}, {"DS_SHADOW_DEPTH2"}, {"DS_SHADOW_DEPTH_MULTIPLE"}, {"RT_SHADOW_MULTIPLE_1"}, {"RT_SHADOW_MULTIPLE_2"}, {"RT_SHADOW_BLUR_TEMP"}, {"DS_DEPTH_HIGHRES"}, {"RT_VIEW_DEPTH_HIGHRES"}, {"RT_VIEW_NORMAL_HIGHRES"}, {"RT_VIEW_SPEC_HIGHRES"}, {"RT_LIGHTING_HIGHRES"}, {"RT_SPECULAR_HIGHRES"}, {"DS_DEPTH_LOWRES"}, {"RT_VIEW_DEPTH_LOWRES"}, {"RT_VIEW_NORMAL_LOWRES"}, {"RT_LIGHTING_LOWRES"}, {"RT_LIGHTING_TEMP_LOWRES"}, {"MAX_RENDER_TARGET_TYPES"} }; enum ViewBindingType_t { RTB_SHADOW_DEPTH0 = 0x0, RTB_SHADOW_DEPTH1, RTB_SHADOW_DEPTH2, RTB_SHADOW_DEPTH_MULTIPLE_0, RTB_SHADOW_DEPTH_MULTIPLE_1, RTB_SHADOW_DEPTH_MULTIPLE_2, RTB_SHADOW_DEPTH_MULTIPLE_3, RTB_SHADOW_DEPTH_MULTIPLE_4, RTB_SHADOW_DEPTH_MULTIPLE_5, RTB_SHADOW_DEPTH_MULTIPLE_6, RTB_SHADOW_DEPTH_MULTIPLE_7, RTB_SHADOW_DEPTH_MULTIPLE_8, RTB_SHADOW_DEPTH_MULTIPLE_9, RTB_SHADOW_DEPTH_MULTIPLE_10, RTB_SHADOW_DEPTH_MULTIPLE_11, RTB_SHADOW_DEPTH_MULTIPLE_12, RTB_SHADOW_DEPTH_MULTIPLE_13, RTB_SHADOW_DEPTH_MULTIPLE_14, RTB_SHADOW_DEPTH_MULTIPLE_15, RTB_SHADOW_DEPTH_MULTIPLE_16, RTB_SHADOW_DEPTH_MULTIPLE_17, RTB_SHADOW_DEPTH_MULTIPLE_18, RTB_SHADOW_DEPTH_MULTIPLE_19, RTB_SHADOW_DEPTH_MULTIPLE_20, RTB_SHADOW_DEPTH_MULTIPLE_21, RTB_SHADOW_DEPTH_MULTIPLE_22, RTB_SHADOW_DEPTH_MULTIPLE_23, RTB_SHADOW_DEPTH_MULTIPLE_24, RTB_SHADOW_DEPTH_MULTIPLE_25, RTB_SHADOW_DEPTH_MULTIPLE_26, RTB_SHADOW_DEPTH_MULTIPLE_27, RTB_SHADOW_DEPTH_MULTIPLE_28, RTB_SHADOW_DEPTH_MULTIPLE_29, RTB_SHADOW_DEPTH_MULTIPLE_30, RTB_SHADOW_DEPTH_MULTIPLE_31, RTB_DEFERRED_DEPTH_NORM_SPEC, RTB_DEFERRED_SCALE_DOWN, RTB_DEFERRED_NORM_SPEC, RTB_CLEAR_SPEC_HIGHRES, RTB_LIGHTING_HIGHRES, RTB_LIGHTING_LOWRES, RTB_SSAO_LOWRES, RTB_BILAT_UPSAMPLE_0, RTB_BILAT_UPSAMPLE_1, RTB_LIGHT_BLUR_0, RTB_LIGHT_BLUR_1, RTB_SHADOW_BLUR_0, RTB_SHADOW_BLUR_1, RTB_SHADOW_BLUR_2, RTB_SAMPLE_LIGHTING, RTB_AERIAL_PERSPECTIVE, RTB_SKY, RTB_FORWARD, MAX_VIEW_BINDING_TYPES }; ViewRelatedConstants_t CreateViewConstantsForFrustum( CWorldRenderFrustum* pFrustum ) { const Vector vEyePt = pFrustum->GetCameraPosition(); Vector vEyeDir = pFrustum->Forward(); float flFarPlane = pFrustum->GetFarPlane(); vEyeDir /= flFarPlane; ViewRelatedConstants_t viewConstants; viewConstants.m_mViewProjection = pFrustum->GetViewProj(); viewConstants.m_vEyePt.Init( vEyePt.x, vEyePt.y, vEyePt.z, 1 ); viewConstants.m_flFarPlane.Init( flFarPlane, flFarPlane, flFarPlane, 1 ); viewConstants.m_vEyeDir.Init( vEyeDir.x, vEyeDir.y, vEyeDir.z, 1 ); return viewConstants; } #define MAX_SIMUL_VIEWS 5 class CRenderView; class CStaticMeshRenderable { public: CStaticMeshRenderable() {} ~CStaticMeshRenderable() {} inline bool operator==( const CStaticMeshRenderable& src ) const { return src.m_pDrawCall == m_pDrawCall; } IBVHNode *m_pNode; CBVHDrawCall *m_pDrawCall; }; class CDynamicRenderable { public: CDynamicRenderable() {} ~CDynamicRenderable() {} inline bool operator==( const CDynamicRenderable &src ) const { return src.m_hRenderable == m_hRenderable; } HRenderableStrong m_hRenderable; VMatrix m_mWorld; Vector m_vOrigin; }; class CPointLightRenderable { public: CPointLightRenderable() {} ~CPointLightRenderable() {} inline bool operator==( const CPointLightRenderable& src ) const { return src.m_pLight == m_pLight; } PointLightData_t *m_pLight; Vector m_vOrigin; }; class CSpotLightRenderable { public: CSpotLightRenderable() {} ~CSpotLightRenderable() {} inline bool operator==( const CSpotLightRenderable& src ) const { return src.m_pLight == m_pLight; } SpotLightData_t *m_pLight; Vector m_vOrigin; float m_flSquaredDistToEye; bool m_bInterior; bool m_bValid; }; class CHemiLightRenderable { public: CHemiLightRenderable() {} ~CHemiLightRenderable() {} inline bool operator==( const CHemiLightRenderable& src ) const { return src.m_pLight == m_pLight; } HemiLightData_t *m_pLight; Vector m_vOrigin; }; struct RenderJob_t { CWorldRendererTest *m_pTestApp; CRenderView *m_pRenderView; int m_nStartStatic; int m_nCountStatic; int m_nStartDynamic; int m_nCountDynamic; int m_nIndex; }; class CRenderView { public: CRenderView() {} ~CRenderView() { g_pRenderDevice->DestroyRenderTargetBinding( m_hRenderTargetBinding ); } void Init( IRenderDevice* pRenderDevice, CWorldRenderFrustum *pFrustum, RenderTargetBinding_t hRenderTargetBinding, RenderViewport_t &viewport, RenderViewFlags_t nFlags, int nPass, int nViewType ) { g_pRenderDevice = pRenderDevice; m_pFrustum = pFrustum; m_hRenderTargetBinding = hRenderTargetBinding; m_viewport = viewport; m_nFlags = nFlags; m_nPass = nPass; m_nViewType = nViewType; m_bValid = true; } RenderTargetBinding_t GetRenderTargetBinding() { return m_hRenderTargetBinding; } RenderViewFlags_t GetViewFlags() { return m_nFlags; } int GetRenderPass() { return m_nPass; } int GetViewType() { return m_nViewType; } CWorldRenderFrustum *GetFrustum() { return m_pFrustum; } IRenderDevice *GetRenderDevice() { return g_pRenderDevice; } bool IsValid() { return m_bValid; } void SetValid( bool bValid ) { m_bValid = bValid; } void UpdateFrustum( CWorldRenderFrustum *pFrustum ) { m_pFrustum = pFrustum; } void Clear( IRenderContext *pRenderContext, Vector4D &vClearColor, int nFlags ) { Assert( pRenderContext ); BeginRender( pRenderContext ); pRenderContext->Clear( vClearColor, nFlags ); // don't call endrender because it clears the rendercontext and the renderable list pRenderContext->Submit(); } void BeginRender( IRenderContext *pRenderContext ) { pRenderContext->BindRenderTargets( m_hRenderTargetBinding ); pRenderContext->SetViewports( 1, &m_viewport ); } void EndRender( IRenderContext *pRenderContext, bool bClearList = true ) { if ( pRenderContext ) { pRenderContext->Submit(); } if ( bClearList ) { if ( m_renderableList.Count() > 0 ) { m_renderableList.SetCountNonDestructively( 0 ); } if ( m_dynList.Count() > 0 ) { m_dynList.SetCountNonDestructively( 0 ); } } } void AddStaticMeshRenderable( CStaticMeshRenderable *pRenderable ) { m_renderableList.AddToTail( pRenderable ); } void AddDynamicRenderable( CDynamicRenderable *pRenderable ) { m_dynList.AddToTail( pRenderable ); } bool HasRenderables() { return ( ( m_renderableList.Count() != 0 ) || ( m_dynList.Count() != 0 ) ); } CUtlVector< CStaticMeshRenderable* > &GetRenderableList() { return m_renderableList; } CUtlVector< CDynamicRenderable* > &GetDynamicList() { return m_dynList; } private: RenderTargetBinding_t m_hRenderTargetBinding; RenderViewport_t m_viewport; RenderViewFlags_t m_nFlags; int m_nPass; int m_nViewType; bool m_bValid; IRenderDevice *g_pRenderDevice; CWorldRenderFrustum *m_pFrustum; CUtlVector< CStaticMeshRenderable* > m_renderableList; CUtlVector< CDynamicRenderable* > m_dynList; }; float RPercent() { return float( rand() - (RAND_MAX/2) ) / (float)(RAND_MAX/2); } float RPercentABS() { return float( rand() ) / (float)(RAND_MAX); } //----------------------------------------------------------------------------- // Tests the world renderer //----------------------------------------------------------------------------- class CWorldRendererTest : public CRenderSystemBenchmarkTest { typedef CRenderSystemBenchmarkTest BaseClass; public: CWorldRendererTest( int nVariant ); virtual ~CWorldRendererTest( void ); virtual void RenderFrame( const RenderViewport_t &viewport, PlatWindow_t hWnd ); virtual void RenderFrame_Internal( const RenderViewport_t &viewport ); virtual void SimulateFrame( float flTimeStep ); virtual void GetDescription( char *pNameBufferOut, size_t nBufLen ); virtual bool ProcessUserInput( const InputEvent_t &ie ); virtual bool CanBeRun(); void RenderViewStatic( CRenderView *pRenderView, int nStart, int nCount, int nIndex ); void RenderViewDynamic( CRenderView *pRenderView, int nStart, int nCount, int nIndex ); void SetStateForRenderViewType( IRenderContext *pRenderContext, int nRenderView ); ConstantBufferHandle_t GetViewRelated() { return m_hViewRelated; } ConstantBufferHandle_t GetLightBufferRelated() { return m_hLightBufferData; } IResourceDictionary *GetResourceDictionary() { return m_pResourceDictionary; } RsDepthStencilStateHandle_t GetSetStencilDS() { return m_hSetStencilDS; } LightBufferData_t *GetLightBufferData() { return &m_lightBufferData; } private: void SetupMultiShadowMatrices( int nViewportStart, int nSqrtNumShadows, float flBias ); void SetupShadowMatrices(); void CullRenderablesAgainstView( CRenderView &renderView, CUtlVector &renderableList, CUtlVector &dynList ); void RenderView( CRenderView &renderView ); void UpdateShadowData(); void UpdateFlashlightData(); void UpdateViewModelData(); void UpdateDroppedRenderables( float flElapsedTime ); void GenerateRenderables( Vector &vCameraPos ); void GeneratePointLightRenderables( IBVHNode *pNode, Vector &vOrigin, CFrustum *pFrustum, Vector &vEye ); void GenerateSpotLightRenderables( IBVHNode *pNode, Vector &vOrigin, CFrustum *pFrustum, Vector &vEye ); void GenerateHemiLightRenderables( IBVHNode *pNode, Vector &vOrigin, CFrustum *pFrustum, Vector &vEye ); void BilateralUpsample(); void RenderSSAO(); void ScaleDepthAndNormalBuffers(); void RenderAerialPerspective(); void RenderSky(); void RenderShadowDepthBuffers( IRenderContext *pRenderContext ); void RenderSunShadowFrustums( IRenderContext *pRenderContext ); void RenderBouncedLight( IRenderContext *pRenderContext ); void RenderDirectLight( IRenderContext *pRenderContext ); void BlurLightBuffer( ); void BlurShadowBuffers( ); void RenderDecals( IRenderContext *pRenderContext, int nVariation ); void RenderDynamic( IRenderContext *pRenderContext, CDynamicRenderable *pRenderable, int nVariation, bool bSunDepth, bool bSetStencil ); void RenderParticleLights( IRenderContext *pRenderContext, CParticleCollection *pParticles, int nVariation, bool bSunDepth, bool bSetStencil ); void RenderScenePointLights( IRenderContext *pRenderContext, CUtlVector &lightVector, bool bInterior ); void RenderSceneHemiLights( IRenderContext *pRenderContext, CUtlVector &lightVector, bool bInterior ); void RenderSceneSpotLights( IRenderContext *pRenderContext, CUtlVector &lightVector, bool bInterior ); void RenderShadowedSpotLights( IRenderContext *pRenderContext, CUtlVector &lightVector ); void SimulateParticles( float flTimeStep ); void CalculateEyeRays( float flFarPlane ); void InitDeferredData( const RenderViewport_t &viewport ); void InitParticleData(); void InitRenderableData(); void UpdateFrustum( int nWidth, int nHeight ); void AddDecal( IRenderContext *pRenderContext, Vector &vHit, Vector &vDecalDir, float flDecalSizeU, float flDecalSizeV, float flDecalShift, float flDecalInfluenceLength, bool bPaint ); void AddWallMonster( IRenderContext *pRenderContext, Vector &vHit, Vector &vDecalDir, float flDecalSizeU, float flDecalSizeV, float flDecalShift, float flDecalInfluenceLength ); void DropRenderable(); void CreateSphere( int nTessellation ); void CreateHemi( int nTessellationRes ); void CreateCone( int nTessellation ); void RenderScreenQuad( IRenderContext *pRenderContext, Vector *pEyeRays, const char *pDebugName ); RenderShaderHandle_t GetVertexShader( char *pShaderName, IRenderDevice *pDevice, const char *pShaderVersion, const char *pDefineText = NULL ); RenderShaderHandle_t GetPixelShader( char *pShaderName, IRenderDevice *pDevice, const char *pShaderVersion, const char *pDefineText = NULL ); HRenderTexture CreateRenderTarget( RenderTargetType_t type, const RenderViewport_t &viewport ); RenderTargetBinding_t CreateRenderTargetBinding( ViewBindingType_t type, const RenderViewport_t &viewport ); void InitRenderTargetsAndViews( const RenderViewport_t &viewport ); CWorldRenderFrustum *m_pFrustum; CWorldRenderFrustum *m_pDropFrustum; Vector m_vCullPos; usercmd_t m_cmd; HRenderTextureStrong m_pRenderTargets[ MAX_RENDER_TARGET_TYPES ]; RenderTargetBinding_t m_pViewBindings[ MAX_VIEW_BINDING_TYPES ]; CRenderView m_pRenderViews[ MAX_VIEW_BINDING_TYPES ]; int m_nRenderThreads; RenderJob_t *m_pRenderJobs; // Resources ConstantBufferHandle_t m_hViewRelated; ConstantBufferHandle_t m_hSingleMatrixRelated; ConstantBufferHandle_t m_hLightingRelated; ConstantBufferHandle_t m_hDeferredLightingRelated; ConstantBufferHandle_t m_hLightBufferData; ConstantBufferHandle_t m_hDecalScreenData; ConstantBufferHandle_t m_hBlurParams; ConstantBufferHandle_t m_hSphereSampleData; CWorldRenderFrustum *m_pSplitFrustums[ NUM_SHADOW_SPLITS ]; VMatrix m_pShadowMatrices[ NUM_SHADOW_SPLITS ]; CWorldRenderFrustum *m_pMultiShadowFrustums[ NUM_MULTI_SHADOWS ]; VMatrix m_pMultiShadowMatrices[ NUM_MULTI_SHADOWS ]; LightingConstants_t m_forwardLightingData; DeferredLightingConstants_t m_deferredLightingData; BlurParams_t m_blurParams; LightBufferData_t m_lightBufferData; AerialPerspectiveConstants_t m_aerialPerspectiveData; SampleSphereData_t m_sphereSampleData; float m_flSampleRadius; // Render list and renderable lists CUtlVector m_renderList; CUtlVector m_renderableList; CUtlVector m_dynRenderableList; CUtlVector m_exteriorPointLights; CUtlVector m_interiorPointLights; CUtlVector m_exteriorSpotLights; CUtlVector m_interiorSpotLights; CUtlVector m_exteriorHemiLights; CUtlVector m_interiorHemiLights; CUtlVector m_shadowedSpotLights; SpotLightData_t m_flashlight; float m_flMaxLightEncompassingFarPlane; bool m_bEnableVis; bool m_bDropFrustum; bool m_bSSAO; bool m_bBlurLighting; bool m_bBlurShadows; bool m_bDrawAerialPerspective; bool m_bDrawBouncedLight; bool m_bDrawDirectLight; bool m_bLightingOnly; bool m_bFlashlight; bool m_bViewLowTexture; // Deferred resources bool m_bMultiThreaded; bool m_bDeferred; bool m_bDeferredInit; bool m_bRenderTargetsInit; RenderTargetType_t m_nViewBuffer; float m_flLowResBufferScale; RenderShaderHandle_t m_hCopyTexture[4]; RenderShaderHandle_t m_hBilateralBlur[4]; RenderShaderHandle_t m_hShadowBlur[4]; RenderInputLayout_t m_hQuadLayout; Vector m_vEyeRays[4]; Vector m_vEyeLocalRays[4]; int m_nRandTextureSize; HRenderTextureStrong m_hFlashlightCookie[2]; HRenderTextureStrong m_hRandomTexture; RenderShaderHandle_t m_hSSAOPS; RenderShaderHandle_t m_hAerialPerspectivePS[2]; ConstantBufferHandle_t m_hAerialPerspectivePSCB; RsBlendStateHandle_t m_hExtinctionBS; RsBlendStateHandle_t m_hInscatteringBS; RsBlendStateHandle_t m_hAdditiveBS; RsBlendStateHandle_t m_hWriteAlphaBS; RsBlendStateHandle_t m_hWriteAllBS; RsDepthStencilStateHandle_t m_hSetStencilDS; RsDepthStencilStateHandle_t m_hZWriteNoTestDS; RenderShaderHandle_t m_hShadowFrustumVS[3]; RenderShaderHandle_t m_hShadowFrustumPS[3]; int m_nSphereIndices; int m_nHemiIndices; int m_nConeIndices; HRenderBufferStrong m_hSphereVB; HRenderBufferStrong m_hSphereIB; HRenderBufferStrong m_hHemiVB; HRenderBufferStrong m_hHemiIB; HRenderBufferStrong m_hConeVB; HRenderBufferStrong m_hConeIB; RenderShaderHandle_t m_hSceneLightVS[3]; RenderShaderHandle_t m_hSceneLightPS[6]; RenderInputLayout_t m_hSceneLightLayout[3]; // Sky RenderInputLayout_t m_hSphereLayout; RenderShaderHandle_t m_hSkyVS; RenderShaderHandle_t m_hSkyPS; ConstantBufferHandle_t m_hSkyVSCB; ConstantBufferHandle_t m_hSkyPSCB; SkyPSCB_t m_skyData; Vector4D m_vRenderLightColor; bool m_bRenderSky; RsDepthStencilStateHandle_t m_hZTestAndStencilTestDS; RsDepthStencilStateHandle_t m_hStencilTestDS; // Decals RenderInputLayout_t m_hDecalLayout; HRenderBufferStrong m_hDecalVB; HRenderBufferStrong m_hDecalVB2; HRenderBufferStrong m_hDecalVB3; HRenderBufferStrong m_hDecalIB; RenderShaderHandle_t m_hDecalVS[2]; RenderShaderHandle_t m_hDecalPS[2]; HRenderTextureStrong m_hDecalAlbedo; HRenderTextureStrong m_hDecalAlbedo2; HRenderTextureStrong m_hDecalNormal; HRenderTextureStrong m_hDecalNormal2; HRenderTextureStrong m_hDecalNormal3[3]; DecalScreenData_t m_decalScreenData; DecalScreenData_t m_lowResScreenData; DecalScreenData_t m_shadowScreenData; DecalVertex_t *m_pDecalBackingStore; DecalVertex_t *m_pDecalBackingStore2; int m_nMaxDecals; bool m_bFullBuffer; bool m_bFullBuffer2; int m_nGlobalDecalPos; int m_nGlobalDecalPos2; int m_nGlobalDecalPos3; Vector m_vPreviousMonsterNormal; int m_nWallMonsterTexture; float m_flWallMonsterTimer; int m_nNumTriangles; // Particles CUtlVector m_lightSystemList; CUtlVector m_sphereSystemList; CUtlVector m_particleWorkUnits; RenderInputLayout_t m_hPointLightLayout; RenderShaderHandle_t m_hPointLightVS[5]; RenderShaderHandle_t m_hPointLightPS[5]; // Renderable test RenderShaderHandle_t m_hSimpleMeshVS[4]; RenderShaderHandle_t m_hSimpleMeshPS[4]; Vector m_vLightDir; Vector2D m_vLightAngleElevation; float m_flLightAngSpeed; float m_flLightElvSpeed; int m_nShadowSplits; RenderViewport_t m_shadowViewport; RenderViewport_t m_multiShadowViewport[ NUM_MULTI_SHADOWS ]; VMatrix m_splitScaleBiasMatrices[ NUM_SHADOW_SPLITS ]; VMatrix m_multiShadowScaleBiasMatrices[ NUM_MULTI_SHADOWS ]; int m_nCurrentFrameNumber; int m_nShadowSize; int m_nLastFrustumWidth; int m_nLastFrustumHeight; int m_nWindowCenterX; int m_nWindowCenterY; int m_nCursorDeltaX; int m_nCursorDeltaY; int m_nCursorDeltaResetX; int m_nCursorDeltaResetY; int m_nReportLevel; float m_flDecalCountdown; float m_flParticleCountdown; float m_flNearPlane; float m_flFarPlane; // WorldRenderer IWorldRendererMgr *m_pWorldRendererMgr; IWorldRenderer *m_pWorldRenderer; IResourceDictionary *m_pResourceDictionary; bool m_bWorldLoaded; }; DECLARE_TEST( CWorldRendererTest ); static void PerformStaticMeshWorkUnit( RenderJob_t & job ) { job.m_pTestApp->RenderViewStatic( job.m_pRenderView, job.m_nStartStatic, job.m_nCountStatic, job.m_nIndex ); job.m_pTestApp->RenderViewDynamic( job.m_pRenderView, job.m_nStartDynamic, job.m_nCountDynamic, job.m_nIndex ); } static int g_pBoxIndices[36] = { 2,1,0,3,2,0, 6,5,1,2,6,1, 7,4,5,6,7,5, 3,0,4,7,3,4, 6,2,3,7,6,3, 1,5,4,0,1,4 }; //----------------------------------------------------------------------------- // Constructor, destructor //----------------------------------------------------------------------------- CWorldRendererTest::CWorldRendererTest( int nVariant ) : BaseClass( nVariant ) { if ( !g_pWorldRendererMgr ) return; g_pWorldRendererTest = this; // Disable HW instancing on GL for now if ( g_nPlatform == RST_PLATFORM_GL ) g_pWorldRendererMgr->SetHWInstancingEnabled( false ); CRenderContextPtr pRenderContext( g_pRenderDevice ); m_flDecalCountdown = 0.0f; m_flParticleCountdown = 0.0f; if ( IsPlatformX360() ) { m_nShadowSize = 512; } else { m_nShadowSize = 1024; } m_shadowViewport.Init( 0, 0, m_nShadowSize, m_nShadowSize, 0, 1 ); SetupShadowMatrices(); m_nViewBuffer = RT_LIGHTING_HIGHRES; m_nRenderThreads = g_pThreadPool->NumThreads(); m_pRenderJobs = new RenderJob_t[ m_nRenderThreads ]; m_nCurrentFrameNumber = 0; m_hViewRelated = g_pRenderDevice->CreateConstantBuffer( sizeof( ViewRelatedConstants_t ) ); m_hSingleMatrixRelated = g_pRenderDevice->CreateConstantBuffer( sizeof( VMatrix ) ); m_hLightingRelated = g_pRenderDevice->CreateConstantBuffer( sizeof( LightingConstants_t ) ); m_hSkyVSCB = g_pRenderDevice->CreateConstantBuffer( sizeof( SkyVSCB_t ) ); m_hSkyPSCB = g_pRenderDevice->CreateConstantBuffer( sizeof( SkyPSCB_t ) ); //m_flLowResBufferScale = 0.5f; m_flLowResBufferScale = 0.5f; m_bEnableVis = true; m_bDropFrustum = false; m_bSSAO = true; m_bBlurLighting = false; m_bBlurShadows = true; m_bDrawAerialPerspective = true; m_bDrawBouncedLight = true; m_bDrawDirectLight = true; m_bLightingOnly = false; m_bFlashlight = false; m_bViewLowTexture = false; // Deferred m_bDeferred = true; m_bDeferredInit = false; m_bRenderTargetsInit = false; m_bMultiThreaded = true; // No deferred on GL yet if ( g_nPlatform == RST_PLATFORM_GL || g_nPlatform == RST_PLATFORM_X360 ) m_bDeferred = false; m_bWorldLoaded = true; // Create a world renderer m_pWorldRenderer = g_pWorldRendererMgr->CreateWorldRenderer(); // Load the world const char *pWorldName = CommandLine()->ParmValue( "-map", "maps/ep2_outland_10" ); if ( !m_pWorldRenderer->Unserialize( pWorldName ) ) { Error( "Cannot load world!\n" ); m_bWorldLoaded = false; return; } m_pResourceDictionary = m_pWorldRenderer->GetResourceDictionary(); // Initialization static const uint64 sMegabyte = 1024 * 1024; uint64 nMaxGPUMemory = 768 * sMegabyte; uint64 nMaxSysMemory = 512 * sMegabyte; if ( IsPlatformX360() ) { // Set this low until texture eviction works on the 360 nMaxGPUMemory = 256 * sMegabyte; nMaxSysMemory = 32 * sMegabyte; } m_pWorldRenderer->Initialize( g_pRenderDevice, nMaxGPUMemory, nMaxSysMemory ); // Alloc split frustums for ( int s=0; s playerstarts; m_pWorldRenderer->GetEntities( "info_player_start", playerstarts ); if ( playerstarts.Count() ) { const char *pEye = playerstarts[0]->GetString( "origin" ); const char *pAngles = playerstarts[0]->GetString( "angles" ); sscanf( pEye, "%f %f %f", &vEyePos.x, &vEyePos.y, &vEyePos.z ); sscanf( pAngles, "%f %f %f", &vAngles.x, &vAngles.y, &vAngles.z ); vEyePos.z += 64; } // eyepos, eyeangles, znear, zfar, fov, aspect ratio m_flNearPlane = 10.0f; m_flFarPlane = 18000.0f; m_pFrustum->InitCamera( vEyePos, vAngles, m_flNearPlane, m_flFarPlane, CalcFovX(flFOVY, flAspect), flAspect ); m_pFrustum->UpdateFrustumFromCamera(); // parallel spit shadow maps m_vLightAngleElevation.x = 120.0f; m_vLightAngleElevation.y = 70.0f; m_vLightDir = Vector(0,0,1); Q_memset( &m_skyData, 0, sizeof( SkyPSCB_t ) ); m_vRenderLightColor = Vector4D(1,1,1,1); m_flLightAngSpeed = 20.0f; m_flLightElvSpeed = 20.0f; m_nShadowSplits = NUM_SHADOW_SPLITS; const char *pVertexShaderVersion = g_pRenderDevice->GetShaderVersionString( RENDER_VERTEX_SHADER ); const char *pPixelShaderVersion = g_pRenderDevice->GetShaderVersionString( RENDER_PIXEL_SHADER ); // sphere and cone primitives CreateSphere( 10 ); CreateHemi( 10 ); CreateCone( 10 ); if ( m_bDeferred ) { // Decals m_nMaxDecals = 2000; m_bFullBuffer = false; m_nGlobalDecalPos = 0; m_bFullBuffer2 = false; m_nGlobalDecalPos2 = 0; m_nGlobalDecalPos3 = 0; m_vPreviousMonsterNormal.Init( 0, 0, 1 ); m_nWallMonsterTexture = 0; m_flWallMonsterTimer = 0.0f; static RenderInputLayoutField_t decalLayout[] = { DEFINE_PER_VERTEX_FIELD( 0, "position", 0, DecalVertex_t, m_vPos ) DEFINE_PER_VERTEX_FIELD( 0, "texcoord", 0, DecalVertex_t, m_vDecalOrigin ) DEFINE_PER_VERTEX_FIELD( 0, "texcoord", 1, DecalVertex_t, m_vDecalRight ) DEFINE_PER_VERTEX_FIELD( 0, "texcoord", 2, DecalVertex_t, m_vDecalUpAndInfluence ) }; m_hDecalLayout = g_pRenderDevice->CreateInputLayout( "decallayout", ARRAYSIZE( decalLayout ), decalLayout ); BufferDesc_t decalDesc; decalDesc.m_nElementCount = m_nMaxDecals * 8; decalDesc.m_nElementSizeInBytes = sizeof( DecalVertex_t ); decalDesc.m_pBudgetGroupName = "decals"; decalDesc.m_pDebugName = "decalVB"; m_hDecalVB = g_pRenderDevice->CreateVertexBuffer( RENDER_BUFFER_TYPE_SEMISTATIC, decalDesc ); decalDesc.m_pDebugName = "decalVB2"; m_hDecalVB2 = g_pRenderDevice->CreateVertexBuffer( RENDER_BUFFER_TYPE_SEMISTATIC, decalDesc ); decalDesc.m_nElementCount = 8; decalDesc.m_pDebugName = "decalVB3"; m_hDecalVB3 = g_pRenderDevice->CreateVertexBuffer( RENDER_BUFFER_TYPE_SEMISTATIC, decalDesc ); decalDesc.m_nElementCount = m_nMaxDecals * 36; decalDesc.m_nElementSizeInBytes = sizeof( uint16 ); decalDesc.m_pDebugName = "decalIB"; m_hDecalIB = g_pRenderDevice->CreateIndexBuffer( RENDER_BUFFER_TYPE_STATIC, decalDesc ); LockDesc_t lockDesc; pRenderContext->LockIndexBuffer( m_hDecalIB, m_nMaxDecals * 36 * sizeof( uint16 ), &lockDesc ); uint16 *pIndices = (uint16*)lockDesc.m_pMemory; int nOffset = 0; for ( int d=0; dUnlockIndexBuffer( m_hDecalIB, m_nMaxDecals * 36 * sizeof( uint16 ), &lockDesc ); m_hDecalVS[0] = GetVertexShader( "maps/decalsvs", g_pRenderDevice, pVertexShaderVersion, "#define SHADER_VARIATION 0\n" ); m_hDecalPS[0] = GetPixelShader( "maps/decalsps", g_pRenderDevice, pPixelShaderVersion, "#define SHADER_VARIATION 0\n" ); m_hDecalVS[1] = GetVertexShader( "maps/decalsvs", g_pRenderDevice, pVertexShaderVersion, "#define SHADER_VARIATION 1\n" ); m_hDecalPS[1] = GetPixelShader( "maps/decalsps", g_pRenderDevice, pPixelShaderVersion, "#define SHADER_VARIATION 1\n" ); m_hDecalScreenData = g_pRenderDevice->CreateConstantBuffer( sizeof( DecalScreenData_t ) ); m_hDecalAlbedo = RENDER_TEXTURE_HANDLE_INVALID;//g_pRenderDevice->FindOrCreateFileTexture( "maps/decaltest_albedo.vtf" ); //m_hDecalNormal = g_pRenderDevice->FindOrCreateFileTexture( "maps/decaltest_normal.vtf" ); m_hDecalNormal = g_pRenderDevice->FindOrCreateFileTexture( "materials/plastercrack.vtf" ); m_hDecalAlbedo2 = g_pRenderDevice->FindOrCreateFileTexture( "materials/paintdecal.vtf" ); m_hDecalNormal2 = g_pRenderDevice->FindOrCreateFileTexture( "materials/paintdecalnorm.vtf" ); m_hDecalNormal3[0] = g_pRenderDevice->FindOrCreateFileTexture( "materials/gearhead1.vtf" ); m_hDecalNormal3[1] = g_pRenderDevice->FindOrCreateFileTexture( "materials/gearhead2.vtf" ); m_hDecalNormal3[2] = g_pRenderDevice->FindOrCreateFileTexture( "materials/gearhead3.vtf" ); m_pDecalBackingStore = new DecalVertex_t[ m_nMaxDecals * 8 ]; m_pDecalBackingStore2 = new DecalVertex_t[ m_nMaxDecals * 8 ]; } m_bRenderSky = true; if ( m_bRenderSky ) { // Load shaders m_hSkyVS = GetVertexShader( "maps/skyvs", g_pRenderDevice, pVertexShaderVersion ); m_hSkyPS = GetPixelShader( "maps/skyps", g_pRenderDevice, pPixelShaderVersion ); } if ( m_bDeferred ) { // particle system InitParticleData(); } InitRenderableData(); // Input Q_memset( &m_cmd, 0, sizeof( usercmd_t ) ); m_nWindowCenterX = -1; m_nWindowCenterY = -1; m_nCursorDeltaX = 0; m_nCursorDeltaY = 0; m_nCursorDeltaResetX = 0; m_nCursorDeltaResetY = 0; m_nReportLevel = 0; g_pInputStackSystem->SetCursorVisible( GetInputContext(), false ); } CWorldRendererTest::~CWorldRendererTest( void ) { if ( !g_pWorldRendererMgr ) return; g_pInputStackSystem->SetCursorVisible( GetInputContext(), true ); g_pRenderDevice->DestroyConstantBuffer( m_hViewRelated ); g_pRenderDevice->DestroyConstantBuffer( m_hLightingRelated ); m_pWorldRenderer->DestroyResources( g_pRenderDevice ); g_pWorldRendererMgr->DestroyWorldRenderer( m_pWorldRenderer ); m_dynRenderableList.RemoveAll(); for ( int s=0; sCreateInputLayout( "quadlayout", ARRAYSIZE( quadLayout ), quadLayout ); // Constants m_hDeferredLightingRelated = g_pRenderDevice->CreateConstantBuffer( sizeof( DeferredLightingConstants_t ) ); m_hLightBufferData = g_pRenderDevice->CreateConstantBuffer( sizeof( LightBufferData_t ) ); const char *pVertexShaderVersion = g_pRenderDevice->GetShaderVersionString( RENDER_VERTEX_SHADER ); const char *pPixelShaderVersion = g_pRenderDevice->GetShaderVersionString( RENDER_PIXEL_SHADER ); // Shaders for low-res buffers //float flBlurFalloff = 0.0005f; float flBlurFalloff = 0.005f; float flSharpness = 1000.0f; m_blurParams.m_flBlurFalloff.Init( flBlurFalloff, flBlurFalloff, flBlurFalloff, flBlurFalloff ); m_blurParams.m_flSharpness.Init( flSharpness, flSharpness, flSharpness, flSharpness ); m_blurParams.m_flFarPlane.Init( 1, 1, 1, 1 ); m_hBlurParams = g_pRenderDevice->CreateConstantBuffer( sizeof( BlurParams_t ) ); m_hCopyTexture[0] = GetPixelShader( "maps/copytextureps", g_pRenderDevice, pPixelShaderVersion, "#define SINGLE_TARGET 0\n#define COPY_TARGET_W 0\n#define COMBINE_LIGHTING 0\n" ); m_hCopyTexture[1] = GetPixelShader( "maps/copytextureps", g_pRenderDevice, pPixelShaderVersion, "#define SINGLE_TARGET 1\n#define COPY_TARGET_W 0\n#define COMBINE_LIGHTING 0\n" ); m_hCopyTexture[2] = GetPixelShader( "maps/copytextureps", g_pRenderDevice, pPixelShaderVersion, "#define SINGLE_TARGET 1\n#define COPY_TARGET_W 1\n#define COMBINE_LIGHTING 0\n" ); m_hCopyTexture[3] = GetPixelShader( "maps/copytextureps", g_pRenderDevice, pPixelShaderVersion, "#define SINGLE_TARGET 1\n#define COPY_TARGET_W 0\n#define COMBINE_LIGHTING 1\n" ); m_hBilateralBlur[0] = GetPixelShader( "maps/bilateralblur", g_pRenderDevice, pPixelShaderVersion, "#define BILAT_BLUR 1\n#define HORZ_BLUR 1\n#define BLUR_RADIUS 8\n" ); m_hBilateralBlur[1] = GetPixelShader( "maps/bilateralblur", g_pRenderDevice, pPixelShaderVersion, "#define BILAT_BLUR 1\n#define HORZ_BLUR 0\n#define BLUR_RADIUS 8\n" ); m_hBilateralBlur[2] = GetPixelShader( "maps/bilateralblur", g_pRenderDevice, pPixelShaderVersion, "#define BILAT_BLUR 1\n#define HORZ_BLUR_FULL 1\n#define BLUR_RADIUS 6\n" ); m_hBilateralBlur[3] = GetPixelShader( "maps/bilateralblur", g_pRenderDevice, pPixelShaderVersion, "#define BILAT_BLUR 1\n#define HORZ_BLUR 0\n#define BLUR_RADIUS 6\n" ); m_hShadowBlur[0] = GetPixelShader( "maps/bilateralblur", g_pRenderDevice, pPixelShaderVersion, "#define BILAT_BLUR 0\n#define HORZ_BLUR_FULL 1\n#define BLUR_RADIUS 3\n" ); m_hShadowBlur[1] = GetPixelShader( "maps/bilateralblur", g_pRenderDevice, pPixelShaderVersion, "#define BILAT_BLUR 0\n#define HORZ_BLUR 0\n#define BLUR_RADIUS 3\n" ); m_hShadowBlur[2] = GetPixelShader( "maps/bilateralblur", g_pRenderDevice, pPixelShaderVersion, "#define BILAT_BLUR 0\n#define HORZ_BLUR_FULL 1\n#define BLUR_RADIUS 2\n" ); m_hShadowBlur[3] = GetPixelShader( "maps/bilateralblur", g_pRenderDevice, pPixelShaderVersion, "#define BILAT_BLUR 0\n#define HORZ_BLUR 0\n#define BLUR_RADIUS 2\n" ); // Shaders for deferred ligthing m_hShadowFrustumVS[0] = GetVertexShader( "maps/shadowfrustumvs", g_pRenderDevice, pVertexShaderVersion, "#define DISCARD_OUTSIDE 1\n#define ALL_FRUSTUMS 0\n" ); m_hShadowFrustumPS[0] = GetPixelShader( "maps/shadowfrustumps", g_pRenderDevice, pPixelShaderVersion, "#define DISCARD_OUTSIDE 1\n#define ALL_FRUSTUMS 0\n" ); m_hShadowFrustumVS[1] = GetVertexShader( "maps/shadowfrustumvs", g_pRenderDevice, pVertexShaderVersion, "#define ALL_FRUSTUMS 0\n" ); m_hShadowFrustumPS[1] = GetPixelShader( "maps/shadowfrustumps", g_pRenderDevice, pPixelShaderVersion, "#define ALL_FRUSTUMS 0\n" ); m_hShadowFrustumVS[2] = GetVertexShader( "maps/shadowfrustumvs", g_pRenderDevice, pVertexShaderVersion, "#define ALL_FRUSTUMS 1\n" ); m_hShadowFrustumPS[2] = GetPixelShader( "maps/shadowfrustumps", g_pRenderDevice, pPixelShaderVersion, "#define ALL_FRUSTUMS 1\n" ); // Scene light shaders m_hSceneLightVS[0] = GetVertexShader( "maps/scenelightvs", g_pRenderDevice, pVertexShaderVersion, "#define LIGHT_TYPE 0\n" ); m_hSceneLightVS[1] = GetVertexShader( "maps/scenelightvs", g_pRenderDevice, pVertexShaderVersion, "#define LIGHT_TYPE 1\n" ); m_hSceneLightVS[2] = GetVertexShader( "maps/scenelightvs", g_pRenderDevice, pVertexShaderVersion, "#define LIGHT_TYPE 2\n" ); m_hSceneLightPS[0] = GetPixelShader( "maps/scenelightps", g_pRenderDevice, pPixelShaderVersion, "#define LIGHT_TYPE 0\n#define LIGHT_SHADOWED 0\n" ); m_hSceneLightPS[1] = GetPixelShader( "maps/scenelightps", g_pRenderDevice, pPixelShaderVersion, "#define LIGHT_TYPE 1\n#define LIGHT_SHADOWED 0\n" ); m_hSceneLightPS[2] = GetPixelShader( "maps/scenelightps", g_pRenderDevice, pPixelShaderVersion, "#define LIGHT_TYPE 2\n#define LIGHT_SHADOWED 0\n" ); m_hSceneLightPS[3] = GetPixelShader( "maps/scenelightps", g_pRenderDevice, pPixelShaderVersion, "#define LIGHT_TYPE 0\n#define LIGHT_SHADOWED 1\n" ); m_hSceneLightPS[4] = GetPixelShader( "maps/scenelightps", g_pRenderDevice, pPixelShaderVersion, "#define LIGHT_TYPE 1\n#define LIGHT_SHADOWED 1\n" ); m_hSceneLightPS[5] = GetPixelShader( "maps/scenelightps", g_pRenderDevice, pPixelShaderVersion, "#define LIGHT_TYPE 2\n#define LIGHT_SHADOWED 1\n" ); static RenderInputLayoutField_t pointLightLayout[] = { DEFINE_PER_VERTEX_FIELD( 0, "position", 0, SphereVertex_t, m_vPos ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 0, PointLightData_t, m_vOrigin ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 1, PointLightData_t, m_vColorNRadius ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 2, PointLightData_t, m_vAttenuation ) }; static RenderInputLayoutField_t hemiLightLayout[] = { DEFINE_PER_VERTEX_FIELD( 0, "position", 0, SphereVertex_t, m_vPos ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 0, HemiLightData_t, m_vTransform0 ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 1, HemiLightData_t, m_vTransform1 ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 2, HemiLightData_t, m_vTransform2 ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 3, HemiLightData_t, m_vColorNRadius ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 4, HemiLightData_t, m_vAttenuation ) }; static RenderInputLayoutField_t spotLightLayout[] = { DEFINE_PER_VERTEX_FIELD( 0, "position", 0, SphereVertex_t, m_vPos ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 0, SpotLightData_t, m_vTransform0 ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 1, SpotLightData_t, m_vTransform1 ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 2, SpotLightData_t, m_vTransform2 ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 3, SpotLightData_t, m_vColorNRadius ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 4, SpotLightData_t, m_vAttenuationNCosSpot ) }; m_hSceneLightLayout[0] = g_pRenderDevice->CreateInputLayout( "scenelight_point", ARRAYSIZE( pointLightLayout ), pointLightLayout ); m_hSceneLightLayout[1] = g_pRenderDevice->CreateInputLayout( "scenelight_hemi", ARRAYSIZE( hemiLightLayout ), hemiLightLayout ); m_hSceneLightLayout[2] = g_pRenderDevice->CreateInputLayout( "scenelight_spot", ARRAYSIZE( spotLightLayout ), spotLightLayout ); m_hFlashlightCookie[0] = g_pRenderDevice->FindOrCreateFileTexture( "materials/flashlight4.vtf" ); m_hFlashlightCookie[1] = g_pRenderDevice->FindOrCreateFileTexture( "materials/flashlight16.vtf" ); // SSAO m_hSSAOPS = GetPixelShader( "maps/ssao", g_pRenderDevice, pPixelShaderVersion ); CUniformSampler ssaoSampler; ssaoSampler.InitSamples( (int)sqrtf( (float)NUM_SSAO_SAMPLES ), 1 ); m_hSphereSampleData = g_pRenderDevice->CreateConstantBuffer( sizeof( SampleSphereData_t ) ); m_flSampleRadius = 16.0f; m_sphereSampleData.m_vRandSampleScale.Init( 1, 1, 1, 1 ); m_sphereSampleData.m_vSampleRadiusNBias.Init( m_flSampleRadius, m_flSampleRadius, m_flSampleRadius, m_flSampleRadius ); for ( int s=0; sSetConstantBufferData( m_hSphereSampleData, &m_sphereSampleData, sizeof( SampleSphereData_t ) ); #if 1 // random texture m_nRandTextureSize = 4; CUniformSampler randTexSampler; randTexSampler.InitSamples( m_nRandTextureSize, 1 ); TextureHeader_t randSpec; memset( &randSpec, 0, sizeof(TextureHeader_t) ); randSpec.m_nWidth = m_nRandTextureSize; randSpec.m_nHeight = m_nRandTextureSize; randSpec.m_nNumMipLevels = 1; randSpec.m_nDepth = 1; randSpec.m_nFlags = TSPEC_UNFILTERABLE_OK; randSpec.m_nImageFormat = IMAGE_FORMAT_BGRA8888; if ( g_nPlatform == RST_PLATFORM_DX11 ) { randSpec.m_nImageFormat = IMAGE_FORMAT_RGBA8888; } m_hRandomTexture = g_pRenderDevice->FindOrCreateTexture( "worldrenderertest", "randomtexture", &randSpec ); int nTotalRands = randSpec.m_nWidth * randSpec.m_nHeight; uint8 *pRandBits = new uint8[ nTotalRands * 4 ]; for ( int r=0; rSetTextureData( m_hRandomTexture, &randSpec, pRandBits, nTotalRands * 4, false ); delete []pRandBits; #else // random texture m_nRandTextureSize = 32; m_hRandomTexture = g_pRenderDevice->FindOrCreateFileTexture( "materials/SSAOReflectionVectors.vtf" ); #endif // Aerial perspective m_hAerialPerspectivePS[0] = GetPixelShader( "maps/aerialperspectiveps", g_pRenderDevice, pPixelShaderVersion, "#define SHADER_VARIATION 0\n" ); m_hAerialPerspectivePS[1] = GetPixelShader( "maps/aerialperspectiveps", g_pRenderDevice, pPixelShaderVersion, "#define SHADER_VARIATION 1\n" ); m_hAerialPerspectivePSCB = g_pRenderDevice->CreateConstantBuffer( sizeof( AerialPerspectiveConstants_t ) ); // states for aerial perspective RsBlendStateDesc_t bd; memset( &bd, 0, sizeof( bd ) ); bd.m_bAlphaToCoverageEnable = false; bd.m_bIndependentBlendEnable = false; for ( int i=0; i<4; ++i ) { bd.m_bBlendEnable[i] = true; bd.m_srcBlend[i] = RS_BLEND_MODE_ZERO; bd.m_destBlend[i] = RS_BLEND_MODE_SRC_COLOR; bd.m_blendOp[i] = RS_BLEND_OP_ADD; bd.m_nRenderTargetWriteMask[i] = RS_COLOR_WRITE_ENABLE_R | RS_COLOR_WRITE_ENABLE_G | RS_COLOR_WRITE_ENABLE_B; } m_hExtinctionBS = pRenderContext->FindOrCreateBlendState( &bd ); for ( int i=0; i<4; ++i ) { bd.m_srcBlend[i] = RS_BLEND_MODE_ONE; bd.m_destBlend[i] = RS_BLEND_MODE_ONE; } m_hInscatteringBS = pRenderContext->FindOrCreateBlendState( &bd ); m_hAdditiveBS = pRenderContext->FindOrCreateBlendState( &bd ); for ( int i=0; i<4; ++i ) { bd.m_bBlendEnable[i] = false; bd.m_srcBlend[i] = RS_BLEND_MODE_ZERO; bd.m_destBlend[i] = RS_BLEND_MODE_SRC_COLOR; bd.m_blendOp[i] = RS_BLEND_OP_ADD; bd.m_nRenderTargetWriteMask[i] = RS_COLOR_WRITE_ENABLE_A; } m_hWriteAlphaBS = pRenderContext->FindOrCreateBlendState( &bd ); for ( int i=0; i<4; ++i ) { bd.m_bBlendEnable[i] = false; bd.m_srcBlend[i] = RS_BLEND_MODE_ZERO; bd.m_destBlend[i] = RS_BLEND_MODE_SRC_COLOR; bd.m_blendOp[i] = RS_BLEND_OP_ADD; bd.m_nRenderTargetWriteMask[i] = RS_COLOR_WRITE_ENABLE_ALL; } m_hWriteAllBS = pRenderContext->FindOrCreateBlendState( &bd ); RsDepthStencilStateDesc_t dsDesc; dsDesc.m_bDepthTestEnable = true; dsDesc.m_bDepthWriteEnable = false; dsDesc.m_depthFunc = RS_CMP_LESS_EQUAL; dsDesc.m_hiZEnable360 = RS_HI_Z_AUTOMATIC; dsDesc.m_hiZWriteEnable360 = RS_HI_Z_AUTOMATIC; dsDesc.m_bStencilEnable = true; dsDesc.m_nStencilReadMask = 0xFF; dsDesc.m_nStencilWriteMask = 0xFF; dsDesc.m_frontStencilFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_frontStencilDepthFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_frontStencilPassOp = RS_STENCIL_OP_KEEP; dsDesc.m_frontStencilFunc = RS_CMP_EQUAL; dsDesc.m_backStencilFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_backStencilDepthFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_backStencilPassOp = RS_STENCIL_OP_KEEP; dsDesc.m_backStencilFunc = RS_CMP_EQUAL; dsDesc.m_bHiStencilEnable360 = false; dsDesc.m_bHiStencilWriteEnable360 = false; dsDesc.m_hiStencilFunc360 = RS_HI_STENCIL_CMP_EQUAL; dsDesc.m_nHiStencilRef360 = 0; m_hZTestAndStencilTestDS = pRenderContext->FindOrCreateDepthStencilState( &dsDesc ); dsDesc.m_bDepthTestEnable = false; dsDesc.m_bDepthWriteEnable = false; m_hStencilTestDS = pRenderContext->FindOrCreateDepthStencilState( &dsDesc ); dsDesc.m_bDepthTestEnable = true; dsDesc.m_bDepthWriteEnable = true; dsDesc.m_frontStencilFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_frontStencilDepthFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_frontStencilPassOp = RS_STENCIL_OP_REPLACE; dsDesc.m_frontStencilFunc = RS_CMP_ALWAYS; dsDesc.m_backStencilFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_backStencilDepthFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_backStencilPassOp = RS_STENCIL_OP_REPLACE; dsDesc.m_backStencilFunc = RS_CMP_ALWAYS; m_hSetStencilDS = pRenderContext->FindOrCreateDepthStencilState( &dsDesc ); // dsDesc.m_bDepthTestEnable = true; dsDesc.m_bDepthWriteEnable = true; dsDesc.m_depthFunc = RS_CMP_ALWAYS; dsDesc.m_hiZEnable360 = RS_HI_Z_AUTOMATIC; dsDesc.m_hiZWriteEnable360 = RS_HI_Z_AUTOMATIC; dsDesc.m_bStencilEnable = false; dsDesc.m_nStencilReadMask = 0xFF; dsDesc.m_nStencilWriteMask = 0xFF; dsDesc.m_frontStencilFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_frontStencilDepthFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_frontStencilPassOp = RS_STENCIL_OP_KEEP; dsDesc.m_frontStencilFunc = RS_CMP_EQUAL; dsDesc.m_backStencilFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_backStencilDepthFailOp = RS_STENCIL_OP_KEEP; dsDesc.m_backStencilPassOp = RS_STENCIL_OP_KEEP; dsDesc.m_backStencilFunc = RS_CMP_EQUAL; dsDesc.m_bHiStencilEnable360 = false; dsDesc.m_bHiStencilWriteEnable360 = false; m_hZWriteNoTestDS = pRenderContext->FindOrCreateDepthStencilState( &dsDesc ); m_bDeferredInit = true; } void CWorldRendererTest::InitParticleData() { CRenderContextPtr pRenderContext( g_pRenderDevice ); struct ParticleVertex_t { Vector m_vPos; }; static RenderInputLayoutField_t pointLightLayout[] = { DEFINE_PER_VERTEX_FIELD( 0, "position", 0, ParticleVertex_t, m_vPos ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 0, PerParticleData_t, m_vPosRadius ) DEFINE_PER_INSTANCE_FIELD( 1, 1, "texcoord", 1, PerParticleData_t, m_vColor ) }; m_hPointLightLayout = g_pRenderDevice->CreateInputLayout( "pointlight", ARRAYSIZE( pointLightLayout ), pointLightLayout ); const char *pVertexShaderVersion = g_pRenderDevice->GetShaderVersionString( RENDER_VERTEX_SHADER); const char *pPixelShaderVersion = g_pRenderDevice->GetShaderVersionString( RENDER_PIXEL_SHADER ); for ( int i=0; i<5; ++i ) { char pBuffer[100]; Q_snprintf( pBuffer, 100, "#define SHADER_VARIATION %d\n", i ); m_hPointLightVS[i] = GetVertexShader( "maps/pointlightvs", g_pRenderDevice, pVertexShaderVersion, pBuffer ); m_hPointLightPS[i] = GetPixelShader( "maps/pointlightps", g_pRenderDevice, pPixelShaderVersion, pBuffer ); } } void CWorldRendererTest::InitRenderableData() { CRenderContextPtr pRenderContext( g_pRenderDevice ); // Load the simple shaders for dynamic renderables const char *pVertexShaderVersion = g_pRenderDevice->GetShaderVersionString( RENDER_VERTEX_SHADER); const char *pPixelShaderVersion = g_pRenderDevice->GetShaderVersionString( RENDER_PIXEL_SHADER ); for ( int i=0; i<4; ++i ) { char pBuffer[100]; Q_snprintf( pBuffer, 100, "#define SHADER_VARIATION %d\n#define g_flPhongExp 10\n#define g_flPhongBoost 1.5\n", i ); m_hSimpleMeshVS[i] = GetVertexShader( "maps/meshsimplevs", g_pRenderDevice, pVertexShaderVersion, pBuffer ); m_hSimpleMeshPS[i] = GetPixelShader( "maps/meshsimpleps", g_pRenderDevice, pPixelShaderVersion, pBuffer ); } // Load the minigun HRenderable hRenderable = g_pMeshSystem->FindOrCreateFileRenderable( g_pRenderableList[ 0 ] ); int index = m_dynRenderableList.AddToTail(); m_dynRenderableList[ index ].m_hRenderable = hRenderable; m_dynRenderableList[ index ].m_vOrigin.Init( 0, 0, 0 ); m_dynRenderableList[ index ].m_mWorld.Identity(); } void CWorldRendererTest::UpdateFrustum( int nWidth, int nHeight ) { // Build up a frustum if ( nWidth == m_nLastFrustumWidth && nHeight == m_nLastFrustumHeight ) return; m_nLastFrustumWidth = nWidth; m_nLastFrustumHeight = nHeight; float flAspect = nWidth / (float)nHeight; m_pFrustum->SetAspect( flAspect ); m_pFrustum->SetFOV( CalcFovX(90.0f, flAspect) ); m_pFrustum->UpdateFrustumFromCamera(); } void CWorldRendererTest::RenderScreenQuad( IRenderContext *pRenderContext, Vector *pEyeRays, const char *pDebugName ) { CDynamicVertexData vb( pRenderContext, 4, pDebugName, "screenquad" ); vb.Lock( ); vb->m_vPos = Vector( -1, -1, 0.5f ); vb->m_vEyeRay = pEyeRays[0]; vb.AdvanceVertex(); vb->m_vPos = Vector( 1, -1, 0.5f ); vb->m_vEyeRay = pEyeRays[1]; vb.AdvanceVertex(); vb->m_vPos = Vector( -1, 1, 0.5f ); vb->m_vEyeRay = pEyeRays[2]; vb.AdvanceVertex(); vb->m_vPos = Vector( 1, 1, 0.5f ); vb->m_vEyeRay = pEyeRays[3]; vb.AdvanceVertex(); vb.Unlock(); vb.Bind( 0, 0 ); pRenderContext->Draw( RENDER_PRIM_TRIANGLE_STRIP, 0, 4 ); } void CWorldRendererTest::RenderFrame( const RenderViewport_t &viewport, PlatWindow_t hWnd ) { if ( !m_bRenderTargetsInit ) { InitRenderTargetsAndViews( viewport ); } if ( !m_bDeferredInit ) { InitDeferredData( viewport ); } if ( m_nReportLevel == 1 ) { g_VProfCurrentProfile.Reset(); g_VProfCurrentProfile.ResetPeaks(); g_VProfCurrentProfile.Start(); m_nReportLevel++; Msg("VPROF Trace Begin\n"); } RenderFrame_Internal( viewport ); if ( m_nReportLevel == 3 ) { g_VProfCurrentProfile.Stop(); g_VProfCurrentProfile.OutputReport( VPRT_FULL & ~VPRT_HIERARCHY, NULL ); Msg("VPROF Trace Complete\n"); m_nReportLevel = 0; } else if ( m_nReportLevel ) { g_VProfCurrentProfile.MarkFrame(); } } void CWorldRendererTest::CullRenderablesAgainstView( CRenderView &renderView, CUtlVector &renderableList, CUtlVector &dynList ) { if ( !renderView.IsValid() ) return; RenderViewFlags_t nFlags = renderView.GetViewFlags(); if ( !( nFlags & ( VIEW_PLAYER_CAMERA | VIEW_LIGHT_SHADOW | VIEW_REFLECTION ) ) ) return; if ( nFlags & ( VIEW_POST_PROCESS | VIEW_LIGHTING | VIEW_DECALS ) ) return; CWorldRenderFrustum *pFrustum = renderView.GetFrustum(); if( !pFrustum ) return; if ( m_bDropFrustum && pFrustum == m_pFrustum ) pFrustum = m_pDropFrustum; // Static int nRenderables = renderableList.Count(); for ( int r=0; rGetOrigin().m_vLocal; CBVHDrawCall *pDraw = renderable.m_pDrawCall; if ( pDraw->m_Flags & DRAW_CULL ) { if ( !pFrustum->BoundingVolumeIntersectsFrustum( pDraw->m_Bounds, vOriginShift ) ) { continue; } } // Add a renderable renderView.AddStaticMeshRenderable( &renderable ); } // Dynamic nRenderables = dynList.Count(); for ( int r=0; rRenderableIntersectsFrustum( renderable.m_hRenderable, pFrustum, -renderable.m_vOrigin ) ) continue; // Add a renderable renderView.AddDynamicRenderable( &renderable ); } } void CWorldRendererTest::SetupMultiShadowMatrices( int nViewportStart, int nSqrtNumShadows, float flBias ) { int nGutterSize = 4; if ( nViewportStart > 0 ) nGutterSize = 2; float flScale = ( 0.5f / nSqrtNumShadows ) - ( nGutterSize / (float)m_nShadowSize ); int nMultiShadowSize = m_nShadowSize / nSqrtNumShadows; int nTop = 0; int nViewport = nViewportStart; float frange = 1.0f; if ( IsPlatformX360() ) { frange = -1.0f; flBias = flBias * frange; } for ( int t=0; tm_flSquaredDistToEye < pTwo->m_flSquaredDistToEye ) return -1; else if ( pOne->m_flSquaredDistToEye > pTwo->m_flSquaredDistToEye ) return 1; return 0; } void CWorldRendererTest::GenerateRenderables( Vector &vCameraPos ) { // Figure out where we are and if we're interior or not int nLeafNode = m_pWorldRenderer->GetLeafNodeForPoint( vCameraPos ); bool bCanSeeSky = true; if ( nLeafNode != -1 ) { IBVHNode *pNode = m_pWorldRenderer->GetNode( nLeafNode ); int nFlags = pNode->GetFlags(); bCanSeeSky = ( nFlags & NODE_CAN_SEE_SKY ) != 0; } // Clear renderables m_renderList.SetCountNonDestructively( 0 ); m_renderableList.SetCountNonDestructively( 0 ); m_interiorPointLights.SetCountNonDestructively( 0 ); m_exteriorPointLights.SetCountNonDestructively( 0 ); m_interiorSpotLights.SetCountNonDestructively( 0 ); m_exteriorSpotLights.SetCountNonDestructively( 0 ); m_interiorHemiLights.SetCountNonDestructively( 0 ); m_exteriorHemiLights.SetCountNonDestructively( 0 ); m_shadowedSpotLights.SetCountNonDestructively( 0 ); // Clear far plane m_flMaxLightEncompassingFarPlane = 0.0f; // Build the render list for this view BVHNodeFlags_t nSkipFlags = (BVHNodeFlags_t)0x0; if ( bCanSeeSky == false ) nSkipFlags = NODE_CAN_SEE_SKY; float flLODScale = 1.0f; if ( IsPlatformX360() ) { flLODScale = 0.5f; } float flElapsedTime = 0.0f; m_pWorldRenderer->BuildRenderList( &m_renderList, nSkipFlags, vCameraPos, flLODScale, m_pFrustum->GetFarPlane(), flElapsedTime, m_nCurrentFrameNumber ); // Distance sort render traversals m_pWorldRenderer->SortRenderList( &m_renderList, vCameraPos ); //Create node requests and dispatch them to the async filesystem // This can cause eviction of resources. m_pWorldRenderer->CreateAndDispatchLoadRequests( g_pRenderDevice, m_pFrustum->GetCameraPosition() ); // Create renderables from each draw call encountered int nNodes = m_renderList.Count(); for ( int n=0; nGetOrigin().m_vLocal; // Gross cull of the bounds before turning them into renderables AABB_t bounds = pNode->GetBounds(); if ( !m_pFrustum->BoundingVolumeIntersectsFrustum( bounds, vOriginShift ) ) continue; // Draw calls int nDraws = pNode->GetNumDrawCalls(); for ( int d=0; dGetDrawCall( d ); CStaticMeshRenderable renderable; renderable.m_pNode = pNode; renderable.m_pDrawCall = &draw; m_renderableList.AddToTail( renderable ); } // Point Lights GeneratePointLightRenderables( pNode, vOriginShift, m_pFrustum, vCameraPos ); // Spot lights GenerateSpotLightRenderables( pNode, vOriginShift, m_pFrustum, vCameraPos ); // Hemi lights GenerateHemiLightRenderables( pNode, vOriginShift, m_pFrustum, vCameraPos ); } if ( m_bFlashlight ) { CSpotLightRenderable renderable; renderable.m_vOrigin.Init( 0, 0, 0 ); renderable.m_pLight = &m_flashlight; renderable.m_bValid = true; renderable.m_flSquaredDistToEye = 0.0f; // We're outside the light renderable.m_bInterior = false; m_shadowedSpotLights.AddToTail( renderable ); } // We've been storing squared distance, but we want linear distance m_flMaxLightEncompassingFarPlane = sqrtf( m_flMaxLightEncompassingFarPlane ); // Sort spot lights and set the NUM_MULTI_SHADOWS closest as shadow casting m_shadowedSpotLights.Sort( SortSpotLights ); /* // Artificially limit shadows past a certain point int nShadows = 0; for ( int s=0; s MAX_LIGHT_DISTANCE * MAX_LIGHT_DISTANCE ) { break; } nShadows++; }*/ int nShadows = m_shadowedSpotLights.Count(); nShadows = MIN( nShadows, NUM_MULTI_SHADOWS ); m_shadowedSpotLights.SetCountNonDestructively( nShadows ); for ( int s=0; sGetNearPlane(); int nLights = pNode->GetNumPointLights(); PointLightData_t *pPointLights = pNode->GetPointLights(); for ( int i=0; iBoundingVolumeIntersectsFrustum( bounds, vOrigin ) ) { CPointLightRenderable renderable; renderable.m_vOrigin = vOrigin; renderable.m_pLight = &pPointLights[i]; Vector vNewOrigin = vLightOrigin - vOrigin; Vector vDelta = vEye - vNewOrigin; float flSquaredDist = DotProduct( vDelta, vDelta ); float flTargetRad = flRadius * 1.2f + flNearPlane; if ( DotProduct( vDelta, vDelta ) < flTargetRad * flTargetRad ) { // We're inside the light m_interiorPointLights.AddToTail( renderable ); } else { // We're outside the light m_exteriorPointLights.AddToTail( renderable ); } m_flMaxLightEncompassingFarPlane = MAX( m_flMaxLightEncompassingFarPlane, flSquaredDist + flTargetRad * flTargetRad ); } } } void CWorldRendererTest::GenerateSpotLightRenderables( IBVHNode *pNode, Vector &vOrigin, CFrustum *pFrustum, Vector &vEye ) { float flNearPlane = pFrustum->GetNearPlane(); Vector vForward = pFrustum->Forward(); Vector vFarEye = vEye + flNearPlane * vForward * 1.2f; int nLights = pNode->GetNumSpotLights(); SpotLightData_t *pSpotLights = pNode->GetSpotLights(); for ( int i=0; iBoundingVolumeIntersectsFrustum( bounds, vOrigin ) ) { CSpotLightRenderable renderable; renderable.m_vOrigin = vOrigin; renderable.m_pLight = &pSpotLights[i]; renderable.m_bValid = true; Vector vNewOrigin = vLightOrigin - vOrigin; Vector vDelta = vEye - vNewOrigin; Vector vLightDir = Vector( pSpotLights[i].m_vTransform0.z, pSpotLights[i].m_vTransform1.z, pSpotLights[i].m_vTransform2.z ); float flSquaredDist = DotProduct( vDelta, vDelta ); renderable.m_flSquaredDistToEye = flSquaredDist; //if ( flRadius > 3000.0f ) // renderable.m_flSquaredDistToEye = FLT_MAX; Vector vToLightFar = vFarEye - vNewOrigin; Vector vToLightNear = vEye - vNewOrigin; vToLightFar.NormalizeInPlace(); vToLightNear.NormalizeInPlace(); float flDotFar = DotProduct( vToLightFar, vLightDir ); float flDotNear = DotProduct( vToLightNear, vLightDir ); float flCosAngle = pSpotLights[i].m_vAttenuationNCosSpot.w * 0.85f; bool bInCone = ( flDotFar > flCosAngle || flDotNear > flCosAngle ); if ( flSquaredDist < flTargetRad * flTargetRad && bInCone ) { // We're inside the light renderable.m_bInterior = true; m_interiorSpotLights.AddToTail( renderable ); } else { // We're outside the light renderable.m_bInterior = false; m_exteriorSpotLights.AddToTail( renderable ); } m_shadowedSpotLights.AddToTail( renderable ); m_flMaxLightEncompassingFarPlane = MAX( m_flMaxLightEncompassingFarPlane, flSquaredDist + flTargetRad * flTargetRad + 4000 * 4000 ); } } } void CWorldRendererTest::GenerateHemiLightRenderables( IBVHNode *pNode, Vector &vOrigin, CFrustum *pFrustum, Vector &vEye ) { float flNearPlane = pFrustum->GetNearPlane(); Vector vForward = pFrustum->Forward(); Vector vFarEye = vEye + flNearPlane * vForward * 1.1f; int nLights = pNode->GetNumHemiLights(); HemiLightData_t *pHemiLights = pNode->GetHemiLights(); for ( int i=0; iBoundingVolumeIntersectsFrustum( bounds, vOrigin ) ) { CHemiLightRenderable renderable; renderable.m_vOrigin = vOrigin; renderable.m_pLight = &pHemiLights[i]; Vector vNewOrigin = vLightOrigin - vOrigin; Vector vDelta = vEye - vNewOrigin; float flSquaredDist = DotProduct( vDelta, vDelta ); Vector vLightDir = Vector( pHemiLights[i].m_vTransform0.z, pHemiLights[i].m_vTransform1.z, pHemiLights[i].m_vTransform2.z ); float flTargetRad = flRadius * 1.2f + flNearPlane; Vector vToLightFar = vFarEye - vNewOrigin; Vector vToLightNear = vEye - vNewOrigin; vToLightFar.NormalizeInPlace(); vToLightNear.NormalizeInPlace(); float flDotFar = DotProduct( vToLightFar, vLightDir ); float flDotNear = DotProduct( vToLightNear, vLightDir ); float flCosAngle = 0.0f; bool bInHemi = ( flDotFar > flCosAngle || flDotNear > flCosAngle ); if ( DotProduct( vDelta, vDelta ) < flTargetRad * flTargetRad && bInHemi ) { // We're inside the light m_interiorHemiLights.AddToTail( renderable ); } else { // We're outside the light m_exteriorHemiLights.AddToTail( renderable ); } m_flMaxLightEncompassingFarPlane = MAX( m_flMaxLightEncompassingFarPlane, flSquaredDist + flTargetRad * flTargetRad ); } } } void CWorldRendererTest::RenderViewStatic( CRenderView *pRenderView, int nStart, int nCount, int nIndex ) { CRenderContextPtr pRenderContext( g_pRenderDevice ); pRenderView->BeginRender( pRenderContext ); SetStateForRenderViewType( pRenderContext, pRenderView->GetViewType() ); int nRenderPass = pRenderView->GetRenderPass(); CWorldRenderFrustum *pFrustum = pRenderView->GetFrustum(); CUtlVector< CStaticMeshRenderable* > &renderableList = pRenderView->GetRenderableList(); // Set commonly used constants ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( pFrustum ); if ( nRenderPass == VARIATION_SAMPLE_LIGHTING ) { pRenderContext->SetConstantBufferData( m_hLightBufferData, (void*)&m_lightBufferData, sizeof( LightBufferData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hLightBufferData, 0, 0 ); } if ( m_bViewLowTexture && nRenderPass == VARIATION_SAMPLE_LIGHTING ) { nRenderPass = VARIATION_SAMPLE_LIGHTING_LOW_TEXTURE; } // Render the nodes Vector vLastOrigin = Vector(0,0,0); bool bFirst = true; bool bSunDepth = false; if ( nRenderPass == VARIATION_DEPTH && pRenderView->GetViewType() < RTB_SHADOW_DEPTH_MULTIPLE_0 ) bSunDepth = true; bool bSetStencil = false; if ( nRenderPass == VARIATION_NORM_DEPTH_SPEC ) bSetStencil = true; for ( int r=0; rm_pNode; AABB_t bounds = pNode->GetBounds(); Vector vOrigin = pNode->GetOrigin().m_vLocal; int nFlags = pNode->GetFlags(); bool bCanSeeSky = ( nFlags & NODE_CAN_SEE_SKY ) != 0; // Don't render depth for sun shadow maps if we can't see the sky if ( bSunDepth && !bCanSeeSky ) continue; if ( ( vLastOrigin != vOrigin ) || bFirst ) { VMatrix mViewRelated = viewConstants.m_mViewProjection; VMatrix mTrans; mTrans.Identity(); mTrans.SetTranslation( -vOrigin ); mViewRelated = mTrans.Transpose() * mViewRelated; ViewRelatedConstants_t newViewConstants = viewConstants; newViewConstants.m_mViewProjection = mViewRelated; newViewConstants.m_vEyePt.x += vOrigin.x; newViewConstants.m_vEyePt.y += vOrigin.y; newViewConstants.m_vEyePt.z += vOrigin.z; pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&newViewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); vLastOrigin = vOrigin; bFirst = false; } if ( bSetStencil ) { if ( bCanSeeSky ) { pRenderContext->SetDepthStencilState( m_hSetStencilDS, g_nCanSeeSkyStencilRef ); } else { pRenderContext->SetDepthStencilState( m_hSetStencilDS, g_nCannotSeeSkyStencilRef ); } } pNode->Draw( pRenderContext, pRenderable->m_pDrawCall, m_pResourceDictionary, (ShaderComboVariation_t)nRenderPass, m_hSingleMatrixRelated ); } pRenderView->EndRender( pRenderContext, false ); } void CWorldRendererTest::RenderViewDynamic( CRenderView *pRenderView, int nStart, int nCount, int nIndex ) { CRenderContextPtr pRenderContext( g_pRenderDevice ); pRenderView->BeginRender( pRenderContext ); // Get view constants CWorldRenderFrustum *pFrustum = pRenderView->GetFrustum(); ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( pFrustum ); // Init material data RenderMaterialData_t &materialData = pRenderContext->GetMaterialData(); materialData.Init(); materialData.flTime = Plat_FloatTime(); materialData.mVP = viewConstants.m_mViewProjection; materialData.mWVP = viewConstants.m_mViewProjection; materialData.vCameraPosition = viewConstants.m_vEyePt.AsVector3D(); materialData.vCameraForwardVec = viewConstants.m_vEyeDir.AsVector3D().Normalized(); materialData.flFarPlane = viewConstants.m_flFarPlane.x; materialData.vViewportSize[0] = 1.0f / m_lightBufferData.m_vInvScreenExtents.x; materialData.vViewportSize[1] = 1.0f / m_lightBufferData.m_vInvScreenExtents.y; materialData.customTextures[0] = m_pRenderTargets[ RT_LIGHTING_HIGHRES ]; materialData.customTextures[1] = m_pRenderTargets[ RT_SPECULAR_HIGHRES ]; int nRenderPass = pRenderView->GetRenderPass(); if ( nRenderPass == VARIATION_DEPTH ) { materialData.nMode = MODE_DEPTH; } else if ( nRenderPass == VARIATION_NORM_DEPTH_SPEC ) { materialData.nMode = MODE_NORMAL_DEPTH_SPEC; } else if ( nRenderPass == VARIATION_SAMPLE_LIGHTING ) { materialData.nMode = MODE_DEFERRED_GATHER; } else { materialData.nMode = MODE_FORWARD; } // Sun and stencil bools bool bSunDepth = false; if ( ( nRenderPass == VARIATION_DEPTH ) && ( pRenderView->GetViewType() < RTB_SHADOW_DEPTH_MULTIPLE_0 ) ) { bSunDepth = true; } bool bSetStencil = false; if ( nRenderPass == VARIATION_NORM_DEPTH_SPEC ) { bSetStencil = true; } // Render the nodes CUtlVector< CDynamicRenderable * > &renderableList = pRenderView->GetDynamicList(); for ( int r = 0; r < nCount; r++ ) { CDynamicRenderable *pRenderable = renderableList[ nStart + r ]; // Copy world matrix into material data memcpy( materialData.mWorldArray[0], &( pRenderable->m_mWorld.m[0] ), sizeof( pRenderable->m_mWorld ) ); RenderDynamic( pRenderContext, pRenderable, ( ShaderComboVariation_t )nRenderPass, bSunDepth, bSetStencil ); } pRenderView->EndRender( pRenderContext, false ); } void CWorldRendererTest::RenderView( CRenderView &renderView ) { if ( m_bMultiThreaded ) { CUtlVector< CStaticMeshRenderable* > &renderableList = renderView.GetRenderableList(); CUtlVector< CDynamicRenderable* > &dynList = renderView.GetDynamicList(); int nRenderablesStatic = renderableList.Count(); int nRenderablesDynamic = dynList.Count(); int nCountStatic = nRenderablesStatic / m_nRenderThreads; int nCountDynamic = nRenderablesDynamic / m_nRenderThreads; int nTotalRenderablesStatic = 0; int nTotalRenderablesDynamic = 0; for ( int t=0; tGetViewProj(); m_pShadowMatrices[s] = mLightRelated * m_splitScaleBiasMatrices[ s ]; m_forwardLightingData.m_mShadowMatrices[s] = m_pShadowMatrices[s]; } for ( int s=0; sm_vTransform0.w, renderable.m_pLight->m_vTransform1.w, renderable.m_pLight->m_vTransform2.w ); vOrigin -= renderable.m_vOrigin; Vector vDirection = Vector( renderable.m_pLight->m_vTransform0.z, renderable.m_pLight->m_vTransform1.z, renderable.m_pLight->m_vTransform2.z ); Vector vUp = Vector( renderable.m_pLight->m_vTransform0.y, renderable.m_pLight->m_vTransform1.y, renderable.m_pLight->m_vTransform2.y ); vDirection.NormalizeInPlace(); vUp.NormalizeInPlace(); QAngle vAngles; VectorAngles( vDirection, vUp, vAngles ); float flRadius = renderable.m_pLight->m_vColorNRadius.w; float flFOV = RAD2DEG( acosf( renderable.m_pLight->m_vAttenuationNCosSpot.w ) * 2 ); m_pMultiShadowFrustums[ s ]->InitCamera( vOrigin, vAngles, 20.0f, flRadius + 500.0f, flFOV, 1.0f ); m_pMultiShadowFrustums[ s ]->UpdateFrustumFromCamera(); VMatrix mLightRelated = m_pMultiShadowFrustums[ s ]->GetViewProj(); m_pMultiShadowMatrices[ s ] = mLightRelated * m_multiShadowScaleBiasMatrices[ s ]; m_pRenderViews[ RTB_SHADOW_DEPTH_MULTIPLE_0 + s ].SetValid( true ); } } void CWorldRendererTest::UpdateFlashlightData() { float flFlashlightLength = 1000.0f; float flSpotAngle = DEG2RAD( 45.0f ); Vector vColor( 1,1,0.8f ); vColor *= 100.0f; float flMax = 255.0f; Vector vAttenuation; vAttenuation.x = 0; vAttenuation.y = flMax / flFlashlightLength; vAttenuation.z = 0; float flTan45 = tanf( M_PI / 4.0f ); float flScale = tanf( flSpotAngle ) / flTan45; Vector vOrigin = m_pFrustum->GetCameraPosition(); Vector vDirection = m_pFrustum->Forward(); Vector vLeft = m_pFrustum->Left(); Vector vUp = m_pFrustum->Up(); vOrigin -= vUp * 15.0f; vOrigin += vLeft * 25; Vector vRight = -vLeft; vRight *= flScale * flFlashlightLength; vUp *= flScale * flFlashlightLength; vDirection *= flFlashlightLength; m_flashlight.m_vTransform0.Init( vRight.x, vUp.x, vDirection.x, vOrigin.x ); m_flashlight.m_vTransform1.Init( vRight.y, vUp.y, vDirection.y, vOrigin.y ); m_flashlight.m_vTransform2.Init( vRight.z, vUp.z, vDirection.z, vOrigin.z ); m_flashlight.m_vColorNRadius.Init( vColor.x, vColor.y, vColor.z, flFlashlightLength ); m_flashlight.m_vAttenuationNCosSpot.Init( vAttenuation.x, vAttenuation.y, vAttenuation.z, cosf( flSpotAngle ) ); } void CWorldRendererTest::UpdateViewModelData() { if ( m_dynRenderableList.Count() < 1 ) return; Vector vOrigin = m_pFrustum->GetCameraPosition(); Vector vDirection = m_pFrustum->Forward(); Vector vLeft = m_pFrustum->Left(); Vector vUp = m_pFrustum->Up(); vOrigin -= vUp * 15.0f; vOrigin -= vLeft * 25; vOrigin += vDirection * 30; VMatrix mWorld; mWorld.Identity(); mWorld.SetForward( vDirection * 0.6f ); mWorld.SetLeft( vLeft ); mWorld.SetUp( vUp ); VMatrix mRot; Vector vAxis( 0, 0, 1 ); MatrixBuildRotationAboutAxis( mRot, vAxis, 90.0f ); vAxis.Init( 1, 0, 0 ); MatrixRotate( mRot, vAxis, 90.0f ); m_dynRenderableList[ 0 ].m_vOrigin = vOrigin; m_dynRenderableList[ 0 ].m_mWorld = mWorld * mRot; m_dynRenderableList[ 0 ].m_mWorld.SetTranslation( vOrigin ); } void CWorldRendererTest::UpdateDroppedRenderables( float flElapsedTime ) { int nRenderables = m_dynRenderableList.Count(); for ( int i=1; iSetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetBlendMode( RENDER_BLEND_NOPIXELWRITE ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_AND_WRITE ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); int nParticleSystems = m_sphereSystemList.Count(); for ( int p=0; pSetViewports( 1, &m_shadowViewport ); pRenderContext->Clear( vShadowClear, RENDER_CLEAR_FLAGS_CLEAR_DEPTH ); m_pRenderViews[ RTB_SHADOW_DEPTH_MULTIPLE_0 + s ].EndRender( pRenderContext, false ); } if ( s == NUM_HIGH_RES_SHADOWS ) { m_pRenderViews[ RTB_SHADOW_DEPTH_MULTIPLE_0 + s ].BeginRender( pRenderContext ); pRenderContext->SetViewports( 1, &m_shadowViewport ); pRenderContext->Clear( vShadowClear, RENDER_CLEAR_FLAGS_CLEAR_DEPTH ); m_pRenderViews[ RTB_SHADOW_DEPTH_MULTIPLE_0 + s ].EndRender( pRenderContext, false ); } if ( m_pRenderViews[ RTB_SHADOW_DEPTH_MULTIPLE_0 + s ].HasRenderables() ) { RenderView( m_pRenderViews[ RTB_SHADOW_DEPTH_MULTIPLE_0 + s ] ); } // Render spheres m_pRenderViews[ RTB_SHADOW_DEPTH_MULTIPLE_0 + s ].BeginRender( pRenderContext ); ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pMultiShadowFrustums[ s ] ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); int nParticleSystems = m_sphereSystemList.Count(); for ( int p=0; pSetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetBlendState( m_hAdditiveBS ); pRenderContext->SetDepthStencilState( m_hStencilTestDS, g_nCanSeeSkyStencilRef ); pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_NORMAL_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT ); if ( IsPlatformX360() ) { pRenderContext->BindTexture( 1, m_pRenderTargets[ DS_DEPTH_HIGHRES ] ); } else { pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_VIEW_DEPTH_HIGHRES ] ); } pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_POINT ); pRenderContext->BindTexture( 2, m_pRenderTargets[ RT_VIEW_SPEC_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 2, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hShadowFrustumPS[2] ); for ( int s=0; sBindTexture( 4 + s, m_pRenderTargets[ DS_SHADOW_DEPTH0 + s ] ); if ( g_nPlatform == RST_PLATFORM_DX11 ) { pRenderContext->SetSamplerStatePS( 4 + s, RS_FILTER_MIN_MAG_MIP_POINT ); } else { pRenderContext->SetSamplerStatePS( 4 + s, RS_FILTER_MIN_MAG_MIP_LINEAR ); } } pRenderContext->SetConstantBufferData( m_hDeferredLightingRelated, (void*)&m_deferredLightingData, sizeof( DeferredLightingConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDeferredLightingRelated, 0, 0 ); RenderScreenQuad( pRenderContext, m_vEyeRays, "sunshadows" ); } void CWorldRendererTest::RenderBouncedLight( IRenderContext *pRenderContext ) { ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pFrustum ); pRenderContext->SetBlendState( m_hAdditiveBS ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_NO_WRITE ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_NORMAL_LOWRES ] ); pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_VIEW_DEPTH_LOWRES ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_lowResScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); RenderSceneHemiLights( pRenderContext, m_exteriorHemiLights, false ); RenderSceneHemiLights( pRenderContext, m_interiorHemiLights, true ); } void CWorldRendererTest::RenderDirectLight( IRenderContext *pRenderContext ) { ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pFrustum ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); if ( IsPlatformX360() ) { pRenderContext->BindTexture( 1, m_pRenderTargets[ DS_DEPTH_HIGHRES ] ); } else { pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_VIEW_DEPTH_HIGHRES ] ); } pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_POINT ); pRenderContext->BindTexture( 2, m_pRenderTargets[ RT_VIEW_SPEC_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 2, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); // Additive light phase pRenderContext->SetBlendState( m_hAdditiveBS ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE_STENCIL_TEST_NOTEQUAL ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); int nParticleSystems = m_lightSystemList.Count(); for ( int p=0; pSetConstantBufferData( m_hDecalScreenData, &m_decalScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); RenderScenePointLights( pRenderContext, m_exteriorPointLights, false ); RenderScenePointLights( pRenderContext, m_interiorPointLights, true ); RenderSceneSpotLights( pRenderContext, m_exteriorSpotLights, false ); RenderSceneSpotLights( pRenderContext, m_interiorSpotLights, true ); RenderShadowedSpotLights( pRenderContext, m_shadowedSpotLights ); } void CWorldRendererTest::BlurLightBuffer( ) { CRenderContextPtr pRenderContext( g_pRenderDevice ); ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pFrustum ); // Bilat blur ( Horizontal ) { m_pRenderViews[ RTB_LIGHT_BLUR_0 ].BeginRender( pRenderContext ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE ); //pRenderContext->SetBlendState( m_hWriteAllBS ); pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_DEPTH_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_LIGHTING_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_decalScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->SetConstantBufferData( m_hBlurParams, (void*)&m_blurParams, sizeof( BlurParams_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hBlurParams, 1, 7 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hBilateralBlur[2] ); RenderScreenQuad( pRenderContext, m_vEyeRays, "bilatblurhorz" ); // Submit m_pRenderViews[ RTB_LIGHT_BLUR_0 ].EndRender( pRenderContext ); } // Bilat upsampling ( Vertical ) { m_pRenderViews[ RTB_LIGHT_BLUR_1 ].BeginRender( pRenderContext ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE ); //pRenderContext->SetBlendState( m_hWriteAllBS ); pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_DEPTH_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_VIEW_SPEC_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_decalScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->SetConstantBufferData( m_hBlurParams, (void*)&m_blurParams, sizeof( BlurParams_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hBlurParams, 1, 7 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hBilateralBlur[3] ); RenderScreenQuad( pRenderContext, m_vEyeRays, "bilatblurvert" ); // Submit m_pRenderViews[ RTB_LIGHT_BLUR_1 ].EndRender( pRenderContext ); } } void CWorldRendererTest::BlurShadowBuffers( ) { CRenderContextPtr pRenderContext( g_pRenderDevice ); ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pFrustum ); BlurParams_t highResBlurParams = m_blurParams; BlurParams_t lowResBlurParams = m_blurParams; // High res shadow blur { // blur ( Horizontal ) { m_pRenderViews[ RTB_SHADOW_BLUR_0 ].BeginRender( pRenderContext ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE ); pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_SHADOW_MULTIPLE_0 ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_shadowScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->SetConstantBufferData( m_hBlurParams, (void*)&highResBlurParams, sizeof( BlurParams_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hBlurParams, 1, 7 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hShadowBlur[0] ); RenderScreenQuad( pRenderContext, m_vEyeRays, "blurshadowshorz" ); // Submit m_pRenderViews[ RTB_SHADOW_BLUR_0 ].EndRender( pRenderContext ); } // blur ( Vertical ) { m_pRenderViews[ RTB_SHADOW_BLUR_1 ].BeginRender( pRenderContext ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE ); pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_SHADOW_BLUR_TEMP ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_shadowScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->SetConstantBufferData( m_hBlurParams, (void*)&highResBlurParams, sizeof( BlurParams_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hBlurParams, 1, 7 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hShadowBlur[1] ); RenderScreenQuad( pRenderContext, m_vEyeRays, "blurshadowvert" ); // Submit m_pRenderViews[ RTB_SHADOW_BLUR_1 ].EndRender( pRenderContext ); } } // Low res shadow blur { // blur ( Horizontal ) { m_pRenderViews[ RTB_SHADOW_BLUR_0 ].BeginRender( pRenderContext ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE ); pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_SHADOW_MULTIPLE_1 ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_shadowScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->SetConstantBufferData( m_hBlurParams, (void*)&lowResBlurParams, sizeof( BlurParams_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hBlurParams, 1, 7 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hShadowBlur[2] ); RenderScreenQuad( pRenderContext, m_vEyeRays, "blurshadowhorz2" ); // Submit m_pRenderViews[ RTB_SHADOW_BLUR_0 ].EndRender( pRenderContext ); } // blur ( Vertical ) { m_pRenderViews[ RTB_SHADOW_BLUR_2 ].BeginRender( pRenderContext ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE ); pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_SHADOW_BLUR_TEMP ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_shadowScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->SetConstantBufferData( m_hBlurParams, (void*)&lowResBlurParams, sizeof( BlurParams_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hBlurParams, 1, 7 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hShadowBlur[3] ); RenderScreenQuad( pRenderContext, m_vEyeRays, "blurshadowvert2" ); // Submit m_pRenderViews[ RTB_SHADOW_BLUR_2 ].EndRender( pRenderContext ); } } } void CWorldRendererTest::RenderDecals( IRenderContext *pRenderContext, int nVariation ) { ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pFrustum ); // Paint Decals if ( m_bFullBuffer2 || m_nGlobalDecalPos2 ) { pRenderContext->SetBlendMode( RENDER_BLEND_ALPHABLENDING ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_decalScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); if ( nVariation == 0 ) { pRenderContext->BindTexture( 1, m_hDecalNormal2 ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); } else { pRenderContext->BindTexture( 1, m_hDecalAlbedo2 ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); } pRenderContext->BindVertexBuffer( 1, 0, 0, 0 ); pRenderContext->BindVertexBuffer( 0, m_hDecalVB2, 0, sizeof( DecalVertex_t ) ); pRenderContext->BindIndexBuffer( m_hDecalIB, 0 ); pRenderContext->BindVertexShader( m_hDecalVS[ nVariation ], m_hDecalLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hDecalPS[ nVariation ] ); int nIndices = 0; if ( m_bFullBuffer2 ) { nIndices = m_nMaxDecals * 36; } else { nIndices = m_nGlobalDecalPos2 * 36; } pRenderContext->DrawIndexed( RENDER_PRIM_TRIANGLES, 0, nIndices ); } // Bullet Decals if ( m_bFullBuffer || m_nGlobalDecalPos ) { bool bDraw = true; pRenderContext->SetBlendMode( RENDER_BLEND_ALPHABLENDING ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_decalScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); if ( nVariation == 0 ) { pRenderContext->BindTexture( 1, m_hDecalNormal ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); } else { if ( m_hDecalAlbedo == RENDER_TEXTURE_HANDLE_INVALID ) { bDraw = false; } else { pRenderContext->BindTexture( 1, m_hDecalAlbedo ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); } } if ( bDraw ) { pRenderContext->BindVertexBuffer( 0, m_hDecalVB, 0, sizeof( DecalVertex_t ) ); pRenderContext->BindIndexBuffer( m_hDecalIB, 0 ); pRenderContext->BindVertexShader( m_hDecalVS[ nVariation ], m_hDecalLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hDecalPS[ nVariation ] ); int nIndices = 0; if ( m_bFullBuffer ) { nIndices = m_nMaxDecals * 36; } else { nIndices = m_nGlobalDecalPos * 36; } pRenderContext->DrawIndexed( RENDER_PRIM_TRIANGLES, 0, nIndices ); } } // Wall monster decals if ( m_nGlobalDecalPos3 ) { pRenderContext->SetBlendMode( RENDER_BLEND_ALPHABLENDING ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_decalScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); if ( nVariation == 0 ) { pRenderContext->BindTexture( 1, m_hDecalNormal3[ m_nWallMonsterTexture ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindVertexBuffer( 0, m_hDecalVB3, 0, sizeof( DecalVertex_t ) ); pRenderContext->BindIndexBuffer( m_hDecalIB, 0 ); pRenderContext->BindVertexShader( m_hDecalVS[ nVariation ], m_hDecalLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hDecalPS[ nVariation ] ); int nIndices = 36; pRenderContext->DrawIndexed( RENDER_PRIM_TRIANGLES, 0, nIndices ); } } } void CWorldRendererTest::RenderDynamic( IRenderContext *pRenderContext, CDynamicRenderable *pRenderable, int nVariation, bool bSunDepth, bool bSetStencil ) { if ( bSunDepth ) { bool bCanSeeSky = true; int nLeafNode = m_pWorldRenderer->GetLeafNodeForPoint( pRenderable->m_vOrigin ); if ( nLeafNode > -1 ) { IBVHNode *pNode = m_pWorldRenderer->GetNode( nLeafNode ); if ( pNode ) { int nFlags = pNode->GetFlags(); bCanSeeSky = ( nFlags & NODE_CAN_SEE_SKY ) ? true : false; } } if ( !bCanSeeSky ) { return; } } g_pMeshSystem->DrawRenderable( pRenderContext, pRenderable->m_hRenderable, m_hSimpleMeshVS[ nVariation ], m_hSimpleMeshPS[ nVariation ] ); } void CWorldRendererTest::RenderParticleLights( IRenderContext *pRenderContext, CParticleCollection *pInputSystem, int nVariation, bool bSunDepth, bool bSetStencil ) { VPROF("RenderParticleLights"); Vector vCenter = pInputSystem->GetControlPointAtCurrentTime( 0 ); int nLeafNode = m_pWorldRenderer->GetLeafNodeForPoint( vCenter ); IBVHNode *pNode = m_pWorldRenderer->GetNode( nLeafNode ); int nFlags = pNode->GetFlags(); bool bCanSeeSky = ( nFlags & NODE_CAN_SEE_SKY ) != 0; if ( bSunDepth && !bCanSeeSky ) return; if ( bSetStencil ) { if ( bCanSeeSky ) { pRenderContext->SetDepthStencilState( m_hSetStencilDS, g_nCanSeeSkyStencilRef ); } else { pRenderContext->SetDepthStencilState( m_hSetStencilDS, g_nCannotSeeSkyStencilRef ); } } pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_decalScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->BindVertexShader( m_hPointLightVS[nVariation], m_hPointLightLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hPointLightPS[nVariation] ); pRenderContext->BindVertexBuffer( 0, m_hSphereVB, 0, sizeof( SphereVertex_t ) ); pRenderContext->BindIndexBuffer( m_hSphereIB, 0 ); CDynamicVertexData vb( pRenderContext, pInputSystem->m_nActiveParticles, "particles", "particles" ); vb.Lock( ); for ( int p=0; pm_nActiveParticles; ++p ) { float const *pPos = pInputSystem->GetFloatAttributePtr( PARTICLE_ATTRIBUTE_XYZ, p ); float const *pRadius = pInputSystem->GetFloatAttributePtr( PARTICLE_ATTRIBUTE_RADIUS, p ); float const *pColor = pInputSystem->GetFloatAttributePtr( PARTICLE_ATTRIBUTE_TINT_RGB, p ); switch( nVariation ) { case VARIATION_DEFAULT: vb->m_vPosRadius.Init( pPos[0], pPos[4], pPos[8], pRadius[0] ); break; case 4: vb->m_vPosRadius.Init( pPos[0], pPos[4], pPos[8], pRadius[0] * 0.05f ); break; default: vb->m_vPosRadius.Init( pPos[0], pPos[4], pPos[8], pRadius[0] * 0.10f ); break; } vb->m_vColor.Init( pColor[0], pColor[4], pColor[8], 1 ); //vb->m_vColor.Init( 0.9, 0.4, 1.0, 1 ); vb->m_vColor.AsVector3D().NormalizeInPlace(); vb.AdvanceVertex(); } vb.Unlock( ); vb.Bind( 1, 0 ); pRenderContext->DrawIndexedInstanced( RENDER_PRIM_TRIANGLES, 0, m_nNumTriangles * 3, pInputSystem->m_nActiveParticles ); } void CWorldRendererTest::RenderScenePointLights( IRenderContext *pRenderContext, CUtlVector &lightVector, bool bInterior ) { if ( bInterior ) { pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_FRONTFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_GREATER_NO_WRITE ); } else { pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_NO_WRITE ); } const int nMaxLightsPerDraw = 512; CDynamicVertexData *pVB = NULL; int nLights = lightVector.Count(); int nLightsDrawn = 0; for ( int i=0; i( pRenderContext, nMaxLightsPerDraw, "scenelights_point", "scenelights_point" ); pVB->Lock(); } Vector vLightOrigin = lightVector[i].m_pLight->m_vOrigin; Vector vNewOrigin = vLightOrigin - lightVector[i].m_vOrigin; (*pVB)->m_vOrigin = vNewOrigin; (*pVB)->m_vColorNRadius = lightVector[i].m_pLight->m_vColorNRadius; (*pVB)->m_vAttenuation = lightVector[i].m_pLight->m_vAttenuation; pVB->AdvanceVertex(); nLightsDrawn ++; if ( nLightsDrawn >= nMaxLightsPerDraw ) { nLightsDrawn = 0; pVB->Unlock(); pRenderContext->BindVertexBuffer( 0, m_hSphereVB, 0, sizeof( SphereVertex_t ) ); pRenderContext->BindIndexBuffer( m_hSphereIB, 0 ); pVB->Bind( 1, 0 ); pRenderContext->BindVertexShader( m_hSceneLightVS[0], m_hSceneLightLayout[0] ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hSceneLightPS[0] ); pRenderContext->DrawIndexedInstanced( RENDER_PRIM_TRIANGLES, 0, m_nSphereIndices, nMaxLightsPerDraw ); delete pVB; pVB = NULL; } } if ( pVB ) { Assert( nLightsDrawn > 0 ); pVB->Unlock(); pRenderContext->BindVertexBuffer( 0, m_hSphereVB, 0, sizeof( SphereVertex_t ) ); pRenderContext->BindIndexBuffer( m_hSphereIB, 0 ); pVB->Bind( 1, 0 ); pRenderContext->BindVertexShader( m_hSceneLightVS[0], m_hSceneLightLayout[0] ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hSceneLightPS[0] ); pRenderContext->DrawIndexedInstanced( RENDER_PRIM_TRIANGLES, 0, m_nSphereIndices, nLightsDrawn ); delete pVB; } } void CWorldRendererTest::RenderSceneHemiLights( IRenderContext *pRenderContext, CUtlVector &lightVector, bool bInterior ) { if ( bInterior ) { pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_FRONTFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_GREATER_NO_WRITE ); } else { pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_NO_WRITE ); } const int nMaxLightsPerDraw = 512; CDynamicVertexData *pVB = NULL; int nLights = lightVector.Count(); int nLightsDrawn = 0; for ( int i=0; i( pRenderContext, nMaxLightsPerDraw, "scenelights_hemi", "scenelights_hemi" ); pVB->Lock(); } Vector vOrigin = lightVector[i].m_vOrigin; (*pVB)->m_vTransform0 = lightVector[i].m_pLight->m_vTransform0; (*pVB)->m_vTransform1 = lightVector[i].m_pLight->m_vTransform1; (*pVB)->m_vTransform2 = lightVector[i].m_pLight->m_vTransform2; (*pVB)->m_vTransform0.w -= vOrigin.x; (*pVB)->m_vTransform1.w -= vOrigin.y; (*pVB)->m_vTransform2.w -= vOrigin.z; (*pVB)->m_vColorNRadius = lightVector[i].m_pLight->m_vColorNRadius; (*pVB)->m_vAttenuation = lightVector[i].m_pLight->m_vAttenuation; pVB->AdvanceVertex(); nLightsDrawn ++; if ( nLightsDrawn >= nMaxLightsPerDraw ) { nLightsDrawn = 0; pVB->Unlock(); pRenderContext->BindVertexBuffer( 0, m_hHemiVB, 0, sizeof( SphereVertex_t ) ); pRenderContext->BindIndexBuffer( m_hHemiIB, 0 ); pVB->Bind( 1, 0 ); pRenderContext->BindVertexShader( m_hSceneLightVS[1], m_hSceneLightLayout[1] ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hSceneLightPS[1] ); pRenderContext->DrawIndexedInstanced( RENDER_PRIM_TRIANGLES, 0, m_nHemiIndices, nMaxLightsPerDraw ); delete pVB; pVB = NULL; } } if ( pVB ) { pVB->Unlock(); if ( nLightsDrawn > 0 ) { pRenderContext->BindVertexBuffer( 0, m_hHemiVB, 0, sizeof( SphereVertex_t ) ); pRenderContext->BindIndexBuffer( m_hHemiIB, 0 ); pVB->Bind( 1, 0 ); pRenderContext->BindVertexShader( m_hSceneLightVS[1], m_hSceneLightLayout[1] ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hSceneLightPS[1] ); pRenderContext->DrawIndexedInstanced( RENDER_PRIM_TRIANGLES, 0, m_nHemiIndices, nLightsDrawn ); } delete pVB; } } void CWorldRendererTest::RenderSceneSpotLights( IRenderContext *pRenderContext, CUtlVector &lightVector, bool bInterior ) { if ( bInterior ) { pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_FRONTFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_GREATER_NO_WRITE ); } else { pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_NO_WRITE ); } const int nMaxLightsPerDraw = 512; CDynamicVertexData *pVB = NULL; int nLights = lightVector.Count(); int nLightsDrawn = 0; for ( int i=0; i( pRenderContext, nMaxLightsPerDraw, "scenelights_spot", "scenelights_spot" ); pVB->Lock(); } Vector vOrigin = lightVector[i].m_vOrigin; (*pVB)->m_vTransform0 = lightVector[i].m_pLight->m_vTransform0; (*pVB)->m_vTransform1 = lightVector[i].m_pLight->m_vTransform1; (*pVB)->m_vTransform2 = lightVector[i].m_pLight->m_vTransform2; (*pVB)->m_vTransform0.w -= vOrigin.x; (*pVB)->m_vTransform1.w -= vOrigin.y; (*pVB)->m_vTransform2.w -= vOrigin.z; (*pVB)->m_vColorNRadius = lightVector[i].m_pLight->m_vColorNRadius; (*pVB)->m_vAttenuationNCosSpot = lightVector[i].m_pLight->m_vAttenuationNCosSpot; pVB->AdvanceVertex(); nLightsDrawn ++; if ( nLightsDrawn >= nMaxLightsPerDraw ) { nLightsDrawn = 0; pVB->Unlock(); pRenderContext->BindVertexBuffer( 0, m_hConeVB, 0, sizeof( SphereVertex_t ) ); pRenderContext->BindIndexBuffer( m_hConeIB, 0 ); pVB->Bind( 1, 0 ); pRenderContext->BindVertexShader( m_hSceneLightVS[2], m_hSceneLightLayout[2] ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hSceneLightPS[2] ); pRenderContext->DrawIndexedInstanced( RENDER_PRIM_TRIANGLES, 0, m_nHemiIndices, nMaxLightsPerDraw ); delete pVB; pVB = NULL; } } if ( pVB ) { pVB->Unlock(); Assert( nLightsDrawn > 0 ); pRenderContext->BindVertexBuffer( 0, m_hConeVB, 0, sizeof( SphereVertex_t ) ); pRenderContext->BindIndexBuffer( m_hConeIB, 0 ); pVB->Bind( 1, 0 ); pRenderContext->BindVertexShader( m_hSceneLightVS[2], m_hSceneLightLayout[2] ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hSceneLightPS[2] ); pRenderContext->DrawIndexedInstanced( RENDER_PRIM_TRIANGLES, 0, m_nConeIndices, nLightsDrawn ); delete pVB; } } void CWorldRendererTest::RenderShadowedSpotLights( IRenderContext *pRenderContext, CUtlVector &lightVector ) { int nLights = lightVector.Count(); if ( nLights == 0 ) return; const int nMaxLightsPerDraw = NUM_MULTI_SHADOWS; CDynamicVertexData *pVB = new CDynamicVertexData( pRenderContext, nMaxLightsPerDraw, "scenelights_shadowspot", "scenelights_shadowspot" ); pVB->Lock(); Assert( nLights <= NUM_MULTI_SHADOWS ); for ( int i=0; im_vTransform0 = lightVector[i].m_pLight->m_vTransform0; (*pVB)->m_vTransform1 = lightVector[i].m_pLight->m_vTransform1; (*pVB)->m_vTransform2 = lightVector[i].m_pLight->m_vTransform2; (*pVB)->m_vTransform0.w -= vOrigin.x; (*pVB)->m_vTransform1.w -= vOrigin.y; (*pVB)->m_vTransform2.w -= vOrigin.z; (*pVB)->m_vColorNRadius = lightVector[i].m_pLight->m_vColorNRadius; (*pVB)->m_vAttenuationNCosSpot = lightVector[i].m_pLight->m_vAttenuationNCosSpot; pVB->AdvanceVertex(); } pVB->Unlock(); // Bind pRenderContext->BindVertexShader( m_hSceneLightVS[2], m_hSceneLightLayout[2] ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hSceneLightPS[5] ); pRenderContext->BindVertexBuffer( 0, m_hConeVB, 0, sizeof( SphereVertex_t ) ); pRenderContext->BindIndexBuffer( m_hConeIB, 0 ); for ( int i=0; iBindTexture( 4, m_pRenderTargets[ RT_SHADOW_MULTIPLE_0 ] ); pRenderContext->SetSamplerStatePS( 4, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 3, m_hFlashlightCookie[0] ); pRenderContext->SetSamplerStatePS( 3, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); } else { pRenderContext->BindTexture( 4, m_pRenderTargets[ RT_SHADOW_MULTIPLE_1 ] ); pRenderContext->SetSamplerStatePS( 4, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 3, m_hFlashlightCookie[1] ); pRenderContext->SetSamplerStatePS( 3, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); } pRenderContext->SetConstantBufferData( m_hSingleMatrixRelated, &m_pMultiShadowMatrices[ i ], sizeof( VMatrix ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hSingleMatrixRelated, 1, 7 ); if ( lightVector[i].m_bInterior ) { pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_FRONTFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_GREATER_NO_WRITE ); } else { pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_NO_WRITE ); } pVB->Bind( 1, i * sizeof( SpotLightData_t ) ); pRenderContext->DrawIndexedInstanced( RENDER_PRIM_TRIANGLES, 0, m_nConeIndices, 1 ); } delete pVB; } void CWorldRendererTest::CalculateEyeRays( float flFarPlane ) { Vector vForward = m_pFrustum->Forward(); Vector vUp = m_pFrustum->Up(); Vector vLeft = m_pFrustum->Left(); float flFovX = m_pFrustum->GetFOV(); float flFovY = CalcFovY( flFovX, m_pFrustum->GetAspect() ); flFovX *= 0.5f; flFovY *= 0.5f; Vector vFowardShift = flFarPlane * vForward; Vector vUpShift = flFarPlane * tanf( DEG2RAD( flFovY ) ) * vUp; Vector vRightShift = flFarPlane * tanf( DEG2RAD( flFovX ) ) * -vLeft; m_vEyeRays[0] = vFowardShift + -vRightShift + -vUpShift; m_vEyeRays[1] = vFowardShift + vRightShift + -vUpShift; m_vEyeRays[2] = vFowardShift + -vRightShift + vUpShift; m_vEyeRays[3] = vFowardShift + vRightShift + vUpShift; vFowardShift = flFarPlane * Vector( 0, 0, 1 ); vUpShift = flFarPlane * tanf( DEG2RAD( flFovY ) ) * Vector( 0, 1, 0 ); vRightShift = flFarPlane * tanf( DEG2RAD( flFovX ) ) * Vector( 1, 0, 0 ); m_vEyeLocalRays[0] = vFowardShift + -vRightShift + -vUpShift; m_vEyeLocalRays[1] = vFowardShift + vRightShift + -vUpShift; m_vEyeLocalRays[2] = vFowardShift + -vRightShift + vUpShift; m_vEyeLocalRays[3] = vFowardShift + vRightShift + vUpShift; } void CWorldRendererTest::BilateralUpsample( ) { CRenderContextPtr pRenderContext( g_pRenderDevice ); ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pFrustum ); // Bilat upsampling ( Horizontal ) { m_pRenderViews[ RTB_BILAT_UPSAMPLE_0 ].BeginRender( pRenderContext ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE ); pRenderContext->SetBlendState( m_hWriteAllBS ); if ( IsPlatformX360() ) pRenderContext->BindTexture( 0, m_pRenderTargets[ DS_DEPTH_LOWRES ] ); else pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_DEPTH_LOWRES ] ); pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_LIGHTING_LOWRES ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_lowResScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->SetConstantBufferData( m_hBlurParams, (void*)&m_blurParams, sizeof( BlurParams_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hBlurParams, 1, 7 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hBilateralBlur[0] ); RenderScreenQuad( pRenderContext, m_vEyeRays, "bilatupsamplehorz" ); // Submit m_pRenderViews[ RTB_BILAT_UPSAMPLE_0 ].EndRender( pRenderContext ); } // Bilat upsampling ( Vertical ) { m_pRenderViews[ RTB_BILAT_UPSAMPLE_1 ].BeginRender( pRenderContext ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE ); pRenderContext->SetBlendState( m_hWriteAllBS ); if ( IsPlatformX360() ) pRenderContext->BindTexture( 0, m_pRenderTargets[ DS_DEPTH_HIGHRES ] ); else pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_DEPTH_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_LIGHTING_TEMP_LOWRES ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_decalScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->SetConstantBufferData( m_hBlurParams, (void*)&m_blurParams, sizeof( BlurParams_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hBlurParams, 1, 7 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hBilateralBlur[1] ); RenderScreenQuad( pRenderContext, m_vEyeRays, "bilatupsamplevert" ); // Submit m_pRenderViews[ RTB_BILAT_UPSAMPLE_1 ].EndRender( pRenderContext ); } } void CWorldRendererTest::RenderSSAO() { CRenderContextPtr pRenderContext( g_pRenderDevice ); ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pFrustum ); m_pRenderViews[ RTB_SSAO_LOWRES ].BeginRender( pRenderContext ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetBlendState( m_hWriteAlphaBS ); #if 0 pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_DEPTH_LOWRES ] ); pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_VIEW_NORMAL_LOWRES ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_LINEAR, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 2, m_hRandomTexture ); pRenderContext->SetSamplerStatePS( 2, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_WRAP, RS_TEXTURE_ADDRESS_WRAP, RS_TEXTURE_ADDRESS_WRAP ); #else pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_DEPTH_LOWRES ] ); pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_VIEW_NORMAL_LOWRES ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 2, m_hRandomTexture ); pRenderContext->SetSamplerStatePS( 2, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_WRAP, RS_TEXTURE_ADDRESS_WRAP, RS_TEXTURE_ADDRESS_WRAP ); #endif pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_lowResScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->SetConstantBufferData( m_hSphereSampleData, &m_sphereSampleData, sizeof( SampleSphereData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hSphereSampleData, 1, 7 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hSSAOPS ); RenderScreenQuad( pRenderContext, m_vEyeRays/*m_vEyeLocalRays*/, "ssao" ); // Submit m_pRenderViews[ RTB_SSAO_LOWRES ].EndRender( pRenderContext ); } void CWorldRendererTest::ScaleDepthAndNormalBuffers() { CRenderContextPtr pRenderContext( g_pRenderDevice ); ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pFrustum ); m_pRenderViews[ RTB_DEFERRED_SCALE_DOWN ].BeginRender( pRenderContext ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->SetDepthStencilState( m_hZWriteNoTestDS ); if ( IsPlatformX360() ) { pRenderContext->BindTexture( 0, m_pRenderTargets[ DS_DEPTH_HIGHRES ] ); } else { pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_DEPTH_HIGHRES ] ); } pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT/*RENDER_TEXFILTERMODE_LINEAR*/, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_VIEW_NORMAL_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_POINT/*RENDER_TEXFILTERMODE_LINEAR*/, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); DecalScreenData_t lowResCopyData = m_lowResScreenData; lowResCopyData.m_mInvViewProj = viewConstants.m_mViewProjection; pRenderContext->SetConstantBufferData( m_hDecalScreenData, &lowResCopyData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hCopyTexture[0] ); RenderScreenQuad( pRenderContext, m_vEyeRays, "scaledepthnorm" ); // Submit m_pRenderViews[ RTB_DEFERRED_SCALE_DOWN ].EndRender( pRenderContext ); } void CWorldRendererTest::RenderAerialPerspective() { CRenderContextPtr pRenderContext( g_pRenderDevice ); ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pFrustum ); m_pRenderViews[ RTB_AERIAL_PERSPECTIVE ].BeginRender( pRenderContext ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE_STENCIL_TEST_NOTEQUAL ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); if ( IsPlatformX360() ) { pRenderContext->BindTexture( 0, m_pRenderTargets[ DS_DEPTH_HIGHRES ] ); } else { pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_DEPTH_HIGHRES ] ); } pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hAerialPerspectivePSCB, (void*)&m_aerialPerspectiveData, sizeof( AerialPerspectiveConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hAerialPerspectivePSCB, 0, 0 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); // Extinction pRenderContext->SetBlendState( m_hExtinctionBS ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hAerialPerspectivePS[0] ); RenderScreenQuad( pRenderContext, m_vEyeRays, "exinction" ); // In-scattering pRenderContext->SetDepthStencilState( m_hStencilTestDS, g_nCanSeeSkyStencilRef ); pRenderContext->SetBlendState( m_hInscatteringBS ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hAerialPerspectivePS[1] ); RenderScreenQuad( pRenderContext, m_vEyeRays, "inscattering" ); // Submit m_pRenderViews[ RTB_AERIAL_PERSPECTIVE ].EndRender( pRenderContext ); } void CWorldRendererTest::RenderSky() { VPROF("RenderSky"); CRenderContextPtr pRenderContext( g_pRenderDevice ); // Update the camera m_pFrustum->SetNearFarPlanes( m_flNearPlane, m_flFarPlane ); m_pFrustum->UpdateFrustumFromCamera(); if ( m_bDeferred ) { m_pRenderViews[ RTB_SKY ].BeginRender( pRenderContext ); } else { m_pRenderViews[ RTB_FORWARD ].BeginRender( pRenderContext ); } // Sky pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_FRONTFACING ); if ( m_bDeferred ) { pRenderContext->SetDepthStencilState( m_hZTestAndStencilTestDS, g_nNothingRenderedStencilRef ); } else { pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_NO_WRITE ); } SkyVSCB_t skyVSCB; VMatrix mTrans; mTrans.Identity(); mTrans.SetTranslation( m_pFrustum->GetCameraPosition() ); skyVSCB.m_mViewProj = mTrans.Transpose() * m_pFrustum->GetViewProj(); skyVSCB.m_vSkyScale = Vector4D( 17000.0f, 17000.0f, 3000.0f, 0.0f ); m_skyData.m_vEyePt = Vector4D( 0,0,0,0 ); m_skyData.m_vLightDir = Vector4D( m_vLightDir.x, m_vLightDir.y, m_vLightDir.z, 1 ); pRenderContext->SetConstantBufferData( m_hSkyVSCB, (void*)&skyVSCB, sizeof( SkyVSCB_t ) ); pRenderContext->SetConstantBufferData( m_hSkyPSCB, (void*)&m_skyData, sizeof( SkyPSCB_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hSkyVSCB, 0, 0 ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hSkyPSCB, 0, 0 ); pRenderContext->BindVertexShader( m_hSkyVS, m_hSphereLayout ); pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hSkyPS ); pRenderContext->BindVertexBuffer( 0, m_hSphereVB, 0, sizeof( SphereVertex_t ) ); pRenderContext->BindIndexBuffer( m_hSphereIB, 0 ); pRenderContext->DrawIndexed( RENDER_PRIM_TRIANGLES, 0, m_nNumTriangles * 3 ); // Submit if ( m_bDeferred ) { m_pRenderViews[ RTB_SKY ].EndRender( pRenderContext ); } else { m_pRenderViews[ RTB_FORWARD ].EndRender( pRenderContext ); } } void CWorldRendererTest::RenderFrame_Internal( const RenderViewport_t &viewport ) { VPROF("RenderFrame_Internal"); if ( !m_bWorldLoaded ) return; m_nWindowCenterX = viewport.m_nTopLeftX + (viewport.m_nWidth / 2); m_nWindowCenterY = viewport.m_nTopLeftY + (viewport.m_nHeight / 2); RenderViewport_t lowResViewport; lowResViewport = viewport; lowResViewport.m_nWidth = (int)( lowResViewport.m_nWidth * m_flLowResBufferScale ); lowResViewport.m_nHeight = (int)( lowResViewport.m_nHeight * m_flLowResBufferScale ); UpdateFrustum( viewport.m_nWidth, viewport.m_nHeight ); CRenderContextPtr pRenderContext( g_pRenderDevice ); VMatrix mWorld; mWorld.Identity(); Vector vCameraPos = m_pFrustum->GetCameraPosition(); float flFarPlane = m_pWorldRenderer->GetMaxVisibleDistance( vCameraPos ); float flShiftedFar = m_flFarPlane; if ( m_bEnableVis ) flShiftedFar = MIN( flFarPlane, m_flFarPlane ); CWorldRenderFrustum *pCullFrustum = m_pFrustum; if ( m_bDropFrustum ) { pCullFrustum = m_pDropFrustum; vCameraPos = m_vCullPos; flShiftedFar = m_flFarPlane; } // Update the camera m_pFrustum->SetNearFarPlanes( m_flNearPlane, flShiftedFar ); m_pFrustum->UpdateFrustumFromCamera(); VMatrix mViewProj = m_pFrustum->GetViewProj(); // Shadow split frustums float flLightDistance = 5000.0f; float flLightFarPlane = 8000.0f; float flMaxShadowDistance = 5000.0f; m_pFrustum->CalculateLightFrusta( m_pSplitFrustums, m_nShadowSplits, m_vLightDir, flLightDistance, flLightFarPlane, flMaxShadowDistance ); // Pull flashlight data from the camera UpdateFlashlightData(); // Pull viewmodel data from the camera UpdateViewModelData(); // Build renderables list GenerateRenderables( vCameraPos ); // Update Shadow Data (do this before culling!!!) UpdateShadowData(); // Culling if ( m_bDeferred ) { for ( int v=0; vSetNearFarPlanes( m_flNearPlane, flShiftedFar ); m_pFrustum->UpdateFrustumFromCamera(); mViewProj = m_pFrustum->GetViewProj(); ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pFrustum ); m_forwardLightingData.m_vLightColor = m_vRenderLightColor; m_forwardLightingData.m_vLightDir = Vector4D( m_vLightDir.x, m_vLightDir.y, m_vLightDir.z, 1 ); m_lightBufferData.m_vInvScreenExtents = Vector4D( 1.0f / viewport.m_nWidth, 1.0f / viewport.m_nHeight, 0, 0 ); // Calculate eye rays CalculateEyeRays( flShiftedFar ); // // Start of rendering // // Shadow depth buffers RenderShadowDepthBuffers( pRenderContext ); if ( m_bDeferred ) { m_deferredLightingData.m_vLightColor = m_vRenderLightColor; m_deferredLightingData.m_vLightDir = Vector4D( m_vLightDir.x, m_vLightDir.y, m_vLightDir.z, 1 ); m_deferredLightingData.m_vInvScreenExtents = Vector4D( 1.0f / viewport.m_nWidth, 1.0f / viewport.m_nHeight, 0, 0 ); m_deferredLightingData.m_vEyePt = Vector4D( vCameraPos.x, vCameraPos.y, vCameraPos.z, 1 ); m_aerialPerspectiveData.m_vLightDir = m_deferredLightingData.m_vLightDir; m_aerialPerspectiveData.m_vLightColor = m_skyData.m_vLightColor; m_aerialPerspectiveData.m_vInvScreenExtents = m_deferredLightingData.m_vInvScreenExtents; m_aerialPerspectiveData.m_vBm = m_skyData.m_vBm; m_aerialPerspectiveData.m_flG = Vector4D( 0.7f, 0,0,0 ); m_aerialPerspectiveData.m_vNearAndFar = Vector4D( m_flNearPlane, flShiftedFar, 0, 0 ); m_aerialPerspectiveData.m_vEyePt = Vector4D( vCameraPos.x, vCameraPos.y, vCameraPos.z, 1 ); m_sphereSampleData.m_mViewProj = viewConstants.m_mViewProjection; m_sphereSampleData.m_vRandSampleScale.Init( 1 / (float)m_nRandTextureSize, 1 / (float)m_nRandTextureSize, 0.5f + ( 0.5f / lowResViewport.m_nWidth ), 0.5f + ( 0.5f / lowResViewport.m_nHeight ) ); float flSSAOBias = 0.005f; float flSSAOStrenth = 5.0f; m_sphereSampleData.m_vSampleRadiusNBias.Init( m_flSampleRadius, flShiftedFar / ( m_flSampleRadius * flSSAOStrenth ), flShiftedFar, flSSAOBias * flShiftedFar ); m_blurParams.m_flFarPlane.Init( flShiftedFar, flShiftedFar, flShiftedFar, flShiftedFar ); VMatrix mPosLookupViewProj = mViewProj; if ( IsPlatformX360() ) { VMatrix mDepthFlip( 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f ); mPosLookupViewProj = mPosLookupViewProj * mDepthFlip; } if ( !MatrixInverseGeneral( mPosLookupViewProj, m_deferredLightingData.m_mInvViewProj ) ) return; m_decalScreenData.m_vInvScreenExtents = m_deferredLightingData.m_vInvScreenExtents; m_decalScreenData.m_mInvViewProj = m_deferredLightingData.m_mInvViewProj; m_decalScreenData.m_vEyePt = m_aerialPerspectiveData.m_vEyePt; m_decalScreenData.m_vEyeDir = viewConstants.m_vEyeDir; m_lowResScreenData.m_vInvScreenExtents = Vector4D( 1.0f / lowResViewport.m_nWidth, 1.0f / lowResViewport.m_nHeight, 0, 0 ); m_lowResScreenData.m_mInvViewProj = m_deferredLightingData.m_mInvViewProj; m_lowResScreenData.m_vEyePt = m_aerialPerspectiveData.m_vEyePt; m_lowResScreenData.m_vEyeDir = viewConstants.m_vEyeDir; m_shadowScreenData.m_vInvScreenExtents = Vector4D( 1.0f / m_shadowViewport.m_nWidth, 1.0f / m_shadowViewport.m_nHeight, 0, 0 ); m_shadowScreenData.m_mInvViewProj = m_deferredLightingData.m_mInvViewProj; m_shadowScreenData.m_vEyePt = m_aerialPerspectiveData.m_vEyePt; m_shadowScreenData.m_vEyeDir = viewConstants.m_vEyeDir; m_aerialPerspectiveData.m_mInvViewProj = m_deferredLightingData.m_mInvViewProj;; // Blur shadow buffers if ( m_bBlurShadows ) { BlurShadowBuffers(); } // Render depth and normal pass { // SetRenderTarget must be the first call in any command list Vector4D vNormalClear(1,1,1,1); m_pRenderViews[ RTB_DEFERRED_DEPTH_NORM_SPEC ].Clear( pRenderContext, vNormalClear, RENDER_CLEAR_FLAGS_CLEAR_DEPTH | RENDER_CLEAR_FLAGS_CLEAR_STENCIL ); RenderView( m_pRenderViews[ RTB_DEFERRED_DEPTH_NORM_SPEC ] ); // Render spheres m_pRenderViews[ RTB_DEFERRED_DEPTH_NORM_SPEC ].BeginRender( pRenderContext ); VMatrix mViewRelated; mViewRelated = m_pFrustum->GetViewProj(); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_AND_WRITE_STENCIL_SET1 ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); int nParticleSystems = m_sphereSystemList.Count(); for ( int p=0; pSetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_NO_WRITE ); // Render decals into normal map... using depth if ( IsPlatformX360() ) { pRenderContext->BindTexture( 0, m_pRenderTargets[ DS_DEPTH_HIGHRES ] ); } else { pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_DEPTH_HIGHRES ] ); } pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT ); RenderDecals( pRenderContext, 0 ); // Submit m_pRenderViews[ RTB_DEFERRED_NORM_SPEC ].EndRender( pRenderContext ); } // Scale depth and normal buffers ScaleDepthAndNormalBuffers(); // SSAO only requires depth (and normal later) if ( m_bSSAO ) { RenderSSAO(); } // Low res lighting requires depth and normal { m_pRenderViews[ RTB_LIGHTING_LOWRES ].BeginRender( pRenderContext ); if ( m_bDrawBouncedLight ) { RenderBouncedLight( pRenderContext ); } // Submit m_pRenderViews[ RTB_LIGHTING_LOWRES ].EndRender( pRenderContext ); } // Upsample BilateralUpsample(); // Clear specular buffer { Vector4D vSpecClear(0,0,0,0); m_pRenderViews[ RTB_CLEAR_SPEC_HIGHRES ].Clear( pRenderContext, vSpecClear, 0 ); } // Do lighting { m_pRenderViews[ RTB_LIGHTING_HIGHRES ].BeginRender( pRenderContext ); RenderSunShadowFrustums( pRenderContext ); if ( m_bDrawDirectLight ) { RenderDirectLight( pRenderContext ); } // Submit m_pRenderViews[ RTB_LIGHTING_HIGHRES ].EndRender( pRenderContext ); } // Blur the light buffer if ( m_bBlurLighting ) { BlurLightBuffer(); } if ( m_bLightingOnly ) { m_pRenderViews[ RTB_SAMPLE_LIGHTING ].BeginRender( pRenderContext ); pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_NONE ); pRenderContext->BindTexture( 0, m_pRenderTargets[ m_nViewBuffer ] ); pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); if ( m_nViewBuffer == RT_LIGHTING_HIGHRES ) { pRenderContext->BindTexture( 1, m_pRenderTargets[ RT_SPECULAR_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 1, RS_FILTER_MIN_MAG_MIP_POINT, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP, RS_TEXTURE_ADDRESS_CLAMP ); } pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); pRenderContext->SetConstantBufferData( m_hDecalScreenData, &m_decalScreenData, sizeof( DecalScreenData_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hDecalScreenData, 0, 0 ); pRenderContext->BindVertexShader( m_hShadowFrustumVS[2], m_hQuadLayout ); if ( m_nViewBuffer == RT_LIGHTING_LOWRES ) { pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hCopyTexture[2] ); } else if ( m_nViewBuffer == RT_LIGHTING_HIGHRES ) { pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hCopyTexture[3] ); } else { pRenderContext->BindShader( RENDER_PIXEL_SHADER, m_hCopyTexture[1] ); } RenderScreenQuad( pRenderContext, m_vEyeRays, "lightingonly" ); // Submit m_pRenderViews[ RTB_SAMPLE_LIGHTING ].EndRender( pRenderContext ); } // Render forward pass while sampling lighting else { Vector4D vForwardClear(0,0,0,0); m_pRenderViews[ RTB_SAMPLE_LIGHTING ].Clear( pRenderContext, vForwardClear, 0 ); RenderView( m_pRenderViews[ RTB_SAMPLE_LIGHTING ] ); // Render spheres m_pRenderViews[ RTB_SAMPLE_LIGHTING ].BeginRender( pRenderContext ); pRenderContext->SetConstantBufferData( m_hViewRelated, (void*)&viewConstants, sizeof( ViewRelatedConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, m_hViewRelated, 0, 0 ); int nParticleSystems = m_sphereSystemList.Count(); pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_EQUAL_NO_WRITE ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->BindTexture( 4, m_pRenderTargets[ RT_LIGHTING_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 4, RS_FILTER_MIN_MAG_MIP_POINT ); pRenderContext->BindTexture( 5, m_pRenderTargets[ RT_SPECULAR_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 5, RS_FILTER_MIN_MAG_MIP_POINT ); for ( int p=0; pSetZBufferMode( RENDER_ZBUFFER_ZTEST_NO_WRITE ); if ( IsPlatformX360() ) { pRenderContext->BindTexture( 0, m_pRenderTargets[ DS_DEPTH_HIGHRES ] ); } else { pRenderContext->BindTexture( 0, m_pRenderTargets[ RT_VIEW_DEPTH_HIGHRES ] ); } pRenderContext->SetSamplerStatePS( 0, RS_FILTER_MIN_MAG_MIP_POINT ); pRenderContext->BindTexture( 2, m_pRenderTargets[ RT_LIGHTING_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 2, RS_FILTER_MIN_MAG_MIP_POINT ); pRenderContext->BindTexture( 3, m_pRenderTargets[ RT_SPECULAR_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 3, RS_FILTER_MIN_MAG_MIP_POINT ); RenderDecals( pRenderContext, 1 ); // Render pointlights pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_AND_WRITE ); nParticleSystems = m_lightSystemList.Count(); for ( int p=0; pBindTexture( 4 + s, RENDER_TEXTURE_HANDLE_INVALID ); } pRenderContext->Submit(); for ( int v=0; vUpdateResources( g_pRenderDevice, pRenderContext, 10 ); m_nGlobalDecalPos3 = 0; m_nCurrentFrameNumber++; } void CWorldRendererTest::SimulateFrame( float flTimeStep ) { UpdateDroppedRenderables( flTimeStep ); const float forwardSpeed = 500.0f; const float sideSpeed = 500.0f; const float yawSpeed = 90.0f; const float pitchSpeed = 45.0f; #if defined( _X360 ) const float flYawSensitivity = -0.04f; const float flPitchSensitivity = 0.04f; #else const float flYawSensitivity = -0.2f; const float flPitchSensitivity = 0.2f; #endif float flForward = forwardSpeed; float flSide = sideSpeed; if ( m_cmd.m_nKeys & FKEY_FAST ) { flForward *= 5; flSide *= 5; } if ( m_cmd.m_nKeys & FKEY_ENABLE_VIS ) { m_bEnableVis = true; Msg( "Vis enabled\n" ); } else if( m_cmd.m_nKeys & FKEY_DISABLE_VIS ) { m_bEnableVis = false; Msg( "Vis disabled\n" ); } if ( m_cmd.m_nKeys & FKEY_DROP_FRUSTUM ) { Q_memcpy( m_pDropFrustum, m_pFrustum, sizeof( CWorldRenderFrustum ) ); m_bDropFrustum = !m_bDropFrustum; m_vCullPos = m_pFrustum->GetCameraPosition(); if ( m_bDropFrustum ) Msg( "Drop frustum\n" ); else Msg( "no drop\n" ); ThreadSleep( 200 ); } if ( m_cmd.m_nKeys & FKEY_TOGGLE_AERIAL ) { m_bDrawAerialPerspective = !m_bDrawAerialPerspective; if ( m_bDrawAerialPerspective ) Msg( "Aerial Perspective: On\n" ); else Msg( "Aerial Perspective: Off\n" ); ThreadSleep( 200 ); } if ( m_cmd.m_nKeys & FKEY_TOGGLE_BOUNCE ) { m_bDrawBouncedLight = !m_bDrawBouncedLight; if ( m_bDrawBouncedLight ) Msg( "Bounced light: On\n" ); else Msg( "Bounced light: Off\n" ); ThreadSleep( 200 ); } if ( m_cmd.m_nKeys & FKEY_TOGGLE_DIRECT ) { m_bDrawDirectLight = !m_bDrawDirectLight; if ( m_bDrawDirectLight ) Msg( "Direct light: On\n" ); else Msg( "Direct light: Off\n" ); ThreadSleep( 200 ); } if ( m_cmd.m_nKeys & FKEY_TOGGLE_LIGHTING_ONLY ) { m_bLightingOnly = !m_bLightingOnly; if ( m_bLightingOnly ) Msg( "Lighting Only: On\n" ); else Msg( "Lighting Only: Off\n" ); ThreadSleep( 200 ); } if ( m_cmd.m_nKeys & FKEY_SSAO ) { m_bSSAO = !m_bSSAO; if ( m_bSSAO ) Msg( "SSAO: On\n" ); else Msg( "SSAO: Off\n" ); ThreadSleep( 200 ); } if ( m_cmd.m_nKeys & FKEY_BLUR_LIGHTING ) { m_bBlurLighting = !m_bBlurLighting; if ( m_bBlurLighting ) Msg( "Blur Lighting: On\n" ); else Msg( "Blur Lighting: Off\n" ); ThreadSleep( 200 ); } if ( m_cmd.m_nKeys & FKEY_BLUR_SHADOWS ) { m_bBlurShadows = !m_bBlurShadows; if ( m_bBlurShadows ) Msg( "Blur Shadows: On\n" ); else Msg( "Blur Shadows: Off\n" ); ThreadSleep( 200 ); } m_cmd.m_flForwardMove = (m_cmd.m_nKeys & (FKEY_FORWARD|FKEY_BACK)) ? ( (m_cmd.m_nKeys & FKEY_FORWARD) ? flForward : -flForward) : 0; m_cmd.m_flRightMove = (m_cmd.m_nKeys & (FKEY_LEFT|FKEY_RIGHT)) ? ( (m_cmd.m_nKeys & FKEY_RIGHT) ? flSide : -flSide) : 0; float flYawMove = (m_cmd.m_nKeys & (FKEY_TURNLEFT|FKEY_TURNRIGHT)) ? ( (m_cmd.m_nKeys & FKEY_TURNLEFT) ? yawSpeed : -yawSpeed) : 0; float flPitchMove = (m_cmd.m_nKeys & (FKEY_TURNUP|FKEY_TURNDOWN)) ? ( (m_cmd.m_nKeys & FKEY_TURNDOWN) ? pitchSpeed : -pitchSpeed) : 0; if ( m_nCursorDeltaX || m_nCursorDeltaY ) { m_cmd.m_flYawMove = m_nCursorDeltaX * flYawSensitivity; m_cmd.m_flPitchMove = m_nCursorDeltaY * flPitchSensitivity; m_nCursorDeltaX = m_nCursorDeltaResetX; m_nCursorDeltaY = m_nCursorDeltaResetY; if ( !IsPlatformX360() ) { g_pInputStackSystem->SetCursorPosition( GetInputContext(), m_nWindowCenterX, m_nWindowCenterY ); } } m_cmd.m_flPitchMove += flPitchMove * flTimeStep; m_cmd.m_flYawMove += flYawMove * flTimeStep; Vector vMoveAmount = ((m_pFrustum->Forward() * m_cmd.m_flForwardMove ) - ( m_pFrustum->Left() * m_cmd.m_flRightMove )) * flTimeStep; Vector eyePos = m_pFrustum->GetCameraPosition() + vMoveAmount; m_pFrustum->SetCameraPosition( eyePos ); QAngle angles = m_pFrustum->GetCameraAngles(); angles.y += m_cmd.m_flYawMove; angles.x += m_cmd.m_flPitchMove; angles.x = clamp( angles.x, -89.0f, 89.0f ); m_cmd.m_flYawMove = 0; m_cmd.m_flPitchMove = 0; if ( angles.y > 180.0f ) { angles.y -= 360.0f; } if ( angles.y < -180.0f ) { angles.y += 360.0f; } m_pFrustum->SetCameraAngles( angles ); // Update light VMatrix mLight,mLightAngle, mLightElevation; mLightAngle.Identity(); mLightElevation.Identity(); mLight.Identity(); MatrixRotate( mLightElevation, Vector(1,0,0), m_vLightAngleElevation.y ); MatrixRotate( mLightAngle, Vector(0,0,1), m_vLightAngleElevation.x ); mLight = mLightElevation * mLightAngle; Vector vLightStart(1,0,0); matrix3x4_t mLight3x4 = mLight.As3x4(); VectorRotate( vLightStart, mLight3x4, m_vLightDir ); m_vLightDir.NormalizeInPlace(); float flLerp = sinf( DEG2RAD( m_vLightAngleElevation.x ) ); Vector4D vColorRed( 1.0, 0.7, 0.6, 1 ); Vector4D vColorYellow( 1.0, 0.9, 0.7, 1 ); m_skyData.m_vLightColor = Lerp( flLerp, vColorRed, vColorYellow ); Vector4D vRenderColorRed( 1.0, 0.6, 0.4, 1 ); Vector4D vRenderColorYellow( 1.0, 0.9, 0.7, 1 ); m_vRenderLightColor = Lerp( flLerp, vRenderColorRed, vRenderColorYellow ); Vector4D vBmRed( 1.0e-4, 0.4e-4, 0.3e-4, 1 ); Vector4D vBmYellow( 1.0e-4, 0.7e-4, 0.3e-4, 1 ); m_skyData.m_vBm = Lerp( flLerp, vBmRed, vBmYellow ); float flGRed = 0.90f; float flGYellow = 0.99f; m_skyData.m_flG.x = Lerp( flLerp, flGRed, flGYellow ); if ( m_cmd.m_nKeys & FKEY_LIGHTANG_POS ) { m_vLightAngleElevation.x += m_flLightAngSpeed * flTimeStep; } else if ( m_cmd.m_nKeys & FKEY_LIGHTANG_NEG ) { m_vLightAngleElevation.x -= m_flLightAngSpeed * flTimeStep; } if ( m_cmd.m_nKeys & FKEY_LIGHTELV ) { m_vLightAngleElevation.y += m_flLightElvSpeed * flTimeStep; if ( m_vLightAngleElevation.y > 88.0f || m_vLightAngleElevation.y < 30.0f ) { m_flLightElvSpeed = -m_flLightElvSpeed; } } // Shooting decals if ( m_cmd.m_nKeys & FKEY_SHOOTDECAL ) { if ( m_flDecalCountdown <= 0 ) { Vector vEye = m_pFrustum->GetCameraPosition(); Vector vDir = m_pFrustum->Forward(); Vector vSurfaceNormal; float flDistance = m_pWorldRenderer->CastRay( &vSurfaceNormal, vEye, vDir ); if ( flDistance > 0 ) { float flSize = RPercentABS() * 40.0f + 70.0f; CRenderContextPtr pRenderContext( g_pRenderDevice ); Vector vPos = vEye + vDir * flDistance; AddDecal( pRenderContext, vPos, vSurfaceNormal, flSize, flSize, //size x,y 6.0f, 12.0f, false ); // intersection, length } m_flDecalCountdown = 0.1f; } m_flDecalCountdown -= flTimeStep; } // Shooting blood decals if ( m_cmd.m_nKeys & FKEY_SHOOTDECAL2 ) { if ( m_flDecalCountdown <= 0 ) { Vector vEye = m_pFrustum->GetCameraPosition(); Vector vDir = m_pFrustum->Forward(); Vector vSurfaceNormal; float flDistance = m_pWorldRenderer->CastRay( &vSurfaceNormal, vEye, vDir ); if ( flDistance > 0 ) { float flSize = RPercentABS() * 50.0f + 80.0f; CRenderContextPtr pRenderContext( g_pRenderDevice ); Vector vPos = vEye + vDir * flDistance; AddDecal( pRenderContext, vPos, vSurfaceNormal, flSize, flSize, //size x,y 20.0f, 40.0f, true ); // intersection, length } m_flDecalCountdown = 0.05f; } m_flDecalCountdown -= flTimeStep; } // Shooting the wall-monster decal if ( m_cmd.m_nKeys & FKEY_SHOOTWALLMONSTER ) { Vector vEye = m_pFrustum->GetCameraPosition(); Vector vDir = m_pFrustum->Forward(); Vector vSurfaceNormal; float flDistance = m_pWorldRenderer->CastRay( &vSurfaceNormal, vEye, vDir ); if ( flDistance > 0 ) { float flSize = 100.0f; CRenderContextPtr pRenderContext( g_pRenderDevice ); Vector vPos = vEye + vDir * flDistance; Vector vMonsterNormal = m_vPreviousMonsterNormal + vSurfaceNormal * 4; vMonsterNormal.NormalizeInPlace(); AddWallMonster( pRenderContext, vPos, vMonsterNormal, flSize, flSize, //size x,y 50.0f, 100.0f ); // intersection, length m_vPreviousMonsterNormal = vMonsterNormal; if ( m_flWallMonsterTimer < 0 ) { m_nWallMonsterTexture = ( m_nWallMonsterTexture + 1 ) % 3; m_flWallMonsterTimer = 0.05f; } else { m_flWallMonsterTimer -= MAX( 0.01f, flTimeStep ); } } } if ( !( m_cmd.m_nKeys & FKEY_SHOOTDECAL || m_cmd.m_nKeys & FKEY_SHOOTDECAL2 ) ) { m_flDecalCountdown = 0.0f; } // shoot a particle system if ( m_cmd.m_nKeys & FKEY_SHOOTPSYSTEM || m_cmd.m_nKeys & FKEY_SHOOTSSYSTEM ) { if ( m_flParticleCountdown <= 0 ) { bool bSphereSystem = ( m_cmd.m_nKeys & FKEY_SHOOTSSYSTEM ) != 0; Vector vEye = m_pFrustum->GetCameraPosition(); Vector vDir = m_pFrustum->Forward(); Vector vSurfaceNormal; float flDistance = m_pWorldRenderer->CastRay( &vSurfaceNormal, vEye, vDir ); if ( flDistance > 0 ) { Msg( "psystem distance = %f\n", flDistance ); CParticleCollection *pParticleSystem = g_pSceneSystem->CreateParticleCollection( "wonderinglights" ); if ( !pParticleSystem ) Error( "No wondering lights particle system!\n" ); Vector vPos = vEye + vDir * flDistance; vPos += vSurfaceNormal * 100; pParticleSystem->SetControlPoint( 0, vPos ); pParticleSystem->SetControlPointOrientation( 0, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) ); if ( bSphereSystem ) m_sphereSystemList.AddToTail( pParticleSystem ); else m_lightSystemList.AddToTail( pParticleSystem ); SimulateWorkUnitWorldRender_t workUnit; workUnit.m_nNumSystems = 1; workUnit.m_pParticles = pParticleSystem; m_particleWorkUnits.AddToTail( workUnit ); } m_flParticleCountdown = 0.5f; } m_flParticleCountdown -= flTimeStep; } else { m_flParticleCountdown = 0.0f; } // Sim particles SimulateParticles( flTimeStep ); } void CWorldRendererTest::AddDecal( IRenderContext *pRenderContext, Vector &vHit, Vector &vDecalDir, float flDecalSizeU, float flDecalSizeV, float flDecalShift, float flDecalInfluenceLength, bool bPaint ) { if ( g_nPlatform == RST_PLATFORM_GL ) return; Vector vUp(RPercent(),RPercent(),RPercent()); vUp.NormalizeInPlace(); Vector vNegUp = -vUp; if ( DotProduct( vDecalDir, vUp ) > 0.95f || DotProduct( vDecalDir, vNegUp ) > 0.95f ) vUp = Vector(0,1,0); Vector vRight; vRight = CrossProduct( vUp, vDecalDir ); vUp = CrossProduct( vDecalDir, vRight ); vRight.NormalizeInPlace(); vUp.NormalizeInPlace(); vRight *= flDecalSizeU; vUp *= flDecalSizeV; vDecalDir.NormalizeInPlace(); Vector vStartCorner = vHit; vStartCorner -= vRight * 0.5f; vStartCorner -= vUp * 0.5f; vStartCorner -= vDecalDir * flDecalShift; vDecalDir *= flDecalInfluenceLength; // Create the 8 corners of a box surrounding our decal Vector vCorners[8]; vCorners[0] = vStartCorner; vCorners[1] = vStartCorner + vRight; vCorners[2] = vStartCorner + vRight + vUp; vCorners[3] = vStartCorner + vUp; vCorners[4] = vStartCorner + vDecalDir; vCorners[5] = vCorners[4] + vRight; vCorners[6] = vCorners[4] + vRight + vUp; vCorners[7] = vCorners[4] + vUp; float fRMul = 1.0f / ( flDecalSizeU * flDecalSizeU ); float fUMul = 1.0f / ( flDecalSizeV * flDecalSizeV ); vRight = fRMul * vRight; vUp = fUMul * vUp; if ( bPaint ) { DecalVertex_t *pVertices = &m_pDecalBackingStore2[ m_nGlobalDecalPos2 * 8 ]; for ( int i=0; i<8; ++i ) { pVertices[i].m_vPos = vCorners[i]; pVertices[i].m_vDecalRight = vRight; pVertices[i].m_vDecalUpAndInfluence = Vector4D( vUp.x, vUp.y, vUp.z, flDecalInfluenceLength ); pVertices[i].m_vDecalOrigin = vStartCorner; } LockDesc_t lockDesc; pRenderContext->LockVertexBuffer( m_hDecalVB2, m_nMaxDecals * 8 * sizeof( DecalVertex_t ), &lockDesc ); Q_memcpy( lockDesc.m_pMemory, m_pDecalBackingStore2, m_nMaxDecals * 8 * sizeof( DecalVertex_t ) ); pRenderContext->UnlockVertexBuffer( m_hDecalVB2, m_nMaxDecals * 8 * sizeof( DecalVertex_t ), &lockDesc ); // Go to the next decal m_nGlobalDecalPos2 ++; if ( m_nGlobalDecalPos2 >= m_nMaxDecals ) { m_bFullBuffer2 = true; m_nGlobalDecalPos2 = 0; } } else { DecalVertex_t *pVertices = &m_pDecalBackingStore[ m_nGlobalDecalPos * 8 ]; for ( int i=0; i<8; ++i ) { pVertices[i].m_vPos = vCorners[i]; pVertices[i].m_vDecalRight = vRight; pVertices[i].m_vDecalUpAndInfluence = Vector4D( vUp.x, vUp.y, vUp.z, flDecalInfluenceLength ); pVertices[i].m_vDecalOrigin = vStartCorner; } LockDesc_t lockDesc; pRenderContext->LockVertexBuffer( m_hDecalVB, m_nMaxDecals * 8 * sizeof( DecalVertex_t ), &lockDesc ); Q_memcpy( lockDesc.m_pMemory, m_pDecalBackingStore, m_nMaxDecals * 8 * sizeof( DecalVertex_t ) ); pRenderContext->UnlockVertexBuffer( m_hDecalVB, m_nMaxDecals * 8 * sizeof( DecalVertex_t ), &lockDesc ); // Go to the next decal m_nGlobalDecalPos ++; if ( m_nGlobalDecalPos >= m_nMaxDecals ) { m_bFullBuffer = true; m_nGlobalDecalPos = 0; } } } void CWorldRendererTest::AddWallMonster( IRenderContext *pRenderContext, Vector &vHit, Vector &vDecalDir, float flDecalSizeU, float flDecalSizeV, float flDecalShift, float flDecalInfluenceLength ) { if ( g_nPlatform == RST_PLATFORM_GL ) return; Vector vUp(0,0,1); Vector vNegUp = -vUp; if ( DotProduct( vDecalDir, vUp ) > 0.95f || DotProduct( vDecalDir, vNegUp ) > 0.95f ) vUp = m_pFrustum->Up(); Vector vRight; vRight = CrossProduct( vUp, vDecalDir ); vUp = CrossProduct( vDecalDir, vRight ); vRight.NormalizeInPlace(); vUp.NormalizeInPlace(); vRight *= flDecalSizeU; vUp *= flDecalSizeV; vDecalDir.NormalizeInPlace(); Vector vStartCorner = vHit; vStartCorner -= vRight * 0.5f; vStartCorner -= vUp * 0.5f; vStartCorner -= vDecalDir * flDecalShift; vDecalDir *= flDecalInfluenceLength; // Create the 8 corners of a box surrounding our decal Vector vCorners[8]; vCorners[0] = vStartCorner; vCorners[1] = vStartCorner + vRight; vCorners[2] = vStartCorner + vRight + vUp; vCorners[3] = vStartCorner + vUp; vCorners[4] = vStartCorner + vDecalDir; vCorners[5] = vCorners[4] + vRight; vCorners[6] = vCorners[4] + vRight + vUp; vCorners[7] = vCorners[4] + vUp; float fRMul = 1.0f / ( flDecalSizeU * flDecalSizeU ); float fUMul = 1.0f / ( flDecalSizeV * flDecalSizeV ); vRight = fRMul * vRight; vUp = fUMul * vUp; DecalVertex_t pVertices[8]; for ( int i=0; i<8; ++i ) { pVertices[i].m_vPos = vCorners[i]; pVertices[i].m_vDecalRight = vRight; pVertices[i].m_vDecalUpAndInfluence = Vector4D( vUp.x, vUp.y, vUp.z, flDecalInfluenceLength ); pVertices[i].m_vDecalOrigin = vStartCorner; } LockDesc_t lockDesc; pRenderContext->LockVertexBuffer( m_hDecalVB3, 8 * sizeof( DecalVertex_t ), &lockDesc ); Q_memcpy( lockDesc.m_pMemory, pVertices, 8 * sizeof( DecalVertex_t ) ); pRenderContext->UnlockVertexBuffer( m_hDecalVB3, 8 * sizeof( DecalVertex_t ), &lockDesc ); // Go to the next decal m_nGlobalDecalPos3 = 1; } void CWorldRendererTest::DropRenderable() { Vector vOrigin = m_pFrustum->GetCameraPosition(); vOrigin.z -= 32.0f; int index = m_dynRenderableList.AddToTail(); VMatrix mRot; Vector vAxis( 0, 0, 1 ); MatrixBuildRotationAboutAxis( mRot, vAxis, 90.0f ); vAxis.Init( 1, 0, 0 ); MatrixRotate( mRot, vAxis, 90.0f ); m_dynRenderableList[ index ].m_vOrigin = vOrigin; m_dynRenderableList[ index ].m_mWorld = mRot; m_dynRenderableList[ index ].m_hRenderable = g_pMeshSystem->FindOrCreateFileRenderable( g_pRenderableList[ g_nCurrentModel ] ); g_nCurrentModel ++; if ( g_nCurrentModel >= MAX_MESH_SYSTEM_MODELS ) g_nCurrentModel = 0; } Vector Evaluate( float flU, float flV, Vector vRadius ) { flU *= 2.0 * M_PI; flV *= 2.0 * M_PI; return Vector( vRadius.x * cos( flU ) * sin( flV ), vRadius.y * sin( flU ) * sin( flV ), vRadius.z * cos ( flV ) ); } void CWorldRendererTest::CreateSphere( int nTessellationRes ) { Vector vRadius(1,1,1); CRenderContextPtr pRenderContext( g_pRenderDevice ); // create the static index buffer BufferDesc_t indexDesc; indexDesc.m_nElementSizeInBytes = sizeof(uint16); indexDesc.m_nElementCount = 2 * 3 * ( nTessellationRes * nTessellationRes ); indexDesc.m_pDebugName = "sphereib"; indexDesc.m_pBudgetGroupName = "shapes"; m_hSphereIB = g_pRenderDevice->CreateIndexBuffer( RENDER_BUFFER_TYPE_STATIC, indexDesc ); // fill in the index buffer CIndexData ib( pRenderContext, m_hSphereIB ); ib.Lock( indexDesc.m_nElementCount ); m_nNumTriangles = 0; // generate the fixed tesselation for( int u = 0; u < nTessellationRes; u += 1 ) { int nu = ( u + 1 ) % nTessellationRes; for( int v = 0; v < nTessellationRes; v++ ) { int nv = ( v + 1 ) % nTessellationRes; ib.Index2( u * nTessellationRes + v, nu * nTessellationRes + v ); ib.Index2( u * nTessellationRes + nv, nu * nTessellationRes + v); ib.Index2( nu * nTessellationRes + nv, u * nTessellationRes + nv ); m_nNumTriangles += 2; } } ib.Unlock( ); m_nSphereIndices = indexDesc.m_nElementCount; // VB int nVertices = ( nTessellationRes ) * ( nTessellationRes ); BufferDesc_t vertexDesc; vertexDesc.m_nElementSizeInBytes = sizeof(SphereVertex_t); vertexDesc.m_nElementCount = nVertices; vertexDesc.m_pDebugName = "spherevb"; vertexDesc.m_pBudgetGroupName = "shapes"; m_hSphereVB = g_pRenderDevice->CreateVertexBuffer( RENDER_BUFFER_TYPE_STATIC, vertexDesc ); CVertexData vb( pRenderContext, m_hSphereVB ); vb.Lock( nVertices ); for( int u = 0 ; u < nTessellationRes; u++ ) { float flU = u * ( 1.0 / nTessellationRes ); for( int v = 0; v < nTessellationRes; v++ ) { float flV = v * ( 1.0 / nTessellationRes ); Vector pos1 = Evaluate( flU + 0.5 / nTessellationRes, flV, vRadius ); vb->m_vPos = pos1; vb.AdvanceVertex(); } } vb.Unlock( ); static RenderInputLayoutField_t sphereLayout[] = { DEFINE_PER_VERTEX_FIELD( 0, "position", 0, SphereVertex_t, m_vPos ) }; m_hSphereLayout = g_pRenderDevice->CreateInputLayout( "spherelayout", ARRAYSIZE( sphereLayout ), sphereLayout ); pRenderContext->Submit(); } void CWorldRendererTest::CreateHemi( int nTessellationRes ) { Vector vRadius(1,1,1); CRenderContextPtr pRenderContext( g_pRenderDevice ); // create the static index buffer BufferDesc_t indexDesc; indexDesc.m_nElementSizeInBytes = sizeof(uint16); indexDesc.m_nElementCount = 2 * 3 * ( nTessellationRes * nTessellationRes ); indexDesc.m_pDebugName = "hemiIB"; indexDesc.m_pBudgetGroupName = "shapes"; m_hHemiIB = g_pRenderDevice->CreateIndexBuffer( RENDER_BUFFER_TYPE_STATIC, indexDesc ); // fill in the index buffer CIndexData ib( pRenderContext, m_hHemiIB ); ib.Lock( indexDesc.m_nElementCount ); // generate the fixed tesselation for( int u = 0; u < nTessellationRes; u += 1 ) { int nu = ( u + 1 ) % nTessellationRes; for( int v = 0; v < nTessellationRes; v++ ) { int nv = ( v + 1 ) % nTessellationRes; ib.Index2( u * nTessellationRes + v, nu * nTessellationRes + v ); ib.Index2( u * nTessellationRes + nv, nu * nTessellationRes + v); ib.Index2( nu * nTessellationRes + nv, u * nTessellationRes + nv ); } } ib.Unlock( ); m_nHemiIndices = indexDesc.m_nElementCount; // VB int nVertices = ( nTessellationRes ) * ( nTessellationRes ); BufferDesc_t vertexDesc; vertexDesc.m_nElementSizeInBytes = sizeof(SphereVertex_t); vertexDesc.m_nElementCount = nVertices; vertexDesc.m_pDebugName = "hemiVB"; vertexDesc.m_pBudgetGroupName = "shapes"; m_hHemiVB = g_pRenderDevice->CreateVertexBuffer( RENDER_BUFFER_TYPE_STATIC, vertexDesc ); CVertexData vb( pRenderContext, m_hHemiVB ); vb.Lock( nVertices ); for( int u = 0 ; u < nTessellationRes; u++ ) { float flU = u * ( 1.0 / nTessellationRes ); for( int v = 0; v < nTessellationRes; v++ ) { float flV = v * ( 1.0 / nTessellationRes ); Vector pos1 = Evaluate( flU + 0.5 / nTessellationRes, flV, vRadius ); if ( pos1.z < 0 ) pos1.z = 0; vb->m_vPos = pos1; vb.AdvanceVertex(); } } vb.Unlock( ); pRenderContext->Submit(); } void CWorldRendererTest::CreateCone( int nTessellationRes ) { CRenderContextPtr pRenderContext( g_pRenderDevice ); Vector vTop(0,0,0); int nVertices = nTessellationRes + 1; int nIndices = ( nTessellationRes + nTessellationRes - 2 ) * 3; // create the static index buffer BufferDesc_t indexDesc; indexDesc.m_nElementSizeInBytes = sizeof(uint16); indexDesc.m_nElementCount = nIndices; indexDesc.m_pDebugName = "coneib"; indexDesc.m_pBudgetGroupName = "shapes"; m_hConeIB = g_pRenderDevice->CreateIndexBuffer( RENDER_BUFFER_TYPE_STATIC, indexDesc ); // create the static vertex buffer BufferDesc_t vertexDesc; vertexDesc.m_nElementSizeInBytes = sizeof(SphereVertex_t); vertexDesc.m_nElementCount = nVertices; vertexDesc.m_pDebugName = "conevb"; vertexDesc.m_pBudgetGroupName = "shapes"; m_hConeVB = g_pRenderDevice->CreateVertexBuffer( RENDER_BUFFER_TYPE_STATIC, vertexDesc ); m_nConeIndices = nIndices; CVertexData vb( pRenderContext, m_hConeVB ); vb.Lock( nVertices ); vb->m_vPos = vTop; vb.AdvanceVertex(); float flTesRes = (float)nTessellationRes; for ( int i=0; im_vPos = vPos; vb.AdvanceVertex(); } vb.Unlock(); CIndexData ib( pRenderContext, m_hConeIB ); ib.Lock( indexDesc.m_nElementCount ); // Cone for ( int i=1; iReadFile( pLocalFileName, NULL, buffer ) ) { Error( "Couldn't load %s!\n", pFileName ); return false; } return true; } RenderShaderHandle_t CWorldRendererTest::GetVertexShader( char *pShaderName, IRenderDevice *pDevice, const char *pShaderVersion, const char *pDefineText ) { CUtlBuffer buffer; char pLevelText[100]; if ( 0 == Q_strncmp( pShaderVersion, "vs_3_0", 6 ) || 0 == Q_strncmp( pShaderVersion, "ps_3_0", 6 ) ) Q_snprintf( pLevelText, 100, "#define SHADER_LEVEL 3\n" ); else Q_snprintf( pLevelText, 100, "#define SHADER_LEVEL 4\n" ); buffer.Put( pLevelText, strlen( pLevelText ) ); if ( pDefineText ) buffer.Put( pDefineText, strlen( pDefineText ) ); if ( !LoadFile( pShaderName, buffer, "vs_3_0" ) ) { return RENDER_SHADER_HANDLE_INVALID; } char *pText = (char*)buffer.Base(); int nBytes = buffer.TellPut(); if ( nBytes < 1 ) return RENDER_SHADER_HANDLE_INVALID; // Create the shader return pDevice->CreateShader( RENDER_VERTEX_SHADER, pText, nBytes, pShaderVersion ); } RenderShaderHandle_t CWorldRendererTest::GetPixelShader( char *pShaderName, IRenderDevice *pDevice, const char *pShaderVersion, const char *pDefineText ) { CUtlBuffer buffer; char pLevelText[100]; if ( 0 == Q_strncmp( pShaderVersion, "ps_3_0", 6 ) ) Q_snprintf( pLevelText, 100, "#define SHADER_LEVEL 3\n" ); else Q_snprintf( pLevelText, 100, "#define SHADER_LEVEL 4\n" ); buffer.Put( pLevelText, strlen( pLevelText ) ); if ( pDefineText ) buffer.Put( pDefineText, strlen( pDefineText ) ); if ( !LoadFile( pShaderName, buffer, "ps_3_0" ) ) { return RENDER_SHADER_HANDLE_INVALID; } char *pText = (char*)buffer.Base(); int nBytes = buffer.TellPut(); if ( nBytes < 1 ) return RENDER_SHADER_HANDLE_INVALID; // Create the shader return pDevice->CreateShader( RENDER_PIXEL_SHADER, pText, nBytes, pShaderVersion ); } intp g_nMagicNumber = 1234567; HRenderTexture CWorldRendererTest::CreateRenderTarget( RenderTargetType_t type, const RenderViewport_t &viewport ) { HRenderTexture hRetHandle = RENDER_TEXTURE_HANDLE_INVALID; TextureHeader_t spec; spec.m_nNumMipLevels = 1; spec.m_nDepth = 1; spec.m_Reflectivity.Init( 1, 1, 1 ); int nLowResWidth = (int)( viewport.m_nWidth * m_flLowResBufferScale ); int nLowResHeight = (int)( viewport.m_nHeight * m_flLowResBufferScale ); ImageFormat ssaoFormat = IMAGE_FORMAT_A8; if ( g_nPlatform == RST_PLATFORM_DX11 ) ssaoFormat = IMAGE_FORMAT_RGBA8888; switch ( type ) { case DS_SHADOW_DEPTH0: case DS_SHADOW_DEPTH1: case DS_SHADOW_DEPTH2: { spec.m_nWidth = m_nShadowSize; spec.m_nHeight = m_nShadowSize; spec.m_nFlags = TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_D24X8/*IMAGE_FORMAT_D16*/; } break; case DS_SHADOW_DEPTH_MULTIPLE: { spec.m_nWidth = m_nShadowSize; spec.m_nHeight = m_nShadowSize; spec.m_nFlags = TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_D24X8/*IMAGE_FORMAT_D16*/; } break; case RT_SHADOW_MULTIPLE_0: case RT_SHADOW_MULTIPLE_1: case RT_SHADOW_BLUR_TEMP: { spec.m_nWidth = m_nShadowSize; spec.m_nHeight = m_nShadowSize; spec.m_nFlags = TSPEC_RENDER_TARGET; spec.m_nImageFormat = IMAGE_FORMAT_RG1616F; } break; case DS_DEPTH_HIGHRES: { spec.m_nWidth = viewport.m_nWidth; spec.m_nHeight = viewport.m_nHeight; spec.m_nFlags = TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_D24S8; } break; case RT_VIEW_DEPTH_HIGHRES: { spec.m_nWidth = viewport.m_nWidth; spec.m_nHeight = viewport.m_nHeight; spec.m_nFlags = TSPEC_RENDER_TARGET | TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_R32F; } break; case RT_VIEW_NORMAL_HIGHRES: { spec.m_nWidth = viewport.m_nWidth; spec.m_nHeight = viewport.m_nHeight; spec.m_nFlags = TSPEC_RENDER_TARGET | TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_RGBA1010102; } break; case RT_VIEW_SPEC_HIGHRES: { spec.m_nWidth = viewport.m_nWidth; spec.m_nHeight = viewport.m_nHeight; spec.m_nFlags = TSPEC_RENDER_TARGET | TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_BGRA8888; if ( g_nPlatform == RST_PLATFORM_DX11 ) { spec.m_nImageFormat = IMAGE_FORMAT_RGBA8888; } } break; case RT_LIGHTING_HIGHRES: { spec.m_nWidth = viewport.m_nWidth; spec.m_nHeight = viewport.m_nHeight; spec.m_nFlags = TSPEC_RENDER_TARGET | TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_RGBA16161616F; /* if ( g_nPlatform == RST_PLATFORM_DX11 ) { spec.m_nImageFormat = IMAGE_FORMAT_RGBA8888; } */ } break; case RT_SPECULAR_HIGHRES: { spec.m_nWidth = viewport.m_nWidth; spec.m_nHeight = viewport.m_nHeight; spec.m_nFlags = TSPEC_RENDER_TARGET | TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_BGRA8888; if ( g_nPlatform == RST_PLATFORM_DX11 ) { spec.m_nImageFormat = IMAGE_FORMAT_RGBA8888; } } break; case DS_DEPTH_LOWRES: { spec.m_nWidth = nLowResWidth; spec.m_nHeight = nLowResHeight; spec.m_nFlags = 0; spec.m_nImageFormat = IMAGE_FORMAT_D24S8; } break; case RT_VIEW_DEPTH_LOWRES: { spec.m_nWidth = nLowResWidth; spec.m_nHeight = nLowResHeight; spec.m_nFlags = TSPEC_RENDER_TARGET | TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_R32F; } break; case RT_VIEW_NORMAL_LOWRES: { spec.m_nWidth = nLowResWidth; spec.m_nHeight = nLowResHeight; spec.m_nFlags = TSPEC_RENDER_TARGET | TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_RGBA1010102; } break; case RT_LIGHTING_LOWRES: { spec.m_nWidth = nLowResWidth; spec.m_nHeight = nLowResHeight; spec.m_nFlags = TSPEC_RENDER_TARGET | TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_BGRA8888; if ( g_nPlatform == RST_PLATFORM_DX11 ) { spec.m_nImageFormat = IMAGE_FORMAT_RGBA8888; } } break; case RT_LIGHTING_TEMP_LOWRES: { spec.m_nWidth = nLowResWidth; spec.m_nHeight = nLowResHeight; spec.m_nFlags = TSPEC_RENDER_TARGET | TSPEC_UNFILTERABLE_OK | TSPEC_RENDER_TARGET_SAMPLEABLE; spec.m_nImageFormat = IMAGE_FORMAT_BGRA8888; if ( g_nPlatform == RST_PLATFORM_DX11 ) { spec.m_nImageFormat = IMAGE_FORMAT_RGBA8888; } } break; default: return RENDER_TEXTURE_HANDLE_INVALID; } char pResourceName[16]; Q_snprintf( pResourceName, sizeof(pResourceName), "%d", g_nMagicNumber ); ++g_nMagicNumber; hRetHandle = g_pRenderDevice->FindOrCreateTexture( "worldrenderer", pResourceName, &spec ); return hRetHandle; } RenderTargetBinding_t CWorldRendererTest::CreateRenderTargetBinding( ViewBindingType_t type, const RenderViewport_t &viewport ) { RenderTargetBinding_t hRetHandle = RENDER_TARGET_BINDING_INVALID; HRenderTexture pRenderTargets[ 4 ] = { RENDER_TEXTURE_HANDLE_INVALID, RENDER_TEXTURE_HANDLE_INVALID, RENDER_TEXTURE_HANDLE_INVALID, RENDER_TEXTURE_HANDLE_INVALID }; HRenderTexture hDepthStencil; int nTargets = 0; int nFlags = 0; RenderViewport_t lowResViewport = viewport; lowResViewport.m_nWidth = (int)( viewport.m_nWidth * m_flLowResBufferScale ); lowResViewport.m_nHeight = (int)( viewport.m_nHeight * m_flLowResBufferScale ); CWorldRenderFrustum *pFrustum = NULL; RenderViewport_t targetViewport; int nViewFlags = VIEW_PLAYER_CAMERA; int nViewPass = 0; switch ( type ) { case RTB_SHADOW_DEPTH0: case RTB_SHADOW_DEPTH1: case RTB_SHADOW_DEPTH2: { nTargets = 1; pRenderTargets[0] = m_pRenderTargets[ RT_SHADOW_MULTIPLE_0 ]; hDepthStencil = m_pRenderTargets[ type - DS_SHADOW_DEPTH0 ]; nFlags = DISCARD_CONTENTS; pFrustum = m_pSplitFrustums[ type - DS_SHADOW_DEPTH0 ]; targetViewport = m_shadowViewport; nViewFlags = VIEW_LIGHT_SHADOW; nViewPass = VARIATION_DEPTH; } break; case RTB_SHADOW_DEPTH_MULTIPLE_0: case RTB_SHADOW_DEPTH_MULTIPLE_1: case RTB_SHADOW_DEPTH_MULTIPLE_2: case RTB_SHADOW_DEPTH_MULTIPLE_3: case RTB_SHADOW_DEPTH_MULTIPLE_4: case RTB_SHADOW_DEPTH_MULTIPLE_5: case RTB_SHADOW_DEPTH_MULTIPLE_6: case RTB_SHADOW_DEPTH_MULTIPLE_7: case RTB_SHADOW_DEPTH_MULTIPLE_8: case RTB_SHADOW_DEPTH_MULTIPLE_9: case RTB_SHADOW_DEPTH_MULTIPLE_10: case RTB_SHADOW_DEPTH_MULTIPLE_11: case RTB_SHADOW_DEPTH_MULTIPLE_12: case RTB_SHADOW_DEPTH_MULTIPLE_13: case RTB_SHADOW_DEPTH_MULTIPLE_14: case RTB_SHADOW_DEPTH_MULTIPLE_15: case RTB_SHADOW_DEPTH_MULTIPLE_16: case RTB_SHADOW_DEPTH_MULTIPLE_17: case RTB_SHADOW_DEPTH_MULTIPLE_18: case RTB_SHADOW_DEPTH_MULTIPLE_19: case RTB_SHADOW_DEPTH_MULTIPLE_20: case RTB_SHADOW_DEPTH_MULTIPLE_21: case RTB_SHADOW_DEPTH_MULTIPLE_22: case RTB_SHADOW_DEPTH_MULTIPLE_23: case RTB_SHADOW_DEPTH_MULTIPLE_24: case RTB_SHADOW_DEPTH_MULTIPLE_25: case RTB_SHADOW_DEPTH_MULTIPLE_26: case RTB_SHADOW_DEPTH_MULTIPLE_27: case RTB_SHADOW_DEPTH_MULTIPLE_28: case RTB_SHADOW_DEPTH_MULTIPLE_29: case RTB_SHADOW_DEPTH_MULTIPLE_30: case RTB_SHADOW_DEPTH_MULTIPLE_31: { int nFrustum = type - RTB_SHADOW_DEPTH_MULTIPLE_0; nTargets = 1; if ( nFrustum < NUM_HIGH_RES_SHADOWS ) pRenderTargets[0] = m_pRenderTargets[ RT_SHADOW_MULTIPLE_0 ]; else pRenderTargets[0] = m_pRenderTargets[ RT_SHADOW_MULTIPLE_1 ]; hDepthStencil = m_pRenderTargets[ DS_SHADOW_DEPTH_MULTIPLE ]; nFlags = PRESERVE_DEPTHSTENCIL;//DISCARD_CONTENTS; if ( nFrustum < NUM_MULTI_SHADOWS ) { pFrustum = m_pMultiShadowFrustums[ nFrustum ]; targetViewport = m_multiShadowViewport[ nFrustum ]; } else { pFrustum = NULL; targetViewport = viewport; } nViewFlags = VIEW_LIGHT_SHADOW; nViewPass = VARIATION_DEPTH; } break; case RTB_DEFERRED_DEPTH_NORM_SPEC: { nTargets = 3; pRenderTargets[0] = m_pRenderTargets[ RT_VIEW_NORMAL_HIGHRES ]; pRenderTargets[1] = m_pRenderTargets[ RT_VIEW_DEPTH_HIGHRES ]; pRenderTargets[2] = m_pRenderTargets[ RT_VIEW_SPEC_HIGHRES ]; hDepthStencil = m_pRenderTargets[ DS_DEPTH_HIGHRES ]; nFlags = DISCARD_CONTENTS; pFrustum = m_pFrustum; targetViewport = viewport; nViewFlags = VIEW_PLAYER_CAMERA; nViewPass = VARIATION_NORM_DEPTH_SPEC; } break; case RTB_DEFERRED_SCALE_DOWN: { nTargets = 2; pRenderTargets[0] = m_pRenderTargets[ RT_VIEW_DEPTH_LOWRES ]; pRenderTargets[1] = m_pRenderTargets[ RT_VIEW_NORMAL_LOWRES ]; hDepthStencil = m_pRenderTargets[ DS_DEPTH_LOWRES ]; nFlags = PRESERVE_DEPTHSTENCIL; pFrustum = m_pFrustum; targetViewport = lowResViewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_POST_PROCESS; nViewPass = VARIATION_DEFAULT; } break; case RTB_DEFERRED_NORM_SPEC: { nTargets = 2; pRenderTargets[0] = m_pRenderTargets[ RT_VIEW_NORMAL_HIGHRES ]; pRenderTargets[1] = m_pRenderTargets[ RT_VIEW_SPEC_HIGHRES ]; hDepthStencil = m_pRenderTargets[ DS_DEPTH_HIGHRES ]; nFlags = PRESERVE_CONTENTS; pFrustum = m_pFrustum; targetViewport = viewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_DECALS; nViewPass = 0; } break; case RTB_CLEAR_SPEC_HIGHRES: { nTargets = 1; pRenderTargets[0] = m_pRenderTargets[ RT_SPECULAR_HIGHRES ]; hDepthStencil = RENDER_TEXTURE_HANDLE_INVALID; nFlags = 0; pFrustum = m_pFrustum; targetViewport = viewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_LIGHTING; nViewPass = VARIATION_DEFAULT; } break; case RTB_LIGHTING_HIGHRES: { nTargets = 2; pRenderTargets[0] = m_pRenderTargets[ RT_LIGHTING_HIGHRES ]; pRenderTargets[1] = m_pRenderTargets[ RT_SPECULAR_HIGHRES ]; hDepthStencil = m_pRenderTargets[ DS_DEPTH_HIGHRES ]; nFlags = PRESERVE_DEPTHSTENCIL; pFrustum = m_pFrustum; targetViewport = viewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_LIGHTING; nViewPass = VARIATION_DEFAULT; } break; case RTB_LIGHTING_LOWRES: { nTargets = 1; pRenderTargets[0] = m_pRenderTargets[ RT_LIGHTING_LOWRES ]; hDepthStencil = m_pRenderTargets[ DS_DEPTH_LOWRES ]; nFlags = PRESERVE_DEPTHSTENCIL; pFrustum = m_pFrustum; targetViewport = lowResViewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_LIGHTING; nViewPass = VARIATION_DEFAULT; } break; case RTB_SSAO_LOWRES: { nTargets = 1; pRenderTargets[0] = m_pRenderTargets[ RT_LIGHTING_LOWRES ]; hDepthStencil = RENDER_TEXTURE_HANDLE_INVALID; nFlags = 0; pFrustum = NULL; targetViewport = lowResViewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_POST_PROCESS; nViewPass = VARIATION_DEFAULT; } break; case RTB_BILAT_UPSAMPLE_0: { nTargets = 1; pRenderTargets[0] = m_pRenderTargets[ RT_LIGHTING_TEMP_LOWRES ]; hDepthStencil = RENDER_TEXTURE_HANDLE_INVALID; nFlags = 0; pFrustum = NULL; targetViewport = lowResViewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_POST_PROCESS; nViewPass = VARIATION_DEFAULT; } break; case RTB_BILAT_UPSAMPLE_1: { nTargets = 1; pRenderTargets[0] = m_pRenderTargets[ RT_LIGHTING_HIGHRES ]; hDepthStencil = RENDER_TEXTURE_HANDLE_INVALID; nFlags = 0; pFrustum = NULL; targetViewport = viewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_POST_PROCESS; nViewPass = VARIATION_DEFAULT; } break; case RTB_LIGHT_BLUR_0: { nTargets = 1; pRenderTargets[0] = m_pRenderTargets[ RT_VIEW_SPEC_HIGHRES ]; hDepthStencil = RENDER_TEXTURE_HANDLE_INVALID; nFlags = 0; pFrustum = NULL; targetViewport = viewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_POST_PROCESS; nViewPass = VARIATION_DEFAULT; } break; case RTB_LIGHT_BLUR_1: { nTargets = 1; pRenderTargets[0] = m_pRenderTargets[ RT_LIGHTING_HIGHRES ]; hDepthStencil = RENDER_TEXTURE_HANDLE_INVALID; nFlags = 0; pFrustum = NULL; targetViewport = viewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_POST_PROCESS; nViewPass = VARIATION_DEFAULT; } break; case RTB_SHADOW_BLUR_0: { nTargets = 1; pRenderTargets[0] = m_pRenderTargets[ RT_SHADOW_BLUR_TEMP ]; hDepthStencil = RENDER_TEXTURE_HANDLE_INVALID; nFlags = 0; pFrustum = NULL; targetViewport = m_shadowViewport; nViewFlags = VIEW_LIGHT_SHADOW | VIEW_POST_PROCESS; nViewPass = VARIATION_DEFAULT; } break; case RTB_SHADOW_BLUR_1: { nTargets = 1; pRenderTargets[0] = m_pRenderTargets[ RT_SHADOW_MULTIPLE_0 ]; hDepthStencil = RENDER_TEXTURE_HANDLE_INVALID; nFlags = 0; pFrustum = NULL; targetViewport = m_shadowViewport; nViewFlags = VIEW_LIGHT_SHADOW | VIEW_POST_PROCESS; nViewPass = VARIATION_DEFAULT; } break; case RTB_SHADOW_BLUR_2: { nTargets = 1; pRenderTargets[0] = m_pRenderTargets[ RT_SHADOW_MULTIPLE_1 ]; hDepthStencil = RENDER_TEXTURE_HANDLE_INVALID; nFlags = 0; pFrustum = NULL; targetViewport = m_shadowViewport; nViewFlags = VIEW_LIGHT_SHADOW | VIEW_POST_PROCESS; nViewPass = VARIATION_DEFAULT; } break; case RTB_SAMPLE_LIGHTING: { nTargets = 1; pRenderTargets[0] = RENDER_TEXTURE_DEFAULT_RENDER_TARGET; hDepthStencil = m_pRenderTargets[ DS_DEPTH_HIGHRES ]; nFlags = PRESERVE_DEPTHSTENCIL; pFrustum = m_pFrustum; targetViewport = viewport; nViewFlags = VIEW_PLAYER_CAMERA; nViewPass = VARIATION_SAMPLE_LIGHTING; } break; case RTB_AERIAL_PERSPECTIVE: { nTargets = 1; pRenderTargets[0] = RENDER_TEXTURE_DEFAULT_RENDER_TARGET; hDepthStencil = m_pRenderTargets[ DS_DEPTH_HIGHRES ]; nFlags = PRESERVE_DEPTHSTENCIL; pFrustum = NULL; targetViewport = viewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_POST_PROCESS; nViewPass = VARIATION_DEFAULT; } break; case RTB_SKY: { nTargets = 1; pRenderTargets[0] = RENDER_TEXTURE_DEFAULT_RENDER_TARGET; hDepthStencil = m_pRenderTargets[ DS_DEPTH_HIGHRES ]; nFlags = PRESERVE_DEPTHSTENCIL; pFrustum = m_pFrustum; targetViewport = viewport; nViewFlags = VIEW_PLAYER_CAMERA | VIEW_POST_PROCESS; nViewPass = VARIATION_DEFAULT; } break; case RTB_FORWARD: { nTargets = 1; pRenderTargets[0] = RENDER_TEXTURE_DEFAULT_RENDER_TARGET; hDepthStencil = RENDER_TEXTURE_DEFAULT_RENDER_TARGET; nFlags = PRESERVE_DEPTHSTENCIL; pFrustum = m_pFrustum; targetViewport = viewport; nViewFlags = VIEW_PLAYER_CAMERA; nViewPass = VARIATION_DEFAULT; } break; default: return RENDER_TARGET_BINDING_INVALID; } hRetHandle = g_pRenderDevice->CreateRenderTargetBinding( nFlags, nTargets, pRenderTargets, hDepthStencil ); m_pRenderViews[ type ].Init( g_pRenderDevice, pFrustum, hRetHandle, targetViewport, (RenderViewFlags_t)nViewFlags, nViewPass, type ); return hRetHandle; } void CWorldRendererTest::SetStateForRenderViewType( IRenderContext *pRenderContext, int nRenderView ) { switch ( nRenderView ) { case RTB_SHADOW_DEPTH0: case RTB_SHADOW_DEPTH1: case RTB_SHADOW_DEPTH2: { pRenderContext->SetBlendMode( RENDER_BLEND_NOPIXELWRITE ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_AND_WRITE ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_NONE ); } break; case RTB_SHADOW_DEPTH_MULTIPLE_0: case RTB_SHADOW_DEPTH_MULTIPLE_1: case RTB_SHADOW_DEPTH_MULTIPLE_2: case RTB_SHADOW_DEPTH_MULTIPLE_3: case RTB_SHADOW_DEPTH_MULTIPLE_4: case RTB_SHADOW_DEPTH_MULTIPLE_5: case RTB_SHADOW_DEPTH_MULTIPLE_6: case RTB_SHADOW_DEPTH_MULTIPLE_7: case RTB_SHADOW_DEPTH_MULTIPLE_8: case RTB_SHADOW_DEPTH_MULTIPLE_9: case RTB_SHADOW_DEPTH_MULTIPLE_10: case RTB_SHADOW_DEPTH_MULTIPLE_11: case RTB_SHADOW_DEPTH_MULTIPLE_12: case RTB_SHADOW_DEPTH_MULTIPLE_13: case RTB_SHADOW_DEPTH_MULTIPLE_14: case RTB_SHADOW_DEPTH_MULTIPLE_15: case RTB_SHADOW_DEPTH_MULTIPLE_16: case RTB_SHADOW_DEPTH_MULTIPLE_17: case RTB_SHADOW_DEPTH_MULTIPLE_18: case RTB_SHADOW_DEPTH_MULTIPLE_19: case RTB_SHADOW_DEPTH_MULTIPLE_20: case RTB_SHADOW_DEPTH_MULTIPLE_21: case RTB_SHADOW_DEPTH_MULTIPLE_22: case RTB_SHADOW_DEPTH_MULTIPLE_23: case RTB_SHADOW_DEPTH_MULTIPLE_24: case RTB_SHADOW_DEPTH_MULTIPLE_25: case RTB_SHADOW_DEPTH_MULTIPLE_26: case RTB_SHADOW_DEPTH_MULTIPLE_27: case RTB_SHADOW_DEPTH_MULTIPLE_28: case RTB_SHADOW_DEPTH_MULTIPLE_29: case RTB_SHADOW_DEPTH_MULTIPLE_30: case RTB_SHADOW_DEPTH_MULTIPLE_31: { pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_AND_WRITE ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); } break; case RTB_DEFERRED_DEPTH_NORM_SPEC: { pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_AND_WRITE_STENCIL_SET1 ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); } break; case RTB_DEFERRED_SCALE_DOWN: { } break; case RTB_DEFERRED_NORM_SPEC: { } break; case RTB_LIGHTING_HIGHRES: { } break; case RTB_LIGHTING_LOWRES: { } break; case RTB_SSAO_LOWRES: { } break; case RTB_BILAT_UPSAMPLE_0: { } break; case RTB_BILAT_UPSAMPLE_1: { } break; case RTB_LIGHT_BLUR_0: { } break; case RTB_LIGHT_BLUR_1: { } break; case RTB_SAMPLE_LIGHTING: { pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_EQUAL_NO_WRITE ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); pRenderContext->BindTexture( 4, m_pRenderTargets[ RT_LIGHTING_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 4, RS_FILTER_MIN_MAG_MIP_POINT ); pRenderContext->BindTexture( 5, m_pRenderTargets[ RT_SPECULAR_HIGHRES ] ); pRenderContext->SetSamplerStatePS( 5, RS_FILTER_MIN_MAG_MIP_POINT ); } break; case RTB_AERIAL_PERSPECTIVE: { } break; case RTB_SKY: { } break; case RTB_FORWARD: { // viewport and state pRenderContext->SetBlendMode( RENDER_BLEND_NONE ); pRenderContext->SetZBufferMode( RENDER_ZBUFFER_ZTEST_AND_WRITE ); pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_BACKFACING ); // Bind for ( int s=0; sBindTexture( 4 + s, m_pRenderTargets[ DS_SHADOW_DEPTH0 + s ] ); pRenderContext->SetSamplerStatePS( 4 + s, RS_FILTER_MIN_MAG_MIP_POINT ); } pRenderContext->SetConstantBufferData( m_hLightingRelated, (void*)&m_forwardLightingData, sizeof( LightingConstants_t ) ); pRenderContext->BindConstantBuffer( RENDER_PIXEL_SHADER, m_hLightingRelated, 0, 0 ); } break; } } void CWorldRendererTest::InitRenderTargetsAndViews( const RenderViewport_t &viewport ) { for ( int i=0; i 0 && m_nWindowCenterY > 0 ) { m_nCursorDeltaX += ie.m_nData2 - m_nWindowCenterX; m_nCursorDeltaY += ie.m_nData3 - m_nWindowCenterY; } break; case JOYSTICK_AXIS( 0, JOY_AXIS_U ): m_nCursorDeltaResetX = ie.m_nData2 / 300; m_nCursorDeltaX += m_nCursorDeltaResetX; break; case JOYSTICK_AXIS( 0, JOY_AXIS_R ): m_nCursorDeltaResetY = -ie.m_nData2 / 300; m_nCursorDeltaY += m_nCursorDeltaResetY; break; case JOYSTICK_AXIS( 0, JOY_AXIS_X ): if ( abs( ie.m_nData2 ) < 2 ) { m_cmd.m_nKeys &= ~FKEY_RIGHT; m_cmd.m_nKeys &= ~FKEY_LEFT; } else if ( ie.m_nData2 > 0 ) { m_cmd.m_nKeys |= FKEY_RIGHT; m_cmd.m_nKeys &= ~FKEY_LEFT; } else { m_cmd.m_nKeys &= ~FKEY_RIGHT; m_cmd.m_nKeys |= FKEY_LEFT; } break; case JOYSTICK_AXIS( 0, JOY_AXIS_Y ): if ( abs( ie.m_nData2 ) < 2 ) { m_cmd.m_nKeys &= ~FKEY_FORWARD; m_cmd.m_nKeys &= ~FKEY_BACK; } else if ( ie.m_nData2 > 0 ) { m_cmd.m_nKeys |= FKEY_FORWARD; m_cmd.m_nKeys &= ~FKEY_BACK; } else { m_cmd.m_nKeys &= ~FKEY_FORWARD; m_cmd.m_nKeys |= FKEY_BACK; } break; } } else if ( ie.m_nType == IE_ButtonPressed || ie.m_nType == IE_ButtonReleased ) { bool bDown = (ie.m_nType == IE_ButtonPressed) ? true : false; ButtonCode_t code = (ButtonCode_t)ie.m_nData; uint nFlag = 0; switch( code ) { case KEY_W: nFlag = FKEY_FORWARD; break; case KEY_S: nFlag = FKEY_BACK; break; case KEY_A: nFlag = FKEY_LEFT; break; case KEY_D: nFlag = FKEY_RIGHT; break; case KEY_UP: nFlag = FKEY_TURNUP; break; case KEY_DOWN: nFlag = FKEY_TURNDOWN; break; case KEY_LEFT: nFlag = FKEY_TURNLEFT; break; case KEY_RIGHT: nFlag = FKEY_TURNRIGHT; break; case KEY_XBUTTON_X: case MOUSE_LEFT: nFlag = FKEY_SHOOTDECAL; break; case KEY_XBUTTON_B: case KEY_N: nFlag = FKEY_SHOOTPSYSTEM; break; case KEY_XBUTTON_Y: case KEY_M: nFlag = FKEY_SHOOTSSYSTEM; break; case KEY_O: nFlag = FKEY_LIGHTELV; break; case KEY_XBUTTON_UP: case KEY_K: nFlag = FKEY_LIGHTANG_POS; break; case KEY_XBUTTON_DOWN: case KEY_L: nFlag = FKEY_LIGHTANG_NEG; break; case KEY_XBUTTON_LEFT_SHOULDER: case KEY_LSHIFT: nFlag = FKEY_FAST; break; case KEY_HOME: nFlag = FKEY_ENABLE_VIS; break; case KEY_END: nFlag = FKEY_DISABLE_VIS; break; case KEY_RSHIFT: nFlag = FKEY_DROP_FRUSTUM; break; case KEY_P: nFlag = FKEY_TOGGLE_AERIAL; break; case KEY_V: nFlag = FKEY_TOGGLE_BOUNCE; break; case KEY_C: nFlag = FKEY_TOGGLE_DIRECT; break; case KEY_B: nFlag = FKEY_TOGGLE_LIGHTING_ONLY; break; case KEY_PAD_ENTER: nFlag = FKEY_SSAO; break; case KEY_PAD_8: nFlag = FKEY_BLUR_LIGHTING; break; case KEY_PAD_9: nFlag = FKEY_BLUR_SHADOWS; break; case MOUSE_RIGHT: nFlag = FKEY_SHOOTDECAL2; break; case MOUSE_MIDDLE: nFlag = FKEY_SHOOTWALLMONSTER; break; case KEY_X: { if ( !bDown ) { m_bViewLowTexture = !m_bViewLowTexture; if ( m_bViewLowTexture ) Msg( "Low Texture Mode: On\n" ); else Msg( "Low Texture Mode: Off\n" ); } break; } case KEY_F: { if ( !bDown ) { m_bFlashlight = !m_bFlashlight; if ( m_bFlashlight ) Msg( "Flashlight: On\n" ); else Msg( "Flashlight: Off\n" ); } break; } case KEY_G: { if ( !bDown ) { Msg( "Dropped Renderable\n" ); DropRenderable(); } break; } case KEY_0: { // Reload shaders if ( ie.m_nType == IE_ButtonPressed ) { g_pMaterialSystem2->DynamicShaderCompile_ReloadAllShaders(); return false; } break; } case KEY_PAD_PLUS: { m_flSampleRadius += 1.0f; Msg( "SSAO Sample Radius: %f\n", m_flSampleRadius ); break; } case KEY_PAD_MINUS: { m_flSampleRadius -= 1.0f; m_flSampleRadius = MAX( 1, m_flSampleRadius ); Msg( "SSAO Sample Radius: %f\n", m_flSampleRadius ); break; } case KEY_PAD_DIVIDE: { if ( !bDown ) { m_nViewBuffer = (RenderTargetType_t)( m_nViewBuffer + 1 ); if ( m_nViewBuffer >= MAX_RENDER_TARGET_TYPES ) { m_nViewBuffer = (RenderTargetType_t)0; } Msg( "%s\n", g_pRenderTargetName[ m_nViewBuffer ] ); } break; } case KEY_PAD_MULTIPLY: { if ( !bDown ) { m_nViewBuffer = (RenderTargetType_t)( m_nViewBuffer - 1 ); if ( m_nViewBuffer < 0 ) { m_nViewBuffer = (RenderTargetType_t)( MAX_RENDER_TARGET_TYPES - 1 ); } Msg( "%s\n", g_pRenderTargetName[ m_nViewBuffer ] ); } break; } case KEY_TAB: { m_nReportLevel = bDown ? 1 : 3; break; } case KEY_Z: { if ( !bDown ) { Vector vCameraOrigin( 100, 24975, 250 ); QAngle vCameraAngles( 9.6, -27, 0 ); m_pFrustum->SetCameraPosition( vCameraOrigin ); m_pFrustum->SetCameraAngles( vCameraAngles ); m_pWorldRenderer->ClearOutstandingLoadRequests(); } } break; } if ( nFlag ) { if ( bDown ) { m_cmd.m_nKeys |= nFlag; } else { m_cmd.m_nKeys &= ~nFlag; } return false; } } return BaseClass::ProcessUserInput( ie ); } static void PerformWorkUnit( SimulateWorkUnitWorldRender_t & job ) { for( int i =0; i < job.m_nNumSystems; i++ ) { job.m_pParticles->Simulate( job.m_flTimeStep ); } } void CWorldRendererTest::SimulateParticles( float flTimeStep ) { int nSystems = m_particleWorkUnits.Count(); for( int i = 0; i < nSystems; i++ ) { m_particleWorkUnits[i].m_flTimeStep = flTimeStep; } ParallelProcess( m_particleWorkUnits.Base(), nSystems, PerformWorkUnit ); }