2012-06-23 34 views
5

在WPF中,OuterGlowBitmapEffect不再被Net4.0支持或渲染。 DropShadow有一点共同点,在我的情况下是不可接受的。我最初的目标是在AeroGlass窗口上为黑色ClearType文本制作一个白色模糊的背景,以便在黑暗场景中使其更易读。我开始玩fx和HLSL。这是相当有趣和强大的,但我仍然无法接近OuterGlowBitmapEffect。如何使用HLSL制作外发光效果?

反映的想法我当前的虚拟版本:

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:我可以得到一个HLSL源DropShadowEffect使用它作为一个参考?有人可以用任何语言指向我的OuterGlowEffect算法吗?

注意:Windows 7 Aero Glass标题栏具有使标题更具可读性的效果!这正是我想要在窗口的其他部分(DwmExtendFrameIntoClientArea应用)我的文本Aero Glass Window Title

回答

3

一般的想法是先渲染白色文本,然后模糊它。最后使用模糊的白色文字作为黑色文字的背景图像。

您的着色器是一个正确的模糊,但它有点低效(例如对于x = 0的冗余样本)。您可以通过两次传递创建一个很好的大模糊:一个水平模糊和一个垂直模糊。 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. 

这两个7样本遍模拟7×7高斯模糊(14个样本,而不是49个)。您可以使用更多样本来改善结果(使模糊变宽)或者只是调整权重以创建更柔和的外观。

+0

听起来不错!但是对于WPF BitmapEffect来说,多通道着色器通常是不可能的:(有一些提示和说明:http://www.codeproject.com/Articles/71617/Getting-Started-with-Shader-Effects-in-WPF 现在性能不是问题,因为有少量的文本和少量的位图来渲染,如果你能帮助创建一个单通道函数来渲染具有背景模糊的文本,那将是非常好的。 –

+2

你没有创建一个多通道着色器,你要做的是: 1.用'PS_BlurHorizo​​ntal'模糊原始图像, 2.用'PS_BlurVertical'模糊上一步的结果 如果你需要一次通过,看看这个:http://code.google.com/p/sbip/source/browse/trunk/SBIPFramework/Resources/GaussianBlur.fx?r=76 – miloszmaki