Jump to content
  • Advertisement
Sign in to follow this  
FantasyVII

Diretcx Rotation Matrix Problem

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

If you intended to correct an error in the post then please contact us.

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.
 
 
gl_matrix04.png
 
 
 
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 r = ToRadians(angle);
	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 this post


Link to post
Share on other sites
Advertisement

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

 

you should use one order for both.

 

you could also add shaders here.

 

in other words post your shader code here (ogl and dx)

 

and youse one matrix notation for both dx and ogl

Edited by WiredCat

Share this post


Link to post
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.

 

you could also add shaders here.

 

in other words post your shader code here (ogl and dx)

 

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

cbuffer shader_data
{
	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;

layout (std140) uniform shader_data
{
	mat4 buffer_modelMatrix;
	vec4 buffer_color;
};

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

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!