💿🐜 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.

724 lines
25 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 "renderer/passes/material-pass.hpp"
  20. #include "configuration.hpp"
  21. #include "resources/resource-manager.hpp"
  22. #include "gl/rasterizer.hpp"
  23. #include "gl/framebuffer.hpp"
  24. #include "gl/shader.hpp"
  25. #include "gl/shader-type.hpp"
  26. #include "gl/shader-program.hpp"
  27. #include "gl/shader-input.hpp"
  28. #include "gl/vertex-buffer.hpp"
  29. #include "gl/vertex-array.hpp"
  30. #include "gl/vertex-attribute-type.hpp"
  31. #include "gl/drawing-mode.hpp"
  32. #include "gl/texture-2d.hpp"
  33. #include "gl/texture-wrapping.hpp"
  34. #include "gl/texture-filter.hpp"
  35. #include "renderer/vertex-attributes.hpp"
  36. #include "renderer/material-flags.hpp"
  37. #include "renderer/model.hpp"
  38. #include "renderer/render-context.hpp"
  39. #include "scene/camera.hpp"
  40. #include "scene/collection.hpp"
  41. #include "scene/ambient-light.hpp"
  42. #include "scene/directional-light.hpp"
  43. #include "scene/point-light.hpp"
  44. #include "scene/spot-light.hpp"
  45. #include "configuration.hpp"
  46. #include "math/math.hpp"
  47. #include <cmath>
  48. #include <glad/glad.h>
  49. #include "shadow-map-pass.hpp"
  50. static bool operation_compare(const render_operation& a, const render_operation& b);
  51. material_pass::material_pass(gl::rasterizer* rasterizer, const gl::framebuffer* framebuffer, resource_manager* resource_manager):
  52. render_pass(rasterizer, framebuffer),
  53. fallback_material(nullptr),
  54. time_tween(nullptr),
  55. mouse_position({0.0f, 0.0f}),
  56. focal_point_tween(nullptr),
  57. shadow_map_pass(nullptr),
  58. shadow_map(nullptr)
  59. {
  60. max_ambient_light_count = MATERIAL_PASS_MAX_AMBIENT_LIGHT_COUNT;
  61. max_point_light_count = MATERIAL_PASS_MAX_POINT_LIGHT_COUNT;
  62. max_directional_light_count = MATERIAL_PASS_MAX_DIRECTIONAL_LIGHT_COUNT;
  63. max_spot_light_count = MATERIAL_PASS_MAX_SPOTLIGHT_COUNT;
  64. ambient_light_colors = new float3[max_ambient_light_count];
  65. point_light_colors = new float3[max_point_light_count];
  66. point_light_positions = new float3[max_point_light_count];
  67. point_light_attenuations = new float3[max_point_light_count];
  68. directional_light_colors = new float3[max_directional_light_count];
  69. directional_light_directions = new float3[max_directional_light_count];
  70. directional_light_textures = new const gl::texture_2d*[max_directional_light_count];
  71. directional_light_texture_matrices = new float4x4[max_directional_light_count];
  72. directional_light_texture_opacities = new float[max_directional_light_count];
  73. spot_light_colors = new float3[max_spot_light_count];
  74. spot_light_positions = new float3[max_spot_light_count];
  75. spot_light_directions = new float3[max_spot_light_count];
  76. spot_light_attenuations = new float3[max_spot_light_count];
  77. spot_light_cutoffs = new float2[max_spot_light_count];
  78. }
  79. material_pass::~material_pass()
  80. {
  81. delete[] ambient_light_colors;
  82. delete[] point_light_colors;
  83. delete[] point_light_positions;
  84. delete[] point_light_attenuations;
  85. delete[] directional_light_colors;
  86. delete[] directional_light_directions;
  87. delete[] directional_light_textures;
  88. delete[] directional_light_texture_matrices;
  89. delete[] directional_light_texture_opacities;
  90. delete[] spot_light_colors;
  91. delete[] spot_light_positions;
  92. delete[] spot_light_directions;
  93. delete[] spot_light_attenuations;
  94. delete[] spot_light_cutoffs;
  95. }
  96. void material_pass::render(render_context* context) const
  97. {
  98. rasterizer->use_framebuffer(*framebuffer);
  99. glDisable(GL_BLEND);
  100. glEnable(GL_DEPTH_TEST);
  101. glDepthMask(GL_TRUE);
  102. glDepthFunc(GL_GREATER);
  103. glEnable(GL_CULL_FACE);
  104. glCullFace(GL_BACK);
  105. glDisable(GL_STENCIL_TEST);
  106. glStencilMask(0x00);
  107. // For half-z buffer
  108. glDepthRange(-1.0f, 1.0f);
  109. auto viewport = framebuffer->get_dimensions();
  110. rasterizer->set_viewport(0, 0, std::get<0>(viewport), std::get<1>(viewport));
  111. float2 resolution = {static_cast<float>(std::get<0>(viewport)), static_cast<float>(std::get<1>(viewport))};
  112. float time = time_tween->interpolate(context->alpha);
  113. const float3& camera_position = context->camera_transform.translation;
  114. float3 focal_point = (focal_point_tween) ? focal_point_tween->interpolate(context->alpha) : float3{0, 0, 0};
  115. float4x4 view = context->camera->get_view_tween().interpolate(context->alpha);
  116. float4x4 projection = context->camera->get_projection_tween().interpolate(context->alpha);
  117. float4x4 view_projection = projection * view;
  118. float4x4 model_view_projection;
  119. float4x4 model;
  120. float4x4 model_view;
  121. float3x3 normal_model;
  122. float3x3 normal_model_view;
  123. float2 clip_depth;
  124. clip_depth[0] = context->camera->get_clip_near_tween().interpolate(context->alpha);
  125. clip_depth[1] = context->camera->get_clip_far_tween().interpolate(context->alpha);
  126. float log_depth_coef = 2.0f / std::log2(clip_depth[1] + 1.0f);
  127. float camera_exposure = std::exp2(-6.5f);
  128. int active_material_flags = 0;
  129. const gl::shader_program* active_shader_program = nullptr;
  130. const ::material* active_material = nullptr;
  131. const parameter_set* parameters = nullptr;
  132. // Reset light counts
  133. ambient_light_count = 0;
  134. point_light_count = 0;
  135. directional_light_count = 0;
  136. spot_light_count = 0;
  137. // Collect lights
  138. const std::list<scene::object_base*>* lights = context->collection->get_objects(scene::light::object_type_id);
  139. for (const scene::object_base* object: *lights)
  140. {
  141. // Skip inactive lights
  142. if (!object->is_active())
  143. continue;
  144. const scene::light* light = static_cast<const scene::light*>(object);
  145. switch (light->get_light_type())
  146. {
  147. // Add ambient light
  148. case scene::light_type::ambient:
  149. {
  150. if (ambient_light_count < max_ambient_light_count)
  151. {
  152. // Pre-expose light
  153. ambient_light_colors[ambient_light_count] = light->get_scaled_color_tween().interpolate(context->alpha) * camera_exposure;
  154. ++ambient_light_count;
  155. }
  156. break;
  157. }
  158. // Add point light
  159. case scene::light_type::point:
  160. {
  161. if (point_light_count < max_point_light_count)
  162. {
  163. // Pre-expose light
  164. point_light_colors[point_light_count] = light->get_scaled_color_tween().interpolate(context->alpha) * camera_exposure;
  165. float3 position = light->get_transform_tween().interpolate(context->alpha).translation;
  166. point_light_positions[point_light_count] = position;
  167. point_light_attenuations[point_light_count] = static_cast<const scene::point_light*>(light)->get_attenuation_tween().interpolate(context->alpha);
  168. ++point_light_count;
  169. }
  170. break;
  171. }
  172. // Add directional light
  173. case scene::light_type::directional:
  174. {
  175. if (directional_light_count < max_directional_light_count)
  176. {
  177. const scene::directional_light* directional_light = static_cast<const scene::directional_light*>(light);
  178. // Pre-expose light
  179. directional_light_colors[directional_light_count] = light->get_scaled_color_tween().interpolate(context->alpha) * camera_exposure;
  180. float3 direction = static_cast<const scene::directional_light*>(light)->get_direction_tween().interpolate(context->alpha);
  181. directional_light_directions[directional_light_count] = direction;
  182. if (directional_light->get_light_texture())
  183. {
  184. directional_light_textures[directional_light_count] = directional_light->get_light_texture();
  185. directional_light_texture_opacities[directional_light_count] = directional_light->get_light_texture_opacity_tween().interpolate(context->alpha);
  186. math::transform<float> light_transform = light->get_transform_tween().interpolate(context->alpha);
  187. float3 forward = light_transform.rotation * global_forward;
  188. float3 up = light_transform.rotation * global_up;
  189. float4x4 light_view = math::look_at(light_transform.translation, light_transform.translation + forward, up);
  190. float2 scale = directional_light->get_light_texture_scale_tween().interpolate(context->alpha);
  191. float4x4 light_projection = math::ortho(-scale.x, scale.x, -scale.y, scale.y, -1.0f, 1.0f);
  192. directional_light_texture_matrices[directional_light_count] = light_projection * light_view;
  193. }
  194. else
  195. {
  196. directional_light_textures[directional_light_count] = nullptr;
  197. directional_light_texture_opacities[directional_light_count] = 0.0f;
  198. }
  199. ++directional_light_count;
  200. }
  201. break;
  202. }
  203. // Add spot_light
  204. case scene::light_type::spot:
  205. {
  206. if (spot_light_count < max_spot_light_count)
  207. {
  208. const scene::spot_light* spot_light = static_cast<const scene::spot_light*>(light);
  209. // Pre-expose light
  210. spot_light_colors[spot_light_count] = light->get_scaled_color_tween().interpolate(context->alpha) * camera_exposure;
  211. float3 position = light->get_transform_tween().interpolate(context->alpha).translation;
  212. spot_light_positions[spot_light_count] = position;
  213. float3 direction = spot_light->get_direction_tween().interpolate(context->alpha);
  214. spot_light_directions[spot_light_count] = direction;
  215. spot_light_attenuations[spot_light_count] = spot_light->get_attenuation_tween().interpolate(context->alpha);
  216. spot_light_cutoffs[spot_light_count] = spot_light->get_cosine_cutoff_tween().interpolate(context->alpha);
  217. ++spot_light_count;
  218. }
  219. break;
  220. }
  221. default:
  222. break;
  223. }
  224. }
  225. float4x4 shadow_matrices_directional[4];
  226. float4 shadow_splits_directional;
  227. if (shadow_map_pass)
  228. {
  229. for (int i = 0; i < 4; ++i)
  230. shadow_matrices_directional[i] = shadow_map_pass->get_shadow_matrices()[i];
  231. // Calculate shadow map split distances
  232. for (int i = 0; i < 4; ++i)
  233. shadow_splits_directional[i] = shadow_map_pass->get_split_distances()[i + 1];
  234. }
  235. // Sort render operations
  236. context->operations.sort(operation_compare);
  237. for (const render_operation& operation: context->operations)
  238. {
  239. // Get operation material
  240. const ::material* material = operation.material;
  241. if (!material)
  242. {
  243. if (fallback_material)
  244. {
  245. // No material specified, use fallback material
  246. material = fallback_material;
  247. }
  248. else
  249. {
  250. // No material specified and no fallback material, skip operation
  251. continue;
  252. }
  253. }
  254. // Switch materials if necessary
  255. if (active_material != material)
  256. {
  257. active_material = material;
  258. // Change rasterizer state according to material flags
  259. std::uint32_t material_flags = active_material->get_flags();
  260. if (active_material_flags != material_flags)
  261. {
  262. if ((material_flags & MATERIAL_FLAG_TRANSLUCENT) != (active_material_flags & MATERIAL_FLAG_TRANSLUCENT))
  263. {
  264. if (material_flags & MATERIAL_FLAG_TRANSLUCENT)
  265. {
  266. glEnable(GL_BLEND);
  267. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  268. }
  269. else
  270. {
  271. glDisable(GL_BLEND);
  272. }
  273. }
  274. if ((material_flags & MATERIAL_FLAG_BACK_FACES) != (active_material_flags & MATERIAL_FLAG_BACK_FACES))
  275. {
  276. if (material_flags & MATERIAL_FLAG_BACK_FACES)
  277. {
  278. glEnable(GL_CULL_FACE);
  279. glCullFace(GL_FRONT);
  280. }
  281. else
  282. {
  283. glEnable(GL_CULL_FACE);
  284. glCullFace(GL_BACK);
  285. }
  286. }
  287. else if ((material_flags & MATERIAL_FLAG_FRONT_AND_BACK_FACES) != (active_material_flags & MATERIAL_FLAG_FRONT_AND_BACK_FACES))
  288. {
  289. if (material_flags & MATERIAL_FLAG_FRONT_AND_BACK_FACES)
  290. {
  291. glDisable(GL_CULL_FACE);
  292. }
  293. else
  294. {
  295. glEnable(GL_CULL_FACE);
  296. glCullFace(GL_BACK);
  297. }
  298. }
  299. if ((material_flags & MATERIAL_FLAG_X_RAY) != (active_material_flags & MATERIAL_FLAG_X_RAY))
  300. {
  301. if (material_flags & MATERIAL_FLAG_X_RAY)
  302. {
  303. glDisable(GL_DEPTH_TEST);
  304. }
  305. else
  306. {
  307. glEnable(GL_DEPTH_TEST);
  308. }
  309. }
  310. if ((material_flags & MATERIAL_FLAG_DECAL_SURFACE) != (active_material_flags & MATERIAL_FLAG_DECAL_SURFACE))
  311. {
  312. if (material_flags & MATERIAL_FLAG_DECAL_SURFACE)
  313. {
  314. glEnable(GL_STENCIL_TEST);
  315. glStencilFunc(GL_ALWAYS, 1, ~0);
  316. glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  317. glStencilMask(~0);
  318. }
  319. else
  320. {
  321. glDisable(GL_STENCIL_TEST);
  322. glStencilMask(0);
  323. }
  324. }
  325. if ((material_flags & MATERIAL_FLAG_DECAL) != (active_material_flags & MATERIAL_FLAG_DECAL))
  326. {
  327. if (material_flags & MATERIAL_FLAG_DECAL)
  328. {
  329. glEnable(GL_DEPTH_TEST);
  330. glDepthFunc(GL_GEQUAL);
  331. glDepthMask(GL_FALSE);
  332. glEnable(GL_STENCIL_TEST);
  333. glStencilFunc(GL_EQUAL, 1, ~0);
  334. //glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
  335. //glStencilMask(~0);
  336. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  337. glStencilMask(0);
  338. }
  339. else
  340. {
  341. glEnable(GL_DEPTH_TEST);
  342. glDepthFunc(GL_GREATER);
  343. glDepthMask(GL_TRUE);
  344. glDisable(GL_STENCIL_TEST);
  345. glStencilMask(0);
  346. }
  347. }
  348. /*
  349. if ((material_flags & MATERIAL_FLAG_OUTLINE) != (active_material_flags & MATERIAL_FLAG_OUTLINE))
  350. {
  351. if (material_flags & MATERIAL_FLAG_OUTLINE)
  352. {
  353. glEnable(GL_STENCIL_TEST);
  354. glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  355. glStencilFunc(GL_ALWAYS, 2, 0xFF);
  356. glStencilMask(0xFF);
  357. }
  358. else
  359. {
  360. glDisable(GL_STENCIL_TEST);
  361. glStencilMask(0x00);
  362. }
  363. }
  364. */
  365. active_material_flags = material_flags;
  366. }
  367. // Switch shaders if necessary
  368. const gl::shader_program* shader_program = active_material->get_shader_program();
  369. if (active_shader_program != shader_program)
  370. {
  371. active_shader_program = shader_program;
  372. if (!active_shader_program)
  373. {
  374. continue;
  375. }
  376. // Change shader program
  377. rasterizer->use_program(*active_shader_program);
  378. // Get set of known shader input parameters
  379. if (auto it = parameter_sets.find(active_shader_program); it != parameter_sets.end())
  380. {
  381. parameters = it->second;
  382. }
  383. else
  384. {
  385. parameters = load_parameter_set(active_shader_program);
  386. }
  387. // Upload context-dependent shader parameters
  388. if (parameters->time)
  389. parameters->time->upload(time);
  390. if (parameters->mouse)
  391. parameters->mouse->upload(mouse_position);
  392. if (parameters->resolution)
  393. parameters->resolution->upload(resolution);
  394. if (parameters->camera_position)
  395. parameters->camera_position->upload(camera_position);
  396. if (parameters->camera_exposure)
  397. parameters->camera_exposure->upload(camera_exposure);
  398. if (parameters->view)
  399. parameters->view->upload(view);
  400. if (parameters->view_projection)
  401. parameters->view_projection->upload(view_projection);
  402. if (parameters->ambient_light_count)
  403. parameters->ambient_light_count->upload(ambient_light_count);
  404. if (parameters->ambient_light_colors)
  405. parameters->ambient_light_colors->upload(0, ambient_light_colors, ambient_light_count);
  406. if (parameters->point_light_count)
  407. parameters->point_light_count->upload(point_light_count);
  408. if (parameters->point_light_colors)
  409. parameters->point_light_colors->upload(0, point_light_colors, point_light_count);
  410. if (parameters->point_light_positions)
  411. parameters->point_light_positions->upload(0, point_light_positions, point_light_count);
  412. if (parameters->point_light_attenuations)
  413. parameters->point_light_attenuations->upload(0, point_light_attenuations, point_light_count);
  414. if (parameters->directional_light_count)
  415. parameters->directional_light_count->upload(directional_light_count);
  416. if (parameters->directional_light_colors)
  417. parameters->directional_light_colors->upload(0, directional_light_colors, directional_light_count);
  418. if (parameters->directional_light_directions)
  419. parameters->directional_light_directions->upload(0, directional_light_directions, directional_light_count);
  420. if (parameters->directional_light_textures)
  421. parameters->directional_light_textures->upload(0, directional_light_textures, directional_light_count);
  422. if (parameters->directional_light_texture_matrices)
  423. parameters->directional_light_texture_matrices->upload(0, directional_light_texture_matrices, directional_light_count);
  424. if (parameters->directional_light_texture_opacities)
  425. parameters->directional_light_texture_opacities->upload(0, directional_light_texture_opacities, directional_light_count);
  426. if (parameters->spot_light_count)
  427. parameters->spot_light_count->upload(spot_light_count);
  428. if (parameters->spot_light_colors)
  429. parameters->spot_light_colors->upload(0, spot_light_colors, spot_light_count);
  430. if (parameters->spot_light_positions)
  431. parameters->spot_light_positions->upload(0, spot_light_positions, spot_light_count);
  432. if (parameters->spot_light_directions)
  433. parameters->spot_light_directions->upload(0, spot_light_directions, spot_light_count);
  434. if (parameters->spot_light_attenuations)
  435. parameters->spot_light_attenuations->upload(0, spot_light_attenuations, spot_light_count);
  436. if (parameters->spot_light_cutoffs)
  437. parameters->spot_light_cutoffs->upload(0, spot_light_cutoffs, spot_light_count);
  438. if (parameters->focal_point)
  439. parameters->focal_point->upload(focal_point);
  440. if (parameters->shadow_map_directional && shadow_map)
  441. parameters->shadow_map_directional->upload(shadow_map);
  442. if (parameters->shadow_matrices_directional)
  443. parameters->shadow_matrices_directional->upload(0, shadow_matrices_directional, 4);
  444. if (parameters->shadow_splits_directional)
  445. parameters->shadow_splits_directional->upload(shadow_splits_directional);
  446. }
  447. // Upload material properties to shader
  448. active_material->upload(context->alpha);
  449. }
  450. // Calculate operation-dependent parameters
  451. model = operation.transform;
  452. model_view_projection = view_projection * model;
  453. model_view = view * model;
  454. normal_model = math::transpose(math::inverse(math::resize<3, 3>(model)));
  455. normal_model_view = math::transpose(math::inverse(math::resize<3, 3>(model_view)));
  456. // Upload operation-dependent parameters
  457. if (parameters->model)
  458. parameters->model->upload(model);
  459. if (parameters->model_view)
  460. parameters->model_view->upload(model_view);
  461. if (parameters->model_view_projection)
  462. parameters->model_view_projection->upload(model_view_projection);
  463. if (parameters->normal_model)
  464. parameters->normal_model->upload(normal_model);
  465. if (parameters->normal_model_view)
  466. parameters->normal_model_view->upload(normal_model_view);
  467. if (parameters->clip_depth)
  468. parameters->clip_depth->upload(clip_depth);
  469. if (parameters->log_depth_coef)
  470. parameters->log_depth_coef->upload(log_depth_coef);
  471. // Draw geometry
  472. if (operation.instance_count)
  473. rasterizer->draw_arrays_instanced(*operation.vertex_array, operation.drawing_mode, operation.start_index, operation.index_count, operation.instance_count);
  474. else
  475. rasterizer->draw_arrays(*operation.vertex_array, operation.drawing_mode, operation.start_index, operation.index_count);
  476. }
  477. }
  478. void material_pass::set_fallback_material(const material* fallback)
  479. {
  480. this->fallback_material = fallback;
  481. }
  482. void material_pass::set_time_tween(const tween<double>* time)
  483. {
  484. this->time_tween = time;
  485. }
  486. void material_pass::set_focal_point_tween(const tween<float3>* focal_point)
  487. {
  488. this->focal_point_tween = focal_point;
  489. }
  490. const material_pass::parameter_set* material_pass::load_parameter_set(const gl::shader_program* program) const
  491. {
  492. // Allocate a new parameter set
  493. parameter_set* parameters = new parameter_set();
  494. // Connect inputs
  495. parameters->time = program->get_input("time");
  496. parameters->mouse = program->get_input("mouse");
  497. parameters->resolution = program->get_input("resolution");
  498. parameters->camera_position = program->get_input("camera.position");
  499. parameters->camera_exposure = program->get_input("camera.exposure");
  500. parameters->model = program->get_input("model");
  501. parameters->view = program->get_input("view");
  502. parameters->projection = program->get_input("projection");
  503. parameters->model_view = program->get_input("model_view");
  504. parameters->view_projection = program->get_input("view_projection");
  505. parameters->model_view_projection = program->get_input("model_view_projection");
  506. parameters->normal_model = program->get_input("normal_model");
  507. parameters->normal_model_view = program->get_input("normal_model_view");
  508. parameters->clip_depth = program->get_input("clip_depth");
  509. parameters->log_depth_coef = program->get_input("log_depth_coef");
  510. parameters->ambient_light_count = program->get_input("ambient_light_count");
  511. parameters->ambient_light_colors = program->get_input("ambient_light_colors");
  512. parameters->point_light_count = program->get_input("point_light_count");
  513. parameters->point_light_colors = program->get_input("point_light_colors");
  514. parameters->point_light_positions = program->get_input("point_light_positions");
  515. parameters->point_light_attenuations = program->get_input("point_light_attenuations");
  516. parameters->directional_light_count = program->get_input("directional_light_count");
  517. parameters->directional_light_colors = program->get_input("directional_light_colors");
  518. parameters->directional_light_directions = program->get_input("directional_light_directions");
  519. parameters->directional_light_textures = program->get_input("directional_light_textures");
  520. parameters->directional_light_texture_matrices = program->get_input("directional_light_texture_matrices");
  521. parameters->directional_light_texture_opacities = program->get_input("directional_light_texture_opacities");
  522. parameters->spot_light_count = program->get_input("spot_light_count");
  523. parameters->spot_light_colors = program->get_input("spot_light_colors");
  524. parameters->spot_light_positions = program->get_input("spot_light_positions");
  525. parameters->spot_light_directions = program->get_input("spot_light_directions");
  526. parameters->spot_light_attenuations = program->get_input("spot_light_attenuations");
  527. parameters->spot_light_cutoffs = program->get_input("spot_light_cutoffs");
  528. parameters->focal_point = program->get_input("focal_point");
  529. parameters->shadow_map_directional = program->get_input("shadow_map_directional");
  530. parameters->shadow_splits_directional = program->get_input("shadow_splits_directional");
  531. parameters->shadow_matrices_directional = program->get_input("shadow_matrices_directional");
  532. // Add parameter set to map of parameter sets
  533. parameter_sets[program] = parameters;
  534. return parameters;
  535. }
  536. void material_pass::handle_event(const mouse_moved_event& event)
  537. {
  538. mouse_position = {static_cast<float>(event.x), static_cast<float>(event.y)};
  539. }
  540. bool operation_compare(const render_operation& a, const render_operation& b)
  541. {
  542. if (!a.material)
  543. return false;
  544. else if (!b.material)
  545. return true;
  546. bool xray_a = a.material->get_flags() & MATERIAL_FLAG_X_RAY;
  547. bool xray_b = b.material->get_flags() & MATERIAL_FLAG_X_RAY;
  548. if (xray_a)
  549. {
  550. if (xray_b)
  551. {
  552. // A and B are both xray, render back to front
  553. return (a.depth >= b.depth);
  554. }
  555. else
  556. {
  557. // A is xray, B is not. Render B first
  558. return false;
  559. }
  560. }
  561. else
  562. {
  563. if (xray_b)
  564. {
  565. // A is opaque, B is xray. Render A first
  566. return true;
  567. }
  568. else
  569. {
  570. // Determine transparency
  571. bool transparent_a = a.material->get_flags() & MATERIAL_FLAG_TRANSLUCENT;
  572. bool transparent_b = b.material->get_flags() & MATERIAL_FLAG_TRANSLUCENT;
  573. if (transparent_a)
  574. {
  575. if (transparent_b)
  576. {
  577. // Determine decal status
  578. bool decal_a = a.material->get_flags() & MATERIAL_FLAG_DECAL;
  579. bool decal_b = b.material->get_flags() & MATERIAL_FLAG_DECAL;
  580. if (decal_a)
  581. {
  582. if (decal_b)
  583. {
  584. // A and B are both transparent decals, render back to front
  585. return (a.depth >= b.depth);
  586. }
  587. else
  588. {
  589. // A is a transparent decal, B is transparent but not a decal, render A first
  590. return true;
  591. }
  592. }
  593. else
  594. {
  595. if (decal_b)
  596. {
  597. // A is transparent but not a decal, B is a transparent decal, render B first
  598. return false;
  599. }
  600. else
  601. {
  602. // A and B are both transparent, but not decals, render back to front
  603. return (a.depth >= b.depth);
  604. }
  605. }
  606. }
  607. else
  608. {
  609. // A is transparent, B is opaque. Render B first
  610. return false;
  611. }
  612. }
  613. else
  614. {
  615. if (transparent_b)
  616. {
  617. // A is opaque, B is transparent. Render A first
  618. return true;
  619. }
  620. else
  621. {
  622. // A and B are both opaque
  623. if (a.material->get_shader_program() == b.material->get_shader_program())
  624. {
  625. // A and B have the same shader
  626. if (a.vertex_array == b.vertex_array)
  627. {
  628. // A and B have the same VAO, render front to back
  629. return (a.depth < b.depth);
  630. }
  631. else
  632. {
  633. // Sort by VAO
  634. return (a.vertex_array < b.vertex_array);
  635. }
  636. }
  637. else
  638. {
  639. // A and B are both opaque and have different shaders, sort by shader
  640. return (a.material->get_shader_program() < b.material->get_shader_program());
  641. }
  642. }
  643. }
  644. }
  645. }
  646. }