实现逻辑:
实现逻辑:
创建一张纹理,纹理分辨率由用户设置,创建渲染目标视图,根据纹理宽高重新设置透视投影函数的宽高比以及视口的宽高,绘制目标模型,创建一张纹理D3D11_USAGE_STAGING,设置cpu可读,将数据从GPU拷贝到CPU,将读取的数据保存成jpg图片,然后恢复(与窗口一致)视口及透视投影函数的宽高,然后将Backbuffer与渲染目标视图绑定,绘制到后台缓冲,通过present显示到窗口
D3D11实现
int CD3DRender::CaptureFrame(int nWidth, int nHeight)
{
ID3D11Texture2D* m_pstCaptureTex = nullptr;
int nRet = SUCCESS;
HRESULT hr = S_OK;
D3D11_TEXTURE2D_DESC stTextureDesc;
memset(&stTextureDesc, 0, sizeof(D3D11_TEXTURE2D_DESC));
stTextureDesc.Width = nWidth;
stTextureDesc.Height = nHeight;
stTextureDesc.MipLevels = 1;
stTextureDesc.ArraySize = 1;
stTextureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
stTextureDesc.SampleDesc.Count = 1;
stTextureDesc.SampleDesc.Quality = 0;
stTextureDesc.Usage = D3D11_USAGE_DEFAULT;
stTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
stTextureDesc.CPUAccessFlags = 0;
stTextureDesc.MiscFlags = 0;
hr = m_pstD3d11Device->CreateTexture2D(&stTextureDesc, 0, &m_pstCaptureTex);
if (FAILED(hr))
{
LogErrorText(hr);
return FAIL;
}
D3D11_RELEASE_OPERATE(m_pstRenderTargetView);
D3D11_RELEASE_OPERATE(m_pstID3D11DepthStencilView);
hr = m_pstD3d11Device->CreateRenderTargetView(m_pstCaptureTex, nullptr, &m_pstRenderTargetView);
if (FAILED(hr))
{
LogErrorText(hr);
return FAIL;
}
nRet = CreateDepthStencilView(nWidth, nHeight);
if (FAIL == nRet)
{
return FAIL;
}
if (m_bRenderObjModel)
{
nRet = m_pcCamera->SetFrustum(DirectX::XM_PI / 6, (float)nWidth / nHeight, 0.1f, 1000.0f);
if (FAIL == nRet)
{
return FAIL;
}
nRet = m_pcCamera->GetProjXM(&m_stProjection);
if (FAIL == nRet)
{
return FAIL;
}
nRet = UpdataMVP();
if (FAIL == nRet)
{
return FAIL;
}
}
float fBgColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
m_pstD3D11DevContext->ClearRenderTargetView(m_pstRenderTargetView, fBgColor);
m_pstD3D11DevContext->ClearDepthStencilView(m_pstID3D11DepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0, 0);
m_pstD3D11DevContext->OMSetRenderTargets(1, &m_pstRenderTargetView, m_pstID3D11DepthStencilView);
m_stViewport.Width = nWidth;
m_stViewport.Height = nHeight;
m_pstD3D11DevContext->RSSetViewports(1, &m_stViewport); //设置视口 参数:视口数目, 视口数组
if (true == m_bRenderObjModel)
{
int nVertexStartPos = 0;
for (int i = 0; i < m_vecGroupNum.size(); i++)
{
m_pstD3D11DevContext->PSSetConstantBuffers(1, 1, &m_vecCBMaterialBuffer[0]);
if (!m_vecObjResourceViewPlanes.empty())
{
m_pstD3D11DevContext->PSSetShaderResources(0, 1, &m_vecObjResourceViewPlanes[i]);
}
m_pstD3D11DevContext->DrawIndexed(m_vecGroupNum[i], nVertexStartPos, 0);
nVertexStartPos += m_vecGroupNum[i];
}
}
else
{
m_pstD3D11DevContext->DrawIndexed(m_nVcount, 0, 0);
}
D3D11_TEXTURE2D_DESC stNewTextureDesc;
m_pstCaptureTex->GetDesc(&stNewTextureDesc);
ID3D11Texture2D* pstCopyTex = nullptr;
stNewTextureDesc.Width = nWidth;
stNewTextureDesc.Height = nHeight;
stNewTextureDesc.MipLevels = 1;
stNewTextureDesc.ArraySize = 1;
stNewTextureDesc.SampleDesc.Count = 1;
stNewTextureDesc.SampleDesc.Quality = 0;
stNewTextureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
stNewTextureDesc.Usage = D3D11_USAGE_STAGING;
stNewTextureDesc.BindFlags = 0;
stNewTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
hr = m_pstD3d11Device->CreateTexture2D(&stNewTextureDesc, 0, &pstCopyTex);
if (FAILED(hr))
{
LogErrorText(hr);
return FAIL;
}
m_pstD3D11DevContext->CopyResource(pstCopyTex, m_pstCaptureTex);
D3D11_MAPPED_SUBRESOURCE stMapData;
unsigned char *pImgData = nullptr;
SAFE_NEW_ARRAY(pImgData, unsigned char, nWidth * nHeight * 4);
m_pstD3D11DevContext->Map(pstCopyTex, 0, D3D11_MAP_READ, 0, &stMapData);
unsigned char* pData = reinterpret_cast<unsigned char*>(stMapData.pData);
if (nWidth * 4 == stMapData.RowPitch)
{
memcpy(pImgData, pData, nWidth * nHeight * 4);
}
else
{
for (int i = 0; i < nHeight; ++i)
{
memcpy_s(&pImgData[i*nWidth * 4], nWidth * 4, pData, nWidth * 4);
pData += stMapData.RowPitch;
}
}
m_pstD3D11DevContext->Unmap(pstCopyTex, 0);
CPicOperator* pPicture = nullptr;
SAFE_NEW(pPicture, CPicOperator);
PO_PICINFO enPicInfo;
enPicInfo.pBuffer = pImgData;
enPicInfo.nChannel = 4;
enPicInfo.nPicWid = nWidth;
enPicInfo.nPicHgt = nHeight;
enPicInfo.nSize = nWidth * nHeight * 4;
enPicInfo.nPicMipmapLevel = 1;
enPicInfo.emColor = PO_OP_COLOR_RGBA8;
enPicInfo.bFlip = false;
std::string strSavePath = std::to_string(nWidth) + "_" + std::to_string(nHeight)+ ".jpg";
const char*pPath = strSavePath.c_str();
nRet = pPicture->PictureOperate(PO_OP_ENCODE, pPath, enPicInfo);
if (PO_OK != nRet || NULL == enPicInfo.pBuffer)
{
return FAIL;
}
SAFE_DELETE(pImgData);
SAFE_DELETE(pPicture);
D3D11_RELEASE_OPERATE(pstCopyTex);
D3D11_RELEASE_OPERATE(m_pstCaptureTex);
m_stViewport.Width = m_nVideoWidthRecord;
m_stViewport.Height = m_nVideoHeightRecord;
m_pstD3D11DevContext->RSSetViewports(1, &m_stViewport); //设置视口 参数:视口数目, 视口数组
if (true == m_bRenderObjModel)
{
nRet = m_pcCamera->SetFrustum(DirectX::XM_PI / 6, (float)m_nVideoWidthRecord / m_nVideoHeightRecord, 0.1f, 1000.0f);
if (FAIL == nRet)
{
return FAIL;
}
nRet = m_pcCamera->GetProjXM(&m_stProjection);
if (FAIL == nRet)
{
return FAIL;
}
nRet = UpdataMVP();
if (FAIL == nRet)
{
return FAIL;
}
}
nRet = CreateDepthStencilView(m_nVideoWidthRecord, m_nVideoHeightRecord);
if (FAIL == nRet)
{
return FAIL;
}
return SUCCESS;
}
OPENGL实现
1.先创建帧缓冲可以查看learnopengl帧缓冲那块代码
2.实现
int COpenglRender::CaptureFrame(int nWidth, int nHeight, INTERACTION_OPERATOR stInteractionOperator)
{
CreateFrameBuffer(nWidth, nHeight);
glViewport(0, 0, nWidth, nHeight);
m_pcCamera->SetFrustum(DirectX::XM_PI / 6, (float)nWidth / nHeight, 0.5f, 1000.0f);
m_pcCamera->GetProjXM(&m_stProjection);
glBindFramebuffer(GL_FRAMEBUFFER, m_nFramebuffer);
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(m_nShaderProgram);
glBindVertexArray(m_nVAO);
int nRet = Updata(stInteractionOperator);
if (FAIL == nRet)
{
return FAIL;
}
int nVertexStartPos = 0;
for (int i = 0; i < m_vecGroupNum.size(); i++)
{
glBindTexture(GL_TEXTURE_2D, i + 1);
glDrawArrays(GL_TRIANGLES, nVertexStartPos, m_vecGroupNum[i]);
nVertexStartPos += m_vecGroupNum[i];
}
unsigned char* pRGBA = nullptr;
SAFE_NEW_ARRAY(pRGBA, unsigned char, nWidth * nHeight * 4);
glReadPixels(0, 0, nWidth, nHeight, GL_RGBA, GL_UNSIGNED_BYTE, pRGBA);
CPicOperator* pPicture = nullptr;
SAFE_NEW(pPicture, CPicOperator);
PO_PICINFO enPicInfo;
enPicInfo.pBuffer = pRGBA;
enPicInfo.nChannel = 4;
enPicInfo.nPicWid = nWidth;
enPicInfo.nPicHgt = nHeight;
enPicInfo.nSize = nWidth * nHeight * 4;
enPicInfo.nPicMipmapLevel = 1;
enPicInfo.emColor = PO_OP_COLOR_RGBA8;
enPicInfo.bFlip = true;
std::string strSavePath = std::to_string(nWidth) + "_" + std::to_string(nHeight) + ".jpg";
const char*pPath = strSavePath.c_str();
nRet = pPicture->PictureOperate(PO_OP_ENCODE, pPath, enPicInfo);
if (PO_OK != nRet || NULL == enPicInfo.pBuffer)
{
return FAIL;
}
SAFE_DELETE(pPicture);
SAFE_DELETE(pRGBA);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &m_nFramebuffer);
glUseProgram(0);
return SUCCESS;
}