【问题标题】:How to make Outer Glow Effect using HLSL?如何使用 HLSL 制作外发光效果?
【发布时间】:2012-06-23 21:21:53
【问题描述】:

在 WPF OuterGlowBitmapEffect 中,Net4.0 不再支持也不呈现。 DropShadow 有一些共同点,在我的情况下是不可接受的。我最初的目标是在 AeroGlass 窗口上为黑色 ClearType 文本制作白色模糊背景,使其在黑暗场景中更具可读性。我开始玩 fx 和 HLSL。它非常有趣且功能强大,但我仍然无法接近 OuterGlowBitmapEffect。

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

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;
}

顺便说一句:我可以获得 DropShadowEffect 的 HLSL 源以将其用作参考吗?有人能指出任何语言的 OuterGlowEffect 算法吗?

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

【问题讨论】:

    标签: wpf hlsl


    【解决方案1】:

    总体思路是先渲染白色文字,再模糊。最后使用模糊的白色文本作为黑色文本的背景图像。

    您的着色器是正确的模糊,但它的效率有些低(例如 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 样本通道模拟 7x7 高斯模糊(14 个样本而不是 49 个)。您可以使用更多样本来改善结果(使模糊范围更广)或仅调整权重以创建更柔和的外观。

    【讨论】:

    • 听起来不错!但是通常不可能有 WPF BitmapEffect 的多通道着色器 :( 有一些提示和描述:codeproject.com/Articles/71617/… 现在性能不是问题,因为要渲染的文本量和位图数量很少。它会如果你能帮助创建一个单通道函数来渲染背景模糊的文本,那就太好了。
    • 你不必创建多通道着色器,你要做的是:1. 用PS_BlurHorizontal 模糊原始图像,2. 用PS_BlurVertical 模糊上一步的结果.如果您需要单次通过,请查看:code.google.com/p/sbip/source/browse/trunk/SBIPFramework/…