💿🐜 Antkeeper source code https://antkeeper.com
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.

302 lines
11 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "render/passes/shadow-map-pass.hpp"
  20. #include "resources/resource-manager.hpp"
  21. #include "gl/rasterizer.hpp"
  22. #include "gl/framebuffer.hpp"
  23. #include "gl/shader-program.hpp"
  24. #include "gl/shader-input.hpp"
  25. #include "gl/drawing-mode.hpp"
  26. #include "render/context.hpp"
  27. #include "render/material.hpp"
  28. #include "render/material-flags.hpp"
  29. #include "scene/camera.hpp"
  30. #include "scene/light.hpp"
  31. #include "geom/view-frustum.hpp"
  32. #include "geom/aabb.hpp"
  33. #include "config.hpp"
  34. #include "math/vector.hpp"
  35. #include "math/matrix.hpp"
  36. #include "math/quaternion.hpp"
  37. #include "math/projection.hpp"
  38. #include <cmath>
  39. #include <glad/glad.h>
  40. namespace render {
  41. static bool operation_compare(const render::operation& a, const render::operation& b);
  42. void shadow_map_pass::distribute_frustum_splits(float* split_distances, std::size_t split_count, float split_scheme, float near, float far)
  43. {
  44. // Calculate split distances
  45. for (std::size_t i = 0; i < split_count; ++i)
  46. {
  47. float part = static_cast<float>(i + 1) / static_cast<float>(split_count + 1);
  48. // Calculate uniform split distance
  49. float uniform_split_distance = near + (far - near) * part;
  50. // Calculate logarithmic split distance
  51. float log_split_distance = near * std::pow(far / near, part);
  52. // Interpolate between uniform and logarithmic split distances
  53. split_distances[i] = log_split_distance * split_scheme + uniform_split_distance * (1.0f - split_scheme);
  54. }
  55. }
  56. shadow_map_pass::shadow_map_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffer, resource_manager* resource_manager):
  57. pass(rasterizer, framebuffer),
  58. split_scheme_weight(0.5f),
  59. light(nullptr)
  60. {
  61. // Load skinned shader program
  62. unskinned_shader_program = resource_manager->load<gl::shader_program>("depth-unskinned.glsl");
  63. unskinned_model_view_projection_input = unskinned_shader_program->get_input("model_view_projection");
  64. // Load unskinned shader program
  65. skinned_shader_program = resource_manager->load<gl::shader_program>("depth-skinned.glsl");
  66. skinned_model_view_projection_input = skinned_shader_program->get_input("model_view_projection");
  67. // Calculate bias-tile matrices
  68. float4x4 bias_matrix = math::translate(math::matrix4<float>::identity(), float3{0.5f, 0.5f, 0.5f}) * math::scale(math::matrix4<float>::identity(), float3{0.5f, 0.5f, 0.5f});
  69. float4x4 tile_scale = math::scale(math::matrix4<float>::identity(), float3{0.5f, 0.5f, 1.0f});
  70. for (int i = 0; i < 4; ++i)
  71. {
  72. float x = static_cast<float>(i % 2) * 0.5f;
  73. float y = static_cast<float>(i / 2) * 0.5f;
  74. float4x4 tile_matrix = math::translate(math::matrix4<float>::identity(), float3{x, y, 0.0f}) * tile_scale;
  75. bias_tile_matrices[i] = tile_matrix * bias_matrix;
  76. }
  77. }
  78. shadow_map_pass::~shadow_map_pass()
  79. {}
  80. void shadow_map_pass::render(const render::context& ctx, render::queue& queue) const
  81. {
  82. // Abort if no directional light was set
  83. if (!light)
  84. {
  85. return;
  86. }
  87. rasterizer->use_framebuffer(*framebuffer);
  88. // Disable blending
  89. glDisable(GL_BLEND);
  90. // Enable depth testing
  91. glEnable(GL_DEPTH_TEST);
  92. glDepthFunc(GL_LESS);
  93. glDepthMask(GL_TRUE);
  94. // Disable face culling
  95. glEnable(GL_CULL_FACE);
  96. glCullFace(GL_FRONT);
  97. // For half-z buffer
  98. //glDepthRange(-1.0f, 1.0f);
  99. // Get camera
  100. const scene::camera& camera = *ctx.camera;
  101. // Calculate distances to the depth clipping planes of each frustum split
  102. float clip_near = camera.get_clip_near_tween().interpolate(ctx.alpha);
  103. float clip_far = camera.get_clip_far_tween().interpolate(ctx.alpha);
  104. split_distances[0] = clip_near;
  105. split_distances[4] = clip_far;
  106. distribute_frustum_splits(&split_distances[1], 3, split_scheme_weight, clip_near, clip_far);
  107. // Calculate viewports for each shadow map
  108. const int shadow_map_resolution = std::get<0>(framebuffer->get_dimensions()) / 2;
  109. float4 shadow_map_viewports[4];
  110. for (int i = 0; i < 4; ++i)
  111. {
  112. int x = i % 2;
  113. int y = i / 2;
  114. float4& viewport = shadow_map_viewports[i];
  115. viewport[0] = static_cast<float>(x * shadow_map_resolution);
  116. viewport[1] = static_cast<float>(y * shadow_map_resolution);
  117. viewport[2] = static_cast<float>(shadow_map_resolution);
  118. viewport[3] = static_cast<float>(shadow_map_resolution);
  119. }
  120. // Calculate a view-projection matrix from the directional light's transform
  121. math::transform<float> light_transform = light->get_transform_tween().interpolate(ctx.alpha);
  122. float3 forward = light_transform.rotation * config::global_forward;
  123. float3 up = light_transform.rotation * config::global_up;
  124. float4x4 light_view = math::look_at(light_transform.translation, light_transform.translation + forward, up);
  125. float4x4 light_projection = math::ortho_half_z(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
  126. float4x4 light_view_projection = light_projection * light_view;
  127. // Get the camera's view matrix
  128. float4x4 camera_view = camera.get_view_tween().interpolate(ctx.alpha);
  129. float4x4 crop_matrix;
  130. float4x4 cropped_view_projection;
  131. float4x4 model_view_projection;
  132. // Sort render queue
  133. queue.sort(operation_compare);
  134. gl::shader_program* active_shader_program = nullptr;
  135. for (int i = 0; i < 4; ++i)
  136. {
  137. // Set viewport for this shadow map
  138. const float4& viewport = shadow_map_viewports[i];
  139. rasterizer->set_viewport(viewport[0], viewport[1], viewport[2], viewport[3]);
  140. // Calculate projection matrix for view camera subfrustum
  141. const float subfrustum_near = split_distances[i];
  142. const float subfrustum_far = split_distances[i + 1];
  143. float4x4 subfrustum_projection = math::perspective_half_z(camera.get_fov(), camera.get_aspect_ratio(), subfrustum_near, subfrustum_far);
  144. // Calculate view camera subfrustum
  145. geom::view_frustum<float> subfrustum(subfrustum_projection * camera_view);
  146. // Create AABB containing the view camera subfrustum corners
  147. const std::array<float3, 8>& subfrustum_corners = subfrustum.get_corners();
  148. geom::aabb<float> subfrustum_aabb = {subfrustum_corners[0], subfrustum_corners[0]};
  149. for (int j = 1; j < 8; ++j)
  150. {
  151. for (int k = 0; k < 3; ++k)
  152. {
  153. subfrustum_aabb.min_point[k] = std::min<float>(subfrustum_aabb.min_point[k], subfrustum_corners[j][k]);
  154. subfrustum_aabb.max_point[k] = std::max<float>(subfrustum_aabb.max_point[k], subfrustum_corners[j][k]);
  155. }
  156. }
  157. // Transform subfrustum AABB into the light clip space
  158. geom::aabb<float> cropping_bounds = geom::aabb<float>::transform(subfrustum_aabb, light_view_projection);
  159. // Calculate scale
  160. float3 scale;
  161. scale.x() = 2.0f / (cropping_bounds.max_point.x() - cropping_bounds.min_point.x());
  162. scale.y() = 2.0f / (cropping_bounds.max_point.y() - cropping_bounds.min_point.y());
  163. scale.z() = 1.0f / (cropping_bounds.max_point.z() - cropping_bounds.min_point.z());
  164. //scale.z() = 2.0f / (cropping_bounds.max_point.z() - cropping_bounds.min_point.z());
  165. // Quantize scale
  166. float scale_quantizer = 64.0f;
  167. scale.x() = 1.0f / std::ceil(1.0f / scale.x() * scale_quantizer) * scale_quantizer;
  168. scale.y() = 1.0f / std::ceil(1.0f / scale.y() * scale_quantizer) * scale_quantizer;
  169. // Calculate offset
  170. float3 offset;
  171. offset.x() = (cropping_bounds.max_point.x() + cropping_bounds.min_point.x()) * scale.x() * -0.5f;
  172. offset.y() = (cropping_bounds.max_point.y() + cropping_bounds.min_point.y()) * scale.y() * -0.5f;
  173. offset.z() = -cropping_bounds.min_point.z() * scale.z();
  174. //offset.z() = (cropping_bounds.max_point.z() + cropping_bounds.min_point.z()) * scale.z() * -0.5f;
  175. // Quantize offset
  176. float half_shadow_map_resolution = static_cast<float>(shadow_map_resolution) * 0.5f;
  177. offset.x() = std::ceil(offset.x() * half_shadow_map_resolution) / half_shadow_map_resolution;
  178. offset.y() = std::ceil(offset.y() * half_shadow_map_resolution) / half_shadow_map_resolution;
  179. // Crop the light view-projection matrix
  180. crop_matrix = math::translate(math::matrix4<float>::identity(), offset) * math::scale(math::matrix4<float>::identity(), scale);
  181. cropped_view_projection = crop_matrix * light_view_projection;
  182. // Calculate shadow matrix
  183. shadow_matrices[i] = bias_tile_matrices[i] * cropped_view_projection;
  184. for (const render::operation& operation: queue)
  185. {
  186. // Skip materials which don't cast shadows
  187. const render::material* material = operation.material;
  188. if (material && (material->get_flags() & MATERIAL_FLAG_NOT_SHADOW_CASTER))
  189. {
  190. continue;
  191. }
  192. // Switch shader programs if necessary
  193. gl::shader_program* shader_program = (operation.bone_count) ? skinned_shader_program : unskinned_shader_program;
  194. if (active_shader_program != shader_program)
  195. {
  196. active_shader_program = shader_program;
  197. rasterizer->use_program(*active_shader_program);
  198. }
  199. // Calculate model-view-projection matrix
  200. model_view_projection = cropped_view_projection * operation.transform;
  201. // Upload operation-dependent parameters to shader program
  202. if (active_shader_program == unskinned_shader_program)
  203. {
  204. unskinned_model_view_projection_input->upload(model_view_projection);
  205. }
  206. else if (active_shader_program == skinned_shader_program)
  207. {
  208. skinned_model_view_projection_input->upload(model_view_projection);
  209. }
  210. // Draw geometry
  211. rasterizer->draw_arrays(*operation.vertex_array, operation.drawing_mode, operation.start_index, operation.index_count);
  212. }
  213. }
  214. }
  215. void shadow_map_pass::set_split_scheme_weight(float weight)
  216. {
  217. split_scheme_weight = weight;
  218. }
  219. void shadow_map_pass::set_light(const scene::directional_light* light)
  220. {
  221. this->light = light;
  222. }
  223. bool operation_compare(const render::operation& a, const render::operation& b)
  224. {
  225. // Determine transparency
  226. bool skinned_a = (a.bone_count);
  227. bool skinned_b = (b.bone_count);
  228. if (skinned_a)
  229. {
  230. if (skinned_b)
  231. {
  232. // A and B are both skinned, sort by VAO
  233. return (a.vertex_array < b.vertex_array);
  234. }
  235. else
  236. {
  237. // A is skinned, B is unskinned. Render B first
  238. return false;
  239. }
  240. }
  241. else
  242. {
  243. if (skinned_b)
  244. {
  245. // A is unskinned, B is skinned. Render A first
  246. return true;
  247. }
  248. else
  249. {
  250. // A and B are both unskinned, sort by VAO
  251. return (a.vertex_array < b.vertex_array);
  252. }
  253. }
  254. }
  255. } // namespace render