#include "render_scene_impl.h" #include #include namespace render_scene_impl { color_image_render image_render; void render_image(const render_request &req) { using info_type = scene_render_info::image_info; auto info = std::get(req.item.info); // TODO: color with depth has not been implemented assert(info.depth == nullptr); auto ren_conf = color_image_render::config_type{ .flip_y = info.flip_y, .alpha = req.item.alpha, .stream = req.stream, }; image_render.render_v2(info.img, ren_conf); } void render_mesh(const render_request &req) { using info_type = scene_render_info::mesh_info; auto info = std::get(req.item.info); auto mesh_conf = mesh_info_type{ .mesh = info.mesh.get(), .transform = req.item.transform, .material = info.material, }; auto ren_conf = mesh_render_info{ .mode = MESH_NORMAL, .model = mesh_conf, .camera = req.camera, .light= req.light, }; // depth alpha if (info.enable_depth_alpha) { ren_conf.mode = MESH_DEPTH_ALPHA; auto &extra = ren_conf.extra.depth_alpha; extra.alpha_factor = info.alpha_factor; } render_mesh(ren_conf); } void render_pc(const render_request &req) { using info_type = scene_render_info::pc_info; auto info = std::get(req.item.info); auto ren_conf = pc_render::config_type{ .stream = req.stream, }; ren_conf.pc = { .transform = req.item.transform, .color = info.color, .point_size = info.point_size, }; ren_conf.camera = { .transform = req.camera.transform, .fov = req.camera_raw.fov, .near = req.camera_raw.near, .far = req.camera_raw.far, }; pc_render::render(info.pc, ren_conf); } // standard camera transform matrix -> // OpenGL 's camera transform matrix glm::mat4 cvt_camera_transform(const glm::mat4 &transform) { static constexpr auto default_focal_length = 8.0f; // 8mm auto trans_part = glm::vec3(transform[3]); auto rot_part = glm::mat3(transform); auto focal_point = trans_part + rot_part[2] * default_focal_length; auto view_up = -rot_part[1]; return glm::lookAt(trans_part, focal_point, view_up); } } glm::mat4 camera_info::projection(float aspect) const { return glm::perspective(glm::radians(fov), aspect, near, far); } void render_scene(const scene_ptr &info_ptr) { auto vp_size = query_viewport_size(); auto &info = *info_ptr; auto req = render_request{ .camera_raw = info.camera, .stream = info.stream, }; req.camera.transform = cvt_camera_transform(info.camera.transform); req.camera.project = info.camera.projection(vp_size.aspectRatio()); if (info.light.follow_camera) { req.light.direction = glm::column(info.camera.transform, 2); } else { req.light.direction = info.light.direction; } for (auto &item: info.items) { req.item = item; using info_type = std::remove_cvref_t; switch (item.info.index()) { case 1: { static_assert(std::is_same_v, scene_render_info::image_info>); render_image(req); break; } case 2: { static_assert(std::is_same_v, scene_render_info::mesh_info>); render_mesh(req); break; } case 3: { static_assert(std::is_same_v, scene_render_info::pc_info>); render_pc(req); break; } case 4: { static_assert(std::is_same_v, scene_render_info::custom_info>); std::get<4>(item.info).func(); break; } default: { RET_ERROR; } } } }