#include "globals.h" sampler2D tex : register(s0); //#define uniform float4 colorBias; uniform float4 throttleFactor; // .x = alpha cutoff, .y = alpha boost (clamp) struct VS_INPUT { float4 pos : POSITION; float4 scaleRotLife : TEXCOORD0; // transform matrix float2 disp : TEXCOORD1; // .xy = corner, either (0,0), (1,0), (0,1), or (1,1) float4 color0: COLOR0; float4 color1: COLOR1; }; struct VS_OUTPUT { float4 pos : POSITION; float3 uvFog : TEXCOORD0; float4 color : COLOR0; }; float4 rotScale( float4 scaleRotLife ) { float cr = cos( scaleRotLife.z ); float sr = sin( scaleRotLife.z ); float4 r; r.x = cr * scaleRotLife.x; r.y = -sr * scaleRotLife.x; r.z = sr * scaleRotLife.y; r.w = cr * scaleRotLife.y; return r; } VS_OUTPUT vs( VS_INPUT input ) { VS_OUTPUT o; float4 pos = float4( input.pos.xyz, 1 ); float2 disp = input.disp.xy * 2 - 1; // -1..1 input.scaleRotLife *= float4( 1/256.0f, 1/256.0f, 2 * 3.1415926f / 32767, 1 / 32767.0f ); float4 rs = rotScale( input.scaleRotLife ); pos += G.ViewRight * dot( disp, rs.xy ); pos += G.ViewUp * dot( disp, rs.zw ); o.pos = mul( G.ViewProjection, pos ); o.uvFog.xy = input.disp.xy; o.uvFog.y = 1 - o.uvFog.y; o.uvFog.z = (G.FogParams.z - o.pos.w) * G.FogParams.w; float t = max( 0, min(1, input.scaleRotLife.w ) ); o.color = lerp( input.color1, input.color0, t ); // alpha channel magic for particle throttling float2 cmp = o.color.aa < throttleFactor.xy; o.pos.xyz += cmp.xxx * (1e10f).xxx; // move the particle off-screen o.color.a = lerp( o.color.a, throttleFactor.y, cmp.y ); // if below threshold, alpha = threshold return o; } float4 psAdd( VS_OUTPUT input ) : COLOR0 // #0 { float4 color = tex2D( tex, input.uvFog.xy ); float4 result = float4( input.color.rgb + color.rgb + colorBias.rgb, color.a * input.color.a ); result.rgb = lerp( G.FogColor.rgb, result.rgb, saturate( input.uvFog.zzz ) ); return result; } float4 psMul( VS_OUTPUT input ) : COLOR0 // #1 { float4 color = tex2D( tex, input.uvFog.xy ); float4 result = input.color * color; result.rgb = lerp( G.FogColor.rgb, result.rgb, saturate( input.uvFog.zzz ) ); return result; }