从IDirect3DTexture9向后移植后显示IDirect3DTexture8的问题

时间:2015-11-01 04:04:47

标签: c game-engine direct3d xbox quake

我正在尝试通过ID软件将某些人的Quake 1 Direct3d9端口反向移植到Direct3d8,这样我就可以将它移植到原始Xbox(仅使用D3D8 API)。

在进行更改以使用Direct3d8后,它会在屏幕上显示一些看似小方块的混合像素:/(见图片)。

有谁知道这里出了什么问题?它与D3D9完美配合,是否需要一些额外的参数,我需要D3D8,直接音调可能吗?

传入的数据是Quake 1 .lmp 2d图像文件。 “它由两个整数(宽度和高度)组成,后跟一个宽度为x高度字节的字符串,每个字节都是Quake调色板的索引”

它被传递给D3D_ResampleTexture()函数。

非常感谢任何帮助。

Image output using D3D8

Image output using D3D9

代码:

void D3D_ResampleTexture (image_t *src, image_t *dst)
{
    int y, x , srcpos, srcbase,  dstpos;

    unsigned int *dstdata, *srcdata;

    // take an unsigned pointer to the dest data that we'll actually fill
    dstdata = (unsigned int *) dst->data;

    // easier access to src data for 32 bit resampling
    srcdata = (unsigned int *) src->data;

    // nearest neighbour for now
    for (y = 0, dstpos = 0; y < dst->height; y++)
    {
        srcbase = (y * src->height / dst->height) * src->width;

        for (x = 0; x < dst->width; x++, dstpos++)
        {
            srcpos = srcbase + (x * src->width / dst->width);

            if (src->flags & IMAGE_32BIT)
                dstdata[dstpos] = srcdata[srcpos];
            else if (src->palette)
                dstdata[dstpos] = src->palette[src->data[srcpos]];
            else Sys_Error ("D3D_ResampleTexture: !(flags & IMAGE_32BIT) without palette set");
        }
    }
}


void D3D_LoadTextureStage3 (LPDIRECT3DTEXTURE8/*9*/ *tex, image_t *image)
{
    int i;
    image_t scaled;

    D3DLOCKED_RECT LockRect;

    memset (&LockRect, 0, sizeof(D3DLOCKED_RECT));

    // check scaling here first
    for (scaled.width = 1; scaled.width < image->width; scaled.width *= 2);
    for (scaled.height = 1; scaled.height < image->height; scaled.height *= 2);

    // clamp to max texture size
    if (scaled.width > /*d3d_DeviceCaps.MaxTextureWidth*/640) scaled.width = /*d3d_DeviceCaps.MaxTextureWidth*/640;
    if (scaled.height > /*d3d_DeviceCaps.MaxTextureHeight*/480) scaled.height = /*d3d_DeviceCaps.MaxTextureHeight*/480;


    IDirect3DDevice8/*9*/_CreateTexture(d3d_Device, scaled.width, scaled.height,
    (image->flags & IMAGE_MIPMAP) ? 0 : 1,
    /*(image->flags & IMAGE_MIPMAP) ? D3DUSAGE_AUTOGENMIPMAP :*/ 0,
    (image->flags & IMAGE_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8,
    D3DPOOL_MANAGED,
    tex
    );

    // lock the texture rectangle
    //(*tex)->LockRect (0, &LockRect, NULL, 0);
    IDirect3DTexture8/*9*/_LockRect(*tex, 0, &LockRect, NULL, 0);

    // fill it in - how we do it depends on the scaling
    if (scaled.width == image->width && scaled.height == image->height)
    {
        // no scaling
        for (i = 0; i < (scaled.width * scaled.height); i++)
        {
            unsigned int p;

            // retrieve the correct texel - this will either be direct or a palette lookup
            if (image->flags & IMAGE_32BIT)
                p = ((unsigned *) image->data)[i];
            else if (image->palette)
                p = image->palette[image->data[i]];
            else Sys_Error ("D3D_LoadTexture: !(flags & IMAGE_32BIT) without palette set");
            // store it back
            ((unsigned *) LockRect.pBits)[i] = p;
        }
    }
    else
    {
        // save out lockbits in scaled data pointer
        scaled.data = (byte *) LockRect.pBits;

        // resample data into the texture
        D3D_ResampleTexture (image, &scaled);
    }

    // unlock it
    //(*tex)->UnlockRect (0);
    IDirect3DTexture8/*9*/_UnlockRect(*tex, 0);

    // tell Direct 3D that we're going to be needing to use this managed resource shortly
    //FIXME
    //(*tex)->PreLoad ();
}


LPDIRECT3DTEXTURE8/*9*/ D3D_LoadTextureStage2 (image_t *image)
{
    d3d_texture_t *tex;

    // look for a match

    // create a new one
    tex = (d3d_texture_t *) malloc (sizeof (d3d_texture_t));

    // link it in
    tex->next = d3d_Textures;
    d3d_Textures = tex;

    // fill in the struct
    tex->LastUsage = 0;
    tex->d3d_Texture = NULL;

    // copy the image
    memcpy (&tex->TexImage, image, sizeof (image_t));

    // upload through direct 3d
    D3D_LoadTextureStage3 (&tex->d3d_Texture, image);

    // return the texture we got
    return tex->d3d_Texture;
}


LPDIRECT3DTEXTURE8/*9*/ D3D_LoadTexture (char *identifier, int width, int height, byte *data, /*bool*/qboolean mipmap, /*bool*/qboolean alpha)
{
    image_t image;

    image.data = data;
    image.flags = 0;
    image.height = height;
    image.width = width;
    image.palette = d_8to24table;

    strcpy (image.identifier, identifier);

    if (mipmap) image.flags |= IMAGE_MIPMAP;
    if (alpha) image.flags |= IMAGE_ALPHA;

    return D3D_LoadTextureStage2 (&image);
}

2 个答案:

答案 0 :(得分:1)

锁定纹理时,必须观察Pitch结构的返回D3DLOCKED_RECT成员。您的代码假设所有数据都是连续的,但Pitch可能大于扫描线的宽度,以便允许锁定子区域和缓冲区的其他布局,而不包含连续像素一条扫描线的末端到下一条扫描线的开头。

查看我的图书Chapter 4"The Direct3D Graphics Pipeline",查看访问曲面并正确使用Pitch的示例。

答案 1 :(得分:0)

For anyone else that comes across this issue, it was due to the way the image was been loaded into the Xbox's memory, it needed to be swizzled.