1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-09-19 03:56:10 +08:00

* Added support for building shaders in your mod

* Added nav mesh support
* fixed many warnings and misc bugs
* Fixed the create*projects scripts in mp
* Added a bunch of stuff to .gitignore
This commit is contained in:
Joe Ludwig
2013-07-17 18:26:59 -07:00
parent 64f3b0abed
commit 0e42951d44
210 changed files with 27490 additions and 1351 deletions

View File

@ -0,0 +1,191 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef LOCALD3DTYPES_H
#define LOCALD3DTYPES_H
#ifdef _WIN32
#pragma once
#endif
#if defined( DX10 ) && !defined( DX_TO_GL_ABSTRACTION )
#include <d3d10.h>
#include <d3dx10.h>
struct IDirect3D10BaseTexture
{
ID3D10Resource *m_pBaseTexture;
ID3D10ShaderResourceView *m_pSRView;
ID3D10RenderTargetView *m_pRTView;
};
class CDx10Types
{
public:
typedef struct IDirect3D10BaseTexture IDirect3DTexture;
// FIXME: What is this called now ?
// typedef ID3D10TextureCube IDirect3DCubeTexture;
typedef ID3D10Texture3D IDirect3DVolumeTexture;
typedef ID3D10Device IDirect3DDevice;
typedef D3D10_VIEWPORT D3DVIEWPORT;
typedef ID3D10Buffer IDirect3DIndexBuffer;
typedef ID3D10Buffer IDirect3DVertexBuffer;
typedef ID3D10VertexShader IDirect3DVertexShader;
typedef ID3D10PixelShader IDirect3DPixelShader;
typedef ID3D10ShaderResourceView IDirect3DSurface;
typedef ID3DX10Font ID3DXFont;
typedef ID3D10Query ID3DQuery;
typedef ID3D10Device *LPDIRECT3DDEVICE;
typedef ID3D10Buffer *LPDIRECT3DINDEXBUFFER;
typedef ID3D10Buffer *LPDIRECT3DVERTEXBUFFER;
};
#endif // defined( DX10 ) && !defined( DX_TO_GL_ABSTRACTION )
#if !defined( _X360 ) && !defined( DX_TO_GL_ABSTRACTION )
#ifdef _DEBUG
#define D3D_DEBUG_INFO 1
#endif
#endif
struct IDirect3DTexture9;
struct IDirect3DBaseTexture9;
struct IDirect3DCubeTexture9;
struct IDirect3D9;
struct IDirect3DDevice9;
struct IDirect3DSurface9;
struct IDirect3DIndexBuffer9;
struct IDirect3DVertexBuffer9;
struct IDirect3DVertexShader9;
struct IDirect3DPixelShader9;
struct IDirect3DVolumeTexture9;
typedef struct _D3DLIGHT9 D3DLIGHT9;
typedef struct _D3DADAPTER_IDENTIFIER9 D3DADAPTER_IDENTIFIER9;
typedef struct _D3DCAPS9 D3DCAPS9;
typedef struct _D3DVIEWPORT9 D3DVIEWPORT9;
typedef struct _D3DMATERIAL9 D3DMATERIAL9;
typedef IDirect3DTexture9 IDirect3DTexture;
typedef IDirect3DBaseTexture9 IDirect3DBaseTexture;
typedef IDirect3DCubeTexture9 IDirect3DCubeTexture;
typedef IDirect3DVolumeTexture9 IDirect3DVolumeTexture;
typedef IDirect3DDevice9 IDirect3DDevice;
typedef D3DMATERIAL9 D3DMATERIAL;
typedef D3DLIGHT9 D3DLIGHT;
typedef IDirect3DSurface9 IDirect3DSurface;
typedef D3DCAPS9 D3DCAPS;
typedef IDirect3DIndexBuffer9 IDirect3DIndexBuffer;
typedef IDirect3DVertexBuffer9 IDirect3DVertexBuffer;
typedef IDirect3DPixelShader9 IDirect3DPixelShader;
typedef IDirect3DDevice *LPDIRECT3DDEVICE;
typedef IDirect3DIndexBuffer *LPDIRECT3DINDEXBUFFER;
typedef IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER;
class CDx9Types
{
public:
typedef IDirect3DTexture9 IDirect3DTexture;
typedef IDirect3DBaseTexture9 IDirect3DBaseTexture;
typedef IDirect3DCubeTexture9 IDirect3DCubeTexture;
typedef IDirect3DVolumeTexture9 IDirect3DVolumeTexture;
typedef IDirect3DDevice9 IDirect3DDevice;
typedef D3DMATERIAL9 D3DMATERIAL;
typedef D3DLIGHT9 D3DLIGHT;
typedef IDirect3DSurface9 IDirect3DSurface;
typedef D3DCAPS9 D3DCAPS;
typedef IDirect3DIndexBuffer9 IDirect3DIndexBuffer;
typedef IDirect3DVertexBuffer9 IDirect3DVertexBuffer;
typedef IDirect3DPixelShader9 IDirect3DPixelShader;
typedef IDirect3DDevice *LPDIRECT3DDEVICE;
typedef IDirect3DIndexBuffer *LPDIRECT3DINDEXBUFFER;
typedef IDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFER;
};
typedef void *HardwareShader_t;
//-----------------------------------------------------------------------------
// The vertex and pixel shader type
//-----------------------------------------------------------------------------
typedef int VertexShader_t;
typedef int PixelShader_t;
//-----------------------------------------------------------------------------
// Bitpattern for an invalid shader
//-----------------------------------------------------------------------------
#define INVALID_SHADER ( 0xFFFFFFFF )
#define INVALID_HARDWARE_SHADER ( NULL )
#define D3DSAMP_NOTSUPPORTED D3DSAMP_FORCE_DWORD
#define D3DRS_NOTSUPPORTED D3DRS_FORCE_DWORD
#include "togl/rendermechanism.h"
#if defined( _X360 )
// not supported, keeping for port ease
#define D3DSAMP_SRGBTEXTURE D3DSAMP_NOTSUPPORTED
#define D3DRS_LIGHTING D3DRS_NOTSUPPORTED
#define D3DRS_DIFFUSEMATERIALSOURCE D3DRS_NOTSUPPORTED
#define D3DRS_SPECULARENABLE D3DRS_NOTSUPPORTED
#define D3DRS_SHADEMODE D3DRS_NOTSUPPORTED
#define D3DRS_LASTPIXEL D3DRS_NOTSUPPORTED
#define D3DRS_DITHERENABLE D3DRS_NOTSUPPORTED
#define D3DRS_FOGENABLE D3DRS_NOTSUPPORTED
#define D3DRS_FOGCOLOR D3DRS_NOTSUPPORTED
#define D3DRS_FOGTABLEMODE D3DRS_NOTSUPPORTED
#define D3DRS_FOGSTART D3DRS_NOTSUPPORTED
#define D3DRS_FOGEND D3DRS_NOTSUPPORTED
#define D3DRS_FOGDENSITY D3DRS_NOTSUPPORTED
#define D3DRS_RANGEFOGENABLE D3DRS_NOTSUPPORTED
#define D3DRS_TEXTUREFACTOR D3DRS_NOTSUPPORTED
#define D3DRS_CLIPPING D3DRS_NOTSUPPORTED
#define D3DRS_AMBIENT D3DRS_NOTSUPPORTED
#define D3DRS_FOGVERTEXMODE D3DRS_NOTSUPPORTED
#define D3DRS_COLORVERTEX D3DRS_NOTSUPPORTED
#define D3DRS_LOCALVIEWER D3DRS_NOTSUPPORTED
#define D3DRS_NORMALIZENORMALS D3DRS_NOTSUPPORTED
#define D3DRS_SPECULARMATERIALSOURCE D3DRS_NOTSUPPORTED
#define D3DRS_AMBIENTMATERIALSOURCE D3DRS_NOTSUPPORTED
#define D3DRS_EMISSIVEMATERIALSOURCE D3DRS_NOTSUPPORTED
#define D3DRS_VERTEXBLEND D3DRS_NOTSUPPORTED
#define D3DRS_POINTSCALEENABLE D3DRS_NOTSUPPORTED
#define D3DRS_POINTSCALE_A D3DRS_NOTSUPPORTED
#define D3DRS_POINTSCALE_B D3DRS_NOTSUPPORTED
#define D3DRS_POINTSCALE_C D3DRS_NOTSUPPORTED
#define D3DRS_PATCHEDGESTYLE D3DRS_NOTSUPPORTED
#define D3DRS_DEBUGMONITORTOKEN D3DRS_NOTSUPPORTED
#define D3DRS_INDEXEDVERTEXBLENDENABLE D3DRS_NOTSUPPORTED
#define D3DRS_TWEENFACTOR D3DRS_NOTSUPPORTED
#define D3DRS_POSITIONDEGREE D3DRS_NOTSUPPORTED
#define D3DRS_NORMALDEGREE D3DRS_NOTSUPPORTED
#define D3DRS_ANTIALIASEDLINEENABLE D3DRS_NOTSUPPORTED
#define D3DRS_ADAPTIVETESS_X D3DRS_NOTSUPPORTED
#define D3DRS_ADAPTIVETESS_Y D3DRS_NOTSUPPORTED
#define D3DRS_ADAPTIVETESS_Z D3DRS_NOTSUPPORTED
#define D3DRS_ADAPTIVETESS_W D3DRS_NOTSUPPORTED
#define D3DRS_ENABLEADAPTIVETESSELLATION D3DRS_NOTSUPPORTED
#define D3DRS_SRGBWRITEENABLE D3DRS_NOTSUPPORTED
#define D3DLOCK_DISCARD 0
#define D3DUSAGE_DYNAMIC 0
#define D3DUSAGE_AUTOGENMIPMAP 0
#define D3DDEVTYPE_REF D3DDEVTYPE_HAL
#define D3DENUM_WHQL_LEVEL 0
#define D3DCREATE_SOFTWARE_VERTEXPROCESSING D3DCREATE_HARDWARE_VERTEXPROCESSING
#define D3DDMT_ENABLE 0
typedef enum D3DSHADEMODE
{
D3DSHADE_FLAT = 0,
D3DSHADE_GOURAUD = 0,
};
#endif // _X360
#endif // LOCALD3DTYPES_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,439 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
// This is what all vs/ps (dx8+) shaders inherit from.
//===========================================================================//
#ifndef BASEVSSHADER_H
#define BASEVSSHADER_H
#ifdef _WIN32
#pragma once
#endif
#include "shaderlib/cshader.h"
#include "shaderlib/BaseShader.h"
#include "convar.h"
#include <renderparm.h>
#ifdef _X360
#define SUPPORT_DX8 0
#define SUPPORT_DX7 0
#else
#define SUPPORT_DX8 1
#define SUPPORT_DX7 1
#endif
//-----------------------------------------------------------------------------
// Helper macro for vertex shaders
//-----------------------------------------------------------------------------
#define BEGIN_VS_SHADER_FLAGS(_name, _help, _flags) __BEGIN_SHADER_INTERNAL( CBaseVSShader, _name, _help, _flags )
#define BEGIN_VS_SHADER(_name,_help) __BEGIN_SHADER_INTERNAL( CBaseVSShader, _name, _help, 0 )
// useful parameter initialization macro
#define INIT_FLOAT_PARM( parm, value ) \
if ( !params[(parm)]->IsDefined() ) \
{ \
params[(parm)]->SetFloatValue( (value) ); \
}
// useful pixel shader declaration macro for ps20/20b c++ code
#define SET_STATIC_PS2X_PIXEL_SHADER_NO_COMBOS( basename ) \
if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) \
{ \
DECLARE_STATIC_PIXEL_SHADER( basename##_ps20b ); \
SET_STATIC_PIXEL_SHADER( basename##_ps20b ); \
} \
else \
{ \
DECLARE_STATIC_PIXEL_SHADER( basename##_ps20 ); \
SET_STATIC_PIXEL_SHADER( basename##_ps20 ); \
}
#define SET_DYNAMIC_PS2X_PIXEL_SHADER_NO_COMBOS( basename ) \
if( g_pHardwareConfig->SupportsPixelShaders_2_b() ) \
{ \
DECLARE_DYNAMIC_PIXEL_SHADER( basename##_ps20b ); \
SET_DYNAMIC_PIXEL_SHADER( basename##_ps20b ); \
} \
else \
{ \
DECLARE_DYNAMIC_PIXEL_SHADER( basename##_ps20 ); \
SET_DYNAMIC_PIXEL_SHADER( basename##_ps20 ); \
}
//-----------------------------------------------------------------------------
// Base class for shaders, contains helper methods.
//-----------------------------------------------------------------------------
class CBaseVSShader : public CBaseShader
{
public:
// Loads bump lightmap coordinates into the pixel shader
void LoadBumpLightmapCoordinateAxes_PixelShader( int pixelReg );
// Loads bump lightmap coordinates into the vertex shader
void LoadBumpLightmapCoordinateAxes_VertexShader( int vertexReg );
// Pixel and vertex shader constants....
void SetPixelShaderConstant( int pixelReg, int constantVar );
// Pixel and vertex shader constants....
void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar );
// This version will put constantVar into x,y,z, and constantVar2 into the w
void SetPixelShaderConstant( int pixelReg, int constantVar, int constantVar2 );
void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar, int constantVar2 );
// Helpers for setting constants that need to be converted to linear space (from gamma space).
void SetVertexShaderConstantGammaToLinear( int var, float const* pVec, int numConst = 1, bool bForce = false );
void SetPixelShaderConstantGammaToLinear( int var, float const* pVec, int numConst = 1, bool bForce = false );
void SetVertexShaderConstant( int vertexReg, int constantVar );
// set rgb components of constant from a color parm and give an explicit w value
void SetPixelShaderConstant_W( int pixelReg, int constantVar, float fWValue );
// GR - fix for const/lerp issues
void SetPixelShaderConstantFudge( int pixelReg, int constantVar );
// Sets light direction for pixel shaders.
void SetPixelShaderLightColors( int pixelReg );
// Sets vertex shader texture transforms
void SetVertexShaderTextureTranslation( int vertexReg, int translationVar );
void SetVertexShaderTextureScale( int vertexReg, int scaleVar );
void SetVertexShaderTextureTransform( int vertexReg, int transformVar );
void SetVertexShaderTextureScaledTransform( int vertexReg,
int transformVar, int scaleVar );
// Set pixel shader texture transforms
void SetPixelShaderTextureTranslation( int pixelReg, int translationVar );
void SetPixelShaderTextureScale( int pixelReg, int scaleVar );
void SetPixelShaderTextureTransform( int pixelReg, int transformVar );
void SetPixelShaderTextureScaledTransform( int pixelReg,
int transformVar, int scaleVar );
// Moves a matrix into vertex shader constants
void SetVertexShaderMatrix3x4( int vertexReg, int matrixVar );
void SetVertexShaderMatrix4x4( int vertexReg, int matrixVar );
// Loads the view matrix into vertex shader constants
void LoadViewMatrixIntoVertexShaderConstant( int vertexReg );
// Loads the projection matrix into vertex shader constants
void LoadProjectionMatrixIntoVertexShaderConstant( int vertexReg );
// Loads the model->view matrix into vertex shader constants
void LoadModelViewMatrixIntoVertexShaderConstant( int vertexReg );
// Loads a scale/offset version of the viewport transform into the specified constant.
void LoadViewportTransformScaledIntoVertexShaderConstant( int vertexReg );
// Sets up ambient light cube...
void SetAmbientCubeDynamicStateVertexShader( );
float GetAmbientLightCubeLuminance( );
// Helpers for dealing with envmaptint
void SetEnvMapTintPixelShaderDynamicState( int pixelReg, int tintVar, int alphaVar, bool bConvertFromGammaToLinear = false );
// Helper methods for pixel shader overbrighting
void EnablePixelShaderOverbright( int reg, bool bEnable, bool bDivideByTwo );
// Helper for dealing with modulation
void SetModulationVertexShaderDynamicState();
void SetModulationPixelShaderDynamicState( int modulationVar );
void SetModulationPixelShaderDynamicState_LinearColorSpace( int modulationVar );
void SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( int modulationVar, float flScale );
// Sets a color + alpha into shader constants
void SetColorVertexShaderConstant( int nVertexReg, int colorVar, int alphaVar );
void SetColorPixelShaderConstant( int nPixelReg, int colorVar, int alphaVar );
#ifndef GAME_SHADER_DLL
//
// Standard shader passes!
//
void InitParamsUnlitGeneric_DX8(
int baseTextureVar,
int detailScaleVar,
int envmapOptionalVar,
int envmapVar,
int envmapTintVar,
int envmapMaskScaleVar,
int nDetailBlendMode );
void InitUnlitGeneric_DX8(
int baseTextureVar,
int detailVar,
int envmapVar,
int envmapMaskVar );
// Dx8 Unlit Generic pass
void VertexShaderUnlitGenericPass( int baseTextureVar, int frameVar,
int baseTextureTransformVar,
int detailVar, int detailTransform, bool bDetailTransformIsScale,
int envmapVar, int envMapFrameVar, int envmapMaskVar,
int envmapMaskFrameVar, int envmapMaskScaleVar, int envmapTintVar,
int alphaTestReferenceVar,
int nDetailBlendModeVar,
int nOutlineVar,
int nOutlineColorVar,
int nOutlineStartVar,
int nOutlineEndVar,
int nSeparateDetailUVsVar
);
// Helpers for drawing world bump mapped stuff.
void DrawModelBumpedSpecularLighting( int bumpMapVar, int bumpMapFrameVar,
int envMapVar, int envMapVarFrame,
int envMapTintVar, int alphaVar,
int envMapContrastVar, int envMapSaturationVar,
int bumpTransformVar,
bool bBlendSpecular, bool bNoWriteZ = false );
void DrawWorldBumpedSpecularLighting( int bumpmapVar, int envmapVar,
int bumpFrameVar, int envmapFrameVar,
int envmapTintVar, int alphaVar,
int envmapContrastVar, int envmapSaturationVar,
int bumpTransformVar, int fresnelReflectionVar,
bool bBlend, bool bNoWriteZ = false );
const char *UnlitGeneric_ComputeVertexShaderName( bool bMask,
bool bEnvmap,
bool bBaseTexture,
bool bBaseAlphaEnvmapMask,
bool bDetail,
bool bVertexColor,
bool bEnvmapCameraSpace,
bool bEnvmapSphere );
const char *UnlitGeneric_ComputePixelShaderName( bool bMask,
bool bEnvmap,
bool bBaseTexture,
bool bBaseAlphaEnvmapMask,
bool bDetail,
bool bMultiplyDetail,
bool bMaskBaseByDetailAlpha );
void DrawWorldBaseTexture( int baseTextureVar, int baseTextureTransformVar, int frameVar, int colorVar, int alphaVar );
void DrawWorldBumpedDiffuseLighting( int bumpmapVar, int bumpFrameVar,
int bumpTransformVar, bool bMultiply, bool bSSBump );
void DrawWorldBumpedSpecularLighting( int envmapMaskVar, int envmapMaskFrame,
int bumpmapVar, int envmapVar,
int bumpFrameVar, int envmapFrameVar,
int envmapTintVar, int alphaVar,
int envmapContrastVar, int envmapSaturationVar,
int bumpTransformVar, int fresnelReflectionVar,
bool bBlend );
void DrawBaseTextureBlend( int baseTextureVar, int baseTextureTransformVar,
int baseTextureFrameVar,
int baseTexture2Var, int baseTextureTransform2Var,
int baseTextureFrame2Var, int colorVar, int alphaVar );
void DrawWorldBumpedDiffuseLighting_Base_ps14( int bumpmapVar, int bumpFrameVar,
int bumpTransformVar, int baseTextureVar, int baseTextureTransformVar, int frameVar );
void DrawWorldBumpedDiffuseLighting_Blend_ps14( int bumpmapVar, int bumpFrameVar, int bumpTransformVar,
int baseTextureVar, int baseTextureTransformVar, int baseTextureFrameVar,
int baseTexture2Var, int baseTextureTransform2Var, int baseTextureFrame2Var);
void DrawWorldBumpedUsingVertexShader( int baseTextureVar, int baseTextureTransformVar,
int bumpmapVar, int bumpFrameVar,
int bumpTransformVar,
int envmapMaskVar, int envmapMaskFrame,
int envmapVar,
int envmapFrameVar,
int envmapTintVar, int colorVar, int alphaVar,
int envmapContrastVar, int envmapSaturationVar, int frameVar, int fresnelReflectionVar,
bool doBaseTexture2,
int baseTexture2Var,
int baseTextureTransform2Var,
int baseTextureFrame2Var,
bool bSSBump
);
// Sets up hw morphing state for the vertex shader
void SetHWMorphVertexShaderState( int nDimConst, int nSubrectConst, VertexTextureSampler_t morphSampler );
// Computes the shader index for vertex lit materials
int ComputeVertexLitShaderIndex( bool bVertexLitGeneric, bool hasBump, bool hasEnvmap, bool hasVertexColor, bool bHasNormal ) const;
// Helper for setting up flashlight constants
void SetFlashlightVertexShaderConstants( bool bBump, int bumpTransformVar, bool bDetail, int detailScaleVar, bool bSetTextureTransforms );
#if SUPPORT_DX8
void DrawFlashlight_dx80( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow,
bool bBump, int bumpmapVar, int bumpmapFrame, int bumpTransform, int flashlightTextureVar,
int flashlightTextureFrameVar, bool bLightmappedGeneric, bool bWorldVertexTransition,
int nWorldVertexTransitionPassID, int baseTexture2Var, int baseTexture2FrameVar,
bool bTeeth=false, int nTeethForwardVar=0, int nTeethIllumFactorVar=0 );
#endif
struct DrawFlashlight_dx90_Vars_t
{
DrawFlashlight_dx90_Vars_t()
{
// set all ints to -1
memset( this, 0xFF, sizeof(DrawFlashlight_dx90_Vars_t) );
// set all bools to a default value.
m_bBump = false;
m_bLightmappedGeneric = false;
m_bWorldVertexTransition = false;
m_bTeeth = false;
m_bSSBump = false;
m_fSeamlessScale = 0.0;
}
bool m_bBump;
bool m_bLightmappedGeneric;
bool m_bWorldVertexTransition;
bool m_bTeeth;
int m_nBumpmapVar;
int m_nBumpmapFrame;
int m_nBumpTransform;
int m_nFlashlightTextureVar;
int m_nFlashlightTextureFrameVar;
int m_nBaseTexture2Var;
int m_nBaseTexture2FrameVar;
int m_nBumpmap2Var;
int m_nBumpmap2Frame;
int m_nBump2Transform;
int m_nDetailVar;
int m_nDetailScale;
int m_nDetailTextureCombineMode;
int m_nDetailTextureBlendFactor;
int m_nDetailTint;
int m_nTeethForwardVar;
int m_nTeethIllumFactorVar;
int m_nAlphaTestReference;
bool m_bSSBump;
float m_fSeamlessScale; // 0.0 = not seamless
};
void DrawFlashlight_dx90( IMaterialVar** params,
IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow, DrawFlashlight_dx90_Vars_t &vars );
#endif // GAME_SHADER_DLL
BlendType_t EvaluateBlendRequirements( int textureVar, bool isBaseTexture, int detailTextureVar = -1 );
void HashShadow2DJitter( const float fJitterSeed, float *fU, float* fV );
//Alpha tested materials can end up leaving garbage in the dest alpha buffer if they write depth.
//This pass fills in the areas that passed the alpha test with depth in dest alpha
//by writing only equal depth pixels and only if we should be writing depth to dest alpha
void DrawEqualDepthToDestAlpha( void );
private:
// Helper methods for VertexLitGenericPass
// void UnlitGenericShadowState( int baseTextureVar, int detailVar, int envmapVar, int envmapMaskVar, bool doSkin );
void UnlitGenericDynamicState( int baseTextureVar, int frameVar, int baseTextureTransformVar,
int detailVar, int detailTransform, bool bDetailTransformIsScale, int envmapVar,
int envMapFrameVar, int envmapMaskVar, int envmapMaskFrameVar,
int envmapMaskScaleVar, int envmapTintVar );
// Converts a color + alpha into a vector4
void ColorVarsToVector( int colorVar, int alphaVar, Vector4D &color );
};
FORCEINLINE void SetFlashLightColorFromState( FlashlightState_t const &state, IShaderDynamicAPI *pShaderAPI, int nPSRegister=28, bool bFlashlightNoLambert=false )
{
// Old code
//float flToneMapScale = ( pShaderAPI->GetToneMappingScaleLinear() ).x;
//float flFlashlightScale = 1.0f / flToneMapScale;
// Fix to old code to keep flashlight from ever getting brighter than 1.0
//float flToneMapScale = ( pShaderAPI->GetToneMappingScaleLinear() ).x;
//if ( flToneMapScale < 1.0f )
// flToneMapScale = 1.0f;
//float flFlashlightScale = 1.0f / flToneMapScale;
// Force flashlight to 25% bright always
float flFlashlightScale = 0.25f;
if ( !g_pHardwareConfig->GetHDREnabled() )
{
// Non-HDR path requires 2.0 flashlight
flFlashlightScale = 2.0f;
}
// DX10 requires some hackery due to sRGB/blend ordering change from DX9
if ( g_pHardwareConfig->UsesSRGBCorrectBlending() )
{
flFlashlightScale *= 2.5f; // Magic number that works well on the NVIDIA 8800
}
// Generate pixel shader constant
float const *pFlashlightColor = state.m_Color;
float vPsConst[4] = { flFlashlightScale * pFlashlightColor[0], flFlashlightScale * pFlashlightColor[1], flFlashlightScale * pFlashlightColor[2], pFlashlightColor[3] };
vPsConst[3] = bFlashlightNoLambert ? 2.0f : 0.0f; // This will be added to N.L before saturate to force a 1.0 N.L term
// Red flashlight for testing
//vPsConst[0] = 0.5f; vPsConst[1] = 0.0f; vPsConst[2] = 0.0f;
pShaderAPI->SetPixelShaderConstant( nPSRegister, ( float * )vPsConst );
}
FORCEINLINE float ShadowAttenFromState( FlashlightState_t const &state )
{
// DX10 requires some hackery due to sRGB/blend ordering change from DX9, which makes the shadows too light
if ( g_pHardwareConfig->UsesSRGBCorrectBlending() )
return state.m_flShadowAtten * 0.1f; // magic number
return state.m_flShadowAtten;
}
FORCEINLINE float ShadowFilterFromState( FlashlightState_t const &state )
{
// We developed shadow maps at 1024, so we expect the penumbra size to have been tuned relative to that
return state.m_flShadowFilterSize / 1024.0f;
}
// convenient material variable access functions for helpers to use.
FORCEINLINE bool IsTextureSet( int nVar, IMaterialVar **params )
{
return ( nVar != -1 ) && ( params[nVar]->IsTexture() );
}
FORCEINLINE bool IsBoolSet( int nVar, IMaterialVar **params )
{
return ( nVar != -1 ) && ( params[nVar]->GetIntValue() );
}
FORCEINLINE int GetIntParam( int nVar, IMaterialVar **params, int nDefaultValue = 0 )
{
return ( nVar != -1 ) ? ( params[nVar]->GetIntValue() ) : nDefaultValue;
}
FORCEINLINE float GetFloatParam( int nVar, IMaterialVar **params, float flDefaultValue = 0.0 )
{
return ( nVar != -1 ) ? ( params[nVar]->GetFloatValue() ) : flDefaultValue;
}
FORCEINLINE void InitFloatParam( int nIndex, IMaterialVar **params, float flValue )
{
if ( (nIndex != -1) && !params[nIndex]->IsDefined() )
{
params[nIndex]->SetFloatValue( flValue );
}
}
FORCEINLINE void InitIntParam( int nIndex, IMaterialVar **params, int nValue )
{
if ( (nIndex != -1) && !params[nIndex]->IsDefined() )
{
params[nIndex]->SetIntValue( nValue );
}
}
class ConVar;
#ifdef _DEBUG
extern ConVar mat_envmaptintoverride;
extern ConVar mat_envmaptintscale;
#endif
#endif // BASEVSSHADER_H

View File

@ -0,0 +1,21 @@
@echo off
setlocal
rem ================================
rem ==== MOD PATH CONFIGURATIONS ===
rem == Set the absolute path to your mod's game directory here ==
set GAMEDIR=%cd%\..\..\..\game\mod_hl2mp
rem == Set the relative or absolute path to Source SDK Base 2013 Singleplayer\bin ==
set SDKBINDIR=C:\SteamBetaLibrary\SteamApps\common\Source SDK Base 2013 Singleplayer\bin
rem == Set the Path to your mod's root source code ==
rem This should already be correct, accepts relative paths only!
set SOURCEDIR=..\..
rem ==== MOD PATH CONFIGURATIONS END ===
rem ====================================
call buildsdkshaders.bat

View File

@ -0,0 +1,40 @@
@echo off
setlocal
rem Use dynamic shaders to build .inc files only
rem set dynamic_shaders=1
rem == Setup path to nmake.exe, from vc 2005 common tools directory ==
call "%VS100COMNTOOLS%vsvars32.bat"
set TTEXE=..\..\devtools\bin\timeprecise.exe
if not exist %TTEXE% goto no_ttexe
goto no_ttexe_end
:no_ttexe
set TTEXE=time /t
:no_ttexe_end
rem echo.
rem echo ~~~~~~ buildsdkshaders %* ~~~~~~
%TTEXE% -cur-Q
set tt_all_start=%ERRORLEVEL%
set tt_all_chkpt=%tt_start%
set BUILD_SHADER=call buildshaders.bat
set ARG_EXTRA=
%BUILD_SHADER% stdshader_dx9_20b -game %GAMEDIR% -source %SOURCEDIR%
%BUILD_SHADER% stdshader_dx9_30 -game %GAMEDIR% -source %SOURCEDIR% -dx9_30 -force30
rem echo.
if not "%dynamic_shaders%" == "1" (
rem echo Finished full buildallshaders %*
) else (
rem echo Finished dynamic buildallshaders %*
)
rem %TTEXE% -diff %tt_all_start% -cur
rem echo.

View File

@ -0,0 +1,209 @@
@echo off
set TTEXE=..\..\devtools\bin\timeprecise.exe
if not exist %TTEXE% goto no_ttexe
goto no_ttexe_end
:no_ttexe
set TTEXE=time /t
:no_ttexe_end
echo.
echo ==================== buildshaders %* ==================
%TTEXE% -cur-Q
set tt_start=%ERRORLEVEL%
set tt_chkpt=%tt_start%
REM ****************
REM usage: buildshaders <shaderProjectName>
REM ****************
setlocal
set arg_filename=%1
set shadercompilecommand=shadercompile.exe
set targetdir=shaders
set SrcDirBase=..\..
set shaderDir=shaders
set SDKArgs=
set SHADERINCPATH=vshtmp9/... fxctmp9/...
if "%1" == "" goto usage
set inputbase=%1
set DIRECTX_SDK_VER=pc09.00
set DIRECTX_SDK_BIN_DIR=dx9sdk\utilities
if /i "%6" == "-dx9_30" goto dx_sdk_dx9_30
goto dx_sdk_end
:dx_sdk_dx9_30
set DIRECTX_SDK_VER=pc09.30
set DIRECTX_SDK_BIN_DIR=dx10sdk\utilities\dx9_30
goto dx_sdk_end
:dx_sdk_end
if /i "%7" == "-force30" goto set_force30_arg
goto set_force_end
:set_force30_arg
set DIRECTX_FORCE_MODEL=30
goto set_force_end
:set_force_end
if /i "%2" == "-game" goto set_mod_args
goto build_shaders
REM ****************
REM USAGE
REM ****************
:usage
echo.
echo "usage: buildshaders <shaderProjectName> [-game] [gameDir if -game was specified] [-source sourceDir]"
echo " gameDir is where gameinfo.txt is (where it will store the compiled shaders)."
echo " sourceDir is where the source code is (where it will find scripts and compilers)."
echo "ex : buildshaders myshaders"
echo "ex : buildshaders myshaders -game c:\steam\steamapps\sourcemods\mymod -source c:\mymod\src"
goto :end
REM ****************
REM MOD ARGS - look for -game or the vproject environment variable
REM ****************
:set_mod_args
if not exist "%SDKBINDIR%\shadercompile.exe" goto NoShaderCompile
set ChangeToDir=%SDKBINDIR%
if /i "%4" NEQ "-source" goto NoSourceDirSpecified
set SrcDirBase=%~5
REM ** use the -game parameter to tell us where to put the files
set targetdir=%~3\shaders
set SDKArgs=-nompi -nop4 -game "%~3"
if not exist "%~3\gameinfo.txt" goto InvalidGameDirectory
goto build_shaders
REM ****************
REM ERRORS
REM ****************
:InvalidGameDirectory
echo -
echo Error: "%~3" is not a valid game directory.
echo (The -game directory must have a gameinfo.txt file)
echo -
goto end
:NoSourceDirSpecified
echo ERROR: If you specify -game on the command line, you must specify -source.
goto usage
goto end
:NoShaderCompile
echo -
echo - ERROR: shadercompile.exe doesn't exist in %SDKBINDIR%
echo -
goto end
REM ****************
REM BUILD SHADERS
REM ****************
:build_shaders
rem echo --------------------------------
rem echo %inputbase%
rem echo --------------------------------
REM make sure that target dirs exist
REM files will be built in these targets and copied to their final destination
if not exist %shaderDir% mkdir %shaderDir%
if not exist %shaderDir%\fxc mkdir %shaderDir%\fxc
if not exist %shaderDir%\vsh mkdir %shaderDir%\vsh
if not exist %shaderDir%\psh mkdir %shaderDir%\psh
REM Nuke some files that we will add to later.
if exist filelist.txt del /f /q filelist.txt
if exist filestocopy.txt del /f /q filestocopy.txt
if exist filelistgen.txt del /f /q filelistgen.txt
if exist inclist.txt del /f /q inclist.txt
if exist vcslist.txt del /f /q vcslist.txt
REM ****************
REM Generate a makefile for the shader project
REM ****************
perl "%SrcDirBase%\devtools\bin\updateshaders.pl" -source "%SrcDirBase%" %inputbase%
REM ****************
REM Run the makefile, generating minimal work/build list for fxc files, go ahead and compile vsh and psh files.
REM ****************
rem nmake /S /C -f makefile.%inputbase% clean > clean.txt 2>&1
echo Building inc files, asm vcs files, and VMPI worklist for %inputbase%...
nmake /S /C -f makefile.%inputbase%
REM ****************
REM Copy the inc files to their target
REM ****************
if exist "inclist.txt" (
echo Publishing shader inc files to target...
perl %SrcDirBase%\devtools\bin\copyshaderincfiles.pl inclist.txt
)
REM ****************
REM Add the executables to the worklist.
REM ****************
if /i "%DIRECTX_SDK_VER%" == "pc09.00" (
rem echo "Copy extra files for dx 9 std
)
if /i "%DIRECTX_SDK_VER%" == "pc09.30" (
echo %SrcDirBase%\devtools\bin\d3dx9_33.dll >> filestocopy.txt
)
echo %SrcDirBase%\%DIRECTX_SDK_BIN_DIR%\dx_proxy.dll >> filestocopy.txt
echo %SDKBINDIR%\shadercompile.exe >> filestocopy.txt
echo %SDKBINDIR%\shadercompile_dll.dll >> filestocopy.txt
echo %SDKBINDIR%\vstdlib.dll >> filestocopy.txt
echo %SDKBINDIR%\tier0.dll >> filestocopy.txt
REM ****************
REM Cull duplicate entries in work/build list
REM ****************
if exist filestocopy.txt type filestocopy.txt | perl "%SrcDirBase%\devtools\bin\uniqifylist.pl" > uniquefilestocopy.txt
if exist filelistgen.txt if not "%dynamic_shaders%" == "1" (
echo Generating action list...
copy filelistgen.txt filelist.txt >nul
)
REM ****************
REM Execute distributed process on work/build list
REM ****************
set shader_path_cd=%cd%
if exist "filelist.txt" if exist "uniquefilestocopy.txt" if not "%dynamic_shaders%" == "1" (
echo Running distributed shader compilation...
cd /D %ChangeToDir%
echo %shadercompilecommand% %SDKArgs% -shaderpath "%shader_path_cd:/=\%" -allowdebug
%shadercompilecommand% %SDKArgs% -shaderpath "%shader_path_cd:/=\%" -allowdebug
cd /D %shader_path_cd%
)
REM ****************
REM PC Shader copy
REM Publish the generated files to the output dir using XCOPY
REM This batch file may have been invoked standalone or slaved (master does final smart mirror copy)
REM ****************
:DoXCopy
if not "%dynamic_shaders%" == "1" (
if not exist "%targetdir%" md "%targetdir%"
if not "%targetdir%"=="%shaderDir%" xcopy %shaderDir%\*.* "%targetdir%" /e /y
)
goto end
REM ****************
REM END
REM ****************
:end
%TTEXE% -diff %tt_start%
echo.

View File

@ -0,0 +1,33 @@
@echo off
setlocal
if /i "%1" == "-game" goto CleanGameDir
rem Clean out hl2
if exist ..\..\..\game\hl2\shaders rd /s /q ..\..\..\game\hl2\shaders
goto CleanOtherStuff
:CleanGameDir
set __GameDir=%~2
if not exist "%__GameDir%\gameinfo.txt" goto MissingGameInfo
if exist "%__GameDir%\shaders" rd /s /q "%2\shaders"
goto CleanOtherStuff
:CleanOtherStuff
if exist debug_dx9 rd /s /q debug_dx9
if exist fxctmp9 rd /s /q fxctmp9
if exist vshtmp9 rd /s /q vshtmp9
if exist pshtmp9 rd /s /q pshtmp9
if exist fxctmp9_tmp rd /s /q fxctmp9_tmp
if exist vshtmp9_tmp rd /s /q vshtmp9_tmp
if exist pshtmp9_tmp rd /s /q pshtmp9_tmp
if exist shaders rd /s /q shaders
goto end
:MissingGameInfo
echo Invalid -game parameter specified (no "%__GameDir%\gameinfo.txt" exists).
goto end
:end

View File

@ -0,0 +1,12 @@
@echo off
setlocal
if exist fxctmp9_tmp rd /s /q fxctmp9_tmp
if exist vshtmp9_tmp rd /s /q vshtmp9_tmp
if exist pshtmp9_tmp rd /s /q pshtmp9_tmp
if exist fxctmp9_360_tmp rd /s /q fxctmp9_360_tmp
if exist vshtmp9_360_tmp rd /s /q vshtmp9_360_tmp
if exist pshtmp9_360_tmp rd /s /q pshtmp9_360_tmp
if exist shaders rd /s /q shaders

View File

@ -0,0 +1,407 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
// Utility class for building command buffers into memory
//===========================================================================//
#ifndef COMMANDBUILDER_H
#define COMMANDBUILDER_H
#ifndef COMMANDBUFFER_H
#include "shaderapi/commandbuffer.h"
#endif
#include "BaseVSShader.h"
#include "shaderapi/ishaderapi.h"
#ifdef _WIN32
#pragma once
#endif
extern ConVar my_mat_fullbright;
template<int N> class CFixedCommandStorageBuffer
{
public:
uint8 m_Data[N];
uint8 *m_pDataOut;
#ifdef DBGFLAG_ASSERT
size_t m_nNumBytesRemaining;
#endif
FORCEINLINE CFixedCommandStorageBuffer( void )
{
m_pDataOut = m_Data;
#ifdef DBGFLAG_ASSERT
m_nNumBytesRemaining = N;
#endif
}
FORCEINLINE void EnsureCapacity( size_t sz )
{
Assert( m_nNumBytesRemaining >= sz );
}
template<class T> FORCEINLINE void Put( T const &nValue )
{
EnsureCapacity( sizeof( T ) );
*( reinterpret_cast<T *>( m_pDataOut ) ) = nValue;
m_pDataOut += sizeof( nValue );
#ifdef DBGFLAG_ASSERT
m_nNumBytesRemaining -= sizeof( nValue );
#endif
}
FORCEINLINE void PutInt( int nValue )
{
Put( nValue );
}
FORCEINLINE void PutFloat( float nValue )
{
Put( nValue );
}
FORCEINLINE void PutPtr( void * pPtr )
{
Put( pPtr );
}
FORCEINLINE void PutMemory( const void *pMemory, size_t nBytes )
{
EnsureCapacity( nBytes );
memcpy( m_pDataOut, pMemory, nBytes );
m_pDataOut += nBytes;
}
FORCEINLINE uint8 *Base( void )
{
return m_Data;
}
FORCEINLINE void Reset( void )
{
m_pDataOut = m_Data;
#ifdef DBGFLAG_ASSERT
m_nNumBytesRemaining = N;
#endif
}
FORCEINLINE size_t Size( void ) const
{
return m_pDataOut - m_Data;
}
};
template<class S> class CCommandBufferBuilder
{
public:
S m_Storage;
FORCEINLINE void End( void )
{
m_Storage.PutInt( CBCMD_END );
}
FORCEINLINE IMaterialVar *Param( int nVar ) const
{
return CBaseShader::s_ppParams[nVar];
}
FORCEINLINE void SetPixelShaderConstants( int nFirstConstant, int nConstants )
{
m_Storage.PutInt( CBCMD_SET_PIXEL_SHADER_FLOAT_CONST );
m_Storage.PutInt( nFirstConstant );
m_Storage.PutInt( nConstants );
}
FORCEINLINE void OutputConstantData( float const *pSrcData )
{
m_Storage.PutFloat( pSrcData[0] );
m_Storage.PutFloat( pSrcData[1] );
m_Storage.PutFloat( pSrcData[2] );
m_Storage.PutFloat( pSrcData[3] );
}
FORCEINLINE void OutputConstantData4( float flVal0, float flVal1, float flVal2, float flVal3 )
{
m_Storage.PutFloat( flVal0 );
m_Storage.PutFloat( flVal1 );
m_Storage.PutFloat( flVal2 );
m_Storage.PutFloat( flVal3 );
}
FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, float const *pSrcData, int nNumConstantsToSet )
{
SetPixelShaderConstants( nFirstConstant, nNumConstantsToSet );
m_Storage.PutMemory( pSrcData, 4 * sizeof( float ) * nNumConstantsToSet );
}
FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, int nVar )
{
SetPixelShaderConstant( nFirstConstant, Param( nVar )->GetVecValue() );
}
void SetPixelShaderConstantGammaToLinear( int pixelReg, int constantVar )
{
float val[4];
Param(constantVar)->GetVecValue( val, 3 );
val[0] = val[0] > 1.0f ? val[0] : GammaToLinear( val[0] );
val[1] = val[1] > 1.0f ? val[1] : GammaToLinear( val[1] );
val[2] = val[2] > 1.0f ? val[2] : GammaToLinear( val[2] );
val[3] = 1.0;
SetPixelShaderConstant( pixelReg, val );
}
FORCEINLINE void SetPixelShaderConstant( int nFirstConstant, float const *pSrcData )
{
SetPixelShaderConstants( nFirstConstant, 1 );
OutputConstantData( pSrcData );
}
FORCEINLINE void SetPixelShaderConstant4( int nFirstConstant, float flVal0, float flVal1, float flVal2, float flVal3 )
{
SetPixelShaderConstants( nFirstConstant, 1 );
OutputConstantData4( flVal0, flVal1, flVal2, flVal3 );
}
FORCEINLINE void SetPixelShaderConstant_W( int pixelReg, int constantVar, float fWValue )
{
if ( constantVar != -1 )
{
float val[3];
Param(constantVar)->GetVecValue( val, 3);
SetPixelShaderConstant4( pixelReg, val[0], val[1], val[2], fWValue );
}
}
FORCEINLINE void SetVertexShaderConstant( int nFirstConstant, float const *pSrcData )
{
m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST );
m_Storage.PutInt( nFirstConstant );
m_Storage.PutInt( 1 );
OutputConstantData( pSrcData );
}
FORCEINLINE void SetVertexShaderConstant( int nFirstConstant, float const *pSrcData, int nConsts )
{
m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST );
m_Storage.PutInt( nFirstConstant );
m_Storage.PutInt( nConsts );
m_Storage.PutMemory( pSrcData, 4 * nConsts * sizeof( float ) );
}
FORCEINLINE void SetVertexShaderConstant4( int nFirstConstant, float flVal0, float flVal1, float flVal2, float flVal3 )
{
m_Storage.PutInt( CBCMD_SET_VERTEX_SHADER_FLOAT_CONST );
m_Storage.PutInt( nFirstConstant );
m_Storage.PutInt( 1 );
m_Storage.PutFloat( flVal0 );
m_Storage.PutFloat( flVal1 );
m_Storage.PutFloat( flVal2 );
m_Storage.PutFloat( flVal3 );
}
void SetVertexShaderTextureTransform( int vertexReg, int transformVar )
{
Vector4D transformation[2];
IMaterialVar* pTransformationVar = Param( transformVar );
if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX))
{
const VMatrix &mat = pTransformationVar->GetMatrixValue();
transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] );
transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] );
}
else
{
transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f );
transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f );
}
SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 );
}
void SetVertexShaderTextureScaledTransform( int vertexReg, int transformVar, int scaleVar )
{
Vector4D transformation[2];
IMaterialVar* pTransformationVar = Param( transformVar );
if (pTransformationVar && (pTransformationVar->GetType() == MATERIAL_VAR_TYPE_MATRIX))
{
const VMatrix &mat = pTransformationVar->GetMatrixValue();
transformation[0].Init( mat[0][0], mat[0][1], mat[0][2], mat[0][3] );
transformation[1].Init( mat[1][0], mat[1][1], mat[1][2], mat[1][3] );
}
else
{
transformation[0].Init( 1.0f, 0.0f, 0.0f, 0.0f );
transformation[1].Init( 0.0f, 1.0f, 0.0f, 0.0f );
}
Vector2D scale( 1, 1 );
IMaterialVar* pScaleVar = Param( scaleVar );
if (pScaleVar)
{
if (pScaleVar->GetType() == MATERIAL_VAR_TYPE_VECTOR)
pScaleVar->GetVecValue( scale.Base(), 2 );
else if (pScaleVar->IsDefined())
scale[0] = scale[1] = pScaleVar->GetFloatValue();
}
// Apply the scaling
transformation[0][0] *= scale[0];
transformation[0][1] *= scale[1];
transformation[1][0] *= scale[0];
transformation[1][1] *= scale[1];
transformation[0][3] *= scale[0];
transformation[1][3] *= scale[1];
SetVertexShaderConstant( vertexReg, transformation[0].Base(), 2 );
}
FORCEINLINE void SetEnvMapTintPixelShaderDynamicState( int pixelReg, int tintVar )
{
if( g_pConfig->bShowSpecular && my_mat_fullbright.GetInt() != 2 )
{
SetPixelShaderConstant( pixelReg, Param( tintVar)->GetVecValue() );
}
else
{
SetPixelShaderConstant4( pixelReg, 0.0, 0.0, 0.0, 0.0 );
}
}
FORCEINLINE void SetEnvMapTintPixelShaderDynamicStateGammaToLinear( int pixelReg, int tintVar, float flAlphaValue = 1.0 )
{
if( ( tintVar != -1 ) && g_pConfig->bShowSpecular && my_mat_fullbright.GetInt() != 2 )
{
float color[4];
color[3] = flAlphaValue;
Param( tintVar)->GetLinearVecValue( color, 3 );
SetPixelShaderConstant( pixelReg, color );
}
else
{
SetPixelShaderConstant4( pixelReg, 0.0, 0.0, 0.0, flAlphaValue );
}
}
FORCEINLINE void StoreEyePosInPixelShaderConstant( int nConst )
{
m_Storage.PutInt( CBCMD_STORE_EYE_POS_IN_PSCONST );
m_Storage.PutInt( nConst );
}
FORCEINLINE void CommitPixelShaderLighting( int nConst )
{
m_Storage.PutInt( CBCMD_COMMITPIXELSHADERLIGHTING );
m_Storage.PutInt( nConst );
}
FORCEINLINE void SetPixelShaderStateAmbientLightCube( int nConst )
{
m_Storage.PutInt( CBCMD_SETPIXELSHADERSTATEAMBIENTLIGHTCUBE );
m_Storage.PutInt( nConst );
}
FORCEINLINE void SetAmbientCubeDynamicStateVertexShader( void )
{
m_Storage.PutInt( CBCMD_SETAMBIENTCUBEDYNAMICSTATEVERTEXSHADER );
}
FORCEINLINE void SetPixelShaderFogParams( int nReg )
{
m_Storage.PutInt( CBCMD_SETPIXELSHADERFOGPARAMS );
m_Storage.PutInt( nReg );
}
FORCEINLINE void BindStandardTexture( Sampler_t nSampler, StandardTextureId_t nTextureId )
{
m_Storage.PutInt( CBCMD_BIND_STANDARD_TEXTURE );
m_Storage.PutInt( nSampler );
m_Storage.PutInt( nTextureId );
}
FORCEINLINE void BindTexture( Sampler_t nSampler, ShaderAPITextureHandle_t hTexture )
{
Assert( hTexture != INVALID_SHADERAPI_TEXTURE_HANDLE );
if ( hTexture != INVALID_SHADERAPI_TEXTURE_HANDLE )
{
m_Storage.PutInt( CBCMD_BIND_SHADERAPI_TEXTURE_HANDLE );
m_Storage.PutInt( nSampler );
m_Storage.PutInt( hTexture );
}
}
FORCEINLINE void BindTexture( CBaseVSShader *pShader, Sampler_t nSampler, int nTextureVar, int nFrameVar )
{
ShaderAPITextureHandle_t hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar );
BindTexture( nSampler, hTexture );
}
FORCEINLINE void BindMultiTexture( CBaseVSShader *pShader, Sampler_t nSampler1, Sampler_t nSampler2, int nTextureVar, int nFrameVar )
{
ShaderAPITextureHandle_t hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar, 0 );
BindTexture( nSampler1, hTexture );
hTexture = pShader->GetShaderAPITextureBindHandle( nTextureVar, nFrameVar, 1 );
BindTexture( nSampler2, hTexture );
}
FORCEINLINE void SetPixelShaderIndex( int nIndex )
{
m_Storage.PutInt( CBCMD_SET_PSHINDEX );
m_Storage.PutInt( nIndex );
}
FORCEINLINE void SetVertexShaderIndex( int nIndex )
{
m_Storage.PutInt( CBCMD_SET_VSHINDEX );
m_Storage.PutInt( nIndex );
}
FORCEINLINE void SetDepthFeatheringPixelShaderConstant( int iConstant, float fDepthBlendScale )
{
m_Storage.PutInt( CBCMD_SET_DEPTH_FEATHERING_CONST );
m_Storage.PutInt( iConstant );
m_Storage.PutFloat( fDepthBlendScale );
}
FORCEINLINE void Goto( uint8 *pCmdBuf )
{
m_Storage.PutInt( CBCMD_JUMP );
m_Storage.PutPtr( pCmdBuf );
}
FORCEINLINE void Call( uint8 *pCmdBuf )
{
m_Storage.PutInt( CBCMD_JSR );
m_Storage.PutPtr( pCmdBuf );
}
FORCEINLINE void Reset( void )
{
m_Storage.Reset();
}
FORCEINLINE size_t Size( void ) const
{
return m_Storage.Size();
}
FORCEINLINE uint8 *Base( void )
{
return m_Storage.Base();
}
};
#endif // commandbuilder_h

View File

@ -0,0 +1,821 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Common pixel shader code specific to flashlights
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef COMMON_FLASHLIGHT_FXC_H_
#define COMMON_FLASHLIGHT_FXC_H_
#include "common_ps_fxc.h"
// JasonM - TODO: remove this simpleton version
float DoShadow( sampler DepthSampler, float4 texCoord )
{
const float g_flShadowBias = 0.0005f;
float2 uoffset = float2( 0.5f/512.f, 0.0f );
float2 voffset = float2( 0.0f, 0.5f/512.f );
float3 projTexCoord = texCoord.xyz / texCoord.w;
float4 flashlightDepth = float4( tex2D( DepthSampler, projTexCoord + uoffset + voffset ).x,
tex2D( DepthSampler, projTexCoord + uoffset - voffset ).x,
tex2D( DepthSampler, projTexCoord - uoffset + voffset ).x,
tex2D( DepthSampler, projTexCoord - uoffset - voffset ).x );
# if ( defined( REVERSE_DEPTH_ON_X360 ) )
{
flashlightDepth = 1.0f - flashlightDepth;
}
# endif
float shadowed = 0.0f;
float z = texCoord.z/texCoord.w;
float4 dz = float4(z,z,z,z) - (flashlightDepth + float4( g_flShadowBias, g_flShadowBias, g_flShadowBias, g_flShadowBias));
float4 shadow = float4(0.25f,0.25f,0.25f,0.25f);
if( dz.x <= 0.0f )
shadowed += shadow.x;
if( dz.y <= 0.0f )
shadowed += shadow.y;
if( dz.z <= 0.0f )
shadowed += shadow.z;
if( dz.w <= 0.0f )
shadowed += shadow.w;
return shadowed;
}
float DoShadowNvidiaRAWZOneTap( sampler DepthSampler, const float4 shadowMapPos )
{
float ooW = 1.0f / shadowMapPos.w; // 1 / w
float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once
float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter
float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space
float fDepth = dot(tex2D(DepthSampler, shadowMapCenter).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));
return fDepth > objDepth;
}
float DoShadowNvidiaRAWZ( sampler DepthSampler, const float4 shadowMapPos )
{
float fE = 1.0f / 512.0f; // Epsilon
float ooW = 1.0f / shadowMapPos.w; // 1 / w
float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once
float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter
float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space
float4 vDepths;
vDepths.x = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));
vDepths.y = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));
vDepths.z = dot(tex2D(DepthSampler, shadowMapCenter + float2( fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));
vDepths.w = dot(tex2D(DepthSampler, shadowMapCenter + float2( -fE, -fE )).arg, float3(0.996093809371817670572857294849, 0.0038909914428586627756752238080039, 1.5199185323666651467481343000015e-5));
return dot(vDepths > objDepth.xxxx, float4(0.25, 0.25, 0.25, 0.25));
}
float DoShadowNvidiaCheap( sampler DepthSampler, const float4 shadowMapPos )
{
float fTexelEpsilon = 1.0f / 1024.0f;
float ooW = 1.0f / shadowMapPos.w; // 1 / w
float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once
float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter
float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space
float4 vTaps;
vTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x;
vTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon), objDepth, 1 ) ).x;
vTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x;
vTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon), objDepth, 1 ) ).x;
return dot(vTaps, float4(0.25, 0.25, 0.25, 0.25));
}
float DoShadowNvidiaPCF3x3Box( sampler DepthSampler, const float4 shadowMapPos )
{
float fTexelEpsilon = 1.0f / 1024.0f;
float ooW = 1.0f / shadowMapPos.w; // 1 / w
float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once
float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter
float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space
float4 vOneTaps;
vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x;
vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, fTexelEpsilon ), objDepth, 1 ) ).x;
vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x;
vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, -fTexelEpsilon ), objDepth, 1 ) ).x;
float flOneTaps = dot( vOneTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f));
float4 vTwoTaps;
vTwoTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTexelEpsilon, 0 ), objDepth, 1 ) ).x;
vTwoTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTexelEpsilon, 0 ), objDepth, 1 ) ).x;
vTwoTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x;
vTwoTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTexelEpsilon ), objDepth, 1 ) ).x;
float flTwoTaps = dot( vTwoTaps, float4(1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f, 1.0f / 9.0f));
float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (1.0f / 9.0f);
// Sum all 9 Taps
return flOneTaps + flTwoTaps + flCenterTap;
}
//
// 1 4 7 4 1
// 4 20 33 20 4
// 7 33 55 33 7
// 4 20 33 20 4
// 1 4 7 4 1
//
float DoShadowNvidiaPCF5x5Gaussian( sampler DepthSampler, const float4 shadowMapPos )
{
float fEpsilon = 1.0f / 512.0f;
float fTwoEpsilon = 2.0f * fEpsilon;
float ooW = 1.0f / shadowMapPos.w; // 1 / w
float3 shadowMapCenter_objDepth = shadowMapPos.xyz * ooW; // Do both projections at once
float2 shadowMapCenter = shadowMapCenter_objDepth.xy; // Center of shadow filter
float objDepth = shadowMapCenter_objDepth.z; // Object depth in shadow space
float4 vOneTaps;
vOneTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;
vOneTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;
vOneTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;
vOneTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;
float flOneTaps = dot( vOneTaps, float4(1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f, 1.0f / 331.0f));
float4 vSevenTaps;
vSevenTaps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, 0 ), objDepth, 1 ) ).x;
vSevenTaps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, 0 ), objDepth, 1 ) ).x;
vSevenTaps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x;
vSevenTaps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fTwoEpsilon ), objDepth, 1 ) ).x;
float flSevenTaps = dot( vSevenTaps, float4( 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f, 7.0f / 331.0f ) );
float4 vFourTapsA, vFourTapsB;
vFourTapsA.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x;
vFourTapsA.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;
vFourTapsA.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fTwoEpsilon ), objDepth, 1 ) ).x;
vFourTapsA.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, fEpsilon ), objDepth, 1 ) ).x;
vFourTapsB.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x;
vFourTapsB.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;
vFourTapsB.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fTwoEpsilon ), objDepth, 1 ) ).x;
vFourTapsB.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fTwoEpsilon, -fEpsilon ), objDepth, 1 ) ).x;
float flFourTapsA = dot( vFourTapsA, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) );
float flFourTapsB = dot( vFourTapsB, float4( 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f, 4.0f / 331.0f ) );
float4 v20Taps;
v20Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, fEpsilon ), objDepth, 1 ) ).x;
v20Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, fEpsilon ), objDepth, 1 ) ).x;
v20Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, -fEpsilon ), objDepth, 1 ) ).x;
v20Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, -fEpsilon ), objDepth, 1 ) ).x;
float fl20Taps = dot( v20Taps, float4(20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f, 20.0f / 331.0f));
float4 v33Taps;
v33Taps.x = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( fEpsilon, 0 ), objDepth, 1 ) ).x;
v33Taps.y = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( -fEpsilon, 0 ), objDepth, 1 ) ).x;
v33Taps.z = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x;
v33Taps.w = tex2Dproj( DepthSampler, float4( shadowMapCenter + float2( 0, -fEpsilon ), objDepth, 1 ) ).x;
float fl33Taps = dot( v33Taps, float4(33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f, 33.0f / 331.0f));
float flCenterTap = tex2Dproj( DepthSampler, float4( shadowMapCenter, objDepth, 1 ) ).x * (55.0f / 331.0f);
// Sum all 25 Taps
return flOneTaps + flSevenTaps + +flFourTapsA + flFourTapsB + fl20Taps + fl33Taps + flCenterTap;
}
float DoShadowATICheap( sampler DepthSampler, const float4 shadowMapPos )
{
float2 shadowMapCenter = shadowMapPos.xy/shadowMapPos.w;
float objDepth = shadowMapPos.z / shadowMapPos.w;
float fSampleDepth = tex2D( DepthSampler, shadowMapCenter ).x;
objDepth = min( objDepth, 0.99999 ); //HACKHACK: On 360, surfaces at or past the far flashlight plane have an abrupt cutoff. This is temp until a smooth falloff is implemented
return fSampleDepth > objDepth;
}
// Poisson disc, randomly rotated at different UVs
float DoShadowPoisson16Sample( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks, bool bNvidiaHardwarePCF, bool bFetch4 )
{
float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ),
float2( 0.8806f, 0.3430f ),
float2( -0.0041f, -0.6197f ),
float2( 0.0472f, 0.4964f ),
float2( -0.3730f, 0.0874f ),
float2( -0.9217f, -0.3177f ),
float2( -0.6289f, 0.7388f ),
float2( 0.5744f, -0.7741f ) };
float flScaleOverMapSize = vShadowTweaks.x * 2; // Tweak parameters to shader
float2 vNoiseOffset = vShadowTweaks.zw;
float4 vLightDepths = 0, accum = 0.0f;
float2 rotOffset = 0;
float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter
float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space
// 2D Rotation Matrix setup
float3 RMatTop = 0, RMatBottom = 0;
#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)
RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5) + vNoiseOffset) * 2.0 - 1.0;
RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple
#endif
RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution
RMatBottom *= flScaleOverMapSize;
RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below
RMatBottom.z = shadowMapCenter.y;
float fResult = 0.0f;
if ( bNvidiaHardwarePCF )
{
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[0].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[0].xy) + RMatBottom.z;
vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[1].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[1].xy) + RMatBottom.z;
vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[2].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[2].xy) + RMatBottom.z;
vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[3].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[3].xy) + RMatBottom.z;
vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4].xy) + RMatBottom.z;
vLightDepths.x += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[5].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[5].xy) + RMatBottom.z;
vLightDepths.y += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[6].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[6].xy) + RMatBottom.z;
vLightDepths.z += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[7].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[7].xy) + RMatBottom.z;
vLightDepths.w += tex2Dproj( DepthSampler, float4(rotOffset, objDepth, 1) ).x;
fResult = dot( vLightDepths, float4( 0.25, 0.25, 0.25, 0.25) );
}
else if ( bFetch4 )
{
/*
TODO: Fix this contact hardening stuff
float flNumCloserSamples = 1;
float flAccumulatedCloserSamples = objDepth;
float4 vBlockerDepths;
// First, search for blockers
for( int j=0; j<8; j++ )
{
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[j].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[j].xy) + RMatBottom.z;
vBlockerDepths = tex2D( DepthSampler, rotOffset.xy );
// Which samples are closer than the pixel we're rendering?
float4 vCloserSamples = (vBlockerDepths < objDepth.xxxx ); // Binary comparison results
flNumCloserSamples += dot( vCloserSamples, float4(1, 1, 1, 1) ); // How many samples are closer than receiver?
flAccumulatedCloserSamples += dot (vCloserSamples, vBlockerDepths ); // Total depths from samples closer than receiver
}
float flBlockerDepth = flAccumulatedCloserSamples / flNumCloserSamples;
float flContactHardeningScale = (objDepth - flBlockerDepth) / flBlockerDepth;
// Scale the kernel
RMatTop.xy *= flContactHardeningScale;
RMatBottom.xy *= flContactHardeningScale;
*/
for( int i=0; i<8; i++ )
{
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[i].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[i].xy) + RMatBottom.z;
vLightDepths = tex2D( DepthSampler, rotOffset.xy );
accum += (vLightDepths > objDepth.xxxx);
}
fResult = dot( accum, float4( 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f, 1.0f/32.0f) );
}
else // ATI vanilla hardware shadow mapping
{
for( int i=0; i<2; i++ )
{
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+0].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+0].xy) + RMatBottom.z;
vLightDepths.x = tex2D( DepthSampler, rotOffset.xy ).x;
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+1].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+1].xy) + RMatBottom.z;
vLightDepths.y = tex2D( DepthSampler, rotOffset.xy ).x;
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+2].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+2].xy) + RMatBottom.z;
vLightDepths.z = tex2D( DepthSampler, rotOffset.xy ).x;
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4*i+3].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4*i+3].xy) + RMatBottom.z;
vLightDepths.w = tex2D( DepthSampler, rotOffset.xy ).x;
accum += (vLightDepths > objDepth.xxxx);
}
fResult = dot( accum, float4( 0.125, 0.125, 0.125, 0.125) );
}
return fResult;
}
#if defined( _X360 )
// Poisson disc, randomly rotated at different UVs
float DoShadow360Simple( sampler DepthSampler, const float3 vProjCoords )
{
float fLOD;
float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter
float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space
#if defined( REVERSE_DEPTH_ON_X360 )
objDepth = 1.0f - objDepth;
#endif
float4 vSampledDepths, vWeights;
asm {
getCompTexLOD2D fLOD.x, shadowMapCenter.xy, DepthSampler, AnisoFilter=max16to1
setTexLOD fLOD.x
tfetch2D vSampledDepths.x___, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepths._x__, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepths.__x_, shadowMapCenter, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepths.___x, shadowMapCenter, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
getWeights2D vWeights, shadowMapCenter.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true
};
vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y );
#if defined( REVERSE_DEPTH_ON_X360 )
float4 vCompare = (vSampledDepths < objDepth.xxxx);
#else
float4 vCompare = (vSampledDepths > objDepth.xxxx);
#endif
return dot( vCompare, vWeights );
}
float Do360PCFFetch( sampler DepthSampler, float2 tc, float objDepth )
{
float fLOD;
float4 vSampledDepths, vWeights;
asm {
getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1
setTexLOD fLOD.x
tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
getWeights2D vWeights, tc.xy, DepthSampler, MagFilter=linear, MinFilter=linear, UseComputedLOD=false, UseRegisterLOD=true
};
vWeights = float4( (1-vWeights.x)*(1-vWeights.y), vWeights.x*(1-vWeights.y), (1-vWeights.x)*vWeights.y, vWeights.x*vWeights.y );
#if defined( REVERSE_DEPTH_ON_X360 )
float4 vCompare = (vSampledDepths < objDepth.xxxx);
#else
float4 vCompare = (vSampledDepths > objDepth.xxxx);
#endif
return dot( vCompare, vWeights );
}
float Do360NearestFetch( sampler DepthSampler, float2 tc, float objDepth )
{
float fLOD;
float4 vSampledDepth;
asm {
getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1
setTexLOD fLOD.x
tfetch2D vSampledDepth.x___, tc, DepthSampler, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
};
#if defined( REVERSE_DEPTH_ON_X360 )
return (vSampledDepth.x < objDepth.x);
#else
return (vSampledDepth.x > objDepth.x);
#endif
}
float AmountShadowed_8Tap_360( sampler DepthSampler, float2 tc, float objDepth )
{
float fLOD;
float4 vSampledDepthsA, vSampledDepthsB;
// Optimal 8 rooks pattern to get an idea about whether we're at a penumbra or not
// From [Kallio07] "Scanline Edge-Flag Algorithm for Antialiasing"
//
// +---+---+---+---+---+---+---+---+
// | | | | | | o | | |
// +---+---+---+---+---+---+---+---+
// | o | | | | | | | |
// +---+---+---+---+---+---+---+---+
// | | | | o | | | | |
// +---+---+---+---+---+---+---+---+
// | | | | | | | o | |
// +---+---+---+---+---+---+---+---+
// | | o | | | | | | |
// +---+---+---+---+---+---+---+---+
// | | | | | o | | | |
// +---+---+---+---+---+---+---+---+
// | | | | | | | | o |
// +---+---+---+---+---+---+---+---+
// | | | o | | | | | |
// +---+---+---+---+---+---+---+---+
//
asm {
getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1
setTexLOD fLOD.x
tfetch2D vSampledDepthsA.x___, tc, DepthSampler, OffsetX = -2.0, OffsetY = -1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepthsA._x__, tc, DepthSampler, OffsetX = -1.5, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepthsA.__x_, tc, DepthSampler, OffsetX = -1.0, OffsetY = 2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepthsA.___x, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepthsB.x___, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepthsB._x__, tc, DepthSampler, OffsetX = 1.0, OffsetY = -2.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepthsB.__x_, tc, DepthSampler, OffsetX = 1.5, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepthsB.___x, tc, DepthSampler, OffsetX = 2.0, OffsetY = 1.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
};
#if defined( REVERSE_DEPTH_ON_X360 )
float4 vCompareA = (vSampledDepthsA < objDepth.xxxx);
float4 vCompareB = (vSampledDepthsB < objDepth.xxxx);
#else
float4 vCompareA = (vSampledDepthsA > objDepth.xxxx);
float4 vCompareB = (vSampledDepthsB > objDepth.xxxx);
#endif
return dot( vCompareA, float4(0.125,0.125,0.125,0.125) ) + dot( vCompareB, float4(0.125,0.125,0.125,0.125) );
}
float AmountShadowed_4Tap_360( sampler DepthSampler, float2 tc, float objDepth )
{
float fLOD;
float4 vSampledDepths;
// Rotated grid pattern to get an idea about whether we're at a penumbra or not
asm {
getCompTexLOD2D fLOD.x, tc.xy, DepthSampler, AnisoFilter=max16to1
setTexLOD fLOD.x
tfetch2D vSampledDepths.x___, tc, DepthSampler, OffsetX = -1.0, OffsetY = 0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepths._x__, tc, DepthSampler, OffsetX = -0.5, OffsetY = -1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepths.__x_, tc, DepthSampler, OffsetX = 0.5, OffsetY = 1.0, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
tfetch2D vSampledDepths.___x, tc, DepthSampler, OffsetX = 1.0, OffsetY = -0.5, UseComputedLOD=false, UseRegisterLOD=true, MagFilter = point, MinFilter = point
};
#if defined( REVERSE_DEPTH_ON_X360 )
float4 vCompare = (vSampledDepths < objDepth.xxxx);
#else
float4 vCompare = (vSampledDepths > objDepth.xxxx);
#endif
return dot( vCompare, float4(0.25,0.25,0.25,0.25) );
}
// Poisson disc, randomly rotated at different UVs
float DoShadowPoisson360( sampler DepthSampler, sampler RandomRotationSampler, const float3 vProjCoords, const float2 vScreenPos, const float4 vShadowTweaks )
{
float2 vPoissonOffset[8] = { float2( 0.3475f, 0.0042f ), float2( 0.8806f, 0.3430f ),
float2( -0.0041f, -0.6197f ), float2( 0.0472f, 0.4964f ),
float2( -0.3730f, 0.0874f ), float2( -0.9217f, -0.3177f ),
float2( -0.6289f, 0.7388f ), float2( 0.5744f, -0.7741f ) };
float2 shadowMapCenter = vProjCoords.xy; // Center of shadow filter
float objDepth = min( vProjCoords.z, 0.99999 ); // Object depth in shadow space
#if defined( REVERSE_DEPTH_ON_X360 )
objDepth = 1.0f - objDepth;
#endif
float fAmountShadowed = AmountShadowed_4Tap_360( DepthSampler, shadowMapCenter, objDepth );
if ( fAmountShadowed >= 1.0f ) // Fully in light
{
return 1.0f;
}
else // Do the expensive filtering since we're at least partially shadowed
{
float flScaleOverMapSize = 1.7f / 512.0f; // Tweak parameters to shader
// 2D Rotation Matrix setup
float3 RMatTop = 0, RMatBottom = 0;
#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)
RMatTop.xy = tex2D( RandomRotationSampler, cFlashlightScreenScale.xy * (vScreenPos * 0.5 + 0.5)) * 2.0 - 1.0;
RMatBottom.xy = float2(-1.0, 1.0) * RMatTop.yx; // 2x2 rotation matrix in 4-tuple
#endif
RMatTop *= flScaleOverMapSize; // Scale up kernel while accounting for texture resolution
RMatBottom *= flScaleOverMapSize;
RMatTop.z = shadowMapCenter.x; // To be added in d2adds generated below
RMatBottom.z = shadowMapCenter.y;
float2 rotOffset = float2(0,0);
float4 vAccum = 0;
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[0].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[0].xy) + RMatBottom.z;
vAccum.x = Do360NearestFetch( DepthSampler, rotOffset, objDepth );
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[1].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[1].xy) + RMatBottom.z;
vAccum.y = Do360NearestFetch( DepthSampler, rotOffset, objDepth );
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[2].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[2].xy) + RMatBottom.z;
vAccum.z = Do360NearestFetch( DepthSampler, rotOffset, objDepth );
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[3].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[3].xy) + RMatBottom.z;
vAccum.w = Do360NearestFetch( DepthSampler, rotOffset, objDepth );
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[4].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[4].xy) + RMatBottom.z;
vAccum.x += Do360NearestFetch( DepthSampler, rotOffset, objDepth );
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[5].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[5].xy) + RMatBottom.z;
vAccum.y += Do360NearestFetch( DepthSampler, rotOffset, objDepth );
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[6].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[6].xy) + RMatBottom.z;
vAccum.z += Do360NearestFetch( DepthSampler, rotOffset, objDepth );
rotOffset.x = dot (RMatTop.xy, vPoissonOffset[7].xy) + RMatTop.z;
rotOffset.y = dot (RMatBottom.xy, vPoissonOffset[7].xy) + RMatBottom.z;
vAccum.w += Do360NearestFetch( DepthSampler, rotOffset, objDepth );
return dot( vAccum, float4( 0.25, 0.25, 0.25, 0.25) );
}
}
#endif // _X360
float DoFlashlightShadow( sampler DepthSampler, sampler RandomRotationSampler, float3 vProjCoords, float2 vScreenPos, int nShadowLevel, float4 vShadowTweaks, bool bAllowHighQuality )
{
float flShadow = 1.0f;
#if !defined( _X360 ) //PC
if( nShadowLevel == NVIDIA_PCF_POISSON )
flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, true, false );
else if( nShadowLevel == ATI_NOPCF )
flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, false, false );
else if( nShadowLevel == ATI_NO_PCF_FETCH4 )
flShadow = DoShadowPoisson16Sample( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks, false, true );
return flShadow;
#else
// Compile-time switch for shaders which allow high quality modes on 360
if ( bAllowHighQuality )
{
// Static control flow switch for shadow quality. Some non-interactive sequences use the high quality path
if ( g_bHighQualityShadows )
{
flShadow = DoShadowPoisson360( DepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, vShadowTweaks );
}
else
{
flShadow = DoShadow360Simple( DepthSampler, vProjCoords );
}
}
else
{
flShadow = DoShadow360Simple( DepthSampler, vProjCoords );
}
return flShadow;
#endif
}
float3 SpecularLight( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent,
const float3 vEyeDir, const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel )
{
float3 result = float3(0.0f, 0.0f, 0.0f);
//float3 vReflect = reflect( -vEyeDir, vWorldNormal );
float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal
float3 vSpecular = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?)
vSpecular = pow( vSpecular.x, fSpecularExponent ); // Raise to specular power
// Optionally warp as function of scalar specular and fresnel
if ( bDoSpecularWarp )
vSpecular *= tex2D( specularWarpSampler, float2(vSpecular.x, fFresnel) ); // Sample at { (L.R)^k, fresnel }
return vSpecular;
}
void DoSpecularFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal,
float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler, sampler RandomRotationSampler,
int nShadowLevel, bool bDoShadows, bool bAllowHighQuality, const float2 vScreenPos, const float fSpecularExponent, const float3 vEyeDir,
const bool bDoSpecularWarp, sampler specularWarpSampler, float fFresnel, float4 vShadowTweaks,
// Outputs of this shader...separate shadowed diffuse and specular from the flashlight
out float3 diffuseLighting, out float3 specularLighting )
{
float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w;
float3 flashlightColor = float3(1,1,1);
#if ( defined( _X360 ) )
float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f );
float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f );
[branch]
if ( dot(ltz + gto, float3(1,1,1)) > 0 )
{
clip(-1);
diffuseLighting = specularLighting = float3(0,0,0);
return;
}
else
{
flashlightColor = tex2D( FlashlightSampler, vProjCoords );
[branch]
if ( dot(flashlightColor.xyz, float3(1,1,1)) <= 0 )
{
clip(-1);
diffuseLighting = specularLighting = float3(0,0,0);
return;
}
}
#else
flashlightColor = tex2D( FlashlightSampler, vProjCoords );
#endif
#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)
flashlightColor *= cFlashlightColor.xyz; // Flashlight color
#endif
float3 delta = flashlightPos - worldPos;
float3 L = normalize( delta );
float distSquared = dot( delta, delta );
float dist = sqrt( distSquared );
float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f );
// Attenuation for light and to fade out shadow over distance
float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) );
// Shadowing and coloring terms
#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))
if ( bDoShadows )
{
float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality );
float flAttenuated = lerp( flShadow, 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated
flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation
flashlightColor *= flShadow; // Shadow term
}
#endif
diffuseLighting = fAtten;
#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)
diffuseLighting *= saturate( dot( L.xyz, worldNormal.xyz ) + flFlashlightNoLambertValue ); // Lambertian term
#else
diffuseLighting *= saturate( dot( L.xyz, worldNormal.xyz ) ); // Lambertian (not Half-Lambert) term
#endif
diffuseLighting *= flashlightColor;
diffuseLighting *= endFalloffFactor;
// Specular term (masked by diffuse)
specularLighting = diffuseLighting * SpecularLight ( worldNormal, L, fSpecularExponent, vEyeDir, bDoSpecularWarp, specularWarpSampler, fFresnel );
}
// Diffuse only version
float3 DoFlashlight( float3 flashlightPos, float3 worldPos, float4 flashlightSpacePosition, float3 worldNormal,
float3 attenuationFactors, float farZ, sampler FlashlightSampler, sampler FlashlightDepthSampler,
sampler RandomRotationSampler, int nShadowLevel, bool bDoShadows, bool bAllowHighQuality,
const float2 vScreenPos, bool bClip, float4 vShadowTweaks = float4(3/1024.0f, 0.0005f, 0.0f, 0.0f), bool bHasNormal = true )
{
float3 vProjCoords = flashlightSpacePosition.xyz / flashlightSpacePosition.w;
float3 flashlightColor = float3(1,1,1);
#if ( defined( _X360 ) )
float3 ltz = vProjCoords.xyz < float3( 0.0f, 0.0f, 0.0f );
float3 gto = vProjCoords.xyz > float3( 1.0f, 1.0f, 1.0f );
[branch]
if ( dot(ltz + gto, float3(1,1,1)) > 0 )
{
if ( bClip )
{
clip(-1);
}
return float3(0,0,0);
}
else
{
flashlightColor = tex2D( FlashlightSampler, vProjCoords );
[branch]
if ( dot(flashlightColor.xyz, float3(1,1,1)) <= 0 )
{
if ( bClip )
{
clip(-1);
}
return float3(0,0,0);
}
}
#else
flashlightColor = tex2D( FlashlightSampler, vProjCoords );
#endif
#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)
flashlightColor *= cFlashlightColor.xyz; // Flashlight color
#endif
float3 delta = flashlightPos - worldPos;
float3 L = normalize( delta );
float distSquared = dot( delta, delta );
float dist = sqrt( distSquared );
float endFalloffFactor = RemapValClamped( dist, farZ, 0.6f * farZ, 0.0f, 1.0f );
// Attenuation for light and to fade out shadow over distance
float fAtten = saturate( dot( attenuationFactors, float3( 1.0f, 1.0f/dist, 1.0f/distSquared ) ) );
// Shadowing and coloring terms
#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))
if ( bDoShadows )
{
float flShadow = DoFlashlightShadow( FlashlightDepthSampler, RandomRotationSampler, vProjCoords, vScreenPos, nShadowLevel, vShadowTweaks, bAllowHighQuality );
float flAttenuated = lerp( flShadow, 1.0f, vShadowTweaks.y ); // Blend between fully attenuated and not attenuated
flShadow = saturate( lerp( flAttenuated, flShadow, fAtten ) ); // Blend between shadow and above, according to light attenuation
flashlightColor *= flShadow; // Shadow term
}
#endif
float3 diffuseLighting = fAtten;
float flLDotWorldNormal;
if ( bHasNormal )
{
flLDotWorldNormal = dot( L.xyz, worldNormal.xyz );
}
else
{
flLDotWorldNormal = 1.0f;
}
#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)
diffuseLighting *= saturate( flLDotWorldNormal + flFlashlightNoLambertValue ); // Lambertian term
#else
diffuseLighting *= saturate( flLDotWorldNormal ); // Lambertian (not Half-Lambert) term
#endif
diffuseLighting *= flashlightColor;
diffuseLighting *= endFalloffFactor;
return diffuseLighting;
}
#endif //#ifndef COMMON_FLASHLIGHT_FXC_H_

View File

@ -0,0 +1,326 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef COMMON_FXC_H_
#define COMMON_FXC_H_
#include "common_pragmas.h"
#include "common_hlsl_cpp_consts.h"
#ifdef NV3X
# define HALF half
# define HALF2 half2
# define HALF3 half3
# define HALF4 half4
# define HALF3x3 half3x3
# define HALF3x4 half3x4
# define HALF4x3 half4x3
# define HALF_CONSTANT( _constant ) ((HALF)_constant)
#else
# define HALF float
# define HALF2 float2
# define HALF3 float3
# define HALF4 float4
# define HALF3x3 float3x3
# define HALF3x4 float3x4
# define HALF4x3 float4x3
# define HALF_CONSTANT( _constant ) _constant
#endif
// This is where all common code for both vertex and pixel shaders.
#define OO_SQRT_3 0.57735025882720947f
static const HALF3 bumpBasis[3] = {
HALF3( 0.81649661064147949f, 0.0f, OO_SQRT_3 ),
HALF3( -0.40824833512306213f, 0.70710676908493042f, OO_SQRT_3 ),
HALF3( -0.40824821591377258f, -0.7071068286895752f, OO_SQRT_3 )
};
static const HALF3 bumpBasisTranspose[3] = {
HALF3( 0.81649661064147949f, -0.40824833512306213f, -0.40824833512306213f ),
HALF3( 0.0f, 0.70710676908493042f, -0.7071068286895752f ),
HALF3( OO_SQRT_3, OO_SQRT_3, OO_SQRT_3 )
};
#if defined( _X360 )
#define REVERSE_DEPTH_ON_X360 //uncomment to use D3DFMT_D24FS8 with an inverted depth viewport for better performance. Keep this in sync with the same named #define in public/shaderapi/shareddefs.h
//Note that the reversal happens in the viewport. So ONLY reading back from a depth texture should be affected. Projected math is unaffected.
#endif
HALF3 CalcReflectionVectorNormalized( HALF3 normal, HALF3 eyeVector )
{
// FIXME: might be better of normalizing with a normalizing cube map and
// get rid of the dot( normal, normal )
// compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v
return 2.0 * ( dot( normal, eyeVector ) / dot( normal, normal ) ) * normal - eyeVector;
}
HALF3 CalcReflectionVectorUnnormalized( HALF3 normal, HALF3 eyeVector )
{
// FIXME: might be better of normalizing with a normalizing cube map and
// get rid of the dot( normal, normal )
// compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v
// multiply all values through by N.N. uniformly scaling reflection vector won't affect result
// since it is used in a cubemap lookup
return (2.0*(dot( normal, eyeVector ))*normal) - (dot( normal, normal )*eyeVector);
}
float3 HuePreservingColorClamp( float3 c )
{
// Get the max of all of the color components and a specified maximum amount
float maximum = max( max( c.x, c.y ), max( c.z, 1.0f ) );
return (c / maximum);
}
HALF3 HuePreservingColorClamp( HALF3 c, HALF maxVal )
{
// Get the max of all of the color components and a specified maximum amount
float maximum = max( max( c.x, c.y ), max( c.z, maxVal ) );
return (c * ( maxVal / maximum ) );
}
#if (AA_CLAMP==1)
HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord )
{
HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99;
result += Lightmap3Coord;
return result;
}
void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord,
out HALF2 bumpCoord1,
out HALF2 bumpCoord2,
out HALF2 bumpCoord3 )
{
HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99;
result += Lightmap3Coord;
bumpCoord1 = result + HALF2(Lightmap1and2Coord.z, 0);
bumpCoord2 = result + 2*HALF2(Lightmap1and2Coord.z, 0);
bumpCoord3 = result + 3*HALF2(Lightmap1and2Coord.z, 0);
}
#else
HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord )
{
return Lightmap1and2Coord.xy;
}
void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord,
out HALF2 bumpCoord1,
out HALF2 bumpCoord2,
out HALF2 bumpCoord3 )
{
bumpCoord1 = Lightmap1and2Coord.xy;
bumpCoord2 = Lightmap1and2Coord.wz; // reversed order!!!
bumpCoord3 = Lightmap3Coord.xy;
}
#endif
// Versions of matrix multiply functions which force HLSL compiler to explictly use DOTs,
// not giving it the option of using MAD expansion. In a perfect world, the compiler would
// always pick the best strategy, and these shouldn't be needed.. but.. well.. umm..
//
// lorenmcq
float3 mul3x3(float3 v, float3x3 m)
{
#if !defined( _X360 )
return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2]));
#else
// xbox360 fxc.exe (new back end) borks with transposes, generates bad code
return mul( v, m );
#endif
}
float3 mul4x3(float4 v, float4x3 m)
{
#if !defined( _X360 )
return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2]));
#else
// xbox360 fxc.exe (new back end) borks with transposes, generates bad code
return mul( v, m );
#endif
}
float3 DecompressHDR( float4 input )
{
return input.rgb * input.a * MAX_HDR_OVERBRIGHT;
}
float4 CompressHDR( float3 input )
{
// FIXME: want to use min so that we clamp to white, but what happens if we
// have an albedo component that's less than 1/MAX_HDR_OVERBRIGHT?
// float fMax = max( max( color.r, color.g ), color.b );
float4 output;
float fMax = min( min( input.r, input.g ), input.b );
if( fMax > 1.0f )
{
float oofMax = 1.0f / fMax;
output.rgb = oofMax * input.rgb;
output.a = min( fMax / MAX_HDR_OVERBRIGHT, 1.0f );
}
else
{
output.rgb = input.rgb;
output.a = 0.0f;
}
return output;
}
float3 LinearToGamma( const float3 f3linear )
{
return pow( f3linear, 1.0f / 2.2f );
}
float4 LinearToGamma( const float4 f4linear )
{
return float4( pow( f4linear.xyz, 1.0f / 2.2f ), f4linear.w );
}
float LinearToGamma( const float f1linear )
{
return pow( f1linear, 1.0f / 2.2f );
}
float3 GammaToLinear( const float3 gamma )
{
return pow( gamma, 2.2f );
}
float4 GammaToLinear( const float4 gamma )
{
return float4( pow( gamma.xyz, 2.2f ), gamma.w );
}
float GammaToLinear( const float gamma )
{
return pow( gamma, 2.2f );
}
// These two functions use the actual sRGB math
float SrgbGammaToLinear( float flSrgbGammaValue )
{
float x = saturate( flSrgbGammaValue );
return ( x <= 0.04045f ) ? ( x / 12.92f ) : ( pow( ( x + 0.055f ) / 1.055f, 2.4f ) );
}
float SrgbLinearToGamma( float flLinearValue )
{
float x = saturate( flLinearValue );
return ( x <= 0.0031308f ) ? ( x * 12.92f ) : ( 1.055f * pow( x, ( 1.0f / 2.4f ) ) ) - 0.055f;
}
// These twofunctions use the XBox 360's exact piecewise linear algorithm
float X360GammaToLinear( float fl360GammaValue )
{
float flLinearValue;
fl360GammaValue = saturate( fl360GammaValue );
if ( fl360GammaValue < ( 96.0f / 255.0f ) )
{
if ( fl360GammaValue < ( 64.0f / 255.0f ) )
{
flLinearValue = fl360GammaValue * 255.0f;
}
else
{
flLinearValue = fl360GammaValue * ( 255.0f * 2.0f ) - 64.0f;
flLinearValue += floor( flLinearValue * ( 1.0f / 512.0f ) );
}
}
else
{
if( fl360GammaValue < ( 192.0f / 255.0f ) )
{
flLinearValue = fl360GammaValue * ( 255.0f * 4.0f ) - 256.0f;
flLinearValue += floor( flLinearValue * ( 1.0f / 256.0f ) );
}
else
{
flLinearValue = fl360GammaValue * ( 255.0f * 8.0f ) - 1024.0f;
flLinearValue += floor( flLinearValue * ( 1.0f / 128.0f ) );
}
}
flLinearValue *= 1.0f / 1023.0f;
flLinearValue = saturate( flLinearValue );
return flLinearValue;
}
float X360LinearToGamma( float flLinearValue )
{
float fl360GammaValue;
flLinearValue = saturate( flLinearValue );
if ( flLinearValue < ( 128.0f / 1023.0f ) )
{
if ( flLinearValue < ( 64.0f / 1023.0f ) )
{
fl360GammaValue = flLinearValue * ( 1023.0f * ( 1.0f / 255.0f ) );
}
else
{
fl360GammaValue = flLinearValue * ( ( 1023.0f / 2.0f ) * ( 1.0f / 255.0f ) ) + ( 32.0f / 255.0f );
}
}
else
{
if ( flLinearValue < ( 512.0f / 1023.0f ) )
{
fl360GammaValue = flLinearValue * ( ( 1023.0f / 4.0f ) * ( 1.0f / 255.0f ) ) + ( 64.0f / 255.0f );
}
else
{
fl360GammaValue = flLinearValue * ( ( 1023.0f /8.0f ) * ( 1.0f / 255.0f ) ) + ( 128.0f /255.0f ); // 1.0 -> 1.0034313725490196078431372549016
if ( fl360GammaValue > 1.0f )
{
fl360GammaValue = 1.0f;
}
}
}
fl360GammaValue = saturate( fl360GammaValue );
return fl360GammaValue;
}
float SrgbGammaTo360Gamma( float flSrgbGammaValue )
{
float flLinearValue = SrgbGammaToLinear( flSrgbGammaValue );
float fl360GammaValue = X360LinearToGamma( flLinearValue );
return fl360GammaValue;
}
float3 Vec3WorldToTangent( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )
{
float3 vTangentVector;
vTangentVector.x = dot( iWorldVector.xyz, iWorldTangent.xyz );
vTangentVector.y = dot( iWorldVector.xyz, iWorldBinormal.xyz );
vTangentVector.z = dot( iWorldVector.xyz, iWorldNormal.xyz );
return vTangentVector.xyz; // Return without normalizing
}
float3 Vec3WorldToTangentNormalized( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )
{
return normalize( Vec3WorldToTangent( iWorldVector, iWorldNormal, iWorldTangent, iWorldBinormal ) );
}
float3 Vec3TangentToWorld( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )
{
float3 vWorldVector;
vWorldVector.xyz = iTangentVector.x * iWorldTangent.xyz;
vWorldVector.xyz += iTangentVector.y * iWorldBinormal.xyz;
vWorldVector.xyz += iTangentVector.z * iWorldNormal.xyz;
return vWorldVector.xyz; // Return without normalizing
}
float3 Vec3TangentToWorldNormalized( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )
{
return normalize( Vec3TangentToWorld( iTangentVector, iWorldNormal, iWorldTangent, iWorldBinormal ) );
}
#endif //#ifndef COMMON_FXC_H_

View File

@ -0,0 +1,19 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef COMMON_FXC2_H_
#define COMMON_FXC2_H_
// This file is here so you can add new utility functions without
// changing common_fxc.h and causing a recompile of the entire universe.
float LinearToMonochrome ( float3 r )
{
return dot( r, float3( 0.299f, 0.587f, 0.114f ) );
}
#endif //#ifndef COMMON_FXC2_H_

View File

@ -0,0 +1,27 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef COMMON_HLSL_CONSTS_H_
#define COMMON_HLSL_CONSTS_H_
#ifdef NV3X
#define PSHADER_VECT_SCALE 20.0
#define VSHADER_VECT_SCALE (1.0 / (PSHADER_VECT_SCALE) )
#else
#define PSHADER_VECT_SCALE 1.0
#define VSHADER_VECT_SCALE 1.0
#endif
// GR - HDR luminance maps to 0..n range
// IMPORTANT: Keep the same value as in materialsystem_global.h
// HDRFIXME: Make this a pixel shader constant?
#define MAX_HDR_OVERBRIGHT 16.0f
#define LINEAR_FOG_COLOR 29
#define TONE_MAPPING_SCALE_PSH_CONSTANT 30
#endif //#ifndef COMMON_HLSL_CONSTS_H_

View File

@ -0,0 +1,202 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#if defined( _X360 )
void GetBaseTextureAndNormal( sampler base, sampler base2, sampler bump, bool bBase2, bool bBump, float3 coords, float3 vWeights,
out float4 vResultBase, out float4 vResultBase2, out float4 vResultBump )
{
vResultBase = 0;
vResultBase2 = 0;
vResultBump = 0;
if ( !bBump )
{
vResultBump = float4(0, 0, 1, 1);
}
#if SEAMLESS
vWeights = max( vWeights - 0.3, 0 );
vWeights *= 1.0f / dot( vWeights, float3(1,1,1) );
[branch]
if (vWeights.x > 0)
{
vResultBase += vWeights.x * tex2D( base, coords.zy );
if ( bBase2 )
{
vResultBase2 += vWeights.x * tex2D( base2, coords.zy );
}
if ( bBump )
{
vResultBump += vWeights.x * tex2D( bump, coords.zy );
}
}
[branch]
if (vWeights.y > 0)
{
vResultBase += vWeights.y * tex2D( base, coords.xz );
if ( bBase2 )
{
vResultBase2 += vWeights.y * tex2D( base2, coords.xz );
}
if ( bBump )
{
vResultBump += vWeights.y * tex2D( bump, coords.xz );
}
}
[branch]
if (vWeights.z > 0)
{
vResultBase += vWeights.z * tex2D( base, coords.xy );
if ( bBase2 )
{
vResultBase2 += vWeights.z * tex2D( base2, coords.xy );
}
if ( bBump )
{
vResultBump += vWeights.z * tex2D( bump, coords.xy );
}
}
#else // not seamless
vResultBase = tex2D( base, coords.xy );
if ( bBase2 )
{
vResultBase2 = tex2D( base2, coords.xy );
}
if ( bBump )
{
vResultBump = tex2D( bump, coords.xy );
}
#endif
}
#else // PC
void GetBaseTextureAndNormal( sampler base, sampler base2, sampler bump, bool bBase2, bool bBump, float3 coords, float3 vWeights,
out float4 vResultBase, out float4 vResultBase2, out float4 vResultBump )
{
vResultBase = 0;
vResultBase2 = 0;
vResultBump = 0;
if ( !bBump )
{
vResultBump = float4(0, 0, 1, 1);
}
#if SEAMLESS
vResultBase += vWeights.x * tex2D( base, coords.zy );
if ( bBase2 )
{
vResultBase2 += vWeights.x * tex2D( base2, coords.zy );
}
if ( bBump )
{
vResultBump += vWeights.x * tex2D( bump, coords.zy );
}
vResultBase += vWeights.y * tex2D( base, coords.xz );
if ( bBase2 )
{
vResultBase2 += vWeights.y * tex2D( base2, coords.xz );
}
if ( bBump )
{
vResultBump += vWeights.y * tex2D( bump, coords.xz );
}
vResultBase += vWeights.z * tex2D( base, coords.xy );
if ( bBase2 )
{
vResultBase2 += vWeights.z * tex2D( base2, coords.xy );
}
if ( bBump )
{
vResultBump += vWeights.z * tex2D( bump, coords.xy );
}
#else // not seamless
vResultBase = tex2D( base, coords.xy );
if ( bBase2 )
{
vResultBase2 = tex2D( base2, coords.xy );
}
if ( bBump )
{
vResultBump = tex2D( bump, coords.xy );
}
#endif
}
#endif
float3 LightMapSample( sampler LightmapSampler, float2 vTexCoord )
{
# if ( !defined( _X360 ) || !defined( USE_32BIT_LIGHTMAPS_ON_360 ) )
{
float3 sample = tex2D( LightmapSampler, vTexCoord );
return sample;
}
# else
{
# if 0 //1 for cheap sampling, 0 for accurate scaling from the individual samples
{
float4 sample = tex2D( LightmapSampler, vTexCoord );
return sample.rgb * sample.a;
}
# else
{
float4 Weights;
float4 samples_0; //no arrays allowed in inline assembly
float4 samples_1;
float4 samples_2;
float4 samples_3;
asm {
tfetch2D samples_0, vTexCoord.xy, LightmapSampler, OffsetX = -0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false
tfetch2D samples_1, vTexCoord.xy, LightmapSampler, OffsetX = 0.5, OffsetY = -0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false
tfetch2D samples_2, vTexCoord.xy, LightmapSampler, OffsetX = -0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false
tfetch2D samples_3, vTexCoord.xy, LightmapSampler, OffsetX = 0.5, OffsetY = 0.5, MinFilter=point, MagFilter=point, MipFilter=keep, UseComputedLOD=false
getWeights2D Weights, vTexCoord.xy, LightmapSampler
};
Weights = float4( (1-Weights.x)*(1-Weights.y), Weights.x*(1-Weights.y), (1-Weights.x)*Weights.y, Weights.x*Weights.y );
float3 result;
result.rgb = samples_0.rgb * (samples_0.a * Weights.x);
result.rgb += samples_1.rgb * (samples_1.a * Weights.y);
result.rgb += samples_2.rgb * (samples_2.a * Weights.z);
result.rgb += samples_3.rgb * (samples_3.a * Weights.w);
return result;
}
# endif
}
# endif
}

View File

@ -0,0 +1,38 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Common shader compiler pragmas
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef COMMON_PRAGMAS_H_
#define COMMON_PRAGMAS_H_
//
// Validated shader models:
//
// SHADER_MODEL_VS_1_1
// SHADER_MODEL_VS_2_0
// SHADER_MODEL_VS_3_0
//
// SHADER_MODEL_PS_1_1
// SHADER_MODEL_PS_1_4
// SHADER_MODEL_PS_2_0
// SHADER_MODEL_PS_2_B
// SHADER_MODEL_PS_3_0
//
//
//
// Platforms:
//
// PC
// _X360
//
// Special pragmas silencing common warnings
#pragma warning ( disable : 3557 ) // warning X3557: Loop only executes for N iteration(s), forcing loop to unroll
#pragma warning ( disable : 3595 ) // warning X3595: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused
#pragma warning ( disable : 3596 ) // warning X3596: Microcode Compiler possible performance issue: pixel shader input semantic ___ is unused
#pragma warning ( disable : 4702 ) // warning X4702: complement opportunity missed because input result WAS clamped from 0 to 1
#endif //#ifndef COMMON_PRAGMAS_H_

View File

@ -0,0 +1,804 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Common pixel shader code
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef COMMON_PS_FXC_H_
#define COMMON_PS_FXC_H_
#include "common_fxc.h"
// Put global skip commands here. . make sure and check that the appropriate vars are defined
// so these aren't used on the wrong shaders!
// --------------------------------------------------------------------------------
// HDR should never be enabled if we don't aren't running in float or integer HDR mode.
// SKIP: defined $HDRTYPE && defined $HDRENABLED && !$HDRTYPE && $HDRENABLED
// --------------------------------------------------------------------------------
// We don't ever write water fog to dest alpha if we aren't doing water fog.
// SKIP: defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA
// --------------------------------------------------------------------------------
// We don't need fog in the pixel shader if we aren't in float fog mode2
// NOSKIP: defined $HDRTYPE && defined $HDRENABLED && defined $PIXELFOGTYPE && $HDRTYPE != HDR_TYPE_FLOAT && $FOGTYPE != 0
// --------------------------------------------------------------------------------
// We don't do HDR and LIGHTING_PREVIEW at the same time since it's running LDR in hammer.
// SKIP: defined $LIGHTING_PREVIEW && defined $HDRTYPE && $LIGHTING_PREVIEW && $HDRTYPE != 0
// --------------------------------------------------------------------------------
// Ditch all fastpath attempts if we are doing LIGHTING_PREVIEW.
// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT
// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST
// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH
// --------------------------------------------------------------------------------
// Ditch flashlight depth when flashlight is disabled
// SKIP: ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW
// --------------------------------------------------------------------------------
// System defined pixel shader constants
#if defined( _X360 )
const bool g_bHighQualityShadows : register( b0 );
#endif
// NOTE: w == 1.0f / (Dest alpha compressed depth range).
const float4 g_LinearFogColor : register( c29 );
#define OO_DESTALPHA_DEPTH_RANGE (g_LinearFogColor.w)
// Linear and gamma light scale values
const float4 cLightScale : register( c30 );
#define LINEAR_LIGHT_SCALE (cLightScale.x)
#define LIGHT_MAP_SCALE (cLightScale.y)
#define ENV_MAP_SCALE (cLightScale.z)
#define GAMMA_LIGHT_SCALE (cLightScale.w)
// Flashlight constants
#if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)
const float4 cFlashlightColor : register( c28 );
const float4 cFlashlightScreenScale : register( c31 ); // .zw are currently unused
#define flFlashlightNoLambertValue cFlashlightColor.w // This is either 0.0 or 2.0
#endif
#define HDR_INPUT_MAP_SCALE 16.0f
#define TONEMAP_SCALE_NONE 0
#define TONEMAP_SCALE_LINEAR 1
#define TONEMAP_SCALE_GAMMA 2
#define PIXEL_FOG_TYPE_NONE -1 //MATERIAL_FOG_NONE is handled by PIXEL_FOG_TYPE_RANGE, this is for explicitly disabling fog in the shader
#define PIXEL_FOG_TYPE_RANGE 0 //range+none packed together in ps2b. Simply none in ps20 (instruction limits)
#define PIXEL_FOG_TYPE_HEIGHT 1
// If you change these, make the corresponding change in hardwareconfig.cpp
#define NVIDIA_PCF_POISSON 0
#define ATI_NOPCF 1
#define ATI_NO_PCF_FETCH4 2
struct LPREVIEW_PS_OUT
{
float4 color : COLOR0;
float4 normal : COLOR1;
float4 position : COLOR2;
float4 flags : COLOR3;
};
/*
// unused
HALF Luminance( HALF3 color )
{
return dot( color, HALF3( HALF_CONSTANT(0.30f), HALF_CONSTANT(0.59f), HALF_CONSTANT(0.11f) ) );
}
*/
/*
// unused
HALF LuminanceScaled( HALF3 color )
{
return dot( color, HALF3( HALF_CONSTANT(0.30f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.59f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.11f) / MAX_HDR_OVERBRIGHT ) );
}
*/
/*
// unused
HALF AvgColor( HALF3 color )
{
return dot( color, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) );
}
*/
/*
// unused
HALF4 DiffuseBump( sampler lightmapSampler,
float2 lightmapTexCoord1,
float2 lightmapTexCoord2,
float2 lightmapTexCoord3,
HALF3 normal )
{
HALF3 lightmapColor1 = tex2D( lightmapSampler, lightmapTexCoord1 );
HALF3 lightmapColor2 = tex2D( lightmapSampler, lightmapTexCoord2 );
HALF3 lightmapColor3 = tex2D( lightmapSampler, lightmapTexCoord3 );
HALF3 diffuseLighting;
diffuseLighting = saturate( dot( normal, bumpBasis[0] ) ) * lightmapColor1 +
saturate( dot( normal, bumpBasis[1] ) ) * lightmapColor2 +
saturate( dot( normal, bumpBasis[2] ) ) * lightmapColor3;
return HALF4( diffuseLighting, LuminanceScaled( diffuseLighting ) );
}
*/
/*
// unused
HALF Fresnel( HALF3 normal,
HALF3 eye,
HALF2 scaleBias )
{
HALF fresnel = HALF_CONSTANT(1.0f) - dot( normal, eye );
fresnel = pow( fresnel, HALF_CONSTANT(5.0f) );
return fresnel * scaleBias.x + scaleBias.y;
}
*/
/*
// unused
HALF4 GetNormal( sampler normalSampler,
float2 normalTexCoord )
{
HALF4 normal = tex2D( normalSampler, normalTexCoord );
normal.rgb = HALF_CONSTANT(2.0f) * normal.rgb - HALF_CONSTANT(1.0f);
return normal;
}
*/
// Needs to match NormalDecodeMode_t enum in imaterialsystem.h
#define NORM_DECODE_NONE 0
#define NORM_DECODE_ATI2N 1
#define NORM_DECODE_ATI2N_ALPHA 2
float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode, sampler AlphaSampler )
{
float4 normalTexel = tex2D( NormalSampler, tc );
float4 result;
if ( nDecompressionMode == NORM_DECODE_NONE )
{
result = float4(normalTexel.xyz * 2.0f - 1.0f, normalTexel.a );
}
else if ( nDecompressionMode == NORM_DECODE_ATI2N )
{
result.xy = normalTexel.xy * 2.0f - 1.0f;
result.z = sqrt( 1.0f - dot(result.xy, result.xy) );
result.a = 1.0f;
}
else // ATI2N plus ATI1N for alpha
{
result.xy = normalTexel.xy * 2.0f - 1.0f;
result.z = sqrt( 1.0f - dot(result.xy, result.xy) );
result.a = tex2D( AlphaSampler, tc ).x; // Note that this comes in on the X channel
}
return result;
}
float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode )
{
return DecompressNormal( NormalSampler, tc, nDecompressionMode, NormalSampler );
}
HALF3 NormalizeWithCubemap( sampler normalizeSampler, HALF3 input )
{
// return texCUBE( normalizeSampler, input ) * 2.0f - 1.0f;
return texCUBE( normalizeSampler, input );
}
/*
HALF4 EnvReflect( sampler envmapSampler,
sampler normalizeSampler,
HALF3 normal,
float3 eye,
HALF2 fresnelScaleBias )
{
HALF3 normEye = NormalizeWithCubemap( normalizeSampler, eye );
HALF fresnel = Fresnel( normal, normEye, fresnelScaleBias );
HALF3 reflect = CalcReflectionVectorUnnormalized( normal, eye );
return texCUBE( envmapSampler, reflect );
}
*/
float CalcWaterFogAlpha( const float flWaterZ, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ, const float flFogOORange )
{
// float flDepthFromWater = flWaterZ - flWorldPosZ + 2.0f; // hackity hack . .this is for the DF_FUDGE_UP in view_scene.cpp
float flDepthFromWater = flWaterZ - flWorldPosZ;
// if flDepthFromWater < 0, then set it to 0
// This is the equivalent of moving the vert to the water surface if it's above the water surface
// We'll do this with the saturate at the end instead.
// flDepthFromWater = max( 0.0f, flDepthFromWater );
// Calculate the ratio of water fog to regular fog (ie. how much of the distance from the viewer
// to the vert is actually underwater.
float flDepthFromEye = flEyePosZ - flWorldPosZ;
float f = saturate(flDepthFromWater * (1.0/flDepthFromEye));
// $tmp.w is now the distance that we see through water.
return saturate(f * flProjPosZ * flFogOORange);
}
float CalcRangeFog( const float flProjPosZ, const float flFogStartOverRange, const float flFogMaxDensity, const float flFogOORange )
{
#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
return saturate( min( flFogMaxDensity, (flProjPosZ * flFogOORange) - flFogStartOverRange ) );
#else
return 0.0f; //ps20 shaders will never have range fog enabled because too many ran out of slots.
#endif
}
float CalcPixelFogFactor( int iPIXELFOGTYPE, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ )
{
float retVal;
if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE )
{
retVal = 0.0f;
}
if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //range fog, or no fog depending on fog parameters
{
retVal = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w );
}
else if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) //height fog
{
retVal = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w );
}
return retVal;
}
//g_FogParams not defined by default, but this is the same layout for every shader that does define it
#define g_FogEndOverRange g_FogParams.x
#define g_WaterZ g_FogParams.y
#define g_FogMaxDensity g_FogParams.z
#define g_FogOORange g_FogParams.w
float3 BlendPixelFog( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, const int iPIXELFOGTYPE )
{
if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //either range fog or no fog depending on fog parameters and whether this is ps20 or ps2b
{
# if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
pixelFogFactor = saturate( pixelFogFactor );
return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog
# else
return vShaderColor;
# endif
}
else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT )
{
return lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) );
}
else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE )
{
return vShaderColor;
}
}
#if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) && ( CONVERT_TO_SRGB != 0 ) )
sampler1D GammaTableSampler : register( s15 );
float3 SRGBOutput( const float3 vShaderColor )
{
//On ps2b capable hardware we always have the linear->gamma conversion table texture in sampler s15.
float3 result;
result.r = tex1D( GammaTableSampler, vShaderColor.r ).r;
result.g = tex1D( GammaTableSampler, vShaderColor.g ).r;
result.b = tex1D( GammaTableSampler, vShaderColor.b ).r;
return result;
}
#else
float3 SRGBOutput( const float3 vShaderColor )
{
return vShaderColor; //ps 1.1, 1.4, and 2.0 never do srgb conversion in the pixel shader
}
#endif
float SoftParticleDepth( float flDepth )
{
return flDepth * OO_DESTALPHA_DEPTH_RANGE;
}
float DepthToDestAlpha( const float flProjZ )
{
#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
return SoftParticleDepth( flProjZ );
#else
return 1.0f;
#endif
}
float4 FinalOutput( const float4 vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE, const bool bWriteDepthToDestAlpha = false, const float flProjZ = 1.0f )
{
float4 result;
if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )
{
result.rgb = vShaderColor.rgb * LINEAR_LIGHT_SCALE;
}
else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA )
{
result.rgb = vShaderColor.rgb * GAMMA_LIGHT_SCALE;
}
else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_NONE )
{
result.rgb = vShaderColor.rgb;
}
if( bWriteDepthToDestAlpha )
result.a = DepthToDestAlpha( flProjZ );
else
result.a = vShaderColor.a;
result.rgb = BlendPixelFog( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, iPIXELFOGTYPE );
#if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion
#endif
return result;
}
LPREVIEW_PS_OUT FinalOutput( const LPREVIEW_PS_OUT vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE )
{
LPREVIEW_PS_OUT result;
result.color = FinalOutput( vShaderColor.color, pixelFogFactor, iPIXELFOGTYPE, iTONEMAP_SCALE_TYPE );
result.normal.rgb = SRGBOutput( vShaderColor.normal.rgb );
result.normal.a = vShaderColor.normal.a;
result.position.rgb = SRGBOutput( vShaderColor.position.rgb );
result.position.a = vShaderColor.position.a;
result.flags.rgb = SRGBOutput( vShaderColor.flags.rgb );
result.flags.a = vShaderColor.flags.a;
return result;
}
float RemapValClamped( float val, float A, float B, float C, float D)
{
float cVal = (val - A) / (B - A);
cVal = saturate( cVal );
return C + (D - C) * cVal;
}
//===================================================================================//
// This is based on Natasha Tatarchuk's Parallax Occlusion Mapping (ATI)
//===================================================================================//
// INPUT:
// inTexCoord:
// the texcoord for the height/displacement map before parallaxing
//
// vParallax:
// Compute initial parallax displacement direction:
// float2 vParallaxDirection = normalize( vViewTS.xy );
// float fLength = length( vViewTS );
// float fParallaxLength = sqrt( fLength * fLength - vViewTS.z * vViewTS.z ) / vViewTS.z;
// Out.vParallax = vParallaxDirection * fParallaxLength * fProjectedBumpHeight;
//
// vNormal:
// tangent space normal
//
// vViewW:
// float3 vViewW = /*normalize*/(mul( matViewInverse, float4( 0, 0, 0, 1)) - inPosition );
//
// OUTPUT:
// the new texcoord after parallaxing
float2 CalcParallaxedTexCoord( float2 inTexCoord, float2 vParallax, float3 vNormal,
float3 vViewW, sampler HeightMapSampler )
{
const int nMinSamples = 8;
const int nMaxSamples = 50;
// Normalize the incoming view vector to avoid artifacts:
// vView = normalize( vView );
vViewW = normalize( vViewW );
// vLight = normalize( vLight );
// Change the number of samples per ray depending on the viewing angle
// for the surface. Oblique angles require smaller step sizes to achieve
// more accurate precision
int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewW, vNormal ) );
float4 cResultColor = float4( 0, 0, 0, 1 );
//===============================================//
// Parallax occlusion mapping offset computation //
//===============================================//
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 dx = ddx( inTexCoord );
float2 dy = ddy( inTexCoord );
float2 vTexOffsetPerStep = fStepSize * vParallax;
float2 vTexCurrentOffset = inTexCoord;
float fCurrentBound = 1.0;
float x = 0;
float y = 0;
float xh = 0;
float yh = 0;
float2 texOffset2 = 0;
bool bCondition = true;
while ( bCondition == true && nStepIndex < nNumSteps )
{
vTexCurrentOffset -= vTexOffsetPerStep;
fCurrHeight = tex2Dgrad( HeightMapSampler, vTexCurrentOffset, dx, dy ).r;
fCurrentBound -= fStepSize;
if ( fCurrHeight > fCurrentBound )
{
x = fCurrentBound;
y = fCurrentBound + fStepSize;
xh = fCurrHeight;
yh = fPrevHeight;
texOffset2 = vTexCurrentOffset - vTexOffsetPerStep;
bCondition = false;
}
else
{
nStepIndex++;
fPrevHeight = fCurrHeight;
}
} // End of while ( bCondition == true && nStepIndex > -1 )#else
fCurrentBound -= fStepSize;
float fParallaxAmount;
float numerator = (x * (y - yh) - y * (x - xh));
float denomenator = ((y - yh) - (x - xh));
// avoid NaN generation
if( ( numerator == 0.0f ) && ( denomenator == 0.0f ) )
{
fParallaxAmount = 0.0f;
}
else
{
fParallaxAmount = numerator / denomenator;
}
float2 vParallaxOffset = vParallax * (1 - fParallaxAmount );
// Sample the height at the next possible step:
fNextHeight = tex2Dgrad( HeightMapSampler, texOffset2, dx, dy ).r;
// Original offset:
float2 texSampleBase = inTexCoord - vParallaxOffset;
return texSampleBase;
#if 0
cResultColor.rgb = ComputeDiffuseColor( texSampleBase, vLight );
float fBound = 1.0 - fStepSize * nStepIndex;
if ( fNextHeight < fCurrentBound )
// if( 0 )
{
//void DoIteration( in float2 vParallaxJittered, in float3 vLight, inout float4 cResultColor )
//cResultColor.rgb = float3(1,0,0);
DoIteration( vParallax + vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
DoIteration( vParallax - vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
DoIteration( vParallax + float2( -vPixelSize.x, vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
DoIteration( vParallax + float2( vPixelSize.x, -vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
cResultColor.rgb /= 5;
// cResultColor.rgb = float3( 1.0f, 0.0f, 0.0f );
} // End of if ( fNextHeight < fCurrentBound )
#if DOSHADOWS
{
//============================================//
// Soft shadow and self-occlusion computation //
//============================================//
// Compute the blurry shadows (note that this computation takes into
// account self-occlusion for shadow computation):
float sh0 = tex2D( sNormalMap, texSampleBase).w;
float shA = (tex2D( sNormalMap, texSampleBase + inXY * 0.88 ).w - sh0 - 0.88 ) * 1 * fShadowSoftening;
float sh9 = (tex2D( sNormalMap, texSampleBase + inXY * 0.77 ).w - sh0 - 0.77 ) * 2 * fShadowSoftening;
float sh8 = (tex2D( sNormalMap, texSampleBase + inXY * 0.66 ).w - sh0 - 0.66 ) * 4 * fShadowSoftening;
float sh7 = (tex2D( sNormalMap, texSampleBase + inXY * 0.55 ).w - sh0 - 0.55 ) * 6 * fShadowSoftening;
float sh6 = (tex2D( sNormalMap, texSampleBase + inXY * 0.44 ).w - sh0 - 0.44 ) * 8 * fShadowSoftening;
float sh5 = (tex2D( sNormalMap, texSampleBase + inXY * 0.33 ).w - sh0 - 0.33 ) * 10 * fShadowSoftening;
float sh4 = (tex2D( sNormalMap, texSampleBase + inXY * 0.22 ).w - sh0 - 0.22 ) * 12 * fShadowSoftening;
// Compute the actual shadow strength:
float fShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 );
cResultColor.rgb *= fShadow * 0.6 + 0.4;
}
#endif
return cResultColor;
#endif
}
//======================================//
// HSL Color space conversion routines //
//======================================//
#define HUE 0
#define SATURATION 1
#define LIGHTNESS 2
// Convert from RGB to HSL color space
float4 RGBtoHSL( float4 inColor )
{
float h, s;
float flMax = max( inColor.r, max( inColor.g, inColor.b ) );
float flMin = min( inColor.r, min( inColor.g, inColor.b ) );
float l = (flMax + flMin) / 2.0f;
if (flMax == flMin) // achromatic case
{
s = h = 0;
}
else // chromatic case
{
// Next, calculate the hue
float delta = flMax - flMin;
// First, calculate the saturation
if (l < 0.5f) // If we're in the lower hexcone
{
s = delta/(flMax + flMin);
}
else
{
s = delta/(2 - flMax - flMin);
}
if ( inColor.r == flMax )
{
h = (inColor.g - inColor.b)/delta; // color between yellow and magenta
}
else if ( inColor.g == flMax )
{
h = 2 + (inColor.b - inColor.r)/delta; // color between cyan and yellow
}
else // blue must be max
{
h = 4 + (inColor.r - inColor.g)/delta; // color between magenta and cyan
}
h *= 60.0f;
if (h < 0.0f)
{
h += 360.0f;
}
h /= 360.0f;
}
return float4 (h, s, l, 1.0f);
}
float HueToRGB( float v1, float v2, float vH )
{
float fResult = v1;
vH = fmod (vH + 1.0f, 1.0f);
if ( ( 6.0f * vH ) < 1.0f )
{
fResult = ( v1 + ( v2 - v1 ) * 6.0f * vH );
}
else if ( ( 2.0f * vH ) < 1.0f )
{
fResult = ( v2 );
}
else if ( ( 3.0f * vH ) < 2.0f )
{
fResult = ( v1 + ( v2 - v1 ) * ( ( 2.0f / 3.0f ) - vH ) * 6.0f );
}
return fResult;
}
// Convert from HSL to RGB color space
float4 HSLtoRGB( float4 hsl )
{
float r, g, b;
float h = hsl[HUE];
float s = hsl[SATURATION];
float l = hsl[LIGHTNESS];
if ( s == 0 )
{
r = g = b = l;
}
else
{
float v1, v2;
if ( l < 0.5f )
v2 = l * ( 1.0f + s );
else
v2 = ( l + s ) - ( s * l );
v1 = 2 * l - v2;
r = HueToRGB( v1, v2, h + ( 1.0f / 3.0f ) );
g = HueToRGB( v1, v2, h );
b = HueToRGB( v1, v2, h - ( 1.0f / 3.0f ) );
}
return float4( r, g, b, 1.0f );
}
// texture combining modes for combining base and detail/basetexture2
#define TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2 0 // original mode
#define TCOMBINE_RGB_ADDITIVE 1 // base.rgb+detail.rgb*fblend
#define TCOMBINE_DETAIL_OVER_BASE 2
#define TCOMBINE_FADE 3 // straight fade between base and detail.
#define TCOMBINE_BASE_OVER_DETAIL 4 // use base alpha for blend over detail
#define TCOMBINE_RGB_ADDITIVE_SELFILLUM 5 // add detail color post lighting
#define TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE 6
#define TCOMBINE_MOD2X_SELECT_TWO_PATTERNS 7 // use alpha channel of base to select between mod2x channels in r+a of detail
#define TCOMBINE_MULTIPLY 8
#define TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA 9 // use alpha channel of detail to mask base
#define TCOMBINE_SSBUMP_BUMP 10 // use detail to modulate lighting as an ssbump
#define TCOMBINE_SSBUMP_NOBUMP 11 // detail is an ssbump but use it as an albedo. shader does the magic here - no user needs to specify mode 11
float4 TextureCombine( float4 baseColor, float4 detailColor, int combine_mode,
float fBlendFactor )
{
if ( combine_mode == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS)
{
float3 dc=lerp(detailColor.r,detailColor.a, baseColor.a);
baseColor.rgb*=lerp(float3(1,1,1),2.0*dc,fBlendFactor);
}
if ( combine_mode == TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2)
baseColor.rgb*=lerp(float3(1,1,1),2.0*detailColor.rgb,fBlendFactor);
if ( combine_mode == TCOMBINE_RGB_ADDITIVE )
baseColor.rgb += fBlendFactor * detailColor.rgb;
if ( combine_mode == TCOMBINE_DETAIL_OVER_BASE )
{
float fblend=fBlendFactor * detailColor.a;
baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend);
}
if ( combine_mode == TCOMBINE_FADE )
{
baseColor = lerp( baseColor, detailColor, fBlendFactor);
}
if ( combine_mode == TCOMBINE_BASE_OVER_DETAIL )
{
float fblend=fBlendFactor * (1-baseColor.a);
baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend );
baseColor.a = detailColor.a;
}
if ( combine_mode == TCOMBINE_MULTIPLY )
{
baseColor = lerp( baseColor, baseColor*detailColor, fBlendFactor);
}
if (combine_mode == TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA )
{
baseColor.a = lerp( baseColor.a, baseColor.a*detailColor.a, fBlendFactor );
}
if ( combine_mode == TCOMBINE_SSBUMP_NOBUMP )
{
baseColor.rgb = baseColor.rgb * dot( detailColor.rgb, 2.0/3.0 );
}
return baseColor;
}
float3 lerp5(float3 f1, float3 f2, float i1, float i2, float x)
{
return f1+(f2-f1)*(x-i1)/(i2-i1);
}
float3 TextureCombinePostLighting( float3 lit_baseColor, float4 detailColor, int combine_mode,
float fBlendFactor )
{
if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM )
lit_baseColor += fBlendFactor * detailColor.rgb;
if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE )
{
// fade in an unusual way - instead of fading out color, remap an increasing band of it from
// 0..1
//if (fBlendFactor > 0.5)
// lit_baseColor += min(1, (1.0/fBlendFactor)*max(0, detailColor.rgb-(1-fBlendFactor) ) );
//else
// lit_baseColor += 2*fBlendFactor*2*max(0, detailColor.rgb-.5);
float f = fBlendFactor - 0.5;
float fMult = (f >= 0) ? 1.0/fBlendFactor : 4*fBlendFactor;
float fAdd = (f >= 0) ? 1.0-fMult : -0.5*fMult;
lit_baseColor += saturate(fMult * detailColor.rgb + fAdd);
}
return lit_baseColor;
}
//NOTE: On X360. fProjZ is expected to be pre-reversed for cheaper math here in the pixel shader
float DepthFeathering( sampler DepthSampler, const float2 vScreenPos, float fProjZ, float fProjW, float4 vDepthBlendConstants )
{
# if ( !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) ) //minimum requirement of ps2b
{
float flFeatheredAlpha;
float2 flDepths;
#define flSceneDepth flDepths.x
#define flSpriteDepth flDepths.y
# if ( defined( _X360 ) )
{
//Get depth from the depth texture. Need to sample with the offset of (0.5, 0.5) to fix rounding errors
asm {
tfetch2D flDepths.x___, vScreenPos, DepthSampler, OffsetX=0.5, OffsetY=0.5, MinFilter=point, MagFilter=point, MipFilter=point
};
# if( !defined( REVERSE_DEPTH_ON_X360 ) )
flSceneDepth = 1.0f - flSceneDepth;
# endif
//get the sprite depth into the same range as the texture depth
flSpriteDepth = fProjZ / fProjW;
//unproject to get at the pre-projection z. This value is much more linear than depth
flDepths = vDepthBlendConstants.z / flDepths;
flDepths = vDepthBlendConstants.y - flDepths;
flFeatheredAlpha = flSceneDepth - flSpriteDepth;
flFeatheredAlpha *= vDepthBlendConstants.x;
flFeatheredAlpha = saturate( flFeatheredAlpha );
}
# else
{
flSceneDepth = tex2D( DepthSampler, vScreenPos ).a; // PC uses dest alpha of the frame buffer
flSpriteDepth = SoftParticleDepth( fProjZ );
flFeatheredAlpha = abs(flSceneDepth - flSpriteDepth) * vDepthBlendConstants.x;
flFeatheredAlpha = max( smoothstep( 0.75f, 1.0f, flSceneDepth ), flFeatheredAlpha ); //as the sprite approaches the edge of our compressed depth space, the math stops working. So as the sprite approaches the far depth, smoothly remove feathering.
flFeatheredAlpha = saturate( flFeatheredAlpha );
}
# endif
#undef flSceneDepth
#undef flSpriteDepth
return flFeatheredAlpha;
}
# else
{
return 1.0f;
}
# endif
}
#endif //#ifndef COMMON_PS_FXC_H_

View File

@ -0,0 +1,423 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef COMMON_VERTEXLITGENERIC_DX9_H_
#define COMMON_VERTEXLITGENERIC_DX9_H_
#include "common_ps_fxc.h"
// We store four light colors and positions in an
// array of three of these structures like so:
//
// x y z w
// +------+------+------+------+
// | L0.rgb | |
// +------+------+------+ |
// | L0.pos | L3 |
// +------+------+------+ rgb |
// | L1.rgb | |
// +------+------+------+------+
// | L1.pos | |
// +------+------+------+ |
// | L2.rgb | L3 |
// +------+------+------+ pos |
// | L2.pos | |
// +------+------+------+------+
//
struct PixelShaderLightInfo
{
float4 color;
float4 pos;
};
#define cOverbright 2.0f
#define cOOOverbright 0.5f
#define LIGHTTYPE_NONE 0
#define LIGHTTYPE_SPOT 1
#define LIGHTTYPE_POINT 2
#define LIGHTTYPE_DIRECTIONAL 3
// Better suited to Pixel shader models, 11 instructions in pixel shader
// ... actually, now only 9: mul, cmp, cmp, mul, mad, mad, mad, mad, mad
float3 PixelShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )
{
float3 linearColor, nSquared = worldNormal * worldNormal;
float3 isNegative = ( worldNormal >= 0.0 ) ? 0 : nSquared;
float3 isPositive = ( worldNormal >= 0.0 ) ? nSquared : 0;
linearColor = isPositive.x * cAmbientCube[0] + isNegative.x * cAmbientCube[1] +
isPositive.y * cAmbientCube[2] + isNegative.y * cAmbientCube[3] +
isPositive.z * cAmbientCube[4] + isNegative.z * cAmbientCube[5];
return linearColor;
}
// Better suited to Vertex shader models
// Six VS instructions due to use of constant indexing (slt, mova, mul, mul, mad, mad)
float3 VertexShaderAmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )
{
float3 nSquared = worldNormal * worldNormal;
int3 isNegative = ( worldNormal < 0.0 );
float3 linearColor;
linearColor = nSquared.x * cAmbientCube[isNegative.x] +
nSquared.y * cAmbientCube[isNegative.y+2] +
nSquared.z * cAmbientCube[isNegative.z+4];
return linearColor;
}
float3 AmbientLight( const float3 worldNormal, const float3 cAmbientCube[6] )
{
// Vertex shader cases
#ifdef SHADER_MODEL_VS_1_0
return VertexShaderAmbientLight( worldNormal, cAmbientCube );
#elif SHADER_MODEL_VS_1_1
return VertexShaderAmbientLight( worldNormal, cAmbientCube );
#elif SHADER_MODEL_VS_2_0
return VertexShaderAmbientLight( worldNormal, cAmbientCube );
#elif SHADER_MODEL_VS_3_0
return VertexShaderAmbientLight( worldNormal, cAmbientCube );
#else
// Pixel shader case
return PixelShaderAmbientLight( worldNormal, cAmbientCube );
#endif
}
//-----------------------------------------------------------------------------
// Purpose: Compute scalar diffuse term with various optional tweaks such as
// Half Lambert and ambient occlusion
//-----------------------------------------------------------------------------
float3 DiffuseTerm(const bool bHalfLambert, const float3 worldNormal, const float3 lightDir,
const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
const bool bDoLightingWarp, in sampler lightWarpSampler )
{
float fResult;
float NDotL = dot( worldNormal, lightDir ); // Unsaturated dot (-1 to 1 range)
if ( bHalfLambert )
{
fResult = saturate(NDotL * 0.5 + 0.5); // Scale and bias to 0 to 1 range
if ( !bDoLightingWarp )
{
fResult *= fResult; // Square
}
}
else
{
fResult = saturate( NDotL ); // Saturate pure Lambertian term
}
if ( bDoAmbientOcclusion )
{
// Raise to higher powers for darker AO values
// float fAOPower = lerp( 4.0f, 1.0f, fAmbientOcclusion );
// result *= pow( NDotL * 0.5 + 0.5, fAOPower );
fResult *= fAmbientOcclusion;
}
float3 fOut = float3( fResult, fResult, fResult );
if ( bDoLightingWarp )
{
fOut = 2.0f * tex1D( lightWarpSampler, fResult );
}
return fOut;
}
float3 PixelShaderDoGeneralDiffuseLight( const float fAtten, const float3 worldPos, const float3 worldNormal,
in sampler NormalizeSampler,
const float3 vPosition, const float3 vColor, const bool bHalfLambert,
const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
const bool bDoLightingWarp, in sampler lightWarpSampler )
{
#if (defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0))
float3 lightDir = normalize( vPosition - worldPos );
#else
float3 lightDir = NormalizeWithCubemap( NormalizeSampler, vPosition - worldPos );
#endif
return vColor * fAtten * DiffuseTerm( bHalfLambert, worldNormal, lightDir, bDoAmbientOcclusion, fAmbientOcclusion, bDoLightingWarp, lightWarpSampler );
}
float3 PixelShaderGetLightVector( const float3 worldPos, PixelShaderLightInfo cLightInfo[3], int nLightIndex )
{
if ( nLightIndex == 3 )
{
// Unpack light 3 from w components...
float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w );
return normalize( vLight3Pos - worldPos );
}
else
{
return normalize( cLightInfo[nLightIndex].pos - worldPos );
}
}
float3 PixelShaderGetLightColor( PixelShaderLightInfo cLightInfo[3], int nLightIndex )
{
if ( nLightIndex == 3 )
{
// Unpack light 3 from w components...
return float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w );
}
else
{
return cLightInfo[nLightIndex].color.rgb;
}
}
void SpecularAndRimTerms( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent,
const float3 vEyeDir, const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
const bool bDoSpecularWarp, in sampler specularWarpSampler, const float fFresnel,
const float3 color, const bool bDoRimLighting, const float fRimExponent,
// Outputs
out float3 specularLighting, out float3 rimLighting )
{
rimLighting = float3(0.0f, 0.0f, 0.0f);
//float3 vReflect = reflect( -vEyeDir, vWorldNormal ); // Reflect view through normal
float3 vReflect = 2 * vWorldNormal * dot( vWorldNormal , vEyeDir ) - vEyeDir; // Reflect view through normal
float LdotR = saturate(dot( vReflect, vLightDir )); // L.R (use half-angle instead?)
specularLighting = pow( LdotR, fSpecularExponent ); // Raise to specular exponent
// Optionally warp as function of scalar specular and fresnel
if ( bDoSpecularWarp )
specularLighting *= tex2D( specularWarpSampler, float2(specularLighting.x, fFresnel) ); // Sample at { (L.R)^k, fresnel }
specularLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L
specularLighting *= color; // Modulate with light color
if ( bDoAmbientOcclusion ) // Optionally modulate with ambient occlusion
specularLighting *= fAmbientOcclusion;
if ( bDoRimLighting ) // Optionally do rim lighting
{
rimLighting = pow( LdotR, fRimExponent ); // Raise to rim exponent
rimLighting *= saturate(dot( vWorldNormal, vLightDir )); // Mask with N.L
rimLighting *= color; // Modulate with light color
}
}
// Traditional fresnel term approximation
float Fresnel( const float3 vNormal, const float3 vEyeDir )
{
float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term
return fresnel * fresnel; // Square for a more subtle look
}
// Traditional fresnel term approximation which uses 4th power (square twice)
float Fresnel4( const float3 vNormal, const float3 vEyeDir )
{
float fresnel = saturate( 1 - dot( vNormal, vEyeDir ) ); // 1-(N.V) for Fresnel term
fresnel = fresnel * fresnel; // Square
return fresnel * fresnel; // Square again for a more subtle look
}
//
// Custom Fresnel with low, mid and high parameters defining a piecewise continuous function
// with traditional fresnel (0 to 1 range) as input. The 0 to 0.5 range blends between
// low and mid while the 0.5 to 1 range blends between mid and high
//
// |
// | . M . . . H
// | .
// L
// |
// +----------------
// 0 1
//
float Fresnel( const float3 vNormal, const float3 vEyeDir, float3 vRanges )
{
//float result, f = Fresnel( vNormal, vEyeDir ); // Traditional Fresnel
//if ( f > 0.5f )
// result = lerp( vRanges.y, vRanges.z, (2*f)-1 ); // Blend between mid and high values
//else
// result = lerp( vRanges.x, vRanges.y, 2*f ); // Blend between low and mid values
// note: vRanges is now encoded as ((mid-min)*2, mid, (max-mid)*2) to optimize math
float f = saturate( 1 - dot( vNormal, vEyeDir ) );
f = f*f - 0.5;
return vRanges.y + (f >= 0.0 ? vRanges.z : vRanges.x) * f;
}
void PixelShaderDoSpecularLight( const float3 vWorldPos, const float3 vWorldNormal, const float fSpecularExponent, const float3 vEyeDir,
const float fAtten, const float3 vLightColor, const float3 vLightDir,
const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel,
const bool bDoRimLighting, const float fRimExponent,
// Outputs
out float3 specularLighting, out float3 rimLighting )
{
// Compute Specular and rim terms
SpecularAndRimTerms( vWorldNormal, vLightDir, fSpecularExponent,
vEyeDir, bDoAmbientOcclusion, fAmbientOcclusion,
bDoSpecularWarp, specularWarpSampler, fFresnel, vLightColor * fAtten,
bDoRimLighting, fRimExponent, specularLighting, rimLighting );
}
float3 PixelShaderDoLightingLinear( const float3 worldPos, const float3 worldNormal,
const float3 staticLightingColor, const bool bStaticLight,
const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6],
in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3],
const bool bHalfLambert, const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
const bool bDoLightingWarp, in sampler lightWarpSampler )
{
float3 linearColor = 0.0f;
if ( bStaticLight )
{
// The static lighting comes in in gamma space and has also been premultiplied by $cOOOverbright
// need to get it into
// linear space so that we can do adds.
linearColor += GammaToLinear( staticLightingColor * cOverbright );
}
if ( bAmbientLight )
{
float3 ambient = AmbientLight( worldNormal, cAmbientCube );
if ( bDoAmbientOcclusion )
ambient *= fAmbientOcclusion * fAmbientOcclusion; // Note squaring...
linearColor += ambient;
}
if ( nNumLights > 0 )
{
linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.x, worldPos, worldNormal, NormalizeSampler,
cLightInfo[0].pos, cLightInfo[0].color, bHalfLambert,
bDoAmbientOcclusion, fAmbientOcclusion,
bDoLightingWarp, lightWarpSampler );
if ( nNumLights > 1 )
{
linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.y, worldPos, worldNormal, NormalizeSampler,
cLightInfo[1].pos, cLightInfo[1].color, bHalfLambert,
bDoAmbientOcclusion, fAmbientOcclusion,
bDoLightingWarp, lightWarpSampler );
if ( nNumLights > 2 )
{
linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.z, worldPos, worldNormal, NormalizeSampler,
cLightInfo[2].pos, cLightInfo[2].color, bHalfLambert,
bDoAmbientOcclusion, fAmbientOcclusion,
bDoLightingWarp, lightWarpSampler );
if ( nNumLights > 3 )
{
// Unpack the 4th light's data from tight constant packing
float3 vLight3Color = float3( cLightInfo[0].color.w, cLightInfo[0].pos.w, cLightInfo[1].color.w );
float3 vLight3Pos = float3( cLightInfo[1].pos.w, cLightInfo[2].color.w, cLightInfo[2].pos.w );
linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.w, worldPos, worldNormal, NormalizeSampler,
vLight3Pos, vLight3Color, bHalfLambert,
bDoAmbientOcclusion, fAmbientOcclusion,
bDoLightingWarp, lightWarpSampler );
}
}
}
}
return linearColor;
}
void PixelShaderDoSpecularLighting( const float3 worldPos, const float3 worldNormal, const float fSpecularExponent, const float3 vEyeDir,
const float4 lightAtten, const int nNumLights, PixelShaderLightInfo cLightInfo[3],
const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel,
const bool bDoRimLighting, const float fRimExponent,
// Outputs
out float3 specularLighting, out float3 rimLighting )
{
specularLighting = rimLighting = float3( 0.0f, 0.0f, 0.0f );
float3 localSpecularTerm, localRimTerm;
if( nNumLights > 0 )
{
PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,
lightAtten.x, PixelShaderGetLightColor( cLightInfo, 0 ),
PixelShaderGetLightVector( worldPos, cLightInfo, 0 ),
bDoAmbientOcclusion, fAmbientOcclusion,
bDoSpecularWarp, specularWarpSampler, fFresnel,
bDoRimLighting, fRimExponent,
localSpecularTerm, localRimTerm );
specularLighting += localSpecularTerm; // Accumulate specular and rim terms
rimLighting += localRimTerm;
}
if( nNumLights > 1 )
{
PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,
lightAtten.y, PixelShaderGetLightColor( cLightInfo, 1 ),
PixelShaderGetLightVector( worldPos, cLightInfo, 1 ),
bDoAmbientOcclusion, fAmbientOcclusion,
bDoSpecularWarp, specularWarpSampler, fFresnel,
bDoRimLighting, fRimExponent,
localSpecularTerm, localRimTerm );
specularLighting += localSpecularTerm; // Accumulate specular and rim terms
rimLighting += localRimTerm;
}
if( nNumLights > 2 )
{
PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,
lightAtten.z, PixelShaderGetLightColor( cLightInfo, 2 ),
PixelShaderGetLightVector( worldPos, cLightInfo, 2 ),
bDoAmbientOcclusion, fAmbientOcclusion,
bDoSpecularWarp, specularWarpSampler, fFresnel,
bDoRimLighting, fRimExponent,
localSpecularTerm, localRimTerm );
specularLighting += localSpecularTerm; // Accumulate specular and rim terms
rimLighting += localRimTerm;
}
if( nNumLights > 3 )
{
PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,
lightAtten.w, PixelShaderGetLightColor( cLightInfo, 3 ),
PixelShaderGetLightVector( worldPos, cLightInfo, 3 ),
bDoAmbientOcclusion, fAmbientOcclusion,
bDoSpecularWarp, specularWarpSampler, fFresnel,
bDoRimLighting, fRimExponent,
localSpecularTerm, localRimTerm );
specularLighting += localSpecularTerm; // Accumulate specular and rim terms
rimLighting += localRimTerm;
}
}
float3 PixelShaderDoRimLighting( const float3 worldNormal, const float3 vEyeDir, const float3 cAmbientCube[6], float fFresnel )
{
float3 vReflect = reflect( -vEyeDir, worldNormal ); // Reflect view through normal
return fFresnel * PixelShaderAmbientLight( vEyeDir, cAmbientCube );
}
// Called directly by newer shaders or through the following wrapper for older shaders
float3 PixelShaderDoLighting( const float3 worldPos, const float3 worldNormal,
const float3 staticLightingColor, const bool bStaticLight,
const bool bAmbientLight, const float4 lightAtten, const float3 cAmbientCube[6],
in sampler NormalizeSampler, const int nNumLights, PixelShaderLightInfo cLightInfo[3],
const bool bHalfLambert,
// New optional/experimental parameters
const bool bDoAmbientOcclusion, const float fAmbientOcclusion,
const bool bDoLightingWarp, in sampler lightWarpSampler )
{
float3 linearColor = PixelShaderDoLightingLinear( worldPos, worldNormal, staticLightingColor,
bStaticLight, bAmbientLight, lightAtten,
cAmbientCube, NormalizeSampler, nNumLights, cLightInfo, bHalfLambert,
bDoAmbientOcclusion, fAmbientOcclusion,
bDoLightingWarp, lightWarpSampler );
// go ahead and clamp to the linear space equivalent of overbright 2 so that we match
// everything else.
// linearColor = HuePreservingColorClamp( linearColor, pow( 2.0f, 2.2 ) );
return linearColor;
}
#endif //#ifndef COMMON_VERTEXLITGENERIC_DX9_H_

View File

@ -0,0 +1,955 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: This is where all common code for vertex shaders go.
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef COMMON_VS_FXC_H_
#define COMMON_VS_FXC_H_
#include "common_fxc.h"
// Put global skip commands here. . make sure and check that the appropriate vars are defined
// so these aren't used on the wrong shaders!
// --------------------------------------------------------------------------------
// Ditch all fastpath attemps if we are doing LIGHTING_PREVIEW.
// SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH
// --------------------------------------------------------------------------------
#ifndef COMPRESSED_VERTS
// Default to no vertex compression
#define COMPRESSED_VERTS 0
#endif
#if ( !defined( SHADER_MODEL_VS_2_0 ) && !defined( SHADER_MODEL_VS_3_0 ) )
#if COMPRESSED_VERTS == 1
#error "Vertex compression is only for DX9 and up!"
#endif
#endif
// We're testing 2 normal compression methods
// One compressed normals+tangents into a SHORT2 each (8 bytes total)
// The other compresses them together, into a single UBYTE4 (4 bytes total)
// FIXME: pick one or the other, compare lighting quality in important cases
#define COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 0
#define COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 1
//#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2
#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4
#define FOGTYPE_RANGE 0
#define FOGTYPE_HEIGHT 1
#define COMPILE_ERROR ( 1/0; )
// -------------------------
// CONSTANTS
// -------------------------
#pragma def ( vs, c0, 0.0f, 1.0f, 2.0f, 0.5f )
const float4 cConstants1 : register(c1);
#define cOOGamma cConstants1.x
#define cOverbright 2.0f
#define cOneThird cConstants1.z
#define cOOOverbright ( 1.0f / 2.0f )
// The g_bLightEnabled registers and g_nLightCountRegister hold the same information regarding
// enabling lights, but callers internal to this file tend to use the loops, while external
// callers will end up using the booleans
const bool g_bLightEnabled[4] : register(b0);
// through b3
const int g_nLightCountRegister : register(i0);
#define g_nLightCount g_nLightCountRegister.x
const float4 cEyePosWaterZ : register(c2);
#define cEyePos cEyePosWaterZ.xyz
// Only cFlexScale.x is used
// It is a binary value used to switch on/off the addition of the flex delta stream
const float4 cFlexScale : register( c3 );
const float4x4 cModelViewProj : register(c4);
const float4x4 cViewProj : register(c8);
// Used to compute projPosZ in shaders without skinning
// Using cModelViewProj with FastClip generates incorrect results
// This is just row two of the non-FastClip cModelViewProj matrix
const float4 cModelViewProjZ : register(c12);
// More constants working back from the top...
const float4 cViewProjZ : register(c13);
const float4 cFogParams : register(c16);
#define cFogEndOverFogRange cFogParams.x
#define cFogOne cFogParams.y
#define cFogMaxDensity cFogParams.z
#define cOOFogRange cFogParams.w
const float4x4 cViewModel : register(c17);
const float3 cAmbientCubeX [ 2 ] : register ( c21 ) ;
const float3 cAmbientCubeY [ 2 ] : register ( c23 ) ;
const float3 cAmbientCubeZ [ 2 ] : register ( c25 ) ;
#if defined ( SHADER_MODEL_VS_3_0 )
const float4 cFlexWeights [ 512 ] : register ( c1024 ) ;
#endif
struct LightInfo
{
float4 color; // {xyz} is color w is light type code (see comment below)
float4 dir; // {xyz} is dir w is light type code
float4 pos;
float4 spotParams;
float4 atten;
};
// w components of color and dir indicate light type:
// 1x - directional
// 01 - spot
// 00 - point
// Four lights x 5 constants each = 20 constants
LightInfo cLightInfo[4] : register(c27);
#define LIGHT_0_POSITION_REG c29
#ifdef SHADER_MODEL_VS_1_1
const float4 cModulationColor : register(c37);
#define SHADER_SPECIFIC_CONST_0 c38
#define SHADER_SPECIFIC_CONST_1 c39
#define SHADER_SPECIFIC_CONST_2 c40
#define SHADER_SPECIFIC_CONST_3 c41
#define SHADER_SPECIFIC_CONST_4 c42
#define SHADER_SPECIFIC_CONST_5 c43
#define SHADER_SPECIFIC_CONST_6 c44
#define SHADER_SPECIFIC_CONST_7 c45
#define SHADER_SPECIFIC_CONST_8 c46
#define SHADER_SPECIFIC_CONST_9 c47
#define SHADER_SPECIFIC_CONST_10 c14
#define SHADER_SPECIFIC_CONST_11 c15
static const int cModel0Index = 48;
const float4x3 cModel[16] : register(c48);
// last cmodel is c105 for dx80, c214 for dx90
#else // DX9 shaders (vs20 and beyond)
const float4 cModulationColor : register( c47 );
#define SHADER_SPECIFIC_CONST_0 c48
#define SHADER_SPECIFIC_CONST_1 c49
#define SHADER_SPECIFIC_CONST_2 c50
#define SHADER_SPECIFIC_CONST_3 c51
#define SHADER_SPECIFIC_CONST_4 c52
#define SHADER_SPECIFIC_CONST_5 c53
#define SHADER_SPECIFIC_CONST_6 c54
#define SHADER_SPECIFIC_CONST_7 c55
#define SHADER_SPECIFIC_CONST_8 c56
#define SHADER_SPECIFIC_CONST_9 c57
#define SHADER_SPECIFIC_CONST_10 c14
#define SHADER_SPECIFIC_CONST_11 c15
static const int cModel0Index = 58;
const float4x3 cModel[53] : register( c58 );
// last cmodel is c105 for dx80, c216 for dx90
#define SHADER_SPECIFIC_BOOL_CONST_0 b4
#define SHADER_SPECIFIC_BOOL_CONST_1 b5
#define SHADER_SPECIFIC_BOOL_CONST_2 b6
#define SHADER_SPECIFIC_BOOL_CONST_3 b7
#define SHADER_SPECIFIC_BOOL_CONST_4 b8
#define SHADER_SPECIFIC_BOOL_CONST_5 b9
#define SHADER_SPECIFIC_BOOL_CONST_6 b10
#define SHADER_SPECIFIC_BOOL_CONST_7 b11
#endif // vertex shader model constant packing changes
//=======================================================================================
// Methods to decompress vertex normals
//=======================================================================================
//-----------------------------------------------------------------------------------
// Decompress a normal from two-component compressed format
// We expect this data to come from a signed SHORT2 stream in the range of -32768..32767
//
// -32678 and 0 are invalid encodings
// w contains the sign to use in the cross product when generating a binormal
void _DecompressShort2Tangent( float2 inputTangent, out float4 outputTangent )
{
float2 ztSigns = sign( inputTangent ); // sign bits for z and tangent (+1 or -1)
float2 xyAbs = abs( inputTangent ); // 1..32767
outputTangent.xy = (xyAbs - 16384.0f) / 16384.0f; // x and y
outputTangent.z = ztSigns.x * sqrt( saturate( 1.0f - dot( outputTangent.xy, outputTangent.xy ) ) );
outputTangent.w = ztSigns.y;
}
//-----------------------------------------------------------------------------------
// Same code as _DecompressShort2Tangent, just one returns a float4, one a float3
void _DecompressShort2Normal( float2 inputNormal, out float3 outputNormal )
{
float4 result;
_DecompressShort2Tangent( inputNormal, result );
outputNormal = result.xyz;
}
//-----------------------------------------------------------------------------------
// Decompress normal+tangent together
void _DecompressShort2NormalTangent( float2 inputNormal, float2 inputTangent, out float3 outputNormal, out float4 outputTangent )
{
// FIXME: if we end up sticking with the SHORT2 format, pack the normal and tangent into a single SHORT4 element
// (that would make unpacking normal+tangent here together much cheaper than the sum of their parts)
_DecompressShort2Normal( inputNormal, outputNormal );
_DecompressShort2Tangent( inputTangent, outputTangent );
}
//=======================================================================================
// Decompress a normal and tangent from four-component compressed format
// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255
// The final vTangent.w contains the sign to use in the cross product when generating a binormal
void _DecompressUByte4NormalTangent( float4 inputNormal,
out float3 outputNormal, // {nX, nY, nZ}
out float4 outputTangent ) // {tX, tY, tZ, sign of binormal}
{
float fOne = 1.0f;
float4 ztztSignBits = ( inputNormal - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction
float4 xyxyAbs = abs( inputNormal - 128.0f ) - ztztSignBits; // 0..127
float4 xyxySignBits = ( xyxyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0)
float4 normTan = (abs( xyxyAbs - 64.0f ) - xyxySignBits) / 63.0f; // abs({nX, nY, tX, tY})
outputNormal.xy = normTan.xy; // abs({nX, nY, __, __})
outputTangent.xy = normTan.zw; // abs({tX, tY, __, __})
float4 xyxySigns = 1 - 2*xyxySignBits; // Convert sign bits to signs
float4 ztztSigns = 1 - 2*ztztSignBits; // ( [1,0] -> [-1,+1] )
outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1
outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere
outputNormal.xy *= xyxySigns.xy; // Restore x and y signs
outputNormal.z *= ztztSigns.x; // Restore z sign
outputTangent.z = 1.0f - outputTangent.x - outputTangent.y; // Project onto x+y+z=1
outputTangent.xyz = normalize( outputTangent.xyz ); // Normalize onto unit sphere
outputTangent.xy *= xyxySigns.zw; // Restore x and y signs
outputTangent.z *= ztztSigns.z; // Restore z sign
outputTangent.w = ztztSigns.w; // Binormal sign
}
//-----------------------------------------------------------------------------------
// Decompress just a normal from four-component compressed format (same as above)
// We expect this data to come from an unsigned UBYTE4 stream in the range of 0..255
// [ When compiled, this works out to approximately 17 asm instructions ]
void _DecompressUByte4Normal( float4 inputNormal,
out float3 outputNormal) // {nX, nY, nZ}
{
float fOne = 1.0f;
float2 ztSigns = ( inputNormal.xy - 128.0f ) < 0; // sign bits for zs and binormal (1 or 0) set-less-than (slt) asm instruction
float2 xyAbs = abs( inputNormal.xy - 128.0f ) - ztSigns; // 0..127
float2 xySigns = ( xyAbs - 64.0f ) < 0; // sign bits for xs and ys (1 or 0)
outputNormal.xy = ( abs( xyAbs - 64.0f ) - xySigns ) / 63.0f; // abs({nX, nY})
outputNormal.z = 1.0f - outputNormal.x - outputNormal.y; // Project onto x+y+z=1
outputNormal.xyz = normalize( outputNormal.xyz ); // Normalize onto unit sphere
outputNormal.xy *= lerp( fOne.xx, -fOne.xx, xySigns ); // Restore x and y signs
outputNormal.z *= lerp( fOne.x, -fOne.x, ztSigns.x ); // Restore z sign
}
void DecompressVertex_Normal( float4 inputNormal, out float3 outputNormal )
{
if ( COMPRESSED_VERTS == 1 )
{
if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 )
{
_DecompressShort2Normal( inputNormal.xy, outputNormal );
}
else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 )
{
_DecompressUByte4Normal( inputNormal, outputNormal );
}
}
else
{
outputNormal = inputNormal.xyz;
}
}
void DecompressVertex_NormalTangent( float4 inputNormal, float4 inputTangent, out float3 outputNormal, out float4 outputTangent )
{
if ( COMPRESSED_VERTS == 1 )
{
if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 )
{
_DecompressShort2NormalTangent( inputNormal.xy, inputTangent.xy, outputNormal, outputTangent );
}
else // ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 )
{
_DecompressUByte4NormalTangent( inputNormal, outputNormal, outputTangent );
}
}
else
{
outputNormal = inputNormal.xyz;
outputTangent = inputTangent;
}
}
#ifdef SHADER_MODEL_VS_3_0
//-----------------------------------------------------------------------------
// Methods to sample morph data from a vertex texture
// NOTE: vMorphTargetTextureDim.x = width, cVertexTextureDim.y = height, cVertexTextureDim.z = # of float4 fields per vertex
// For position + normal morph for example, there will be 2 fields.
//-----------------------------------------------------------------------------
float4 SampleMorphDelta( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, const float flField )
{
float flColumn = floor( flVertexID / vMorphSubrect.w );
float4 t;
t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + flField + 0.5f;
t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f;
t.xy /= vMorphTargetTextureDim.xy;
t.z = t.w = 0.f;
return tex2Dlod( vt, t );
}
// Optimized version which reads 2 deltas
void SampleMorphDelta2( sampler2D vt, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect, const float flVertexID, out float4 delta1, out float4 delta2 )
{
float flColumn = floor( flVertexID / vMorphSubrect.w );
float4 t;
t.x = vMorphSubrect.x + vMorphTargetTextureDim.z * flColumn + 0.5f;
t.y = vMorphSubrect.y + flVertexID - flColumn * vMorphSubrect.w + 0.5f;
t.xy /= vMorphTargetTextureDim.xy;
t.z = t.w = 0.f;
delta1 = tex2Dlod( vt, t );
t.x += 1.0f / vMorphTargetTextureDim.x;
delta2 = tex2Dlod( vt, t );
}
#endif // SHADER_MODEL_VS_3_0
#if ( defined( SHADER_MODEL_VS_2_0 ) || defined( SHADER_MODEL_VS_3_0 ) )
//-----------------------------------------------------------------------------
// Method to apply morphs
//-----------------------------------------------------------------------------
bool ApplyMorph( float3 vPosFlex, inout float3 vPosition )
{
// Flexes coming in from a separate stream
float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;
vPosition.xyz += vPosDelta;
return true;
}
bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex, inout float3 vPosition, inout float3 vNormal )
{
// Flexes coming in from a separate stream
float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;
float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x;
vPosition.xyz += vPosDelta;
vNormal += vNormalDelta;
return true;
}
bool ApplyMorph( float3 vPosFlex, float3 vNormalFlex,
inout float3 vPosition, inout float3 vNormal, inout float3 vTangent )
{
// Flexes coming in from a separate stream
float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;
float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x;
vPosition.xyz += vPosDelta;
vNormal += vNormalDelta;
vTangent.xyz += vNormalDelta;
return true;
}
bool ApplyMorph( float4 vPosFlex, float3 vNormalFlex,
inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle )
{
// Flexes coming in from a separate stream
float3 vPosDelta = vPosFlex.xyz * cFlexScale.x;
float3 vNormalDelta = vNormalFlex.xyz * cFlexScale.x;
flWrinkle = vPosFlex.w * cFlexScale.y;
vPosition.xyz += vPosDelta;
vNormal += vNormalDelta;
vTangent.xyz += vNormalDelta;
return true;
}
#endif // defined( SHADER_MODEL_VS_2_0 ) || defined( SHADER_MODEL_VS_3_0 )
#ifdef SHADER_MODEL_VS_3_0
bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect,
const float flVertexID, const float3 vMorphTexCoord,
inout float3 vPosition )
{
#if MORPHING
#if !DECAL
// Flexes coming in from a separate stream
float4 vPosDelta = SampleMorphDelta( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, 0 );
vPosition += vPosDelta.xyz;
#else
float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );
float3 vPosDelta = tex2Dlod( morphSampler, t );
vPosition += vPosDelta.xyz * vMorphTexCoord.z;
#endif // DECAL
return true;
#else // !MORPHING
return false;
#endif
}
bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect,
const float flVertexID, const float3 vMorphTexCoord,
inout float3 vPosition, inout float3 vNormal )
{
#if MORPHING
#if !DECAL
float4 vPosDelta, vNormalDelta;
SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta );
vPosition += vPosDelta.xyz;
vNormal += vNormalDelta.xyz;
#else
float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );
float3 vPosDelta = tex2Dlod( morphSampler, t );
t.x += 1.0f / vMorphTargetTextureDim.x;
float3 vNormalDelta = tex2Dlod( morphSampler, t );
vPosition += vPosDelta.xyz * vMorphTexCoord.z;
vNormal += vNormalDelta.xyz * vMorphTexCoord.z;
#endif // DECAL
return true;
#else // !MORPHING
return false;
#endif
}
bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect,
const float flVertexID, const float3 vMorphTexCoord,
inout float3 vPosition, inout float3 vNormal, inout float3 vTangent )
{
#if MORPHING
#if !DECAL
float4 vPosDelta, vNormalDelta;
SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta );
vPosition += vPosDelta.xyz;
vNormal += vNormalDelta.xyz;
vTangent += vNormalDelta.xyz;
#else
float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );
float3 vPosDelta = tex2Dlod( morphSampler, t );
t.x += 1.0f / vMorphTargetTextureDim.x;
float3 vNormalDelta = tex2Dlod( morphSampler, t );
vPosition += vPosDelta.xyz * vMorphTexCoord.z;
vNormal += vNormalDelta.xyz * vMorphTexCoord.z;
vTangent += vNormalDelta.xyz * vMorphTexCoord.z;
#endif // DECAL
return true;
#else // MORPHING
return false;
#endif
}
bool ApplyMorph( sampler2D morphSampler, const float3 vMorphTargetTextureDim, const float4 vMorphSubrect,
const float flVertexID, const float3 vMorphTexCoord,
inout float3 vPosition, inout float3 vNormal, inout float3 vTangent, out float flWrinkle )
{
#if MORPHING
#if !DECAL
float4 vPosDelta, vNormalDelta;
SampleMorphDelta2( morphSampler, vMorphTargetTextureDim, vMorphSubrect, flVertexID, vPosDelta, vNormalDelta );
vPosition += vPosDelta.xyz;
vNormal += vNormalDelta.xyz;
vTangent += vNormalDelta.xyz;
flWrinkle = vPosDelta.w;
#else
float4 t = float4( vMorphTexCoord.x, vMorphTexCoord.y, 0.0f, 0.0f );
float4 vPosDelta = tex2Dlod( morphSampler, t );
t.x += 1.0f / vMorphTargetTextureDim.x;
float3 vNormalDelta = tex2Dlod( morphSampler, t );
vPosition += vPosDelta.xyz * vMorphTexCoord.z;
vNormal += vNormalDelta.xyz * vMorphTexCoord.z;
vTangent += vNormalDelta.xyz * vMorphTexCoord.z;
flWrinkle = vPosDelta.w * vMorphTexCoord.z;
#endif // DECAL
return true;
#else // MORPHING
flWrinkle = 0.0f;
return false;
#endif
}
#endif // SHADER_MODEL_VS_3_0
float RangeFog( const float3 projPos )
{
return max( cFogMaxDensity, ( -projPos.z * cOOFogRange + cFogEndOverFogRange ) );
}
float WaterFog( const float3 worldPos, const float3 projPos )
{
float4 tmp;
tmp.xy = cEyePosWaterZ.wz - worldPos.z;
// tmp.x is the distance from the water surface to the vert
// tmp.y is the distance from the eye position to the vert
// if $tmp.x < 0, then set it to 0
// This is the equivalent of moving the vert to the water surface if it's above the water surface
tmp.x = max( 0.0f, tmp.x );
// $tmp.w = $tmp.x / $tmp.y
tmp.w = tmp.x / tmp.y;
tmp.w *= projPos.z;
// $tmp.w is now the distance that we see through water.
return max( cFogMaxDensity, ( -tmp.w * cOOFogRange + cFogOne ) );
}
float CalcFog( const float3 worldPos, const float3 projPos, const int fogType )
{
#if defined( _X360 )
// 360 only does pixel fog
return 1.0f;
#endif
if( fogType == FOGTYPE_RANGE )
{
return RangeFog( projPos );
}
else
{
#if SHADERMODEL_VS_2_0 == 1
// We do this work in the pixel shader in dx9, so don't do any fog here.
return 1.0f;
#else
return WaterFog( worldPos, projPos );
#endif
}
}
float CalcFog( const float3 worldPos, const float3 projPos, const bool bWaterFog )
{
#if defined( _X360 )
// 360 only does pixel fog
return 1.0f;
#endif
float flFog;
if( !bWaterFog )
{
flFog = RangeFog( projPos );
}
else
{
#if SHADERMODEL_VS_2_0 == 1
// We do this work in the pixel shader in dx9, so don't do any fog here.
flFog = 1.0f;
#else
flFog = WaterFog( worldPos, projPos );
#endif
}
return flFog;
}
float4 DecompressBoneWeights( const float4 weights )
{
float4 result = weights;
if ( COMPRESSED_VERTS )
{
// Decompress from SHORT2 to float. In our case, [-1, +32767] -> [0, +1]
// NOTE: we add 1 here so we can divide by 32768 - which is exact (divide by 32767 is not).
// This avoids cracking between meshes with different numbers of bone weights.
// We use SHORT2 instead of SHORT2N for a similar reason - the GPU's conversion
// from [-32768,+32767] to [-1,+1] is imprecise in the same way.
result += 1;
result /= 32768;
}
return result;
}
void SkinPosition( bool bSkinning, const float4 modelPos,
const float4 boneWeights, float4 fBoneIndices,
out float3 worldPos )
{
#if !defined( _X360 )
int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices );
#else
int3 boneIndices = fBoneIndices;
#endif
// Needed for invariance issues caused by multipass rendering
#if defined( _X360 )
[isolate]
#endif
{
if ( !bSkinning )
{
worldPos = mul4x3( modelPos, cModel[0] );
}
else // skinning - always three bones
{
float4x3 mat1 = cModel[boneIndices[0]];
float4x3 mat2 = cModel[boneIndices[1]];
float4x3 mat3 = cModel[boneIndices[2]];
float3 weights = DecompressBoneWeights( boneWeights ).xyz;
weights[2] = 1 - (weights[0] + weights[1]);
float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2];
worldPos = mul4x3( modelPos, blendMatrix );
}
}
}
void SkinPositionAndNormal( bool bSkinning, const float4 modelPos, const float3 modelNormal,
const float4 boneWeights, float4 fBoneIndices,
out float3 worldPos, out float3 worldNormal )
{
// Needed for invariance issues caused by multipass rendering
#if defined( _X360 )
[isolate]
#endif
{
#if !defined( _X360 )
int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices );
#else
int3 boneIndices = fBoneIndices;
#endif
if ( !bSkinning )
{
worldPos = mul4x3( modelPos, cModel[0] );
worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] );
}
else // skinning - always three bones
{
float4x3 mat1 = cModel[boneIndices[0]];
float4x3 mat2 = cModel[boneIndices[1]];
float4x3 mat3 = cModel[boneIndices[2]];
float3 weights = DecompressBoneWeights( boneWeights ).xyz;
weights[2] = 1 - (weights[0] + weights[1]);
float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2];
worldPos = mul4x3( modelPos, blendMatrix );
worldNormal = mul3x3( modelNormal, ( float3x3 )blendMatrix );
}
} // end [isolate]
}
// Is it worth keeping SkinPosition and SkinPositionAndNormal around since the optimizer
// gets rid of anything that isn't used?
void SkinPositionNormalAndTangentSpace(
bool bSkinning,
const float4 modelPos, const float3 modelNormal,
const float4 modelTangentS,
const float4 boneWeights, float4 fBoneIndices,
out float3 worldPos, out float3 worldNormal,
out float3 worldTangentS, out float3 worldTangentT )
{
#if !defined( _X360 )
int3 boneIndices = D3DCOLORtoUBYTE4( fBoneIndices );
#else
int3 boneIndices = fBoneIndices;
#endif
// Needed for invariance issues caused by multipass rendering
#if defined( _X360 )
[isolate]
#endif
{
if ( !bSkinning )
{
worldPos = mul4x3( modelPos, cModel[0] );
worldNormal = mul3x3( modelNormal, ( const float3x3 )cModel[0] );
worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )cModel[0] );
}
else // skinning - always three bones
{
float4x3 mat1 = cModel[boneIndices[0]];
float4x3 mat2 = cModel[boneIndices[1]];
float4x3 mat3 = cModel[boneIndices[2]];
float3 weights = DecompressBoneWeights( boneWeights ).xyz;
weights[2] = 1 - (weights[0] + weights[1]);
float4x3 blendMatrix = mat1 * weights[0] + mat2 * weights[1] + mat3 * weights[2];
worldPos = mul4x3( modelPos, blendMatrix );
worldNormal = mul3x3( modelNormal, ( const float3x3 )blendMatrix );
worldTangentS = mul3x3( ( float3 )modelTangentS, ( const float3x3 )blendMatrix );
}
worldTangentT = cross( worldNormal, worldTangentS ) * modelTangentS.w;
}
}
//-----------------------------------------------------------------------------
// Lighting helper functions
//-----------------------------------------------------------------------------
float3 AmbientLight( const float3 worldNormal )
{
float3 nSquared = worldNormal * worldNormal;
int3 isNegative = ( worldNormal < 0.0 );
float3 linearColor;
linearColor = nSquared.x * cAmbientCubeX[isNegative.x] +
nSquared.y * cAmbientCubeY[isNegative.y] +
nSquared.z * cAmbientCubeZ[isNegative.z];
return linearColor;
}
// The following "internal" routines are called "privately" by other routines in this file which
// handle the particular flavor of vs20 control flow appropriate to the original caller
float VertexAttenInternal( const float3 worldPos, int lightNum )
{
float result = 0.0f;
// Get light direction
float3 lightDir = cLightInfo[lightNum].pos - worldPos;
// Get light distance squared.
float lightDistSquared = dot( lightDir, lightDir );
// Get 1/lightDistance
float ooLightDist = rsqrt( lightDistSquared );
// Normalize light direction
lightDir *= ooLightDist;
float3 vDist;
# if defined( _X360 )
{
//X360 dynamic compile hits an internal compiler error using dst(), this is the breakdown of how dst() works from the 360 docs.
vDist.x = 1;
vDist.y = lightDistSquared * ooLightDist;
vDist.z = lightDistSquared;
//flDist.w = ooLightDist;
}
# else
{
vDist = dst( lightDistSquared, ooLightDist );
}
# endif
float flDistanceAtten = 1.0f / dot( cLightInfo[lightNum].atten.xyz, vDist );
// Spot attenuation
float flCosTheta = dot( cLightInfo[lightNum].dir.xyz, -lightDir );
float flSpotAtten = (flCosTheta - cLightInfo[lightNum].spotParams.z) * cLightInfo[lightNum].spotParams.w;
flSpotAtten = max( 0.0001f, flSpotAtten );
flSpotAtten = pow( flSpotAtten, cLightInfo[lightNum].spotParams.x );
flSpotAtten = saturate( flSpotAtten );
// Select between point and spot
float flAtten = lerp( flDistanceAtten, flDistanceAtten * flSpotAtten, cLightInfo[lightNum].dir.w );
// Select between above and directional (no attenuation)
result = lerp( flAtten, 1.0f, cLightInfo[lightNum].color.w );
return result;
}
float CosineTermInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert )
{
// Calculate light direction assuming this is a point or spot
float3 lightDir = normalize( cLightInfo[lightNum].pos - worldPos );
// Select the above direction or the one in the structure, based upon light type
lightDir = lerp( lightDir, -cLightInfo[lightNum].dir, cLightInfo[lightNum].color.w );
// compute N dot L
float NDotL = dot( worldNormal, lightDir );
if ( !bHalfLambert )
{
NDotL = max( 0.0f, NDotL );
}
else // Half-Lambert
{
NDotL = NDotL * 0.5 + 0.5;
NDotL = NDotL * NDotL;
}
return NDotL;
}
// This routine uses booleans to do early-outs and is meant to be called by routines OUTSIDE of this file
float GetVertexAttenForLight( const float3 worldPos, int lightNum, bool bUseStaticControlFlow )
{
float result = 0.0f;
// Direct3D uses static control flow but OpenGL currently does not
if ( bUseStaticControlFlow )
{
if ( g_bLightEnabled[lightNum] )
{
result = VertexAttenInternal( worldPos, lightNum );
}
}
else // OpenGL non-static-control-flow path
{
result = VertexAttenInternal( worldPos, lightNum );
}
return result;
}
float3 DoLightInternal( const float3 worldPos, const float3 worldNormal, int lightNum, bool bHalfLambert )
{
return cLightInfo[lightNum].color *
CosineTermInternal( worldPos, worldNormal, lightNum, bHalfLambert ) *
VertexAttenInternal( worldPos, lightNum );
}
float3 DoLighting( const float3 worldPos, const float3 worldNormal,
const float3 staticLightingColor, const bool bStaticLight,
const bool bDynamicLight, bool bHalfLambert )
{
float3 linearColor = float3( 0.0f, 0.0f, 0.0f );
if( bStaticLight ) // Static light
{
float3 col = staticLightingColor * cOverbright;
#if defined ( _X360 )
linearColor += col * col;
#else
linearColor += GammaToLinear( col );
#endif
}
if( bDynamicLight ) // Dynamic light
{
for (int i = 0; i < g_nLightCount; i++)
{
linearColor += DoLightInternal( worldPos, worldNormal, i, bHalfLambert );
}
}
if( bDynamicLight )
{
linearColor += AmbientLight( worldNormal ); //ambient light is already remapped
}
return linearColor;
}
float3 DoLightingUnrolled( const float3 worldPos, const float3 worldNormal,
const float3 staticLightingColor, const bool bStaticLight,
const bool bDynamicLight, bool bHalfLambert, const int nNumLights )
{
float3 linearColor = float3( 0.0f, 0.0f, 0.0f );
if( bStaticLight ) // Static light
{
linearColor += GammaToLinear( staticLightingColor * cOverbright );
}
if( bDynamicLight ) // Ambient light
{
if ( nNumLights >= 1 )
linearColor += DoLightInternal( worldPos, worldNormal, 0, bHalfLambert );
if ( nNumLights >= 2 )
linearColor += DoLightInternal( worldPos, worldNormal, 1, bHalfLambert );
if ( nNumLights >= 3 )
linearColor += DoLightInternal( worldPos, worldNormal, 2, bHalfLambert );
if ( nNumLights >= 4 )
linearColor += DoLightInternal( worldPos, worldNormal, 3, bHalfLambert );
}
if( bDynamicLight )
{
linearColor += AmbientLight( worldNormal ); //ambient light is already remapped
}
return linearColor;
}
int4 FloatToInt( in float4 floats )
{
return D3DCOLORtoUBYTE4( floats.zyxw / 255.001953125 );
}
float2 ComputeSphereMapTexCoords( in float3 reflectionVector )
{
// transform reflection vector into view space
reflectionVector = mul( reflectionVector, ( float3x3 )cViewModel );
// generate <rx ry rz+1>
float3 tmp = float3( reflectionVector.x, reflectionVector.y, reflectionVector.z + 1.0f );
// find 1 / len
float ooLen = dot( tmp, tmp );
ooLen = 1.0f / sqrt( ooLen );
// tmp = tmp/|tmp| + 1
tmp.xy = ooLen * tmp.xy + 1.0f;
return tmp.xy * 0.5f;
}
#define DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE 1
// minxyz.minsoftness / maxxyz.maxsoftness
float3 ApplyDeformation( float3 worldpos, int deftype, float4 defparms0, float4 defparms1,
float4 defparms2, float4 defparms3 )
{
float3 ret = worldpos;
if ( deftype == DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE )
{
ret=max( ret, defparms2.xyz );
ret=min( ret, defparms3.xyz );
}
return ret;
}
#endif //#ifndef COMMON_VS_FXC_H_

View File

@ -0,0 +1,45 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Provide convenient mapping for shader constants
//
// $NoKeywords: $
//=============================================================================
#define C_CODE_HACK
#include "shader_constant_register_map.h"
#undef C_CODE_HACK
// For the C code, map the above file's defines back to integers...
#define PSREG_CONSTANT_00 0
#define PSREG_CONSTANT_01 1
#define PSREG_CONSTANT_02 2
#define PSREG_CONSTANT_03 3
#define PSREG_CONSTANT_04 4
#define PSREG_CONSTANT_05 5
#define PSREG_CONSTANT_06 6
#define PSREG_CONSTANT_07 7
#define PSREG_CONSTANT_08 8
#define PSREG_CONSTANT_09 9
#define PSREG_CONSTANT_10 10
#define PSREG_CONSTANT_11 11
#define PSREG_CONSTANT_12 12
#define PSREG_CONSTANT_13 13
#define PSREG_CONSTANT_14 14
#define PSREG_CONSTANT_15 15
#define PSREG_CONSTANT_16 16
#define PSREG_CONSTANT_17 17
#define PSREG_CONSTANT_18 18
#define PSREG_CONSTANT_19 19
#define PSREG_CONSTANT_20 20
#define PSREG_CONSTANT_21 21
#define PSREG_CONSTANT_22 22
#define PSREG_CONSTANT_23 23
#define PSREG_CONSTANT_24 24
#define PSREG_CONSTANT_25 25
#define PSREG_CONSTANT_26 26
#define PSREG_CONSTANT_27 27
#define PSREG_CONSTANT_28 28
#define PSREG_CONSTANT_29 29
#define PSREG_CONSTANT_30 30
#define PSREG_CONSTANT_31 31

View File

@ -0,0 +1,11 @@
#include "BaseVSShader.h"
// This one isn't supported on dx8
DEFINE_FALLBACK_SHADER( SDK_DepthWrite, Wireframe )
DEFINE_FALLBACK_SHADER( SDK_EyeRefract, Eyes_dx8 )
DEFINE_FALLBACK_SHADER( SDK_VolumeClouds, UnlitGeneric_DX8 )
// FIXME: These aren't supported on dx8, but need to be.
DEFINE_FALLBACK_SHADER( SDK_EyeGlint, EyeGlint )
DEFINE_FALLBACK_SHADER( SDK_AfterShock, AfterShock )

View File

@ -0,0 +1,60 @@
//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
//
// Example shader that can be applied to models
//
//==================================================================================================
#include "BaseVSShader.h"
#include "convar.h"
#include "example_model_dx9_helper.h"
#ifdef GAME_SHADER_DLL
DEFINE_FALLBACK_SHADER( Mod_Example_Model, Mod_Example_Model_DX9 )
BEGIN_VS_SHADER( Mod_Example_Model_DX9, "Help for Example Model Shader" )
#else
DEFINE_FALLBACK_SHADER( Example_Model, Example_Model_DX9 )
BEGIN_VS_SHADER( Example_Model_DX9, "Help for Example Model Shader" )
#endif
BEGIN_SHADER_PARAMS
SHADER_PARAM( ALPHATESTREFERENCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "" )
END_SHADER_PARAMS
void SetupVars( ExampleModel_DX9_Vars_t& info )
{
info.m_nBaseTexture = BASETEXTURE;
info.m_nBaseTextureFrame = FRAME;
info.m_nBaseTextureTransform = BASETEXTURETRANSFORM;
info.m_nAlphaTestReference = ALPHATESTREFERENCE;
info.m_nFlashlightTexture = FLASHLIGHTTEXTURE;
info.m_nFlashlightTextureFrame = FLASHLIGHTTEXTUREFRAME;
}
SHADER_INIT_PARAMS()
{
ExampleModel_DX9_Vars_t info;
SetupVars( info );
InitParamsExampleModel_DX9( this, params, pMaterialName, info );
}
SHADER_FALLBACK
{
return 0;
}
SHADER_INIT
{
ExampleModel_DX9_Vars_t info;
SetupVars( info );
InitExampleModel_DX9( this, params, info );
}
SHADER_DRAW
{
ExampleModel_DX9_Vars_t info;
SetupVars( info );
DrawExampleModel_DX9( this, params, pShaderAPI, pShaderShadow, info, vertexCompression, pContextDataPtr );
}
END_SHADER

View File

@ -0,0 +1,341 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#include "BaseVSShader.h"
#include "example_model_dx9_helper.h"
#include "convar.h"
#include "cpp_shader_constant_register_map.h"
#include "example_model_vs20.inc"
#include "example_model_ps20b.inc"
#include "commandbuilder.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static ConVar mat_fullbright( "mat_fullbright", "0", FCVAR_CHEAT );
static ConVar r_lightwarpidentity( "r_lightwarpidentity", "0", FCVAR_CHEAT );
static ConVar r_rimlight( "r_rimlight", "1", FCVAR_CHEAT );
// Textures may be bound to the following samplers:
// SHADER_SAMPLER0 Base (Albedo) / Gloss in alpha
// SHADER_SAMPLER4 Flashlight Shadow Depth Map
// SHADER_SAMPLER5 Normalization cube map
// SHADER_SAMPLER6 Flashlight Cookie
//-----------------------------------------------------------------------------
// Initialize shader parameters
//-----------------------------------------------------------------------------
void InitParamsExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, ExampleModel_DX9_Vars_t &info )
{
// FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture
Assert( info.m_nFlashlightTexture >= 0 );
if ( g_pHardwareConfig->SupportsBorderColor() )
{
params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight_border" );
}
else
{
params[FLASHLIGHTTEXTURE]->SetStringValue( "effects/flashlight001" );
}
// This shader can be used with hw skinning
SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING );
SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT );
}
//-----------------------------------------------------------------------------
// Initialize shader
//-----------------------------------------------------------------------------
void InitExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, ExampleModel_DX9_Vars_t &info )
{
Assert( info.m_nFlashlightTexture >= 0 );
pShader->LoadTexture( info.m_nFlashlightTexture, TEXTUREFLAGS_SRGB );
bool bIsBaseTextureTranslucent = false;
if ( params[info.m_nBaseTexture]->IsDefined() )
{
pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB );
if ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() )
{
bIsBaseTextureTranslucent = true;
}
}
}
class CExampleModel_DX9_Context : public CBasePerMaterialContextData
{
public:
CCommandBufferBuilder< CFixedCommandStorageBuffer< 800 > > m_SemiStaticCmdsOut;
bool m_bFastPath;
};
//-----------------------------------------------------------------------------
// Draws the shader
//-----------------------------------------------------------------------------
void DrawExampleModel_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow,
bool bHasFlashlight, ExampleModel_DX9_Vars_t &info, VertexCompressionType_t vertexCompression,
CBasePerMaterialContextData **pContextDataPtr )
{
bool bHasBaseTexture = (info.m_nBaseTexture != -1) && params[info.m_nBaseTexture]->IsTexture();
bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0;
BlendType_t nBlendType= pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true );
bool bFullyOpaque = ( nBlendType != BT_BLENDADD ) && ( nBlendType != BT_BLEND ) && !bIsAlphaTested && !bHasFlashlight;
CExampleModel_DX9_Context *pContextData = reinterpret_cast< CExampleModel_DX9_Context *> ( *pContextDataPtr );
if ( !pContextData )
{
pContextData = new CExampleModel_DX9_Context;
*pContextDataPtr = pContextData;
}
if( pShader->IsSnapshotting() )
{
pShaderShadow->EnableAlphaTest( bIsAlphaTested );
if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f )
{
pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() );
}
int nShadowFilterMode = 0;
if( bHasFlashlight )
{
if (params[info.m_nBaseTexture]->IsTexture())
{
pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true );
}
if( bIsAlphaTested )
{
// disable alpha test and use the zfunc zequals since alpha isn't guaranteed to
// be the same on both the regular pass and the flashlight pass.
pShaderShadow->EnableAlphaTest( false );
pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL );
}
pShaderShadow->EnableBlending( true );
pShaderShadow->EnableDepthWrites( false );
// Be sure not to write to dest alpha
pShaderShadow->EnableAlphaWrites( false );
nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats
}
else // not flashlight pass
{
if (params[info.m_nBaseTexture]->IsTexture())
{
pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true );
}
}
unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
int userDataSize = 0;
// Always enable...will bind white if nothing specified...
pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base (albedo) map
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, true );
if( bHasFlashlight )
{
pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Shadow depth map
pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 );
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false );
pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Noise map
pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Flashlight cookie
pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, true );
userDataSize = 4; // tangent S
}
// Always enable, since flat normal will be bound
pShaderShadow->EnableTexture( SHADER_SAMPLER3, true ); // Normal map
userDataSize = 4; // tangent S
pShaderShadow->EnableTexture( SHADER_SAMPLER5, true ); // Normalizing cube map
pShaderShadow->EnableSRGBWrite( true );
// texcoord0 : base texcoord, texcoord2 : decal hw morph delta
int pTexCoordDim[3] = { 2, 0, 3 };
int nTexCoordCount = 1;
// This shader supports compressed vertices, so OR in that flag:
flags |= VERTEX_FORMAT_COMPRESSED;
pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize );
DECLARE_STATIC_VERTEX_SHADER( example_model_vs20 );
SET_STATIC_VERTEX_SHADER( example_model_vs20 );
// Assume we're only going to get in here if we support 2b
DECLARE_STATIC_PIXEL_SHADER( example_model_ps20b );
SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
SET_STATIC_PIXEL_SHADER_COMBO( CONVERT_TO_SRGB, 0 );
SET_STATIC_PIXEL_SHADER( example_model_ps20b );
if( bHasFlashlight )
{
pShader->FogToBlack();
}
else
{
pShader->DefaultFog();
}
// 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 );
if( bHasBaseTexture )
{
pShader->BindTexture( SHADER_SAMPLER0, info.m_nBaseTexture, info.m_nBaseTextureFrame );
}
else
{
pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_WHITE );
}
LightState_t lightState = { 0, false, false };
bool bFlashlightShadows = false;
if( bHasFlashlight )
{
Assert( info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0 );
pShader->BindTexture( SHADER_SAMPLER6, info.m_nFlashlightTexture, info.m_nFlashlightTextureFrame );
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 )
{
pShader->BindTexture( SHADER_SAMPLER4, pFlashlightDepthTexture, 0 );
pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D );
}
}
else // no flashlight
{
pShaderAPI->GetDX9LightState( &lightState );
}
MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode();
int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0;
int numBones = pShaderAPI->GetCurrentNumBones();
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." );
}
DECLARE_DYNAMIC_VERTEX_SHADER( example_model_vs20 );
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( example_model_vs20 );
DECLARE_DYNAMIC_PIXEL_SHADER( example_model_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( example_model_ps20b );
pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform );
pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 );
pShader->SetAmbientCubeDynamicStateVertexShader();
if( !bHasFlashlight )
{
pShaderAPI->BindStandardTexture( SHADER_SAMPLER5, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED );
}
pShaderAPI->SetPixelShaderStateAmbientLightCube( PSREG_AMBIENT_CUBE, !lightState.m_bAmbientLight ); // Force to black if not bAmbientLight
pShaderAPI->CommitPixelShaderLighting( PSREG_LIGHT_INFO_ARRAY );
// handle mat_fullbright 2 (diffuse lighting only)
if( bLightingOnly )
{
pShaderAPI->BindStandardTexture( SHADER_SAMPLER0, TEXTURE_GREY );
}
pShaderAPI->SetPixelShaderFogParams( PSREG_FOG_PARAMS );
if( bHasFlashlight )
{
VMatrix worldToTexture;
float atten[4], pos[4], tweaks[4];
const FlashlightState_t &flashlightState = pShaderAPI->GetFlashlightState( worldToTexture );
SetFlashLightColorFromState( flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR );
pShader->BindTexture( SHADER_SAMPLER6, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame );
atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors
atten[1] = flashlightState.m_fLinearAtten;
atten[2] = flashlightState.m_fQuadraticAtten;
atten[3] = flashlightState.m_FarZ;
pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, atten, 1 );
pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin
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 );
pShader->HashShadow2DJitter( flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] );
pShaderAPI->SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, tweaks, 1 );
// Dimensions of screen, used for screen-space noise map sampling
float vScreenScale[4] = {1280.0f / 32.0f, 720.0f / 32.0f, 0, 0};
int nWidth, nHeight;
pShaderAPI->GetBackBufferDimensions( nWidth, nHeight );
vScreenScale[0] = (float) nWidth / 32.0f;
vScreenScale[1] = (float) nHeight / 32.0f;
pShaderAPI->SetPixelShaderConstant( PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1 );
}
}
pShader->Draw();
}
//-----------------------------------------------------------------------------
// Draws the shader
//-----------------------------------------------------------------------------
void DrawExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow,
ExampleModel_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr )
{
bool bHasFlashlight = pShader->UsingFlashlight( params );
if ( bHasFlashlight )
{
DrawExampleModel_DX9_Internal( pShader, params, pShaderAPI, pShaderShadow, false, info, vertexCompression, pContextDataPtr++ );
if ( pShaderShadow )
{
pShader->SetInitialShadowState( );
}
}
DrawExampleModel_DX9_Internal( pShader, params, pShaderAPI, pShaderShadow, bHasFlashlight, info, vertexCompression, pContextDataPtr );
}

View File

@ -0,0 +1,46 @@
//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
//
// Example shader that can be applied to models
//
//==================================================================================================
#ifndef EXAMPLE_MODEL_DX9_HELPER_H
#define EXAMPLE_MODEL_DX9_HELPER_H
#include <string.h>
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CBaseVSShader;
class IMaterialVar;
class IShaderDynamicAPI;
class IShaderShadow;
//-----------------------------------------------------------------------------
// Init params/ init/ draw methods
//-----------------------------------------------------------------------------
struct ExampleModel_DX9_Vars_t
{
ExampleModel_DX9_Vars_t() { memset( this, 0xFF, sizeof(*this) ); }
int m_nBaseTexture;
int m_nBaseTextureFrame;
int m_nBaseTextureTransform;
int m_nAlphaTestReference;
int m_nFlashlightTexture;
int m_nFlashlightTextureFrame;
};
void InitParamsExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params,
const char *pMaterialName, ExampleModel_DX9_Vars_t &info );
void InitExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params,
ExampleModel_DX9_Vars_t &info );
void DrawExampleModel_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI,
IShaderShadow* pShaderShadow,
ExampleModel_DX9_Vars_t &info, VertexCompressionType_t vertexCompression,
CBasePerMaterialContextData **pContextDataPtr );
#endif // EXAMPLE_MODEL_DX9_HELPER_H

View File

@ -0,0 +1,92 @@
//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
//
// Example pixel shader that can be applied to models
//
//==================================================================================================
// STATIC: "CONVERT_TO_SRGB" "0..0"
// STATIC: "FLASHLIGHT" "0..1"
// STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps20b]
// DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1"
// DYNAMIC: "PIXELFOGTYPE" "0..1"
// DYNAMIC: "NUM_LIGHTS" "0..4"
// DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b]
// DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b]
// 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 ) [ps20b]
#include "common_flashlight_fxc.h"
#include "shader_constant_register_map.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 ); // On non-flashlight pass
const float4 g_FlashlightPos_RimBoost : 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)
#define g_FlashlightPos g_FlashlightPos_RimBoost.xyz
sampler BaseTextureSampler : register( s0 ); // Base map, selfillum in alpha
sampler ShadowDepthSampler : register( s4 ); // Flashlight shadow depth map sampler
sampler NormalizeRandRotSampler : register( s5 ); // Normalization / RandomRotation samplers
sampler FlashlightSampler : register( s6 ); // Flashlight cookie
struct PS_INPUT
{
float2 baseTexCoord : TEXCOORD0;
float4 lightAtten : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
float3 worldPos : TEXCOORD3;
float3 projPos : TEXCOORD4;
};
float4 main( PS_INPUT i ) : COLOR
{
float4 baseColor = tex2D( BaseTextureSampler, i.baseTexCoord );
float3 diffuseLighting;
if ( FLASHLIGHT != 0 )
{
float4 flashlightSpacePosition = mul( float4( i.worldPos, 1.0f ), g_FlashlightWorldToTexture );
diffuseLighting = DoFlashlight( g_FlashlightPos, i.worldPos, flashlightSpacePosition,
i.worldNormal, g_FlashlightAttenuationFactors.xyz,
g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler,
NormalizeRandRotSampler, FLASHLIGHTDEPTHFILTERMODE, FLASHLIGHTSHADOWS, true, i.projPos, false, g_ShadowTweaks );
}
else // non-flashlight path
{
// Summation of diffuse illumination from all local lights
diffuseLighting = PixelShaderDoLighting( i.worldPos, i.worldNormal,
float3( 0.0f, 0.0f, 0.0f ), false, true, i.lightAtten,
cAmbientCube, NormalizeRandRotSampler, NUM_LIGHTS, cLightInfo, true,
// These are dummy parameters:
false, 1.0f,
false, BaseTextureSampler );
}
float3 result = baseColor.rgb * g_DiffuseModulation.rgb * diffuseLighting;
float alpha = g_DiffuseModulation.a * baseColor.a;
float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_FogParams, g_EyePos.z, i.worldPos.z, i.projPos.z );
#if WRITEWATERFOGTODESTALPHA && ( PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT )
alpha = fogFactor;
#endif
bool bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 );
return FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.projPos.z );
}

View File

@ -0,0 +1,91 @@
//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
//
// Example vertex shader that can be applied to 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;
};
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;
};
//-----------------------------------------------------------------------------
// Main shader entry point
//-----------------------------------------------------------------------------
VS_OUTPUT main( const VS_INPUT v )
{
VS_OUTPUT o = ( VS_OUTPUT )0;
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.xyz = 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;
}

View File

@ -0,0 +1,237 @@
#include "shaderlib/cshader.h"
class example_model_ps20b_Static_Index
{
private:
int m_nCONVERT_TO_SRGB;
#ifdef _DEBUG
bool m_bCONVERT_TO_SRGB;
#endif
public:
void SetCONVERT_TO_SRGB( int i )
{
Assert( i >= 0 && i <= 0 );
m_nCONVERT_TO_SRGB = i;
#ifdef _DEBUG
m_bCONVERT_TO_SRGB = true;
#endif
}
void SetCONVERT_TO_SRGB( bool i )
{
m_nCONVERT_TO_SRGB = i ? 1 : 0;
#ifdef _DEBUG
m_bCONVERT_TO_SRGB = true;
#endif
}
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
}
public:
example_model_ps20b_Static_Index( )
{
#ifdef _DEBUG
m_bCONVERT_TO_SRGB = false;
#endif // _DEBUG
m_nCONVERT_TO_SRGB = 0;
#ifdef _DEBUG
m_bFLASHLIGHT = false;
#endif // _DEBUG
m_nFLASHLIGHT = 0;
#ifdef _DEBUG
m_bFLASHLIGHTDEPTHFILTERMODE = false;
#endif // _DEBUG
m_nFLASHLIGHTDEPTHFILTERMODE = 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_bCONVERT_TO_SRGB && m_bFLASHLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE;
Assert( bAllStaticVarsDefined );
#endif // _DEBUG
return ( 80 * m_nCONVERT_TO_SRGB ) + ( 80 * m_nFLASHLIGHT ) + ( 160 * m_nFLASHLIGHTDEPTHFILTERMODE ) + 0;
}
};
#define shaderStaticTest_example_model_ps20b psh_forgot_to_set_static_CONVERT_TO_SRGB + psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE + 0
class example_model_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:
example_model_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_example_model_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

View File

@ -0,0 +1,160 @@
#include "shaderlib/cshader.h"
class example_model_vs20_Static_Index
{
public:
example_model_vs20_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_example_model_vs20 0
class example_model_vs20_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:
example_model_vs20_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_example_model_vs20 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

View File

@ -0,0 +1,101 @@
//-----------------------------------------------------------------------------
// game_shader_dx9.vpc
//
// Project Script for mods to use an an example of how to override shaders
//-----------------------------------------------------------------------------
$Macro OUTBINDIR "$SRCDIR\..\game\$GAMENAME\bin"
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
$Configuration "Debug"
{
$General
{
$OutputDirectory "Debug_dx9_$GAMENAME" [$WIN32]
$IntermediateDirectory "Debug_dx9_$GAMENAME" [$WIN32]
}
}
$Configuration "Release"
{
$General
{
$OutputDirectory "Release_dx9_$GAMENAME" [$WIN32]
$IntermediateDirectory "Release_dx9_$GAMENAME" [$WIN32]
}
}
// Common Configuration
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE;fxctmp9;vshtmp9;" [$WIN32||$POSIX]
// $AdditionalIncludeDirectories "$BASE;..\..\dx9sdk\include" [$WIN32]
$AdditionalIncludeDirectories "$BASE;fxctmp9_360;vshtmp9_360" [$X360]
$PreprocessorDefinitions "$BASE;STDSHADER_DX9_DLL_EXPORT;FAST_MATERIALVAR_ACCESS;GAME_SHADER_DLL"
$PreprocessorDefinitions "$BASE;USE_ACTUAL_DX" [($WIN32||$X360) && !$GL]
}
$Linker
{
$AdditionalDependencies "$BASE version.lib winmm.lib" [$WIN32]
$SystemLibraries "iconv" [$OSXALL]
}
}
$Project
{
$Folder "Source Files"
{
$File "BaseVSShader.cpp"
$File "example_model_dx9.cpp"
$File "example_model_dx9_helper.cpp"
}
$Folder "Header Files"
{
$File "BaseVSShader.h"
$File "common_fxc.h"
$File "common_hlsl_cpp_consts.h"
$File "common_ps_fxc.h"
$File "common_vertexlitgeneric_dx9.h"
$File "common_vs_fxc.h"
$File "shader_constant_register_map.h"
$File "example_model_dx9_helper.h"
}
$Folder "Link Libraries" [$WIN32]
{
// $File "$SRCDIR\dx9sdk\lib\d3dx9.lib"
$DynamicFile "$SRCDIR\lib\public\mathlib.lib"
$DynamicFile "$SRCDIR\lib\public\shaderlib.lib"
}
$Folder "Link Libraries" [$X360]
{
$DynamicFile "$SRCDIR\lib\public\mathlib_360.lib"
$DynamicFile "$SRCDIR\lib\public\shaderlib_360.lib"
}
$Folder "Link Libraries" [$POSIX&&!$LINUX]
{
$DynamicFile "$SRCDIR\lib\$PLATFORM\mathlib$_STATICLIB_EXT"
$DynamicFile "$SRCDIR\lib\$PLATFORM\shaderlib$_STATICLIB_EXT"
}
$Folder "Link Libraries" [$LINUX]
{
$Lib mathlib
$Lib shaderlib
}
$File "buildsdkshaders.bat"
$File "buildshaders.bat"
$Shaders "stdshader_dx9_20b.txt"
$Shaders "stdshader_dx9_30.txt"
}

View File

@ -0,0 +1,13 @@
//-----------------------------------------------------------------------------
// game_shader_dx9.vpc
//
// Project Script for mods to use an an example of how to override shaders
//-----------------------------------------------------------------------------
$Macro SRCDIR "..\.."
$Macro GAMENAME "mod_hl2mp"
$Include "$SRCDIR\materialsystem\stdshaders\game_shader_dx9_base.vpc"
$Project "Shaders (HL2MP)"
{
}

View File

@ -0,0 +1,9 @@
for($ix=-2;$ix<=2;$ix++)
{
for($iy=-2;$iy<=2;$iy++)
{
print "vRefractColor += tex2D( RefractSampler, vRefractTexCoord + $ix * ddx1 + $iy * ddy1 );\n";
$sumweights+=1;
}
}
print "float sumweights = $sumweights;\n";

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Provide convenient mapping for shader constants
//
// $NoKeywords: $
//=============================================================================
#ifndef C_CODE_HACK
#include "common_vertexlitgeneric_dx9.h"
#endif
#define PSREG_SELFILLUMTINT PSREG_CONSTANT_00
#define PSREG_DIFFUSE_MODULATION PSREG_CONSTANT_01
#define PSREG_ENVMAP_TINT__SHADOW_TWEAKS PSREG_CONSTANT_02
#define PSREG_SELFILLUM_SCALE_BIAS_EXP PSREG_CONSTANT_03
#define PSREG_AMBIENT_CUBE PSREG_CONSTANT_04
// PSREG_AMBIENT_CUBE PSREG_CONSTANT_05
// PSREG_AMBIENT_CUBE PSREG_CONSTANT_06
// PSREG_AMBIENT_CUBE PSREG_CONSTANT_07
// PSREG_AMBIENT_CUBE PSREG_CONSTANT_08
// PSREG_AMBIENT_CUBE PSREG_CONSTANT_09
#define PSREG_ENVMAP_FRESNEL__SELFILLUMMASK PSREG_CONSTANT_10
#define PSREG_EYEPOS_SPEC_EXPONENT PSREG_CONSTANT_11
#define PSREG_FOG_PARAMS PSREG_CONSTANT_12
#define PSREG_FLASHLIGHT_ATTENUATION PSREG_CONSTANT_13
#define PSREG_FLASHLIGHT_POSITION_RIM_BOOST PSREG_CONSTANT_14
#define PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_15
// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_16
// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_17
// PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_18
#define PSREG_FRESNEL_SPEC_PARAMS PSREG_CONSTANT_19
#define PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_20
// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_21
// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_22
// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_23
// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_24
// PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_25
#define PSREG_SPEC_RIM_PARAMS PSREG_CONSTANT_26
// #define **free** PSREG_CONSTANT_27 //actually using this often blows constant limits, since literals have to get stuffed somewhere...
#define PSREG_FLASHLIGHT_COLOR PSREG_CONSTANT_28
#define PSREG_LINEAR_FOG_COLOR PSREG_CONSTANT_29
#define PSREG_LIGHT_SCALE PSREG_CONSTANT_30
#define PSREG_FLASHLIGHT_SCREEN_SCALE PSREG_CONSTANT_31
// --- End of ps_2_0 and ps_2_b constants ---
#ifndef C_CODE_HACK
//for fxc code, map the constants to register names.
#define PSREG_CONSTANT_00 c0
#define PSREG_CONSTANT_01 c1
#define PSREG_CONSTANT_02 c2
#define PSREG_CONSTANT_03 c3
#define PSREG_CONSTANT_04 c4
#define PSREG_CONSTANT_05 c5
#define PSREG_CONSTANT_06 c6
#define PSREG_CONSTANT_07 c7
#define PSREG_CONSTANT_08 c8
#define PSREG_CONSTANT_09 c9
#define PSREG_CONSTANT_10 c10
#define PSREG_CONSTANT_11 c11
#define PSREG_CONSTANT_12 c12
#define PSREG_CONSTANT_13 c13
#define PSREG_CONSTANT_14 c14
#define PSREG_CONSTANT_15 c15
#define PSREG_CONSTANT_16 c16
#define PSREG_CONSTANT_17 c17
#define PSREG_CONSTANT_18 c18
#define PSREG_CONSTANT_19 c19
#define PSREG_CONSTANT_20 c20
#define PSREG_CONSTANT_21 c21
#define PSREG_CONSTANT_22 c22
#define PSREG_CONSTANT_23 c23
#define PSREG_CONSTANT_24 c24
#define PSREG_CONSTANT_25 c25
#define PSREG_CONSTANT_26 c26
#define PSREG_CONSTANT_27 c27
#define PSREG_CONSTANT_28 c28
#define PSREG_CONSTANT_29 c29
#define PSREG_CONSTANT_30 c30
#define PSREG_CONSTANT_31 c31
#endif

View File

@ -0,0 +1,11 @@
//
// Standard shaders collection
//
// These shaders are compiled as the following shader models:
// _ps20.vcs
// _ps20b.vcs
// _vs20.vcs
//
example_model_ps20b.fxc
example_model_vs20.fxc

View File

@ -0,0 +1,10 @@
//
// vs 3.0 ps 3.0 shaders collection
//
// These shaders are forced to compile as shader model 3.0
// using the new compiler.
// _ps30.vcs
// _vs30.vcs
//
// There are no examples of such shaders in the SDK, but add yours here.