Counter Strike : Global Offensive Source Code
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.
 
 
 
 
 
 

88 lines
3.2 KiB

//========== Copyright (c) Valve Corporation, All rights reserved. ==========//
#include "common_vs_fxc.h"
#include "spline_fxc.h"
const hlsl_float4x3 cModelView : register(SHADER_SPECIFIC_CONST_0);
const float4x4 cProj : register(SHADER_SPECIFIC_CONST_3);
const float g_MinPixelSize : register(SHADER_SPECIFIC_CONST_7);
const float g_Const8 : register(SHADER_SPECIFIC_CONST_8);
#define g_FlTilingMultiplier g_Const8.x
struct VS_INPUT
{
// This is all of the stuff that we ever use.
float4 vTint : COLOR;
float4 vParms : POSITION; // T V side_id
float4 vSplinePt0 : TEXCOORD0; // x y z rad
float4 vSplinePt1 : TEXCOORD1; // x y z rad
float4 vSplinePt2 : TEXCOORD2; // x y z rad
float4 vSplinePt3 : TEXCOORD3; // x y z rad
};
// VS_OUTPUT in a common file.
#include "common_splinerope_fxc.h"
#define P0 (v.vSplinePt0)
#define P1 (v.vSplinePt1)
#define P2 (v.vSplinePt2)
#define P3 (v.vSplinePt3)
VS_OUTPUT main( const VS_INPUT v )
{
VS_OUTPUT o;
// posrad.xyz is worldspace position and posrad.w is worldspace diameter.
float4 posrad = CatmullRomSpline( P0, P1, P2, P3, v.vParms.x );
// calculate projected position here so that we can figure out how much to bloat the diameter to avoid aliasing of the sort where you skip pixels in a segment.
{
// PERF FIXME!! This could be simplified quite a bit if this ever becomes a bottleneck. I feel dirty.
// Get the view-space position for two points that are posrad.w units away from each other horizontally.
float3 viewPos1 = mul4x3( float4( posrad.xyz, 1.0f ), cModelView );
float3 viewPos2 = viewPos1 + float3( posrad.w, 0.0f, 0.0f );
// Project both points.
float4 projPos1 = mul( float4( viewPos1, 1.0f ), cProj );
float4 projPos2 = mul( float4( viewPos2, 1.0f ), cProj );
// Get the distance of the two points from each other in normalized screen space.
float projectedDiameterInPixels = abs( ( projPos1.x / projPos1.w ) - ( projPos2.x / projPos2.w ) );
// Compare the distance between the two points to the minimum allowed to keep from skipping pixels and causing aliasing.
if ( projectedDiameterInPixels < g_MinPixelSize )
{
// Scale the radius in world space so that it is bigger than the required pixel size in screen space.
posrad.w *= ( g_MinPixelSize / projectedDiameterInPixels );
}
}
float3 v2p = float3( 0, 0, 1 );
v2p = posrad.xyz - cEyePos; // screen aligned
float3 tangent = DCatmullRomSpline3( P0, P1, P2, P3, v.vParms.x );
float3 ofs = normalize( cross( v2p, normalize( tangent ) ) );
posrad.xyz += ofs * ( posrad.w * ( v.vParms.z - .5 ) );
o.projPos = mul( float4(posrad.xyz, 1.0f), cViewProj );
#ifdef _PS3
// Account for OpenGL's flipped y coordinate and expanded z range [-1,1] instead of [0,1]
o.projPos.y = -o.projPos.y;
o.projPos.z = 2.0f * o.projPos.z - o.projPos.w;
#endif // _PS3
o.worldPos_projPosZ.xyz = posrad.xyz;
o.worldPos_projPosZ.w = o.projPos.z;
o.texCoord.xy = float2( 1.0f - v.vParms.z, v.vParms.y );
o.texCoord.y *= g_FlTilingMultiplier;
o.argbcolor = float4( v.vTint.rgb, v.vTint.a );
#if !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 )
{
o.fog = CalcFixedFunctionFog( posrad.xyz, 0 );
}
#endif
return o;
}