Hello,
I'm trying to get view and projection matrices for directional light for shadow map. I'm confused about getting rotation part for rotating/multiplying corners. Currently this seems work:
GkCamera*
gkCameraForLight(GkScene *scene, GkLight *light) {
mat4 view, proj;
GkCamera *cam;
cam = scene->camera;
switch (light->type) {
case GK_LIGHT_TYPE_DIRECTIONAL: {
vec4 *c;
vec3 box[2], he, v;
int32_t i;
memset(box, 0, sizeof(box));
gkLightRotation(scene, light, view[0], view[1], view[2]);
glm_vec_broadcast(0.0f, view[3]);
view[0][3] = view[1][3] = view[2][3] = 0.0f;
view[3][3] = 1.0f;
c = cam->frustum.corners;
for (i = 0; i < 8; i++) {
glm_vec_rotate_m4(view, c[i], v);
box[0][0] = glm_min(box[0][0], v[0]);
box[0][1] = glm_min(box[0][1], v[1]);
box[0][2] = glm_min(box[0][2], v[2]);
box[1][0] = glm_max(box[1][0], v[0]);
box[1][1] = glm_max(box[1][1], v[1]);
box[1][2] = glm_max(box[1][2], v[2]);
}
glm_vec_sub(box[1], box[0], he);
glm_vec_scale(he, 0.5f, he);
glm_mat4_copy(GLM_MAT4_IDENTITY, proj);
proj[0][0] = 1.0f / he[0];
proj[1][1] = 1.0f / he[1];
proj[2][2] = 1.0f / he[2];
/* create view matrix: there is no position */
glm_mat4_transpose(view);
break;
}
case GK_LIGHT_TYPE_POINT:
case GK_LIGHT_TYPE_SPOT:
default:
break;
}
return gkMakeCamera(proj, view);
}
/* ------ */
void
gkLightRotation(GkScene *scene,
GkLight *light,
vec3 right,
vec3 up,
vec3 fwd) {
GkTransform *trans;
glm_vec_copy(light->direction, fwd);
glm_vec_copy(light->up, up);
if ((trans = gkLightTransform(light))) {
glm_vec_rotate_m4(trans->world, fwd, fwd);
glm_vec_rotate_m4(trans->world, up, up);
}
glm_vec_cross(fwd, up, right);
glm_vec_normalize(right);
glm_vec_normalize(up);
glm_vec_normalize(fwd);
}
I was getting rotation matrix (for getting bbox for light) with this by following question / answers:
gkLightDirWorld(scene, light, view[2]); /* forward vector */
glm_vec_normalize(view[2]);
glm_vec_cross(view[2], GLM_ZUP, view[0]); /* right vector */
glm_vec_normalize(view[0]);
glm_vec_cross(view[2], rot[0], view[1]); /* up vector */
glm_vec_normalize(view[1]);
this also works. Since I don't know how it works because we need least two vector for cross product, right? Z_UP (0, 0, 1) seems arbitrary vector :-S
So I stored default UP (0, 1, 0) vector in light struct as I did for default light direction (0, 0 -1), now every light has direction and up vector, right vector is computed as cross product. They will be rotated when every transform changed. Is it good idea to store extra UP vector since we can get like above? How do you get UP vector if you do similar? if not what is best way to get projection/view matrix for directional light?
My TODOS:
- I'll iterate all objects and create bbox which surrounds all objects instead of taking camera's frustum corners