You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5750 lines
193 KiB
5750 lines
193 KiB
//=========== (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<CStaticMeshRenderable> &renderableList, CUtlVector<CDynamicRenderable> &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<CPointLightRenderable> &lightVector, bool bInterior );
|
|
void RenderSceneHemiLights( IRenderContext *pRenderContext, CUtlVector<CHemiLightRenderable> &lightVector, bool bInterior );
|
|
void RenderSceneSpotLights( IRenderContext *pRenderContext, CUtlVector<CSpotLightRenderable> &lightVector, bool bInterior );
|
|
void RenderShadowedSpotLights( IRenderContext *pRenderContext, CUtlVector<CSpotLightRenderable> &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<IBVHNode*> m_renderList;
|
|
CUtlVector<CStaticMeshRenderable> m_renderableList;
|
|
CUtlVector<CDynamicRenderable> m_dynRenderableList;
|
|
CUtlVector<CPointLightRenderable> m_exteriorPointLights;
|
|
CUtlVector<CPointLightRenderable> m_interiorPointLights;
|
|
CUtlVector<CSpotLightRenderable> m_exteriorSpotLights;
|
|
CUtlVector<CSpotLightRenderable> m_interiorSpotLights;
|
|
CUtlVector<CHemiLightRenderable> m_exteriorHemiLights;
|
|
CUtlVector<CHemiLightRenderable> m_interiorHemiLights;
|
|
CUtlVector<CSpotLightRenderable> 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<CParticleCollection*> m_lightSystemList;
|
|
CUtlVector<CParticleCollection*> m_sphereSystemList;
|
|
CUtlVector<SimulateWorkUnitWorldRender_t> 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<NUM_SHADOW_SPLITS; ++s )
|
|
{
|
|
m_pSplitFrustums[s] = (CWorldRenderFrustum*)MemAlloc_AllocAligned( sizeof( CWorldRenderFrustum ), 16 );
|
|
}
|
|
|
|
// Alloc multi-shadow frustums
|
|
for ( int s=0; s<NUM_MULTI_SHADOWS; ++s )
|
|
{
|
|
m_pMultiShadowFrustums[s] = (CWorldRenderFrustum*)MemAlloc_AllocAligned( sizeof( CWorldRenderFrustum ), 16 );
|
|
}
|
|
|
|
// Build up a frustum
|
|
m_pFrustum = (CWorldRenderFrustum*)MemAlloc_AllocAligned( sizeof( CWorldRenderFrustum ), 16 );
|
|
m_pDropFrustum = (CWorldRenderFrustum*)MemAlloc_AllocAligned( sizeof( CWorldRenderFrustum ), 16 );
|
|
|
|
m_nLastFrustumWidth = 1024;
|
|
m_nLastFrustumHeight = 768;
|
|
float flFOVY = 90.0f;
|
|
float flAspect = m_nLastFrustumWidth / (float)m_nLastFrustumHeight;
|
|
|
|
// Find the player start
|
|
Vector vEyePos( 0, 0, 0 );
|
|
QAngle vAngles( -64, 90, 0 );
|
|
|
|
CUtlVector< KeyValues* > 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; d<m_nMaxDecals; ++d )
|
|
{
|
|
for ( int i=0; i<36; ++i )
|
|
{
|
|
pIndices[i] = g_pBoxIndices[i] + nOffset;
|
|
}
|
|
nOffset += 8;
|
|
pIndices += 36;
|
|
}
|
|
pRenderContext->UnlockIndexBuffer( 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; s<NUM_SHADOW_SPLITS; ++s )
|
|
{
|
|
MemAlloc_FreeAligned( m_pSplitFrustums[s] );
|
|
}
|
|
for ( int s=0; s<NUM_MULTI_SHADOWS; ++s )
|
|
{
|
|
MemAlloc_FreeAligned( m_pMultiShadowFrustums[s] );
|
|
}
|
|
|
|
MemAlloc_FreeAligned( m_pFrustum );
|
|
}
|
|
|
|
|
|
class CUniformSampler
|
|
{
|
|
private:
|
|
Vector* m_pvDirections;
|
|
int m_NumSamples;
|
|
int m_NumVariations;
|
|
|
|
public:
|
|
CUniformSampler() :
|
|
m_pvDirections( NULL ),
|
|
m_NumSamples( 0 ),
|
|
m_NumVariations( 0 )
|
|
{
|
|
}
|
|
~CUniformSampler()
|
|
{
|
|
if ( m_pvDirections ) { delete []m_pvDirections; };
|
|
}
|
|
|
|
int GetNumVariations() { return m_NumVariations; }
|
|
int GetNumSamples() { return m_NumSamples; }
|
|
bool InitSamples( int SqrtNumSamples, int NumVariations );
|
|
Vector GetSampleDirection( int Sample, int Variation );
|
|
};
|
|
|
|
|
|
bool CUniformSampler::InitSamples( int SqrtNumSamples, int NumVariations )
|
|
{
|
|
m_NumSamples = SqrtNumSamples * SqrtNumSamples;
|
|
m_NumVariations = NumVariations;
|
|
|
|
m_pvDirections = new Vector[ m_NumSamples * m_NumVariations ];
|
|
if ( !m_pvDirections )
|
|
return false;
|
|
#if 1
|
|
int i=0; // array index
|
|
float oneoverN = 1.0f/(float)SqrtNumSamples;
|
|
|
|
for ( int n=0; n<m_NumVariations; n++ )
|
|
{
|
|
// fill an N*N*2 array with uniformly distributed
|
|
// samples across the sphere using jittered stratification
|
|
for ( int a=0; a<SqrtNumSamples; a++ )
|
|
{
|
|
for ( int b=0; b<SqrtNumSamples; b++ )
|
|
{
|
|
// generate unbiased distribution of spherical coords
|
|
float x = ( a + fabs( RPercent() ) ) * oneoverN; // do not reuse results
|
|
float y = ( b + fabs( RPercent() ) ) * oneoverN; // each sample must be random
|
|
float theta = 2.0f * acosf(sqrtf(1.0f - x));
|
|
float phi = 2.0f * M_PI * y;
|
|
|
|
// convert spherical coords to unit vector
|
|
Vector vec(sinf(theta)*cosf(phi), sinf(theta)*sinf(phi), cosf(theta));
|
|
m_pvDirections[i] = vec;
|
|
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
int i=0;
|
|
for ( int n=0; n<m_NumVariations; n++ )
|
|
{
|
|
// fill an N*N*2 array with uniformly distributed
|
|
// samples across the sphere using jittered stratification
|
|
for ( int a=0; a<SqrtNumSamples * SqrtNumSamples; a++ )
|
|
{
|
|
m_pvDirections[i].x = RPercent();
|
|
m_pvDirections[i].y = RPercent();
|
|
m_pvDirections[i].z = RPercent();
|
|
m_pvDirections[i].NormalizeInPlace();
|
|
i++;
|
|
}
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
Vector CUniformSampler::GetSampleDirection( int Sample, int Variation )
|
|
{
|
|
int Start = m_NumSamples * Variation;
|
|
return m_pvDirections[ Start + Sample ];
|
|
}
|
|
|
|
void CWorldRendererTest::InitDeferredData( const RenderViewport_t &viewport )
|
|
{
|
|
CRenderContextPtr pRenderContext( g_pRenderDevice );
|
|
|
|
static RenderInputLayoutField_t quadLayout[] =
|
|
{
|
|
DEFINE_PER_VERTEX_FIELD( 0, "position", 0, QuadVertex_t, m_vPos )
|
|
DEFINE_PER_VERTEX_FIELD( 0, "texcoord", 0, QuadVertex_t, m_vEyeRay )
|
|
};
|
|
m_hQuadLayout = g_pRenderDevice->CreateInputLayout( "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; s<NUM_SSAO_SAMPLES; ++s )
|
|
{
|
|
Vector vSample = ssaoSampler.GetSampleDirection( s, 0 );
|
|
//vSample *= 0.2f + 0.8f * RPercentABS();
|
|
vSample *= RPercentABS();
|
|
m_sphereSampleData.m_vSphereSamples[s].Init( vSample.x, vSample.y, vSample.z, 1 );
|
|
}
|
|
pRenderContext->SetConstantBufferData( 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; r<nTotalRands; ++r )
|
|
{
|
|
Vector vRandVector = randTexSampler.GetSampleDirection( r, 0 );
|
|
|
|
pRandBits[ r * 4 ] = (uint8)( ( vRandVector.z * 128.0f ) + 127 );
|
|
pRandBits[ r * 4 + 1 ] = (uint8)( ( vRandVector.y * 128.0f ) + 127 );
|
|
pRandBits[ r * 4 + 2 ] = (uint8)( ( vRandVector.x * 128.0f ) + 127 );
|
|
pRandBits[ r * 4 + 3 ] = 0;
|
|
}
|
|
|
|
pRenderContext->SetTextureData( 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<QuadVertex_t> 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<CStaticMeshRenderable> &renderableList, CUtlVector<CDynamicRenderable> &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; r<nRenderables; ++r )
|
|
{
|
|
CStaticMeshRenderable &renderable = renderableList[ r ];
|
|
|
|
IBVHNode *pNode = renderable.m_pNode;
|
|
Vector vOriginShift = pNode->GetOrigin().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; r<nRenderables; ++r )
|
|
{
|
|
CDynamicRenderable &renderable = dynList[ r ];
|
|
|
|
if ( !g_pMeshSystem->RenderableIntersectsFrustum( 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; t<nSqrtNumShadows; ++t )
|
|
{
|
|
int nLeft = 0;
|
|
for( int s=0; s<nSqrtNumShadows; ++s )
|
|
{
|
|
int nGutteredLeft = nLeft + nGutterSize;
|
|
int nGutteredTop = nTop + nGutterSize;
|
|
int nGutteredMultiShadowedSize = nMultiShadowSize - nGutterSize * 2;
|
|
m_multiShadowViewport[ nViewport ].Init( nGutteredLeft, nGutteredTop, nGutteredMultiShadowedSize, nGutteredMultiShadowedSize, 0, 1.0f );
|
|
|
|
float fBiasVal = flBias;
|
|
if ( IsPlatformX360() )
|
|
{
|
|
fBiasVal = 1.0f - flBias;
|
|
}
|
|
|
|
float flShiftX = flScale + ( nGutteredLeft + 0.5f ) / m_nShadowSize;
|
|
float flShiftY = flScale + ( nGutteredTop + 0.5f ) / m_nShadowSize;
|
|
|
|
VMatrix texScaleBiasMat( flScale, 0.0f, 0.0f, 0.0f,
|
|
0.0f, -flScale, 0.0f, 0.0f,
|
|
0.0f, 0.0f, frange, 0.0f,
|
|
flShiftX, flShiftY, fBiasVal, 1.0f );
|
|
|
|
m_multiShadowScaleBiasMatrices[ nViewport ] = texScaleBiasMat;
|
|
|
|
nViewport++;
|
|
nLeft += nMultiShadowSize;
|
|
}
|
|
nTop += nMultiShadowSize;
|
|
}
|
|
}
|
|
|
|
void CWorldRendererTest::SetupShadowMatrices()
|
|
{
|
|
// Multiple shadow viewports
|
|
float fOffsetX = 0.5f + (0.5f / (float)m_nShadowSize);
|
|
float fOffsetY = 0.5f + (0.5f / (float)m_nShadowSize);
|
|
float frange = 1.0f;
|
|
float fBias = -0.001f * frange;
|
|
if ( IsPlatformX360() )
|
|
{
|
|
frange = -1.0f;
|
|
fBias = 0.005f * frange;
|
|
}
|
|
|
|
for ( int s=0; s<NUM_SHADOW_SPLITS; ++s )
|
|
{
|
|
//set special texture matrix for shadow mapping
|
|
float fBiasVal = fBias;
|
|
if ( IsPlatformX360() )
|
|
{
|
|
fBiasVal = 1.0f - fBias;
|
|
}
|
|
|
|
VMatrix texScaleBiasMat( 0.5f, 0.0f, 0.0f, 0.0f,
|
|
0.0f, -0.5f, 0.0f, 0.0f,
|
|
0.0f, 0.0f, frange, 0.0f,
|
|
fOffsetX, fOffsetY, fBiasVal, 1.0f );
|
|
m_splitScaleBiasMatrices[ s ] = texScaleBiasMat;
|
|
|
|
fBias *= 1.5f;
|
|
}
|
|
|
|
SetupMultiShadowMatrices( 0, SQRT_NUM_HIGH_RES_SHADOWS, -0.001f );
|
|
if ( SQRT_NUM_LOW_RES_SHADOWS )
|
|
{
|
|
SetupMultiShadowMatrices( NUM_HIGH_RES_SHADOWS, SQRT_NUM_LOW_RES_SHADOWS, -0.003f );
|
|
}
|
|
}
|
|
|
|
int SortSpotLights( const CSpotLightRenderable *pOne, const CSpotLightRenderable *pTwo )
|
|
{
|
|
if ( pOne->m_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; n<nNodes; ++n )
|
|
{
|
|
IBVHNode *pNode = m_renderList[ n ];
|
|
Vector vOriginShift = pNode->GetOrigin().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; d<nDraws; ++d )
|
|
{
|
|
CBVHDrawCall &draw = pNode->GetDrawCall( 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<m_shadowedSpotLights.Count(); ++s )
|
|
{
|
|
if ( m_shadowedSpotLights[ s ].m_flSquaredDistToEye > 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; s<nShadows; ++s )
|
|
{
|
|
int index = m_exteriorSpotLights.Find( m_shadowedSpotLights[s] );
|
|
if ( index != -1 )
|
|
{
|
|
m_exteriorSpotLights.FastRemove( index );
|
|
}
|
|
|
|
index = m_interiorSpotLights.Find( m_shadowedSpotLights[s] );
|
|
if ( index != -1 )
|
|
{
|
|
m_interiorSpotLights.FastRemove( index );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CWorldRendererTest::GeneratePointLightRenderables( IBVHNode *pNode, Vector &vOrigin, CFrustum *pFrustum, Vector &vEye )
|
|
{
|
|
float flNearPlane = pFrustum->GetNearPlane();
|
|
int nLights = pNode->GetNumPointLights();
|
|
PointLightData_t *pPointLights = pNode->GetPointLights();
|
|
|
|
for ( int i=0; i<nLights; ++i )
|
|
{
|
|
float flRadius = pPointLights[i].m_vColorNRadius.w;
|
|
|
|
AABB_t bounds;
|
|
Vector vLightOrigin = pPointLights[i].m_vOrigin;
|
|
bounds.m_vMinBounds = vLightOrigin - Vector( flRadius, flRadius, flRadius );
|
|
bounds.m_vMaxBounds = vLightOrigin + Vector( flRadius, flRadius, flRadius );
|
|
|
|
if ( pFrustum->BoundingVolumeIntersectsFrustum( 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; i<nLights; ++i )
|
|
{
|
|
float flRadius = pSpotLights[i].m_vColorNRadius.w;
|
|
float flTargetRad = flRadius * 1.2f + 500.0f + flNearPlane;
|
|
Vector vLightOrigin = Vector( pSpotLights[i].m_vTransform0.w, pSpotLights[i].m_vTransform1.w, pSpotLights[i].m_vTransform2.w );
|
|
|
|
AABB_t bounds;
|
|
bounds.m_vMinBounds = vLightOrigin - Vector( flTargetRad, flTargetRad, flTargetRad );
|
|
bounds.m_vMaxBounds = vLightOrigin + Vector( flTargetRad, flTargetRad, flTargetRad );
|
|
|
|
if ( pFrustum->BoundingVolumeIntersectsFrustum( 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; i<nLights; ++i )
|
|
{
|
|
float flRadius = pHemiLights[i].m_vColorNRadius.w;
|
|
Vector vLightOrigin = Vector( pHemiLights[i].m_vTransform0.w, pHemiLights[i].m_vTransform1.w, pHemiLights[i].m_vTransform2.w );
|
|
AABB_t bounds;
|
|
bounds.m_vMinBounds = vLightOrigin - Vector( flRadius, flRadius, flRadius );
|
|
bounds.m_vMaxBounds = vLightOrigin + Vector( flRadius, flRadius, flRadius );
|
|
|
|
if ( pFrustum->BoundingVolumeIntersectsFrustum( 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; r<nCount; ++r )
|
|
{
|
|
CStaticMeshRenderable *pRenderable = renderableList[ nStart + r ];
|
|
|
|
IBVHNode *pNode = pRenderable->m_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; t<m_nRenderThreads; ++t )
|
|
{
|
|
m_pRenderJobs[ t ].m_pRenderView = &renderView;
|
|
m_pRenderJobs[ t ].m_nStartStatic = nTotalRenderablesStatic;
|
|
m_pRenderJobs[ t ].m_nCountStatic = nCountStatic;
|
|
m_pRenderJobs[ t ].m_nStartDynamic = nTotalRenderablesDynamic;
|
|
m_pRenderJobs[ t ].m_nCountDynamic = nCountDynamic;
|
|
|
|
m_pRenderJobs[ t ].m_pTestApp = this;
|
|
m_pRenderJobs[ t ].m_nIndex = t;
|
|
nTotalRenderablesStatic += nCountStatic;
|
|
nTotalRenderablesDynamic += nCountDynamic;
|
|
}
|
|
m_pRenderJobs[ m_nRenderThreads - 1 ].m_nCountStatic = nRenderablesStatic - m_pRenderJobs[ m_nRenderThreads - 1 ].m_nStartStatic;
|
|
m_pRenderJobs[ m_nRenderThreads - 1 ].m_nCountDynamic = nRenderablesDynamic - m_pRenderJobs[ m_nRenderThreads - 1 ].m_nStartDynamic;
|
|
|
|
ParallelProcess( m_pRenderJobs, m_nRenderThreads, PerformStaticMeshWorkUnit );
|
|
}
|
|
else
|
|
{
|
|
RenderViewStatic( &renderView, 0, renderView.GetRenderableList().Count(), 0 );
|
|
RenderViewDynamic( &renderView, 0, renderView.GetDynamicList().Count(), 0 );
|
|
}
|
|
}
|
|
|
|
void CWorldRendererTest::UpdateShadowData()
|
|
{
|
|
for ( int s=0; s<m_nShadowSplits; ++s )
|
|
{
|
|
VMatrix mLightRelated;
|
|
mLightRelated = m_pSplitFrustums[s]->GetViewProj();
|
|
m_pShadowMatrices[s] = mLightRelated * m_splitScaleBiasMatrices[ s ];
|
|
m_forwardLightingData.m_mShadowMatrices[s] = m_pShadowMatrices[s];
|
|
}
|
|
|
|
for ( int s=0; s<NUM_MULTI_SHADOWS; ++s )
|
|
{
|
|
m_pRenderViews[ RTB_SHADOW_DEPTH_MULTIPLE_0 + s ].SetValid( false );
|
|
}
|
|
|
|
for ( int s=0; s<m_shadowedSpotLights.Count(); ++s )
|
|
{
|
|
CSpotLightRenderable &renderable = m_shadowedSpotLights[s];
|
|
|
|
Vector vOrigin = Vector( renderable.m_pLight->m_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; i<nRenderables; ++i )
|
|
{
|
|
Vector vAxis( 0, 1, 0 );
|
|
MatrixRotate( m_dynRenderableList[ i ].m_mWorld, vAxis, flElapsedTime * 60.0f );
|
|
m_dynRenderableList[ i ].m_mWorld.SetTranslation( m_dynRenderableList[ i ].m_vOrigin );
|
|
}
|
|
}
|
|
|
|
void CWorldRendererTest::RenderShadowDepthBuffers( IRenderContext *pRenderContext )
|
|
{
|
|
Vector4D vShadowClear(1,1,1,1);
|
|
|
|
VPROF_SCOPE_BEGIN("RenderSplitShadows");
|
|
for ( int s=0; s<m_nShadowSplits; ++s )
|
|
{
|
|
m_pRenderViews[ RTB_SHADOW_DEPTH0 + s ].Clear( pRenderContext, vShadowClear, RENDER_CLEAR_FLAGS_CLEAR_DEPTH );
|
|
|
|
if ( m_pRenderViews[ RTB_SHADOW_DEPTH0 + s ].HasRenderables() )
|
|
{
|
|
RenderView( m_pRenderViews[ RTB_SHADOW_DEPTH0 + s ] );
|
|
|
|
// Render spheres
|
|
m_pRenderViews[ RTB_SHADOW_DEPTH0 + s ].BeginRender( pRenderContext );
|
|
|
|
ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pSplitFrustums[s] );
|
|
pRenderContext->SetConstantBufferData( 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; p<nParticleSystems; ++p )
|
|
{
|
|
RenderParticleLights( pRenderContext, m_sphereSystemList[p], VARIATION_DEPTH, true, false );
|
|
}
|
|
|
|
// Submit
|
|
m_pRenderViews[ RTB_SHADOW_DEPTH0 + s ].EndRender( pRenderContext );
|
|
}
|
|
}
|
|
VPROF_SCOPE_END();
|
|
|
|
VPROF_SCOPE_BEGIN("RenderMultiShadows");
|
|
for ( int s=0; s<m_shadowedSpotLights.Count(); ++s )
|
|
{
|
|
if ( s == 0 )
|
|
{
|
|
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 ( 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; p<nParticleSystems; ++p )
|
|
{
|
|
RenderParticleLights( pRenderContext, m_sphereSystemList[p], VARIATION_DEPTH, false, false );
|
|
}
|
|
|
|
// Submit
|
|
m_pRenderViews[ RTB_SHADOW_DEPTH_MULTIPLE_0 + s ].EndRender( pRenderContext );
|
|
}
|
|
VPROF_SCOPE_END();
|
|
}
|
|
|
|
void CWorldRendererTest::RenderSunShadowFrustums( IRenderContext *pRenderContext )
|
|
{
|
|
ViewRelatedConstants_t viewConstants = CreateViewConstantsForFrustum( m_pFrustum );
|
|
|
|
pRenderContext->SetCullMode( 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; s<NUM_SHADOW_SPLITS; ++s )
|
|
{
|
|
m_deferredLightingData.m_mShadowMatrix[s] = m_pShadowMatrices[s];
|
|
pRenderContext->BindTexture( 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; p<nParticleSystems; ++p )
|
|
{
|
|
RenderParticleLights( pRenderContext, m_lightSystemList[p], VARIATION_DEFAULT, false, false );
|
|
}
|
|
|
|
// Render scene lights
|
|
pRenderContext->SetConstantBufferData( 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<PerParticleData_t> vb( pRenderContext, pInputSystem->m_nActiveParticles, "particles", "particles" );
|
|
vb.Lock( );
|
|
|
|
for ( int p=0; p<pInputSystem->m_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<CPointLightRenderable> &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<PointLightData_t> *pVB = NULL;
|
|
|
|
int nLights = lightVector.Count();
|
|
int nLightsDrawn = 0;
|
|
for ( int i=0; i<nLights; ++i )
|
|
{
|
|
if ( !pVB )
|
|
{
|
|
pVB = new CDynamicVertexData<PointLightData_t>( 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<CHemiLightRenderable> &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<HemiLightData_t> *pVB = NULL;
|
|
|
|
int nLights = lightVector.Count();
|
|
int nLightsDrawn = 0;
|
|
for ( int i=0; i<nLights; ++i )
|
|
{
|
|
if ( !pVB )
|
|
{
|
|
pVB = new CDynamicVertexData<HemiLightData_t>( 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<CSpotLightRenderable> &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<SpotLightData_t> *pVB = NULL;
|
|
|
|
int nLights = lightVector.Count();
|
|
int nLightsDrawn = 0;
|
|
for ( int i=0; i<nLights; ++i )
|
|
{
|
|
if ( !lightVector[i].m_bValid )
|
|
continue;
|
|
|
|
if ( !pVB )
|
|
{
|
|
pVB = new CDynamicVertexData<SpotLightData_t>( 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<CSpotLightRenderable> &lightVector )
|
|
{
|
|
int nLights = lightVector.Count();
|
|
if ( nLights == 0 )
|
|
return;
|
|
|
|
const int nMaxLightsPerDraw = NUM_MULTI_SHADOWS;
|
|
CDynamicVertexData<SpotLightData_t> *pVB = new CDynamicVertexData<SpotLightData_t>( pRenderContext, nMaxLightsPerDraw, "scenelights_shadowspot", "scenelights_shadowspot" );
|
|
pVB->Lock();
|
|
|
|
Assert( nLights <= NUM_MULTI_SHADOWS );
|
|
for ( int i=0; i<nLights; ++i )
|
|
{
|
|
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();
|
|
}
|
|
|
|
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; i<nLights; ++i )
|
|
{
|
|
if ( i < NUM_HIGH_RES_SHADOWS )
|
|
{
|
|
pRenderContext->BindTexture( 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; v<RTB_FORWARD; ++v )
|
|
{
|
|
CullRenderablesAgainstView( m_pRenderViews[ v ], m_renderableList, m_dynRenderableList );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( int v=RTB_SHADOW_DEPTH0; v<RTB_SHADOW_DEPTH_MULTIPLE_0; ++v )
|
|
{
|
|
CullRenderablesAgainstView( m_pRenderViews[ v ], m_renderableList, m_dynRenderableList );
|
|
}
|
|
|
|
CullRenderablesAgainstView( m_pRenderViews[ RTB_FORWARD ], m_renderableList, m_dynRenderableList );
|
|
}
|
|
|
|
// Update the camera to make sure we shift the far plane out enough to encompass any lights
|
|
flShiftedFar = MAX( flShiftedFar, m_flMaxLightEncompassingFarPlane );
|
|
m_pFrustum->SetNearFarPlanes( 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; p<nParticleSystems; ++p )
|
|
{
|
|
RenderParticleLights( pRenderContext, m_sphereSystemList[p], VARIATION_NORM_DEPTH_SPEC, false, true );
|
|
}
|
|
|
|
// Submit
|
|
m_pRenderViews[ RTB_DEFERRED_DEPTH_NORM_SPEC ].EndRender( pRenderContext );
|
|
}
|
|
|
|
// Clear low -res lighting
|
|
{
|
|
Vector4D vLightingClear(0,0,0,1);
|
|
m_pRenderViews[ RTB_LIGHTING_LOWRES ].Clear( pRenderContext, vLightingClear, 0 );
|
|
}
|
|
|
|
// Decals
|
|
{
|
|
m_pRenderViews[ RTB_DEFERRED_NORM_SPEC ].BeginRender( pRenderContext );
|
|
|
|
pRenderContext->SetCullMode( 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; p<nParticleSystems; ++p )
|
|
{
|
|
RenderParticleLights( pRenderContext, m_sphereSystemList[p], VARIATION_SAMPLE_LIGHTING, false, false );
|
|
}
|
|
|
|
// Decals
|
|
pRenderContext->SetZBufferMode( 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; p<nParticleSystems; ++p )
|
|
{
|
|
RenderParticleLights( pRenderContext, m_lightSystemList[p], 4, false, false );
|
|
}
|
|
|
|
// Submit
|
|
m_pRenderViews[ RTB_SAMPLE_LIGHTING ].EndRender( pRenderContext );
|
|
}
|
|
|
|
|
|
// Render aerial perspective
|
|
if ( m_bDrawAerialPerspective )
|
|
{
|
|
RenderAerialPerspective();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VPROF_SCOPE_BEGIN("RenderWorldNodes");
|
|
|
|
Vector4D c(0,1,0,0);
|
|
m_pRenderViews[ RTB_FORWARD ].Clear( pRenderContext, c, RENDER_CLEAR_FLAGS_CLEAR_DEPTH );
|
|
|
|
RenderView( m_pRenderViews[ RTB_FORWARD ] );
|
|
|
|
// Submit
|
|
m_pRenderViews[ RTB_FORWARD ].EndRender( pRenderContext );
|
|
|
|
VPROF_SCOPE_END();
|
|
}
|
|
|
|
if ( m_bRenderSky )
|
|
{
|
|
RenderSky();
|
|
}
|
|
|
|
// Unbind the render targets
|
|
for ( int s=0; s<NUM_SHADOW_SPLITS; ++s )
|
|
{
|
|
pRenderContext->BindTexture( 4 + s, RENDER_TEXTURE_HANDLE_INVALID );
|
|
}
|
|
pRenderContext->Submit();
|
|
|
|
for ( int v=0; v<MAX_VIEW_BINDING_TYPES; ++v )
|
|
{
|
|
m_pRenderViews[ v ].EndRender( NULL );
|
|
}
|
|
|
|
// Update resources phase (arbitrarily only allow 10 resources to be updated)
|
|
m_pWorldRenderer->UpdateResources( 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<uint16> 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<SphereVertex_t> 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<uint16> 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<SphereVertex_t> 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<SphereVertex_t> vb( pRenderContext, m_hConeVB );
|
|
vb.Lock( nVertices );
|
|
|
|
vb->m_vPos = vTop;
|
|
vb.AdvanceVertex();
|
|
|
|
float flTesRes = (float)nTessellationRes;
|
|
for ( int i=0; i<nTessellationRes; ++i )
|
|
{
|
|
float flU = ( i / flTesRes ) * (2.0 * M_PI);
|
|
|
|
Vector vPos = Vector( 1.1f * cos( flU ), 1.1f * sin( flU ), 1 );
|
|
|
|
vb->m_vPos = vPos;
|
|
vb.AdvanceVertex();
|
|
}
|
|
|
|
vb.Unlock();
|
|
|
|
CIndexData<uint16> ib( pRenderContext, m_hConeIB );
|
|
ib.Lock( indexDesc.m_nElementCount );
|
|
|
|
// Cone
|
|
for ( int i=1; i<nTessellationRes+1; ++i )
|
|
{
|
|
ib.Index( 0 );
|
|
ib.Index( i );
|
|
ib.Index( ( i % nTessellationRes ) + 1 );
|
|
}
|
|
|
|
// Cap
|
|
for ( int i=2; i<nTessellationRes; ++i )
|
|
{
|
|
ib.Index( ( i + 1 ) );
|
|
ib.Index( i );
|
|
ib.Index( 1 );
|
|
}
|
|
|
|
ib.Unlock();
|
|
}
|
|
|
|
bool LoadFile( char *pFileName, CUtlBuffer &buffer, const char *pShaderVersion )
|
|
{
|
|
Assert( pFileName && pShaderVersion );
|
|
|
|
char pLocalFileName[260];
|
|
Q_snprintf( pLocalFileName, 260, "%s.%s", pFileName, pShaderVersion );
|
|
|
|
if ( !g_pFullFileSystem->ReadFile( 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; s<NUM_SHADOW_SPLITS; ++s )
|
|
{
|
|
m_forwardLightingData.m_mShadowMatrices[s] = m_pShadowMatrices[s];
|
|
pRenderContext->BindTexture( 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<MAX_RENDER_TARGET_TYPES; ++i )
|
|
{
|
|
m_pRenderTargets[i] = CreateRenderTarget( (RenderTargetType_t)i, viewport );
|
|
}
|
|
|
|
for ( int i=0; i<MAX_VIEW_BINDING_TYPES; ++i )
|
|
{
|
|
m_pViewBindings[i] = CreateRenderTargetBinding( (ViewBindingType_t)i, viewport );
|
|
}
|
|
|
|
m_bRenderTargetsInit = true;
|
|
}
|
|
|
|
void CWorldRendererTest::GetDescription( char *pNameBufferOut, size_t nBufLen )
|
|
{
|
|
if ( m_nVariant )
|
|
{
|
|
Q_snprintf( pNameBufferOut, nBufLen, "Render the world (deferred) (Press Space to Continue)" );
|
|
}
|
|
else
|
|
{
|
|
Q_snprintf( pNameBufferOut, nBufLen, "Render the world (forward) (Press Space to Continue)" );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Can this test be run?
|
|
//-----------------------------------------------------------------------------
|
|
bool CWorldRendererTest::CanBeRun()
|
|
{
|
|
return ( g_pWorldRendererMgr != NULL ) && m_bWorldLoaded;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// check for a keypress
|
|
//-----------------------------------------------------------------------------
|
|
bool CWorldRendererTest::ProcessUserInput( const InputEvent_t &ie )
|
|
{
|
|
if ( ie.m_nType == IE_AnalogValueChanged )
|
|
{
|
|
switch( ie.m_nData )
|
|
{
|
|
case MOUSE_XY:
|
|
if ( m_nWindowCenterX > 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 );
|
|
}
|