나는 다른 스레드가 당신이해야 할 일을 설명 할 수 있다고 생각한다. 셰이더에 세 가지 색을 모두 전달한 다음 원하는 픽셀을 얻으려면 픽셀 단위로 계산해야합니다.
다른 답변과 같은 방법으로 현재 픽셀의 각도를 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로 변환하고 색상이 보간 될 것으로 예상되는 경우 보간하는 것이 좋습니다.
나는 셰이더를 만드는 것에 대한 지식이 전혀 없으며 셰이더 부분을 분명히 이해하지 못합니다. 그러나 그것은 작동합니다! :) 내가 놓친 유일한 이유는 처음 색 센터를 얻을 수 있도록 (셰이더에서) 솔루션을 회전하는 방법을 이해하는 것입니다. 위로 가기 – ericmas001
간단한 변화입니다. 세로로 뒤집을 각도를 계산할 때 셰이더에서 위치의 y 구성 요소를 반전합니다. 'float value = (atan2 (pos.x, -pos.y) + 3.141596)/(2.0 * 3.141596);'가로로 뒤집고 싶다면 x를 뒤집을 수도 있습니다. – Xavier
나는 Y 축을 뒤집기 위해 쉐이더를 편집했고, 소스의 알파 값은 전달 된 색상뿐만 아니라 존중되도록 알파 처리를 변경했습니다. 셰이더가 무엇을하고 있는지 설명하기 위해 코드 주석을 추가했습니다. – Xavier