渲染到纹理RTT

实现逻辑:

实现逻辑:
创建一张纹理,纹理分辨率由用户设置,创建渲染目标视图,根据纹理宽高重新设置透视投影函数的宽高比以及视口的宽高,绘制目标模型,创建一张纹理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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LV小猪精

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值