为什么DirectX会跳过每一次着色器调用?

时间:2015-10-09 13:44:52

标签: c++ directx shader directx-11 hlsl

我试图找出为什么必须两次调用DirectX 11着色器以查看所需结果,我感到有点沮丧。

这是我目前的状态: 我有一个从顶点和索引缓冲区构建的3d对象。然后,该对象多次实例化。之后,将会有不仅仅是一个对象,但是现在,我只用这个对象进行测试。在我的渲染例程中,我遍历所有实例,更改世界矩阵(以便将所有对象实例放在一起并形成"一个大的整个对象")并调用着色器方法将数据呈现给屏幕。

到目前为止,这里的代码不起作用:

vendors.js

我的m_pLevel->Simulate(0.1f); std::list<CLevelElementInstance*>& lst = m_pLevel->GetInstances(); float x = -(*lst.begin())->GetPosition().x, y = -(*lst.begin())->GetPosition().y, z = -(*lst.begin())->GetPosition().z; int i = 0; for (std::list<CLevelElementInstance*>::iterator it = lst.begin(); it != lst.end(); it++) { // Extract base element from current instance CLevelElement* elem = (*it)->GetBaseElement(); // Write vertex and index buffer to video memory elem->Render(m_pDirect3D->GetDeviceContext()); // Call shader m_pTextureShader->Render(m_pDirect3D->GetDeviceContext(), elem->GetIndexCount(), XMMatrixTranslation(x, y, z + (i * 8)), viewMatrix, projectionMatrix, elem->GetTexture()); ++i; } 由4个3d对象组成,它们都是相同的。它们只在3d空间中的位置不同。所有对象都是8.0f x 8.0f x 8.0f,所以为了简单起见,我只需将它们排成一行。 (可以在着色器渲染线上看到,我只需要向Z维度添加8个单位)

结果如下:我只看到屏幕上呈现的两个元素。在它们之间,有一个像元素一样大小的空白空间。 起初,我以为我在使用3d数学时遇到了一些错误,但经过大量时间调试我的代码后,我找不到任何错误。

现在是令人困惑的部分: 如果我更改for循环的内容并向着色器添加另一个调用,我会突然看到所有四个元素;他们在3d空间中处于正确的位置:

std::list

有人知道这里发生了什么吗?

如果有帮助,请点击着色器的代码:

m_pLevel->Simulate(0.1f);
std::list<CLevelElementInstance*>& lst = m_pLevel->GetInstances();
float x = -(*lst.begin())->GetPosition().x, y = -(*lst.begin())->GetPosition().y, z = -(*lst.begin())->GetPosition().z;
int i = 0;
for (std::list<CLevelElementInstance*>::iterator it = lst.begin(); it != lst.end(); it++)
{
    // Extract base element from current instance
    CLevelElement* elem = (*it)->GetBaseElement();

    // Write vertex and index buffer to video memory
    elem->Render(m_pDirect3D->GetDeviceContext());

    // Call shader
    m_pTextureShader->Render(m_pDirect3D->GetDeviceContext(), elem->GetIndexCount(), XMMatrixTranslation(x, y, z + (i * 8)), viewMatrix, projectionMatrix, elem->GetTexture());

    // Call shader a second time - this seems to have no effect but to allow the next iteration to perform it's shader rendering...
    m_pTextureShader->Render(m_pDirect3D->GetDeviceContext(), elem->GetIndexCount(), XMMatrixTranslation(x, y, z + (i * 8)), viewMatrix, projectionMatrix, elem->GetTexture());
    ++i;
}

如果有帮助,我也可以在这里发布着色器的代码。

任何帮助都将不胜感激 - 我完全被困在这里: - (

2 个答案:

答案 0 :(得分:2)

问题是你每帧都要转置你的数据,所以它只是每隔一帧“正确”:

_WorldMatrix = XMMatrixTranspose(_WorldMatrix);
_ViewMatrix = XMMatrixTranspose(_ViewMatrix);
_ProjectionMatrix = XMMatrixTranspose(_ProjectionMatrix);

相反,你应该做的事情如下:

XMMATRIX worldMatrix = XMMatrixTranspose(_WorldMatrix);
XMMATRIX viewMatrix = XMMatrixTranspose(_ViewMatrix);
XMMATRIX projectionMatrix = XMMatrixTranspose(_ProjectionMatrix);

result = _pDeviceContext->Map(m_pMatrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
    return false;
dataPtr = (MatrixBufferType*)mappedResource.pData;
dataPtr->world = worldMatrix;
dataPtr->view = viewMatrix;
dataPtr->projection = projectionMatrix;
_pDeviceContext->Unmap(m_pMatrixBuffer, 0);

答案 1 :(得分:0)

我想知道问题是由XMMatrixTranslation(x,y,z +(i * 8))调用创建的临时函数是通过引用传递给函数,然后通过引用传递给另一个函数被修改。

我对c ++规范的了解还不足以让我判断是否存在未定义的行为(但我知道这个领域有一些棘手的规则 - 将一个临时规则分配给非例如,不支持const temporary。无论如何,它足够接近于怀疑,即使它已经很好地定义了c ++,它仍然可能是一个尘土飞扬的角落,可能会使不合规的编译器绊倒。

要排除这种可能性,请尝试这样做:

In [5]: def grouped_weighted_avg(values, weights, by):
   ...:     return (values * weights).groupby(by).sum() / weights.groupby(by).sum()

In [6]: grouped_weighted_avg(values=df.wt, weights=df.value, by=df.index)
Out[6]: 
Date
01/01/2012    0.791667
01/02/2012    0.722222
dtype: float64