light_system.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #include "light_system.h"
  2. #include "core/engine.h"
  3. #include "debug/kassert.h"
  4. #include "logger.h"
  5. #include "math/kmath.h"
  6. #include "memory/kmemory.h"
  7. #include "renderer/renderer_frontend.h"
  8. #include "renderer/renderer_types.h"
  9. static klight create_new_handle(light_system_state* state);
  10. b8 light_system_initialize(u64* memory_requirement, light_system_state* memory, void* config) {
  11. *memory_requirement = sizeof(light_system_state);
  12. if (!memory) {
  13. return true;
  14. }
  15. // NOTE: perform config/init here.
  16. light_system_state* state = (light_system_state*)memory;
  17. state->lights = KALLOC_TYPE_CARRAY(klight_data, MAX_GLOBAL_SSBO_LIGHTS);
  18. // Global lighting storage buffer
  19. u64 buffer_size = sizeof(light_global_ssbo_data);
  20. state->lighting_global_ssbo = renderer_renderbuffer_create(engine_systems_get()->renderer_system, kname_create(KRENDERBUFFER_NAME_LIGHTING_GLOBAL), RENDERBUFFER_TYPE_STORAGE, buffer_size, RENDERBUFFER_TRACK_TYPE_NONE, RENDERBUFFER_FLAG_AUTO_MAP_MEMORY_BIT | RENDERBUFFER_FLAG_TRIPLE_BUFFERED_BIT);
  21. KASSERT(state->lighting_global_ssbo != KRENDERBUFFER_INVALID);
  22. KDEBUG("Created lighting global storage buffer.");
  23. return true;
  24. }
  25. void light_system_shutdown(light_system_state* state) {
  26. if (state) {
  27. // NOTE: perform teardown here.
  28. renderer_renderbuffer_destroy(engine_systems_get()->renderer_system, state->lighting_global_ssbo);
  29. }
  30. }
  31. void light_system_frame_prepare(light_system_state* state, frame_data* p_frame_data) {
  32. void* memory = renderer_renderbuffer_get_mapped_memory(engine_systems_get()->renderer_system, state->lighting_global_ssbo);
  33. for (u16 i = 0; i < MAX_GLOBAL_SSBO_LIGHTS; ++i) {
  34. klight_data* l = &state->lights[i];
  35. light_shader_data* sd = &((light_shader_data*)memory)[i];
  36. if (l->type == KLIGHT_TYPE_POINT) {
  37. sd->colour = vec4_from_vec3(l->colour, l->attenuation.linear);
  38. sd->position = vec4_from_vec3(l->position, l->attenuation.quadratic);
  39. } else if (l->type == KLIGHT_TYPE_DIRECTIONAL) {
  40. sd->colour = vec4_from_vec3(l->colour, 0);
  41. sd->direction = vec4_from_vec3(l->direction, 0);
  42. }
  43. // NOTE: Other/KLIGHT_TYPE_UNDEFINED are skipped.
  44. }
  45. }
  46. klight point_light_create(light_system_state* state, vec3 position, colour3 colour, f32 constant_f, f32 linear, f32 quadratic) {
  47. klight light = create_new_handle(state);
  48. KASSERT_DEBUG(light != KLIGHT_INVALID);
  49. klight_data* l = &state->lights[light];
  50. l->type = KLIGHT_TYPE_POINT;
  51. l->colour = colour;
  52. l->position = position;
  53. l->attenuation.constant_f = constant_f;
  54. l->attenuation.linear = linear;
  55. l->attenuation.quadratic = quadratic;
  56. return light;
  57. }
  58. klight directional_light_create(light_system_state* state, vec3 direction, colour3 colour) {
  59. klight light = create_new_handle(state);
  60. KASSERT_DEBUG(light != KLIGHT_INVALID);
  61. klight_data* l = &state->lights[light];
  62. l->type = KLIGHT_TYPE_DIRECTIONAL;
  63. l->colour = colour;
  64. l->direction = direction;
  65. return light;
  66. }
  67. vec3 directional_light_get_direction(light_system_state* state, klight light) {
  68. KASSERT_DEBUG(light != KLIGHT_INVALID);
  69. klight_data* l = &state->lights[light];
  70. KASSERT_DEBUG(l->type == KLIGHT_TYPE_DIRECTIONAL);
  71. return l->direction;
  72. }
  73. colour3 directional_light_get_colour(light_system_state* state, klight light) {
  74. KASSERT_DEBUG(light != KLIGHT_INVALID);
  75. klight_data* l = &state->lights[light];
  76. KASSERT_DEBUG(l->type == KLIGHT_TYPE_DIRECTIONAL);
  77. return l->colour;
  78. }
  79. vec3 point_light_get_position(light_system_state* state, klight light) {
  80. KASSERT_DEBUG(light != KLIGHT_INVALID);
  81. klight_data* l = &state->lights[light];
  82. KASSERT_DEBUG(l->type == KLIGHT_TYPE_POINT);
  83. return l->position;
  84. }
  85. colour3 point_light_get_colour(light_system_state* state, klight light) {
  86. KASSERT_DEBUG(light != KLIGHT_INVALID);
  87. klight_data* l = &state->lights[light];
  88. KASSERT_DEBUG(l->type == KLIGHT_TYPE_POINT || l->type == KLIGHT_TYPE_DIRECTIONAL);
  89. return l->colour;
  90. }
  91. void directional_light_set_direction(light_system_state* state, klight light, vec3 direction) {
  92. KASSERT_DEBUG(light != KLIGHT_INVALID);
  93. klight_data* l = &state->lights[light];
  94. KASSERT_DEBUG(l->type == KLIGHT_TYPE_DIRECTIONAL);
  95. l->direction = direction;
  96. }
  97. void point_light_set_position(light_system_state* state, klight light, vec3 position) {
  98. KASSERT_DEBUG(light != KLIGHT_INVALID);
  99. klight_data* l = &state->lights[light];
  100. KASSERT_DEBUG(l->type == KLIGHT_TYPE_POINT);
  101. l->position = position;
  102. }
  103. void point_light_set_colour(light_system_state* state, klight light, colour3 colour) {
  104. KASSERT_DEBUG(light != KLIGHT_INVALID);
  105. klight_data* l = &state->lights[light];
  106. KASSERT_DEBUG(l->type == KLIGHT_TYPE_POINT || l->type == KLIGHT_TYPE_DIRECTIONAL);
  107. l->colour = colour;
  108. }
  109. f32 point_light_radius_get(light_system_state* state, klight light) {
  110. KASSERT_DEBUG(light != KLIGHT_INVALID);
  111. klight_data* l = &state->lights[light];
  112. KASSERT_DEBUG(l->type == KLIGHT_TYPE_POINT);
  113. klight_attenuation* att = &l->attenuation;
  114. f32 intensity = 1.0f;
  115. f32 threshold = 0.1f;
  116. if (att->quadratic > K_FLOAT_EPSILON) {
  117. float disc = att->linear * att->linear - 4.0f * att->quadratic * (att->constant_f - intensity / threshold);
  118. if (disc <= 0.0f) {
  119. return 0.0f;
  120. }
  121. return KMAX(0.0f, (-att->linear + ksqrt(disc)) / (2.0f * att->quadratic));
  122. } else if (att->linear > 1e-8f) {
  123. return KMAX(0.0f, (intensity / threshold - att->constant_f) / att->linear);
  124. } else {
  125. return K_INFINITY;
  126. }
  127. }
  128. void light_destroy(light_system_state* state, klight light) {
  129. kzero_memory(&state->lights[light], sizeof(klight_data));
  130. }
  131. klight_data light_get_data(light_system_state* state, klight light) {
  132. return state->lights[light];
  133. }
  134. static klight create_new_handle(light_system_state* state) {
  135. for (u32 i = 0; i < MAX_GLOBAL_SSBO_LIGHTS; ++i) {
  136. if (state->lights[i].type == KLIGHT_TYPE_UNDEFINED) {
  137. return i;
  138. }
  139. }
  140. return KLIGHT_INVALID;
  141. }