代码之家  ›  专栏  ›  技术社区  ›  Mark P Neyer

hlsl pixel shader-更改特定色调的图像颜色

  •  4
  • Mark P Neyer  · 技术社区  · 16 年前

    我想编写一个像素着色程序,它获取一个输入图像,并将一个色调范围(即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游戏工作室工作,如果这些信息对任何人都很重要的话。

    4 回复  |  直到 11 年前
        1
  •  6
  •   Tchami    16 年前

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

    否则,我想你可以“简单”地将一个RGB颜色转换为HSV在你的像素着色中使用 the formula from Wikipedia 然后从那里拿走。

        2
  •  3
  •   bmcnett    15 年前

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

    在像素明暗器中,通过该矩阵变换像素颜色。然后,根据未转换像素的色调和源颜色的色调之间的角度,在未转换和转换的颜色之间进行LERP。当角度很小时,使用转换后的颜色。当角度较大时,使用未转换的颜色。

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

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

        4
  •  1
  •   Delta9    11 年前

    色调/饱和度/亮度/对比度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; 
    }
    
    推荐文章