c++ - Direct3D11(C++) : Updating Texture coordinates in constant buffer?

标签 c++ directx rendering direct3d direct3d11

我正在尝试使用 Direct3D 制作一个相当基本的 2D 引擎。

我制作了一个 LoadImage() 函数,它将图像的所有相当静态的行为存储在一个对象中。 (着色器、顶点缓冲区、采样器等)

我计划在常量缓冲区中使用矩阵定位顶点。

但是,我还想有一个 DrawImage() 函数,它有一个参数来告诉纹理的哪一部分应该被绘制(剪裁),所以我必须更新纹理坐标。 由于顶点缓冲区已经预定义,我想知道是否有一种方法可以通过发送到顶点着色器的常量缓冲区来更新纹理坐标?

我希望我的问题足够清楚,如果您有任何疑问,请查看下面的代码。

bool GameManager::GMLoadImage(Image* pImage, const char* pkcFilePath, ImageDesc* pImDesc)
{
    pImage = new Image();

    ID3D11ShaderResourceView* pColorMap = (pImage)->GetpColorMap();


/// CREATE SHADER RESOURCE VIEW (from file) ///
    HRESULT result = D3DX11CreateShaderResourceViewFromFileA(m_pDevice,
                                                             pkcFilePath,
                                                             0,
                                                             0,
                                                             &pColorMap,
                                                             0);
    if (FAILED(result)) {
        MessageBoxA(NULL,"Error loading ShaderResourceView from file","Error",MB_OK);
        return false;
    }


/// RECEIVE TEXTURE DESC ///
    ID3D11Resource* pColorTex;
    pColorMap->GetResource(&pColorTex);
    ((ID3D11Texture2D*)pColorTex)->GetDesc(&((pImage)->GetColorTexDesc()));
    pColorTex->Release();

/// CREATE VERTEX BUFFER ///
    D3D11_TEXTURE2D_DESC colorTexDesc = pImage->GetColorTexDesc();
    float halfWidth = static_cast<float>(colorTexDesc.Width)/2.0f;
    float halfHeight = static_cast<float>(colorTexDesc.Height)/2.0f;

    Vertex.PosTex vertices[]=
    {
        {XMFLOAT3( halfWidth, halfHeight, 1.0f ),   XMFLOAT2( 1.0f, 0.0f )},
        {XMFLOAT3( halfWidth, -halfHeight, 1.0f ),  XMFLOAT2( 1.0f, 1.0f )},
        {XMFLOAT3( -halfWidth, -halfHeight, 1.0f ), XMFLOAT2( 0.0f, 1.0f )},

        {XMFLOAT3( -halfWidth, -halfHeight, 1.0f ), XMFLOAT2( 0.0f, 1.0f )},
        {XMFLOAT3( -halfWidth, halfHeight, 1.0f ),  XMFLOAT2( 0.0f, 0.0f )},
        {XMFLOAT3( halfWidth, halfHeight, 1.0f ),   XMFLOAT2( 1.0f, 0.0f )}
    };

    D3D11_BUFFER_DESC vertexDesc;
    ZeroMemory(&vertexDesc,sizeof(vertexDesc));
    vertexDesc.Usage = D3D11_USAGE_DEFAULT;
    vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vertexDesc.ByteWidth = sizeof(Vertex.PosTex)*6;

    D3D11_SUBRESOURCE_DATA resourceData;
    resourceData.pSysMem = vertices;

    ID3D11Buffer* pVBuffer = pImage->GetpVertexBuffer();
    result = m_pDevice->CreateBuffer(&vertexDesc,&resourceData,&pVBuffer);

    if (FAILED(result))
    {
        MessageBoxA(NULL,"Error Creating VBuffer","Error",MB_OK);
        return false;
    }



/// SET POINTER TO IMAGEDESC
    ImageDesc* pThisImDesc = pImage->GetpImageDesc();
    pThisImDesc = pImDesc;

    return true;
}

bool GameManager::GMDrawImage(Image* pImage, const CLIPRECT& rkClip)
{
    ImageDesc* thisImDesc = pImage->GetpImageDesc();

    if ( (thisImDesc != m_pImDesc) ) {
        m_pImDesc = thisImDesc;
        m_pContext->IASetInputLayout(m_pImDesc->pInputLayout);
        m_pContext->IASetPrimitiveTopology(m_pImDesc->Topology);

        m_pContext->VSSetShader(m_pImDesc->pSolidColorVS,0,0);
        m_pContext->PSSetShader(m_pImDesc->pSolidColorPS,0,0);
        m_pContext->PSSetSamplers(0,1,&m_pImDesc->pSampler);
        m_pContext->OMSetBlendState(m_pImDesc->pBlendState,NULL,0xFFFFFFFF);
    }

    UINT stride = m_pImDesc->VertexSize;
    UINT offset = 0;
    ID3D11Buffer* pVBuffer = pImage->GetpVertexBuffer();
    ID3D11ShaderResourceView* pColorMap = pImage->GetpColorMap();

    m_pContext->IASetVertexBuffers(0,1,&pVBuffer,&stride,&offset);
    m_pContext->PSSetShaderResources(0,1,&pColorMap);

    //set constant buffers?

    m_pContext->Draw(6,0);
}

最佳答案

是的,只要在顶点缓冲区中将纹理坐标硬编码为 0.0 到 1.0,就可以使用纹理变换矩阵。这是一个 3x3 矩阵,可以转换您的 2D 纹理坐标。

例如,如果您想使用纹理的右下象限(假设左上角为原点),您可以使用以下矩阵:

0.5 0.0 0.0
0.0 0.5 0.0
0.5 0.5 1.0

然后,在顶点着色器中,将纹理坐标乘以该矩阵,如下所示:

float3 coord = float3(In.texCoord, 1.0);
coord *= textureTransform;
Out.texCoord = coord.xy / coord.z;

In.texCoord 和 Out.texCoord 分别是 float2 输入和输出纹理坐标。

如果您只进行仿射变换(平移、缩放、旋转和倾斜),除以 Z 是可选的,因此如果不需要,请随意删除它。

推广矩阵:

Sx  0.0 0.0
0.0 Sy  0.0
Tx  Ty  1.0

其中 Txy 是剪辑区域的位置,Sxy 是剪辑区域的大小,以纹理坐标表示。

关于c++ - Direct3D11(C++) : Updating Texture coordinates in constant buffer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7353992/

相关文章:

windows - 是什么导致了不明确的符号错误? C++

c++ - 如何将 DirectX 库包含到我自己的静态库(独立库)中?

swift - 使用 NSAttributedString 绘图时在非视网膜 Mac 上呈现模糊字体

javascript - 以最容易访问的方式预隐藏元素

c++ - 我可以在枚举中使用枚举吗?

c++ - Steam for Linux 平台库导致 Qt 应用程序行为不当

c# - 浮点 Div/Mul > 比 Add/Sub 慢 30 倍?

c++ - 将 DCMTK 与 Visual Studio 结合使用时出现链接器错误 LNK2019

winapi - 如何使用DirectWrite在面向脚本的OpenType功能与其他OpenType功能之间取得平衡?

当父 View 添加 subview 的目标元素时,BackBone.js subview 不会渲染其元素