【问题标题】:HLSL Pixel Shader - Change Image Color For Specific HueHLSL 像素着色器 - 更改特定色调的图像颜色
【发布时间】:2014-07-09 18:21:34
【问题描述】:

我想编写一个像素着色器,它接受输入图像,并将一个色调范围(即 HSV)的所有颜色转换为另一个色调范围。

我的动机很简单:我想给一堆不同的纹理上色,但我不想给整个纹理上色,只是在特定范围内有色调的部分。这样,我可以绘制一张赛车的图像,然后使用像素着色器仅更改汽车上的条纹和徽标的颜色。

我在网上查看了 HLSL 文档,找不到任何可以处理色调的内容。是否有在线可用的 HLSL 代码库?

这是我想要完成的一些伪代码:

external float SrcMinHue,SrcMaxHue,TargetMin
void changeHues(image source)
{
   foreach x,y in image:
   {
      float sourceHue = getHue(source,x,y)
      if (SrcMinHue < sourceHue < SrcNaxHue):
          setHue(source,x,y,(TargetMin + (sourceHue - MinHue))
   }
}

如果该信息对任何人都很重要,我正在与 XNA Game Studio 合作。

【问题讨论】:

    标签: shader hlsl


    【解决方案1】:

    看看"post RGB to HSV" sample over at the NVidia Shader Library page。这可能会给你一些启发。

    否则我猜您可以使用the formula from Wikipedia 在像素着色器中“简单地”将 RGB 颜色转换为 HSV,然后从那里获取。

    【讨论】:

      【解决方案2】:

      创建一个矩阵,将 RGB 颜色围绕 [1,1,1] 轴(亮度轴)* 旋转一个角度,将源颜色旋转到目标颜色。将此矩阵设置为像素着色器常量。

      在像素着色器中,通过这个矩阵变换像素颜色。然后,根据未变换像素的色调和源颜色的色调之间的角度,在未变换的颜色和变换的颜色之间进行调整。当角度较小时,使用变换后的颜色。角度大时,使用未变换的颜色。

      要确定像素的色调,请从像素中减去其 RGB* 的平均值。这个向量和 [1,0,0] 之间的夹角就是色调。

      *我知道亮度并不是这么简单,但对于这种情况来说,这是一个足够好的近似值。

      【讨论】:

        【解决方案3】:

        色相/饱和度/亮度/对比度 HLSL 像素着色器 (shazzam .fx)

        /// <class>7Aliens HSBC Hue/Saturation/Brightness/Contrast</class>
        /// <description>Blend modes Brightness/Contrast (Photoshop CS) with Hue and Saturation.</description>
        
        sampler2D input : register(s0);
        
        /// <summary>The brightness offset.</summary>
        /// <minValue>-2</minValue>
        /// <maxValue>2</maxValue>
        /// <defaultValue>0</defaultValue>
        float SliderBrightnes : register(C0);
        
        /// <summary>The brightness offset.</summary> 
        /// <minValue>-1</minValue>
        /// <maxValue>1</maxValue>
        /// <defaultValue>0</defaultValue>
        float SliderContrast : register(C1);
        
        /// <summary>The brightness offset.</summary>
        /// <minValue>-1</minValue>
        /// <maxValue>1</maxValue>
        /// <defaultValue>0</defaultValue>
        float sliderSaturation : register(C2);
        
        /// <summary>The brightness offset.</summary>
        /// <minValue>-180</minValue>
        /// <maxValue>180</maxValue>
        /// <defaultValue>0</defaultValue>
        float sliderHue : register(C3);
        
        float3x3 QuaternionToMatrix(float4 quat)
        {
            float3 cross = quat.yzx * quat.zxy;
            float3 square= quat.xyz * quat.xyz;
            float3 wimag = quat.w * quat.xyz;
        
            square = square.xyz + square.yzx;
        
            float3 diag = 0.5 - square;
            float3 a = (cross + wimag);
            float3 b = (cross - wimag);
        
            return float3x3(
            2.0 * float3(diag.x, b.z, a.y),
            2.0 * float3(a.z, diag.y, b.x),
            2.0 * float3(b.y, a.x, diag.z));
        }
        
        const float3 lumCoeff = float3(0.2125, 0.7154, 0.0721);
        
        float4 Desaturate(float3 color, float Desaturation)
        {
            float3 grayXfer = float3(0.3, 0.59, 0.11);
            float grayf = dot(grayXfer, color);
            float3 gray = float3(grayf, grayf, grayf);
            return float4(lerp(color, gray, Desaturation), 1.0);
        }
        
        float4 main(float2 uv : TEXCOORD) : COLOR 
        { 
            float4  cInput; 
            cInput = tex2D( input , uv.xy);
        
            float4 inputColor;
            inputColor = cInput;
            float4 blendColor;
            blendColor = cInput;
            float4 resultColor;
            resultColor = cInput;
        
            float3 hsv; 
            float3 intensity;           
            float3 root3 = float3(0.57735, 0.57735, 0.57735);
            float half_angle = 0.5 * radians(sliderHue); // Hue is radians of 0 tp 360 degree
            float4 rot_quat = float4( (root3 * sin(half_angle)), cos(half_angle));
            float3x3 rot_Matrix = QuaternionToMatrix(rot_quat);     
            resultColor.rgb = mul(rot_Matrix, inputColor.rgb);
        
            resultColor = Desaturate(resultColor, -sliderSaturation);
        
            inputColor = resultColor;`enter code here`
            blendColor = resultColor;
            resultColor = resultColor;
        
            blendColor.rgb = clamp(blendColor.rgb / blendColor.a, 0, 1);
            if (resultColor.r > 0.5) resultColor.r = 1 - (1 - 2 * (resultColor.r - 0.5)) * (1 - blendColor.r); else resultColor.r = (2 * resultColor.r) * blendColor.r;
            if (resultColor.g > 0.5) resultColor.g = 1 - (1 - 2 * (resultColor.g - 0.5)) * (1 - blendColor.g); else resultColor.g = (2 * resultColor.g) * blendColor.g;
            if (resultColor.b > 0.5) resultColor.b = 1 - (1 - 2 * (resultColor.b - 0.5)) * (1 - blendColor.b); else resultColor.b = (2 * resultColor.b) * blendColor.b;
        
            float4 colorOverlay = resultColor;
            colorOverlay = colorOverlay * SliderContrast;
            resultColor.rgb = (1 - (colorOverlay.a)) * inputColor.rgb + colorOverlay.rgb;       
        
            inputColor = resultColor;
            blendColor = resultColor;
        
            float4 colorScreen = resultColor;
            colorScreen.rgb = (1.0f - (1.0f - inputColor.rgb) * (1.0f - blendColor.rgb));
            colorScreen = -(colorScreen * SliderBrightnes * -(1 - inputColor.r));
            resultColor.rgb = (1 - (colorScreen.a)) * inputColor.rgb + colorScreen.rgb;
        
            return resultColor; 
        }
        

        【讨论】:

          【解决方案4】:
          猜你喜欢
          • 1970-01-01
          • 2020-07-26
          • 2018-11-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-14
          相关资源
          最近更新 更多