4

入力画像を取得し、1 つの色相範囲 (つまり HSV) のすべての色を別の色相範囲に変換するピクセル シェーダーを作成したいと考えています。

私の動機は単純です。さまざまなテクスチャの束を別々に色付けしたいのですが、テクスチャ全体ではなく、特定の範囲の色相を持つ部分だけを色付けしたいと考えています。そうすれば、レーシング カーのイメージを 1 つ描画してから、ピクセル シェーダーを使用して車のストライプとロゴの色だけを変更できます。

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 を使用しています。

4

4 に答える 4

6

NVidia シェーダー ライブラリ ページで、「RGB から HSV へのポスト」サンプルをご覧ください。それはあなたにいくつかのインスピレーションを与えるかもしれません。

それ以外の場合は、Wikipedia の式を使用して、ピクセル シェーダーで RGB カラーを HSV に「単純に」変換し、そこから取得できると思います。

于 2009-09-08T17:19:07.240 に答える
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; 
}
于 2014-07-09T10:21:34.960 に答える
3

[1,1,1] 軸 (輝度軸)* を中心に、ソース カラーをターゲット カラーに回転させる角度で RGB カラーを回転させるマトリックスを作成します。この行列をピクセル シェーダー定数として設定します。

ピクセル シェーダーでは、このマトリックスによってピクセルの色を変換します。次に、変換されていないピクセルの色相と元の色の色相の間の角度に従って、変換されていない色と変換された色の間で lerp します。角度が小さい場合は、変換された色を使用します。角度が大きい場合は、変換前の色を使用します。

ピクセルの色相を決定するには、そのピクセルから RGB* の平均を引きます。このベクトルと [1,0,0] の間の角度が色相です。

*輝度がこれほど単純ではないことは承知していますが、このケースではこれで十分な近似値です。

于 2011-04-18T22:42:09.627 に答える
2

を見てみましょう

于 2010-01-24T14:48:47.707 に答える