44 return gfx::texture_format::RGBA8;
49 return gfx::texture_format::RGBA16F;
54 return gfx::texture_format::D32F;
81 pass.
clear(BGFX_CLEAR_COLOR, 0, 0.0f, 0);
85void apply_pipeline_taa_jitter_to_camera(
const camera& view_camera,
108 depth = std::make_shared<gfx::texture>(viewport_size.
width,
112 gfx::texture_format::D32F,
126 hiz = std::make_shared<gfx::texture>(viewport_size.
width,
130 gfx::texture_format::R32F,
132 BGFX_TEXTURE_COMPUTE_WRITE |
133 BGFX_SAMPLER_MIN_POINT |
134 BGFX_SAMPLER_MAG_POINT |
135 BGFX_SAMPLER_MIP_POINT |
136 BGFX_SAMPLER_U_CLAMP |
148 auto& depth = create_or_resize_d_buffer(rview, viewport_size, params);
155 auto tex0 = std::make_shared<gfx::texture>(viewport_size.
width,
159 get_default_format(),
160 BGFX_TEXTURE_COMPUTE_WRITE | BGFX_TEXTURE_RT);
162 auto tex1 = std::make_shared<gfx::texture>(viewport_size.
width,
169 auto tex2 = std::make_shared<gfx::texture>(viewport_size.
width,
176 auto tex3 = std::make_shared<gfx::texture>(viewport_size.
width,
180 get_default_format(),
184 fbo = std::make_shared<gfx::frame_buffer>();
185 fbo->populate({tex0, tex1, tex2, tex3, depth});
195 auto& depth = create_or_resize_d_buffer(rview, viewport_size, params);
202 auto tex = std::make_shared<gfx::texture>(viewport_size.
width,
208 fbo = std::make_shared<gfx::frame_buffer>();
209 fbo->populate({tex});
211 auto tex_unshadowed = std::make_shared<gfx::texture>(viewport_size.
width,
221 fbo_depth = std::make_shared<gfx::frame_buffer>();
222 fbo_depth->populate({tex, depth});
237 auto tex = std::make_shared<gfx::texture>(viewport_size.
width,
242 BGFX_TEXTURE_RT | BGFX_TEXTURE_COMPUTE_WRITE);
245 fbo = std::make_shared<gfx::frame_buffer>();
246 fbo->populate({tex});
255 auto& depth = create_or_resize_d_buffer(rview, viewport_size, params);
261 tex = std::make_shared<gfx::texture>(viewport_size.
width,
265 get_default_format(),
266 BGFX_TEXTURE_COMPUTE_WRITE | BGFX_TEXTURE_RT);
274 fbo = std::make_shared<gfx::frame_buffer>();
275 fbo->populate({tex, depth});
283 fbo = std::make_shared<gfx::frame_buffer>();
284 fbo->populate({tex});
301 tex = std::make_shared<gfx::texture>(9,
305 gfx::texture_format::RGBA32F,
306 BGFX_TEXTURE_RT | BGFX_TEXTURE_COMPUTE_WRITE |
307 BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT |
308 BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
310 float initial_coeffs[9 * 4] = {};
324 auto light_world_bounds =
math::bbox::mul(light_bounds, light_transform);
325 for(
const auto& element : visibility_set)
327 const auto&
entity = element.entity;
328 const auto&
lod_data = element.lod_data;
331 const auto& model_world_bounds = model_comp_ref.get_world_bounds();
333 bool result = light_world_bounds.intersect(model_world_bounds);
349auto deferred::get_light_program(
const light& l)
const ->
const color_lighting&
351 return color_lighting_[uint8_t(l.type)][uint8_t(l.shadow_params.depth)][uint8_t(l.shadow_params.type)];
354auto deferred::get_light_program_no_shadows(
const light& l)
const ->
const color_lighting&
356 return color_lighting_no_shadow_[uint8_t(l.type)];
359void deferred::submit_pbr_material(geom_program& program,
const pbr_material& mat)
368 const auto& albedo = color_map ? color_map : mat.default_color_map();
369 const auto&
normal = normal_map ? normal_map : mat.default_normal_map();
370 const auto& roughness = roughness_map ? roughness_map : mat.default_color_map();
371 const auto& metalness = metalness_map ? metalness_map : mat.default_color_map();
372 const auto& ao = ao_map ? ao_map : mat.default_color_map();
373 const auto& emissive = emissive_map ? emissive_map : mat.default_color_map();
382 const auto albedo_tex = albedo.get();
383 const auto normal_tex =
normal.get();
384 const auto roughness_tex = roughness.get();
385 const auto metalness_tex = metalness.get();
386 const auto ao_tex = ao.get();
387 const auto emissive_tex = emissive.get();
406 emissive_color.value.r * emissive_intensity,
407 emissive_color.value.g * emissive_intensity,
408 emissive_color.value.b * emissive_intensity,
409 emissive_color.value.a};
419 auto state = mat.get_render_states(
true,
true,
true);
429 [&](
auto e,
auto&& transform_comp,
auto&& reflection_probe_comp,
auto&& active)
431 if(reflection_probe_comp.already_generated())
438 const auto& world_transform = transform_comp.get_transform_global();
440 const auto& bounds = reflection_probe_comp.get_bounds();
446 const auto& probe = reflection_probe_comp.get_probe();
452 if(reflection_probe_comp.is_bake_cycle_unstarted())
454 for(std::uint32_t face = 0; face < 6; ++face)
456 clear_reflection_probe_face(reflection_probe_comp.get_cubemap_fbo(face));
460 bool any_face_dirty =
false;
462 for(std::uint32_t face = 0; face < 6; ++face)
464 if(reflection_probe_comp.already_generated(face))
473 auto& rview = reflection_probe_comp.get_render_view(face);
474 const auto& cubemap_fbo = reflection_probe_comp.get_cubemap_fbo(face);
488 if(reflection_probe_comp.get_capture_sky())
493 if(reflection_probe_comp.get_capture_shadows())
501 params.vflags = vflags;
502 params.pflags = pflags;
503 strip_post_effects_for_reflection_probe_capture(params);
507 clear_reflection_probe_face(cubemap_fbo);
511 any_face_dirty =
true;
514 if(any_face_dirty && reflection_probe_comp.is_bake_complete())
516 auto env_cube = reflection_probe_comp.get_cubemap();
517 auto env_cube_prefiltered = reflection_probe_comp.get_cubemap_prefiltered();
520 prefilter_params.
apply_prefilter = reflection_probe_comp.get_apply_prefilter();
522 for(std::uint32_t face = 0; face < 6; ++face)
524 const auto& cubemap_fbo = reflection_probe_comp.get_cubemap_fbo(face);
525 prefilter_params.
input_faces[face] = cubemap_fbo->get_texture();
545 bool queried =
false;
553 [&](
auto e,
auto&& transform_comp,
auto&& light_comp)
555 const auto&
light = light_comp.get_light();
559 bool camera_dependant = is_directional || has_render_mask;
562 auto&
generator = light_comp.get_shadowmap_generator();
564 generator.set_altitude_scale_factor(0.4f);
565 if(!camera_dependant &&
generator.already_updated())
572 auto world_transform = transform_comp.get_transform_global();
573 world_transform.reset_scale();
574 const auto& light_direction = world_transform.z_unit_axis();
583 const auto& bounds = light_comp.get_bounds_precise(light_direction);
603 bool should_rebuild = should_rebuild_shadows(dirty_models,
light, bounds, world_transform);
609 APP_SCOPE_PERF(
"Rendering/Shadow Generation Pass Per Light After Cull");
623 const auto& obuffer = create_or_resize_o_buffer(rview, viewport_size, params);
625 run_pipeline_impl(obuffer, scn,
camera, rview, dt, params, render_mask);
641 pass_params.
input = obuffer;
642 pass_params.
output = output;
676 if(build_reflection_probes)
687 create_or_resize_d_buffer(rview, viewport_size, params);
688 create_or_resize_g_buffer(rview, viewport_size, params);
689 create_or_resize_l_buffer(rview, viewport_size, params);
690 create_or_resize_r_buffer(rview, viewport_size, params);
692 apply_pipeline_taa_jitter_to_camera(
camera, viewport_size, params);
698 visibility_set.emplace_back(visibility_data{entity, lod_data});
702 run_g_buffer_pass(visibility_set,
camera, rview, dt);
704 run_assao_pass(
camera, rview, dt, params);
706 run_reflection_probe_pass(scn,
camera, rview, build_reflection_probes, dt);
708 const bool hiz_active = run_hiz_pass(
camera, rview, params, viewport_size, dt);
712 run_ssr_pass(
camera, rview, output, params);
715 target = run_direct_lighting_pass(scn,
camera, rview, build_shadowmaps, dt);
718 run_ssil_pass(
camera, rview, params);
721 target = run_indirect_lighting_pass(scn,
camera, rview, build_reflection_probes, dt);
723 if(stages & pipeline_steps::atmospheric)
725 target = run_atmospherics_pass(target, scn,
camera, rview, dt);
728 if(stages & pipeline_steps::particles_pass)
730 run_particle_pass(scn,
camera, rview, target);
735 blit_pass::run_params pass_params;
736 pass_params.input = target;
737 pass_params.output = output;
738 blit_pass_.run(rview, pass_params);
739 batch_collector_.clear();
743 target = run_taa_pass(camera, rview, target, output, params);
745 run_auto_exposure_pass(rview, target, params, dt);
747 target = run_bloom_pass(rview, target, params);
749 target = run_tonemapping_pass(rview, target, output, params);
751 run_fxaa_pass(rview, target, output, params);
755 run_ui_pass(scn, camera, rview, output);
759 run_debug_visualization_pass(camera, rview, output);
766 const bool taa_active =
static_cast<bool>(params.fill_taa_params);
767 if(hiz_active || taa_active)
769 snapshot_prev_depth(rview, viewport_size);
773 batch_collector_.clear();
779 auto depth_src = rview.
fbo_get(
"GBUFFER")->get_texture(4);
784 prev_depth = std::make_shared<gfx::texture>(viewport_size.
width,
788 gfx::texture_format::D32F,
789 BGFX_TEXTURE_BLIT_DST);
793 prev_depth->native_handle(), 0, 0,
794 depth_src->native_handle(), 0, 0);
808 const auto& gbuffer = rview.
fbo_get(
"GBUFFER");
813 pass.
bind(gbuffer.get());
816 batch_collector_.clear();
820 for(
const auto& element : visibility_set)
822 const auto&
entity = element.entity;
823 const auto&
lod_data = element.lod_data;
827 const auto&
model = model_comp.get_model();
847 const auto params = math::vec3{1.0f - transition_progress, 0.0f, 0.0f};
848 const auto params_inv = math::vec3{-transition_progress, 0.0f, 0.0f};
850 const auto& submesh_transforms = model_comp.get_submesh_transforms();
851 const auto& bone_transforms = model_comp.get_bone_transforms();
852 const auto& skinning_matrices = model_comp.get_skinning_transforms();
860 if(submit_params.skinned)
862 stats_.drawn_skinned_models++;
866 stats_.drawn_models++;
868 geom_program& prog = submit_params.skinned ? geom_program_skinned_ : geom_program_;
869 prog.program->begin();
875 geom_program& prog = submit_params.skinned ? geom_program_skinned_ : geom_program_;
884 stats_.drawn_skinned_submeshes++;
888 stats_.drawn_static_submeshes++;
890 geom_program& prog = submit_params.
skinned ? geom_program_skinned_ : geom_program_;
892 bool submitted = mat.submit(prog.program.get());
897 const auto& pbr =
static_cast<const pbr_material&
>(mat);
898 submit_pbr_material(prog, pbr);
906 geom_program& prog = submit_params.
skinned ? geom_program_skinned_ : geom_program_;
913 const auto extras = model_comp.get_submit_extras(
false);
916 const bool is_skinned = !skinning_matrices.empty();
923 stats_.drawn_models++;
925 if(math::epsilonNotEqual(current_time, 0.0f, math::epsilon<float>()))
928 stats_.drawn_models++;
943 if(math::epsilonNotEqual(current_time, 0.0f, math::epsilon<float>()))
947 geom_program& prog = submit_params.
skinned ? geom_program_skinned_ : geom_program_;
968 submit_batched_geometry(pass,
camera);
985 batch_collector_.prepare_batches(context);
987 const auto& prepared_batches = batch_collector_.get_prepared_batches();
988 if (prepared_batches.empty())
997 geom_program_instanced_.program->begin();
999 gfx::set_uniform(geom_program_instanced_.u_camera_clip_planes, clip_planes);
1002 for (
const auto* batch : prepared_batches)
1004 if (!batch->is_valid() || batch->instances.empty())
1009 const auto instance_count =
static_cast<uint32_t
>(batch->instances.size());
1010 stats_.drawn_static_submeshes += instance_count;
1012 const auto mesh_ptr = batch->key.mesh_ptr;
1013 const auto material_ptr = batch->key.material_ptr;
1014 const auto lod_index = batch->key.lod_index;
1015 const auto submesh_index = batch->key.submesh_index;
1017 if (!mesh_ptr || !material_ptr)
1022 const auto submesh = mesh_ptr->get_submesh(submesh_index, lod_index);
1032 bgfx::InstanceDataBuffer instance_buffer;
1033 bgfx::allocInstanceDataBuffer(&instance_buffer, instance_count, instance_data_size);
1034 if (!instance_buffer.data)
1042 mesh_ptr->bind_render_buffers_for_submesh(submesh, lod_index);
1045 auto* buffer_data =
reinterpret_cast<instance_vertex_data*
>(instance_buffer.data);
1046 for (
size_t i = 0;
i < batch->instances.size(); ++
i)
1048 buffer_data[
i] = instance_vertex_data(batch->instances[i]);
1052 bgfx::setInstanceDataBuffer(&instance_buffer);
1055 bool material_submitted = material_ptr->submit(geom_program_instanced_.program.get());
1056 if (!material_submitted)
1058 if (material_ptr->is<pbr_material>())
1060 const auto& pbr =
static_cast<const pbr_material&
>(*material_ptr);
1061 submit_pbr_material(geom_program_instanced_, pbr);
1066 const auto lod_params = math::vec3{0.0f, -1.0f, 1.0f};
1070 gfx::submit(pass.
id, geom_program_instanced_.program->native_handle(), 0,
false);
1073 geom_program_instanced_.program->end();
1076 const auto& batch_stats = batch_collector_.get_stats();
1077 stats_.add_batch_stats(batch_stats);
1080 batch_collector_.clear();
1090 assao_pass_.release_resources(rview);
1095 const auto& gbuffer = rview.
fbo_get(
"GBUFFER");
1097 auto color_ao = gbuffer->get_texture(0);
1098 auto normal = gbuffer->get_texture(1);
1099 auto depth = gbuffer->get_texture(4);
1102 params.
depth = depth.get();
1108 assao_pass_.run(
camera, rview, params);
1111auto deferred::run_irradiance_pass(
scene& scn,
gfx::render_view& rview) -> deferred::irradiance_pass_result
1115 irradiance_pass_result result;
1117 if(irradiance_compute_program_.program && irradiance_compute_program_.program->is_valid())
1119 const auto& irradiance_tex = create_or_get_irradiance_texture(rview);
1121 struct skylight_params
1123 float intensity = 0.0f;
1124 float sun_weight = 1.0f;
1125 float exposition = 0.1f;
1126 float sky_brightness = 1.0f;
1127 math::vec3
color = {1.0f, 1.0f, 1.0f};
1128 math::vec3 tint = {1.0f, 1.0f, 1.0f};
1129 math::vec3 light_dir;
1130 irradiance_perez_params perez;
1131 bool use_perez =
false;
1132 bool is_skybox =
false;
1133 bool use_sky =
true;
1134 bool directional =
true;
1137 skylight_params dominant;
1139 scn.registry->view<transform_component, skylight_component, active_component>().each(
1140 [&](
auto e,
auto&& transform_comp_ref,
auto&& skylight_comp_ref,
auto&& active)
1142 const auto& skylight = skylight_comp_ref;
1143 float irradiance_intensity = skylight.get_irradiance_intensity();
1144 if(irradiance_intensity <= 0.0f)
1147 const auto& world_transform = transform_comp_ref.get_transform_global();
1148 math::vec3 light_dir = world_transform.z_unit_axis();
1149 math::vec3 irradiance_color = {1.0f, 1.0f, 1.0f};
1150 bool use_perez =
false;
1155 const bool wants_sky = skylight.get_irradiance_use_sky();
1158 float sun_weight = 1.0f;
1162 float sun_elevation = -light_dir.y;
1164 float x = math::clamp(sun_elevation / 0.35f, 0.0f, 1.0f);
1165 sun_weight =
x *
x * (3.0f - 2.0f *
x);
1167 float exposition = 0.1f;
1181 irradiance_color = glm::mix(dominant.perez.sky_luminance_rgb, dominant.perez.sun_luminance_rgb, sun_weight);
1182 exposition = dominant.perez.exposition;
1189 math::vec3 sky_luminance_rgb;
1190 math::vec3 sun_luminance_rgb;
1192 irradiance_color = glm::mix(sky_luminance_rgb, sun_luminance_rgb, sun_weight * 0.25f);
1193 float sun_altitude = -light_dir.y;
1194 float altitude_factor = bx::lerp(0.6f, 1.0f, bx::clamp(bx::abs(sun_altitude), 0.0f, 1.0f));
1195 exposition = 0.1f * altitude_factor;
1199 float sky_brightness = skylight.get_sky_brightness();
1200 exposition *= sky_brightness;
1202 const auto& tint = skylight.get_irradiance_tint();
1203 math::vec3 tint_vec = {tint.value.r, tint.value.g, tint.value.b};
1204 irradiance_color.x *= tint_vec.x;
1205 irradiance_color.y *= tint_vec.y;
1206 irradiance_color.z *= tint_vec.z;
1208 if(irradiance_intensity > dominant.intensity)
1210 dominant.intensity = irradiance_intensity;
1211 dominant.color = irradiance_color;
1212 dominant.tint = tint_vec;
1213 dominant.light_dir = light_dir;
1214 dominant.use_perez = use_perez;
1215 dominant.is_skybox = is_skybox;
1216 dominant.use_sky = wants_sky;
1218 dominant.sun_weight = sun_weight;
1219 dominant.exposition = exposition;
1220 dominant.sky_brightness = sky_brightness;
1226 irradiance_compute_program_.program->begin();
1227 gfx::set_image(0, irradiance_tex->native_handle(), 0, bgfx::Access::Write);
1230 float ambient_vec[4];
1231 if(dominant.use_perez)
1233 ambient_vec[0] = dominant.tint.x;
1234 ambient_vec[1] = dominant.tint.y;
1235 ambient_vec[2] = dominant.tint.z;
1236 ambient_vec[3] = dominant.intensity;
1240 ambient_vec[0] = dominant.color.x;
1241 ambient_vec[1] = dominant.color.y;
1242 ambient_vec[2] = dominant.color.z;
1243 ambient_vec[3] = dominant.intensity;
1245 auto cubemap_tex = dominant.cubemap.get();
1246 const bool use_cubemap = dominant.is_skybox && dominant.use_sky && cubemap_tex && cubemap_tex->info.cubeMap;
1252 constexpr float ambient_intensity_boost = 2.0f;
1254 ambient_vec[3] *= dominant.sky_brightness;
1255 else if(dominant.use_sky)
1256 ambient_vec[3] *= ambient_intensity_boost;
1258 gfx::set_uniform(irradiance_compute_program_.u_irradiance_tint_intensity, ambient_vec);
1261 float exp_val = dominant.exposition;
1262 float exp_vec[4] = {exp_val, 0.0f, 0.0f, 0.0f};
1265 if(dominant.intensity > 0.0f && dominant.use_perez)
1268 gfx::set_uniform(irradiance_compute_program_.u_sun_direction, dominant.perez.sun_direction);
1269 gfx::set_uniform(irradiance_compute_program_.u_sun_luminance, dominant.perez.sun_luminance_rgb);
1270 gfx::set_uniform(irradiance_compute_program_.u_sky_luminance_xyz, dominant.perez.sky_luminance_xyz);
1271 gfx::set_uniform(irradiance_compute_program_.u_perez_coeff, &dominant.perez.perez_coeff[0][0], 5);
1273 else if(use_cubemap)
1276 mode = dominant.directional ? 2 : 3;
1279 else if(!dominant.use_sky && dominant.directional)
1287 float mode_vec[4] = {float(mode), dominant.sun_weight, 0.0f, 0.0f};
1290 bgfx::dispatch(irr_pass.id, irradiance_compute_program_.program->native_handle(), 1, 1, 1);
1291 irradiance_compute_program_.program->end();
1293 result.irradiance_tex = irradiance_tex;
1294 result.global_color = dominant.color;
1295 result.global_intensity = dominant.intensity;
1300 const auto& irradiance_tex = create_or_get_irradiance_texture(rview);
1301 result.irradiance_tex = irradiance_tex;
1302 scn.registry->view<transform_component, skylight_component, active_component>().each(
1303 [&](
auto e,
auto&& transform_comp_ref,
auto&& skylight_comp_ref,
auto&& active)
1305 const auto& skylight = skylight_comp_ref;
1308 float irradiance_intensity = skylight.get_irradiance_intensity();
1309 if(irradiance_intensity <= 0.0f)
1311 const auto& world_transform = transform_comp_ref.get_transform_global();
1312 math::vec3 light_dir = world_transform.z_unit_axis();
1313 math::vec3 irradiance_color = {1.0f, 1.0f, 1.0f};
1318 math::vec3 sky_luminance_rgb;
1319 math::vec3 sun_luminance_rgb;
1321 float sun_elevation = -light_dir.y;
1322 float x = math::clamp(sun_elevation / 0.35f, 0.0f, 1.0f);
1323 float sun_weight =
x *
x * (3.0f - 2.0f *
x);
1324 irradiance_color = glm::mix(sky_luminance_rgb, sun_luminance_rgb, sun_weight);
1325 irradiance_intensity *= sun_weight;
1327 const auto& tint = skylight.get_irradiance_tint();
1328 irradiance_color.x *= tint.value.r;
1329 irradiance_color.y *= tint.value.g;
1330 irradiance_color.z *= tint.value.b;
1331 if(irradiance_intensity > result.global_intensity)
1333 result.global_intensity = irradiance_intensity;
1334 result.global_color = irradiance_color;
1342auto deferred::run_direct_lighting_pass(
scene& scn,
1354 const auto& gbuffer = rview.
fbo_get(
"GBUFFER");
1355 const auto& lbuffer = rview.
fbo_get(
"LBUFFER");
1357 const auto buffer_size = lbuffer->get_size();
1360 pass.
bind(lbuffer.get());
1362 pass.
clear(BGFX_CLEAR_COLOR, 0, 0.0f, 0);
1365 [&](
auto e,
auto&& transform_comp_ref,
auto&& light_comp_ref,
auto&& active)
1367 const auto&
light = light_comp_ref.get_light();
1368 const auto&
generator = light_comp_ref.get_shadowmap_generator();
1369 auto world_transform = transform_comp_ref.get_transform_global();
1370 world_transform.reset_scale();
1371 const auto& light_position = world_transform.get_position();
1372 const auto& light_direction = world_transform.z_unit_axis();
1374 const auto& bounds = light_comp_ref.get_bounds_precise(light_direction);
1382 .compute_projected_sphere_rect(
rect, light_position, light_direction, camera_pos,
view, proj) == 0)
1390 stats_.drawn_lights++;
1391 stats_.drawn_lights_casting_shadows += uint32_t(has_shadows);
1393 const auto& lprogram = has_shadows ? get_light_program(
light) : get_light_program_no_shadows(
light);
1395 lprogram.program->begin();
1403 if(n_dot_l_high < n_dot_l_low)
1405 const float t = n_dot_l_low;
1406 n_dot_l_low = n_dot_l_high;
1416 float light_data[4] = {0.0f, 0.0f, 0.0f, contact_shadow_distance};
1426 contact_shadow_distance};
1437 contact_shadow_distance};
1456 for(; i < gbuffer->get_attachment_count(); ++i)
1470 gfx::set_state(topology | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_BLEND_ADD);
1474 lprogram.program->end();
1482auto deferred::run_indirect_lighting_pass(
scene& scn,
1485 bool apply_reflection,
1494 const auto& gbuffer = rview.
fbo_get(
"GBUFFER");
1496 const auto& lbuffer = rview.
fbo_get(
"LBUFFER");
1498 const auto irradiance_result = run_irradiance_pass(scn, rview);
1501 pass.
bind(lbuffer.get());
1504 const auto& iprogram = indirect_lighting_program_;
1505 iprogram.program->begin();
1507 float light_data[4] = {irradiance_result.global_color.x, irradiance_result.global_color.y, irradiance_result.global_color.z, irradiance_result.global_intensity};
1512 for(; i < gbuffer->get_attachment_count(); ++i)
1530 gfx::set_state(topology | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_BLEND_ADD);
1534 iprogram.program->end();
1555 const auto& gbuffer = rview.
fbo_get(
"GBUFFER");
1556 const auto& rbuffer = rview.
fbo_get(
"RBUFFER");
1558 const auto buffer_size = rbuffer->get_size();
1561 pass.
bind(rbuffer.get());
1563 pass.
clear(BGFX_CLEAR_COLOR, 0, 0.0f, 0);
1566 std::vector<entt::entity> sorted_probes;
1570 [&](
auto e,
auto&& transform_comp_ref,
auto&& probe_comp_ref,
auto&& active)
1572 sorted_probes.emplace_back(e);
1576 std::sort(std::begin(sorted_probes),
1577 std::end(sorted_probes),
1578 [&](
const auto& lhs,
const auto& rhs)
1581 const auto& lhs_probe = lhs_comp.
get_probe();
1584 const auto& rhs_probe = rhs_comp.
get_probe();
1587 if(lhs_probe.method != rhs_probe.method)
1589 return lhs_probe.method < rhs_probe.method;
1593 return lhs_probe.get_max_range() > rhs_probe.get_max_range();
1597 for(
const auto& e : sorted_probes)
1602 const auto& probe = probe_comp_ref.get_probe();
1604 const auto& probe_position = world_transform.get_position();
1605 const auto& probe_scale = world_transform.get_scale();
1608 if(probe_comp_ref.compute_projected_sphere_rect(
rect, probe_position, probe_scale, camera_pos,
view, proj) == 0)
1613 const auto& cubemap = probe_comp_ref.get_cubemap_prefiltered();
1615 ref_probe_program* ref_probe_program =
nullptr;
1616 float influence_radius = 0.0f;
1619 ref_probe_program = &sphere_ref_probe_program_;
1621 math::max(probe_scale.x, math::max(probe_scale.y, probe_scale.z)) * probe.sphere_data.range;
1627 t.scale(probe.box_data.extents);
1629 float data2[4] = {probe.box_data.extents.x,
1630 probe.box_data.extents.y,
1631 probe.box_data.extents.z,
1632 probe.box_data.transition_distance};
1634 ref_probe_program = &box_ref_probe_program_;
1639 influence_radius = math::length(t.get_scale() + probe.box_data.transition_distance);
1642 if(ref_probe_program)
1644 float mips = cubemap ? float(cubemap->info.numMips) : 1.0f;
1653 const float source_validity = 1.0f;
1654 float data1[4] = {mips, probe.intensity, is_global_fallback ? 1.0f : 0.0f, source_validity};
1655 float capture[4] = {probe_comp_ref.get_apply_prefilter() ? 1.0f : 0.0f, 0.0f, 0.0f, 0.0f};
1661 for(
size_t i = 0; i < gbuffer->get_attachment_count(); ++i)
1670 gfx::set_state(topology | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_BLEND_ALPHA);
1672 ref_probe_program->program->begin();
1673 gfx::submit(pass.
id, ref_probe_program->program->native_handle());
1675 ref_probe_program->program->end();
1693 bool found_sun =
false;
1697 [&](
auto e,
auto&& transform_comp_ref,
auto&& light_comp_ref,
auto&& active)
1699 auto entity = scn.create_handle(e);
1703 APPLOG_WARNING(
"[{}] More than one entity with this component. Others are ignored.",
"Skylight");
1706 const auto& cubemap = light_comp_ref.get_cubemap();
1707 auto cubemap_texture = cubemap.get();
1710 if(cubemap_texture->info.cubeMap)
1712 params_skybox.
cubemap = cubemap;
1716 mode = light_comp_ref.get_mode();
1718 if(
auto light_comp =
entity.template try_get<light_component>())
1720 const auto&
light = light_comp->get_light();
1724 const auto& world_transform = transform_comp_ref.get_transform_global();
1727 params_perez.
turbidity = light_comp_ref.get_turbidity();
1728 params_perez.
cloud_mode =
static_cast<int>(light_comp_ref.get_cloud_mode());
1729 params_perez.
cloud_coverage = light_comp_ref.get_cloud_coverage();
1732 params_perez.
cloud_density = light_comp_ref.get_cloud_density();
1735 params_perez.
cloud_time = light_comp_ref.get_cloud_time();
1736 params_perez.
sky_brightness = light_comp_ref.get_sky_brightness();
1748 params_skybox.
sky_brightness = light_comp_ref.get_sky_brightness();
1760 auto lbuffer_depth = rview.
fbo_get(
"LBUFFER_DEPTH");
1765 atmospheric_pass_skybox_.run(lbuffer_depth, c, rview, dt, params_skybox);
1768 atmospheric_pass_perez_.run(lbuffer_depth, c, rview, dt, params_perez);
1780 if(!reflection_screen_stack_enabled(rparams) || !rparams.
fill_ssr_params)
1782 ssr_pass_.release_resources(rview);
1792 previous_frame_source ? previous_frame_source->get_texture() : rview.
fbo_get(
"LBUFFER")->get_texture();
1806 ssr_pass_.run(rview, ssr_params);
1815 ssil_pass_.release_resources(rview);
1836 auto result = ssil_pass_.run(rview, ssil_params);
1846 const auto prev_sz = result->get_size();
1852 prev_ssil = std::make_shared<gfx::texture>(
static_cast<std::uint16_t
>(prev_sz.width),
1853 static_cast<std::uint16_t
>(prev_sz.height),
1856 gfx::texture_format::RGBA16F,
1857 BGFX_TEXTURE_BLIT_DST |
1858 BGFX_SAMPLER_U_CLAMP |
1859 BGFX_SAMPLER_V_CLAMP);
1863 prev_ssil->native_handle(), 0, 0,
1864 result->native_handle(), 0, 0);
1879 if(!rparams.fill_taa_params)
1881 taa_pass_.release_resources(rview);
1885 if(!
input || !gbuffer)
1893 p.g_buffer = gbuffer;
1894 rparams.fill_taa_params(p);
1895 return taa_pass_.run(rview, p);
1903 if(!rparams.fill_fxaa_params || rparams.fill_taa_params)
1905 fxaa_pass_.release_resources(rview);
1915 rparams.fill_fxaa_params(params);
1917 return fxaa_pass_.run(rview, params);
1927 auto_exposure_pass_.release_resources(rview);
1934 auto_exposure_pass_.run(rview, params);
1941 if(!reflection_screen_stack_enabled(rparams) || !rparams.fill_bloom_params || !rparams.fill_hdr_params)
1943 bloom_pass_.release_resources(rview);
1948 rparams.fill_bloom_params(params);
1950 if(rparams.fill_auto_exposure_params)
1955 return bloom_pass_.run(rview, params);
1963 if(!rparams.fill_hdr_params)
1965 tonemapping_pass_.release_resources(rview);
1973 if(!rparams.fill_fxaa_params || rparams.fill_taa_params)
1978 rparams.fill_hdr_params(params);
1980 if(rparams.fill_auto_exposure_params)
1985 return tonemapping_pass_.run(rview, params);
1994 const auto& gbuffer = rview.
fbo_get(
"GBUFFER");
1996 const auto& irradiance_tex = create_or_get_irradiance_texture(rview);
1999 pass.
bind(output.get());
2003 const auto output_size = output->get_size();
2005 debug_visualization_program_.program->begin();
2007 float u_params[4] = {float(debug_pass_), 0.0f, 0.0f, 0.0f};
2012 for(; i < gbuffer->get_attachment_count(); ++i)
2014 gfx::set_texture(debug_visualization_program_.s_tex[i], i, gbuffer->get_texture(i));
2018 gfx::set_texture(debug_visualization_program_.s_tex[i], i, irradiance_tex);
2029 gfx::set_state(topology | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A);
2030 gfx::submit(pass.
id, debug_visualization_program_.program->native_handle());
2032 debug_visualization_program_.program->end();
2044 const bool want_hiz =
2045 reflection_screen_stack_enabled(params) && (params.fill_ssr_params || params.fill_ssil_params);
2054 create_or_resize_hiz_buffer(rview, viewport_size);
2058 const auto& gbuffer = rview.
fbo_get(
"GBUFFER");
2069 hiz_pass_.run(rview, hp);
2078deferred::~deferred()
2087 auto load_program = [&](
const std::string& vs,
const std::string&
fs)
2089 auto vs_shader = am.get_asset<
gfx::shader>(
"engine:/data/shaders/" + vs +
".sc");
2090 auto fs_shadfer = am.get_asset<
gfx::shader>(
"engine:/data/shaders/" +
fs +
".sc");
2092 return std::make_unique<gpu_program>(vs_shader, fs_shadfer);
2095 geom_program_.program = load_program(
"deferred_geom/vs_deferred_geom",
"deferred_geom/fs_deferred_geom");
2096 geom_program_.cache_uniforms();
2098 geom_program_skinned_.program = load_program(
"deferred_geom/vs_deferred_geom_skinned",
"deferred_geom/fs_deferred_geom");
2099 geom_program_skinned_.cache_uniforms();
2101 geom_program_instanced_.program = load_program(
"deferred_geom/vs_deferred_geom_instanced",
"deferred_geom/fs_deferred_geom");
2102 geom_program_instanced_.cache_uniforms();
2104 sphere_ref_probe_program_.program = load_program(
"vs_clip_quad_ex",
"reflection_probe/fs_sphere_reflection_probe");
2105 sphere_ref_probe_program_.cache_uniforms();
2107 box_ref_probe_program_.program = load_program(
"vs_clip_quad_ex",
"reflection_probe/fs_box_reflection_probe");
2108 box_ref_probe_program_.cache_uniforms();
2110 indirect_lighting_program_.program = load_program(
"vs_clip_quad",
"fs_deferred_indirect_light");
2111 indirect_lighting_program_.cache_uniforms();
2113 auto cs_irradiance = am.get_asset<
gfx::shader>(
"engine:/data/shaders/irradiance/cs_irradiance_sh.sc");
2116 irradiance_compute_program_.program = std::make_unique<gpu_program>(cs_irradiance);
2117 irradiance_compute_program_.cache_uniforms();
2120 debug_visualization_program_.program = load_program(
"vs_clip_quad",
"gbuffer/fs_gbuffer_visualize");
2121 debug_visualization_program_.cache_uniforms();
2126 color_lighting_no_shadow_[uint8_t(
light_type::spot)].program = load_program(
"vs_clip_quad",
"fs_deferred_spot_light");
2139 color_lighting_no_shadow_[uint8_t(
light_type::point)].program = load_program(
"vs_clip_quad",
"fs_deferred_point_light");
2152 color_lighting_no_shadow_[uint8_t(
light_type::directional)].program = load_program(
"vs_clip_quad",
"fs_deferred_directional_light");
2166 for(
auto& byLightType : color_lighting_no_shadow_)
2168 if(byLightType.program)
2170 byLightType.cache_uniforms();
2173 for(
auto& byLightType : color_lighting_)
2175 for(
auto& byDepthType : byLightType)
2177 for(
auto& bySmImpl : byDepthType)
2179 if(bySmImpl.program)
2181 bySmImpl.cache_uniforms();
2187 ibl_brdf_lut_ = am.get_asset<
gfx::texture>(
"engine:/data/textures/ibl_brdf_lut.png");
2189 return pipeline::init(ctx);