• 作者:老汪软件技巧
  • 发表时间:2024-09-29 11:01
  • 浏览量:

前言

由于WPF只能写像素着色器,没法写顶点着色器,所以只能在这上面做文章了。

刚好有个纹理坐标TEXCOORD输入可用,而且值的范围是已知的0-1,左上角是原点,这就好办了

索引二分网格

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float ab =  ceil( uv.y-0.5 );
    return float4(ab,ab,ab,1.0);
}

四分网格

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float ab =  ceil( uv.y*4-0.5 );
    float scale=ab/4;
    return float4(scale,scale,scale,1.0);
}

二值化多分网格

//三角函数是天然的周期函数
float4 main(float2 uv : TEXCOORD) : COLOR
{
    float num=6;
    float2 ab =  0.5*sin(uv*3.1415*num )+0.5;
    float2 scale=round(ab);
    return float4(scale.y,scale.y,scale.y,1.0);
}

二值化方格

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float num=7;
    float abx =  0.5*sin(uv.x*3.1415*num )+0.5;
    float aby =  0.5*sin(uv.y*3.1415*num )+0.5;
    float scale=abs((round(abx)/2)+(round(aby)/2)-0.5);
    //0.4是避免浮点数精度问题,否则直接用round(scale)
    float scale2=ceil(scale-0.4);
    return float4(scale2,scale2,scale2,1.0);
}

动态方格

///  time 
/// 0
/// 100
/// 0
float time : register(C0);
float4 main(float2 uv : TEXCOORD) : COLOR
{
    float num=7;
    float abx =  0.5*sin(uv.x*3.1415*num+time )+0.5;
    float aby =  0.5*sin(uv.y*3.1415*num )+0.5;
    float scale=abs((round(abx)/2)+(round(aby)/2)-0.5);
    float scale2=ceil(scale-0.4);
    return float4(scale2,scale2,scale2,1.0);
}

线框网格

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float gridLines = 11;
    float gridLineX = step(0.99, abs(sin(uv.x * 3.1415 * gridLines))); 
    float gridLineY = step(0.99, abs(sin(uv.y * 3.1415 * gridLines))); 
    float4 color = float4(max(gridLineX,gridLineY) , max(gridLineX,gridLineY) , max(gridLineX,gridLineY) , 1.0);
    return color;
}

线框网格上滚动的小球

float2 mousePosition : register(C0);
float4 main(float2 uv : TEXCOORD,float2 positon : VPOS) : COLOR
{
    float gridLines = 11;
    float gridLineX = step(0.99, abs(sin(uv.x * 3.1415 * gridLines))); 
    float gridLineY = step(0.99, abs(sin(uv.y * 3.1415 * gridLines)));
    float maxline=max(gridLineX,gridLineY);
    
    float innerCircle = 1.0 - step(50,length(positon-mousePosition));
    float maxResult=max(maxline,innerCircle);
    float4 color = float4(maxResult , maxResult , maxResult , 1.0);
    return color;
}

鼠标操控小球

public class MouseCaptureEffect : ShaderEffect
{
    public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(MouseCaptureEffect), 0);
    public static readonly DependencyProperty MousePositionProperty = DependencyProperty.Register("MousePosition", typeof(Point), typeof(MouseCaptureEffect), new UIPropertyMetadata(new Point(0D, 0D), PixelShaderConstantCallback(0)));
    public MouseCaptureEffect()
    {
        PixelShader pixelShader = new PixelShader();
        pixelShader.UriSource = new Uri("pack://application:,,,/你的程序集名称;component/路径/TextEffect3.ps", UriKind.Absolute);
        this.PixelShader = pixelShader;
        this.UpdateShaderValue(InputProperty);
        this.UpdateShaderValue(MousePositionProperty);
    }
    public Brush Input
    {
        get
        {
            return ((Brush)(this.GetValue(InputProperty)));
        }
        set
        {
            this.SetValue(InputProperty, value);
        }
    }
    ///  mouse 
    public Point MousePosition
    {
        get
        {
            return ((Point)(this.GetValue(MousePositionProperty)));
        }
        set
        {
            this.SetValue(MousePositionProperty, value);
            Debug.WriteLine("aaa");
        }
    }
}

this.MouseMove += (sender, e) =>
{
    //这行代码不管用
    //MousePositionw = e.GetPosition(this);
    // 更新鼠标位置
    me.MousePosition= MousePositionw;
};

要注意的时,通过绑定的方式更新没成功,只好手动赋值,不知道哪里出问题了(找到原因了,我把绑定ownerClass写错了)

总结

本文详细介绍了如何利用C#与WPF技术实现具有网格风格的像素着色效果。通过逐步解析着色器的编写与集成过程,本文为大家提供了从理论到实践的全面指导。学习本文后,将能够为自己的WPF应用程序添加独特的视觉效果,从而提升应用的美观性和用户体验。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!