当前位置: 首页 > article >正文

WPF如何全局应用黑白主题效果

灰白色很多时候用于纪念,哀悼等。那么使用 WPF如何来做到这种效果呢?要实现的这种效果,我们会发现,它其实不仅仅是要针对图片,而是要针对整个窗口来实现灰白色。

如果只是针对图片的话,我可以可以对图片进行灰阶转换,即可达到灰色效果。

以下是图片转灰阶的代码,当然方法不仅仅是这一种:

//……省略……                FormatConvertedBitmap grayImage = new FormatConvertedBitmap();grayImage.BeginInit();grayImage.Source = originImage as BitmapSource;grayImage.DestinationFormat = PixelFormats.Gray32Float;grayImage.EndInit();                //……省略……

上述方法也可以直接在 xaml里面表示。

    <Image.Source>      <FormatConvertedBitmap DestinationFormat="Gray32">        <FormatConvertedBitmap.Source>          <BitmapImage UriSource="Images\1.png" />        </FormatConvertedBitmap.Source>      </FormatConvertedBitmap>    </Image.Source>

 如果我们想针对整个窗口应用这种灰色的效果,那我们可以用着色器特效( ShaderEffect)来实现。

说明:

  1. *.fx格式文件:是一种应用特效效果文件,也叫渲染管线的配置文件。编写该文件语言名为高阶着色器语言(High Level Shader Language,简称HLSL),由微软拥有及开发的一种语言。

  2. *.ps格式文件:是通过 *.fx文件编译出来的文件,该文件是通过 ShaderEffect所指定的原始文件。通过 ShaderEffect类,将其应用于 WPF

灰阶相关 fx, ps等文件已有大佬写好了,我们直接拿来用即可跳转下载(https://github.com/abursjoo/GrayscaleEffectSample/tree/master/WpfApplication1/WpfApplication1)。相关解释,会在注释中说明。

渲染管线配置文件(*.fx)

//sampler2D 2D纹理采样器//s0中,s表示取样器,0是表示取样器的子组件编号sampler2D implicitInput : register(s0);//c 表示缓冲区偏移量float factor : register(c0);//TEXCOORD 表示纹理坐标;COLOR 漫反射/镜面反射颜色float4 main(float2 uv : TEXCOORD) : COLOR{    //返回纹理implicitInput在uv位置的颜色。    float4 color = tex2D(implicitInput, uv);    //将颜色转成灰阶    float gray = color.r * 0.3 + color.g * 0.59 + color.b *0.11;        float4 result;        result.r = (color.r - gray) * factor + gray;    result.g = (color.g - gray) * factor + gray;    result.b = (color.b - gray) * factor + gray;    result.a = color.a;    return result;}

应用WPF中特效类 

    //灰阶特效
    public class GrayscaleEffect : ShaderEffect
    {
        //将像素着色器映射到灰阶着色器
        private static PixelShader _pixelShader = new PixelShader() { UriSource = new Uri(@"pack://application:,,,/GrayscaleEffect;component/GrayscaleEffect.ps") };

        public GrayscaleEffect()
        {
            PixelShader = _pixelShader;
            //更新着色器的值
            UpdateShaderValue(InputProperty);
            //该属性可以不要,该熟悉用于彩色到灰色过渡效果
            UpdateShaderValue(DesaturationFactorProperty);
        }

        public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(GrayscaleEffect), 0);
        public Brush Input
        {
            get { return (Brush)GetValue(InputProperty); }
            set { SetValue(InputProperty, value); }
        }

        public static readonly DependencyProperty DesaturationFactorProperty = DependencyProperty.Register("DesaturationFactor", typeof(double), typeof(GrayscaleEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(0), CoerceDesaturationFactor));

        //用于调节过渡效果
        public double DesaturationFactor
        {
            get { return (double)GetValue(DesaturationFactorProperty); }
            set { SetValue(DesaturationFactorProperty, value); }
        }

        private static object CoerceDesaturationFactor(DependencyObject d, object value)
        {
            GrayscaleEffect effect = (GrayscaleEffect)d;
            double newFactor = (double)value;

            if (newFactor < 0.0 || newFactor > 1.0)
            {
                return effect.DesaturationFactor;
            }

            return newFactor;
        }
    }

WPF里面的使用示例:


        <!--effect 代表GrayscaleEffect所在的命名空间-->
        <Grid.Effect>
            <effect:GrayscaleEffect/>
        </Grid.Effect>

需要应用到哪个根元素上,就将该特效给对应元素的 Effect 赋值即可。

这种实现方法,性能还是很不错的,如果想对 Shader有更深入的认识,可以阅读 《DirectX3DHLSL高级实例精讲》.


http://www.kler.cn/a/404824.html

相关文章:

  • WPF窗体基本知识-笔记-命名空间
  • 细说STM32单片机DMA中断收发RTC实时时间并改善其鲁棒性的另一种方法
  • 项目:华清速递
  • Kafka 到 Kafka 数据同步
  • Rust 力扣 - 746. 使用最小花费爬楼梯
  • sql server 查看索引的使用
  • Java多线程编程详解
  • 亿咖通科技应邀出席微软汽车行业智享会,分享ECARX AutoGPT全新实践
  • GitLab|GitLab报错:PG::ConnectionBad: could not connect to server...
  • springboot基于微信小程序的食堂预约点餐系统
  • 使用线程局部存储解决ffmpeg中多实例调用下自定义日志回调问题
  • 力扣 LeetCode 110. 平衡二叉树(Day8:二叉树)
  • 在windows电脑上安装docker服务
  • 大模型试用-t5-base
  • 深度学习的分布式训练与集合通信(一)
  • 调试QRNet遇到的问题
  • 基于Windows系统用C++做一个点名工具
  • 算法学习笔记(六):二叉树一创建、插入、删除、BFS
  • 测试工程师如何在面试中脱颖而出
  • 【软件架构】软件的十二种架构简介
  • 操作系统安全入门:渗透测试基础与实践
  • 存算分离的过去、现在和未来
  • 【Oracle篇】SQL性能优化实战案例(从15秒优化到0.08秒)(第七篇,总共七篇)
  • 前端反向代理的配置和實現
  • 深入解析MySQL中的事务处理
  • 从0开始linux(28)——使用vscode远程链接linux云服务器