着色器shader
+ -

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;
}

0 篇笔记 写笔记

作者信息
站长漫谈
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!