Diretcx Rotation Matrix Problem

This topic is 859 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hi,

I'm making a DirectX/OpenGL engine for learning purposes. However I'm having a problem with my implementation of the rotation matrix for DirectX.

The rotation on the x and z axis looks fine for both DirectX and OpenGL. Also the rotation on the Y axis in OpenGL looks fine too. However the rotation on the Y axis in DirectX looks very weird.

This how OpenGL Y axis rotation looks like. Which looks perfectly fine.

And here how DirectX Y axis rotation looks like.

The triangle in DirectX looks like a  right-angled triangle for some reason.

Now I understand why the triangle doesn't get rendered in DirectX when it is flipped. That is not the problem, the problem is that the triangle looks like it somehow turned into a right-angled triangle. I don't know why.

This is the image I'm using for my implementation.

Here is my matrix function

/*
m11 m12 m13 m14  x
m21 m22 m23 m24  y
m31 m32 m33 m34  z
x y z w  m41 m42 m43 m44  w

C++ array indices		[0,   1,   2,   3  ], [4,   5,   6,   7  ], [8,   9,   10,  11 ]  [12,  13,  14,  15 ]
DirectX matrix layout		[m11, m21, m31, m41], [m12, m22, m32, m42], [m13, m23, m33, m43], [m14, m24, m34, m44]
OpenGL matrix layout		[m11, m12, m13, m14], [m21, m22, m23, m24], [m31, m32, m33, m34], [m41, m42, m43, m44]
*/

const int ROW_COLUMN_SIZE = 4;

Matrix4 Matrix4::Rotate(const float &angle, const Vector3 &axis)
{
Matrix4 RotationMatrix = Matrix4::Identity();

float c = cos(r);
float s = sin(r);
float oc = 1 - c;

if (Graphics::Renderer::renderingAPI == Graphics::Renderer::RenderingAPI::DirectX11)
{
//First column
RotationMatrix.elements[0 * ROW_COLUMN_SIZE + 0] = axis.x * axis.x * oc + c;
RotationMatrix.elements[0 * ROW_COLUMN_SIZE + 1] = axis.x * axis.y * oc + axis.z * s;
RotationMatrix.elements[0 * ROW_COLUMN_SIZE + 2] = axis.x * axis.z * oc - axis.y * s;

//Second column
RotationMatrix.elements[1 * ROW_COLUMN_SIZE + 0] = axis.x * axis.y * oc - axis.z * s;
RotationMatrix.elements[1 * ROW_COLUMN_SIZE + 1] = axis.y * axis.y * oc + c;
RotationMatrix.elements[1 * ROW_COLUMN_SIZE + 2] = axis.y * axis.z * oc + axis.x * s;

//Third column
RotationMatrix.elements[2 * ROW_COLUMN_SIZE + 0] = axis.x * axis.z * oc + axis.y * s;
RotationMatrix.elements[2 * ROW_COLUMN_SIZE + 1] = axis.y * axis.z * oc - axis.x * s;
RotationMatrix.elements[2 * ROW_COLUMN_SIZE + 2] = axis.z * axis.z * oc + c;
}
else if (Graphics::Renderer::renderingAPI == Graphics::Renderer::RenderingAPI::OpenGL4_5)
{
//First row
RotationMatrix.elements[0 + 0 * ROW_COLUMN_SIZE] = axis.x * axis.x * oc + c;
RotationMatrix.elements[1 + 0 * ROW_COLUMN_SIZE] = axis.x * axis.y * oc - axis.z * s;
RotationMatrix.elements[2 + 0 * ROW_COLUMN_SIZE] = axis.x * axis.z * oc + axis.y * s;

//Second row
RotationMatrix.elements[0 + 1 * ROW_COLUMN_SIZE] = axis.x * axis.y * oc + axis.z * s;
RotationMatrix.elements[1 + 1 * ROW_COLUMN_SIZE] = axis.y * axis.y * oc + c;
RotationMatrix.elements[2 + 1 * ROW_COLUMN_SIZE] = axis.y * axis.z * oc - axis.x * s;

//Third row
RotationMatrix.elements[0 + 2 * ROW_COLUMN_SIZE] = axis.x * axis.z * oc - axis.y * s;
RotationMatrix.elements[1 + 2 * ROW_COLUMN_SIZE] = axis.y * axis.z * oc + axis.x * s;
RotationMatrix.elements[2 + 2 * ROW_COLUMN_SIZE] = axis.z * axis.z * oc + c;
}

return RotationMatrix;
}



OpenGL and DirectX rotation

[spoiler]

OpenGL rotation

X axis

Y axis

Z axis

DirectX rotation

X axis

Y axis

Z axis
[/spoiler]

Edited by FantasyVII

Share on other sites

just to be sure, are you using the same multiplication order in shaders (both ogl and dx)?

you should use one order for both.

and youse one matrix notation for both dx and ogl

Edited by WiredCat

Share on other sites

just to be sure, are you using the same multiplication order in shaders (both ogl and dx)?

you should use one order for both.

and youse one matrix notation for both dx and ogl

I'm only passing the rotation matrix to the shader.

My modelMatrix has nothing but the rotation matrix.

initBuffer.modelMatrix = Matrix4::Rotate(initBuffer.angle, Vector3(0, 0, 1));

hlsl

{
float4x4 buffer_modelMatrix;
float4 buffer_color;
};

struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};

VOut main(float4 position : POSITION, float4 color : COLOR)
{
VOut output;

output.position = mul(position, buffer_modelMatrix);
output.color = color + buffer_color;

return output;
}

//-------------------------------------------------------------

glsl

#version 450 core
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;

out vec3 fragmentColor;

{
mat4 buffer_modelMatrix;
vec4 buffer_color;
};

void main()
{
gl_Position = buffer_modelMatrix * vec4(inPosition.xyz, 1.0f);
fragmentColor = inColor + buffer_color.xyz;
}


Share on other sites

It can be many things, implying that we must guess a solution.

Check the winding order of the triangle. DX will back-face cull CCW oriented triangles/polygons by default, whereas OpenGL culls CW oriented ones when viewed front-face by default.

Disable depth.

Disable culling.

Validate the projection matrix.

Validate vertex/index/constant buffers.

Use RenderDoc/IntelGPA/Visual Studio Graphics Debugger if available for debugging/resource validation.

BTW, there is absolutely no reason for using the general angle-axis function to create a rotation matrix along a *basis* axis which is much more error-prone than doing the following, assuming a column-major matrix:


Mat3 Mat3::RotationY(float angle)
{
float c = cos(angle);
float s = sin(angle);

Mat3 A =
{ {
{  c, 0, s },
{  0, 1, 0 },
{ -s, 0, c }
} };

return A;
}



Try those things out and post the results here. You also might want to post these kinds of questions in the graphics section in the future as well, as the rotation matrix seems to be correct by looking at the equation (which is math-related).

Share on other sites

For the life of me I can't figure out why is this happening. I have spent all day and can't figure it out.

I have set the Cull mode in DX11 to D3D11_CULL_NONE.

I have taken your rotation matrix and put it in the shader. So the only thing i'm passing to the shader is an angle that I incurment by 0.00025f every frame.

I'm still having the same problem.

cbuffer shader_data
{
float angle;
};

struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};

float3x3 RotationY(float angle)
{
float c = cos(angle);
float s = sin(angle);

float3x3 A =
{ {
{ c, 0, s },
{ 0, 1, 0 },
{ -s, 0, c }
} };

return A;
}

VOut main(float4 position : POSITION, float4 color : COLOR)
{
float3x3 buffer_modelMatrix = RotationY(angle);

VOut output;

output.position = float4(mul(position.xyz, buffer_modelMatrix), 1.0f);
output.color = color;

return output;
}


Edited by FantasyVII

Share on other sites

This tutorial seems to be a good introduction for begginers:

http://www.rastertek.com/dx11tut04.html

I agree, but that still doesn't help me with this problem. I have no interest in using the built-in Math library in DirectX.

Share on other sites

Disable depth.

I'm so dumb. I thought I disabled depth. It turns out I didn't. After setting DepthClipEnable to false, everything worked just fine. Thanks

Share on other sites

You can't expect your code to work since the projection matrix is missing. I copied over below the one I'm using currently (RH):

Mat4 PerspectiveRH(float fovy, float aspect, float zNear, float zFar)
{
float f = tanf(0.5f * (PI - fovy));
float invRange = 1.0f / (zNear - zFar);
Mat4 A =
{ {
{ f / aspect, 0.0f, 0.0f,                        0.0f },
{ 0.0f,       f,    0.0f,                        0.0f },
{ 0.0f,       0.0f, invRange * (zNear + zFar),  -1.0f },
{ 0.0f,       0.0f, invRange *  zNear * zFar,    0.0f }
} };
return A;
}



You should also swap your multiplication order to matrix-vector in the shader. Example:


void main(in float3 InPos : POSITION, out float4 OutPos : SV_Position)
{
float4 HomoPos = float4(InPos, 1.0);
OutPos = mul(ProjectionMatrix, HomoPos);
}



Good luck!

Share on other sites

You can't expect your code to work since the projection matrix is missing. I copied over below the one I'm using currently (RH):

Mat4 PerspectiveRH(float fovy, float aspect, float zNear, float zFar)
{
float f = tanf(0.5f * (PI - fovy));
float invRange = 1.0f / (zNear - zFar);
Mat4 A =
{ {
{ f / aspect, 0.0f, 0.0f,                        0.0f },
{ 0.0f,       f,    0.0f,                        0.0f },
{ 0.0f,       0.0f, invRange * (zNear + zFar),  -1.0f },
{ 0.0f,       0.0f, invRange *  zNear * zFar,    0.0f }
} };
return A;
}



You should also swap your multiplication order to matrix-vector in the shader. Example:


void main(in float3 InPos : POSITION, out float4 OutPos : SV_Position)
{
float4 HomoPos = float4(InPos, 1.0);
OutPos = mul(ProjectionMatrix, HomoPos);
}



Good luck!

Well I didn't think I needed to add the projection matrix yet since OpenGL didn't need one. Obviously I was wrong. Thanks :)

1. 1
2. 2
3. 3
Rutin
13
4. 4
5. 5

• 26
• 10
• 9
• 9
• 11
• Forum Statistics

• Total Topics
633696
• Total Posts
3013394
×