void render_scene(const Camera& cam, bool skybox_enabled, char render_type) { glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, cam.width, cam.height); glm::mat4 view_proj_mat = compute_mvp_matrix(cam); // Draw the skybox first. skybox_shader.update_uniform("enabled", (GLuint)skybox_enabled); skybox_shader.update_uniform("world_to_cam", view_proj_mat); skybox_shader.update_uniform("cube_texture", skybox_texture_index); // Skybox should follow the camera. skybox_scene_object.transformation = glm::translate(cam.position); glDepthMask(GL_FALSE); skybox_shader.render_all(render_type); glDepthMask(GL_TRUE); phong.update_uniform("cam_pos", cam.position); phong.update_uniform("world_to_cam", view_proj_mat); color_direct.update_uniform("world_to_cam", view_proj_mat); points.update_uniform("world_to_cam", view_proj_mat); points.render_all(render_type); color_direct.render_all(render_type); phong.render_all(render_type); }
void render_all(const Camera& main_cam) { phong.update_uniform("shadows_enabled", (GLuint)shadows_enabled); // Compute shadow maps by rendering to textures from light perspectives. for (unsigned int i = 0; i < lights.size(); i++) { std::string ind_s = "[" + std::to_string(i) + "]"; phong.update_uniform("light_pos" + ind_s, lights[i].first->position); if (shadows_enabled) { lights[i].second.bind_for_writing(); Camera light_cam; light_cam.position = lights[i].first->position; light_cam.direction = glm::vec3(0, 0, 1); light_cam.fov = 0.35f; light_cam.width = lights[i].second.width; light_cam.height = lights[i].second.height; light_cam.up = glm::vec3(0, 1, 0); glm::mat4 light_mvp = compute_mvp_matrix(light_cam); // It's harmless to set these uniforms here. phong.update_uniform("world_to_light" + ind_s, light_mvp); phong.update_uniform("shadow_map" + ind_s, lights[i].second.texture_unit - GL_TEXTURE0); render_scene(light_cam, false, RENDER_SHADOW); } } // Render to the main screen. glBindFramebuffer(GL_FRAMEBUFFER, 0); if (shadows_enabled) { phong.update_uniform("light_count", (GLuint)lights.size()); for (auto& pair : lights) { pair.second.bind_for_reading(); } } render_scene(main_cam, skybox_enabled, RENDER_MAIN); // Render to any targets, e.g. vision. if (offscreen_enabled) { for (auto& target : render_targets) { void *data = target.render_buffer.get_data(); target.image_callback((unsigned char *)data, &target.acq_time); target.render_buffer.data_cleanup(); } for (auto& target : render_targets) { target.render_buffer.bind_for_writing(); render_scene(*target.cam, skybox_enabled, RENDER_OFFSCREEN); // Store the time the image was acquired. clock_gettime(CLOCK_REALTIME, &target.acq_time); // Initiate GPU to CPU DMA transfer! target.render_buffer.bind_for_reading(); } } }
glm::mat4 compute_mvp_matrix(const Camera& cam) { return compute_mvp_matrix(cam.position, cam.direction, cam.up, (float)cam.width / cam.height, cam.fov); }