2009-09-08 108 views
4

我想編寫一個像素着色器,它接受輸入圖像,並將一個色調範圍(即HSV)的所有顏色轉換爲另一個色調範圍。我的動機很簡單:我想以不同的顏色對一堆不同的紋理着色,但我不想着色整個紋理,只是色調在特定範圍內的部分。這樣,我可以繪製出賽車的一幅圖像,然後使用像素着色器更改汽車上條紋和徽標的顏色。HLSL像素着色器 - 更改特定色相的圖像顏色

我在網上查看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遊戲工作室的工作,如果這些信息關係到人。

回答

3

作出這樣的旋轉圍繞[1,1,1]軸(亮度軸)RGB顏色的矩陣*由將您的源顏色旋轉到目標顏色的角度。將此矩陣設置爲像素着色器常量。

在像素着色器中,通過此矩陣轉換像素顏色。然後,根據未轉換像素的色調與源色調之間的角度,在未轉換和已轉換的顏色之間進行lerp。當角度較小時,使用轉換後的顏色。當角度較大時,請使用未轉換的顏色。

要確定像素的色調,請從像素中減去RGB *的平均值。這個矢量與[1,0,0]之間的角度是色調。我知道亮度並不是這麼簡單,但對於這種情況來說,這是一個足夠好的近似值。

1

色相/飽和度/亮度/對比度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; 
}