General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 rivejä
1.7 KiB

  1. #pragma once
  2. #include "gp_config.hpp"
  3. #include "gp/math.hpp"
  4. #include "gp/function.hpp"
  5. #include "gp/algorithm/min_of.hpp"
  6. #include "gp/indexed_array.hpp"
  7. using vec2 = gp::vec2_g<>;
  8. using vec3 = gp::vec3_g<>;
  9. using vec4 = gp::vec4_g<>;
  10. struct camera{
  11. vec3 position;
  12. vec3 normal;
  13. };
  14. using index_t = size_t;
  15. using distance_t = gp_config::rendering::default_type;
  16. using color_t = GP_CONFIG__RENDERING__COLOR_T;
  17. struct render_point{
  18. distance_t distance;
  19. index_t material;
  20. bool operator<(const render_point& rhs) {
  21. return distance < rhs.distance;
  22. }
  23. };
  24. using sdf_t = gp::function<render_point(vec3)>;
  25. using material_t = gp::function<color_t(vec3)>;
  26. class renderer {
  27. using g_t = gp_config::rendering::default_type;
  28. constexpr static auto epsilon = gp_config::rendering::epsilon;
  29. public:
  30. gp::indexed_array<sdf_t, 4096> scene_elements;
  31. gp::indexed_array<material_t, 4096> materials;
  32. material_t sky_box = [](vec3) -> color_t { return vec4{0,0,0,0};};
  33. vec2 _resolution{128,64};
  34. camera _camera{{0, 0, -1}, {0, 0, 0}};
  35. vec2 _fov{90, 45};
  36. distance_t projection_start = 1;
  37. distance_t projection_end = 50;
  38. size_t passes = 12;
  39. renderer() = default;
  40. color_t render(vec2 pixel) {
  41. g_t depth = projection_start;
  42. vec3 target{0,0,0};
  43. target = target.normalize();
  44. vec3 render_target{_camera.position};
  45. for(int i = 0; i < passes; ++i) {
  46. render_target = _camera.position+depth*target;
  47. render_point distance = gp::min_of(
  48. scene_elements.begin(),
  49. scene_elements.end(),
  50. [&](auto& p){
  51. return p(render_target);
  52. }
  53. );
  54. if(distance.distance < epsilon) {
  55. return materials[distance.material](render_target);
  56. }
  57. depth += distance.distance;
  58. if(depth >= projection_end) {
  59. break;
  60. }
  61. }
  62. return sky_box(render_target);
  63. }
  64. };