在 DirectX C++ 中尝试矩阵转换时顶点着色器的输出错误

Output from Vertex Shader is wrong when attempting Matrix Translation in DirectX C++

我正在尝试通过 Matrix Translation 移动 3D 对象的位置。我了解矩阵乘法的工作原理,但我使用的是我的大学为我提供的图形框架,因此着色器中可能发生了我不完全理解的其他事情。着色器代码如下:

PixelInputType output;
float4 worldPosition;


// Change the position vector to be 4 units for proper matrix calculations.
input.position.w = 1.0f;

// Rotate model and move to correct position
input.position = mul(input.position, rotate);
input.position = mul(input.position, modelPosition);

// Calculate the position of the vertex against the world, view, and projection matrices.
output.position = mul(input.position, worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);

// Store the texture coordinates for the pixel shader.
output.tex = input.tex;

// Calculate the normal vector against the world matrix only.
output.normal = mul(input.normal, (float3x3)worldMatrix);

// Normalize the normal vector.
output.normal = normalize(output.normal);

// Calculate the position of the vertex in the world.
worldPosition = mul(input.position, viewMatrix);

// Determine the viewing direction based on the position of the camera and the position of the vertex in the world.
output.viewDirection = cameraPosition.xyz - worldPosition.xyz;

// Normalize the viewing direction vector.
output.viewDirection = normalize(output.viewDirection);

return output;

当我尝试使用它时,它看起来像下面这样jagged chaos

奇怪的是,当我只是传入一个 Vector3 并在之前执行此操作时它工作正常:

 PixelInputType output;
float4 worldPosition;


// Change the position vector to be 4 units for proper matrix calculations.
input.position.w = 1.0f;

// Calculate the position of the vertex against the world, view, and projection matrices.
output.position = mul(input.position, worldMatrix);
output.position = mul(output.position, rotate);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);

output.position.x = output.position.x + modelPosition.x;
output.position.y = output.position.y + modelPosition.y;
output.position.z = output.position.z + modelPosition.z;

// Store the texture coordinates for the pixel shader.
output.tex = input.tex;

// Calculate the normal vector against the world matrix only.
output.normal = mul(input.normal, (float3x3)worldMatrix);

// Normalize the normal vector.
output.normal = normalize(output.normal);

// Calculate the position of the vertex in the world.
worldPosition = mul(input.position, viewMatrix);

// Determine the viewing direction based on the position of the camera and the position of the vertex in the world.
output.viewDirection = cameraPosition.xyz - worldPosition.xyz;

// Normalize the viewing direction vector.
output.viewDirection = normalize(output.viewDirection);

return output;

所以我不完全确定哪里出错了。所有的值都被正确地传递到着色器中。

您可能正在使用列优先而不是行优先矩阵,在这种情况下,您的所有矩阵都被转置了。这意味着通常位于最后一列(主要列)的平移偏移量将位于底行。在最后一行中使用 0 0 0 1 以外的值的效果是您的矩阵不再是笛卡尔矩阵,而是最终得到旋转和缩放因子,这就是在输出中产生收缩效果的原因。

解决方案是在乘法之前转置矩阵,或者对于 vector/matrix 乘法,您可以预乘而不是 post 与顶点相乘(反之亦然)。 Here 是一个很好的解释。

在 glsl (OpenGL) 中,您将使用列主矩阵并编写 v' = Mcm * v 我不经常使用 DirectX,但它在代码中使用行主矩阵,而 hlsl 使用列主矩阵。将矩阵传递到着色器时,转置矩阵很常见。