由于WPF只能写像素着色器,没法写顶点着色器,所以只能在这上面做文章了
刚好有个纹理坐标TEXCOORD
输入可用,而且值的范围是已知的0-1,左上角是原点,这就好办了
例子
索引
二分网格
- 使用
ceil
- 0-1移动定义域到-0.5 - 0.5,然后向上取整变成 0 / 1
float4 main(float2 uv : TEXCOORD) : COLOR
{float ab = ceil( uv.y-0.5 );return float4(ab,ab,ab,1.0);
}
4分网格
- 使用
ceil
- 0-1,先放大定义域0-4,然后向左移动定义域,-0.5 - 3.5,向上取整 0/1/2/3,最后压缩0/0.25/0.5/0.75/1
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);
}
二值化多分网格
- 使用
sin
round
- 利用周期函数把定义域0-1范围的周期调整到指定数,然后值域压扁-0.5 - 0.5,向上移动0-1,四舍五入二值化
//三角函数是天然的周期函数
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);
}
二值化方格
- 使用
sin
round
abs
- 在上一篇基础上,相乘生成纵横条纹。但这形成十字条纹,为了产生交错条纹,就不能相乘,只能相加
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);
}
动态方格
- 使用
sin
round
abs
/// <summary> time </summary>
/// <minValue>0</minValue>
/// <maxValue>100</maxValue>
/// <defaultValue>0</defaultValue>
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);
}
线框网格
- 使用
sin
abs
max
step
- 将周期函数取绝对值,变成一个个山峰,然后下沉,利用一个阈值,过滤出山尖
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;
}
线框网格上滚动的小球
- 使用
sin
abs
max
step
- 在前一篇基础上,再传入鼠标位置,并再鼠标周围画一个白色圆形,覆盖线框颜色设置。使用语义
VPOS
获取像素位置判断和鼠标距离
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);}}/// <summary> mouse </summary>public Point MousePosition{get{return ((Point)(this.GetValue(MousePositionProperty)));}set{this.SetValue(MousePositionProperty, value);Debug.WriteLine("aaa");}}
}
<Button Content="Btn"><Button.Effect><local:MouseCaptureEffect x:Name="me" MousePosition="{Binding MousePositionw,Mode=TwoWay}" ></local:MouseCaptureEffect></Button.Effect>
</Button>
this.MouseMove += (sender, e) =>
{//这行代码不管用//MousePositionw = e.GetPosition(this);// 更新鼠标位置me.MousePosition= MousePositionw;
};
要注意的时,通过绑定的方式更新没成功,只好手动赋值,不知道哪里出问题了