Search code examples
wpfimagec#-4.0hlslpixel-shader

Pixel Shader effect is not working for Red, Green & Blue


I'm really looking for a solution for the problem of applying the shader effect of the colours Red, Green & Blue. When I move the slider for Red, Green & Blue there is no change in the image.

Note: Brightness and Contrast is working in this code.

Code for ShaderEffect class:

 public class BrightContrastEffect : ShaderEffect
    {
        private static PixelShader m_shader = new PixelShader() { UriSource = MakePackUri("bricon.ps") };

        public BrightContrastEffect()
        {
            PixelShader = m_shader;
            UpdateShaderValue(InputProperty);
            UpdateShaderValue(BrightnessProperty);
            UpdateShaderValue(ContrastProperty);
            UpdateShaderValue(RedProperty);
            UpdateShaderValue(GreenProperty);
            UpdateShaderValue(BlueProperty);
        }

        public static Uri MakePackUri(string relativeFile)
        {
            Assembly a = typeof(BrightContrastEffect).Assembly;
            string assemblyShortName = a.ToString().Split(',')[0];
            string uriString = "pack://application:,,,/" +assemblyShortName +";component/" +relativeFile;
            return new Uri(uriString);
        }

        public Brush Input
        {
            get { return (Brush)GetValue(InputProperty); }
            set { SetValue(InputProperty, value); }
        }

        public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(BrightContrastEffect), 0);

        public float Brightness
        {
            get { return (float)GetValue(BrightnessProperty); }
            set { SetValue(BrightnessProperty, value); }
        }

        public static readonly DependencyProperty BrightnessProperty = DependencyProperty.Register("Brightness", typeof(double), typeof(BrightContrastEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(0)));

        public float Contrast
        {
            get { return (float)GetValue(ContrastProperty); }
            set { SetValue(ContrastProperty, value); }
        }

        public static readonly DependencyProperty ContrastProperty = DependencyProperty.Register("Contrast", typeof(double), typeof(BrightContrastEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(1)));


        public float Red
        {
            get { return (float)GetValue(RedProperty); }
            set { SetValue(RedProperty, value); }
        }

        public static readonly DependencyProperty RedProperty = DependencyProperty.Register("Red", typeof(double), typeof(BrightContrastEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(2)));

        public float Green
        {
            get { return (float)GetValue(GreenProperty); }
            set { SetValue(RedProperty, value); }
        }

        public static readonly DependencyProperty GreenProperty = DependencyProperty.Register("Green", typeof(double), typeof(BrightContrastEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(3)));

        public float Blue
        {
            get { return (float)GetValue(BlueProperty); }
            set { SetValue(BlueProperty, value); }
        }

        public static readonly DependencyProperty BlueProperty = DependencyProperty.Register("Blue", typeof(double), typeof(BrightContrastEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(4)));

    }
}

XAML Code:

<Image Name="ViewedPhoto" Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" Stretch="Uniform"  VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
            <Image.Effect>
                <l:BrightContrastEffect 
                    Brightness="{Binding ElementName=bVal, Path=Value}"
                    Contrast="{Binding ElementName=cVal, Path=Value}"
                    Red="{Binding ElementName=rVal, Path=Value}"
                    Green="{Binding ElementName=gVal, Path=Value}"
                    Blue="{Binding ElementName=blVal, Path=Value}"
                    />
            </Image.Effect>
</Image>
<!-- Sliders for Reg, Green & Blue -->
<TextBlock Text="Red"/>
<Slider Maximum="1" Minimum="-1" Name="rVal" TickFrequency="1" TickPlacement="BottomRight"/>
<TextBox Text="{Binding ElementName=rVal, Path=Value, 
UpdateSourceTrigger=PropertyChanged}"  TextAlignment="Right" Width="30" />

<TextBlock Text="Green"/>
<Slider Maximum="1" Minimum="-1" Name="gVal" TickFrequency="1" TickPlacement="BottomRight"/>
<TextBox Text="{Binding ElementName=gVal, Path=Value, 
UpdateSourceTrigger=PropertyChanged}"  TextAlignment="Right" Width="30" />

<TextBlock Text="Blue"/>
<Slider Maximum="1" Minimum="-1" Name="blVal" TickFrequency="1" TickPlacement="BottomRight"/>
<TextBox Text="{Binding ElementName=blVal, Path=Value, 
UpdateSourceTrigger=PropertyChanged}"  TextAlignment="Right" Width="30" />

HLSL Shader code:

float Brightness : register(C0);
float Contrast : register(C1);
float Red: register(C2);
float Green: register(C3);
float Blue: register(C4);

sampler2D Texture1Sampler : register(S0);

float4 main(float2 uv : TEXCOORD) : COLOR
{

    float4 pixelColor = tex2D(Texture1Sampler, uv);
    pixelColor.rgb /= pixelColor.a;

    // Apply contrast.
    pixelColor.rgb = ((pixelColor.rgb - 0.5f) * max(Contrast, 0)) + 0.5f;

    // Apply brightness.
    pixelColor.rgb += Brightness;

    // Return final pixel color.
    pixelColor.rgb *= pixelColor.a;

    pixelColor.r += Red;
    pixelColor.g += Green;
    pixelColor.b += Blue;

//return float4(Red, Green Blue, 1);
    return pixelColor;
}

Solution

  • This is the answer as per the suggestion from Nico Schertler

    float Brightness : register(C0);
    float Contrast : register(C1);
    float Red: register(C2);
    float Green: register(C3);
    float Blue: register(C4);
    
    sampler2D Texture1Sampler : register(S0);
    
    float4 main(float2 uv : TEXCOORD) : COLOR
    {
    
        float4 pixelColor = tex2D(Texture1Sampler, uv);
        pixelColor.rgb /= pixelColor.a;
    
        // Apply contrast.
        //pixelColor.rgb = ((pixelColor.rgb - 1.5f) * max(Contrast, 1)) + 1.5f;
        pixelColor.rgb = ((pixelColor.rgb - 0.5f) * max(Contrast+1, 0)) + 0.5f;
    
        // Apply brightness.
        pixelColor.rgb += Brightness;
    
    
        // Return final pixel color.
        pixelColor.rgb *= pixelColor.a;
    
        pixelColor.r += Red;
        pixelColor.g += Green;
        pixelColor.b += Blue;
    
    //return float4(Red, Green Blue, 1);
        return pixelColor;
    }