scene_render.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #include "scene_render.h"
  2. #include "render/render_mesh.h"
  3. #include <glm/gtc/matrix_access.hpp>
  4. #include <glm/gtx/transform.hpp>
  5. #include <list>
  6. namespace scene_render_impl {
  7. glm::vec3 vec3_from_ptr(const float *ptr) {
  8. static_assert(sizeof(glm::vec3) == 3 * sizeof(float));
  9. return *(glm::vec3 *) ptr;
  10. }
  11. }
  12. using namespace scene_render_impl;
  13. struct scene_render::impl {
  14. struct actor_store_type {
  15. std::shared_ptr<mesh_type> model;
  16. actor_store_type *background = nullptr;
  17. float alpha_factor = 0.25f;
  18. bool visible = true;
  19. glm::mat4 transform = {};
  20. using material_type = mesh_info_type::material_type;
  21. material_type material = {};
  22. mesh_info_type get_mesh_info() const {
  23. return {.mesh = model.get(),
  24. .transform = transform, .material = material};
  25. }
  26. };
  27. bool enable_light_follow_camera = false;
  28. glm::vec3 light_direction = {1.0f, 0.0f, 0.0f};
  29. float camera_fov = 60.0f; // in degree
  30. float camera_near = 0.1f, camera_far = 1000.0f;
  31. glm::mat4 camera_transform = {};
  32. std::list<actor_store_type> actor_list;
  33. void *create_actor(const char *model_path, void *bg_actor) {
  34. auto &actor = actor_list.emplace_back();
  35. actor.model = mesh_type::create({.path = model_path});
  36. actor.background = (actor_store_type *) bg_actor;
  37. return &actor;
  38. }
  39. void draw() {
  40. auto info = mesh_render_info();
  41. info.camera.transform = camera_transform;
  42. float aspect = query_viewport_size().aspectRatio();
  43. info.camera.project = glm::perspective(camera_fov, aspect, camera_near, camera_far);
  44. if (enable_light_follow_camera) {
  45. auto camera_rot = glm::inverse(glm::mat3{camera_transform});
  46. light_direction = -glm::column(camera_rot, 2);
  47. }
  48. info.light.direction = light_direction;
  49. for (const auto &actor: actor_list) {
  50. if (!actor.visible) continue;
  51. info.model = actor.get_mesh_info();
  52. if (actor.background == nullptr) { // no background
  53. info.mode = MESH_NORMAL;
  54. render_mesh(info);
  55. } else { // with background
  56. info.mode = MESH_DEPTH_ALPHA;
  57. auto &ext = info.extra.depth_alpha;
  58. ext.bg = actor.background->get_mesh_info();
  59. ext.alpha_factor = actor.alpha_factor;
  60. ext.show_bg = false;
  61. render_mesh(info);
  62. }
  63. }
  64. }
  65. };
  66. scene_render::scene_render()
  67. : pimpl(std::make_unique<impl>()) {}
  68. scene_render::~scene_render() = default;
  69. void *scene_render::create_actor(const char *model_path, void *bg_actor) {
  70. return pimpl->create_actor(model_path, bg_actor);
  71. }
  72. void scene_render::set_actor_visibility(void *actor, bool visible) {
  73. auto real_ptr = (impl::actor_store_type *) actor;
  74. real_ptr->visible = visible;
  75. }
  76. void scene_render::set_actor_color(void *actor, const float *color, float ambient_factor) {
  77. auto real_ptr = (impl::actor_store_type *) actor;
  78. auto color_vec = vec3_from_ptr(color);
  79. real_ptr->material.diffuse = color_vec;
  80. real_ptr->material.ambient = ambient_factor * color_vec;
  81. }
  82. void scene_render::set_actor_alpha_factor(void *actor, float alpha_factor) {
  83. auto real_ptr = (impl::actor_store_type *) actor;
  84. real_ptr->alpha_factor = alpha_factor;
  85. }
  86. void scene_render::set_actor_transform(void *actor, glm::mat4 transform) {
  87. auto real_ptr = (impl::actor_store_type *) actor;
  88. real_ptr->transform = transform;
  89. }
  90. void scene_render::set_light_direction(glm::vec3 direction) {
  91. pimpl->light_direction = direction;
  92. }
  93. void scene_render::set_light_follow_camera(bool enable) {
  94. pimpl->enable_light_follow_camera = enable;
  95. }
  96. void scene_render::set_camera_fov(float fov) {
  97. pimpl->camera_fov = fov;
  98. }
  99. void scene_render::set_camera_clip_range(float near, float far) {
  100. pimpl->camera_near = near;
  101. pimpl->camera_far = far;
  102. }
  103. void scene_render::set_camera_transform(glm::mat4 transform) {
  104. static constexpr auto default_focal_length = 8.0f; // 8mm
  105. auto trans_part = glm::vec3(transform[3]);
  106. auto rot_part = glm::mat3(transform);
  107. auto focal_point = trans_part + rot_part[2] * default_focal_length;
  108. auto view_up = -rot_part[1];
  109. auto view_mat = glm::lookAt(trans_part, focal_point, view_up);
  110. pimpl->camera_transform = view_mat;
  111. }
  112. void scene_render::render() {
  113. pimpl->draw();
  114. }