2012-06-23 13 views
5

In WPF OuterGlowBitmapEffect non è più supportato né reso da Net4.0. DropShadow ha un po 'in comune e non è accettabile nel mio caso. Il mio obiettivo iniziale è quello di creare uno sfondo bianco sfocato per il testo ClearType nero sulla finestra di AeroGlass per renderlo più leggibile su scene buie. Ho iniziato a giocare con fx e HLSL. È piuttosto interessante e potente ma non riesco ancora ad avvicinarmi a OuterGlowBitmapEffect.Come rendere Outer Glow Effect usando HLSL?

La mia versione fittizia corrente che riflette l'idea:

sampler2D Sampler : register(S0); 
#define PI 3.14f 
float4 main(float2 uv : TEXCOORD) : COLOR 
{ 
    float4 px = tex2D(Sampler, uv); 

    /* 
    if (px.a > 0.9) 
    { 
     return px; 
    } 
    */ 

    const float d = 3; 

    int cnt = 0; 
    float a = 0; 
    for (float x = -0.1*d; x < 0.1*d; x += 0.05*d) 
    { 
     a += tex2D(Sampler, uv + float2(x, 0)).a; 
     a += tex2D(Sampler, uv + float2(0, x)).a; 
     a += tex2D(Sampler, uv + x).a; 
     cnt += 3; 
    } 
    a /= cnt; 

    float4 s = a; 

    float4 r = float4(px.rgb*px.a + s.rgb*(1-px.a), max(px.a, a)); 

    return r; 
} 

BTW: posso ottenere una fonte HLSL per DropShadowEffect da usare come riferimento? Qualcuno può indicarmi un algoritmo OuterGlowEffect in qualsiasi lingua?

NOTA: la barra del titolo Windows 7 Aero Glass ha tale effetto da rendere il titolo più leggibile! Questo è esattamente ciò che mi piacerebbe avere per il mio testo su altre parti della finestra (DwmExtendFrameIntoClientArea applicato) Aero Glass Window Title

risposta

3

L'idea generale è di rendere il testo bianco prima, quindi sfocare. E infine usare il testo bianco sfocato come immagine di sfondo per il testo nero.

Lo shader è una sfocatura corretta, ma è alquanto inefficiente (esempi ridondanti per x = 0, ad esempio). È possibile creare una buona sfocatura di grandi dimensioni con due passaggi: uno orizzontale e uno sfocato verticale. codice HLSL:

float4 PS_BlurHorizontal(float2 Tex : TEXCOORD0) : COLOR0 
{ 
    float Color = 0.0f; 

    Color += tex2D(sampler, float2(Tex.x - 3.0*blurSizeX, Tex.y)) * 0.09f; 
    Color += tex2D(sampler, float2(Tex.x - 2.0*blurSizeX, Tex.y)) * 0.11f; 
    Color += tex2D(sampler, float2(Tex.x - blurSizeX, Tex.y)) * 0.18f; 
    Color += tex2D(sampler, Tex) * 0.24f; 
    Color += tex2D(sampler, float2(Tex.x + blurSizeX, Tex.y)) * 0.18f; 
    Color += tex2D(sampler, float2(Tex.x + 2.0*blurSizeX, Tex.y)) * 0.11f; 
    Color += tex2D(sampler, float2(Tex.x + 3.0*blurSizeX, Tex.y)) * 0.09f; 

    return Color; 
} 

float4 PS_BlurVertical(float2 Tex : TEXCOORD0) : COLOR0 
{ 
    float Color = 0.0f; 

    Color += tex2D(sampler, float2(Tex.x, Tex.y - 3.0*blurSizeY)) * 0.09f; 
    Color += tex2D(sampler, float2(Tex.x, Tex.y - 2.0*blurSizeY)) * 0.11f; 
    Color += tex2D(sampler, float2(Tex.x, Tex.y - blurSizeY)) * 0.18f; 
    Color += tex2D(sampler, Tex) * 0.24f; 
    Color += tex2D(sampler, float2(Tex.x, Tex.y + blurSizeY)) * 0.18f; 
    Color += tex2D(sampler, float2(Tex.x, Tex.y + 2.0*blurSizeY)) * 0.11f; 
    Color += tex2D(sampler, float2(Tex.x, Tex.y + 3.0*blurSizeY)) * 0.09f; 

    return Color; 
} 
// weights: 0.09 + 0.11 + 0.18 + 0.24 + 0.18 + 0.11 + 0.9 = 1 
// By default, weigths are symmetrical and sum up to 1, 
// but they don't necessarily have to. 
// You can change the weights to create more fancy results. 

Questi due passaggi 7-campione simulano un 7x7 sfocatura gaussiana (14 campioni anziché 49). È possibile utilizzare più campioni per migliorare il risultato (rendere più sfocato più ampio) o semplicemente regolare i pesi per creare un aspetto più morbido.

+0

Sembra fantastico! Ma è generalmente impossibile avere shader multi-pass per WPF BitmapEffect :(ci sono alcuni suggerimenti e descrizioni: http://www.codeproject.com/Articles/71617/Getting-Started-with-Shader-Effects-in-WPF Per ora le prestazioni non sono un problema dal momento che una piccola quantità di testo e una piccola quantità di bitmap da renderizzare. Sarebbe fantastico se fosse possibile aiutare a creare una funzione single-pass per il rendering di testo con sfondo sfocato. –

+2

non hai per creare uno shader multi-pass, è necessario: 1. sfocare l'immagine originale con 'PS_BlurHorizontal', 2. sfocare il risultato del passaggio precedente con' PS_BlurVertical'. se è necessario un singolo passaggio, prendere un'occhiata a questo: http://code.google.com/p/sbip/source/browse/trunk/SBIPFramework/Resources/GaussianBlur.fx?r=76 – miloszmaki