I am following "Raycasting Tutorial" in this site Rayacasting Tutorial, in order to create a 3D perspective in a 2D map similar to an old game known as Wolfenstein_3D.
Here is the result so far as shown in this image:
What I am confused about is the math behind rendering a billboard 2d sprite which is always facing the camera direction.
Here is the billboard 2d sprite how it looks like:
I followed the tutorial about sprite rendering, that you can find it here Draw_Sprite, and I managed to display the billboard sprite in my scene as you can see in the first image, and in the tutorial, they used the inverse matrix, they multiplied the relative position of the sprite with the inverse of the camera matrix.
the relative position of the sprite is combined with 2 coordinates since we are working on a 2d map and it's as follows:
(Disable the dark theme if you want to see a clear image)
and the camera matrix is as follows:
in the tutorial as I mentioned earlier they multiplied the relative position of the sprite with the inverse of the camera matrix as shown below:
But I don't understand how it works, why we need to multiply the inverse of the camera matrix with the matrix of our sprite, I want to understand the logic behind it, How this formula makes the sprite rotate to be always facing the camera direction ?! I am still new in game development.
First some math background for this:
2x2 matrix for 2D holds just rotation matrix. That means:
mat2 m; // rotation matrix
vec2 a,b; // 2D points
b = m*a; // rotates a by m and stores into b
If you multiply by inverse:
mat2 n;
n = inverse(m);
b = n*b;
You obtained original position a
because multiplying inverse and direct matrix is unit matrix:
b = m*a
inverse(m)*b = inverse(m)*m*a
inverse(m)*b = a
However using matrices for 2D ray caster is highly unusual as its complicates things. See:
Also using just rotational matrix means you have to offset/translate on your own either before or after rotation. So my bet you are doing in code something like this:
a = rotation_matrix*a;
a += translation;
a = Inverse(rotation_matrix)*a;
As I mentioned in the comments for purely rotational matrices the Transpose function is the same as Its inverse so for 2D:
m = a0 a1 inverse(m) = transpose(m) = a0 a2
a2 a3 a1 a3
For more info about matrices take a look at:
There are more possible notations of doing this math (using direct or inverse matrices, using row/column major order, multiplying order etc ... which might slightly change the equations).
However your matrix description does not seem right. It should be:
| camerax.x cameray.x |
| camerax.y cameray.y |
So basically the 2 direction vectors (one for x axis and one for y axis of camera/player) in world coordinates (but the camera plane normal is parallel to the other direction so its the same ... just confusing a lot)
Now this is how I see it:
The player is your camera so what you need os to convert the sprite world postion sw
into player coordinates sp
. And then just render the sprite parallel to player xz
plane (or any other if your axises are configured differently).
so let the mp
be player rotation matrix and pp
players world position then:
sp = mp*(sw-pp)
is the sprite converted into player coordinates. However depending on your engine you might need a fake wall parallel to players xz
in world coordinates instead. So the wall would be at:
sprite_wall_vertexes = sw (+/-) (inverse(mp)*sprite_half_size)