# Why is quad rendered at the center (0,0) instead of top left when using orthographic projection

I have been trying to render a quad(containg a texture) using orthographic camera so that the quad can be rendered using the screen coordinates directly.

I started of by rendering just a triangle with a image. The triangle is rendered but it seems teh center of the screen is 0,0 but using the code below it should have been at top left of the screen.

Ortho camera matrix code:

// Set the camera position
var cameraPosition = new Vector3(0.0f, 0.0f, 0.0f);
var cameraTarget = new Vector3(0f, 0.0f, 1.0f); // Looking at the origin 0,0,0
var cameraUp = new Vector3(0.0f, 1.0f, 0.0f); // Y+ is Up

// Prepare matrices
// Create the view matrix from our camera position, look target and up direction
// direct X uses left hand co-ordinate system
m_viewMatrix = Matrix.LookAtLH(cameraPosition, cameraTarget, cameraUp);

// Initialize the world matrix
m_worldMatrix = Matrix.Identity;
var scalingMatrix = Matrix.Scaling(720, 576, 1);
var translationMatrix = Matrix.Translation(new Vector3(0, 0, 0));
var rotationMatrix = Matrix.RotationZ(0);
m_worldMatrix = translationMatrix * scalingMatrix * rotationMatrix;

m_worldMatrix = translationMatrix * scalingMatrix * rotationMatrix;
var worlViewMatrix = Matrix.Multiply(m_worldMatrix, m_viewMatrix);
m_projectionMatrix = Matrix.OrthoOffCenterLH(0, 720, 576, 0, 1f, 1000.0f);
m_perObject.WorldViewProjection = Matrix.Multiply(worlViewMatrix, m_projectionMatrix);


Vertices code:

stream.WriteRange(new[]
{
new VertexPositionTexture(
new Vector4(720, 576, 0.5f, 1.0f), // position bottom-right
new Vector2(1024,576)
),
new VertexPositionTexture(
new Vector4(0, 0, 0.5f, 1.0f), // position top-left
new Vector2(0, 0)
),
new VertexPositionTexture(
new Vector4(720, 0, 0.5f, 1.0f), // position top-right
new Vector2(1024, 0)
),
});


float4x4 WorldViewProj;

{
float4 Position : SV_Position;
float2 TextureUV : TEXCOORD0;
};

{
//output.Position = input.Position;
output.Position = mul(input.Position, WorldViewProj);
output.TextureUV = input.TextureUV;
return output;
}


Screenshot of image rendered: Now I can't seem to figure out why the center of the screen is 0,0 and not top left ? Also as a part of this if I do not use a scaling matrix the triangle is not rendered.

The main reason behind the above attempt is to draw a quad/triangle using screen co-ordinates so that i can place exactly where i want without the need to calculate the vertices all the time when ever i wish to place my quad/triangle.

This issue has left me baffled for last couple days. Any help or suggestion would be really helpful.

Note: I am using Directx11 with sharpdx and still learning directx learner.

• @Jon If by GL you mean Opengl then in that case no. I'm using Directx11. In reference to multiplying matrices, that's the way I've read it should be done unless iv misinterpreted thing incorrectly. Feel free to correct me if I'm wrong – Dave23Rave Mar 27 '16 at 22:08
• @Jon If I understand correctly then in regards to your comment about matrices multiplication, to generate worldviewprojection matrix I should be doing world * (view * projection). As for the comment on Vector3. Forward I will try it when I'm back in front of my pc . – Dave23Rave Mar 27 '16 at 22:48
• You are doing WVP = W * V * P, but you are also doing W = T * S * R. It should be WVP = S * R * T * V * P, not WVP = T * S * R * V * P. I think you just have T in the wrong place, but be sure to read the very bottom of my answer regarding clip-space. – Jon Mar 28 '16 at 0:47

There are a few things going on. This is probably important to know, even if you never use GL.

These aren't the same anywhere, anytime:

"translationMatrix * rotationMatrix * scalingMatrix" //translate then rotate then scale
"scalingMatrix * rotationMatrix * translationMatrix" //scale then rotate then translate


On top of that:

GL is like an RPN-calculator using the last value provided, first (post-multiply):

 translationMatrix * rotationMatrix * scalingMatrix ==
"scalingMatrix * rotationMatrix * translationMatrix" //scale then rotate then translate

[R2] translationMatrix
[R1] rotationMatrix
[R0] scalingMatrix
[op] * //(replaces scaling and rotation matrices with (scalingMatrix, then rotationMatrix)
[op] * //(replaces [result] with ([result], then translationMatrix)


DX is like a "normal" calculator (pre-multiply):

 scalingMatrix *  rotationMatrix  * translationMatrix ==
"scalingMatrix *  rotationMatrix  * translationMatrix" ==
(scalingMatrix * (rotationMatrix) * translationMatrix) //() wherever you want

scalingMatrix * rotationMatrix    = [immediate result] //scale, then rotate
[immediate result] * translationMatrix = [immediate result] //then translate


Both are correct for their respective API's and both produce the same results:

scaling then rotation then translation


I'm not an oracle, but all of my DX code looks like this (although I use the built-in matrix methods??):

world = scale * rotation * translation;
viewProj = view * proj;
//HLSL defaults to column-major but DX is row-major, so Transpose()
//(or don't use the defaults)
SendToGPU(world.Transpose());
SendToGPU(viewProj.Transpose());


Generally, we try to re-use geometry. If you create a quad, centered at {0,0,0} whose length and width equal 1.0, then you can easily ModelMatrix that one quad to any size and place you want (including full screen). Using Identity for the MVP, you draw directly in clip-space, which centers a quad constructed as such in the screen by default. Clip-space has a fixed range of -1 to 1 on all axes (length/width/height == 2), so you could just scale the unit-quad by 2 and forget all the camera stuff.