aboutsummaryrefslogtreecommitdiff
path: root/mp/src/materialsystem/stdshaders/eye_refract_vs20.fxc
blob: af975f9923d4e530d46d90bfe51865cc532c320b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
//========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//

// STATIC: "INTRO"				"0..1"
// STATIC: "HALFLAMBERT"		"0..1"
// STATIC: "FLASHLIGHT"			"0..1"
// STATIC: "LIGHTWARPTEXTURE"	"0..1"

// DYNAMIC: "COMPRESSED_VERTS"	"0..1"
// DYNAMIC: "SKINNING"			"0..1"
// DYNAMIC: "DOWATERFOG"		"0..1"
// DYNAMIC: "DYNAMIC_LIGHT"		"0..1"
// DYNAMIC: "STATIC_LIGHT"		"0..1"
// DYNAMIC: "NUM_LIGHTS"		"0..4"
// DYNAMIC: "MORPHING"			"0..1" [vs30]

#include "vortwarp_vs20_helper.h"

static const bool g_bSkinning		= SKINNING ? true : false;
static const int  g_iFogType		= DOWATERFOG;
static const bool g_bHalfLambert	= HALFLAMBERT ? true : false;

const float3 g_cEyeOrigin			:  register( SHADER_SPECIFIC_CONST_0 );
const float4 g_vIrisProjectionU		:  register( SHADER_SPECIFIC_CONST_2 );
const float4 g_vIrisProjectionV		:  register( SHADER_SPECIFIC_CONST_3 );
const float4 g_vFlashlightPosition	:  register( SHADER_SPECIFIC_CONST_4 );

#if INTRO
const float4 g_vConst4	:  register( SHADER_SPECIFIC_CONST_5 );
#define g_vModelOrigin g_vConst4.xyz
#define g_flTime       g_vConst4.w
#endif

const float4 g_vFlashlightMatrixRow1  :  register( SHADER_SPECIFIC_CONST_6 );
const float4 g_vFlashlightMatrixRow2  :  register( SHADER_SPECIFIC_CONST_7 );
const float4 g_vFlashlightMatrixRow3  :  register( SHADER_SPECIFIC_CONST_8 );
const float4 g_vFlashlightMatrixRow4  :  register( SHADER_SPECIFIC_CONST_9 );

#ifdef SHADER_MODEL_VS_3_0
// NOTE: cMorphTargetTextureDim.xy = target dimensions,
//		 cMorphTargetTextureDim.z = 4tuples/morph
const float3 cMorphTargetTextureDim		: register( SHADER_SPECIFIC_CONST_10 );
const float4 cMorphSubrect				: register( SHADER_SPECIFIC_CONST_11 );

sampler2D morphSampler					: register( D3DVERTEXTEXTURESAMPLER0, s0 );
#endif

struct VS_INPUT
{
	float4 vPos					: POSITION;		// Position
	float4 vBoneWeights			: BLENDWEIGHT;	// Skin weights
	float4 vBoneIndices			: BLENDINDICES;	// Skin indices
	float4 vTexCoord0			: TEXCOORD0;	// Base (sclera) texture coordinates

	// Position deltas
	float3 vPosFlex				: POSITION1;
	
#ifdef SHADER_MODEL_VS_3_0
	float vVertexID				: POSITION2;
#endif
};

struct VS_OUTPUT
{
    float4 projPos							: POSITION;		// Projection-space position
#if !defined( _X360 )
	float  fog								: FOG;			// Fixed-function fog factor
#endif
	float4 vAmbientOcclUv_fallbackCorneaUv	: TEXCOORD0;	// Base texture coordinate
	float4 cVertexLight						: TEXCOORD1;	// Vertex-lit color (Note: w is used for flashlight pass)
	float4 vTangentViewVector				: TEXCOORD2;	// Tangent view vector (Note: w is used for flashlight pass)
	float4 vWorldPosition_ProjPosZ			: TEXCOORD3;
	float3 vWorldNormal						: TEXCOORD4;	// World-space normal
	float3 vWorldTangent					: TEXCOORD5;	// World-space tangent
	float4 vLightFalloffCosine01			: TEXCOORD6;	// Light falloff and cosine terms for first two local lights
	float4 vLightFalloffCosine23			: TEXCOORD7;	// Light falloff and cosine terms for next two local lights

	float3 vWorldBinormal					: COLOR0;	// World-space normal
};

VS_OUTPUT main( const VS_INPUT v )
{
	VS_OUTPUT o;

	bool bDynamicLight = DYNAMIC_LIGHT ? true : false;
	bool bStaticLight = STATIC_LIGHT ? true : false;
	int nNumLights = NUM_LIGHTS;

	float4 vPosition = v.vPos;

#if !defined( SHADER_MODEL_VS_3_0 ) || !MORPHING
	ApplyMorph( v.vPosFlex, vPosition.xyz );
#else
	ApplyMorph( morphSampler, cMorphTargetTextureDim, cMorphSubrect, v.vVertexID, float3( 0, 0, 0 ), vPosition.xyz );
#endif

	// Transform the position
	float3 vWorldPosition;
	SkinPosition( g_bSkinning, vPosition, v.vBoneWeights, v.vBoneIndices, vWorldPosition );

	// Note: I'm relying on the iris projection vector math not changing or this will break
	float3 vEyeSocketUpVector = normalize( -g_vIrisProjectionV.xyz );
	float3 vEyeSocketLeftVector = normalize( -g_vIrisProjectionU.xyz );

#if INTRO
	float3 dummy = float3( 0.0f, 0.0f, 0.0f );
	WorldSpaceVertexProcess( g_flTime, g_vModelOrigin, vWorldPosition, dummy, dummy, dummy );
#endif

	o.vWorldPosition_ProjPosZ.xyz = vWorldPosition.xyz;

	// Transform into projection space
	//vWorldPosition -= ( vWorldPosition - g_cEyeOrigin ) * 0.9; //Debug to visualize eye origin
	float4 vProjPos = mul( float4( vWorldPosition, 1.0f ), cViewProj );
	o.projPos = vProjPos;
	vProjPos.z = dot( float4( vWorldPosition, 1.0f ), cViewProjZ );

	
	o.vWorldPosition_ProjPosZ.w = vProjPos.z;

#if !defined( _X360 )
	// Set fixed-function fog factor
	o.fog = CalcFog( vWorldPosition, vProjPos, g_iFogType );
#endif

	// Normal = (Pos - Eye origin)
	float3 vWorldNormal = normalize( vWorldPosition.xyz - g_cEyeOrigin.xyz );
	o.vWorldNormal.xyz = vWorldNormal.xyz;

	// Tangent & binormal
	/*
	float3 vWorldBinormal = normalize( cross( vWorldNormal.xyz, vEyeSocketLeftVector.xyz ) );
	o.vWorldBinormal.xyz = vWorldBinormal.xyz * 0.5f + 0.5f;

	float3 vWorldTangent = normalize( cross( vWorldBinormal.xyz, vWorldNormal.xyz ) );
	o.vWorldTangent.xyz = vWorldTangent.xyz;
	//*/

	//*
	float3 vWorldTangent = normalize( cross( vEyeSocketUpVector.xyz, vWorldNormal.xyz ) );
	o.vWorldTangent.xyz = vWorldTangent.xyz;

	float3 vWorldBinormal = normalize( cross( vWorldNormal.xyz, vWorldTangent.xyz ) );
	o.vWorldBinormal.xyz = vWorldBinormal.xyz * 0.5f + 0.5f;
	//*/

	float3 vWorldViewVector = normalize (vWorldPosition.xyz - cEyePos.xyz);
	o.vTangentViewVector.xyz = Vec3WorldToTangentNormalized (vWorldViewVector.xyz, vWorldNormal.xyz, vWorldTangent.xyz, vWorldBinormal.xyz);

	// AV - I think this will effectively make the eyeball less rounded left to right to help vertext lighting quality
	// AV - Note: This probably won't look good if put on an exposed eyeball
  	//float vNormalDotSideVec = -dot( vWorldNormal, g_vEyeballUp ) * 0.5f;
  	float vNormalDotSideVec = -dot( vWorldNormal, vEyeSocketLeftVector) * 0.5f;
	float3 vBentWorldNormal = normalize(vNormalDotSideVec * vEyeSocketLeftVector + vWorldNormal);

	// Compute vertex lighting
	o.cVertexLight.a = 0.0f; //Only used for flashlight pass
	o.cVertexLight.rgb = DoLightingUnrolled( vWorldPosition, vBentWorldNormal, float3(0.0f, 0.0f, 0.0f), bStaticLight, bDynamicLight, g_bHalfLambert, nNumLights );

	// Only interpolate ambient light for TF NPR lighting
	bool bDoDiffuseWarp = LIGHTWARPTEXTURE ? true : false;
	if ( bDoDiffuseWarp )
	{
		if( bDynamicLight )
		{
			o.cVertexLight.rgb = AmbientLight( vBentWorldNormal.xyz );
		}
		else
		{
			o.cVertexLight.rgb = float3( 0.0f, 0.0f, 0.0f );
		}
	}

// NOTE: it appears that o.vLightFalloffCosine01 and o.vLightFalloffCosine23 are filled in even if
// we don't have enough lights, meaning we pass garbage to the pixel shader which then throws it away

	// Light falloff for first two local lights
	o.vLightFalloffCosine01.x = VertexAttenInternal( vWorldPosition.xyz, 0 );
	o.vLightFalloffCosine01.y = VertexAttenInternal( vWorldPosition.xyz, 1 );
	o.vLightFalloffCosine01.z = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 0, g_bHalfLambert );
	o.vLightFalloffCosine01.w = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 1, g_bHalfLambert );

	// Light falloff for next two local lights
	o.vLightFalloffCosine23.x = VertexAttenInternal( vWorldPosition.xyz, 2 );
	o.vLightFalloffCosine23.y = VertexAttenInternal( vWorldPosition.xyz, 3 );
	o.vLightFalloffCosine23.z = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 2, g_bHalfLambert );
	o.vLightFalloffCosine23.w = CosineTermInternal( vWorldPosition.xyz, vWorldNormal.xyz, 3, g_bHalfLambert );

	// Texture coordinates set by artists for ambient occlusion
	o.vAmbientOcclUv_fallbackCorneaUv.xy = v.vTexCoord0.xy;

	// Cornea uv for ps.2.0 fallback
	float2 vCorneaUv; // Note: Cornea texture is a cropped version of the iris texture
	vCorneaUv.x = dot( g_vIrisProjectionU, float4( vWorldPosition, 1.0f ) );
	vCorneaUv.y = dot( g_vIrisProjectionV, float4( vWorldPosition, 1.0f ) );
	float2 vSphereUv = ( vCorneaUv.xy * 0.5f ) + 0.25f;
	o.vAmbientOcclUv_fallbackCorneaUv.wz = vCorneaUv.xy; // Note: wz unpacks faster than zw in ps.2.0!

	// Step on the vertex light interpolator for the flashlight tex coords
	bool bFlashlight = ( FLASHLIGHT != 0 ) ? true : false;
	o.vTangentViewVector.w = 0.0f;
	if ( bFlashlight )
	{
		o.cVertexLight.x = dot( g_vFlashlightMatrixRow1.xyzw, float4( vWorldPosition, 1.0f ) );
		o.cVertexLight.y = dot( g_vFlashlightMatrixRow2.xyzw, float4( vWorldPosition, 1.0f ) );
		o.cVertexLight.z = dot( g_vFlashlightMatrixRow3.xyzw, float4( vWorldPosition, 1.0f ) );
		o.cVertexLight.w = dot( g_vFlashlightMatrixRow4.xyzw, float4( vWorldPosition, 1.0f ) );

		o.vTangentViewVector.w = saturate( dot( vBentWorldNormal.xyz, normalize ( g_vFlashlightPosition.xyz - vWorldPosition.xyz ) ) ); // Flashlight N.L with modified normal

		// Half lambert version
		//o.cVertexLight.z = dot( vBentWorldNormal.xyz, normalize ( g_vFlashlightPosition.xyz - vWorldPosition.xyz ) ); // Flashlight N.L with modified normal
		//o.cVertexLight.z = ( o.cVertexLight.z * 0.5f ) + 0.5f;
		//o.cVertexLight.z *= o.cVertexLight.z;
	}

	return o;
}