D3D11像素着色器
2024-05-14
61
0
这段像素着色器的代码实现了从YUV图像到RGB图像的转换,并保留了原始图像的alpha通道。
让我们逐行解释代码:
float4 yuva = {txY.Sample(samLinear, input.Tex).r, txU.Sample(samLinear, input.Tex).r, txV.Sample(samLinear, input.Tex).r, 0};
这一行从三个纹理(txY,txU,txV)中分别采样Y、U和V通道的值,并将它们存储在一个4维向量中。通常,Y通道存储亮度信息,而U和V通道存储色度信息。
yuva -= float4(0, .5f, .5f, 0);
这一行对YUV值进行修正,将U和V通道的取值范围从[0, 1]转换到[-0.5, 0.5],这是因为在某些情况下,U和V的取值范围可能是[-0.5, 0.5],而不是[0, 1]。
return float4(yuv_to_rgb2(yuva.xyz), yuva.w);
这一行调用了之前提到的 yuv_to_rgb2 函数,将修正后的YUV值转换为RGB值,并返回一个包含RGB值和原始alpha通道值的四维向量作为像素的颜色值。
float4 PS(PS_INPUT input) : SV_Target
{
float4 yuva = {txY.Sample(samLinear, input.Tex).r, txU.Sample(samLinear, input.Tex).r, txV.Sample(samLinear, input.Tex).r, 0};
yuva -= float4(0, .5f, .5f, 0);
return float4(yuv_to_rgb2(yuva.xyz), yuva.w); // don't lose alpha
}
YUV转RGB使用的着色器函数:
Texture2D txY : register(t0);
Texture2D txU : register(t1);
Texture2D txV : register(t2);
SamplerState samLinear : register(s0);
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD;//纹理坐标
};
float3 yuv_to_rgb(float3 YUV)
{
/*Y'= 0.299*R' + 0.587*G' + 0.114*B'
U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')
V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')
R' = Y' + 1.140*V'
G' = Y' - 0.394*U' - 0.581*V'
B' = Y' + 2.032*U'*/
float u = YUV.y;
float v = YUV.z;
float r = YUV.x + 1.403f*v;
float g = YUV.x - 0.344f*u - 1.403f*v;
float b = YUV.x + 1.770f*u;
/*if (r < 0.018 && g < 0.018 && b < 0.018)
{*/
/*r = (r < 0.018) ? 4.5*r : 1.099*pow(r, 0.45) - 0.099;
g = (g < 0.018) ? 4.5*g : 1.099*pow(g, 0.45) - 0.099;
b = (b < 0.018) ? 4.5*b : 1.099*pow(b, 0.45) - 0.099;*/
/*}
else
{
r = 1.099*pow(r, 0.45) - 0.099;
g = 1.099*pow(g, 0.45) - 0.099;
b = 1.099*pow(b, 0.45) - 0.099;
}*/
return float3(r, g, b);
}
float3 rgb_to_yuv(float3 RGB)
{
float y = dot(RGB, float3(0.299, 0.587, 0.114));
float u = (RGB.z - y) * 0.565;
float v = (RGB.x - y) * 0.713;
return float3(y, u, v);
}
float3 rgb_to_yuv1(float3 RGB)
{
float y = RGB.x * 0.299 + RGB.y * 0.587 + RGB.z * 0.114;
float u = -RGB.x * 0.169 - RGB.y * 0.331 + RGB.z * 0.500;
float v = RGB.x * 0.500 - RGB.y * 0.419 - RGB.z * 0.081;
return float3(y, u, v);
}
float3 yuv_to_rgb1(float3 YUV)
{
float u = YUV.y;
float v = YUV.z;
float r = YUV.x + 1.400*v;
float g = YUV.x - 0.343*u - 0.711*v;
float b = YUV.x + 1.765*u;
return float3(r, g, b);
}
float3 yuv_to_rgb2(float3 YUV)
{
float y = YUV.x;
float u = YUV.y;
float v = YUV.z;
float r = y + 1.140*v;
float g = y - 0.395*u - 0.581*v;
float b = y + 2.032*u;
return float3(r, g, b);
}
//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS(PS_INPUT input) : SV_Target
{
//这一行从三个纹理(txY,txU,txV)中分别采样Y、U和V通道的值,并将它们存储在一个4维向量中。
float4 yuva = {
txY.Sample(samLinear, input.Tex).r,
txU.Sample(samLinear, input.Tex).r,
txV.Sample(samLinear, input.Tex).r,
0
};
//return yuva; //For RGB
//YUV to RGB uncomment the below 2 lines
yuva -= float4(0, .5f, .5f, 0);
float4 f = float4(yuv_to_rgb2(yuva.xyz), yuva.w); // don't lose alpha
//f.y = 0;
//f.z = 0;
return f;
}