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

DirectX:如何使2D图像始终平移/滚动到位,directx,pan,Directx,Pan,我正试图找到一种使用DirectX 9在适当位置平移2D图像的有效方法 我在下面附上了一张照片,希望能解释我想做什么。基本上,我想滚动纹理上所有四边形顶点的tu和tv坐标,以产生2D纹理的“原地滚动”效果 下面的第一个图像表示我加载的纹理。 第二个图像是纹理,每个角的四个顶点的tu,tv坐标显示标准渲染图像。 第三幅图说明了我希望发生的事情;我想移动顶点,使渲染的长方体跨在图像的末端,并以这样的方式卷回,即纹理将被渲染,如图所示,云的两半分开。 第四幅图显示了我的临时(浪费)解决方案;我只需将图

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

我在下面附上了一张照片,希望能解释我想做什么。基本上,我想滚动纹理上所有四边形顶点的
tu
tv
坐标,以产生2D纹理的“原地滚动”效果

下面的第一个图像表示我加载的纹理。 第二个图像是纹理,每个角的四个顶点的
tu
tv
坐标显示标准渲染图像。 第三幅图说明了我希望发生的事情;我想移动顶点,使渲染的长方体跨在图像的末端,并以这样的方式卷回,即纹理将被渲染,如图所示,云的两半分开。 第四幅图显示了我的临时(浪费)解决方案;我只需将图像翻倍并平移,直到到达最右侧边缘,然后重置顶点的tu和tv,以便渲染的长方体回到最右侧

有没有一种合法的方法可以做到这一点,而不必将所有东西分成两个单独的四边形

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

我有一个函数,它为2D渲染设置DirectX,如下所示。我已按照建议将包裹属性添加到纹理阶段0:

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;
}
这不会使任何渲染的精灵平移。 我一直在学习DirectX教程并阅读MS文档,以了解一些东西,但我的知识中肯定存在漏洞,因此我希望我没有做任何完全脑死的事情

非常感谢您的帮助


谢谢

使用一个四元组应该很容易做到这一点

假设您使用的是带有固定功能管道的DX9,则可以使用
IDirect3DDevice9::SetTransform
()转换纹理,并使用适当的纹理作为
D3DTRANSFORMSTATETYPE
()和2D转换矩阵。您必须确保采样器状态
D3DSAMP_ADDRESSU
D3DSAMP_ADDRESSV
()设置为
D3DTADDRESS_WRAP
()。这将虚拟平铺纹理,以便将负uv值或大于1的值映射到纹理的无限重复


如果使用的是着色器或其他版本的directx,则可以在着色器中自己平移纹理坐标或操纵顶点的uv值

使用一个四元组应该很容易做到这一点

假设您使用的是带有固定功能管道的DX9,则可以使用
IDirect3DDevice9::SetTransform
()转换纹理,并使用适当的纹理作为
D3DTRANSFORMSTATETYPE
()和2D转换矩阵。您必须确保采样器状态
D3DSAMP_ADDRESSU
D3DSAMP_ADDRESSV
()设置为
D3DTADDRESS_WRAP
()。这将虚拟平铺纹理,以便将负uv值或大于1的值映射到纹理的无限重复


如果使用的是着色器或其他版本的directx,则可以在着色器中自己平移纹理坐标或操纵顶点的uv值

我可能在做一些非常愚蠢的事情,但似乎不起作用。你能详细说明一下吗?一分钟后,我将用我的设置代码更新问题。快速猜测:您的
CUSTOMFVF
看起来怎么样?如果您使用的是
D3DFVF\u TEX1
您应该使用
pd3dDevice->SetTransform(D3DTS\u TEXTURE1,&ret)
并且您可以使用函数
D3DXMatrixTransformation2D
()来构建矩阵。看起来你在使用3D转换矩阵。是的,我终于弄明白了。我误解了将uv值移动到1以上的概念,正如您所提到的,这只是将uv值缩放到0和1之间的想象极限之外的问题。谢谢你的帮助!我可能在做一些非常愚蠢的事情,但似乎不起作用。你能详细说明一下吗?一分钟后,我将用我的设置代码更新问题。快速猜测:您的
CUSTOMFVF
看起来怎么样?如果您使用的是
D3DFVF\u TEX1
您应该使用
pd3dDevice->SetTransform(D3DTS\u TEXTURE1,&ret)
并且您可以使用函数
D3DXMatrixTransformation2D
()来构建矩阵。看起来你在使用3D转换矩阵。是的,我终于弄明白了。我误解了将uv值移动到1以上的概念,正如您所提到的,这只是将uv值缩放到0和1之间的想象极限之外的问题。谢谢你的帮助!
{
    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 );
}