C++ 使用正确的alpha复制ID3D11Texture2D

C++ 使用正确的alpha复制ID3D11Texture2D,c++,directx,directx-11,C++,Directx,Directx 11,我是DirectX新手,但我已经成功地使用Windows桌面复制API来捕获视频。API还允许您检索鼠标光标信息,包括光标图像的位置、高度、宽度和原始像素数据(在系统内存中)。默认情况下,鼠标光标不会绘制在捕获的屏幕图像上,需要手动处理 我试图将鼠标光标数据“复制”到主屏幕捕获图像中,以创建一个带有可见鼠标光标的图像。到目前为止,我已经能够通过从光标像素数据创建一个ID3D11Texture2D来显示光标,然后执行一个ID3D11DeviceContext::CopySubresourceReg

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

我试图将鼠标光标数据“复制”到主屏幕捕获图像中,以创建一个带有可见鼠标光标的图像。到目前为止,我已经能够通过从光标像素数据创建一个
ID3D11Texture2D
来显示光标,然后执行一个
ID3D11DeviceContext::CopySubresourceRegion
来将光标复制到主屏幕图像,该图像也存储为
ID3D11Texture2D
。主屏幕图像纹理始终为
DXGI\u格式\u B8G8R8A8\u UNORM
格式,原始光标像素数据,至少对于
DXGI\u OUTDUPL\u指针\u形状\u类型\u颜色
形状

我当前的问题似乎与此副本的alpha处理有关。光标将显示,但复制矩形时,光标周围的alpha将改为黑色。下面是它的一个示例:

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


如果
CopySubresourceRegion
不是适合这份工作的工具,我愿意改变我的方法。关于如何使用正确的alpha将光标移到主屏幕图像纹理上,有什么想法吗?

访问GPU alpha混合功能的唯一方法是使用draw命令。复制调用只进行替换,如您所见

您的鼠标光标已经位于“ID3D11Texture2D”中,现在需要的是一个“ID3D11ShaderResourceView”以将其用作纹理,“ID3DVertexShader”和“ID3DPixelShader”对以在曲面中渲染。来自目标曲面的“ID3D11RenderTargetView”

一组“ID3D11RasterizerState”、“ID3D11DepthStencilState”和“ID3D11BlendState”用于配置gpu状态,无深度测试、alpha混合和其他含义的完整设置,默认情况下,大多数设置都是ok的

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

对于这种四边形blit,我通常更喜欢只处理单个常量缓冲区,并从顶点着色器中的SV_VertexID重建顶点位置,但这取决于您

这就是在没有顶点缓冲区的情况下编写blit着色器的方法,使用条形基本体拓扑的单个绘制(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 );
}
struct IA{
uint vid:SV_VertexID;
};    
结构VSPS{
浮动4位置:SV_位置;
float2uv:颜色;
};    
结构根{
向左浮动;
浮顶;
向右浮动;
浮底;
};
ConstantBuffer根:寄存器(b0);
纹理2d纹理:寄存器(t0);
采样器状态采样器:寄存器(s0);
void mainvs(输入IA,输出VSPS){
float x=输入.vid<2?0.f:1.f;
浮点y=(input.vid&1)?1.f:0.f;
output.uv=float2(x,y);
float px=input.vid<2?root_uu.left:root_uu.right;
float py=(input.vid&1)?根目录下:根目录上;;
output.pos=float4(px,py,0.f,1.f);
output.pos.y=1-output.pos.y;
output.pos.xy*=2;
输出位置xy-=1;
}
float4 mainps(在VSPS输入中):SV_目标{
返回纹理样本(采样器样本,输入uv);
}

答案暗示了这一点,但值得明确指出的是,
CopySubresourceRegion
不执行alpha混合。相反,它执行一个简单的矩形复制,覆盖目标中的所有通道(包括alpha)。您看到黑色的原因是源纹理可能位于光标区域之外,或者透明黑色。当观看时,alpha通道被忽略显示,导致不透明的黑色。谢谢各位,我现在开始,在成功实现后,我会回来接受。