qt+gxdi+ffmpeg远程控制(八)

之前编码数据是直接从gxdi获取的纹理中复制出来,但是参照obs的渲染模式,编码所需的数据不仅仅是屏幕图像,还可能需要如用户自定义场景(比如屏幕上方会有一些文字),包括鼠标的绘制等。因此,传入编码器的数据应该是经过渲染之后的数据,这里就要用到dx11的离屏渲染。

离屏渲染

之前一直使用的渲染方式是将数据渲染到backBuffer中,而离屏渲染指的是先将数据渲染到指定纹理中,再将纹理渲染到屏幕上。类比一下就行,原来的方式是直接在墙上作画,现在的方式是先画到一张纸上,再将纸贴到墙上。

代码改动不多,离屏渲染关键点在RenderTarget,也就是呈现的目标。我们需要做的就是,创建出来一个纹理,根据纹理创建出RenderTarget以绑定到context中,这一步保证将数据渲染到该纹理中。第二部根据纹理创建出ShaderResourceView,这一步保证该纹理将来被渲染到backBuffer中。

    D3D11_TEXTURE2D_DESC tdesc;
	ZeroMemory(&tdesc, sizeof(D3D11_TEXTURE2D_DESC));
	tdesc.Width = _width;
	tdesc.Height = _height;
	tdesc.MipLevels = 1;
	tdesc.ArraySize = 1;
	tdesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	tdesc.SampleDesc.Count = 1;
	tdesc.SampleDesc.Quality = 0;
	tdesc.Usage = D3D11_USAGE_DEFAULT;
	tdesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
	tdesc.CPUAccessFlags = 0;
	tdesc.MiscFlags = 0;
	_device->CreateTexture2D(&tdesc, nullptr, this->m_texture.GetAddressOf());

需要注意的就是创建纹理时的bindFlags,需要绑定到两个阶段。

在渲染时,将该纹理的RenderTarget绑定至纹理中,接下来正常执行渲染逻辑既可。

_context->OMSetRenderTargets(1, this->m_render_target_view.GetAddressOf(), nullptr);
if (this->m_monitor_texture_draw_able != nullptr) {
		this->m_monitor_texture_draw_able->draw(this);
	}

	if (_draw_cursor) {
		if (this->m_cursor_texture_draw_able != nullptr) {
			this->m_cursor_texture_draw_able->draw(this);
		}
		else {
			this->m_cursor_texture_draw_able = new CursorTextureDrawAble(this, 32, 32, 2560.0f, 1440.0f);
			this->m_cursor_texture_draw_able->draw(this);
		}
	}

随后将该纹理渲染至backBuffer,将RenderTarget绑定为原有背景的renderTarget,渲染逻辑与正常纹理渲染逻辑相同。

this->m_context->OMSetRenderTargets(1, &this->m_render_target_view, nullptr);
this->m_render_target_texture->bind(this->m_context);

void RenderTargerTexture::bind(ID3D11DeviceContext* _context)
{
	for (auto item : *this->m_bind_able) {
		item->bind(_context);
	}
	_context->DrawIndexed(this->m_index_size, 0u, 0u);
}

随后可以将该纹理数据保存起来,以供拷贝到编码器。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值