0

使用 DirectX 9,我尝试通过LPDIRECT3DTEXTURE9以下方式创建并填充纹理。

  1. 首先,我创建纹理IDirect3DTexture9::CreateTexture

    LPDIRECT3DTEXTURE9 pTexture;
    
    if ( FAILED( pd3dDevice->CreateTexture( MAX_IMAGE_WIDTH,
                               MAX_IMAGE_HEIGHT,
                               1,
                               0,                 // D3DUSAGE_DYNAMIC,
                               D3DFMT_A8R8G8B8,
                               D3DPOOL_MANAGED,   // D3DPOOL_DEFAULT,
                               &pTexture,
                               NULL ) ) )
    {
        // Handle error case
    }
    
  2. 然后,我尝试在纹理上锁定一个矩形,如下所示:

    unsigned int uiSize = GetTextureSize();
    D3DLOCKED_RECT rect;
    ARGB BlackColor = { (char)0xFF, (char)0xFF, (char)0xFF, (char)0x00 };
    ::ZeroMemory( &rect, sizeof( D3DLOCKED_RECT ) );
    
    // Lock outline texture to rect, and then cast rect to bits and use bits as outlineTexture access point
    
    if ( pTexture == NULL )
    {
        return ERROR_NOT_INITIALIZED;
    }
    
    pTexture->LockRect( 0, &rect, NULL, D3DLOCK_NOSYSLOCK );          // Consider ?
    ARGB* bits = (ARGB*)rect.pBits;
    
    for ( unsigned int uiPixel = 0; uiPixel < uiSize; ++uiPixel )
    {
        // Copy all black pixels only
        if ( compositeMask[uiPixel] == BlackColor )
        {
            bits[uiPixel] = compositeMask[uiPixel];
        }
    }
    
    pTexture->UnlockRect( 0 );
    
    return ERROR_SUCCESS;
    

ARGB只是一个定义如下的结构:

struct ARGB
{
    char b;
    char g;
    char r;
    char a;

    bool operator==( ARGB& comp )
    {
        if ( a == comp.a &&
             r == comp.r &&
             g == comp.g &&
             b == comp.b )
            return TRUE;
        else
            return FALSE;
    }

    bool operator!=( ARGB& comp )
    {
        return !( this->operator==( comp ) );
    }
};

我想要做的是根据应用程序中的算法预先计算一个像素数据数组(黑色轮廓),然后只将该组像素数据中的纯黑色像素写入我的像素数据LPDIRECT3DTEXTURE9中,以便稍后渲染。

应用程序当前在 LockRect 调用中引发 ACCESS_VIOLATION 异常 (0xC0000005)。谁能解释为什么?

这是确切的异常详细信息:

TestApp.exe 中 0x0132F261 处的未处理异常:0xC0000005:访问冲突读取位置 0x00000001。

位置在0x00000000和之间变化0x00000001……这是否暗示了什么?

另外,如果有更好的方法来做我想做的事情,那么我会全神贯注:)

4

2 回答 2

1

与您问题的其他评论员一样,原则上我看不出您创建和锁定纹理的方式有什么问题。我自己也做过同样的事情——在其中创建纹理D3DPOOL_MANAGED并使用LockRect它来更新内容。

但是,我担心三个方面。我发布作为答案是因为评论太多了,所以请多多包涵...

  1. 锁定时使用D3DLOCK_NOSYSLOCK标志。我发现当为多线程操作创建 D3D 设备时,这可能会导致冲突。
  2. 您访问锁定位的方式不考虑步幅。我很欣赏该错误显然发生在此代码之前,但无论如何都值得一提。
  3. 您正在投射自己struct的像素访问权限,但不清楚实际大小struct可能是多少,因为我看不到您的项目打包选项。

因此,我建议您可以做三件事来确定上述任何一项是否导致问题:

首先,只需使用默认的零标志进行锁定调用

pTexture->LockRect( 0, &rect, NULL, 0 );

其次,验证您的ARGB结构确实是 4 个字节

ASSERT(sizeof(ARGB) == 4);

最后,除了锁定和解锁纹理之外什么都不做,看看是否仍然出现运行时错误,还要检查返回码

HRESULT hr = pTexture->LockRect( 0, &rect, NULL, 0 );
ASSERT(SUCCEEDED(hr));
hr = pTexture->UnlockRect( 0 );
ASSERT(SUCCEEDED(hr));

在任何情况下,当更新纹理位时,您必须逐行进行,同时考虑从LockRect调用中返回的步幅D3DLOCKED_RECT.Pitch

也许您可以使用上述结果更新您的问题,我可以根据需要修改此答案。

于 2013-06-02T08:39:33.230 回答
0

这是令人麻木的愚蠢。对不起大家。

我在代码中一直遵循纹理指针;LPDIRECT3DTEXTURE9 指针实际上存储在另一个自定义纹理类对象类型中,并附加了额外的上下文数据;这些包装器对象是另一个类的成员,该类被复制并在各处使用,但没有为该类编写赋值运算符或复制构造函数。在某些时候,在处理的大量纹理列表中,发现从容器类发送的纹理之一是无效的,因为它实际上是;它应该包含另一个纹理的副本,但只包含一个无效指针。

很抱歉给大家带来不幸的业余错误,但感谢大家的指点和保证

于 2013-06-02T23:46:40.600 回答