使用着色器修改IDirect3DSurface9 *

时间:2017-02-02 10:52:17

标签: c++ shader directx-9 alphablending dxva

我从DXVA2视频解码器获得了IDirect3DSurface9 *。我想用着色器修改该表面。我可以通过“绘制”后缓冲区中的表面来渲染没有着色器的视频帧。 我使用以下代码渲染没有着色器的帧:

void Draw(Example* exps){

    IDirect3DSurface9* backbuffer;
    hwctx->d3d9device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    hwctx->d3d9device->BeginScene();
    hwctx->swap_chain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);

    hwctx->d3d9device->StretchRect(videoSurface, NULL, backbuffer, NULL, D3DTEXF_LINEAR);

    hwctx->d3d9device->EndScene();
    hwctx->swap_chain->Present(0, 0, 0, 0, 0);
    backbuffer->Release();
}

直到这里,有人工作。 我会修改Draw函数以使用以下着色器渲染视频帧:

uniform extern float4x4 gWVP;
uniform extern texture  gTexRGB;
uniform extern texture  gTexAlpha;

sampler TexRGB = sampler_state
{
    Texture = <gTexRGB>;
    AddressU  = WRAP;
    AddressV  = WRAP;
};

sampler TexAlpha = sampler_state
{
    Texture = <gTexAlpha>;
    AddressU = WRAP;
    AddressV = WRAP;
};

struct OutputVS
{
    float4 posH    : POSITION0;
    float2 tex0    : TEXCOORD0;
};

OutputVS DirLightTexVS(float3 posL : POSITION0, float3 normalL : NORMAL0, float2 tex0: TEXCOORD0)
{
    // Zero out our output.
    OutputVS outVS = (OutputVS)0;

    // Transform to homogeneous clip space.
    outVS.posH = mul(float4(posL, 1.0f), gWVP);

    // Pass on texture coordinates to be interpolated in rasterization.
    outVS.tex0 = tex0;

    // Done--return the output.
    return outVS;
}

float4 DirLightTexPS(float4 c : COLOR0, float4 spec : COLOR1, float2 tex0 : TEXCOORD0) : COLOR
{
    float3  rgb = tex2D(TexRGB, tex0).rgb;
    float   alpha = tex2D(TexAlpha, tex0).g;
    return float4(rgb, alpha);
}

technique DirLightTexTech
{
    pass P0
    {
        // Specify the vertex and pixel shader associated with this pass.
        vertexShader = compile vs_2_0 DirLightTexVS();
        pixelShader  = compile ps_2_0 DirLightTexPS();

    }
}

其中TexRGB是与视频帧相关联的纹理,而TexAlpha是另一种包含alpha值的纹理。 如何将解码后的曲面传递给着色器?我从未使用过Directx9,所以我很感激一个例子,可以帮助我解决问题。

更新1: 我创建了InitEffect函数来加载文件中的效果

void InitEffect(Example* ctx) {
    auto hwctx = ctx->decoder->stream->HWAccelCtx;

    // Create the FX from a .fx file.
    ID3DXBuffer* errors = 0;
    D3DXCreateEffectFromFile(hwctx->d3d9device, "basicEffect.fx", 0, 0, D3DXSHADER_DEBUG, 0, &ctx->mFX, &errors);

    if (errors)
        MessageBox(0, (LPCSTR)errors->GetBufferPointer(), 0, 0);

    // Obtain handles.
    ctx->mhTech = ctx->mFX->GetTechniqueByName("DirLightTexTech");
    ctx->mhWVP = ctx->mFX->GetParameterByName(0, "gWVP");
    ctx->mhTexAlpha = ctx->mFX->GetParameterByName(0, "gTexAlpha");
    ctx->mhTexRGB = ctx->mFX->GetParameterByName(0, "gTexRGB");
}

并将渲染功能更改为:

void Draw(Example* ctx) {
    InitMatrices(ctx);

    IDirect3DSurface9* backbuffer;

    hwctx->d3d9device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffeeeeee, 1.0f, 0);
    hwctx->d3d9device->BeginScene();

    ctx->mFX->SetTechnique(ctx->mhTech);
    ctx->mFX->SetMatrix(ctx->mhWVP, &(ctx->mCrateWorld*ctx->mView*ctx->mProj));

    ctx->texRGB->GetSurfaceLevel(0, &ctx->surfRGB);
    hwctx->d3d9device->SetRenderTarget(0, ctx->surfRGB);
    hwctx->d3d9device->StretchRect((IDirect3DSurface9*)s->frame->data[3], NULL, ctx->surfRGB, NULL, D3DTEXF_LINEAR);

    ctx->mFX->SetTexture(ctx->mhTexAlpha, ctx->texAlpha);
    ctx->mFX->SetTexture(ctx->mhTexRGB, ctx->texRGB);

    // Enable alpha blending.
    hwctx->d3d9device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
    hwctx->d3d9device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    hwctx->d3d9device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

    hwctx->d3d9device->SetVertexDeclaration(VertexPNT::Decl);
    hwctx->d3d9device->SetStreamSource(0, ctx->mBoxVB, 0, sizeof(VertexPNT));
    hwctx->d3d9device->SetIndices(ctx->mBoxIB);

    UINT numPasses = 0;
    ctx->mFX->Begin(&numPasses, 0);
    for (UINT i = 0; i < numPasses; ++i){
        ctx->mFX->BeginPass(i);
        hwctx->d3d9device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12);
        ctx->mFX->EndPass();
    }
    ctx->mFX->End();

    hwctx->d3d9device->EndScene();
    hwctx->swap_chain->Present(0, 0, 0, 0, 0);

    backbuffer->Release();

    // Disable alpha blending.
    hwctx->d3d9device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
}

但它仍然无效。

更新2 我按照Asesh共享的代码修改了代码。在InitEffect函数中,我添加了以下行来创建渲染目标表面:

ctx->texRGB->GetSurfaceLevel(0, &ctx->surfRGB);
// store orginal rendertarget
hwctx->d3d9device->GetRenderTarget(0, &ctx->origTarget_);
D3DSURFACE_DESC desc;
ctx->origTarget_->GetDesc(&desc);

// create our surface as render target
hwctx->d3d9device->CreateRenderTarget(1920, 1080, D3DFMT_X8R8G8B8,
    desc.MultiSampleType, desc.MultiSampleQuality,
    false, &ctx->surfRGB, NULL);

绘制功能是:

void drawScene(Example* ctx) {
    InitMatrices(ctx);

    auto hwctx = ctx->decoder->stream->HWAccelCtx;
    auto s = (VdrStreamContext*)ctx->decoder->stream->vdrCodecCtx->opaque;

    IDirect3DSurface9* backbuffer;
    hwctx->d3d9device->SetRenderTarget(0, ctx->surfRGB);
    hwctx->d3d9device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffeeeeee, 1.0f, 0);
    hwctx->d3d9device->BeginScene();


    hwctx->d3d9device->StretchRect((IDirect3DSurface9*)s->vdrFrame->data[3], NULL, ctx->surfRGB, NULL, D3DTEXF_NONE);
    hwctx->d3d9device->SetRenderTarget(0, ctx->origTarget_);

    if (!hwctx->d3d9device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer)) {
        hwctx->d3d9device->StretchRect(ctx->surfRGB, NULL, backbuffer, NULL, D3DTEXF_NONE);
    }

    ctx->mFX->SetTechnique(ctx->mhTech);
    ctx->mFX->SetMatrix(ctx->mhWVP, &(ctx->mCrateWorld*ctx->mView*ctx->mProj));

    ctx->mFX->SetTexture(ctx->mhTexAlpha, ctx->texAlpha);
    ctx->mFX->SetTexture(ctx->mhTexRGB, ctx->texRGB);

    // Enable alpha blending.
    hwctx->d3d9device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
    hwctx->d3d9device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    hwctx->d3d9device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

    hwctx->d3d9device->SetVertexDeclaration(VertexPNT::Decl);
    hwctx->d3d9device->SetStreamSource(0, ctx->mBoxVB, 0, sizeof(VertexPNT));
    hwctx->d3d9device->SetIndices(ctx->mBoxIB);

    UINT numPasses = 0;
    ctx->mFX->Begin(&numPasses, 0);
    for (UINT i = 0; i < numPasses; ++i){
        ctx->mFX->BeginPass(i);
        hwctx->d3d9device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12);
        ctx->mFX->EndPass();
    }

    ctx->mFX->End();

    hwctx->d3d9device->EndScene();
    hwctx->d3d9device->Present(0, 0, 0, 0);

    backbuffer->Release();

    // Disable alpha blending.
    hwctx->d3d9device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
}

通过 hwctx-&gt; d3d9device-&gt; StretchRect(ctx-&gt; surfRGB,NULL,backbuffer,NULL,D3DTEXF_NONE)绘制backbuffer; 即使ctx-&gt; surfRGB是与传递给着色器的纹理相关联,视频帧显示在屏幕上,但不应用alpha混合。如果我删除 hwctx-&gt; d3d9device-&gt; StretchRect(ctx-&gt; surfRGB,NULL,backbuffer,NULL,D3DTEXF_NONE); 即使ctx-&gt; surfRGB不是,也不显示视频帧空。

0 个答案:

没有答案