DirectX:如何使2D图像不断平移/滚动到位

时间:2013-06-07 07:09:20

标签: directx pan

我正在尝试使用DirectX 9找到一种有效的平移2D图像的方法

我附上了一张图片,希望能解释我想做什么。基本上,我想在纹理上滚动所有四边形顶点的tutv坐标,以便为2D纹理生成“就地滚动”效果。

下面的第一张图片代表我加载的纹理。 第二个图像是纹理,每个角上的四个顶点的tutv坐标显示标准渲染图像。 第三张图片说明了我想要发生的事情;我想以这样的方式移动顶点:渲染的框架跨越图像的末端并以这样的方式回绕,使得纹理将如图所示呈现,云的两半被分开。 第四张图片显示了我的临时(浪费)解决方案;我简单地将图像加倍并平移,直到我到达最右边缘,此时我重置顶点的tu和tv,以便渲染的框回到最右边。

有没有合法的方法可以做到这一点而不会将所有内容分成两个独立的四边形?

Panning Clouds

我已经在下面添加了我的设置和渲染代码的详细信息,如果这有助于阐明使用我当前设计的解决方案的路径。

我有一个为2D渲染设置DirectX的功能,如下所示。我按照建议在纹理阶段0添加了wrap属性:

VOID SetupDirectXFor2DRender()
{
    pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
    pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
    pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT );

    // Set for wrapping textures to enable panning sprite render
    pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP );
    pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP );

    pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
    pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 0 );

    pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, true );
    pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, false );

    pd3dDevice->SetRenderState( D3DRS_SRCBLEND , D3DBLEND_SRCALPHA );
    pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA) ;

    pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
    pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
    pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );

    pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
    pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
    pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );

    pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
    pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
    pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );

    return;
}

在每一帧上,我按如下方式渲染:

VOID RenderAllEntities()
{
    HRESULT hResult;
    // Void pointer for DirectX buffer locking
    VOID* pVoid;

    hResult = pd3dDevice->Clear( 0,
                                 NULL,
                                 D3DCLEAR_TARGET,
                                 0x0,
                                 1.0f,
                                 0 );

    hResult = pd3dDevice->BeginScene();

    // Do rendering on the back buffer here
    hResult = pd3dDevice->SetFVF( CUSTOMFVF );

    hResult = pd3dDevice->SetStreamSource( 0, pVertexBuffer, 0, sizeof(CUSTOM_VERTEX) );

    for ( std::vector<RenderContext>::iterator renderContextIndex = queuedContexts.begin(); renderContextIndex != queuedContexts.end(); ++renderContextIndex )
    {
        // Render each sprite
        for ( UINT uiIndex = 0; uiIndex < (*renderContextIndex).uiNumSprites; ++uiIndex )
        {
            // Lock the vertex buffer into memory
            hResult = pVertexBuffer->Lock( 0, 0, &pVoid, 0 );
            // Copy our vertex buffer to memory
            ::memcpy( pVoid, &renderContextIndex->vertexLists[uiIndex], sizeof(vertexList) );
            // Unlock buffer
            hResult = pVertexBuffer->Unlock();

            hResult = pd3dDevice->SetTexture( 0, (*renderContextIndex).textures[uiIndex]->GetTexture() );   
            hResult = pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 6 );
        }
    }

    // Complete and present the rendered scene
    hResult = pd3dDevice->EndScene();
    hResult = pd3dDevice->Present( NULL, NULL, NULL, NULL );

    return;
}

为了测试SetTransform,我尝试在调用DrawPrimitive之前在渲染代码中添加以下(草率但临时的)代码块:

{
    static FLOAT di = 0.0f;
    static FLOAT dy = 0.0f;

    di += 0.03f;
    dy += 0.03f;
    // Build and set translation matrix
    D3DXMATRIX ret;

    D3DXMatrixIdentity(&ret);
    ret(3, 0) = di;
    ret(3, 1) = dy;
    //ret(3, 2) = dz;

    hResult = pd3dDevice->SetTransform( D3DTS_TEXTURE0, &ret );
}

这不会使我渲染的任何精灵泛滥。 我一直在研究DirectX教程并阅读MS文档来了解事情,但我的知识肯定存在漏洞,所以我希望我没有做任何完全脑死亡的事情。

任何帮助超级赞赏。

谢谢!

1 个答案:

答案 0 :(得分:1)

对于一个四核音乐应该很容易安静。

假设您正在使用具有固定功能管道的DX9,您可以使用IDirect3DDevice9::SetTransformdoc)将纹理转换为具有D3DTRANSFORMSTATETYPE D3DSAMP_ADDRESSU的正确纹理(doc )和2D翻译矩阵。您必须确保您的采样器状态D3DSAMP_ADDRESSVD3DTADDRESS_WRAPdoc)设置为{{1}}(doc)。这会虚拟地对纹理进行平铺,因此将负值uv值或大于1的值映射到纹理的无限重复。

如果您正在使用着色器或其他版本的directx,则可以在着色器中自行翻译纹理坐标或操纵顶点的uv值。