HLSLを初めて使用しています。 DXGI Desktop Duplication APIを使用してキャプチャした画像の色空間をBGRAからYUV444にレンダリングターゲットとしてテクスチャを使用して変換しようとしています。
ピクセルシェーダで必要な変換を実行するように設定しました。そして、4:2:0サブサンプリングされたYUVをターゲットテクスチャからレンダリングし、ffmpegを使用してH264としてエンコードすると、イメージが表示されます。
問題は - greenishです。
シェーダの入力カラー情報は浮動小数点データ型ですが、RGBからYUVへの変換に使用できる係数行列は整数の色情報を前提としています。
クランプ機能を使用して整数を入力色から取り除くと、精度が失われます。
ご意見やご指摘をお待ちしております。他の情報が役立つかどうかお知らせください。
私は最初にそれを使って作業しているように、私が書いたピクセルシェーダーを疑う。ここにピクセルシェーダがあります。DirectX11ピクセルシェーダを使用したBGRAからYUV444への緑色のイメージ
float3 rgb_to_yuv(float3 RGB)
{
float y = dot(RGB, float3(0.29900f, -0.16874f, 0.50000f));
float u = dot(RGB, float3(0.58700f, -0.33126f, -0.41869f));
float v = dot(RGB, float3(0.11400f, 0.50000f, -0.08131f));
return float3(y, u, v);
}
float4 PS(PS_INPUT input) : SV_Target
{
float4 rgba, yuva;
rgba = tx.Sample(samLinear, input.Tex);
float3 ctr = float3(0, 0, .5f);
return float4(rgb_to_yuv(rgba.rgb) + ctr, rgba.a);
}
ターゲットはCPUで読み取り可能なテクスチャにマッピングされ、3つのバイト配列にYUV444データをコピーし、エンコーダlibx264 ffmpegのために供給されるレンダリング。 エンコーダは、エンコードされたパケットをビデオファイルに書き込みます。
ここでは、ピクセルの2×2行列ごとに1つのU(Cb)と1つのV(Cr)と4つのY値を取っています。
私はテクスチャからYUV420データを取得する:
for (size_t h = 0, uvH = 0; h < desc.Height; ++h)
{
for (size_t w = 0, uvW = 0; w < desc.Width; ++w)
{
dist = resource1.RowPitch *h + w * 4;
distance = resource.RowPitch *h + w * 4;
distance2 = inframe->linesize[0] * h + w;
data = sptr[distance + 2 ];
pY[distance2] = data;
if (w % 2 == 0 && h % 2 == 0)
{
data1 = sptr[distance + 1];
distance2 = inframe->linesize[1] * uvH + uvW++;
pU[distance2] = data1;
data1 = sptr[distance ];
pV[distance2] = data1;
}
}
if (h % 2)
uvH++;
}
EDIT1:ブレンド状態DESCを追加する:
D3D11_BLEND_DESC BlendStateDesc;
BlendStateDesc.AlphaToCoverageEnable = FALSE;
BlendStateDesc.IndependentBlendEnable = FALSE;
BlendStateDesc.RenderTarget[0].BlendEnable = TRUE;
BlendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
BlendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
BlendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
BlendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
BlendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
BlendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
BlendStateDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
hr = m_Device->CreateBlendState(&BlendStateDesc, &m_BlendState);
FLOAT blendFactor[4] = {0.f, 0.f, 0.f, 0.f};
m_DeviceContext->OMSetBlendState(nullptr, blendFactor, 0xffffffff);
m_DeviceContext->OMSetRenderTargets(1, &m_RTV, nullptr);
m_DeviceContext->VSSetShader(m_VertexShader, nullptr, 0);
m_DeviceContext->PSSetShader(m_PixelShader, nullptr, 0);
m_DeviceContext->PSSetShaderResources(0, 1, &ShaderResource);
m_DeviceContext->PSSetSamplers(0, 1, &m_SamplerLinear);
m_DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
EDIT2:CPUで計算YUVの値:45 200 170および値浮動小数点計算を伴うピクセルシェーダーの後:86 141 104. 対応するRGB:48 45 45。違いを生むものは何ですか?
同じ問題に直面しています –
なぜVのオフセットは0.5ですが、Uはありませんか?それは非対称だと思われる – harold
@harold、(0、0.5、0.5)で試してみましたが問題は同じです。緑の効果が他の色効果に変わりました。 –