Celeritas #003 - Basic Shadow Maps working
Got basic shadow maps working in the C layer!
It's very dark because I stripped out all the lights and lighting code not necessary to getting this part working.
As an aside, it'd be nice to have a gallery widget for the above so they could sit horizontal rather than one at a time vertically.
The main loop roughly looks like this
// Main loop
while (!glfwWindowShouldClose(core->renderer.window)) {
rend_frame_begin(core);
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depth_pass_framebuffer.id);
glClear(GL_DEPTH_BUFFER_BIT);
// light space transform setup
f32 near_plane = 1.0, far_plane = 7.5;
mat4 light_projection = mat4_orthographic(-10.0, 10.0, -10.0, 10.0, near_plane, far_plane);
mat4 light_view = mat4_look_at(light_position, VEC3_ZERO, VEC3_Y);
mat4 light_space_matrix = mat4_mult(light_view, light_projection);
// 1. Render scene from light's perspective
// upload the light space transform matrix to our shader
set_shader(core, depth_shader);
uniform_mat4f(depth_shader.program_id, "lightSpaceMatrix", &light_space_matrix);
draw_model(core, cube, main, false);
draw_model(core, cube, large, false);
draw_model(core, cube, small, false);
// 2. Render the scene as normal with the depth map available for shadow mapping
set_backbuffer(); // set the active framebuffer back to 0 a.k.a. the final image
set_shader(core, core->renderer.default_shader);
// data setup
mat4 view = mat4_look_at(vec3_create(5.0, 5.0, -4.0), VEC3_ZERO, VEC3_Y);
mat4 projection =
mat4_perspective(45.0 * 3.14 / 180.0, (f32)SCR_WIDTH / (f32)SCR_HEIGHT, 0.1, 100.0);
mat4 view_proj = mat4_mult(view, projection);
vec3 cam_pos = vec3_create(5.0, 5.0, -4.0);
// upload uniforms
uniform_i32(core->renderer.default_shader.program_id, "shadowMap", 2);
uniform_mat4f(core->renderer.default_shader.program_id, "lightSpaceMatrix",
&light_space_matrix);
uniform_vec3f(core->renderer.default_shader.program_id, "lightPos", &light_position);
uniform_vec3f(core->renderer.default_shader.program_id, "viewPos", &cam_pos);
uniform_mat4f(core->renderer.default_shader.program_id, "viewProjection", &view_proj);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, depth_tex.raw);
draw_model(core, cube, main, true);
draw_model(core, cube, large, true);
draw_model(core, cube, small, true);
// (Optional) 3. debug depth texture
// set_shader(core, debug_quad);
// glActiveTexture(GL_TEXTURE0);
// glBindTexture(GL_TEXTURE_2D, depth_tex.raw);
// model quad = core->underworld.models->data[plane.raw];
// draw_mesh(&core->renderer, &quad.meshes.data[0], &TRANSFORM_DEFAULT, NULL);
rend_frame_end(core);
}
The last (Optional)
part can be uncommented to draw a fullscreen quad showing the contents of the shadow depth map texture
shown in the first image in this post.
A relatively large change behind the scenes is removing a lot of the implicit uniform uploads inside draw_model()
. It now more or less just uploads a model
uniform for each mesh, binds textures if that final boolean is true indicating we want to bind textures from its material, and then execute the draw call. This has the consequence of meaning the calling code needs to be more explicit and handle uploading uniforms (although this can be abstracted on again if we want just a generic "draw object with material and camera") but I prefer it this way anyway, it makes it more flexible.