You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
5.0 KiB
148 lines
5.0 KiB
//========== Copyright (c) Valve Corporation, All rights reserved. ==========//
|
|
|
|
// STATIC: "FLATTEN_STATIC_CONTROL_FLOW" "0..1" [vs20] [PC]
|
|
// STATIC: "FLATTEN_STATIC_CONTROL_FLOW" "0..0" [CONSOLE]
|
|
|
|
// DYNAMIC: "COMPRESSED_VERTS" "0..1"
|
|
// DYNAMIC: "SKINNING" "0..1"
|
|
// DYNAMIC: "NUM_LIGHTS" "0..2" [vs20] [PC]
|
|
// DYNAMIC: "NUM_LIGHTS" "0..0" [vs20] [CONSOLE]
|
|
|
|
// If using static control flow on Direct3D, we should use the NUM_LIGHTS=0 combo
|
|
// SKIP: ( $FLATTEN_STATIC_CONTROL_FLOW == 0 ) && ( $NUM_LIGHTS > 0 ) [vs20] [PC]
|
|
|
|
// Includes
|
|
#include "common_vs_fxc.h"
|
|
|
|
// Globals
|
|
const float g_flUVScale : register( SHADER_SPECIFIC_CONST_0 );
|
|
const float3 g_vUVProjOffset : register( SHADER_SPECIFIC_CONST_1 );
|
|
const float3 g_vBBMin : register( SHADER_SPECIFIC_CONST_2 );
|
|
const float3 g_vBBMax : register( SHADER_SPECIFIC_CONST_3 );
|
|
|
|
// Structs
|
|
struct VS_INPUT
|
|
{
|
|
float4 vPos : POSITION; // Position
|
|
float4 vNormal : NORMAL; // Normal
|
|
float4 vBoneWeights : BLENDWEIGHT; // Skin weights
|
|
float4 vBoneIndices : BLENDINDICES; // Skin indices
|
|
float4 vClosestSurfaceDir : TEXCOORD0;
|
|
float4 vTangent : TANGENT;
|
|
};
|
|
|
|
struct VS_OUTPUT
|
|
{
|
|
float4 vProjPosition : POSITION; // Projection-space position
|
|
float4 vWorldNormal : TEXCOORD0; // w is proj. z coord (for depth stuff)
|
|
float4 vClosestSurfaceDir : TEXCOORD1;
|
|
float4 vWorldPos : TEXCOORD2; // w is proj. w coord
|
|
float4 vUV0 : TEXCOORD3;
|
|
float4 vUV1 : TEXCOORD4;
|
|
float4 vLightAtten : TEXCOORD5;
|
|
float3 vAmbient : TEXCOORD6;
|
|
};
|
|
|
|
float3 CubeUV( float3 vWorldPosition, float3 vWorldNormal, float3 vUVSpacePos )
|
|
{
|
|
// Generate texcoords for a cubemap wrapped around the ice sculpture's bounding box
|
|
float3 vDir = normalize( lerp( normalize( vUVSpacePos.xyz ), vWorldNormal.xyz, 0.5 ) );
|
|
float3 tMins = ( g_vBBMin - vWorldPosition ) / vDir;
|
|
float3 tMaxs = ( g_vBBMax - vWorldPosition ) / vDir;
|
|
tMaxs = max( tMaxs, tMins ); // weed out negative t's per axis
|
|
float t = min( tMaxs.x, min( tMaxs.y, tMaxs.z ) );
|
|
float3 vIntersectionPos = vWorldPosition + t * vDir;
|
|
// transform into unit cube
|
|
float3 vCubeUV = vIntersectionPos;
|
|
vCubeUV -= 0.5*( g_vBBMax + g_vBBMin );
|
|
vCubeUV /= 0.5*( g_vBBMax - g_vBBMin );
|
|
vCubeUV = normalize( vCubeUV );
|
|
return vCubeUV;
|
|
}
|
|
|
|
|
|
// Main
|
|
VS_OUTPUT main( const VS_INPUT i )
|
|
{
|
|
VS_OUTPUT o;
|
|
|
|
float4 vObjPosition = i.vPos;
|
|
float4 vObjTangent = i.vTangent;
|
|
float3 vObjNormal;
|
|
DecompressVertex_Normal( i.vNormal, vObjNormal );
|
|
|
|
// Transform the position and normal
|
|
float3 vWorldPosition = { 0.0f, 0.0f, 0.0f };
|
|
float3 vWorldNormal = { 0.0f, 0.0f, 0.0f };
|
|
float3 vWorldTangent = { 0.0f, 0.0f, 0.0f };
|
|
float3 vWorldBinormal = { 0.0f, 0.0f, 0.0f };
|
|
SkinPositionNormalAndTangentSpace( SKINNING ? true : false,
|
|
vObjPosition, vObjNormal.xyz, vObjTangent.xyzw,
|
|
i.vBoneWeights, i.vBoneIndices,
|
|
vWorldPosition, vWorldNormal, vWorldTangent, vWorldBinormal );
|
|
vWorldNormal.xyz = normalize( vWorldNormal.xyz );
|
|
|
|
o.vWorldNormal.xyz = vWorldNormal.xyz;
|
|
o.vWorldPos.xyz = vWorldPosition.xyz;
|
|
|
|
// Transform into projection space
|
|
float4 vProjPosition = mul( float4( vWorldPosition, 1.0f ), cViewProj );
|
|
|
|
o.vProjPosition = vProjPosition;
|
|
o.vWorldNormal.w = vProjPosition.z;
|
|
o.vWorldPos.w = vProjPosition.w;
|
|
|
|
#ifdef _PS3
|
|
// Account for OpenGL's flipped y coordinate and expanded z range [-1,1] instead of [0,1]
|
|
o.vProjPosition.y = -o.vProjPosition.y;
|
|
o.vProjPosition.z = 2.0f * o.vProjPosition.z - o.vProjPosition.w;
|
|
#endif // _PS3
|
|
|
|
// Seamless texturing UV projections
|
|
float3 vUVSpacePos = vWorldPosition.xyz - g_vUVProjOffset.xyz;
|
|
o.vUV0.xy = g_flUVScale * vUVSpacePos.yz;
|
|
o.vUV0.wz = g_flUVScale * vUVSpacePos.xz;
|
|
o.vUV1.xy = g_flUVScale * vUVSpacePos.xy;
|
|
|
|
// Cubemap UV gen
|
|
//o.vCubeUVW.xyz = CubeUV( vWorldPosition, vWorldNormal, vUVSpacePos );
|
|
|
|
// Screen-space texcoord
|
|
float2 vScreenPos = float2( 0.5, -0.5 ) * vProjPosition.xy + 0.5 * vProjPosition.w;
|
|
o.vUV1.wz = vScreenPos;
|
|
|
|
// Dynamic light attenuation factors
|
|
#if ( defined( SHADER_MODEL_VS_2_0 ) && FLATTEN_STATIC_CONTROL_FLOW )
|
|
{
|
|
o.vLightAtten.xyzw = float4(0,0,0,0);
|
|
#if ( NUM_LIGHTS > 0 )
|
|
o.vLightAtten.x = GetVertexAttenForLight( vWorldPosition, 0, false );
|
|
#endif
|
|
#if ( NUM_LIGHTS > 1 )
|
|
o.vLightAtten.y = GetVertexAttenForLight( vWorldPosition, 1, false );
|
|
#endif
|
|
#if ( NUM_LIGHTS > 2 )
|
|
o.vLightAtten.z = GetVertexAttenForLight( vWorldPosition, 2, false );
|
|
#endif
|
|
#if ( NUM_LIGHTS > 3 )
|
|
o.vLightAtten.w = GetVertexAttenForLight( vWorldPosition, 3, false );
|
|
#endif
|
|
}
|
|
#else
|
|
{
|
|
o.vLightAtten.x = GetVertexAttenForLight( vWorldPosition, 0 );
|
|
o.vLightAtten.y = GetVertexAttenForLight( vWorldPosition, 1 );
|
|
o.vLightAtten.z = GetVertexAttenForLight( vWorldPosition, 2 );
|
|
o.vLightAtten.w = GetVertexAttenForLight( vWorldPosition, 3 );
|
|
}
|
|
#endif
|
|
|
|
// Ambient light
|
|
o.vAmbient = AmbientLight( vWorldNormal );
|
|
|
|
// Closest surface's direction and distance, for contact shadowing
|
|
o.vClosestSurfaceDir.xyz = i.vClosestSurfaceDir.xyz;
|
|
o.vClosestSurfaceDir.w = length( i.vClosestSurfaceDir.xyz );
|
|
|
|
return o;
|
|
}
|