// #define ENABLE_DX10
// EFFECT DEFINITIONS; CAN BE TOGGLED BY COMMENTING OR DELETING LINE
#define ENABLE_EMBOSS
#define ENABLE_BAR
#define ENABLE_GRADIENT
#define ENABLE_SPOTLIGHT
// END EFFECT DEFINITIONS
#define SPOTLIGHT_COLOR float4(.1,.1,.1,0);
#define BASELINE -1./2.
#define MAG max(-track_magnitude.r, track_magnitude.g)
texture tex : WAVEFORMDATA;
sampler sTex = sampler_state {
Texture = (tex);
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
AddressU = Clamp;
};
struct VS_IN {
float2 pos : POSITION;
float2 tc : TEXCOORD0;
};
struct PS_IN {
float4 pos : SV_POSITION;
float2 tc : TEXCOORD0;
};
float4 backgroundColor : BACKGROUNDCOLOR;
float4 highlightColor : HIGHLIGHTCOLOR;
float4 selectionColor : SELECTIONCOLOR;
float4 textColor : TEXTCOLOR;
float cursorPos : CURSORPOSITION;
bool cursorVisible : CURSORVISIBLE;
float seekPos : SEEKPOSITION;
bool seeking : SEEKING;
float4 replayGain : REPLAYGAIN; // album gain/peak, track gain/peak
float2 viewSize : VIEWPORTSIZE;
bool horizontal : ORIENTATION;
bool flipped : FLIPPED;
bool shade_played : SHADEPLAYED;
float3 track_magnitude : TRACKMAGNITUDE;
/* VERTEX SHADER, SAME FOR ALL */
PS_IN VS(VS_IN input) {
PS_IN output = (PS_IN)0;
float2 half_pixel = float2(1,-1) / viewSize;
output.pos = float4(input.pos - half_pixel, 0, 1);
if (horizontal) output.tc = float2((input.tc.x + 1.0) / 2.0, input.tc.y);
else output.tc = float2((-input.tc.y + 1.0) / 2.0, input.tc.x);
if (flipped) output.tc.x = 1.0 - output.tc.x;
return output;
}
// END VERTEX SHADER
/* MISCELLANEOUS FUNCTIONS */
bool is_outside(float2 tc) {
float4 minmaxrms = tex1D(sTex, tc.x);
minmaxrms.rgb -= 0.5 * minmaxrms.a;
minmaxrms.rgb *= 1.0 + minmaxrms.a;
float below = tc.y - minmaxrms.r;
float above = tc.y - minmaxrms.g;
return (below < 0 || above > 0);
}
float apply_mirror(float2 tc) {
bool mirrored = tc.y < BASELINE;
float low_unscale = 21./10.;
float high_unscale = 23./35.;
if (mirrored) tc.y = (BASELINE - tc.y) * low_unscale;
else tc.y = (tc.y - BASELINE) * high_unscale;
return tc.y;
}
// END MISCELLANEOUS FUNCTIONS
/* FIRST PASS */
float4 evaluate(float2 tc, float cursorPos) {
bool played = cursorPos < tc.x;
float4 inside_color = played ? textColor : highlightColor;
float4 wave = is_outside(tc) ? backgroundColor : inside_color;
if (tc.x < 0.001) return saturate(wave)*(tc.x*1000);
if (tc.x > 0.999) return saturate(wave)*((1-tc.x)*1000);
return saturate(wave);
}
float4 emboss(float2 tc) {
float4 s11 = tex2D(sTex, tc + float2(-1.0f / viewSize.x, -1.0 / viewSize.y));
float4 s22 = tex2D(sTex, tc);
float4 s33 = tex2D(sTex, tc);
s11.rgb = (s11.r + s11.g + s11.b);
s22.rgb = (s22.r + s22.g + s22.b) * -.5;
s33.rgb = (s22.r + s22.g + s22.b) * .4;
return s11 + s22 + s33;
}
float4 PS(PS_IN input) : SV_Target {
input.tc.y = lerp(0,MAG/0.95,apply_mirror(input.tc.y));
float4 c = saturate(evaluate(input.tc,cursorPos));
/* EMBOSSING ONLY RUNS IF ENABLE_EMBOSS IS ENABLED AT TOP OF FILE */
#ifdef ENABLE_EMBOSS
c += (c * emboss(input.tc));
#endif
return c;
}
// END FIRST PASS
// BAR
// ONLY RUNS IF ENABLE_BAR IS DEFINED AT TOP OF FILE
float4 bar(float pos, float2 tc, float4 fg, float4 bg, float width) {
float dist = abs(pos - tc.x);
return (dist > width) ? bg : lerp(fg,bg,smoothstep(0,width,dist));
}
float4 PS_Bar(PS_IN input) : SV_Target {
float dx, dy;
if (horizontal) { dx = 1/viewSize.x; dy = 1/viewSize.y; }
else { dx = 1/viewSize.y; dy = 1/viewSize.x; }
float width = 1.5 * dx;
input.tc.y = lerp(0,MAG/0.95,apply_mirror(input.tc.y));
float4 c = 0;
if (cursorVisible) c = bar(cursorPos, input.tc, selectionColor, 0, width);
if (seeking) c = bar(seekPos, input.tc, selectionColor, c, width);
return is_outside(input.tc) ? backgroundColor : c;
}
// END BAR
// GRADIENT
// ONLY RUNS IF ENABLE_GRADIENT IS DEFINED AT TOP OF FILE
float4 PS_Gradient(PS_IN input) : SV_Target {
bool mirrored = input.tc.y < BASELINE;
input.tc.y = apply_mirror(input.tc);
float4 c = 0;
c.a += mirrored ? lerp(0.35,0.01,input.tc.y) : lerp(0.6,1.0,input.tc.y);
return c;
}
// END GRADIENT
// SPOTLIGHT
// ONLY RUNS IF ENABLE_SPOTLIGHT IS DEFINED AT TOP OF FILE
float4 PS_Spotlight(PS_IN input) : SV_Target {
input.tc.y = lerp(0,MAG/0.95,apply_mirror(input.tc.y));
float4 c = SPOTLIGHT_COLOR;
c.a = lerp(1,.75,input.tc.x);
// c.a = lerp(.75*c.a,c.a,input.tc.y);
return is_outside(input.tc) ? backgroundColor : c;
}
// END SPOTLIGHT
// SHADERS
// DIRECTX 10 SHADERS
#define DX10_GEOMETRYSHADER SetGeometryShader(0);
#define DX10_VERTEXSHADER SetVertexShader(CompileShader(vs_4_0,VS()));
#define DX10_PIXELSHADER(ps) SetPixelShader(CompileShader(ps_4_0,ps));
// END DIRECTX 10 SHADERS
// DIRECTX 9 SHADERS
#define DX9_VERTEXSHADER VertexShader = compile vs_2_0 VS();
#define DX9_PIXELSHADER(ps) PixelShader = compile ps_2_0 ps;
// END DIRECTX 9 SHADERS
#ifdef ENABLE_DX10
#define SHADERS(p) DX10_GEOMETRYSHADER DX10_VERTEXSHADER DX10_PIXELSHADER(p)
#else
#define SHADERS(p) DX9_VERTEXSHADER DX9_PIXELSHADER(p)
#endif
// END SHADERS
// BLENDING OPTIONS
#define BLENDENABLE AlphaBlendEnable = true;
#define SRCBLEND(sb) SrcBlend = sb;
#define DESTBLEND(db) DestBlend = db;
#define BLENDOP(op) BlendOp = op;
#define BLEND(s,d,o) BLENDENABLE SRCBLEND(s) DESTBLEND(d) BLENDOP(o)
// END BLENDING OPTIONS
technique Render
{
pass main {
SHADERS(PS())
}
#ifdef ENABLE_BAR
pass bar {
SHADERS(PS_Bar())
BLEND(SrcAlpha,DestAlpha,ADD)
}
#endif
#ifdef ENABLE_SPOTLIGHT
pass spotlight {
SHADERS(PS_Spotlight())
BLEND(SrcAlpha,SrcAlpha,ADD)
}
#endif
#ifdef ENABLE_GRADIENT
pass gradient {
SHADERS(PS_Gradient())
BLEND(SrcAlpha,SrcAlpha,ADD)
}
#endif
}