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:
191
materialsystem/shaderapidx9/locald3dtypes.h
Normal file
191
materialsystem/shaderapidx9/locald3dtypes.h
Normal 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
|
2234
materialsystem/stdshaders/BaseVSShader.cpp
Normal file
2234
materialsystem/stdshaders/BaseVSShader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
439
materialsystem/stdshaders/BaseVSShader.h
Normal file
439
materialsystem/stdshaders/BaseVSShader.h
Normal 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
|
21
materialsystem/stdshaders/buildhl2mpshaders.bat
Normal file
21
materialsystem/stdshaders/buildhl2mpshaders.bat
Normal 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
|
40
materialsystem/stdshaders/buildsdkshaders.bat
Normal file
40
materialsystem/stdshaders/buildsdkshaders.bat
Normal 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.
|
209
materialsystem/stdshaders/buildshaders.bat
Normal file
209
materialsystem/stdshaders/buildshaders.bat
Normal 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.
|
||||
|
33
materialsystem/stdshaders/clean.bat
Normal file
33
materialsystem/stdshaders/clean.bat
Normal 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
|
12
materialsystem/stdshaders/cleantemps.bat
Normal file
12
materialsystem/stdshaders/cleantemps.bat
Normal 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
|
407
materialsystem/stdshaders/commandbuilder.h
Normal file
407
materialsystem/stdshaders/commandbuilder.h
Normal 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
|
821
materialsystem/stdshaders/common_flashlight_fxc.h
Normal file
821
materialsystem/stdshaders/common_flashlight_fxc.h
Normal 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_
|
326
materialsystem/stdshaders/common_fxc.h
Normal file
326
materialsystem/stdshaders/common_fxc.h
Normal 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_
|
19
materialsystem/stdshaders/common_fxc2.h
Normal file
19
materialsystem/stdshaders/common_fxc2.h
Normal 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_
|
27
materialsystem/stdshaders/common_hlsl_cpp_consts.h
Normal file
27
materialsystem/stdshaders/common_hlsl_cpp_consts.h
Normal 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_
|
202
materialsystem/stdshaders/common_lightmappedgeneric_fxc.h
Normal file
202
materialsystem/stdshaders/common_lightmappedgeneric_fxc.h
Normal 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
|
||||
}
|
||||
|
38
materialsystem/stdshaders/common_pragmas.h
Normal file
38
materialsystem/stdshaders/common_pragmas.h
Normal 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_
|
804
materialsystem/stdshaders/common_ps_fxc.h
Normal file
804
materialsystem/stdshaders/common_ps_fxc.h
Normal 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_
|
423
materialsystem/stdshaders/common_vertexlitgeneric_dx9.h
Normal file
423
materialsystem/stdshaders/common_vertexlitgeneric_dx9.h
Normal 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_
|
955
materialsystem/stdshaders/common_vs_fxc.h
Normal file
955
materialsystem/stdshaders/common_vs_fxc.h
Normal 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_
|
45
materialsystem/stdshaders/cpp_shader_constant_register_map.h
Normal file
45
materialsystem/stdshaders/cpp_shader_constant_register_map.h
Normal 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
|
||||
|
11
materialsystem/stdshaders/dx8fallbacks.cpp
Normal file
11
materialsystem/stdshaders/dx8fallbacks.cpp
Normal 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 )
|
60
materialsystem/stdshaders/example_model_dx9.cpp
Normal file
60
materialsystem/stdshaders/example_model_dx9.cpp
Normal 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
|
||||
|
341
materialsystem/stdshaders/example_model_dx9_helper.cpp
Normal file
341
materialsystem/stdshaders/example_model_dx9_helper.cpp
Normal 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 );
|
||||
}
|
46
materialsystem/stdshaders/example_model_dx9_helper.h
Normal file
46
materialsystem/stdshaders/example_model_dx9_helper.h
Normal 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
|
92
materialsystem/stdshaders/example_model_ps20b.fxc
Normal file
92
materialsystem/stdshaders/example_model_ps20b.fxc
Normal 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 );
|
||||
}
|
91
materialsystem/stdshaders/example_model_vs20.fxc
Normal file
91
materialsystem/stdshaders/example_model_vs20.fxc
Normal 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;
|
||||
}
|
237
materialsystem/stdshaders/fxctmp9/example_model_ps20b.inc
Normal file
237
materialsystem/stdshaders/fxctmp9/example_model_ps20b.inc
Normal 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
|
160
materialsystem/stdshaders/fxctmp9/example_model_vs20.inc
Normal file
160
materialsystem/stdshaders/fxctmp9/example_model_vs20.inc
Normal 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
|
101
materialsystem/stdshaders/game_shader_dx9_base.vpc
Normal file
101
materialsystem/stdshaders/game_shader_dx9_base.vpc
Normal 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"
|
||||
}
|
13
materialsystem/stdshaders/game_shader_dx9_hl2mp.vpc
Normal file
13
materialsystem/stdshaders/game_shader_dx9_hl2mp.vpc
Normal 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)"
|
||||
{
|
||||
}
|
9
materialsystem/stdshaders/genwaterloop.pl
Normal file
9
materialsystem/stdshaders/genwaterloop.pl
Normal 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";
|
1393
materialsystem/stdshaders/macros.vsh
Normal file
1393
materialsystem/stdshaders/macros.vsh
Normal file
File diff suppressed because it is too large
Load Diff
81
materialsystem/stdshaders/shader_constant_register_map.h
Normal file
81
materialsystem/stdshaders/shader_constant_register_map.h
Normal 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
|
11
materialsystem/stdshaders/stdshader_dx9_20b.txt
Normal file
11
materialsystem/stdshaders/stdshader_dx9_20b.txt
Normal 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
|
10
materialsystem/stdshaders/stdshader_dx9_30.txt
Normal file
10
materialsystem/stdshaders/stdshader_dx9_30.txt
Normal 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.
|
Reference in New Issue
Block a user