【问题标题】:How to update Texture2D in pixel shader every frame (in D3D10)?如何在每帧(在 D3D10 中)更新像素着色器中的 Texture2D?
【发布时间】:2013-01-15 15:54:56
【问题描述】:

使用 D3D10,我正在绘制一个 2d 矩形,并希望用每秒应更改几次的纹理(位图)填充它(例如显示视频)。

我正在使用带有 Texture2D 变量的着色器效果,并尝试更新 ID3D10EffectShaderResourceVariable 并重绘网格。

我的实际用途是从内存中复制位图,并使用 UpdateSubresource。 但它不起作用,所以我将其缩小以测试两个 DDS 图像之间的切换。 结果是它按预期绘制了第一个图像,但一直在绘制它而不是在两个图像之间切换。

我是 D3D 的新手。您能否解释一下这种方法是否可行,或者提出正确的方法。

着色器效果:

Texture2D txDiffuse;
SamplerState samLinear
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};
struct VS_INPUT
{
    float4 Pos : POSITION;
    float2 Tex : TEXCOORD;
};
struct PS_INPUT
{
    float4 Pos : SV_POSITION;
    float2 Tex : TEXCOORD0;
};
PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;
    output.Pos = input.Pos;
    output.Tex = input.Tex;    
    return output;
}
float4 PS( PS_INPUT input) : SV_Target
{
    return txDiffuse.Sample( samLinear, input.Tex );
}
technique10 Render
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
    }
}

代码(跳过了很多部分):

ID3D10ShaderResourceView*           g_pTextureRV = NULL;
ID3D10EffectShaderResourceVariable* g_pDiffuseVariable = NULL;

D3DX10CreateEffectFromResource(gInstance, MAKEINTRESOURCE(IDR_RCDATA1), NULL, NULL, NULL, "fx_4_0", dwShaderFlags, 0, device, NULL, NULL, &g_pEffect, NULL, NULL);

g_pTechnique = g_pEffect->GetTechniqueByName( "Render" );
g_pDiffuseVariable = g_pEffect->GetVariableByName( "txDiffuse" )->AsShaderResource();

// this part is called on Frame render:

device->CreateRenderTargetView( backBuffer, NULL, &rtView);
device->ClearRenderTargetView( rtView, ClearColor );

if(g_pTextureRV != NULL) {
    g_pTextureRV->Release();
    g_pTextureRV = NULL;
}

D3DX10CreateShaderResourceViewFromFile(device, pCurrentDDSFilePath, NULL, NULL, &g_pTextureRV, NULL );
g_pDiffuseVariable->SetResource( g_pTextureRV );

D3D10_TECHNIQUE_DESC techDesc;
g_pTechnique->GetDesc( &techDesc );
for( UINT p = 0; p < techDesc.Passes; ++p )
{
    g_pTechnique->GetPassByIndex( p )->Apply( 0 );
    direct2dDrawingContext->dev->Draw( 6, 0 );
}

// ... present the current back buffer 

【问题讨论】:

    标签: direct3d pixel-shader d3dx


    【解决方案1】:

    以下是一种解决方案,不一定是最好的,但不使用自定义着色器(我用 C# / Managed DirectX 编写,但它应该很容易转码。)

    Bitmap bmp; //the bitmap that you will use to update the texture
    Texture tex; //the texture that DirectX will render
    
    void Render()
    {
      //render some stuff
    
      bmp = GetNextTextureFrame(); //whatever you do to update your bitmap
      Surface s = tex.GetSurfaceLevel(0);
      Graphics g = s.GetGraphics();
      //IntPtr hdc = g.GetHdc();
      //BitBlt(hdc, 0, 0, bmp.Width, bmp.Height, bmpHdc, 0, 0, 0xcc0020);
      g.DrawImageUnscaled(bmp, 0, 0);
      g.ReleaseHdc(hdc);
      s.ReleaseGraphics();
      device.SetTexture(0, tex);
      //now render your primitives
    
      //render some more stuff
      //present
    }
    

    注释掉的行是我实际使用的方式,使用 hBitmap 和 DC 与 BitBlt,因为它比 GDI+ 快。很多人可能会告诉您,上述方法是一种不好的方法,因为必须发生所有内存锁定,而且他们可能是对的。但是我能够使用多个 1920x1080 纹理实现 30fps,所以无论它是否合适,它都可以工作。

    【讨论】:

      猜你喜欢
      • 2012-09-01
      • 2021-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多