WPF中实现图片的滤色混合模式

文章讲述了作者在WPF中遇到如何实现滤色效果的困惑,通过使用ShaderEffect和HLSL编程,展示了如何自定义混合模式,包括代码示例和HLSL源码。寻求更优实现建议。

概述

真希望有大佬能带带我啊!这块我是真不会,主要是只了解了WPF的一些基础内容,对如何做图片的一些效果(混合模式)就有点懵逼了,开始公司的大佬说要做滤色这些混合模式要用到OpenGL啥的,我也去看了不少文章,然后发现好像在WPF里面用起来,我不会啊!然后又找了一天的资料,发现可以用WPF中的Effect来进行实现这样一个效果!如果有更好的实现方式,还请帮帮我~

准备说明

PS中有滤色效果,借用知乎上的一位哥们的图片进行说明(https://zhuanlan.zhihu.com/p/158555958)。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如上就是滤色效果了!如何在WPF中实现呢?

元素

  • 两张图片:你需要准备两张图片,一张用作底图,一张用作效率叠加图!
  • 效果算法:WPF支持已有的一些效果,也支持自定义效果!这里采用自定义效果算法!
  • ShaderEffect:本文采用该方式进行混合模式的处理!
  • HLSL:全称“高级着色器语言”,参考链接:https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl

代码

继承ShaderEffect类,实现自定义的效果代码!
/// <summary>
/// 滤色混合模式
/// </summary>
public class BlendScreenEffect: ShaderEffect
{
    public static readonly DependencyProperty InputProperty = RegisterPixelShaderSamplerProperty("Input", typeof(BlendScreenEffect), 0);
    public static readonly DependencyProperty OverlayProperty = RegisterPixelShaderSamplerProperty("Overlay", typeof(BlendScreenEffect), 1);

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

    public Brush Overlay
    {
        get { return (Brush)GetValue(OverlayProperty); }
        set { SetValue(OverlayProperty, value); }
    }

    public BlendScreenEffect()
    {
        PixelShader = new PixelShader { UriSource = new Uri("pack://application:,,,/Shaders/ScreenEffect.ps", UriKind.RelativeOrAbsolute) };
        UpdateShaderValue(InputProperty);
        UpdateShaderValue(OverlayProperty);
    }
}

其中InputOverlay被定义为画刷类型,前一个是底图画刷,后一个是覆盖图层画刷!
PixelShader在构造函数中赋值,这里引用加载的就是基于HLSL描述编译后的ps文件。
可以看看滤色效果的HLSL文件源码。

滤色混合模式的源码
//--------------------------------------------------------------------------------------
// 
// WPF ShaderEffect HLSL -- ScreenEffect
//
//--------------------------------------------------------------------------------------

sampler2D input : register(s0);
sampler2D blend : register(s1);

//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------

float4 main(float2 uv : TEXCOORD) : COLOR
{
	float4 inputColor;
	inputColor = tex2D(input, uv);

	float4 blendColor;
	blendColor = tex2D(blend, uv);
	
	float4 resultColor;
	resultColor.a = inputColor.a;

	// un-premultiply the blendColor alpha out from blendColor
	blendColor.rgb = clamp(blendColor.rgb / blendColor.a, 0, 1);

	// apply the blend mode math
	// R = 1 - (1-Base) ?(1-Blend)
	resultColor.rgb = 1 - (1 - inputColor.rgb) * (1 - blendColor.rgb);

	// re-multiply the blendColor alpha in to blendColor, weight inputColor according to blendColor.a
	resultColor.rgb = (1 - blendColor.a) * inputColor.rgb + resultColor.rgb * blendColor.a;

	return resultColor;
}

算法和效果代码的准备工作已经做好了,接下来看看如何使用!

<Image
    Source="1.png">
    <Image.Effect>
        <common:BlendScreenEffect>
            <common:BlendScreenEffect.Overlay>
                <ImageBrush ImageSource="2.png" />
            </common:BlendScreenEffect.Overlay>
        </common:BlendScreenEffect>
    </Image.Effect>
</Image>

<common:BlendScreenEffect>中的common即wpf引用相关命名空间的名称!该命名空间下有BlendScreenEffect类,即我们开始继承ShaderEffect的自定义类!

大致情况就是这样了,如果想做更多效果或者动画,就自行扩展啦!更多混合模式的HLSL编码大家可以网上找找看,也可以留言找我拿!
感谢各位,求大佬们帮忙,看看有没有更好的实现方式?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值