如何在direct3d 9中正确实现纹理像素到纹理像素校正?

时间:2012-05-15 07:58:47

标签: directx textures direct3d texture-mapping direct3d9

我已阅读a couple articles,其中描述了将纹理移动一半顶点位置的必要性,以便在纹素和像素之间获得正确的映射。虽然我认为我理解它背后的理论,但当我尝试实现解决方案时(向左移动半个单元),我得到的只是渲染图像两侧的黑线。

我得到的印象是我要么不调整正确的x和y参数,要么这不适用于我的特定场景。我使用direct3d 9进行线性过滤,并渲染覆盖整个屏幕的图像。我已尝试使用纹理的实际大小和-1到+1(即根据两个链接文章中的不同解决方案)。两种方法都有同样的效果。

我的问题是,这种纠正何时需要,是否有正确的方法来解决这个问题?

1 个答案:

答案 0 :(得分:1)

根据DirectX文档,仅在“使用预转换顶点渲染2D输出时”需要偏移半个像素。预转换顶点是D3DFVF_XYZRHW调用中指定IDirect3DDevice9::SetFVF标记的顶点。为了正确绘制变换顶点,您必须将其位置设置为(posx - 0.5, posy - 0.5, 0, 1),其中(posx, posy)是顶点的屏幕空间坐标(以像素为单位)。

这是一个渲染全屏纹理四边形的代码:

struct TRANSFORMED_VERTEX
{
    D3DXVECTOR4 pos;
    D3DXVECTOR2 tex;
    static const DWORD FVF;
};
const DWORD TRANSFORMED_VERTEX::FVF = D3DFVF_XYZRHW | D3DFVF_TEX1;

void RenderFullScreenQuad()
{
    D3DSURFACE_DESC desc;
    LPDIRECT3DSURFACE9 pSurf;

    g_pd3dDevice->GetRenderTarget(0, &pSurf);
    pSurf->GetDesc(&desc);
    pSurf->Release();

    float width = (float)desc.Width - 0.5f;
    float height = (float)desc.Height - 0.5f;

    TRANSFORMED_VERTEX v[4];
    v[0].pos = D3DXVECTOR4(-0.5f, -0.5f, 0.0f, 1.0f);
    v[1].pos = D3DXVECTOR4(width, -0.5f, 0.0f, 1.0f);
    v[2].pos = D3DXVECTOR4(-0.5f, height, 0.0f, 1.0f);
    v[3].pos = D3DXVECTOR4(width, height, 0.0f, 1.0f);

    v[0].tex = D3DXVECTOR2(0.0f, 0.0f);
    v[1].tex = D3DXVECTOR2(1.0f, 0.0f);
    v[2].tex = D3DXVECTOR2(0.0f, 1.0f);
    v[3].tex = D3DXVECTOR2(1.0f, 1.0f);

    g_pd3dDevice->SetFVF(TRANSFORMED_VERTEX::FVF);
    g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(TRANSFORMED_VERTEX));
}

当然,您需要在BeginScene()EndScene()之间调用此功能。您还必须正确设置纹理和采样器状态(或着色器常量)。