c++ - DirectX9 C++ 实时重新着色顶点数据

标签 c++ windows directx

我是 DirectX 的新手,我开始了解 API 的功能。

我已经设法使用这些函数正确显示和渲染三角形:

初始化顶点:

void Menu::InitializeMenu(float x, float y, float width, float height, D3DCOLOR color,    IDirect3DDevice9* d3dDevice)
{
CUSTOMVERTEX vertices[] =
{
    { x, y, 0.5f, 1.0f, color },
    { x + width, y, 0.5f, 1.0f, color },
    { x + width, y + height, 0.5f, 1.0f, color },

    { x, y, 0.5f, 1.0f, color },
    { x , y + height, 0.5f, 1.0f, color },
    { x + width, y + height, 0.5f, 1.0f, color },
};

if (FAILED(d3dDevice->CreateVertexBuffer(6 * sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_vertexBuffer, NULL)))
    return;

void *locked_buffer;
if (FAILED(m_vertexBuffer->Lock(0, sizeof(vertices), (void **)&locked_buffer, 0)))
    return;



memcpy(locked_buffer, vertices, sizeof(vertices));
m_vertexBuffer->Unlock();
}

此处的所有内容都在 Menu 类中定义。

绘图:

void Menu::RenderMenu(IDirect3DDevice9 *d3dDevice)
{
d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
d3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
d3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DRS_DESTBLENDALPHA);
d3dDevice->SetStreamSource(0, m_vertexBuffer, 0, sizeof(CUSTOMVERTEX));
d3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
d3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
}

一切都很完美,我渲染了两个三角形,这又产生了一个半透明的四边形。

现在的问题: 我希望能够在程序开始渲染后更改三角形中顶点的颜色(所有内容都已经初始化并至少渲染一次)。

我想到的事情: -我想过用不同的参数调用InitializeMenu函数来重新初始化不同颜色的顶点,我没有这样做是因为它看起来很低效而且不实用。

- Material :我还没有实现 Material ,这是因为我(还)不知道怎么做,因为我希望找到一个更简单的替代方案。我只需要顶点颜色。如果 Material 是实现这一目标的唯一途径,我会实现。

-着色器:我知道您可以使用着色器为顶点着色,但我的着色器经验很少,而且如前所述,我宁愿找到更简单的替代方法。是的,我知道着色器很简单,我已经到了可以实时更改着色器中顶点颜色的地步。它在 GLSL 中,但我相信它不会有太大差异。当我想添加多个四边形(每个四边形的 2 个三角形的集合)时,问题就来了。我只知道如何更改进入顶点着色器的所有顶点的颜色。和以前一样,如果着色器是完成的唯一方法,我会实现。请给我指出正确的方向。我对着色器如何在低级别上工作知之甚少(我了解概念和流程,只是不知道如何利用我的优势来有效地使用)。

-研究:我到处都看了,也许我没有正确地问我的问题,但我找不到任何地方的答案。

这实际上是我第一次发帖提问,通常已经有人问过我的问题了。我已尽力解释我的问题,但如果仍然不清楚,请随时索取更多代码或信息。

P.S:我使用的是 Windows 8 桌面,不确定这是否真的很重要。

最佳答案

要更新顶点,您需要执行类似于 InitializeMenu 的操作,但无需再次调用 CreateVertexBuffer。您还需要对创建顶点缓冲区的方式稍作修改。

有两种类型的顶点缓冲区:静态和动态。静态顶点缓冲区不允许 CPU 访问以进行更改,而动态顶点缓冲区则允许。

要创建动态顶点缓冲区,请将 D3DUSAGE_DYNAMIC 添加到 CreateVertexBuffer:

d3dDevice->CreateVertexBuffer(6 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_vertexBuffer, NULL)

然后你可以创建一个像这样的新函数来改变颜色:

void Menu::ChangeColor(D3DColor color) {
    CUSTOMVERTEX *locked_buffer;
    if (FAILED(m_vertexBuffer->Lock(0, 0, (void **)&locked_buffer, 0))) {
        return;
    }

    for (int i=0; i<6; i++) {
        // use whatever you called color in your CUSTOMVERTEX struct
        locked_buffer[i].color = color;
    }
    m_vertexBuffer->Unlock();
}

此代码实质上是从 GPU 获取顶点数据,并允许您在 CPU 上更新它。您无需重新创建顶点缓冲区,只需更新所需的值即可。

关于c++ - DirectX9 C++ 实时重新着色顶点数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26076769/

相关文章:

c++ - 确定调用者是从 EXE 还是 DLL 调用

windows - IE10 在 IE7 模式下呈现。如何强制标准模式?

windows - TCHAR 和 _TCHAR 的区别

visual-c++ - 是否可以在绘制时查看后台缓冲区?

C++ 和 SQLite - 如何执行由用户输入形成的查询?

c++ - 编译器构造虚表

c# - 创建一组文件的打包二进制表示?

c++ - 将读取预编译的着色器文件发送到 ID3DBlob

c++ - 我的循环永远不会结束......我不明白为什么。有任何想法吗?

c++ - 在 C++ 中按升序对数组集进行排序