zao / foo_wave_seekbar

A foobar2000 UI seekbar element displaying the playing waveform.
http://www.foobar2000.org/components/view/foo_wave_seekbar
Other
85 stars 7 forks source link

0.2.45 displays the shader differently #30

Closed tophf closed 10 years ago

tophf commented 10 years ago

The shader below is displayed differently after updating from 0.2.40 to 0.2.45 - instead of being centered vertically ok only the lower half is drawn at the top: pic

Texture1D tex : WAVEFORMDATA;

SamplerState sTex
{
    Filter = MIN_MAG_MIP_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, track gain, album peak, track peak
float2 viewportSize : VIEWPORTSIZE;
bool horizontal : ORIENTATION;
bool shade_played : SHADEPLAYED;

PS_IN VS( VS_IN input )
{
    PS_IN output = (PS_IN)0;

    float2 half_pixel = float2(1,-1) / viewportSize;
    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);

    return output;
}

float4 bar( float pos, float2 tc, float4 fg, float4 bg, float width, bool show )
{
    float dist = abs(pos - tc.x);
    float4 c = (show && dist < width)
        ? lerp(fg, bg, smoothstep(0, width, dist))
        : bg;
    return c;
}

float4 evaluate(float4 bg, float4 fg, float factor)
{
    return saturate(lerp(bg, fg, factor));
}

float4 played( float pos, float2 tc, float4 bg, float factor)
{
    float4 c = bg;
    if (pos > tc.x)
        c = evaluate(backgroundColor, highlightColor, factor);
    return c;
}

float RMSfactor( float2 tc, float border )
{
    // alpha 1 indicates biased texture
    float4 minmaxrms = tex.Sample(sTex, tc.x);
    if (replayGain.g != -1000) {
        minmaxrms.rgb *= pow(10,(replayGain.g) / 20) * 1.8; //use track gain
    } else if (replayGain.r != -1000) {
        minmaxrms.rgb *= pow(10,(replayGain.r) / 20) * 1.8; //use album gain
    } else {
        minmaxrms.rgb *= 0.9 + minmaxrms.a;
    }

    float belowWave = tc.y + border - minmaxrms.r;
    float aboveWave = tc.y - border - minmaxrms.g;
    float factorWave = min(abs(belowWave), abs(aboveWave));
    bool insideWave = (belowWave > 0 && aboveWave < 0);

    float diffRms = abs(tc.y) - border - minmaxrms.b;
    float factorRms = abs(diffRms);
    bool insideRms = diffRms < 0;

    float factor = insideRms ? (0.5 + 0.5 * saturate(factorRms / border / 2)): 0.5;
    factor = insideWave ? (factor * saturate(factorWave / border / 2)) : 0.0;

    return factor;
}

float4 PS( PS_IN input ) : SV_Target
{
    float dx, dy;
    if (horizontal)
    {
        dx = 1/viewportSize.x;
        dy = 1/viewportSize.y;
    }
    else
    {
        dx = 1/viewportSize.y;
        dy = 1/viewportSize.x;
    }
    float seekWidth = 2.5 * dx;
    float positionWidth = 2.5 * dx;

    float factor = RMSfactor(input.tc, 2.5 * dy);

    float4 c0 = evaluate(backgroundColor, textColor, factor);
    if (shade_played)
        c0 = played(cursorPos, input.tc, c0, factor);
    c0 = bar(cursorPos, input.tc, selectionColor, c0, positionWidth, cursorVisible);
    c0 = bar(seekPos, input.tc, selectionColor, c0, seekWidth, seeking );
    return c0;
}

technique10 Render10
{
    pass P0
    {
        SetGeometryShader( 0 );
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
    }
}

technique Render9
{
    pass
    {
        VertexShader = compile vs_2_0 VS();
        PixelShader = compile ps_2_0 PS();
    }
}
zao commented 10 years ago

Your effect was always broken on any GPU that didn't do 32-bit per channel floating point textures. For less capable cards the component not only supported R32G32B32A32F but also R10G10B10A2 and R8G8B8A8 integer textures. 0.2.45 removed floating point and 10-bit textures leaving just 8-bit as it's good enough for pretty much any content. Common to both of those is that their range is only positive numbers, interpreted when shading as [0..1] while the floating point texture is [-1..1]. The stock effect has code to fix up this bias and it seems that whoever wrote your effect stripped out the unbias operation.

// alpha 1 indicates biased texture
float4 minmaxrms = tex1D(sTex, tc.x);
minmaxrms.rgb -= 0.5 * minmaxrms.a;
minmaxrms.rgb *= 1.0 + minmaxrms.a;