WPF绘图轮颜色选择器?
WPF Drawing Wheel Color Picker?
我正在尝试使用 Ellipse LinearGradientBrush 绘制颜色选择器。
<Ellipse Width="200" Height="200">
<Ellipse.Fill>
<VisualBrush TileMode="None">
<VisualBrush.Visual>
<Canvas Width="1" Height="1" SnapsToDevicePixels="True">
<Rectangle Width="1" Height="1" SnapsToDevicePixels="True">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FF0000" Offset="0" />
<GradientStop Color="#FFFF00" Offset="0.167" />
<GradientStop Color="#00FF00" Offset="0.333" />
<GradientStop Color="#00FFFF" Offset="0.5" />
<GradientStop Color="#0000FF" Offset="0.667" />
<GradientStop Color="#FF00FF" Offset="0.833" />
<GradientStop Color="#FF0000" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#00FFFFFF" Offset="1"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.OpacityMask>
</Rectangle>
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
</Ellipse.Fill>
</Ellipse>
就是这样:
但是画一个颜色选择器怎么可能有多种颜色,而且像这样分散出来的颜色。
我不知道。请任何人帮助。
就个人而言,我只使用背景纹理。 @Jim Foye 是对的,使用像素着色器很容易做到:
确保您已经安装了 fxc 着色器编译器 (this tutorial should help)。
写一个着色器将原始UV坐标转换为HSV,然后从HSV转换为RGB(数学在the HSL and HSV Wikipedia page上)。这是我刚刚创建的一个简单的工具,它可以很好地完成工作:
// ColorWheelEffect.hlsl
#define PI 3.141592653f
#define value 1.0f
float4 main(float2 uv : TEXCOORD) : COLOR {
uv = 2 * uv - 1;
float saturation = length(uv);
float hue = 3 * (PI - atan2(uv.y, -uv.x)) / PI;
float chroma = value * saturation;
float second = chroma * (1 - abs(hue % 2.0 - 1));
float m = value - chroma;
float3 rgb;
if (hue < 1)
rgb = float3(chroma, second, 0);
else if (hue < 2)
rgb = float3(second, chroma, 0);
else if (hue < 3)
rgb = float3(0, chroma, second);
else if (hue < 4)
rgb = float3(0, second, chroma);
else if (hue < 5)
rgb = float3(second, 0, chroma);
else
rgb = float3(chroma, 0, second);
return float4(rgb + m, saturation < 1);
}
- 将着色器编译成 ps 文件,内容如下:
fxc.exe /T ps_3_0 /E main /Fo ColorWheelEffect.ps ColorWheelEffect.hlsl
- 将 ps 文件作为资源添加到您的 WPF 项目并为其提供效果 class:
public class ColorWheelEffect : ShaderEffect
{
public ColorWheelEffect()
{
this.PixelShader = new PixelShader { UriSource = new Uri("pack://application:,,,/YourApplicationName;component/ColorWheelEffect.ps", UriKind.Absolute) };
}
}
- 在您的 XAML 中创建一个 ellipse 并将效果设置为您的效果实例 class:
<!-- Must fill with transparent or you won't see anything -->
<Ellipse Width="200" Height="200" Fill="Transparent">
<Ellipse.Effect>
<local:ColorWheelEffect />
</Ellipse.Effect>
</Ellipse>
结果:
我正在尝试使用 Ellipse LinearGradientBrush 绘制颜色选择器。
<Ellipse Width="200" Height="200">
<Ellipse.Fill>
<VisualBrush TileMode="None">
<VisualBrush.Visual>
<Canvas Width="1" Height="1" SnapsToDevicePixels="True">
<Rectangle Width="1" Height="1" SnapsToDevicePixels="True">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FF0000" Offset="0" />
<GradientStop Color="#FFFF00" Offset="0.167" />
<GradientStop Color="#00FF00" Offset="0.333" />
<GradientStop Color="#00FFFF" Offset="0.5" />
<GradientStop Color="#0000FF" Offset="0.667" />
<GradientStop Color="#FF00FF" Offset="0.833" />
<GradientStop Color="#FF0000" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#00FFFFFF" Offset="1"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.OpacityMask>
</Rectangle>
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
</Ellipse.Fill>
</Ellipse>
就是这样:
但是画一个颜色选择器怎么可能有多种颜色,而且像这样分散出来的颜色。
我不知道。请任何人帮助。
就个人而言,我只使用背景纹理。 @Jim Foye 是对的,使用像素着色器很容易做到:
确保您已经安装了 fxc 着色器编译器 (this tutorial should help)。
写一个着色器将原始UV坐标转换为HSV,然后从HSV转换为RGB(数学在the HSL and HSV Wikipedia page上)。这是我刚刚创建的一个简单的工具,它可以很好地完成工作:
// ColorWheelEffect.hlsl
#define PI 3.141592653f
#define value 1.0f
float4 main(float2 uv : TEXCOORD) : COLOR {
uv = 2 * uv - 1;
float saturation = length(uv);
float hue = 3 * (PI - atan2(uv.y, -uv.x)) / PI;
float chroma = value * saturation;
float second = chroma * (1 - abs(hue % 2.0 - 1));
float m = value - chroma;
float3 rgb;
if (hue < 1)
rgb = float3(chroma, second, 0);
else if (hue < 2)
rgb = float3(second, chroma, 0);
else if (hue < 3)
rgb = float3(0, chroma, second);
else if (hue < 4)
rgb = float3(0, second, chroma);
else if (hue < 5)
rgb = float3(second, 0, chroma);
else
rgb = float3(chroma, 0, second);
return float4(rgb + m, saturation < 1);
}
- 将着色器编译成 ps 文件,内容如下:
fxc.exe /T ps_3_0 /E main /Fo ColorWheelEffect.ps ColorWheelEffect.hlsl
- 将 ps 文件作为资源添加到您的 WPF 项目并为其提供效果 class:
public class ColorWheelEffect : ShaderEffect
{
public ColorWheelEffect()
{
this.PixelShader = new PixelShader { UriSource = new Uri("pack://application:,,,/YourApplicationName;component/ColorWheelEffect.ps", UriKind.Absolute) };
}
}
- 在您的 XAML 中创建一个 ellipse 并将效果设置为您的效果实例 class:
<!-- Must fill with transparent or you won't see anything -->
<Ellipse Width="200" Height="200" Fill="Transparent">
<Ellipse.Effect>
<local:ColorWheelEffect />
</Ellipse.Effect>
</Ellipse>
结果: