【发布时间】:2013-12-28 10:08:11
【问题描述】:
如您所知,PhotoShop 中有一个名为 AngleGradient 的渐变选项。但是,WPF 只有LinearGradientBrush 和RadialGradientBrush 渐变。您知道如何使用XAML 创建AngleGradient 吗?
更新: 样品 - 来自 photoshop:
【问题讨论】:
标签: wpf xaml gradient wpf-4.0 wpf-brushes
如您所知,PhotoShop 中有一个名为 AngleGradient 的渐变选项。但是,WPF 只有LinearGradientBrush 和RadialGradientBrush 渐变。您知道如何使用XAML 创建AngleGradient 吗?
更新: 样品 - 来自 photoshop:
【问题讨论】:
标签: wpf xaml gradient wpf-4.0 wpf-brushes
我为此编写了一个着色器,对其进行编译并将 .ps 文件作为资源添加到您的项目中:
// no input texture, the output is completely generated in code
sampler2D inputSampler : register(S0);
/// <summary>The center of the gradient. </summary>
/// <minValue>0,0</minValue>
/// <maxValue>1,1</maxValue>
/// <defaultValue>.5,.5</defaultValue>
float2 centerPoint : register(C0);
/// <summary>The primary color of the gradient. </summary>
/// <defaultValue>Blue</defaultValue>
float4 primaryColor : register(C1);
/// <summary>The secondary color of the gradient. </summary>
/// <defaultValue>Red</defaultValue>
float4 secondaryColor : register(C2);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 src= tex2D(inputSampler, uv);
float2 p = float2(centerPoint)-uv;
float angle = (atan2(p.x, p.y) + 3.141596) / (2 * 3.141596);
float3 f = lerp(primaryColor.rgb, secondaryColor.rgb, angle);
float4 color = float4(src.a < 0.01
? float3(0, 0, 0) // WPF uses pre-multiplied alpha everywhere internally for a number of performance reasons.
: f, src.a < 0.01 ? 0 : 1);
return color;
}
这样包装:
public class AngularGradientEffect : ShaderEffect {
public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty(
"Input",
typeof(AngularGradientEffect),
0);
public static readonly DependencyProperty CenterPointProperty = DependencyProperty.Register(
"CenterPoint",
typeof(Point),
typeof(AngularGradientEffect),
new UIPropertyMetadata(new Point(0.5D, 0.5D), PixelShaderConstantCallback(0)));
public static readonly DependencyProperty PrimaryColorProperty = DependencyProperty.Register(
"PrimaryColor",
typeof(Color),
typeof(AngularGradientEffect),
new UIPropertyMetadata(Color.FromArgb(255, 0, 0, 255), PixelShaderConstantCallback(1)));
public static readonly DependencyProperty SecondaryColorProperty = DependencyProperty.Register(
"SecondaryColor",
typeof(Color),
typeof(AngularGradientEffect),
new UIPropertyMetadata(Color.FromArgb(255, 255, 0, 0), PixelShaderConstantCallback(2)));
public AngularGradientEffect() {
PixelShader pixelShader = new PixelShader();
pixelShader.UriSource = new Uri("/So.Wpf;component/Effects/AngularGradientEffect.ps", UriKind.Relative);
this.PixelShader = pixelShader;
this.UpdateShaderValue(InputProperty);
this.UpdateShaderValue(CenterPointProperty);
this.UpdateShaderValue(PrimaryColorProperty);
this.UpdateShaderValue(SecondaryColorProperty);
}
public Brush Input {
get {
return ((Brush)(this.GetValue(InputProperty)));
}
set {
this.SetValue(InputProperty, value);
}
}
/// <summary>The center of the gradient. </summary>
public Point CenterPoint {
get {
return ((Point)(this.GetValue(CenterPointProperty)));
}
set {
this.SetValue(CenterPointProperty, value);
}
}
/// <summary>The primary color of the gradient. </summary>
public Color PrimaryColor {
get {
return ((Color)(this.GetValue(PrimaryColorProperty)));
}
set {
this.SetValue(PrimaryColorProperty, value);
}
}
/// <summary>The secondary color of the gradient. </summary>
public Color SecondaryColor {
get {
return ((Color)(this.GetValue(SecondaryColorProperty)));
}
set {
this.SetValue(SecondaryColorProperty, value);
}
}
}
这样在Xaml中使用,效果用渐变替换所有不透明的像素,因此形状必须有颜色,任意颜色:
<Ellipse x:Name="ShaderEllipse" Fill="Transparent" Stroke="Blue" StrokeThickness="15">
<Ellipse.Effect>
<effects:AngularGradientEffect PrimaryColor="Red"
SecondaryColor="Transparent"/>
</Ellipse.Effect>
</Ellipse>
输出是:
添加到this lib
【讨论】:
Charles Petzold,Windows 编程的原始大师有一个简单的方法描述here。他使用了 Graphical Paths 和 LinearGradientBrushes 的优雅组合。博客条目是为 Silverlight 编写的,但这个概念很容易转化为 WPF。他还有一个链接到他的方法的基础,该方法基于 WPF。
和往常一样,Petzold 先生(我相信他应该是爵士)提供他所有的代码。
【讨论】: