2

我正在考虑使用 HLSL 执行从 YUV422 到 RGB 的色彩空间转换。一个四字节的 YUYV 将产生 2 个三字节的 RGB 值,例如,Y1UY2V 将给出 R1G1B1(左像素)和 R2G2B2(右像素)。给定像素着色器中的纹理坐标逐渐增加,我如何区分左侧像素(即所有 R1G1B1)的纹理坐标和右侧像素(即所有 R2G2B2)的纹理坐标。这样我就可以在一个纹理而不是两个纹理上渲染所有 R1G1B1 和所有 R2G2B2。

谢谢!

4

1 回答 1

1

不确定您使用的是哪个版本的 DirectX,但这是我用于 dx11 的版本(请注意,在这种情况下,我在 StructuredBuffer 中发送 yuv 数据,这样我就不用处理行跨度了。您可以应用相同的技术发送您的 yuv 数据当然是纹理(对下面的代码几乎没有什么改动)。

这是像素着色器代码(我假设您的渲染目标与输入图像的大小相同,并且您渲染全屏四边形/三角形)。

StructuredBuffer<uint> yuy;

int w;
int h;

struct psInput
{
float4 p : SV_Position;
float2 uv : TEXCOORD0;
};

float4 PS(psInput input) : SV_Target
{
    //Calculate pixel location within buffer (if you use texture change lookup here)
uint2 xy = input.p.xy;
uint p = (xy.x) + (xy.y * w);
uint pixloc = p / 2;

uint pixdata = yuy[pixloc];

    //Since pixdata is packed, use some bitshift to remove non useful data
uint v  = (pixdata & 0xff000000) >> 24;
uint y1  = (pixdata & 0xff0000) >> 16;
uint u  = (pixdata & 0xff00) >> 8;
uint y0  = pixdata & 0x000000FF;

    //Check if you are left/right pixel
uint y = p % 2 == 0 ? y0: y1;

    //Convert yuv to rgb
float cb = u;
float cr = v;

float r  = (y + 1.402 * (cr - 128.0));
float g =  (y - 0.344 * (cb - 128.0) - 0.714 * (cr - 128));
    float b =  (y + 1.772 * (cb - 128));

return float4(r,g,b,1.0f) / 256.0f;
}

希望有帮助。

于 2013-09-07T17:01:33.617 回答