What is the value returned by:
dot(normalize(a), normalize(b))
given that the angle between the vectors a and b is 45°.
0
1
sqrt(2)
1 / sqrt(2)
In general The dot product of 2 vectors is equal the cosine of the angle between the 2 vectors multiplied by the magnitude (length) of both vectors.
dot( A, B ) == | A | * | B | * cos( angle_A_B )
This follows, that the dot product of 2 unit vectors is equal the cosine of the angle between the 2 vectors, because the length of a unit vector is 1.
uA = normalize( A )
uB = normalize( B )
cos( angle_A_B ) == dot( uA, uB )
This means that, if the angle between a vector a and b is 45 degrees, then:
dot(normalize(a), normalize(b)) = cos(45°) = 1 / sqrt(2)
Note, the length of the diagonal in a square with a side length of 1, is sqrt(2). If the lenght of the diagonal is 1, then the length of one side is 1 / sqrt(2).
this topic has been discussed quite a few times. There are a lot of information on the memory layout of matrices in OpenGL on the internet. Sadly different sources often contradict each other.
My question boils down to:
When I have three base vectors of my matrix bx, by and bz. If I want to make a matrix out of them to plug them into a shader, how are they laid out in memory?
Lets clarify what I mean by base vector, because I suspect this can also mean different things:
When I have a 3D model, that is Z-up and I want to lay it down flat in my world space along the X-axis, then bz is [1 0 0]. I.e. a vertex [0 0 2] in model space will be transformed to [2 0 0] when that vertex is multiplied by my matrix that has bz as the base vector for the Z-axis.
Coming to OpenGL matrix memory layout:
According to the GLSL spec (GLSL Spec p.110) it says:
vec3 v, u;
mat3 m;
u = v * m;
is equivalent to
u.x = dot(v, m[0]); // m[0] is the left column of m
u.y = dot(v, m[1]); // dot(a,b) is the inner (dot) product of a and b
u.z = dot(v, m[2]);
So, in order to have best performance, I should premultiply my vertices in the vertex shader (that way the GPU can use the dot product and so on):
attribute vec4 vertex;
uniform mat4 mvp;
void main()
{
gl_Position = vertex * mvp;
}
Now OpenGL is said to be column-major (GLSL Spec p 101). I.e. the columns are laid out contiguously in memory:
[ column 0 | column 1 | column 2 | column 3 ]
[ 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 13 14 15 ]
or:
[
0 4 8 12,
1 5 9 13,
2 6 10 14,
3 7 11 15,
]
This would mean that I have to store my base vectors in the rows like this:
bx.x bx.y bx.z 0
by.x by.y by.z 0
bz.x bz.y bz.z 0
0 0 0 1
So for my example with the 3D model that I want to lay flat down, it has the base vectors:
bx = [0 0 -1]
by = [0 1 0]
bz = [1 0 0]
The model vertex [0 0 2] from above would be transformed like dis in the vertex shader:
// m[0] is [ 0 0 1 0]
// m[1] is [ 0 1 0 0]
// m[2] is [-1 0 0 0]
// v is [ 0 0 2 1]
u.x = dot([ 0 0 2 1], [ 0 0 1 0]);
u.y = dot([ 0 0 2 1], [ 0 1 0 0]);
u.z = dot([ 0 0 2 1], [-1 0 0 0]);
// u is [ 2 0 0]
Just as expected!
On the contrary:
This: Correct OpenGL matrix format?
SO question and consequently the OpenGL Faq states:
For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out contiguously in memory. The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix, where indices are numbered from 1 to 16 as described in section 2.11.2 of the OpenGL 2.1 Specification.
This says that my base vectors should be laid out in columns like this:
bx.x by.x bz.x 0
bx.y by.y bz.y 0
bx.z by.z bz.z 0
0 0 0 1
To me these two sources which both are official documentation from Khronos seem to contradict each other.
Can somebody explain this to me? Have I made a mistake? Is there indeed some wrong information?
The FAQ is correct, it should be:
bx.x by.x bz.x 0
bx.y by.y bz.y 0
bx.z by.z bz.z 0
0 0 0 1
and it's your reasoning that is flawed.
Assuming that your base vectors bx, by, bz are the model basis given in world coordinates, then the transformation from the model-space vertex v to the world space vertex Bv is given by linear combination of the base vectors:
B*v = bx*v.x + by*v.y + bz*v.z
It is not a dot product of b with v. Instead it's the matrix multiplication where B is of the above form.
Taking a dot product of a vertex u with bx would answer the inverse question: given a world-space u what would be its coordinates in the model space along the axis bx? Therefore multiplying by the transposed matrix transpose(B) would give you the transformation from world space to model space.
I try to construct my own View Matrix in OpenGL.
I'm following this link
https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
From the OpenGL doc, I have following.
eye position = eye(xe, ye, ze)
center position = cen(0, 0, 0)
up = up(xu, yu, zu). (e.g. up = (0, 1, 0))
forward vector
f' = cen - eye = (0, 0, 0) - (xe, ye, ze) = (-xe, -ye, -ze)
side vector
s' = f' x up
I don't understand why f' x up, why not up x f'
u' = s' x f'
I do't understand why u' = s' x f', why not u' = f' x s'
we normalize s', u', f'
s = norm(s'), u = norm(u'), f=norm(f')
We construct the rotation matrix with row-major(what we learn in algebra class)
R =
s_x u_x f_x 0
s_y u_y f_y 0
s_z u_z f_z 0
0 0 0 1
translation matrix:
T =
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1
we know
M = T*R
View Matrix V = invert(M)
V = invert(T*R) = invert(R)invert(T)
V = transpose(R)invert(T)
transpose(R) =
s_x s_y s_z 0
u_x u_y u_z 0
f_x f_y f_z 0
0 0 0 1
invert(T) =
1 0 0 -x
0 1 0 -y
0 0 1 -z
0 0 0 1
so
View Matrix V = transpose(R)invert(T)
But from the OpenGL doc., f change to -f
The rotation changes to following
R =
s_x u_x -f_x 0
s_y u_y -f_y 0
s_z u_z -f_z 0
0 0 0 1
I Don't understand why we need to change the forward vector to negative.
The cross product order just follows from its definition. It is just like it is. You are setting up a right-handed coordinate system. So if you align the thumb of your right hand with the first factor and the index finger with the second factor, then the middle finger will point in the direction of the cross product (perpendicular to both). There is really not much more to tell about this.
And since you are setting up a right-handed coordinate system, the forward direction of the camera must be mapped to the negative z-direction. That's why the third column of the rotation matrix is inverted. If you don't do this, you end up with a left-handed coordinate system, where the camera looks in the direction of the positive z-axis.
I am implementing perspective from scratch for an academic project. I am using "Computer Graphics: principles and practices", by Foley, van Dam, Feiner and Hughes (second edition in C).
I just followed the book by implementing all the matrices transformations needed to traslate, rotate, shear, scale, project, transform from perspective to parallel canonical view volumes and for clipping. The book apparently uses a right-handed coordinate system. However, I ended up with primitives appearing in a left-handed coordinate system and I cannot explain why.
Here are the matrices that I used:
Translation:
1, 0, 0, dx
0, 1, 0, dy
0, 0, 1, dz
0, 0, 0, 1
Rotation (to align a coordinate system (rx, ry, rz) to XYZ):
rx1, rx2, rx3, 0
ry1, ry2, ry3, 0
rz1, rz2, rz3, 0
0 , 0 , 0 , 1
Scale:
sx, 0 , 0 , 0
0 , sy, 0 , 0
0 , 0 , sz, 0
0 , 0 , 0 , 1
Shear XY:
1, 0, shx, 0
0, 1, shy, 0
0, 0, 1 , 0
0, 0, 0 , 1
Projecting onto a plane at z = d, with PRP at origin, looking in the positive z direction:
1, 0, 0 , 0
0, 1, 0 , 0
0, 0, 1 , 0
0, 0, 1/d, 0
Then given VRP, VPN, PRP, VUP, f and b (and the direction of projection dop), reduce the space to the canonical viewing volume for perspective using P:
rz = VPN / |VPN|
rx = (VUP x rz) / |VUP x rz|
ry = rz x rx
P = ScaleUniform(-1 / (vrp1Z + b)) *
Scale(-2 * vrp1Z / deltaU, -2 * vrp1Z / deltaV, 1) *
Shear(-dopX / dopZ, -dopY / dopZ) *
T(PRP) *
R(rx, ry, rz) *
T(-VRP)
Where vrp1 is ShearXY * T(-PRP) * (0, 0, 0, 1), deltaU and deltaV the width and height of the viewing window. dop is computed as CW - PRP, where CW is the center of the viewing window.
Then Projection(d) * P gives me the projection matrix.
I projected simple lines representing the unit vectors on x, y and z, but the representation that I obtained drawn on the screen was clearly a left handed coordinate system... Now I need to work in a right handed coordinate system, so is there a way to know where I did wrong?
Here is the code I used:
As you can see, the Z component of the scale matrix is of opposite sign, since clipping wasn't working properly because something was right-handed and something left-handed, but I couldn't discern what exactly, so I swapped the sign of the scale because it wasn't needed in a left-hand system.
Vector rz = vpn.toUnitVector();
Vector rx = vup.cross(rz).toUnitVector();
Vector ry = rz.cross(rx).toUnitVector();
Vector cw = viewWindow.getCenter();
Vector dop = cw - prp;
Matrix t1 = Matrix::traslation(-vrp[X], -vrp[Y], -vrp[Z]);
Matrix r = Matrix::rotation(rx, ry, rz);
Matrix t2 = Matrix::traslation(-prp[X], -prp[Y], -prp[Z]);
Matrix partial = t2 * r * t1;
Matrix shear = Matrix::shearXY(-dop[X] / dop[Z], -dop[Y] / dop[Z]);
Matrix inverseShear = Matrix::shearXY(dop[X] / dop[Z], dop[Y] / dop[Z]);
Vector vrp1 = shear * t2 * Vector(0, 0, 0, 1);
Matrix scale = Matrix::scale(
2 * vrp1[Z] / ((viewWindow.xMax - viewWindow.xMin) * (vrp1[Z] + b)),
2 * vrp1[Z] / ((viewWindow.yMax - viewWindow.yMin) * (vrp1[Z] + b)),
1 / (vrp1[Z] + b)); // HERE <--- WAS NEGATIVE
Matrix inverseScale = Matrix::scale(
((viewWindow.xMax - viewWindow.xMin) * (vrp1[Z] + b)) / (2 * vrp1[Z]),
((viewWindow.yMax - viewWindow.yMin) * (vrp1[Z] + b)) / (2 * vrp1[Z]),
(vrp1[Z] + b));
float zMin = -(vrp1[Z] + f) / (vrp1[Z] + b);
Matrix parallel = Perspective::toParallelCvv(zMin);
Matrix inverseParallel = Perspective::inverseToParallelCvv(zMin);
Matrix perspective = Perspective::copAtOrigin(-vrp1[Z]);
projection = perspective * shear * partial;
canonicalView = parallel * scale * shear * partial;
canonicalToProjection = perspective * inverseScale * inverseParallel;
I want to use the depth-fail algorithm to make shadow volumes and all works great, but i can't figure out how to extrude the shadow volume quads to infinity.
The aim is to create the shadow volume for a triangle that is lit up from a point light. I have red that i first have to change the perspective matrix that it has no far clip pane and set the w coordinate to 0. But what are the x,y,z coordinates then?
An example would be very helpful, but i also want to understand how its done.
This link shows an example of a projection matrix. It has the form:
a 0 b 0
A = 0 d e 0
0 0 -(f+n)/(f-n) -2fn/(f-n)
0 0 -1 0
f is the far plane and you want f -> infinity.
limit f -> infinity of (f+n)/(f-n) = limit f -> infinity of (1+n/f)/(1-n/f)
and
limit f -> infinity of 2fn/(f-n) = limit f -> infinity of 2n/(1-n/f)
since
f -> infinity => n/f -> 0
your matrix with f -> infinity becomes
a 0 b 0
B = 0 d e 0
0 0 -1 -2n
0 0 -1 0
if you transform your (x,y,z,w=0) with B you'll get
x' = ax + bz
y' = dy + ez
z' = -z
w' = -z
and the perspective division gives
x' = -ax/z - b
y' = -dy/z - e
z' = 1
While x' and y' are the same as transforming (x,y,z,w=0) with A, z' is now a constant that is always equal to the far plane in normalized device coordinates.
This article shows an efficient implementation of shadow volumes with capping at infinity.