WPF内发光效果 [英] WPF Inner Glow Effect

查看:2913
本文介绍了WPF内发光效果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有谁知道如何使WPF中的内发光效果,而不会使用EX pression混合或去precated BitmapEffects?

样图:

例如,这里是一些XAML与图像和一些文本的按钮。我想这个按钮有一个内发光(不是外发光):

 <按钮单击=HandleDeleteRows风格={的StaticResource ButtonCellStyle}>
    < D​​ockPanel中>
        <图像风格={的StaticResource DeleteButtonImage}/>
        < TextBlock的风格={的StaticResource DeleteButtonCaption}/>
    < / DockPanel中>
< /按钮>
 

解决方案

虽然我简单的例子以上是由PompolutZ的回答解决,我是不是在一个位置,以覆盖控制的控制模板,我想的样式应用到在我的现实世界的例子 - 让我走上定义自己的作用,下面的说明这里

第1步 - 写一个HLSL .FX文件,会做你想要的效果。我放弃了灼热的太复杂,因为它需要的边缘检测。我决定去与标准颜色,亮度,伽玛,饱和度调整摆那是相当容易实现,而且会让我创造一些良好的视觉线索。他们是pretty的容易实现使用常识和仰视像素着色算法在线。

Col​​ourAdjust.fx

  sampler2D implicitInput:注册(S0);
浮动饱和度:寄存器(C0);
浮伽玛:注册(C1);
浮动亮度:注册(C2);
浮red_adjust:注册(C3);
浮green_adjust:注册(C4);
浮blue_adjust:注册(C5);

静态常量浮动max_gamma = 100;

FLOAT4主(FLOAT2 UV:TEXCOORD):COLOR
{
    的float4颜色= tex2D(implicitInput,UV);
    的float4结果;

    //应用灰阶饱和度下降
    浮灰= color.r * 0.3 + color.g * 0.59 + color.b * 0.11;
    result.r =(color.r  - 灰色)*饱和度+灰色;
    result.g =(color.g  - 灰色)*饱和度+灰色;
    result.b =(color.b  - 灰色)*饱和度+灰色;

    //应用Gamma调整(如果它不是约为0.5  - 这意味着没有调整)
    浮gammafactor =伽玛== 0? max_gamma:日志(伽马)/日志(0.5);
    result.r = POW(result.r,gammafactor);
    result.g = POW(result.g,gammafactor);
    result.b = POW(result.b,gammafactor);

    //应用线性亮度调节
    result.r + =亮度+ red_adjust;
    result.g + =亮度+ green_adjust;
    result.b + =亮度+ blue_adjust;

    //钳亮度调节结果范围0℃= VAL< = 1
    result.r =(result.r→1 1:(result.r℃,0:?result.r));
    result.g =(result.g→1 1:(result.g℃,0:?result.g));
    result.b =(result.b→1 1:(result.b℃,0:result.b));

    result.a = color.a;
    返回结果;
}
 

第2步 - 我不得不下载的的DirectX SDK ,这样我可以编译上面的HLSL code到PS文件,这是何等的使用WPF - 给我 Col​​ourAdjust.ps

 > > fxc.exe / T ps_2_0 / E PS /ColourAdjust.ps ColourAdjust.fx
 

第3步 - 编写将通过DependencyProperties暴露的效果参数ShaderEffect类。这里是 Col​​ourAdjustEffect.cs

 使用系统;
使用的System.Reflection;
使用System.Windows;
使用System.Windows.Media;
使用System.Windows.Media.Effects;

命名空间WPF.Utilities.UI
{
    公共类ColourAdjustEffect:ShaderEffect
    {
        私有静态PixelShader _pixelShader =新PixelShader(){UriSource =新的URI(包://应用:,,, /+ Assembly.GetExecutingAssembly()+;组件/效果/ ColourAdjust.ps)};
        公共静态只读的DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty(输入的typeof(ColourAdjustEffect),0);
        公共静态只读的DependencyProperty SaturationProperty = DependencyProperty.Register(饱和度的typeof(双),typeof运算(ColourAdjustEffect),新UIPropertyMetadata(1.0,PixelShaderConstantCallback(0),CoerceFactor));
        公共静态只读的DependencyProperty GammaProperty = DependencyProperty.Register(伽马的typeof(双),typeof运算(ColourAdjustEffect),新UIPropertyMetadata(0.5,PixelShaderConstantCallback(1),CoerceFactor));
        公共静态只读的DependencyProperty BrightnessAdjustmentProperty = DependencyProperty.Register(BrightnessAdjustment的typeof(双),typeof运算(ColourAdjustEffect),新UIPropertyMetadata(0.0,PixelShaderConstantCallback(2),CoerceBrightnessAdjustment));
        公共静态只读的DependencyProperty RedAdjustmentProperty = DependencyProperty.Register(RedAdjustment的typeof(双),typeof运算(ColourAdjustEffect),新UIPropertyMetadata(0.0,PixelShaderConstantCallback(3),CoerceBrightnessAdjustment));
        公共静态只读的DependencyProperty GreenAdjustmentProperty = DependencyProperty.Register(GreenAdjustment的typeof(双),typeof运算(ColourAdjustEffect),新UIPropertyMetadata(0.0,PixelShaderConstantCallback(4),CoerceBrightnessAdjustment));
        公共静态只读的DependencyProperty BlueAdjustmentProperty = DependencyProperty.Register(BlueAdjustment的typeof(双),typeof运算(ColourAdjustEffect),新UIPropertyMetadata(0.0,PixelShaderConstantCallback(5),CoerceBrightnessAdjustment));

        公共ColourAdjustEffect()
        {
            PixelShader = _pixelShader;

            UpdateShaderValue(InputProperty);
            UpdateShaderValue(SaturationProperty);
            UpdateShaderValue(GammaProperty);
            UpdateShaderValue(BrightnessAdjustmentProperty);
            UpdateShaderValue(RedAdjustmentProperty);
            UpdateShaderValue(GreenAdjustmentProperty);
            UpdateShaderValue(BlueAdjustmentProperty);
        }

        公共刷输入
        {
            {返回(刷)的GetValue(InputProperty); }
            集合{的SetValue(InputProperty,价值); }
        }

        ///&其中;总结> 0和1之间的值,以改变左图像中的颜色的量。 0是完全灰度,和1不受影响。默认值为1进行; /总结>
        大众双饱和
        {
            {返回(双)的GetValue(SaturationProperty); }
            集合{的SetValue(SaturationProperty,价值); }
        }

        ///&其中;总结> 0和1之间的一个值来改变灰阶的亮度,而不改变纯黑或真正的白色。
        /// 0班色调更接近真正的黑色,和1班的色调更接近真正的白色。默认值是0.5< /总结>
        大众双伽玛
        {
            {返回(双)的GetValue(GammaProperty); }
            集合{的SetValue(GammaProperty,价值); }
        }

        ///<总结> -1到1之间的值线性移动分别最终的结果更接近真实的黑色或白色的真实。
        /// -1将导致完全黑色图像,1将导致一个全白图像。默认值为0< /总结>
        大众双BrightnessAdjustment
        {
            {返回(双)的GetValue(BrightnessAdjustmentProperty); }
            集合{的SetValue(BrightnessAdjustmentProperty,价值); }
        }

        ///<总结> -1到1之间的值线性增加结果的红色成分。
        /// -1将删除所有红色的图像,+ 1将最大限度地发挥所有红色的形象。默认值为0< /总结>
        大众双RedAdjustment
        {
            {返回(双)的GetValue(RedAdjustmentProperty); }
            集合{的SetValue(RedAdjustmentProperty,价值); }
        }
        ///<总结> -1到1之间的值线性增加结果的绿色成分。
        /// -1将删除所有绿色的形象,+ 1将最大限度地发挥所有绿色的形象。默认值为0< /总结>
        大众双GreenAdjustment
        {
            {返回(双)的GetValue(GreenAdjustmentProperty); }
            集合{的SetValue(GreenAdjustmentProperty,价值); }
        }
        ///<总结> -1到1之间的值线性增加结果的蓝色成分。
        /// -1将删除所有蓝色的图像,+ 1将最大限度地发挥所有蓝色的形象。默认值为0< /总结>
        大众双BlueAdjustment
        {
            {返回(双)的GetValue(BlueAdjustmentProperty); }
            集合{的SetValue(BlueAdjustmentProperty,价值); }
        }

        私有静态对象CoerceFactor(DependencyObject的研发,目标价值)
        {
            双newFactor =(双)值;

            如果(newFactor< 0.0)返回0.0;
            如果(newFactor> 1.0)返回1.0;
            返回newFactor;
        }

        私有静态对象CoerceBrightnessAdjustment(DependencyObject的研发,目标价值)
        {
            双newFactor =(双)值;

            如果(newFactor< -1.0)返回-1.0;
            如果(newFactor> 1.0)返回1.0;
            返回newFactor;
        }
    }
}
 

第四步:用你的影响在XAML:

 < setter属性=效果>
    < Setter.Value>
        < UI:ColourAdjustEffect饱和度=0伽玛=0.6
                               BrightnessAdjustment = -  0.2RedAdjustment =0.04/>
    < /Setter.Value>
< /二传手>
 

因此​​,虽然我没有得到我的光晕效果,我有足够的参数与玩我能得到一个突出的视觉线索,这是我真正的目标。这里的一些事情,我能够用它做:

Does anyone know how to make an Inner Glow effect in WPF without using expression blend or deprecated BitmapEffects?

Sample image:

For instance, here is some xaml for a button with an image and some text. I want this button to have an inner glow (not an outer glow):

<Button Click="HandleDeleteRows" Style="{StaticResource ButtonCellStyle}">
    <DockPanel>
        <Image Style="{StaticResource DeleteButtonImage}" />
        <TextBlock Style="{StaticResource DeleteButtonCaption}" />
    </DockPanel>
</Button>

解决方案

While my simplified example above is solved by PompolutZ's answer, I wasn't in a position to override the control template of the control I wanted to apply the style to in my real world example - so I took to defining my own Effect, following instructions here.

Step 1 - Write an HLSL .FX file that will do your desired effect. I gave up on the glow as being too complicated, since it required edge detection. I decided to go with a slew of standard colour, brightness, gamma, and saturation adjustments that were fairly easy to implement and would let me create some good visual cues. They were pretty easy to implement using common sense and looking up pixel shading algorithms online.

ColourAdjust.fx:

sampler2D implicitInput : register(s0);
float saturation : register(c0);
float gamma : register(c1);
float brightness : register(c2);
float red_adjust : register(c3);
float green_adjust : register(c4);
float blue_adjust : register(c5);

static const float max_gamma = 100;

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 color = tex2D(implicitInput, uv);
    float4 result;

    // Apply greyscale desaturation
    float gray = color.r * 0.3 + color.g * 0.59 + color.b *0.11; 
    result.r = (color.r - gray) * saturation + gray;
    result.g = (color.g - gray) * saturation + gray;
    result.b = (color.b - gray) * saturation + gray;

    // Apply Gamma Adjustment (if it's not approximately 0.5 - which means no adjustment)
    float gammafactor = gamma == 0 ? max_gamma : log(gamma) / log(0.5);
    result.r = pow(result.r, gammafactor);
    result.g = pow(result.g, gammafactor);
    result.b = pow(result.b, gammafactor);

    //Apply linear brightness adjustment
    result.r += brightness + red_adjust;
    result.g += brightness + green_adjust;
    result.b += brightness + blue_adjust;

    //Clamp brightness adjustment result to bounds 0 <= val <= 1
    result.r = (result.r > 1 ? 1 : (result.r < 0 ? 0 : result.r));
    result.g = (result.g > 1 ? 1 : (result.g < 0 ? 0 : result.g));
    result.b = (result.b > 1 ? 1 : (result.b < 0 ? 0 : result.b));

    result.a = color.a;
    return result;
}

Step 2 - I had to download a local copy of the DirectX SDK so that I could compile the above HLSL code into a PS file, which is what's used by WPF - giving me ColourAdjust.ps.

> > fxc.exe /T ps_2_0 /E PS /ColourAdjust.ps ColourAdjust.fx

Step 3 - Write a ShaderEffect class that will expose the effect parameters via DependencyProperties. Here is ColourAdjustEffect.cs:

using System;
using System.Reflection;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;

namespace WPF.Utilities.UI
{
    public class ColourAdjustEffect : ShaderEffect
    {
        private static PixelShader _pixelShader = new PixelShader() { UriSource = new Uri("pack://application:,,,/" + Assembly.GetExecutingAssembly() + ";component/Effects/ColourAdjust.ps") };
        public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(ColourAdjustEffect), 0);
        public static readonly DependencyProperty SaturationProperty = DependencyProperty.Register("Saturation", typeof(double), typeof(ColourAdjustEffect), new UIPropertyMetadata(1.0, PixelShaderConstantCallback(0), CoerceFactor));
        public static readonly DependencyProperty GammaProperty = DependencyProperty.Register("Gamma", typeof(double), typeof(ColourAdjustEffect), new UIPropertyMetadata(0.5, PixelShaderConstantCallback(1), CoerceFactor));
        public static readonly DependencyProperty BrightnessAdjustmentProperty = DependencyProperty.Register("BrightnessAdjustment", typeof(double), typeof(ColourAdjustEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(2), CoerceBrightnessAdjustment));
        public static readonly DependencyProperty RedAdjustmentProperty = DependencyProperty.Register("RedAdjustment", typeof(double), typeof(ColourAdjustEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(3), CoerceBrightnessAdjustment));
        public static readonly DependencyProperty GreenAdjustmentProperty = DependencyProperty.Register("GreenAdjustment", typeof(double), typeof(ColourAdjustEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(4), CoerceBrightnessAdjustment));
        public static readonly DependencyProperty BlueAdjustmentProperty = DependencyProperty.Register("BlueAdjustment", typeof(double), typeof(ColourAdjustEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(5), CoerceBrightnessAdjustment));

        public ColourAdjustEffect()
        {
            PixelShader = _pixelShader;

            UpdateShaderValue(InputProperty);
            UpdateShaderValue(SaturationProperty);
            UpdateShaderValue(GammaProperty);
            UpdateShaderValue(BrightnessAdjustmentProperty);
            UpdateShaderValue(RedAdjustmentProperty);
            UpdateShaderValue(GreenAdjustmentProperty);
            UpdateShaderValue(BlueAdjustmentProperty);
        }

        public Brush Input
        {
            get { return (Brush)GetValue(InputProperty); }
            set { SetValue(InputProperty, value); }
        }

        /// <summary>A value between 0 and 1 to alter the amount of colour left in the image. 0 is entirely greyscale, and 1 is unaffected. Default is 1.</summary>
        public double Saturation
        {
            get { return (double)GetValue(SaturationProperty); }
            set { SetValue(SaturationProperty, value); }
        }

        /// <summary>A value between 0 and 1 to alter the lightness of the greyscale without altering true black or true white. 
        /// 0 shifts shades closer to true black, and 1 shifts shades closer to true white. Default is 0.5.</summary>
        public double Gamma
        {
            get { return (double)GetValue(GammaProperty); }
            set { SetValue(GammaProperty, value); }
        }

        /// <summary>A value between -1 and 1 to linearly move the end result closer to true black or true white respectively.
        /// -1 will result in an entirely black image, +1 will result in an entirely white image. Default is 0.</summary>
        public double BrightnessAdjustment
        {
            get { return (double)GetValue(BrightnessAdjustmentProperty); }
            set { SetValue(BrightnessAdjustmentProperty, value); }
        }

        /// <summary>A value between -1 and 1 to linearly increase the Red component of the result.
        /// -1 will remove all Red from the image, +1 will maximize all Red in the image. Default is 0.</summary>
        public double RedAdjustment
        {
            get { return (double)GetValue(RedAdjustmentProperty); }
            set { SetValue(RedAdjustmentProperty, value); }
        }
        /// <summary>A value between -1 and 1 to linearly increase the Green component of the result.
        /// -1 will remove all Green from the image, +1 will maximize all Green in the image. Default is 0.</summary>
        public double GreenAdjustment
        {
            get { return (double)GetValue(GreenAdjustmentProperty); }
            set { SetValue(GreenAdjustmentProperty, value); }
        }
        /// <summary>A value between -1 and 1 to linearly increase the Blue component of the result.
        /// -1 will remove all Blue from the image, +1 will maximize all Blue in the image. Default is 0.</summary>
        public double BlueAdjustment
        {
            get { return (double)GetValue(BlueAdjustmentProperty); }
            set { SetValue(BlueAdjustmentProperty, value); }
        }

        private static object CoerceFactor(DependencyObject d, object value)
        {
            double newFactor = (double)value;

            if( newFactor < 0.0 ) return 0.0;
            if( newFactor > 1.0 ) return 1.0;
            return newFactor;
        }

        private static object CoerceBrightnessAdjustment(DependencyObject d, object value)
        {
            double newFactor = (double)value;

            if( newFactor < -1.0 ) return -1.0;
            if( newFactor > 1.0 ) return 1.0;
            return newFactor;
        }
    }
}

Step 4: Use your effect in the xaml:

<Setter Property="Effect">
    <Setter.Value>
        <ui:ColourAdjustEffect Saturation="0" Gamma="0.6" 
                               BrightnessAdjustment="-0.2" RedAdjustment="0.04" />
    </Setter.Value>
</Setter>

So while I didn't get my glow effect, I had enough parameters to play with that I could get a 'highlighting' visual cue, which was my real goal. Here's some of the things I was able to do with it:

这篇关于WPF内发光效果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆