light_cluster_builder.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*************************************************************************/
  2. /* light_cluster_builder.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "light_cluster_builder.h"
  31. void LightClusterBuilder::begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection) {
  32. view_xform = p_view_transform;
  33. projection = p_cam_projection;
  34. z_near = -projection.get_z_near();
  35. z_far = -projection.get_z_far();
  36. //reset counts
  37. light_count = 0;
  38. refprobe_count = 0;
  39. item_count = 0;
  40. sort_id_count = 0;
  41. }
  42. void LightClusterBuilder::bake_cluster() {
  43. float slice_depth = (z_near - z_far) / depth;
  44. PoolVector<uint8_t>::Write cluster_dataw = cluster_data.write();
  45. Cell *cluster_data_ptr = (Cell *)cluster_dataw.ptr();
  46. //clear the cluster
  47. zeromem(cluster_data_ptr, (width * height * depth * sizeof(Cell)));
  48. /* Step 1, create cell positions and count them */
  49. for (uint32_t i = 0; i < item_count; i++) {
  50. const Item &item = items[i];
  51. int from_slice = Math::floor((z_near - (item.aabb.position.z + item.aabb.size.z)) / slice_depth);
  52. int to_slice = Math::floor((z_near - item.aabb.position.z) / slice_depth);
  53. if (from_slice >= (int)depth || to_slice < 0) {
  54. continue; //sorry no go
  55. }
  56. from_slice = MAX(0, from_slice);
  57. to_slice = MIN((int)depth - 1, to_slice);
  58. for (int j = from_slice; j <= to_slice; j++) {
  59. Vector3 min = item.aabb.position;
  60. Vector3 max = item.aabb.position + item.aabb.size;
  61. float limit_near = MIN((z_near - slice_depth * j), max.z);
  62. float limit_far = MAX((z_near - slice_depth * (j + 1)), min.z);
  63. max.z = limit_near;
  64. min.z = limit_near;
  65. Vector3 proj_min = projection.xform(min);
  66. Vector3 proj_max = projection.xform(max);
  67. int near_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width));
  68. int near_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height));
  69. int near_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width));
  70. int near_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height));
  71. max.z = limit_far;
  72. min.z = limit_far;
  73. proj_min = projection.xform(min);
  74. proj_max = projection.xform(max);
  75. int far_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width));
  76. int far_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height));
  77. int far_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width));
  78. int far_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height));
  79. //print_line(itos(j) + " near - " + Vector2i(near_from_x, near_from_y) + " -> " + Vector2i(near_to_x, near_to_y));
  80. //print_line(itos(j) + " far - " + Vector2i(far_from_x, far_from_y) + " -> " + Vector2i(far_to_x, far_to_y));
  81. int from_x = MIN(near_from_x, far_from_x);
  82. int from_y = MIN(near_from_y, far_from_y);
  83. int to_x = MAX(near_to_x, far_to_x);
  84. int to_y = MAX(near_to_y, far_to_y);
  85. if (from_x >= (int)width || to_x < 0 || from_y >= (int)height || to_y < 0) {
  86. continue;
  87. }
  88. int sx = MAX(0, from_x);
  89. int sy = MAX(0, from_y);
  90. int dx = MIN((int)width - 1, to_x);
  91. int dy = MIN((int)height - 1, to_y);
  92. //print_line(itos(j) + " - " + Vector2i(sx, sy) + " -> " + Vector2i(dx, dy));
  93. for (int x = sx; x <= dx; x++) {
  94. for (int y = sy; y <= dy; y++) {
  95. uint32_t offset = j * (width * height) + y * width + x;
  96. if (unlikely(sort_id_count == sort_id_max)) {
  97. sort_id_max = nearest_power_of_2_templated(sort_id_max + 1);
  98. sort_ids = (SortID *)memrealloc(sort_ids, sizeof(SortID) * sort_id_max);
  99. if (ids.size()) {
  100. ids.resize(sort_id_max);
  101. RD::get_singleton()->free(items_buffer);
  102. items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * sort_id_max);
  103. }
  104. }
  105. sort_ids[sort_id_count].cell_index = offset;
  106. sort_ids[sort_id_count].item_index = item.index;
  107. sort_ids[sort_id_count].item_type = item.type;
  108. sort_id_count++;
  109. //for now, only count
  110. cluster_data_ptr[offset].item_pointers[item.type]++;
  111. //print_line("at offset " + itos(offset) + " value: " + itos(cluster_data_ptr[offset].item_pointers[item.type]));
  112. }
  113. }
  114. }
  115. }
  116. /* Step 2, Assign pointers (and reset counters) */
  117. uint32_t offset = 0;
  118. for (uint32_t i = 0; i < (width * height * depth); i++) {
  119. for (int j = 0; j < ITEM_TYPE_MAX; j++) {
  120. uint32_t count = cluster_data_ptr[i].item_pointers[j]; //save count
  121. cluster_data_ptr[i].item_pointers[j] = offset; //replace count by pointer
  122. offset += count; //increase offset by count;
  123. }
  124. }
  125. //print_line("offset: " + itos(offset));
  126. /* Step 3, Place item lists */
  127. PoolVector<uint32_t>::Write idsw = ids.write();
  128. uint32_t *ids_ptr = idsw.ptr();
  129. for (uint32_t i = 0; i < sort_id_count; i++) {
  130. const SortID &id = sort_ids[i];
  131. Cell &cell = cluster_data_ptr[id.cell_index];
  132. uint32_t pointer = cell.item_pointers[id.item_type] & POINTER_MASK;
  133. uint32_t counter = cell.item_pointers[id.item_type] >> COUNTER_SHIFT;
  134. ids_ptr[pointer + counter] = id.item_index;
  135. cell.item_pointers[id.item_type] = pointer | ((counter + 1) << COUNTER_SHIFT);
  136. }
  137. cluster_dataw = PoolVector<uint8_t>::Write();
  138. RD::get_singleton()->texture_update(cluster_texture, 0, cluster_data, true);
  139. RD::get_singleton()->buffer_update(items_buffer, 0, offset * sizeof(uint32_t), ids_ptr, true);
  140. idsw = PoolVector<uint32_t>::Write();
  141. }
  142. void LightClusterBuilder::setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth) {
  143. if (width == p_width && height == p_height && depth == p_depth) {
  144. return;
  145. }
  146. if (cluster_texture.is_valid()) {
  147. RD::get_singleton()->free(cluster_texture);
  148. }
  149. width = p_width;
  150. height = p_height;
  151. depth = p_depth;
  152. cluster_data.resize(width * height * depth * sizeof(Cell));
  153. {
  154. RD::TextureFormat tf;
  155. tf.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
  156. tf.type = RD::TEXTURE_TYPE_3D;
  157. tf.width = width;
  158. tf.height = height;
  159. tf.depth = depth;
  160. tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
  161. cluster_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
  162. }
  163. }
  164. RID LightClusterBuilder::get_cluster_texture() const {
  165. return cluster_texture;
  166. }
  167. RID LightClusterBuilder::get_cluster_indices_buffer() const {
  168. return items_buffer;
  169. }
  170. LightClusterBuilder::LightClusterBuilder() {
  171. //initialize accumulators to something
  172. lights = (LightData *)memalloc(sizeof(LightData) * 1024);
  173. light_max = 1024;
  174. refprobes = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024);
  175. refprobe_max = 1024;
  176. decals = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024);
  177. decal_max = 1024;
  178. items = (Item *)memalloc(sizeof(Item) * 1024);
  179. item_max = 1024;
  180. sort_ids = (SortID *)memalloc(sizeof(SortID) * 1024);
  181. ids.resize(2014);
  182. items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 1024);
  183. item_max = 1024;
  184. }
  185. LightClusterBuilder::~LightClusterBuilder() {
  186. if (cluster_data.size()) {
  187. RD::get_singleton()->free(cluster_texture);
  188. }
  189. if (lights) {
  190. memfree(lights);
  191. }
  192. if (refprobes) {
  193. memfree(refprobes);
  194. }
  195. if (decals) {
  196. memfree(decals);
  197. }
  198. if (items) {
  199. memfree(items);
  200. }
  201. if (sort_ids) {
  202. memfree(sort_ids);
  203. RD::get_singleton()->free(items_buffer);
  204. }
  205. }