我想写一个带有输入图像的像素着色器,并将一个Hue范围(即HSV)的所有颜色转换为另一个Hue Range。
我的动机很简单:我想以不同的方式为一堆不同的纹理着色,但我不想为整个纹理着色,只是在特定范围内具有色调的部分。这样,我可以绘制一辆赛车的图像,然后使用像素着色器更改汽车上的条纹和徽标的颜色。
我在线查看了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,如果这些信息对任何人都很重要。
答案 0 :(得分:6)
看看"post RGB to HSV" sample over at the NVidia Shader Library page。这可能会给你一些启发。
否则我猜你可以“简单地”使用the formula from Wikipedia将RGB颜色转换为像素着色器中的HSV,然后从那里取出。
答案 1 :(得分:3)
制作一个矩阵,围绕[1,1,1]轴(亮度轴)*旋转RGB颜色一个角度,将源颜色旋转到目标颜色上。将此矩阵设置为像素着色器常量。
在像素着色器中,通过此矩阵变换像素颜色。然后,根据未转换像素的色调和源颜色的色调之间的角度,在未转换和转换的颜色之间进行透镜化。当角度很小时,使用变换后的颜色。当角度很大时,使用未转换的颜色。
要确定像素的色调,请从像素中减去RGB *的平均值。该向量与[1,0,0]之间的角度是色调。
*我知道亮度不是那么简单,但对于这种情况,这是一个足够好的近似值。
答案 2 :(得分:2)
看看
答案 3 :(得分: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;
}