使用适当的alpha复制ID3D11Texture2D

时间:2016-04-22 13:55:27

标签: c++ directx directx-11

我是Direct X的新手,但我已经成功地使用Windows桌面复制API来捕获视频。 API还允许您检索鼠标光标信息,包括光标图像的位置,高度,宽度和原始像素数据(在系统内存中)。默认情况下,鼠标光标未在捕获的屏幕图像上绘制,需要手动处理。

我正在尝试将此鼠标光标数据“复制”到主屏幕捕获图像,以创建具有可见鼠标光标的单个图像。到目前为止,我已经能够通过从光标像素数据创建ID3D11Texture2D来显示光标,然后预先形成ID3D11DeviceContext::CopySubresourceRegion以将光标复制到主屏幕图像,也存储为{{ 1}}。主屏幕图像纹理始终采用ID3D11Texture2D格式,原始光标像素数据seems to be in the same format,至少为DXGI_FORMAT_B8G8R8A8_UNORM形状。

我当前的问题似乎与此副本的Alpha处理有关。光标显示,但是当复制矩形时,光标周围的alpha将填充为黑色。以下是它的示例:Black border around mouse

另外,对我来说这很重要,因为最终的纹理会从视频内存直接进入视频编码器。

如果DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR不适合这项工作,我愿意改变我的方法。关于如何将这个光标放到​​具有正确alpha的主屏幕图像纹理的任何想法?

1 个答案:

答案 0 :(得分:3)

访问GPU的alpha混合功能的唯一方法是使用绘图命令。正如您所见,复制通话仅进行替换。

你已经将鼠标光标放在了ID3D11Texture2D'中,你现在需要的是一个' ID3D11ShaderResourceView'将它用作纹理,ID3DVertexShader'和' ID3DPixelShader'对在表面渲染。一个' ID3D11RenderTargetView'来自目的地表面。

一组ID3D11RasterizerState' ID3D11DepthStencilState'和' ID3D11BlendState'配置没有深度测试,alpha混合和其他意义完全设置的gpu状态,默认情况下大多数都应该没问题。

然后你需要绘制一个四边形以显示你的光标。根据您编写着色器的方式,您将需要一个常量缓冲区,一个顶点缓冲区和一个输入布局,或者两者都需要。

对于那种四元素,我通常更喜欢只处理一个常量缓冲区并从顶点着色器中的SV_VertexID重建顶点位置,但这取决于你。

这是你可以编写没有顶点缓冲区来管理的blit着色器的方法,带有条带原始拓扑的单个Draw(4,0)就足够了:

struct IA {
    uint vid : SV_VertexID;
};    
struct VSPS {
    float4 pos : SV_Position;
    float2 uv : COLOR;
};    
struct Root {
    float left;
    float top;
    float right;
    float bottom;
};

ConstantBuffer<Root> root_ : register(b0);
Texture2D<float4> texture_ : register(t0);
SamplerState sampler_ : register(s0);

void mainvs( in IA input, out VSPS output ) {
    float x = input.vid < 2 ? 0.f : 1.f;
    float y = (input.vid & 1) ? 1.f : 0.f;

    output.uv = float2(x, y);

    float px = input.vid < 2 ? root_.left : root_.right;
    float py = (input.vid & 1) ? root_.bottom : root_.top;;

    output.pos = float4(px,py,0.f,1.f);

    output.pos.y = 1 - output.pos.y;
    output.pos.xy *= 2;
    output.pos.xy -= 1;
}

float4 mainps( in VSPS input ) : SV_TARGET {
    return texture_.Sample( sampler_, input.uv );
}