burst2flame
Topic Author
Posts: 23
Joined: 11 Mar 2024, 18:04

Shader Input Color Incorrect

06 Sep 2024, 23:43

Working with shaders, it seems like the color input comes in different than what I input into the xaml. I made a simple effect shader that simply outputs the input color. But on the screen the colors don't match. I input "#888888" but what is shown on the screen is "#c1c1c1". Is there some function or multiplier I need to get the original color? The color of the outer rectangle should be the same as the inner square. Thanks for your help!
Screenshot 2024-09-06 143348.png
Screenshot 2024-09-06 143348.png (411 Bytes) Viewed 803 times
Xaml:
<Rectangle Fill="White">
            <Rectangle.Effect>
                <local:GrayscaleEffect Color="#888888"/>
            </Rectangle.Effect>
        </Rectangle>
        <Rectangle Fill="#888888" Width="100" Height="100"/>
Grayscale.noesiseffect
#include "EffectHelpers.h"

uniforms
{
    fixed4 _color;
};

fixed4 main_effect()
{
    fixed4 c = GetInput();

    return float4
    (
        _color.r,
        _color.g,
        _color.b,
        _color.a
    );
}
GrayscaleEffect.cs
using System;
using System.Runtime.InteropServices;
using Noesis;

namespace Quantum_Survivor
{
    public class GrayscaleEffect : ShaderEffect
    {
        private static NoesisShader Shader;

        public GrayscaleEffect()
        {
            if (Shader == null) Shader = CreateShader();

            SetShader(Shader);
            SetConstantBuffer(_constants);
        }

        #region Color
        public Color Color
        {
            get { return (Color)GetValue(ColorProperty); }
            set { SetValue(ColorProperty, value); }
        }

        public static readonly DependencyProperty ColorProperty = DependencyProperty.Register(
            "Color", typeof(Color), typeof(GrayscaleEffect),
            new PropertyMetadata(Colors.White, OnColorChanged));

        private static void OnColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            GrayscaleEffect this_ = (GrayscaleEffect)d;
            this_._constants.color = (Color)e.NewValue;
            this_.InvalidateConstantBuffer();
        }
        #endregion

        [StructLayout(LayoutKind.Sequential)]
        private class Constants
        {
            public Color color = Colors.White;
        }

        private Constants _constants = new Constants();
    }
}
 
User avatar
jsantos
Site Admin
Posts: 4070
Joined: 20 Jan 2012, 17:18
Contact:

Re: Shader Input Color Incorrect

09 Sep 2024, 17:21

Working with shaders, it seems like the color input comes in different than what I input into the xaml. I made a simple effect shader that simply outputs the input color. But on the screen the
Is this using linear rendering? Right now, for linear rendering, colors must be manually converted to linear space before storing then in the constant buffer.
 
burst2flame
Topic Author
Posts: 23
Joined: 11 Mar 2024, 18:04

Re: Shader Input Color Incorrect

09 Sep 2024, 20:47

I tried converting, but the colors don't match still. Before it gave me a lighter color than it was supposed to, but now it's giving me a darker color than it's supposed to. How am I supposed to convert?

Here is my conversion code:

ColorExtensions.cs
using Mathf = UnityEngine.Mathf;

namespace Quantum_Survivor
{
    public static class ColorExtensions
    {
        
        public static Noesis.Color GammaToLinear(this Noesis.Color color)
        {
            return new Noesis.Color {
                A = color.A,
                R = (byte)Mathf.RoundToInt(Mathf.GammaToLinearSpace(color.R)),
                G = (byte)Mathf.RoundToInt(Mathf.GammaToLinearSpace(color.G)),
                B = (byte)Mathf.RoundToInt(Mathf.GammaToLinearSpace(color.B))
            };
        }

        public static Noesis.Color LinearToGamma(this Noesis.Color color)
        {
            return new Noesis.Color {
                A = color.A,
                R = (byte)Mathf.RoundToInt(Mathf.LinearToGammaSpace(color.R)),
                G = (byte)Mathf.RoundToInt(Mathf.LinearToGammaSpace(color.G)),
                B = (byte)Mathf.RoundToInt(Mathf.LinearToGammaSpace(color.B))
            };
        }

    }
}

GrayscaleEffect.cs

using System;
using System.Runtime.InteropServices;
using Noesis;

namespace Quantum_Survivor
{
    public class GrayscaleEffect : ShaderEffect
    {
        private static NoesisShader Shader;

        public GrayscaleEffect()
        {
            if (Shader == null) Shader = CreateShader();

            SetShader(Shader);
            SetConstantBuffer(_constants);
        }

        #region Color
        public Color Color
        {
            get { return (Color)GetValue(ColorProperty); }
            set { SetValue(ColorProperty, Color); }
        }

        public static readonly DependencyProperty ColorProperty = DependencyProperty.Register(
            "Color", typeof(Color), typeof(GrayscaleEffect),
            new PropertyMetadata(Colors.White, OnColorChanged));

        private static void OnColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            GrayscaleEffect this_ = (GrayscaleEffect)d;
            this_._constants.color = ((Color)e.NewValue).GammaToLinear();
            this_.InvalidateConstantBuffer();
        }
        #endregion

        [StructLayout(LayoutKind.Sequential)]
        private class Constants
        {
            public Color color = Colors.White;
        }

        private Constants _constants = new Constants();
    }
}

 
User avatar
jsantos
Site Admin
Posts: 4070
Joined: 20 Jan 2012, 17:18
Contact:

Re: Shader Input Color Incorrect

10 Sep 2024, 14:40

Could you please confirm if you're using linear rendering in Unity? This will help ensure that I can accurately reproduce your scenario.

When working in linear color space, more than 8 bits are typically required for proper color representation. Given that, the function responsible for the gamma-to-linear conversion should resemble something like this:
public static Noesis.Color GammaToLinear(this Noesis.Color color)
{
    return new Noesis.Color {
        A = color.A,
        ScR = Mathf.GammaToLinearSpace(color.R),
        ScG = Mathf.GammaToLinearSpace(color.G),
        ScB = Mathf.GammaToLinearSpace(color.B)
    };
}
This approach ensures that the RGB values are correctly converted from gamma to linear space.

Let me know if you're working with linear rendering, and feel free to test this conversion.
 
burst2flame
Topic Author
Posts: 23
Joined: 11 Mar 2024, 18:04

Re: Shader Input Color Incorrect

11 Sep 2024, 00:32

I am using Linear Colorspace. For some reason I couldn't get the color conversions to work in unity but the following code worked in the hlsl. So you were right! I can get the color to match now.
float4 GammaToLinear(float4 srgbColor)
{
    return srgbColor * (srgbColor * (srgbColor * 0.305306011 + 0.682171111) + 0.012522878);
}
I'll try to get it working in unity too.

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 1 guest