diff --git a/README.md b/README.md index 21267158..4655f6ad 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Discord: https://discord.gg/hZRB7WMgGw - [x] rewrite achivement system( to work without steam ) - [x] 64-bit support - [x] VTF 7.5 support +- [x] PBR support - [ ] improve performance - [ ] fixing bugs - [ ] dxvk-native support diff --git a/game/client/c_physicsprop.cpp b/game/client/c_physicsprop.cpp index 7727be66..515c70cf 100644 --- a/game/client/c_physicsprop.cpp +++ b/game/client/c_physicsprop.cpp @@ -20,11 +20,17 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" +#define PBR_CHANGE + IMPLEMENT_CLIENTCLASS_DT(C_PhysicsProp, DT_PhysicsProp, CPhysicsProp) RecvPropBool( RECVINFO( m_bAwake ) ), END_RECV_TABLE() -ConVar r_PhysPropStaticLighting( "r_PhysPropStaticLighting", "1" ); +#ifdef PBR_CHANGE + ConVar r_PhysPropStaticLighting( "r_PhysPropStaticLighting", "0" ); +#else + ConVar r_PhysPropStaticLighting( "r_PhysPropStaticLighting", "1" ); +#endif //----------------------------------------------------------------------------- diff --git a/materialsystem/stdshaders/fxctmp9/pbr_ps20b.inc b/materialsystem/stdshaders/fxctmp9/pbr_ps20b.inc new file mode 100644 index 00000000..18170a71 --- /dev/null +++ b/materialsystem/stdshaders/fxctmp9/pbr_ps20b.inc @@ -0,0 +1,287 @@ +#include "shaderlib/cshader.h" +class pbr_ps20b_Static_Index +{ +private: + int m_nFLASHLIGHT; +#ifdef _DEBUG + bool m_bFLASHLIGHT; +#endif +public: + void SetFLASHLIGHT( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nFLASHLIGHT = i; +#ifdef _DEBUG + m_bFLASHLIGHT = true; +#endif + } + void SetFLASHLIGHT( bool i ) + { + m_nFLASHLIGHT = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHT = true; +#endif + } +private: + int m_nFLASHLIGHTDEPTHFILTERMODE; +#ifdef _DEBUG + bool m_bFLASHLIGHTDEPTHFILTERMODE; +#endif +public: + void SetFLASHLIGHTDEPTHFILTERMODE( int i ) + { + Assert( i >= 0 && i <= 2 ); + m_nFLASHLIGHTDEPTHFILTERMODE = i; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = true; +#endif + } + void SetFLASHLIGHTDEPTHFILTERMODE( bool i ) + { + m_nFLASHLIGHTDEPTHFILTERMODE = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = true; +#endif + } +private: + int m_nLIGHTMAPPED; +#ifdef _DEBUG + bool m_bLIGHTMAPPED; +#endif +public: + void SetLIGHTMAPPED( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nLIGHTMAPPED = i; +#ifdef _DEBUG + m_bLIGHTMAPPED = true; +#endif + } + void SetLIGHTMAPPED( bool i ) + { + m_nLIGHTMAPPED = i ? 1 : 0; +#ifdef _DEBUG + m_bLIGHTMAPPED = true; +#endif + } +private: + int m_nEMISSIVE; +#ifdef _DEBUG + bool m_bEMISSIVE; +#endif +public: + void SetEMISSIVE( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nEMISSIVE = i; +#ifdef _DEBUG + m_bEMISSIVE = true; +#endif + } + void SetEMISSIVE( bool i ) + { + m_nEMISSIVE = i ? 1 : 0; +#ifdef _DEBUG + m_bEMISSIVE = true; +#endif + } +private: + int m_nSPECULAR; +#ifdef _DEBUG + bool m_bSPECULAR; +#endif +public: + void SetSPECULAR( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nSPECULAR = i; +#ifdef _DEBUG + m_bSPECULAR = true; +#endif + } + void SetSPECULAR( bool i ) + { + m_nSPECULAR = i ? 1 : 0; +#ifdef _DEBUG + m_bSPECULAR = true; +#endif + } +public: + pbr_ps20b_Static_Index( ) + { +#ifdef _DEBUG + m_bFLASHLIGHT = false; +#endif // _DEBUG + m_nFLASHLIGHT = 0; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = false; +#endif // _DEBUG + m_nFLASHLIGHTDEPTHFILTERMODE = 0; +#ifdef _DEBUG + m_bLIGHTMAPPED = false; +#endif // _DEBUG + m_nLIGHTMAPPED = 0; +#ifdef _DEBUG + m_bEMISSIVE = false; +#endif // _DEBUG + m_nEMISSIVE = 0; +#ifdef _DEBUG + m_bSPECULAR = false; +#endif // _DEBUG + m_nSPECULAR = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllStaticVarsDefined = m_bFLASHLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE && m_bLIGHTMAPPED && m_bEMISSIVE && m_bSPECULAR; + Assert( bAllStaticVarsDefined ); +#endif // _DEBUG + return ( 80 * m_nFLASHLIGHT ) + ( 160 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 480 * m_nLIGHTMAPPED ) + ( 960 * m_nEMISSIVE ) + ( 1920 * m_nSPECULAR ) + 0; + } +}; +#define shaderStaticTest_pbr_ps20b psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_LIGHTMAPPED + psh_forgot_to_set_static_EMISSIVE + psh_forgot_to_set_static_SPECULAR + 0 +class pbr_ps20b_Dynamic_Index +{ +private: + int m_nWRITEWATERFOGTODESTALPHA; +#ifdef _DEBUG + bool m_bWRITEWATERFOGTODESTALPHA; +#endif +public: + void SetWRITEWATERFOGTODESTALPHA( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nWRITEWATERFOGTODESTALPHA = i; +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = true; +#endif + } + void SetWRITEWATERFOGTODESTALPHA( bool i ) + { + m_nWRITEWATERFOGTODESTALPHA = i ? 1 : 0; +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = true; +#endif + } +private: + int m_nPIXELFOGTYPE; +#ifdef _DEBUG + bool m_bPIXELFOGTYPE; +#endif +public: + void SetPIXELFOGTYPE( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPIXELFOGTYPE = i; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } + void SetPIXELFOGTYPE( bool i ) + { + m_nPIXELFOGTYPE = i ? 1 : 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } +private: + int m_nNUM_LIGHTS; +#ifdef _DEBUG + bool m_bNUM_LIGHTS; +#endif +public: + void SetNUM_LIGHTS( int i ) + { + Assert( i >= 0 && i <= 4 ); + m_nNUM_LIGHTS = i; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } + void SetNUM_LIGHTS( bool i ) + { + m_nNUM_LIGHTS = i ? 1 : 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } +private: + int m_nWRITE_DEPTH_TO_DESTALPHA; +#ifdef _DEBUG + bool m_bWRITE_DEPTH_TO_DESTALPHA; +#endif +public: + void SetWRITE_DEPTH_TO_DESTALPHA( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nWRITE_DEPTH_TO_DESTALPHA = i; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = true; +#endif + } + void SetWRITE_DEPTH_TO_DESTALPHA( bool i ) + { + m_nWRITE_DEPTH_TO_DESTALPHA = i ? 1 : 0; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = true; +#endif + } +private: + int m_nFLASHLIGHTSHADOWS; +#ifdef _DEBUG + bool m_bFLASHLIGHTSHADOWS; +#endif +public: + void SetFLASHLIGHTSHADOWS( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nFLASHLIGHTSHADOWS = i; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = true; +#endif + } + void SetFLASHLIGHTSHADOWS( bool i ) + { + m_nFLASHLIGHTSHADOWS = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = true; +#endif + } +public: + pbr_ps20b_Dynamic_Index() + { +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = false; +#endif // _DEBUG + m_nWRITEWATERFOGTODESTALPHA = 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = false; +#endif // _DEBUG + m_nPIXELFOGTYPE = 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = false; +#endif // _DEBUG + m_nNUM_LIGHTS = 0; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = false; +#endif // _DEBUG + m_nWRITE_DEPTH_TO_DESTALPHA = 0; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = false; +#endif // _DEBUG + m_nFLASHLIGHTSHADOWS = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bWRITEWATERFOGTODESTALPHA && m_bPIXELFOGTYPE && m_bNUM_LIGHTS && m_bWRITE_DEPTH_TO_DESTALPHA && m_bFLASHLIGHTSHADOWS; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nWRITEWATERFOGTODESTALPHA ) + ( 2 * m_nPIXELFOGTYPE ) + ( 4 * m_nNUM_LIGHTS ) + ( 20 * m_nWRITE_DEPTH_TO_DESTALPHA ) + ( 40 * m_nFLASHLIGHTSHADOWS ) + 0; + } +}; +#define shaderDynamicTest_pbr_ps20b psh_forgot_to_set_dynamic_WRITEWATERFOGTODESTALPHA + psh_forgot_to_set_dynamic_PIXELFOGTYPE + psh_forgot_to_set_dynamic_NUM_LIGHTS + psh_forgot_to_set_dynamic_WRITE_DEPTH_TO_DESTALPHA + psh_forgot_to_set_dynamic_FLASHLIGHTSHADOWS + 0 diff --git a/materialsystem/stdshaders/fxctmp9/pbr_ps30.inc b/materialsystem/stdshaders/fxctmp9/pbr_ps30.inc new file mode 100644 index 00000000..b516e54b --- /dev/null +++ b/materialsystem/stdshaders/fxctmp9/pbr_ps30.inc @@ -0,0 +1,337 @@ +#include "shaderlib/cshader.h" +class pbr_ps30_Static_Index +{ +private: + int m_nFLASHLIGHT; +#ifdef _DEBUG + bool m_bFLASHLIGHT; +#endif +public: + void SetFLASHLIGHT( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nFLASHLIGHT = i; +#ifdef _DEBUG + m_bFLASHLIGHT = true; +#endif + } + void SetFLASHLIGHT( bool i ) + { + m_nFLASHLIGHT = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHT = true; +#endif + } +private: + int m_nFLASHLIGHTDEPTHFILTERMODE; +#ifdef _DEBUG + bool m_bFLASHLIGHTDEPTHFILTERMODE; +#endif +public: + void SetFLASHLIGHTDEPTHFILTERMODE( int i ) + { + Assert( i >= 0 && i <= 2 ); + m_nFLASHLIGHTDEPTHFILTERMODE = i; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = true; +#endif + } + void SetFLASHLIGHTDEPTHFILTERMODE( bool i ) + { + m_nFLASHLIGHTDEPTHFILTERMODE = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = true; +#endif + } +private: + int m_nLIGHTMAPPED; +#ifdef _DEBUG + bool m_bLIGHTMAPPED; +#endif +public: + void SetLIGHTMAPPED( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nLIGHTMAPPED = i; +#ifdef _DEBUG + m_bLIGHTMAPPED = true; +#endif + } + void SetLIGHTMAPPED( bool i ) + { + m_nLIGHTMAPPED = i ? 1 : 0; +#ifdef _DEBUG + m_bLIGHTMAPPED = true; +#endif + } +private: + int m_nUSEENVAMBIENT; +#ifdef _DEBUG + bool m_bUSEENVAMBIENT; +#endif +public: + void SetUSEENVAMBIENT( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nUSEENVAMBIENT = i; +#ifdef _DEBUG + m_bUSEENVAMBIENT = true; +#endif + } + void SetUSEENVAMBIENT( bool i ) + { + m_nUSEENVAMBIENT = i ? 1 : 0; +#ifdef _DEBUG + m_bUSEENVAMBIENT = true; +#endif + } +private: + int m_nEMISSIVE; +#ifdef _DEBUG + bool m_bEMISSIVE; +#endif +public: + void SetEMISSIVE( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nEMISSIVE = i; +#ifdef _DEBUG + m_bEMISSIVE = true; +#endif + } + void SetEMISSIVE( bool i ) + { + m_nEMISSIVE = i ? 1 : 0; +#ifdef _DEBUG + m_bEMISSIVE = true; +#endif + } +private: + int m_nSPECULAR; +#ifdef _DEBUG + bool m_bSPECULAR; +#endif +public: + void SetSPECULAR( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nSPECULAR = i; +#ifdef _DEBUG + m_bSPECULAR = true; +#endif + } + void SetSPECULAR( bool i ) + { + m_nSPECULAR = i ? 1 : 0; +#ifdef _DEBUG + m_bSPECULAR = true; +#endif + } +private: + int m_nPARALLAXOCCLUSION; +#ifdef _DEBUG + bool m_bPARALLAXOCCLUSION; +#endif +public: + void SetPARALLAXOCCLUSION( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPARALLAXOCCLUSION = i; +#ifdef _DEBUG + m_bPARALLAXOCCLUSION = true; +#endif + } + void SetPARALLAXOCCLUSION( bool i ) + { + m_nPARALLAXOCCLUSION = i ? 1 : 0; +#ifdef _DEBUG + m_bPARALLAXOCCLUSION = true; +#endif + } +public: + pbr_ps30_Static_Index( ) + { +#ifdef _DEBUG + m_bFLASHLIGHT = false; +#endif // _DEBUG + m_nFLASHLIGHT = 0; +#ifdef _DEBUG + m_bFLASHLIGHTDEPTHFILTERMODE = false; +#endif // _DEBUG + m_nFLASHLIGHTDEPTHFILTERMODE = 0; +#ifdef _DEBUG + m_bLIGHTMAPPED = false; +#endif // _DEBUG + m_nLIGHTMAPPED = 0; +#ifdef _DEBUG + m_bUSEENVAMBIENT = false; +#endif // _DEBUG + m_nUSEENVAMBIENT = 0; +#ifdef _DEBUG + m_bEMISSIVE = false; +#endif // _DEBUG + m_nEMISSIVE = 0; +#ifdef _DEBUG + m_bSPECULAR = false; +#endif // _DEBUG + m_nSPECULAR = 0; +#ifdef _DEBUG + m_bPARALLAXOCCLUSION = false; +#endif // _DEBUG + m_nPARALLAXOCCLUSION = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllStaticVarsDefined = m_bFLASHLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE && m_bLIGHTMAPPED && m_bUSEENVAMBIENT && m_bEMISSIVE && m_bSPECULAR && m_bPARALLAXOCCLUSION; + Assert( bAllStaticVarsDefined ); +#endif // _DEBUG + return ( 80 * m_nFLASHLIGHT ) + ( 160 * m_nFLASHLIGHTDEPTHFILTERMODE ) + ( 480 * m_nLIGHTMAPPED ) + ( 960 * m_nUSEENVAMBIENT ) + ( 1920 * m_nEMISSIVE ) + ( 3840 * m_nSPECULAR ) + ( 7680 * m_nPARALLAXOCCLUSION ) + 0; + } +}; +#define shaderStaticTest_pbr_ps30 psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + psh_forgot_to_set_static_LIGHTMAPPED + psh_forgot_to_set_static_USEENVAMBIENT + psh_forgot_to_set_static_EMISSIVE + psh_forgot_to_set_static_SPECULAR + psh_forgot_to_set_static_PARALLAXOCCLUSION + 0 +class pbr_ps30_Dynamic_Index +{ +private: + int m_nWRITEWATERFOGTODESTALPHA; +#ifdef _DEBUG + bool m_bWRITEWATERFOGTODESTALPHA; +#endif +public: + void SetWRITEWATERFOGTODESTALPHA( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nWRITEWATERFOGTODESTALPHA = i; +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = true; +#endif + } + void SetWRITEWATERFOGTODESTALPHA( bool i ) + { + m_nWRITEWATERFOGTODESTALPHA = i ? 1 : 0; +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = true; +#endif + } +private: + int m_nPIXELFOGTYPE; +#ifdef _DEBUG + bool m_bPIXELFOGTYPE; +#endif +public: + void SetPIXELFOGTYPE( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nPIXELFOGTYPE = i; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } + void SetPIXELFOGTYPE( bool i ) + { + m_nPIXELFOGTYPE = i ? 1 : 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = true; +#endif + } +private: + int m_nNUM_LIGHTS; +#ifdef _DEBUG + bool m_bNUM_LIGHTS; +#endif +public: + void SetNUM_LIGHTS( int i ) + { + Assert( i >= 0 && i <= 4 ); + m_nNUM_LIGHTS = i; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } + void SetNUM_LIGHTS( bool i ) + { + m_nNUM_LIGHTS = i ? 1 : 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } +private: + int m_nWRITE_DEPTH_TO_DESTALPHA; +#ifdef _DEBUG + bool m_bWRITE_DEPTH_TO_DESTALPHA; +#endif +public: + void SetWRITE_DEPTH_TO_DESTALPHA( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nWRITE_DEPTH_TO_DESTALPHA = i; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = true; +#endif + } + void SetWRITE_DEPTH_TO_DESTALPHA( bool i ) + { + m_nWRITE_DEPTH_TO_DESTALPHA = i ? 1 : 0; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = true; +#endif + } +private: + int m_nFLASHLIGHTSHADOWS; +#ifdef _DEBUG + bool m_bFLASHLIGHTSHADOWS; +#endif +public: + void SetFLASHLIGHTSHADOWS( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nFLASHLIGHTSHADOWS = i; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = true; +#endif + } + void SetFLASHLIGHTSHADOWS( bool i ) + { + m_nFLASHLIGHTSHADOWS = i ? 1 : 0; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = true; +#endif + } +public: + pbr_ps30_Dynamic_Index() + { +#ifdef _DEBUG + m_bWRITEWATERFOGTODESTALPHA = false; +#endif // _DEBUG + m_nWRITEWATERFOGTODESTALPHA = 0; +#ifdef _DEBUG + m_bPIXELFOGTYPE = false; +#endif // _DEBUG + m_nPIXELFOGTYPE = 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = false; +#endif // _DEBUG + m_nNUM_LIGHTS = 0; +#ifdef _DEBUG + m_bWRITE_DEPTH_TO_DESTALPHA = false; +#endif // _DEBUG + m_nWRITE_DEPTH_TO_DESTALPHA = 0; +#ifdef _DEBUG + m_bFLASHLIGHTSHADOWS = false; +#endif // _DEBUG + m_nFLASHLIGHTSHADOWS = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bWRITEWATERFOGTODESTALPHA && m_bPIXELFOGTYPE && m_bNUM_LIGHTS && m_bWRITE_DEPTH_TO_DESTALPHA && m_bFLASHLIGHTSHADOWS; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nWRITEWATERFOGTODESTALPHA ) + ( 2 * m_nPIXELFOGTYPE ) + ( 4 * m_nNUM_LIGHTS ) + ( 20 * m_nWRITE_DEPTH_TO_DESTALPHA ) + ( 40 * m_nFLASHLIGHTSHADOWS ) + 0; + } +}; +#define shaderDynamicTest_pbr_ps30 psh_forgot_to_set_dynamic_WRITEWATERFOGTODESTALPHA + psh_forgot_to_set_dynamic_PIXELFOGTYPE + psh_forgot_to_set_dynamic_NUM_LIGHTS + psh_forgot_to_set_dynamic_WRITE_DEPTH_TO_DESTALPHA + psh_forgot_to_set_dynamic_FLASHLIGHTSHADOWS + 0 diff --git a/materialsystem/stdshaders/fxctmp9/pbr_vs20b.inc b/materialsystem/stdshaders/fxctmp9/pbr_vs20b.inc new file mode 100644 index 00000000..4828f751 --- /dev/null +++ b/materialsystem/stdshaders/fxctmp9/pbr_vs20b.inc @@ -0,0 +1,160 @@ +#include "shaderlib/cshader.h" +class pbr_vs20b_Static_Index +{ +public: + pbr_vs20b_Static_Index( ) + { + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG +#endif // _DEBUG + return 0; + } +}; +#define shaderStaticTest_pbr_vs20b 0 +class pbr_vs20b_Dynamic_Index +{ +private: + int m_nCOMPRESSED_VERTS; +#ifdef _DEBUG + bool m_bCOMPRESSED_VERTS; +#endif +public: + void SetCOMPRESSED_VERTS( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nCOMPRESSED_VERTS = i; +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = true; +#endif + } + void SetCOMPRESSED_VERTS( bool i ) + { + m_nCOMPRESSED_VERTS = i ? 1 : 0; +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = true; +#endif + } +private: + int m_nDOWATERFOG; +#ifdef _DEBUG + bool m_bDOWATERFOG; +#endif +public: + void SetDOWATERFOG( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nDOWATERFOG = i; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } + void SetDOWATERFOG( bool i ) + { + m_nDOWATERFOG = i ? 1 : 0; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } +private: + int m_nSKINNING; +#ifdef _DEBUG + bool m_bSKINNING; +#endif +public: + void SetSKINNING( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nSKINNING = i; +#ifdef _DEBUG + m_bSKINNING = true; +#endif + } + void SetSKINNING( bool i ) + { + m_nSKINNING = i ? 1 : 0; +#ifdef _DEBUG + m_bSKINNING = true; +#endif + } +private: + int m_nLIGHTING_PREVIEW; +#ifdef _DEBUG + bool m_bLIGHTING_PREVIEW; +#endif +public: + void SetLIGHTING_PREVIEW( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nLIGHTING_PREVIEW = i; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = true; +#endif + } + void SetLIGHTING_PREVIEW( bool i ) + { + m_nLIGHTING_PREVIEW = i ? 1 : 0; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = true; +#endif + } +private: + int m_nNUM_LIGHTS; +#ifdef _DEBUG + bool m_bNUM_LIGHTS; +#endif +public: + void SetNUM_LIGHTS( int i ) + { + Assert( i >= 0 && i <= 4 ); + m_nNUM_LIGHTS = i; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } + void SetNUM_LIGHTS( bool i ) + { + m_nNUM_LIGHTS = i ? 1 : 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } +public: + pbr_vs20b_Dynamic_Index() + { +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = false; +#endif // _DEBUG + m_nCOMPRESSED_VERTS = 0; +#ifdef _DEBUG + m_bDOWATERFOG = false; +#endif // _DEBUG + m_nDOWATERFOG = 0; +#ifdef _DEBUG + m_bSKINNING = false; +#endif // _DEBUG + m_nSKINNING = 0; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = false; +#endif // _DEBUG + m_nLIGHTING_PREVIEW = 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = false; +#endif // _DEBUG + m_nNUM_LIGHTS = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bCOMPRESSED_VERTS && m_bDOWATERFOG && m_bSKINNING && m_bLIGHTING_PREVIEW && m_bNUM_LIGHTS; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nCOMPRESSED_VERTS ) + ( 2 * m_nDOWATERFOG ) + ( 4 * m_nSKINNING ) + ( 8 * m_nLIGHTING_PREVIEW ) + ( 16 * m_nNUM_LIGHTS ) + 0; + } +}; +#define shaderDynamicTest_pbr_vs20b vsh_forgot_to_set_dynamic_COMPRESSED_VERTS + vsh_forgot_to_set_dynamic_DOWATERFOG + vsh_forgot_to_set_dynamic_SKINNING + vsh_forgot_to_set_dynamic_LIGHTING_PREVIEW + vsh_forgot_to_set_dynamic_NUM_LIGHTS + 0 diff --git a/materialsystem/stdshaders/fxctmp9/pbr_vs30.inc b/materialsystem/stdshaders/fxctmp9/pbr_vs30.inc new file mode 100644 index 00000000..63da2329 --- /dev/null +++ b/materialsystem/stdshaders/fxctmp9/pbr_vs30.inc @@ -0,0 +1,160 @@ +#include "shaderlib/cshader.h" +class pbr_vs30_Static_Index +{ +public: + pbr_vs30_Static_Index( ) + { + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG +#endif // _DEBUG + return 0; + } +}; +#define shaderStaticTest_pbr_vs30 0 +class pbr_vs30_Dynamic_Index +{ +private: + int m_nCOMPRESSED_VERTS; +#ifdef _DEBUG + bool m_bCOMPRESSED_VERTS; +#endif +public: + void SetCOMPRESSED_VERTS( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nCOMPRESSED_VERTS = i; +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = true; +#endif + } + void SetCOMPRESSED_VERTS( bool i ) + { + m_nCOMPRESSED_VERTS = i ? 1 : 0; +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = true; +#endif + } +private: + int m_nDOWATERFOG; +#ifdef _DEBUG + bool m_bDOWATERFOG; +#endif +public: + void SetDOWATERFOG( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nDOWATERFOG = i; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } + void SetDOWATERFOG( bool i ) + { + m_nDOWATERFOG = i ? 1 : 0; +#ifdef _DEBUG + m_bDOWATERFOG = true; +#endif + } +private: + int m_nSKINNING; +#ifdef _DEBUG + bool m_bSKINNING; +#endif +public: + void SetSKINNING( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nSKINNING = i; +#ifdef _DEBUG + m_bSKINNING = true; +#endif + } + void SetSKINNING( bool i ) + { + m_nSKINNING = i ? 1 : 0; +#ifdef _DEBUG + m_bSKINNING = true; +#endif + } +private: + int m_nLIGHTING_PREVIEW; +#ifdef _DEBUG + bool m_bLIGHTING_PREVIEW; +#endif +public: + void SetLIGHTING_PREVIEW( int i ) + { + Assert( i >= 0 && i <= 1 ); + m_nLIGHTING_PREVIEW = i; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = true; +#endif + } + void SetLIGHTING_PREVIEW( bool i ) + { + m_nLIGHTING_PREVIEW = i ? 1 : 0; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = true; +#endif + } +private: + int m_nNUM_LIGHTS; +#ifdef _DEBUG + bool m_bNUM_LIGHTS; +#endif +public: + void SetNUM_LIGHTS( int i ) + { + Assert( i >= 0 && i <= 4 ); + m_nNUM_LIGHTS = i; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } + void SetNUM_LIGHTS( bool i ) + { + m_nNUM_LIGHTS = i ? 1 : 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = true; +#endif + } +public: + pbr_vs30_Dynamic_Index() + { +#ifdef _DEBUG + m_bCOMPRESSED_VERTS = false; +#endif // _DEBUG + m_nCOMPRESSED_VERTS = 0; +#ifdef _DEBUG + m_bDOWATERFOG = false; +#endif // _DEBUG + m_nDOWATERFOG = 0; +#ifdef _DEBUG + m_bSKINNING = false; +#endif // _DEBUG + m_nSKINNING = 0; +#ifdef _DEBUG + m_bLIGHTING_PREVIEW = false; +#endif // _DEBUG + m_nLIGHTING_PREVIEW = 0; +#ifdef _DEBUG + m_bNUM_LIGHTS = false; +#endif // _DEBUG + m_nNUM_LIGHTS = 0; + } + int GetIndex() + { + // Asserts to make sure that we aren't using any skipped combinations. + // Asserts to make sure that we are setting all of the combination vars. +#ifdef _DEBUG + bool bAllDynamicVarsDefined = m_bCOMPRESSED_VERTS && m_bDOWATERFOG && m_bSKINNING && m_bLIGHTING_PREVIEW && m_bNUM_LIGHTS; + Assert( bAllDynamicVarsDefined ); +#endif // _DEBUG + return ( 1 * m_nCOMPRESSED_VERTS ) + ( 2 * m_nDOWATERFOG ) + ( 4 * m_nSKINNING ) + ( 8 * m_nLIGHTING_PREVIEW ) + ( 16 * m_nNUM_LIGHTS ) + 0; + } +}; +#define shaderDynamicTest_pbr_vs30 vsh_forgot_to_set_dynamic_COMPRESSED_VERTS + vsh_forgot_to_set_dynamic_DOWATERFOG + vsh_forgot_to_set_dynamic_SKINNING + vsh_forgot_to_set_dynamic_LIGHTING_PREVIEW + vsh_forgot_to_set_dynamic_NUM_LIGHTS + 0 diff --git a/materialsystem/stdshaders/pbr_common_ps2_3_x.h b/materialsystem/stdshaders/pbr_common_ps2_3_x.h new file mode 100644 index 00000000..0e861eb8 --- /dev/null +++ b/materialsystem/stdshaders/pbr_common_ps2_3_x.h @@ -0,0 +1,257 @@ +//================================================================================================== +// +// Physically Based Rendering Header for brushes and models +// +//================================================================================================== + +// Universal Constants +static const float PI = 3.141592; +static const float ONE_OVER_PI = 0.318309; +static const float EPSILON = 0.00001; + +// Shlick's approximation of the Fresnel factor +float3 fresnelSchlick(float3 F0, float cosTheta) +{ + return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); +} + +// GGX/Towbridge-Reitz normal distribution function +// Uses Disney's reparametrization of alpha = roughness^2 +float ndfGGX(float cosLh, float roughness) +{ + float alpha = roughness * roughness; + float alphaSq = alpha * alpha; + + float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0; + return alphaSq / (PI * denom * denom); +} + +// Single term for separable Schlick-GGX below +float gaSchlickG1(float cosTheta, float k) +{ + return cosTheta / (cosTheta * (1.0 - k) + k); +} + +// Schlick-GGX approximation of geometric attenuation function using Smith's method +float gaSchlickGGX(float cosLi, float cosLo, float roughness) +{ + float r = roughness + 1.0; + float k = (r * r) / 8.0; // Epic suggests using this roughness remapping for analytic lights + return gaSchlickG1(cosLi, k) * gaSchlickG1(cosLo, k); +} + +// Monte Carlo integration, approximate analytic version based on Dimitar Lazarov's work +// https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile +float3 EnvBRDFApprox(float3 SpecularColor, float Roughness, float NoV) +{ + const float4 c0 = { -1, -0.0275, -0.572, 0.022 }; + const float4 c1 = { 1, 0.0425, 1.04, -0.04 }; + float4 r = Roughness * c0 + c1; + float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y; + float2 AB = float2(-1.04, 1.04) * a004 + r.zw; + return SpecularColor * AB.x + AB.y; +} + +// Compute the matrix used to transform tangent space normals to world space +// This expects DirectX normal maps in Mikk Tangent Space http://www.mikktspace.com +float3x3 compute_tangent_frame(float3 N, float3 P, float2 uv, out float3 T, out float3 B, out float sign_det) +{ + float3 dp1 = ddx(P); + float3 dp2 = ddy(P); + float2 duv1 = ddx(uv); + float2 duv2 = ddy(uv); + + sign_det = dot(dp2, cross(N, dp1)) > 0.0 ? -1 : 1; + + float3x3 M = float3x3(dp1, dp2, cross(dp1, dp2)); + float2x3 inverseM = float2x3(cross(M[1], M[2]), cross(M[2], M[0])); + T = normalize(mul(float2(duv1.x, duv2.x), inverseM)); + B = normalize(mul(float2(duv1.y, duv2.y), inverseM)); + return float3x3(T, B, N); +} + +float GetAttenForLight(float4 lightAtten, int lightNum) +{ +#if (NUM_LIGHTS > 1) + if (lightNum == 1) return lightAtten.y; +#endif + +#if (NUM_LIGHTS > 2) + if (lightNum == 2) return lightAtten.z; +#endif + +#if (NUM_LIGHTS > 3) + if (lightNum == 3) return lightAtten.w; +#endif + + return lightAtten.x; +} + +// Calculate direct light for one source +float3 calculateLight(float3 lightIn, float3 lightIntensity, float3 lightOut, float3 normal, float3 fresnelReflectance, float roughness, float metalness, float lightDirectionAngle, float3 albedo) +{ + // Lh + float3 HalfAngle = normalize(lightIn + lightOut); + float cosLightIn = max(0.0, dot(normal, lightIn)); + float cosHalfAngle = max(0.0, dot(normal, HalfAngle)); + + // F - Calculate Fresnel term for direct lighting + float3 F = fresnelSchlick(fresnelReflectance, max(0.0, dot(HalfAngle, lightOut))); + + // D - Calculate normal distribution for specular BRDF + float D = ndfGGX(cosHalfAngle, roughness); + + // Calculate geometric attenuation for specular BRDF + float G = gaSchlickGGX(cosLightIn, lightDirectionAngle, roughness); + + // Diffuse scattering happens due to light being refracted multiple times by a dielectric medium + // Metals on the other hand either reflect or absorb energso diffuse contribution is always, zero + // To be energy conserving we must scale diffuse BRDF contribution based on Fresnel factor & metalness +#if SPECULAR + // Metalness is not used if F0 map is available + float3 kd = float3(1, 1, 1) - F; +#else + float3 kd = lerp(float3(1, 1, 1) - F, float3(0, 0, 0), metalness); +#endif + + float3 diffuseBRDF = kd * albedo; + + // Cook-Torrance specular microfacet BRDF + float3 specularBRDF = (F * D * G) / max(EPSILON, 4.0 * cosLightIn * lightDirectionAngle); +#if LIGHTMAPPED && !FLASHLIGHT + // Ambient light from static lights is already precomputed in the lightmap. Don't add it again + return specularBRDF * lightIntensity * cosLightIn; +#else + return (diffuseBRDF + specularBRDF) * lightIntensity * cosLightIn; +#endif +} + +// Get diffuse ambient light +float3 ambientLookupLightmap(float3 normal, float3 EnvAmbientCube[6], float3 textureNormal, float4 lightmapTexCoord1And2, float4 lightmapTexCoord3, sampler LightmapSampler, float4 g_DiffuseModulation) +{ + float2 bumpCoord1; + float2 bumpCoord2; + float2 bumpCoord3; + + ComputeBumpedLightmapCoordinates( + lightmapTexCoord1And2, lightmapTexCoord3.xy, + bumpCoord1, bumpCoord2, bumpCoord3); + + float3 lightmapColor1 = LightMapSample(LightmapSampler, bumpCoord1); + float3 lightmapColor2 = LightMapSample(LightmapSampler, bumpCoord2); + float3 lightmapColor3 = LightMapSample(LightmapSampler, bumpCoord3); + + float3 dp; + dp.x = saturate(dot(textureNormal, bumpBasis[0])); + dp.y = saturate(dot(textureNormal, bumpBasis[1])); + dp.z = saturate(dot(textureNormal, bumpBasis[2])); + dp *= dp; + + float3 diffuseLighting = dp.x * lightmapColor1 + + dp.y * lightmapColor2 + + dp.z * lightmapColor3; + + float sum = dot(dp, float3(1, 1, 1)); + diffuseLighting *= g_DiffuseModulation.xyz / sum; + return diffuseLighting; +} + +float3 ambientLookup(float3 normal, float3 EnvAmbientCube[6], float3 textureNormal, float4 lightmapTexCoord1And2, float4 lightmapTexCoord3, sampler LightmapSampler, float4 g_DiffuseModulation) +{ +#if LIGHTMAPPED + return ambientLookupLightmap(normal, EnvAmbientCube, textureNormal, lightmapTexCoord1And2, lightmapTexCoord3, LightmapSampler, g_DiffuseModulation); +#else + return PixelShaderAmbientLight(normal, EnvAmbientCube); +#endif +} + +// Create an ambient cube from the envmap +void setupEnvMapAmbientCube(out float3 EnvAmbientCube[6], sampler EnvmapSampler) +{ + float4 directionPosX = { 1, 0, 0, 12 }; float4 directionNegX = {-1, 0, 0, 12 }; + float4 directionPosY = { 0, 1, 0, 12 }; float4 directionNegY = { 0,-1, 0, 12 }; + float4 directionPosZ = { 0, 0, 1, 12 }; float4 directionNegZ = { 0, 0,-1, 12 }; + EnvAmbientCube[0] = ENV_MAP_SCALE * texCUBElod(EnvmapSampler, directionPosX).rgb; + EnvAmbientCube[1] = ENV_MAP_SCALE * texCUBElod(EnvmapSampler, directionNegX).rgb; + EnvAmbientCube[2] = ENV_MAP_SCALE * texCUBElod(EnvmapSampler, directionPosY).rgb; + EnvAmbientCube[3] = ENV_MAP_SCALE * texCUBElod(EnvmapSampler, directionNegY).rgb; + EnvAmbientCube[4] = ENV_MAP_SCALE * texCUBElod(EnvmapSampler, directionPosZ).rgb; + EnvAmbientCube[5] = ENV_MAP_SCALE * texCUBElod(EnvmapSampler, directionNegZ).rgb; +} + +#if PARALLAXOCCLUSION +float2 parallaxCorrect(float2 texCoord, float3 viewRelativeDir, sampler depthMap, float parallaxDepth, float parallaxCenter) +{ + float fLength = length( viewRelativeDir ); + float fParallaxLength = sqrt( fLength * fLength - viewRelativeDir.z * viewRelativeDir.z ) / viewRelativeDir.z; + float2 vParallaxDirection = normalize( viewRelativeDir.xy ); + float2 vParallaxOffsetTS = vParallaxDirection * fParallaxLength; + vParallaxOffsetTS *= parallaxDepth; + + // Compute all the derivatives: + float2 dx = ddx( texCoord ); + float2 dy = ddy( texCoord ); + + int nNumSteps = 20; + + float fCurrHeight = 0.0; + float fStepSize = 1.0 / (float) nNumSteps; + float fPrevHeight = 1.0; + float fNextHeight = 0.0; + + int nStepIndex = 0; + bool bCondition = true; + + float2 vTexOffsetPerStep = fStepSize * vParallaxOffsetTS; + float2 vTexCurrentOffset = texCoord; + float fCurrentBound = 1.0; + float fParallaxAmount = 0.0; + + float2 pt1 = 0; + float2 pt2 = 0; + + float2 texOffset2 = 0; + + while ( nStepIndex < nNumSteps ) + { + vTexCurrentOffset -= vTexOffsetPerStep; + + // Sample height map which in this case is stored in the alpha channel of the normal map: + fCurrHeight = parallaxCenter + tex2Dgrad( depthMap, vTexCurrentOffset, dx, dy ).a; + + fCurrentBound -= fStepSize; + + if ( fCurrHeight > fCurrentBound ) + { + pt1 = float2( fCurrentBound, fCurrHeight ); + pt2 = float2( fCurrentBound + fStepSize, fPrevHeight ); + + texOffset2 = vTexCurrentOffset - vTexOffsetPerStep; + + nStepIndex = nNumSteps + 1; + } + else + { + nStepIndex++; + fPrevHeight = fCurrHeight; + } + } // End of while ( nStepIndex < nNumSteps ) + + float fDelta2 = pt2.x - pt2.y; + float fDelta1 = pt1.x - pt1.y; + fParallaxAmount = (pt1.x * fDelta2 - pt2.x * fDelta1 ) / ( fDelta2 - fDelta1 ); + float2 vParallaxOffset = vParallaxOffsetTS * (1 - fParallaxAmount); + // The computed texture offset for the displaced point on the pseudo-extruded surface: + float2 texSample = texCoord - vParallaxOffset; + return texSample; +} +#endif + +float3 worldToRelative(float3 worldVector, float3 surfTangent, float3 surfBasis, float3 surfNormal) +{ + return float3( + dot(worldVector, surfTangent), + dot(worldVector, surfBasis), + dot(worldVector, surfNormal) + ); +} diff --git a/materialsystem/stdshaders/pbr_dx9.cpp b/materialsystem/stdshaders/pbr_dx9.cpp new file mode 100644 index 00000000..b4299fd2 --- /dev/null +++ b/materialsystem/stdshaders/pbr_dx9.cpp @@ -0,0 +1,616 @@ +//================================================================================================== +// +// Physically Based Rendering shader for brushes and models +// +//================================================================================================== + +// Includes for all shaders +#include "BaseVSShader.h" +#include "cpp_shader_constant_register_map.h" + +// Includes for PS30 +#include "pbr_vs30.inc" +#include "pbr_ps30.inc" + +// Includes for PS20b +#include "pbr_vs20b.inc" +#include "pbr_ps20b.inc" + +// Defining samplers +const Sampler_t SAMPLER_BASETEXTURE = SHADER_SAMPLER0; +const Sampler_t SAMPLER_NORMAL = SHADER_SAMPLER1; +const Sampler_t SAMPLER_ENVMAP = SHADER_SAMPLER2; +const Sampler_t SAMPLER_SHADOWDEPTH = SHADER_SAMPLER4; +const Sampler_t SAMPLER_RANDOMROTATION = SHADER_SAMPLER5; +const Sampler_t SAMPLER_FLASHLIGHT = SHADER_SAMPLER6; +const Sampler_t SAMPLER_LIGHTMAP = SHADER_SAMPLER7; +const Sampler_t SAMPLER_MRAO = SHADER_SAMPLER10; +const Sampler_t SAMPLER_EMISSIVE = SHADER_SAMPLER11; +const Sampler_t SAMPLER_SPECULAR = SHADER_SAMPLER12; + +// Convars +static ConVar mat_fullbright("mat_fullbright", "0", FCVAR_CHEAT); +static ConVar mat_specular("mat_specular", "1", FCVAR_CHEAT); +static ConVar mat_pbr_force_20b("mat_pbr_force_20b", "0", FCVAR_CHEAT); +static ConVar mat_pbr_parallaxmap("mat_pbr_parallaxmap", "1"); + +// Variables for this shader +struct PBR_Vars_t +{ + PBR_Vars_t() + { + memset(this, 0xFF, sizeof(*this)); + } + + int baseTexture; + int baseColor; + int normalTexture; + int bumpMap; + int envMap; + int baseTextureFrame; + int baseTextureTransform; + int useParallax; + int parallaxDepth; + int parallaxCenter; + int alphaTestReference; + int flashlightTexture; + int flashlightTextureFrame; + int emissionTexture; + int mraoTexture; + int useEnvAmbient; + int specularTexture; +}; + +// Beginning the shader +BEGIN_VS_SHADER(PBR, "PBR shader") + + // Setting up vmt parameters + BEGIN_SHADER_PARAMS; + SHADER_PARAM(ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0", ""); + SHADER_PARAM(ENVMAP, SHADER_PARAM_TYPE_ENVMAP, "", "Set the cubemap for this material."); + SHADER_PARAM(MRAOTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Texture with metalness in R, roughness in G, ambient occlusion in B."); + SHADER_PARAM(EMISSIONTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Emission texture"); + SHADER_PARAM(NORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Normal texture (deprecated, use $bumpmap)"); + SHADER_PARAM(BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "", "Normal texture"); + SHADER_PARAM(USEENVAMBIENT, SHADER_PARAM_TYPE_BOOL, "0", "Use the cubemaps to compute ambient light."); + SHADER_PARAM(SPECULARTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "Specular F0 RGB map"); + SHADER_PARAM(PARALLAX, SHADER_PARAM_TYPE_BOOL, "0", "Use Parallax Occlusion Mapping."); + SHADER_PARAM(PARALLAXDEPTH, SHADER_PARAM_TYPE_FLOAT, "0.0030", "Depth of the Parallax Map"); + SHADER_PARAM(PARALLAXCENTER, SHADER_PARAM_TYPE_FLOAT, "0.5", "Center depth of the Parallax Map"); + END_SHADER_PARAMS; + + // Setting up variables for this shader + void SetupVars(PBR_Vars_t &info) + { + info.baseTexture = BASETEXTURE; + info.baseColor = COLOR; + info.normalTexture = NORMALTEXTURE; + info.bumpMap = BUMPMAP; + info.baseTextureFrame = FRAME; + info.baseTextureTransform = BASETEXTURETRANSFORM; + info.alphaTestReference = ALPHATESTREFERENCE; + info.flashlightTexture = FLASHLIGHTTEXTURE; + info.flashlightTextureFrame = FLASHLIGHTTEXTUREFRAME; + info.envMap = ENVMAP; + info.emissionTexture = EMISSIONTEXTURE; + info.mraoTexture = MRAOTEXTURE; + info.useEnvAmbient = USEENVAMBIENT; + info.specularTexture = SPECULARTEXTURE; + info.useParallax = PARALLAX; + info.parallaxDepth = PARALLAXDEPTH; + info.parallaxCenter = PARALLAXCENTER; + }; + + // Initializing parameters + SHADER_INIT_PARAMS() + { + // Fallback for changed parameter + if (params[NORMALTEXTURE]->IsDefined()) + params[BUMPMAP]->SetStringValue(params[NORMALTEXTURE]->GetStringValue()); + + // Dynamic lights need a bumpmap + if (!params[BUMPMAP]->IsDefined()) + params[BUMPMAP]->SetStringValue("dev/flat_normal"); + + // Set a good default mrao texture + if (!params[MRAOTEXTURE]->IsDefined()) + params[MRAOTEXTURE]->SetStringValue("dev/pbr_mraotexture"); + + // PBR relies heavily on envmaps + if (!params[ENVMAP]->IsDefined()) + params[ENVMAP]->SetStringValue("env_cubemap"); + + // Check if the hardware supports flashlight border color + if (g_pHardwareConfig->SupportsBorderColor()) + { + params[FLASHLIGHTTEXTURE]->SetStringValue("effects/flashlight_border"); + } + else + { + params[FLASHLIGHTTEXTURE]->SetStringValue("effects/flashlight001"); + } + }; + + // Define shader fallback + SHADER_FALLBACK + { + return 0; + }; + + SHADER_INIT + { + PBR_Vars_t info; + SetupVars(info); + + Assert(info.flashlightTexture >= 0); + LoadTexture(info.flashlightTexture, TEXTUREFLAGS_SRGB); + + Assert(info.bumpMap >= 0); + LoadBumpMap(info.bumpMap); + + Assert(info.envMap >= 0); + int envMapFlags = g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0; + envMapFlags |= TEXTUREFLAGS_ALL_MIPS; + LoadCubeMap(info.envMap, envMapFlags); + + if (info.emissionTexture >= 0 && params[EMISSIONTEXTURE]->IsDefined()) + LoadTexture(info.emissionTexture, TEXTUREFLAGS_SRGB); + + Assert(info.mraoTexture >= 0); + LoadTexture(info.mraoTexture, 0); + + if (params[info.baseTexture]->IsDefined()) + { + LoadTexture(info.baseTexture, TEXTUREFLAGS_SRGB); + } + + if (params[info.specularTexture]->IsDefined()) + { + LoadTexture(info.specularTexture, TEXTUREFLAGS_SRGB); + } + + if (IS_FLAG_SET(MATERIAL_VAR_MODEL)) // Set material var2 flags specific to models + { + SET_FLAGS2(MATERIAL_VAR2_SUPPORTS_HW_SKINNING); // Required for skinning + SET_FLAGS2(MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL); // Required for dynamic lighting + SET_FLAGS2(MATERIAL_VAR2_NEEDS_TANGENT_SPACES); // Required for dynamic lighting + SET_FLAGS2(MATERIAL_VAR2_LIGHTING_VERTEX_LIT); // Required for dynamic lighting + SET_FLAGS2(MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS); // Required for ambient cube + SET_FLAGS2(MATERIAL_VAR2_SUPPORTS_FLASHLIGHT); // Required for flashlight + SET_FLAGS2(MATERIAL_VAR2_USE_FLASHLIGHT); // Required for flashlight + } + else // Set material var2 flags specific to brushes + { + SET_FLAGS2(MATERIAL_VAR2_LIGHTING_LIGHTMAP); // Required for lightmaps + SET_FLAGS2(MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP); // Required for lightmaps + SET_FLAGS2(MATERIAL_VAR2_SUPPORTS_FLASHLIGHT); // Required for flashlight + SET_FLAGS2(MATERIAL_VAR2_USE_FLASHLIGHT); // Required for flashlight + } + }; + + // Drawing the shader + SHADER_DRAW + { + PBR_Vars_t info; + SetupVars(info); + + // Setting up booleans + bool bHasBaseTexture = (info.baseTexture != -1) && params[info.baseTexture]->IsTexture(); + bool bHasNormalTexture = (info.bumpMap != -1) && params[info.bumpMap]->IsTexture(); + bool bHasMraoTexture = (info.mraoTexture != -1) && params[info.mraoTexture]->IsTexture(); + bool bHasEmissionTexture = (info.emissionTexture != -1) && params[info.emissionTexture]->IsTexture(); + bool bHasEnvTexture = (info.envMap != -1) && params[info.envMap]->IsTexture(); + bool bIsAlphaTested = IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) != 0; + bool bHasFlashlight = UsingFlashlight(params); + bool bHasColor = (info.baseColor != -1) && params[info.baseColor]->IsDefined(); + bool bLightMapped = !IS_FLAG_SET(MATERIAL_VAR_MODEL); + bool bUseEnvAmbient = (info.useEnvAmbient != -1) && (params[info.useEnvAmbient]->GetIntValue() == 1); + bool bHasSpecularTexture = (info.specularTexture != -1) && params[info.specularTexture]->IsTexture(); + + // Determining whether we're dealing with a fully opaque material + BlendType_t nBlendType = EvaluateBlendRequirements(info.baseTexture, true); + bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested; + + if (IsSnapshotting()) + { + // If alphatest is on, enable it + pShaderShadow->EnableAlphaTest(bIsAlphaTested); + + if (info.alphaTestReference != -1 && params[info.alphaTestReference]->GetFloatValue() > 0.0f) + { + pShaderShadow->AlphaFunc(SHADER_ALPHAFUNC_GEQUAL, params[info.alphaTestReference]->GetFloatValue()); + } + + if (bHasFlashlight ) + { + pShaderShadow->EnableBlending(true); + pShaderShadow->BlendFunc(SHADER_BLEND_ONE, SHADER_BLEND_ONE); // Additive blending + } + else + { + SetDefaultBlendingShadowState(info.baseTexture, true); + } + + int nShadowFilterMode = bHasFlashlight ? g_pHardwareConfig->GetShadowFilterMode() : 0; + + // Setting up samplers + pShaderShadow->EnableTexture(SAMPLER_BASETEXTURE, true); // Basecolor texture + pShaderShadow->EnableSRGBRead(SAMPLER_BASETEXTURE, true); // Basecolor is sRGB + pShaderShadow->EnableTexture(SAMPLER_EMISSIVE, true); // Emission texture + pShaderShadow->EnableSRGBRead(SAMPLER_EMISSIVE, true); // Emission is sRGB + pShaderShadow->EnableTexture(SAMPLER_LIGHTMAP, true); // Lightmap texture + pShaderShadow->EnableSRGBRead(SAMPLER_LIGHTMAP, false); // Lightmaps aren't sRGB + pShaderShadow->EnableTexture(SAMPLER_MRAO, true); // MRAO texture + pShaderShadow->EnableSRGBRead(SAMPLER_MRAO, false); // MRAO isn't sRGB + pShaderShadow->EnableTexture(SAMPLER_NORMAL, true); // Normal texture + pShaderShadow->EnableSRGBRead(SAMPLER_NORMAL, false); // Normals aren't sRGB + pShaderShadow->EnableTexture(SAMPLER_SPECULAR, true); // Specular F0 texture + pShaderShadow->EnableSRGBRead(SAMPLER_SPECULAR, true); // Specular F0 is sRGB + + // If the flashlight is on, set up its textures + if (bHasFlashlight) + { + pShaderShadow->EnableTexture(SAMPLER_SHADOWDEPTH, true); // Shadow depth map + pShaderShadow->SetShadowDepthFiltering(SAMPLER_SHADOWDEPTH); + pShaderShadow->EnableSRGBRead(SAMPLER_SHADOWDEPTH, false); + pShaderShadow->EnableTexture(SAMPLER_RANDOMROTATION, true); // Noise map + pShaderShadow->EnableTexture(SAMPLER_FLASHLIGHT, true); // Flashlight cookie + pShaderShadow->EnableSRGBRead(SAMPLER_FLASHLIGHT, true); + } + + // Setting up envmap + if (bHasEnvTexture) + { + pShaderShadow->EnableTexture(SAMPLER_ENVMAP, true); // Envmap + if (g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE) + { + pShaderShadow->EnableSRGBRead(SAMPLER_ENVMAP, true); // Envmap is only sRGB with HDR disabled? + } + } + + // Enabling sRGB writing + // See common_ps_fxc.h line 349 + // PS2b shaders and up write sRGB + pShaderShadow->EnableSRGBWrite(true); + + if (IS_FLAG_SET(MATERIAL_VAR_MODEL)) + { + // We only need the position and surface normal + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_FORMAT_COMPRESSED; + // We need three texcoords, all in the default float2 size + pShaderShadow->VertexShaderVertexFormat(flags, 1, 0, 0); + } + else + { + // We need the position, surface normal, and vertex compression format + unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL; + // We only need one texcoord, in the default float2 size + pShaderShadow->VertexShaderVertexFormat(flags, 3, 0, 0); + } + + int useParallax = params[info.useParallax]->GetIntValue(); + if (!mat_pbr_parallaxmap.GetBool()) + { + useParallax = 0; + } + + if (!g_pHardwareConfig->SupportsShaderModel_3_0() || mat_pbr_force_20b.GetBool()) + { + // Setting up static vertex shader + DECLARE_STATIC_VERTEX_SHADER(pbr_vs20b); + SET_STATIC_VERTEX_SHADER(pbr_vs20b); + + // Setting up static pixel shader + DECLARE_STATIC_PIXEL_SHADER(pbr_ps20b); + SET_STATIC_PIXEL_SHADER_COMBO(FLASHLIGHT, bHasFlashlight); + SET_STATIC_PIXEL_SHADER_COMBO(FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode); + SET_STATIC_PIXEL_SHADER_COMBO(LIGHTMAPPED, bLightMapped); + SET_STATIC_PIXEL_SHADER_COMBO(EMISSIVE, bHasEmissionTexture); + SET_STATIC_PIXEL_SHADER_COMBO(SPECULAR, 0); + SET_STATIC_PIXEL_SHADER(pbr_ps20b); + } + else + { + // Setting up static vertex shader + DECLARE_STATIC_VERTEX_SHADER(pbr_vs30); + SET_STATIC_VERTEX_SHADER(pbr_vs30); + + // Setting up static pixel shader + DECLARE_STATIC_PIXEL_SHADER(pbr_ps30); + SET_STATIC_PIXEL_SHADER_COMBO(FLASHLIGHT, bHasFlashlight); + SET_STATIC_PIXEL_SHADER_COMBO(FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode); + SET_STATIC_PIXEL_SHADER_COMBO(LIGHTMAPPED, bLightMapped); + SET_STATIC_PIXEL_SHADER_COMBO(USEENVAMBIENT, bUseEnvAmbient); + SET_STATIC_PIXEL_SHADER_COMBO(EMISSIVE, bHasEmissionTexture); + SET_STATIC_PIXEL_SHADER_COMBO(SPECULAR, bHasSpecularTexture); + SET_STATIC_PIXEL_SHADER_COMBO(PARALLAXOCCLUSION, useParallax); + SET_STATIC_PIXEL_SHADER(pbr_ps30); + } + + // Setting up fog + DefaultFog(); // I think this is correct + + // HACK HACK HACK - enable alpha writes all the time so that we have them for underwater stuff + pShaderShadow->EnableAlphaWrites(bFullyOpaque); + } + else // Not snapshotting -- begin dynamic state + { + bool bLightingOnly = mat_fullbright.GetInt() == 2 && !IS_FLAG_SET(MATERIAL_VAR_NO_DEBUG_OVERRIDE); + + // Setting up albedo texture + if (bHasBaseTexture) + { + BindTexture(SAMPLER_BASETEXTURE, info.baseTexture, info.baseTextureFrame); + } + else + { + pShaderAPI->BindStandardTexture(SAMPLER_BASETEXTURE, TEXTURE_GREY); + } + + // Setting up vmt color + Vector color; + if (bHasColor) + { + params[info.baseColor]->GetVecValue(color.Base(), 3); + } + else + { + color = Vector{1.f, 1.f, 1.f}; + } + pShaderAPI->SetPixelShaderConstant(PSREG_SELFILLUMTINT, color.Base()); + + // Setting up environment map + if (bHasEnvTexture) + { + BindTexture(SAMPLER_ENVMAP, info.envMap, 0); + } + else + { + pShaderAPI->BindStandardTexture(SAMPLER_ENVMAP, TEXTURE_BLACK); + } + + // Setting up emissive texture + if (bHasEmissionTexture) + { + BindTexture(SAMPLER_EMISSIVE, info.emissionTexture, 0); + } + else + { + pShaderAPI->BindStandardTexture(SAMPLER_EMISSIVE, TEXTURE_BLACK); + } + + // Setting up normal map + if (bHasNormalTexture) + { + BindTexture(SAMPLER_NORMAL, info.bumpMap, 0); + } + else + { + pShaderAPI->BindStandardTexture(SAMPLER_NORMAL, TEXTURE_NORMALMAP_FLAT); + } + + // Setting up mrao map + if (bHasMraoTexture) + { + BindTexture(SAMPLER_MRAO, info.mraoTexture, 0); + } + else + { + pShaderAPI->BindStandardTexture(SAMPLER_MRAO, TEXTURE_WHITE); + } + + if (bHasSpecularTexture) + { + BindTexture(SAMPLER_SPECULAR, info.specularTexture, 0); + } + else + { + pShaderAPI->BindStandardTexture(SAMPLER_SPECULAR, TEXTURE_BLACK); + } + + // Getting the light state + LightState_t lightState; + pShaderAPI->GetDX9LightState(&lightState); + + // Brushes don't need ambient cubes or dynamic lights + if (!IS_FLAG_SET(MATERIAL_VAR_MODEL)) + { + lightState.m_bAmbientLight = false; + lightState.m_nNumLights = 0; + } + + // Setting up the flashlight related textures and variables + bool bFlashlightShadows = false; + if (bHasFlashlight) + { + Assert(info.flashlightTexture >= 0 && info.flashlightTextureFrame >= 0); + Assert(params[info.flashlightTexture]->IsTexture()); + BindTexture(SAMPLER_FLASHLIGHT, info.flashlightTexture, info.flashlightTextureFrame); + VMatrix worldToTexture; + ITexture *pFlashlightDepthTexture; + FlashlightState_t state = pShaderAPI->GetFlashlightStateEx(worldToTexture, &pFlashlightDepthTexture); + bFlashlightShadows = state.m_bEnableShadows && (pFlashlightDepthTexture != NULL); + + SetFlashLightColorFromState(state, pShaderAPI, PSREG_FLASHLIGHT_COLOR); + + if (pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows) + { + BindTexture(SAMPLER_SHADOWDEPTH, pFlashlightDepthTexture, 0); + pShaderAPI->BindStandardTexture(SAMPLER_RANDOMROTATION, TEXTURE_SHADOW_NOISE_2D); + } + } + + // Getting fog info + MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); + int fogIndex = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z) ? 1 : 0; + + // Getting skinning info + int numBones = pShaderAPI->GetCurrentNumBones(); + + // Some debugging stuff + bool bWriteDepthToAlpha = false; + bool bWriteWaterFogToAlpha = false; + if (bFullyOpaque) + { + bWriteDepthToAlpha = pShaderAPI->ShouldWriteDepthToDestAlpha(); + bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z); + AssertMsg(!(bWriteDepthToAlpha && bWriteWaterFogToAlpha), + "Can't write two values to alpha at the same time."); + } + + float vEyePos_SpecExponent[4]; + pShaderAPI->GetWorldSpaceCameraPosition(vEyePos_SpecExponent); + + // Determining the max level of detail for the envmap + int iEnvMapLOD = 6; + auto envTexture = params[info.envMap]->GetTextureValue(); + if (envTexture) + { + // Get power of 2 of texture width + int width = envTexture->GetMappingWidth(); + int mips = 0; + while (width >>= 1) + ++mips; + + // Cubemap has 4 sides so 2 mips less + iEnvMapLOD = mips; + } + + // Dealing with very high and low resolution cubemaps + if (iEnvMapLOD > 12) + iEnvMapLOD = 12; + if (iEnvMapLOD < 4) + iEnvMapLOD = 4; + + // This has some spare space + vEyePos_SpecExponent[3] = iEnvMapLOD; + pShaderAPI->SetPixelShaderConstant(PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_SpecExponent, 1); + + // Setting lightmap texture + s_pShaderAPI->BindStandardTexture(SAMPLER_LIGHTMAP, TEXTURE_LIGHTMAP_BUMPED); + + if (!g_pHardwareConfig->SupportsShaderModel_3_0() || mat_pbr_force_20b.GetBool()) + { + // Setting up dynamic vertex shader + DECLARE_DYNAMIC_VERTEX_SHADER(pbr_vs20b); + SET_DYNAMIC_VERTEX_SHADER_COMBO(DOWATERFOG, fogIndex); + SET_DYNAMIC_VERTEX_SHADER_COMBO(SKINNING, numBones > 0); + SET_DYNAMIC_VERTEX_SHADER_COMBO(LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) != 0); + SET_DYNAMIC_VERTEX_SHADER_COMBO(COMPRESSED_VERTS, (int)vertexCompression); + SET_DYNAMIC_VERTEX_SHADER_COMBO(NUM_LIGHTS, lightState.m_nNumLights); + SET_DYNAMIC_VERTEX_SHADER(pbr_vs20b); + + // Setting up dynamic pixel shader + DECLARE_DYNAMIC_PIXEL_SHADER(pbr_ps20b); + SET_DYNAMIC_PIXEL_SHADER_COMBO(NUM_LIGHTS, lightState.m_nNumLights); + SET_DYNAMIC_PIXEL_SHADER_COMBO(WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha); + SET_DYNAMIC_PIXEL_SHADER_COMBO(WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha); + SET_DYNAMIC_PIXEL_SHADER_COMBO(PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo()); + SET_DYNAMIC_PIXEL_SHADER_COMBO(FLASHLIGHTSHADOWS, bFlashlightShadows); + SET_DYNAMIC_PIXEL_SHADER(pbr_ps20b); + } + else + { + // Setting up dynamic vertex shader + DECLARE_DYNAMIC_VERTEX_SHADER(pbr_vs30); + SET_DYNAMIC_VERTEX_SHADER_COMBO(DOWATERFOG, fogIndex); + SET_DYNAMIC_VERTEX_SHADER_COMBO(SKINNING, numBones > 0); + SET_DYNAMIC_VERTEX_SHADER_COMBO(LIGHTING_PREVIEW, pShaderAPI->GetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING) != 0); + SET_DYNAMIC_VERTEX_SHADER_COMBO(COMPRESSED_VERTS, (int)vertexCompression); + SET_DYNAMIC_VERTEX_SHADER_COMBO(NUM_LIGHTS, lightState.m_nNumLights); + SET_DYNAMIC_VERTEX_SHADER(pbr_vs30); + + // Setting up dynamic pixel shader + DECLARE_DYNAMIC_PIXEL_SHADER(pbr_ps30); + SET_DYNAMIC_PIXEL_SHADER_COMBO(NUM_LIGHTS, lightState.m_nNumLights); + SET_DYNAMIC_PIXEL_SHADER_COMBO(WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha); + SET_DYNAMIC_PIXEL_SHADER_COMBO(WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha); + SET_DYNAMIC_PIXEL_SHADER_COMBO(PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo()); + SET_DYNAMIC_PIXEL_SHADER_COMBO(FLASHLIGHTSHADOWS, bFlashlightShadows); + SET_DYNAMIC_PIXEL_SHADER(pbr_ps30); + } + + // Setting up base texture transform + SetVertexShaderTextureTransform(VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.baseTextureTransform); + + // This is probably important + SetModulationPixelShaderDynamicState_LinearColorSpace(1); + + // Send ambient cube to the pixel shader, force to black if not available + pShaderAPI->SetPixelShaderStateAmbientLightCube(PSREG_AMBIENT_CUBE, !lightState.m_bAmbientLight); + + // Send lighting array to the pixel shader + pShaderAPI->CommitPixelShaderLighting(PSREG_LIGHT_INFO_ARRAY); + + // Handle mat_fullbright 2 (diffuse lighting only) + if (bLightingOnly) + { + pShaderAPI->BindStandardTexture(SAMPLER_BASETEXTURE, TEXTURE_GREY); // Basecolor + } + + // Handle mat_specular 0 (no envmap reflections) + if (!mat_specular.GetBool()) + { + pShaderAPI->BindStandardTexture(SAMPLER_ENVMAP, TEXTURE_BLACK); // Envmap + } + + // Sending fog info to the pixel shader + pShaderAPI->SetPixelShaderFogParams(PSREG_FOG_PARAMS); + + // Set up shader modulation color + float modulationColor[4] = { 1.0, 1.0, 1.0, 1.0 }; + ComputeModulationColor(modulationColor); + float flLScale = pShaderAPI->GetLightMapScaleFactor(); + modulationColor[0] *= flLScale; + modulationColor[1] *= flLScale; + modulationColor[2] *= flLScale; + pShaderAPI->SetPixelShaderConstant(PSREG_DIFFUSE_MODULATION, modulationColor); + + // More flashlight related stuff + if (bHasFlashlight) + { + VMatrix worldToTexture; + float atten[4], pos[4], tweaks[4]; + + const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState(worldToTexture); + SetFlashLightColorFromState(flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR); + + BindTexture(SAMPLER_FLASHLIGHT, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame); + + // Set the flashlight attenuation factors + atten[0] = flashlightState.m_fConstantAtten; + atten[1] = flashlightState.m_fLinearAtten; + atten[2] = flashlightState.m_fQuadraticAtten; + atten[3] = flashlightState.m_FarZ; + pShaderAPI->SetPixelShaderConstant(PSREG_FLASHLIGHT_ATTENUATION, atten, 1); + + // Set the flashlight origin + pos[0] = flashlightState.m_vecLightOrigin[0]; + pos[1] = flashlightState.m_vecLightOrigin[1]; + pos[2] = flashlightState.m_vecLightOrigin[2]; + pShaderAPI->SetPixelShaderConstant(PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1); + + pShaderAPI->SetPixelShaderConstant(PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4); + + // Tweaks associated with a given flashlight + tweaks[0] = ShadowFilterFromState(flashlightState); + tweaks[1] = ShadowAttenFromState(flashlightState); + HashShadow2DJitter(flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3]); + pShaderAPI->SetPixelShaderConstant(PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1); + } + + float flParams[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + // Parallax Depth (the strength of the effect) + flParams[0] = GetFloatParam(info.parallaxDepth, params, 3.0f); + // Parallax Center (the height at which it's not moved) + flParams[1] = GetFloatParam(info.parallaxCenter, params, 3.0f); + pShaderAPI->SetPixelShaderConstant(27, flParams, 1); + + } + + // Actually draw the shader + Draw(); + }; + +// Closing it off +END_SHADER; diff --git a/materialsystem/stdshaders/pbr_ps20b.fxc b/materialsystem/stdshaders/pbr_ps20b.fxc new file mode 100644 index 00000000..aad70ce7 --- /dev/null +++ b/materialsystem/stdshaders/pbr_ps20b.fxc @@ -0,0 +1,193 @@ +//================================================================================================== +// +// Physically Based Rendering pixel shader for brushes and models +// +//================================================================================================== + +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" +// STATIC: "LIGHTMAPPED" "0..1" +// STATIC: "EMISSIVE" "0..1" +// STATIC: "SPECULAR" "0..1" + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" + +// Can't write fog to alpha if there is no fog +// SKIP: ($PIXELFOGTYPE == 0) && ($WRITEWATERFOGTODESTALPHA != 0) +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) +// Flashlight shadow filter mode is irrelevant if there is no flashlight +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) + +#include "common_ps_fxc.h" +#include "common_flashlight_fxc.h" +#include "common_lightmappedgeneric_fxc.h" +#include "shader_constant_register_map.h" + +#include "pbr_common_ps2_3_x.h" + +const float4 g_DiffuseModulation : register(PSREG_DIFFUSE_MODULATION); +const float4 g_ShadowTweaks : register(PSREG_ENVMAP_TINT__SHADOW_TWEAKS); +const float3 cAmbientCube[6] : register(PSREG_AMBIENT_CUBE); +const float4 g_EyePos : register(PSREG_EYEPOS_SPEC_EXPONENT); +const float4 g_FogParams : register(PSREG_FOG_PARAMS); +const float4 g_FlashlightAttenuationFactors : register(PSREG_FLASHLIGHT_ATTENUATION); +const float4 g_FlashlightPos : register(PSREG_FLASHLIGHT_POSITION_RIM_BOOST); +const float4x4 g_FlashlightWorldToTexture : register(PSREG_FLASHLIGHT_TO_WORLD_TEXTURE); +PixelShaderLightInfo cLightInfo[3] : register(PSREG_LIGHT_INFO_ARRAY); // 2 registers each - 6 registers total (4th light spread across w's) +const float4 g_BaseColor : register(PSREG_SELFILLUMTINT); + +sampler BaseTextureSampler : register(s0); // Base map, selfillum in alpha +sampler NormalTextureSampler : register(s1); // Normal map +sampler EnvmapSampler : register(s2); // Cubemap +sampler ShadowDepthSampler : register(s4); // Flashlight shadow depth map sampler +sampler RandRotSampler : register(s5); // RandomRotation sampler +sampler FlashlightSampler : register(s6); // Flashlight cookie +sampler LightmapSampler : register(s7); // Lightmap +sampler MRAOTextureSampler : register(s10); // MRAO texture +#if EMISSIVE +sampler EmissionTextureSampler : register(s11); // Emission texture +#endif +#if SPECULAR +sampler SpecularTextureSampler : register(s12); // Specular F0 texture +#endif + +#define ENVMAPLOD (g_EyePos.a) + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float4 lightAtten : TEXCOORD1; + float3 worldNormal : TEXCOORD2; + float3 worldTangent : TEXCOORD3; + float3 worldPos : TEXCOORD4; + float3 projPos : TEXCOORD5; + float4 lightmapTexCoord1And2 : TEXCOORD6; + float4 lightmapTexCoord3 : TEXCOORD7; +}; + +// Entry point +float4 main(PS_INPUT i) : COLOR +{ + float2 correctedTexCoord = i.baseTexCoord; + + float4 albedo = tex2D(BaseTextureSampler, correctedTexCoord); + albedo.xyz *= g_BaseColor; + + float3 mrao = tex2D(MRAOTextureSampler, correctedTexCoord).xyz; + float metalness = mrao.x, roughness = mrao.y, ambientOcclusion = mrao.z; +#if EMISSIVE + float3 emission = tex2D(EmissionTextureSampler, correctedTexCoord).xyz; +#endif +#if SPECULAR + float3 specular = tex2D(SpecularTextureSampler, correctedTexCoord).xyz; +#endif + float3x3 normalBasis = float3x3(i.worldTangent, cross(i.worldNormal, i.worldTangent), i.worldNormal); + float3 textureNormal = normalize((tex2D( NormalTextureSampler, correctedTexCoord).xyz - float3(0.5, 0.5, 0.5)) * 2); + float3 normal = normalize(mul(textureNormal, normalBasis)); // World Normal + + float3 outgoingLightDirection = normalize(g_EyePos.xyz - i.worldPos); // Lo + float lightDirectionAngle = max(0, dot(normal, outgoingLightDirection)); // cosLo + + float3 specularReflectionVector = 2.0 * lightDirectionAngle * normal - outgoingLightDirection; // Lr + +#if SPECULAR + float3 fresnelReflectance = specular.rgb; // F0 +#else + float3 dielectricCoefficient = 0.04; //F0 dielectric + float3 fresnelReflectance = lerp(dielectricCoefficient, albedo.rgb, metalness); // F0 +#endif + + // Start ambient + float3 ambientLighting = 0.0; + if (!FLASHLIGHT) + { + float3 diffuseIrradiance = ambientLookup(normal, cAmbientCube, textureNormal, i.lightmapTexCoord1And2, i.lightmapTexCoord3, LightmapSampler, g_DiffuseModulation); + float3 ambientLightingFresnelTerm = fresnelSchlick(fresnelReflectance, lightDirectionAngle); // F +#if SPECULAR + float3 diffuseContributionFactor = 1 - ambientLightingFresnelTerm; // kd +#else + float3 diffuseContributionFactor = lerp(1 - ambientLightingFresnelTerm, 0, metalness); ; // kd +#endif + float3 diffuseIBL = diffuseContributionFactor * albedo.rgb * diffuseIrradiance; + + float4 specularUV = float4(specularReflectionVector, roughness * ENVMAPLOD); + float3 lookupHigh = ENV_MAP_SCALE * texCUBE(EnvmapSampler, specularUV).xyz; + + float3 lookupLow = PixelShaderAmbientLight(specularReflectionVector, cAmbientCube); + float3 specularIrradiance = lerp(lookupHigh, lookupLow, roughness * roughness); + float3 specularIBL = specularIrradiance * EnvBRDFApprox(fresnelReflectance, roughness, lightDirectionAngle); + + ambientLighting = (diffuseIBL + specularIBL) * ambientOcclusion; + } + // End ambient + + // Start direct + float3 directLighting = 0.0; + if (!FLASHLIGHT) { + for (int n = 0; n < NUM_LIGHTS; ++n) + { + float3 LightIn = normalize(PixelShaderGetLightVector(i.worldPos, cLightInfo, n)); + float3 LightColor = PixelShaderGetLightColor(cLightInfo, n) * GetAttenForLight(i.lightAtten, n); // Li + + directLighting += calculateLight(LightIn, LightColor, outgoingLightDirection, + normal, fresnelReflectance, roughness, metalness, lightDirectionAngle, albedo.rgb); + } + } + // End direct + + // Start flashlight + if (FLASHLIGHT) + { + float4 flashlightSpacePosition = mul(float4(i.worldPos, 1.0), g_FlashlightWorldToTexture); + clip( flashlightSpacePosition.w ); // stop projected textures from projecting backwards (only really happens if they have a big FOV because they get frustum culled.) + float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w; + + float3 delta = g_FlashlightPos.xyz - i.worldPos; + float distSquared = dot(delta, delta); + float dist = sqrt(distSquared); + + float3 flashlightColor = tex2D(FlashlightSampler, vProjCoords.xy); + flashlightColor *= cFlashlightColor.xyz; + +#if FLASHLIGHTSHADOWS + float flashlightShadow = DoFlashlightShadow(ShadowDepthSampler, RandRotSampler, vProjCoords, i.projPos, FLASHLIGHTDEPTHFILTERMODE, g_ShadowTweaks, true); + float flashlightAttenuated = lerp(flashlightShadow, 1.0, g_ShadowTweaks.y); // Blend between fully attenuated and not attenuated + float fAtten = saturate(dot(g_FlashlightAttenuationFactors.xyz, float3(1.0, 1.0 / dist, 1.0 / distSquared))); + flashlightShadow = saturate(lerp(flashlightAttenuated, flashlightShadow, fAtten)); // Blend between shadow and above, according to light attenuation + + flashlightColor *= flashlightShadow; +#endif + float farZ = g_FlashlightAttenuationFactors.w; + float endFalloffFactor = RemapValClamped(dist, farZ, 0.6 * farZ, 0.0, 1.0); + + float3 flashLightIntensity = flashlightColor * endFalloffFactor; + + float3 flashLightIn = normalize(g_FlashlightPos.xyz - i.worldPos); + + directLighting += max(0, calculateLight(flashLightIn, flashLightIntensity, outgoingLightDirection, + normal, fresnelReflectance, roughness, metalness, lightDirectionAngle, albedo.rgb)); + } + // End flashlight + + float fogFactor = CalcPixelFogFactor(PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos.z, i.projPos.z); + +#if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + float alpha = fogFactor; +#else + float alpha = albedo.a; +#endif + + bool bWriteDepthToAlpha = (WRITE_DEPTH_TO_DESTALPHA != 0) && (WRITEWATERFOGTODESTALPHA == 0); + + float3 combinedLighting = directLighting + ambientLighting; +#if EMISSIVE && !FLASHLIGHT + combinedLighting += emission; +#endif + + return FinalOutput(float4(combinedLighting, alpha), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.projPos.z); +} diff --git a/materialsystem/stdshaders/pbr_ps30.fxc b/materialsystem/stdshaders/pbr_ps30.fxc new file mode 100644 index 00000000..e661f6e2 --- /dev/null +++ b/materialsystem/stdshaders/pbr_ps30.fxc @@ -0,0 +1,227 @@ +//================================================================================================== +// +// Physically Based Rendering pixel shader for brushes and models +// +//================================================================================================== + +// STATIC: "FLASHLIGHT" "0..1" +// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" +// STATIC: "LIGHTMAPPED" "0..1" +// STATIC: "USEENVAMBIENT" "0..1" +// STATIC: "EMISSIVE" "0..1" +// STATIC: "SPECULAR" "0..1" +// STATIC: "PARALLAXOCCLUSION" "0..1" + +// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1" +// DYNAMIC: "PIXELFOGTYPE" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" +// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" +// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" + +// Can't write fog to alpha if there is no fog +// SKIP: ($PIXELFOGTYPE == 0) && ($WRITEWATERFOGTODESTALPHA != 0) +// We don't care about flashlight depth unless the flashlight is on +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 ) +// Flashlight shadow filter mode is irrelevant if there is no flashlight +// SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTDEPTHFILTERMODE != 0 ) + +#include "common_ps_fxc.h" +#include "common_flashlight_fxc.h" +#include "common_lightmappedgeneric_fxc.h" +#include "shader_constant_register_map.h" + +#include "pbr_common_ps2_3_x.h" + +const float4 g_DiffuseModulation : register(PSREG_DIFFUSE_MODULATION); +const float4 g_ShadowTweaks : register(PSREG_ENVMAP_TINT__SHADOW_TWEAKS); +const float3 cAmbientCube[6] : register(PSREG_AMBIENT_CUBE); +const float4 g_EyePos : register(PSREG_EYEPOS_SPEC_EXPONENT); +const float4 g_FogParams : register(PSREG_FOG_PARAMS); +const float4 g_FlashlightAttenuationFactors : register(PSREG_FLASHLIGHT_ATTENUATION); +const float4 g_FlashlightPos : register(PSREG_FLASHLIGHT_POSITION_RIM_BOOST); +const float4x4 g_FlashlightWorldToTexture : register(PSREG_FLASHLIGHT_TO_WORLD_TEXTURE); +PixelShaderLightInfo cLightInfo[3] : register(PSREG_LIGHT_INFO_ARRAY); // 2 registers each - 6 registers total (4th light spread across w's) +const float4 g_BaseColor : register(PSREG_SELFILLUMTINT); + +#if PARALLAXOCCLUSION +const float4 g_ParallaxParms : register( c27 ); +#define PARALLAX_DEPTH g_ParallaxParms.r +#define PARALLAX_CENTER g_ParallaxParms.g +#endif + +sampler BaseTextureSampler : register(s0); // Base map, selfillum in alpha +sampler NormalTextureSampler : register(s1); // Normal map +sampler EnvmapSampler : register(s2); // Cubemap +sampler ShadowDepthSampler : register(s4); // Flashlight shadow depth map sampler +sampler RandRotSampler : register(s5); // RandomRotation sampler +sampler FlashlightSampler : register(s6); // Flashlight cookie +sampler LightmapSampler : register(s7); // Lightmap +sampler MRAOTextureSampler : register(s10); // MRAO texture +#if EMISSIVE +sampler EmissionTextureSampler : register(s11); // Emission texture +#endif +#if SPECULAR +sampler SpecularTextureSampler : register(s12); // Specular F0 texture +#endif + +#define ENVMAPLOD (g_EyePos.a) + +struct PS_INPUT +{ + float2 baseTexCoord : TEXCOORD0; + float4 lightAtten : TEXCOORD1; + float3 worldNormal : TEXCOORD2; + float3 worldPos : TEXCOORD3; + float3 projPos : TEXCOORD4; + float4 lightmapTexCoord1And2 : TEXCOORD5; + float4 lightmapTexCoord3 : TEXCOORD6; +}; + +// Entry point +float4 main(PS_INPUT i) : COLOR +{ +#if USEENVAMBIENT + float3 EnvAmbientCube[6]; + setupEnvMapAmbientCube(EnvAmbientCube, EnvmapSampler); +#else + #define EnvAmbientCube cAmbientCube +#endif + + float3 surfNormal = normalize(i.worldNormal); + float3 surfTangent; + float3 surfBase; + float flipSign; + float3x3 normalBasis = compute_tangent_frame(surfNormal, i.worldPos, i.baseTexCoord , surfTangent, surfBase, flipSign); + +#if PARALLAXOCCLUSION + float3 outgoingLightRay = g_EyePos.xyz - i.worldPos; + float3 outgoingLightDirectionTS = worldToRelative( outgoingLightRay, surfTangent, surfBase, surfNormal); + float2 correctedTexCoord = parallaxCorrect(i.baseTexCoord, outgoingLightDirectionTS , NormalTextureSampler , PARALLAX_DEPTH , PARALLAX_CENTER); +#else + float2 correctedTexCoord = i.baseTexCoord; +#endif + + float3 textureNormal = normalize((tex2D( NormalTextureSampler, correctedTexCoord).xyz - float3(0.5, 0.5, 0.5)) * 2); + float3 normal = normalize(mul(textureNormal, normalBasis)); // World Normal + + float4 albedo = tex2D(BaseTextureSampler, correctedTexCoord); + albedo.xyz *= g_BaseColor; + + float3 mrao = tex2D(MRAOTextureSampler, correctedTexCoord).xyz; + float metalness = mrao.x, roughness = mrao.y, ambientOcclusion = mrao.z; +#if EMISSIVE + float3 emission = tex2D(EmissionTextureSampler, correctedTexCoord).xyz; +#endif +#if SPECULAR + float3 specular = tex2D(SpecularTextureSampler, correctedTexCoord).xyz; +#endif + + textureNormal.y *= flipSign; // Fixup textureNormal for ambient lighting + + float3 outgoingLightDirection = normalize(g_EyePos.xyz - i.worldPos); // Lo + float lightDirectionAngle = max(0, dot(normal, outgoingLightDirection)); // cosLo + + float3 specularReflectionVector = 2.0 * lightDirectionAngle * normal - outgoingLightDirection; // Lr + +#if SPECULAR + float3 fresnelReflectance = specular.rgb; // F0 +#else + float3 dielectricCoefficient = 0.04; //F0 dielectric + float3 fresnelReflectance = lerp(dielectricCoefficient, albedo.rgb, metalness); // F0 +#endif + + // Start ambient + float3 ambientLighting = 0.0; + if (!FLASHLIGHT) + { + float3 diffuseIrradiance = ambientLookup(normal, EnvAmbientCube, textureNormal, i.lightmapTexCoord1And2, i.lightmapTexCoord3, LightmapSampler, g_DiffuseModulation); + // return float4(diffuseIrradiance, 1); // testing diffuse irraciance + float3 ambientLightingFresnelTerm = fresnelSchlick(fresnelReflectance, lightDirectionAngle); // F +#if SPECULAR + float3 diffuseContributionFactor = 1 - ambientLightingFresnelTerm; // kd +#else + float3 diffuseContributionFactor = lerp(1 - ambientLightingFresnelTerm, 0, metalness); ; // kd +#endif + float3 diffuseIBL = diffuseContributionFactor * albedo.rgb * diffuseIrradiance; + + float4 specularUV = float4(specularReflectionVector, roughness * ENVMAPLOD); + float3 lookupHigh = ENV_MAP_SCALE * texCUBElod(EnvmapSampler, specularUV).xyz; + float3 lookupLow = PixelShaderAmbientLight(specularReflectionVector, EnvAmbientCube); + float3 specularIrradiance = lerp(lookupHigh, lookupLow, roughness * roughness); + float3 specularIBL = specularIrradiance * EnvBRDFApprox(fresnelReflectance, roughness, lightDirectionAngle); + + ambientLighting = (diffuseIBL + specularIBL) * ambientOcclusion; + } + // End ambient + + // Start direct + float3 directLighting = 0.0; + if (!FLASHLIGHT) { + for (uint n = 0; n < NUM_LIGHTS; ++n) + { + float3 LightIn = normalize(PixelShaderGetLightVector(i.worldPos, cLightInfo, n)); + float3 LightColor = PixelShaderGetLightColor(cLightInfo, n) * GetAttenForLight(i.lightAtten, n); // Li + + directLighting += calculateLight(LightIn, LightColor, outgoingLightDirection, + normal, fresnelReflectance, roughness, metalness, lightDirectionAngle, albedo.rgb); + } + } + // End direct + + // Start flashlight + if (FLASHLIGHT) + { + float4 flashlightSpacePosition = mul(float4(i.worldPos, 1.0), g_FlashlightWorldToTexture); + clip( flashlightSpacePosition.w ); // stop projected textures from projecting backwards (only really happens if they have a big FOV because they get frustum culled.) + float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w; + + float3 delta = g_FlashlightPos.xyz - i.worldPos; + float distSquared = dot(delta, delta); + float dist = sqrt(distSquared); + + float3 flashlightColor = tex2D(FlashlightSampler, vProjCoords.xy); + flashlightColor *= cFlashlightColor.xyz; + +#if FLASHLIGHTSHADOWS + float flashlightShadow = DoFlashlightShadow(ShadowDepthSampler, RandRotSampler, vProjCoords, i.projPos, FLASHLIGHTDEPTHFILTERMODE, g_ShadowTweaks, true); + float flashlightAttenuated = lerp(flashlightShadow, 1.0, g_ShadowTweaks.y); // Blend between fully attenuated and not attenuated + float fAtten = saturate(dot(g_FlashlightAttenuationFactors.xyz, float3(1.0, 1.0 / dist, 1.0 / distSquared))); + flashlightShadow = saturate(lerp(flashlightAttenuated, flashlightShadow, fAtten)); // Blend between shadow and above, according to light attenuation + + flashlightColor *= flashlightShadow; +#endif + float farZ = g_FlashlightAttenuationFactors.w; + float endFalloffFactor = RemapValClamped(dist, farZ, 0.6 * farZ, 0.0, 1.0); + + float3 flashLightIntensity = flashlightColor * endFalloffFactor; + + float3 flashLightIn = normalize(g_FlashlightPos.xyz - i.worldPos); + + directLighting += max(0, calculateLight(flashLightIn, flashLightIntensity, outgoingLightDirection, + normal, fresnelReflectance, roughness, metalness, lightDirectionAngle, albedo.rgb)); + } + // End flashlight + +float fogFactor = 0.0f; +#if !FLASHLIGHT +fogFactor = CalcPixelFogFactor(PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos.z, i.projPos.z); +#endif + +float alpha = 0.0f; +#if !FLASHLIGHT +#if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT) + alpha = fogFactor; +#else + alpha = albedo.a; +#endif +#endif + + bool bWriteDepthToAlpha = (WRITE_DEPTH_TO_DESTALPHA != 0) && (WRITEWATERFOGTODESTALPHA == 0); + + float3 combinedLighting = directLighting + ambientLighting; +#if EMISSIVE && !FLASHLIGHT + combinedLighting += emission; +#endif + + return FinalOutput(float4(combinedLighting, alpha), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.projPos.z); +} diff --git a/materialsystem/stdshaders/pbr_vs20b.fxc b/materialsystem/stdshaders/pbr_vs20b.fxc new file mode 100644 index 00000000..03a61eb8 --- /dev/null +++ b/materialsystem/stdshaders/pbr_vs20b.fxc @@ -0,0 +1,116 @@ +//================================================================================================== +// +// Physically Based Rendering vertex shader for brushes and models +// +//================================================================================================== + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; +const float4 cBaseTexCoordTransform[2] : register(SHADER_SPECIFIC_CONST_0); + +//----------------------------------------------------------------------------- +// Input vertex format +//----------------------------------------------------------------------------- +struct VS_INPUT +{ + // This is all of the stuff that we ever use + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float4 vTangent : TANGENT; + float2 vTexCoord0 : TEXCOORD0; + float4 vLightmapTexCoord : TEXCOORD1; + float4 vLightmapTexCoordOffset : TEXCOORD2; +}; + +struct VS_OUTPUT +{ + // Stuff that isn't seen by the pixel shader + float4 projPosSetup : POSITION; + float fog : FOG; + // Stuff that is seen by the pixel shader + float2 baseTexCoord : TEXCOORD0; + float4 lightAtten : TEXCOORD1; + float3 worldNormal : TEXCOORD2; + float3 worldTangent : TEXCOORD3; + float3 worldPos : TEXCOORD4; + float3 projPos : TEXCOORD5; + float4 lightmapTexCoord1And2 : TEXCOORD6; + float4 lightmapTexCoord3 : TEXCOORD7; +}; + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.lightmapTexCoord3.z = dot(v.vTexCoord0, cBaseTexCoordTransform[0].xy) + cBaseTexCoordTransform[0].w; + o.lightmapTexCoord3.w = dot(v.vTexCoord0, cBaseTexCoordTransform[1].xy) + cBaseTexCoordTransform[1].w; + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord + v.vLightmapTexCoordOffset; + + float2 lightmapTexCoord2 = o.lightmapTexCoord1And2.xy + v.vLightmapTexCoordOffset.xy; + float2 lightmapTexCoord3 = lightmapTexCoord2 + v.vLightmapTexCoordOffset.xy; + + // Reversed component order + o.lightmapTexCoord1And2.w = lightmapTexCoord2.x; + o.lightmapTexCoord1And2.z = lightmapTexCoord2.y; + + o.lightmapTexCoord3.xy = lightmapTexCoord3; + + // Get normal and tangent and stuff + float3 vNormal; float4 vTangent; + DecompressVertex_NormalTangent(v.vNormal, v.vTangent, vNormal, vTangent); + float3 worldNormal, worldPos, worldTangentS, worldTangentT; + SkinPositionNormalAndTangentSpace(g_bSkinning, v.vPos, vNormal, vTangent, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal, worldTangentS, worldTangentT); + + // Transform into projection space + float4 vProjPos = mul(float4(worldPos, 1), cViewProj); + o.projPosSetup = vProjPos; + vProjPos.z = dot(float4(worldPos, 1), cViewProjZ); + + o.projPos = vProjPos.xyz; + o.fog = CalcFog(worldPos, vProjPos.xyz, g_FogType); + + // Needed for water fog alpha and diffuse lighting + o.worldPos = worldPos; + o.worldNormal = normalize(worldNormal); + //o.worldTangent = float4(worldTangentS.xyz, vTangent.w); + o.worldTangent = normalize(worldTangentS); + + // Scalar attenuations for four lights + + o.lightAtten = float4(0, 0, 0, 0); + + #if (NUM_LIGHTS > 0) + o.lightAtten.x = GetVertexAttenForLight(worldPos, 0, false); + #endif + + #if (NUM_LIGHTS > 1) + o.lightAtten.y = GetVertexAttenForLight(worldPos, 1, false); + #endif + + #if (NUM_LIGHTS > 2) + o.lightAtten.z = GetVertexAttenForLight(worldPos, 2, false); + #endif + + #if (NUM_LIGHTS > 3) + o.lightAtten.w = GetVertexAttenForLight(worldPos, 3, false); + #endif + + // Base texture coordinate transform + o.baseTexCoord.x = dot(v.vTexCoord0, cBaseTexCoordTransform[0].xy); + o.baseTexCoord.y = dot(v.vTexCoord0, cBaseTexCoordTransform[1].xy); + + return o; +} diff --git a/materialsystem/stdshaders/pbr_vs30.fxc b/materialsystem/stdshaders/pbr_vs30.fxc new file mode 100644 index 00000000..9b8857b7 --- /dev/null +++ b/materialsystem/stdshaders/pbr_vs30.fxc @@ -0,0 +1,111 @@ +//================================================================================================== +// +// Physically Based Rendering vertex shader for brushes and models +// +//================================================================================================== + +// DYNAMIC: "COMPRESSED_VERTS" "0..1" +// DYNAMIC: "DOWATERFOG" "0..1" +// DYNAMIC: "SKINNING" "0..1" +// DYNAMIC: "LIGHTING_PREVIEW" "0..1" +// DYNAMIC: "NUM_LIGHTS" "0..4" + +#include "common_vs_fxc.h" + +static const bool g_bSkinning = SKINNING ? true : false; +static const int g_FogType = DOWATERFOG; +const float4 cBaseTexCoordTransform[2] : register(SHADER_SPECIFIC_CONST_0); + +//----------------------------------------------------------------------------- +// Input vertex format +//----------------------------------------------------------------------------- +struct VS_INPUT +{ + // This is all of the stuff that we ever use + float4 vPos : POSITION; + float4 vBoneWeights : BLENDWEIGHT; + float4 vBoneIndices : BLENDINDICES; + float4 vNormal : NORMAL; + float2 vTexCoord0 : TEXCOORD0; + float4 vLightmapTexCoord : TEXCOORD1; + float4 vLightmapTexCoordOffset : TEXCOORD2; +}; + +struct VS_OUTPUT +{ + // Stuff that isn't seen by the pixel shader + float4 projPosSetup : POSITION; + float fog : FOG; + // Stuff that is seen by the pixel shader + float2 baseTexCoord : TEXCOORD0; + float4 lightAtten : TEXCOORD1; + float3 worldNormal : TEXCOORD2; + float3 worldPos : TEXCOORD3; + float3 projPos : TEXCOORD4; + float4 lightmapTexCoord1And2 : TEXCOORD5; + float4 lightmapTexCoord3 : TEXCOORD6; +}; + +//----------------------------------------------------------------------------- +// Main shader entry point +//----------------------------------------------------------------------------- +VS_OUTPUT main( const VS_INPUT v ) +{ + VS_OUTPUT o = ( VS_OUTPUT )0; + + o.lightmapTexCoord3.z = dot(v.vTexCoord0, cBaseTexCoordTransform[0]) + cBaseTexCoordTransform[0].w; + o.lightmapTexCoord3.w = dot(v.vTexCoord0, cBaseTexCoordTransform[1]) + cBaseTexCoordTransform[1].w; + o.lightmapTexCoord1And2.xy = v.vLightmapTexCoord + v.vLightmapTexCoordOffset; + + float2 lightmapTexCoord2 = o.lightmapTexCoord1And2.xy + v.vLightmapTexCoordOffset; + float2 lightmapTexCoord3 = lightmapTexCoord2 + v.vLightmapTexCoordOffset; + + // Reversed component order + o.lightmapTexCoord1And2.w = lightmapTexCoord2.x; + o.lightmapTexCoord1And2.z = lightmapTexCoord2.y; + + o.lightmapTexCoord3.xy = lightmapTexCoord3; + + float3 vNormal; + DecompressVertex_Normal(v.vNormal, vNormal); + + float3 worldNormal, worldPos; + SkinPositionAndNormal(g_bSkinning, v.vPos, vNormal, v.vBoneWeights, v.vBoneIndices, worldPos, worldNormal); + + // Transform into projection space + float4 vProjPos = mul(float4(worldPos, 1), cViewProj); + o.projPosSetup = vProjPos; + vProjPos.z = dot(float4(worldPos, 1), cViewProjZ); + + o.projPos = vProjPos.xyz; + o.fog = CalcFog(worldPos, vProjPos.xyz, g_FogType); + + // Needed for water fog alpha and diffuse lighting + o.worldPos = worldPos; + o.worldNormal = normalize(worldNormal); + + // Scalar attenuations for four lights + o.lightAtten = float4(0, 0, 0, 0); + + #if (NUM_LIGHTS > 0) + o.lightAtten.x = GetVertexAttenForLight(worldPos, 0, false); + #endif + + #if (NUM_LIGHTS > 1) + o.lightAtten.y = GetVertexAttenForLight(worldPos, 1, false); + #endif + + #if (NUM_LIGHTS > 2) + o.lightAtten.z = GetVertexAttenForLight(worldPos, 2, false); + #endif + + #if (NUM_LIGHTS > 3) + o.lightAtten.w = GetVertexAttenForLight(worldPos, 3, false); + #endif + + // Base texture coordinate transform + o.baseTexCoord.x = dot(v.vTexCoord0, cBaseTexCoordTransform[0]); + o.baseTexCoord.y = dot(v.vTexCoord0, cBaseTexCoordTransform[1]); + + return o; +} diff --git a/materialsystem/stdshaders/stdshader_dx9.vpc b/materialsystem/stdshaders/stdshader_dx9.vpc index 46428bde..c36aa2b2 100644 --- a/materialsystem/stdshaders/stdshader_dx9.vpc +++ b/materialsystem/stdshaders/stdshader_dx9.vpc @@ -120,6 +120,7 @@ $Project "stdshader_dx9" $File "particlelitgeneric_dx9.cpp" $File "particlelitgeneric_dx9_helper.cpp" $File "particlesphere_dx9.cpp" + $File "pbr_dx9.cpp" $File "portal.cpp" $File "portalstaticoverlay.cpp" $File "portal_refract.cpp" @@ -212,6 +213,7 @@ $Project "stdshader_dx9" $File "shader_constant_register_map.h" $File "skin_dx9_helper.h" $File "particlelitgeneric_dx9_helper.h" + $File "pbr_common_ps2_3_x.h" $File "vertexlitgeneric_dx95_helper.h" $File "vortwarp_vs20_helper.h" $File "worldvertextransition_dx8_helper.h" @@ -244,4 +246,4 @@ $Project "stdshader_dx9" $Shaders "stdshader_dx9_20b.txt" $Shaders "stdshader_dx9_30.txt" //$Shaders "stdshader_dx10.txt" -} +} \ No newline at end of file diff --git a/materialsystem/stdshaders/stdshader_dx9_20b.txt b/materialsystem/stdshaders/stdshader_dx9_20b.txt index 647a3936..7f3e1fd5 100644 --- a/materialsystem/stdshaders/stdshader_dx9_20b.txt +++ b/materialsystem/stdshaders/stdshader_dx9_20b.txt @@ -272,6 +272,9 @@ particlesphere_vs11.fxc particlesphere_ps2x.fxc particlesphere_vs20.fxc +pbr_ps20b.fxc +pbr_vs20b.fxc + portal_ps11.fxc portal_vs11.fxc portal_ps2x.fxc diff --git a/materialsystem/stdshaders/stdshader_dx9_30.txt b/materialsystem/stdshaders/stdshader_dx9_30.txt index b23b9fc8..dccaafbd 100644 --- a/materialsystem/stdshaders/stdshader_dx9_30.txt +++ b/materialsystem/stdshaders/stdshader_dx9_30.txt @@ -26,6 +26,8 @@ morphaccumulate_vs30.fxc morphaccumulate_ps30.fxc morphweight_vs30.fxc morphweight_ps30.fxc +pbr_ps30.fxc +pbr_vs30.fxc pyro_vision_ps2x.fxc pyro_vision_vs20.fxc skin_vs20.fxc diff --git a/materialsystem/stdshaders/wscript b/materialsystem/stdshaders/wscript index c9bc98c4..4d82e515 100644 --- a/materialsystem/stdshaders/wscript +++ b/materialsystem/stdshaders/wscript @@ -78,6 +78,7 @@ def build(bld): 'particlelitgeneric_dx9.cpp', 'particlelitgeneric_dx9_helper.cpp', 'particlesphere_dx9.cpp', + 'pbr_dx9.cpp', 'portal.cpp', 'portalstaticoverlay.cpp', 'portal_refract.cpp',