I'm using OpenGL ES 2.0 to render only 2D shapes, since it's OpenGL ES 2.0 I have to create my own transformaton matrices.

Being only 2D shapes I'd like to keep all my matrices as 3x3 and my vectors with only 2 coordinates.

I also need a projection matrix as I would like to have my coordinates mapped to the screen, I don't want to specify positions from [-1.0; 1.0].

From what I've seen people still use 4x4 matrices for 2D and vectors with z set to 1, and an orthographic projection matrix.

My question is: How can I do all my transformations and the projection with only 3x3 matrices? I have all but the projection matrix set up, but the translation doesn't work.

So far I've done my translation matrix like this:

```
m[0][0] = 1; m[0][1] = 0; m[0][2] = tx;
m[1][0] = 0; m[1][2] = 1; m[1][2] = ty;
m[2][0] = 0; m[2][3] = 0; m[2][2] = 1;
```

And from what I can tell this should work, even with NDC coordinates, when multiplied by a vector it should result in

```
x+tx y+ty 1.0
```

But when I try to translate this triangle that goes from -1 to 1 with tx = 2f it gets squashed and doesn't move.

Before translation:

After translation:

for reference here is how I draw the triangle:

```
GLES20.glUniformMatrix3fv(shader.GetUniform("u_transform_mat"), 1, false, Transform.GetTransformationMatrix().ToFloatBuffer());
GLES20.glEnableVertexAttribArray(shader.GetAttribute("a_vert_position"));
GLES20.glEnableVertexAttribArray(shader.GetAttribute("a_vert_color"));
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, VBO[0]);
GLES20.glVertexAttribPointer(shader.GetAttribute("a_vert_position"), 2, GLES20.GL_FLOAT, false, Vertex.SIZE, 0);
GLES20.glVertexAttribPointer(shader.GetAttribute("a_vert_color"), 4, GLES20.GL_FLOAT, false, Vertex.SIZE, Vertex.POS_SIZE);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, IBO[0]);
GLES20.glDrawElements(primitive, size, GLES20.GL_UNSIGNED_INT, 0);
GLES20.glDisableVertexAttribArray(shader.GetAttribute("a_vert_color"));
GLES20.glDisableVertexAttribArray(shader.GetAttribute("a_vert_position"));
```

and my vertex shader

```
uniform mat3 u_transform_mat;
attribute vec3 a_vert_position;
attribute vec4 a_vert_color;
varying vec4 v_vert_color;
void main()
{
v_vert_color = a_vert_color;
gl_Position = vec4(u_transform_mat * a_vert_position, 1.0);
}
```

# Best How To :

You can certainly use 3x3 matrices to apply affine transformations in 2D. You just have to be careful that you're consistent about it.

From a look at the code fragments you posted, there are two things that look problematic:

## Matrices need to be column major

OpenGL expects matrices to be stored in column major order. From the way you build your matrix:

```
m[0][0] = 1; m[0][1] = 0; m[0][2] = tx;
m[1][0] = 0; m[1][2] = 1; m[1][2] = ty;
m[2][0] = 0; m[2][3] = 0; m[2][2] = 1;
```

this places the translation components where they would have to be for a row major matrix. It also assigns `m[1][2]`

twice, and assigns `m[2][3]`

, which is out of range for a 3x3 matrix. In turn, it never assigns `m[1][1]`

and `m[2][1]`

.

If you want to keep writing your matrices this way (which I agree is more readable), you can swap around the indices:

```
m[0][0] = 1; m[1][0] = 0; m[2][0] = tx;
m[0][1] = 0; m[1][1] = 1; m[2][1] = ty;
m[0][2] = 0; m[1][2] = 0; m[2][2] = 1;
```

## 3rd vector component needs to be 1.0

You're specifying two components for your vertex position attribute, which makes sense:

```
GLES20.glVertexAttribPointer(shader.GetAttribute("a_vert_position"), 2,
GLES20.GL_FLOAT, false, Vertex.SIZE, 0);
```

But then in the shader, you have this:

```
attribute vec3 a_vert_position;
```

Declaring the attribute variable larger than the number of components passed into the shader is perfectly legal. Unspecified components are filled with 0.0 for components `y`

and `z`

, and 1.0 for `w`

. Therefore, in your shader code, `a_vert_position.z`

will be filled with 0.0. If you then multiply it with the 3x3 transformation matrix:

```
u_transform_mat * a_vert_position
```

This means that the translation part will not be applied. Just like the 4th component needs to 1.0 when applying 4x4 matrices to 4 component vectors for an affine transformation in 3D space, the 3rd component needs to be 1.0 when applying 3x3 matrices to 3 component vectors for an affine transformation in 2D space.

The easiest way to fix this is to declare the attribute as `vec2`

, and add 1.0 as the 3rd component when applying the transformation matrix:

```
attribute vec2 a_vert_position;
...
gl_Position = vec4(u_transform_mat * vec3(a_vert_position, 1.0), 1.0);
```