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
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;
|
|
}
|