繁体   English   中英

WPF中的3种颜色AngleGradient

[英]3 Colors AngleGradient in WPF

我正在尝试在WPF中实现简单的3色角度渐变。 最好的情况是您得到了仅XAML的答案,但是我很确定这是不可能的。

这个问题和答案( 在WPF中AngleGradient )是我想要的一半。 我尝试使用该代码,但显然数学没有正确。

在此处输入图片说明

我的问题是:我该如何正确执行上述问题,但要使用3种颜色以及3和1之间的渐变(在上面的问题中,渐变是从蓝色到白色,但又直接回到蓝色)之后,我也想要从白色到蓝色的反向渐变。

将其视为具有完美水平底面的等边三角形。 例如,我要在上角处使用红色,在左下角处使用绿色,在右下角处使用蓝色,并且在两者之间具有理想的角度辐射。

在此处输入图片说明

我不介意像其他线程建议的答案那样编译成.ps :)

非常感谢 !

我认为其他线程可以很好地解释您需要做什么。 您将需要将所有三种颜色传递给着色器,然后对每个像素进行数学运算以获得所需的颜色。

以与其他答案相同的方式获取当前像素的0-1角。 然后以那个角度在适当的颜色之间徘徊。

着色器

sampler2D inputSampler : register(S0);
float2 center : register(C0);
float4 firstColor : register(C1);
float4 secondColor : register(C2);
float4 thirdColor : register(C3);

float4 main(float2 uv : TEXCOORD) : COLOR
{
    // Put the three colors into an array.
    float4 colors[3] = { firstColor, secondColor, thirdColor };

    // Figure out where this pixel is in relation to the center point
    float2 pos = center - uv;

    // Compute the angle of this pixel relative to the center (in radians),
    // then divide by 2 pi to normalize the angle into a 0 to 1 range.
    // We are flipping the Y here so that 0 is at the top (instead of the bottom) and we
    // rotate clockwise. Could also flip X if we want to rotate counter-clockwise.
    float value = (atan2(pos.x, -pos.y) + 3.141596) / (2.0 * 3.141596);

    // Scale the angle based on the size of our array and determine which indices
    // we are currently between, wrapping around to 0 at the end.
    float scaledValue = value * 3;
    float4 prevColor = colors[(int)scaledValue];
    float4 nextColor = colors[((int)scaledValue + 1) % 3];

    // Figure out how far between the two colors we are
    float lerpValue = scaledValue - (float)((int)scaledValue);

    // Get the alpha of the incoming pixel from the sampler.
    float alpha = tex2D(inputSampler, uv).a;

    // Lerp between the colors. Multiply each color by its own alpha and the result by the
    // incoming alpha becuse WPF expects shaders to return premultiplied alpha pixel values.
    return float4(
        lerp(prevColor.rgb * prevColor.a, nextColor.rgb * nextColor.a, lerpValue) * alpha,
        lerp(prevColor.a, nextColor.a, lerpValue) * alpha);
}

影响

class AngleGradientEffect : ShaderEffect
{
    public Brush Input
    {
        get { return (Brush)GetValue(InputProperty); }
        set { SetValue(InputProperty, value); }
    }
    public static readonly DependencyProperty InputProperty = RegisterPixelShaderSamplerProperty("Input", typeof(AngleGradientEffect), 0);

    public Point Center
    {
        get { return (Point)GetValue(CenterProperty); }
        set { SetValue(CenterProperty, value); }
    }
    public static readonly DependencyProperty CenterProperty = DependencyProperty.Register("Center", typeof(Point), typeof(AngleGradientEffect),
        new PropertyMetadata(new Point(0.5, 0.5), PixelShaderConstantCallback(0)));

    public Color FirstColor
    {
        get { return (Color)GetValue(FirstColorProperty); }
        set { SetValue(FirstColorProperty, value); }
    }
    public static readonly DependencyProperty FirstColorProperty = DependencyProperty.Register("FirstColor", typeof(Color), typeof(AngleGradientEffect),
        new PropertyMetadata(Color.FromRgb(255, 0, 0), PixelShaderConstantCallback(1)));

    public Color SecondColor
    {
        get { return (Color)GetValue(SecondColorProperty); }
        set { SetValue(SecondColorProperty, value); }
    }
    public static readonly DependencyProperty SecondColorProperty = DependencyProperty.Register("SecondColor", typeof(Color), typeof(AngleGradientEffect),
        new PropertyMetadata(Color.FromRgb(0, 255, 0), PixelShaderConstantCallback(2)));

    public Color ThirdColor
    {
        get { return (Color)GetValue(ThirdColorProperty); }
        set { SetValue(ThirdColorProperty, value); }
    }
    public static readonly DependencyProperty ThirdColorProperty = DependencyProperty.Register("ThirdColor", typeof(Color), typeof(AngleGradientEffect),
        new PropertyMetadata(Color.FromRgb(0, 0, 255), PixelShaderConstantCallback(3)));

    public AngleGradientEffect()
    {
        // ResourceHelper is my own utility that formats URIs for me. The returned URI
        // string will be something like /AssemblyName;component/Effects/AngleGradient.ps
        PixelShader = new PixelShader() { UriSource = ResourceHelper.GetResourceUri("Effects/AngleGradient.ps", relative: true)};

        UpdateShaderValue(InputProperty);
        UpdateShaderValue(CenterProperty);
        UpdateShaderValue(FirstColorProperty);
        UpdateShaderValue(SecondColorProperty);
        UpdateShaderValue(ThirdColorProperty);
    }
}

用法

<Ellipse
    Width="200"
    Height="200"
    Fill="White">
    <Ellipse.Effect>
        <effects:AngleGradientEffect
            FirstColor="Red"
            SecondColor="Lime"
            ThirdColor="Blue" />
    </Ellipse.Effect>
</Ellipse>

在此处输入图片说明

请记住,在某些情况下,在RGB空间中的不同色调之间进行插值会提供一些难看的结果。 如果您希望这样做,则可能要考虑转换为HSV并插入色相。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM