C# XAML具有多个渐变停止点的角度渐变
我试图在XAML中创建一个角度渐变(类似于Photoshop所做的)。我发现了这篇文章:它确实有效,但只支持两个渐变停止,我需要11个C# XAML具有多个渐变停止点的角度渐变,c#,wpf,xaml,directx,shader,C#,Wpf,Xaml,Directx,Shader,我试图在XAML中创建一个角度渐变(类似于Photoshop所做的)。我发现了这篇文章:它确实有效,但只支持两个渐变停止,我需要11个 我已经查看了在后端进行计算的着色器,但我不知道如何添加对更多渐变停止的支持。即使着色器被硬编码为使用11种颜色,它也可以工作。这里有一个类似的着色器,它支持20个停止点,并且在边缘周围没有锯齿: 设置: 将着色器代码放入shader.hlsl中,并使用编译。我运行的命令是“fxc/tps_3_0/Fo shader.ps shader.hlsl” 将输出文件
我已经查看了在后端进行计算的着色器,但我不知道如何添加对更多渐变停止的支持。即使着色器被硬编码为使用11种颜色,它也可以工作。这里有一个类似的着色器,它支持20个停止点,并且在边缘周围没有锯齿: 设置:
- 将着色器代码放入shader.hlsl中,并使用编译。我运行的命令是“fxc/tps_3_0/Fo shader.ps shader.hlsl”
- 将输出文件shader.ps添加到项目的根目录,并将其生成类型更改为resource
- 将效果代码和xaml添加到项目中李>
为了保持一致性,我重用了LinearGradientBrush的GradientStopCollection/GradientStop
AngularGradientEffect.cs:
public class AngularGradientEffect : ShaderEffect
{
const int STOP_COUNT = 20;
const int STOP_ANGLE_OFFSET = 10;
const int STOP_COLOR_OFFSET = 50;
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 GradientStopsProperty =
DependencyProperty.Register("GradientStops",
typeof(GradientStopCollection),
typeof(AngularGradientEffect),
new PropertyMetadata(new GradientStopCollection()));
static readonly DependencyProperty[] StopAngles = new DependencyProperty[STOP_COUNT];
static readonly DependencyProperty[] StopColors = new DependencyProperty[STOP_COUNT];
static AngularGradientEffect()
{
for (int i = 0; i < STOP_COUNT; i++)
{
StopAngles[i] = DependencyProperty.Register("GradientStopAngle" + i, typeof(float), typeof(AngularGradientEffect), new UIPropertyMetadata(-1.0f, PixelShaderConstantCallback(STOP_ANGLE_OFFSET + i)));
StopColors[i] = DependencyProperty.Register("GradientStopColor" + i, typeof(Color), typeof(AngularGradientEffect), new UIPropertyMetadata(Colors.RosyBrown, PixelShaderConstantCallback(STOP_COLOR_OFFSET + i)));
}
}
public AngularGradientEffect()
{
PixelShader = new PixelShader()
{
UriSource = new Uri("/ShaderTest;component/shader.ps", UriKind.Relative)
};
UpdateShaderValue(InputProperty);
UpdateShaderValue(CenterPointProperty);
GradientStops = new GradientStopCollection();
GradientStops.Changed += GradientStops_Changed;
}
void GradientStops_Changed(object sender, EventArgs e)
{
SetGradientStopDependencyProperties(sender as GradientStopCollection);
}
public void SetGradientStopDependencyProperties(IEnumerable<GradientStop> stops)
{
var orderedStops = stops.OrderBy(s => s.Offset).ToArray();
for (int i = 0; i < STOP_COUNT; i++)
{
var current = orderedStops.ElementAtOrDefault(i);
DependencyProperty angleProperty = StopAngles[i];
SetValue(angleProperty, current == null ? -1.0f : (float)current.Offset * 2 * 3.141596f);
DependencyProperty colorProperty = StopColors[i];
SetValue(colorProperty, current == null ? Color.FromArgb(0, 0, 0, 0) : current.Color);
}
}
public Brush Input
{
get
{
return ((Brush)(this.GetValue(InputProperty)));
}
set
{
this.SetValue(InputProperty, value);
}
}
public Point CenterPoint
{
get
{
return ((Point)(this.GetValue(CenterPointProperty)));
}
set
{
this.SetValue(CenterPointProperty, value);
}
}
public GradientStopCollection GradientStops
{
get { return (GradientStopCollection)GetValue(GradientStopsProperty); }
set
{
SetValue(GradientStopsProperty, value);
}
}
}
公共类AngularGradientEffect:ShaderEffect
{
常数int STOP_计数=20;
常数int STOP_角度_偏移=10;
常数int STOP_COLOR_OFFSET=50;
公共静态只读DependencyProperty InputProperty=ShaderEffect.RegisterPixelShaderSamplerProperty(
“输入”,
类型(角度梯度效应),
0);
公共静态只读DependencyProperty CenterPointProperty=DependencyProperty.Register(
“中心点”,
类型(点),
类型(角度梯度效应),
新UIPropertyMetadata(新点(0.5D,0.5D),PixelShaderConstantCallback(0));
公共静态只读从属属性GradientStopsProperty=
DependencyProperty.Register(“GradientStops”,
类型(GradientStopCollection),
类型(角度梯度效应),
新的PropertyMetadata(新的GradientStopCollection());
静态只读DependencyProperty[]StopAngles=新DependencyProperty[STOP_COUNT];
静态只读DependencyProperty[]StopColor=新DependencyProperty[STOP_COUNT];
静态角度梯度效应()
{
对于(int i=0;is.Offset.ToArray();
对于(int i=0;i
着色器:
sampler2D inputSampler : register(S0);
float2 centerPoint : register(C0);
float angle1 : register(C10);
float angle2 : register(C11);
float angle3 : register(C12);
float angle4 : register(C13);
float angle5 : register(C14);
float angle6 : register(C15);
float angle7 : register(C16);
float angle8 : register(C17);
float angle9 : register(C18);
float angle10 : register(C19);
float angle11 : register(C20);
float angle12 : register(C21);
float angle13 : register(C22);
float angle14 : register(C23);
float angle15 : register(C24);
float angle16 : register(C25);
float angle17 : register(C26);
float angle18 : register(C27);
float angle19 : register(C28);
float angle20 : register(C29);
float4 color1 : register(C50);
float4 color2 : register(C51);
float4 color3 : register(C52);
float4 color4 : register(C53);
float4 color5 : register(C54);
float4 color6 : register(C55);
float4 color7 : register(C56);
float4 color8 : register(C57);
float4 color9 : register(C58);
float4 color10 : register(C59);
float4 color11 : register(C60);
float4 color12 : register(C61);
float4 color13 : register(C62);
float4 color14 : register(C63);
float4 color15 : register(C64);
float4 color16 : register(C65);
float4 color17 : register(C66);
float4 color18 : register(C67);
float4 color19 : register(C68);
float4 color20 : register(C69);
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;
float startAngle;
float endAngle;
float4 startColor;
float4 endColor;
if (angle >= angle1 && angle < angle2)
{
startAngle = angle1;
startColor = color1;
endAngle = angle2;
endColor = color2;
}
else if (angle >= angle2 && angle < angle3)
{
startAngle = angle2;
startColor = color2;
endAngle = angle3;
endColor = color3;
}
else if (angle >= angle3 && angle < angle4)
{
startAngle = angle3;
startColor = color3;
endAngle = angle4;
endColor = color4;
}
else if (angle >= angle4 && angle < angle5)
{
startAngle = angle4;
startColor = color4;
endAngle = angle5;
endColor = color5;
}
else if (angle >= angle5 && angle <= angle6)
{
startAngle = angle5;
startColor = color5;
endAngle = angle6;
endColor = color6;
}
else if (angle >= angle6 && angle <= angle7)
{
startAngle = angle6;
startColor = color6;
endAngle = angle7;
endColor = color7;
}
else if (angle >= angle7 && angle <= angle8)
{
startAngle = angle7;
startColor = color7;
endAngle = angle8;
endColor = color8;
}
else if (angle >= angle8 && angle <= angle9)
{
startAngle = angle8;
startColor = color8;
endAngle = angle9;
endColor = color9;
}
else if (angle >= angle9 && angle <= angle10)
{
startAngle = angle9;
startColor = color9;
endAngle = angle10;
endColor = color10;
}
else if (angle >= angle10 && angle <= angle11)
{
startAngle = angle10;
startColor = color10;
endAngle = angle11;
endColor = color11;
}
else if (angle >= angle11 && angle <= angle12)
{
startAngle = angle11;
startColor = color11;
endAngle = angle12;
endColor = color12;
}
else if (angle >= angle12 && angle <= angle13)
{
startAngle = angle12;
startColor = color12;
endAngle = angle13;
endColor = color13;
}
else if (angle >= angle13 && angle <= angle14)
{
startAngle = angle13;
startColor = color13;
endAngle = angle14;
endColor = color14;
}
else if (angle >= angle14 && angle <= angle15)
{
startAngle = angle14;
startColor = color14;
endAngle = angle15;
endColor = color15;
}
else if (angle >= angle15 && angle <= angle16)
{
startAngle = angle15;
startColor = color15;
endAngle = angle16;
endColor = color16;
}
else if (angle >= angle16 && angle <= angle17)
{
startAngle = angle16;
startColor = color16;
endAngle = angle17;
endColor = color17;
}
else if (angle >= angle17 && angle <= angle18)
{
startAngle = angle17;
startColor = color17;
endAngle = angle18;
endColor = color18;
}
else if (angle >= angle18 && angle <= angle19)
{
startAngle = angle18;
startColor = color18;
endAngle = angle19;
endColor = color19;
}
else if (angle >= angle19 && angle <= angle20)
{
startAngle = angle19;
startColor = color19;
endAngle = angle20;
endColor = color20;
}
float offset = (angle - startAngle) / (endAngle - startAngle);
float4 color = lerp(startColor, endColor, offset);
// Multiply by the transparency of the source pixel
float3 output = color.rgb * src.a;
return float4(output, src.a);
}
sampler2D输入采样器:寄存器(S0);
浮动2中心点:寄存器(C0);
浮动角度1:寄存器(C10);
浮动角度2:寄存器(C11);
浮动角度3:寄存器(C12);
浮动角度4:寄存器(C13);
浮动角度5:寄存器(C14);
浮动角度6:寄存器(C15);
浮动角度7:寄存器(C16);
浮动角度8:寄存器(C17);
浮动角度9:寄存器(C18);
浮动角度10:寄存器(C19);
浮动角度11:寄存器(C20);
浮动角度12:寄存器(C21);
浮动角度13:寄存器(C22);
浮动角度14:寄存器(C23);
浮动角度15:寄存器(C24);
浮动角度16:寄存器(C25);
浮动角度17:寄存器(C26);
浮动角度18:寄存器(C27);
浮动角度19:寄存器(C28);
浮动角度20:寄存器(C29);
float4-color1:寄存器(C50);
float4-color2:寄存器(C51);
float4-color3:寄存器(C52);
float4-color4:寄存器(C53);
float4-color5:寄存器(C54);
float4-color6:寄存器(C55);
float4-color7:寄存器(C56);
float4-color8:寄存器(C57);
float4-color9:寄存器(C58);
float4-color10:寄存器(C59);
float4-color11:寄存器(C60);
float4-color12:寄存器(C61);
float4-color13:寄存器(C62);
float4-color14:寄存器(C63);
float4-color15:寄存器(C64);
float4-color16:寄存器(C65);
浮动4色
sampler2D inputSampler : register(S0);
float2 centerPoint : register(C0);
float angle1 : register(C10);
float angle2 : register(C11);
float angle3 : register(C12);
float angle4 : register(C13);
float angle5 : register(C14);
float angle6 : register(C15);
float angle7 : register(C16);
float angle8 : register(C17);
float angle9 : register(C18);
float angle10 : register(C19);
float angle11 : register(C20);
float angle12 : register(C21);
float angle13 : register(C22);
float angle14 : register(C23);
float angle15 : register(C24);
float angle16 : register(C25);
float angle17 : register(C26);
float angle18 : register(C27);
float angle19 : register(C28);
float angle20 : register(C29);
float4 color1 : register(C50);
float4 color2 : register(C51);
float4 color3 : register(C52);
float4 color4 : register(C53);
float4 color5 : register(C54);
float4 color6 : register(C55);
float4 color7 : register(C56);
float4 color8 : register(C57);
float4 color9 : register(C58);
float4 color10 : register(C59);
float4 color11 : register(C60);
float4 color12 : register(C61);
float4 color13 : register(C62);
float4 color14 : register(C63);
float4 color15 : register(C64);
float4 color16 : register(C65);
float4 color17 : register(C66);
float4 color18 : register(C67);
float4 color19 : register(C68);
float4 color20 : register(C69);
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;
float startAngle;
float endAngle;
float4 startColor;
float4 endColor;
if (angle >= angle1 && angle < angle2)
{
startAngle = angle1;
startColor = color1;
endAngle = angle2;
endColor = color2;
}
else if (angle >= angle2 && angle < angle3)
{
startAngle = angle2;
startColor = color2;
endAngle = angle3;
endColor = color3;
}
else if (angle >= angle3 && angle < angle4)
{
startAngle = angle3;
startColor = color3;
endAngle = angle4;
endColor = color4;
}
else if (angle >= angle4 && angle < angle5)
{
startAngle = angle4;
startColor = color4;
endAngle = angle5;
endColor = color5;
}
else if (angle >= angle5 && angle <= angle6)
{
startAngle = angle5;
startColor = color5;
endAngle = angle6;
endColor = color6;
}
else if (angle >= angle6 && angle <= angle7)
{
startAngle = angle6;
startColor = color6;
endAngle = angle7;
endColor = color7;
}
else if (angle >= angle7 && angle <= angle8)
{
startAngle = angle7;
startColor = color7;
endAngle = angle8;
endColor = color8;
}
else if (angle >= angle8 && angle <= angle9)
{
startAngle = angle8;
startColor = color8;
endAngle = angle9;
endColor = color9;
}
else if (angle >= angle9 && angle <= angle10)
{
startAngle = angle9;
startColor = color9;
endAngle = angle10;
endColor = color10;
}
else if (angle >= angle10 && angle <= angle11)
{
startAngle = angle10;
startColor = color10;
endAngle = angle11;
endColor = color11;
}
else if (angle >= angle11 && angle <= angle12)
{
startAngle = angle11;
startColor = color11;
endAngle = angle12;
endColor = color12;
}
else if (angle >= angle12 && angle <= angle13)
{
startAngle = angle12;
startColor = color12;
endAngle = angle13;
endColor = color13;
}
else if (angle >= angle13 && angle <= angle14)
{
startAngle = angle13;
startColor = color13;
endAngle = angle14;
endColor = color14;
}
else if (angle >= angle14 && angle <= angle15)
{
startAngle = angle14;
startColor = color14;
endAngle = angle15;
endColor = color15;
}
else if (angle >= angle15 && angle <= angle16)
{
startAngle = angle15;
startColor = color15;
endAngle = angle16;
endColor = color16;
}
else if (angle >= angle16 && angle <= angle17)
{
startAngle = angle16;
startColor = color16;
endAngle = angle17;
endColor = color17;
}
else if (angle >= angle17 && angle <= angle18)
{
startAngle = angle17;
startColor = color17;
endAngle = angle18;
endColor = color18;
}
else if (angle >= angle18 && angle <= angle19)
{
startAngle = angle18;
startColor = color18;
endAngle = angle19;
endColor = color19;
}
else if (angle >= angle19 && angle <= angle20)
{
startAngle = angle19;
startColor = color19;
endAngle = angle20;
endColor = color20;
}
float offset = (angle - startAngle) / (endAngle - startAngle);
float4 color = lerp(startColor, endColor, offset);
// Multiply by the transparency of the source pixel
float3 output = color.rgb * src.a;
return float4(output, src.a);
}