19 auto fs_ssr_fidelityfx = am.get_asset<
gfx::shader>(
"engine:/data/shaders/ssr/fs_ssr_fidelityfx.sc");
22 auto fs_ssr_temporal_resolve = am.get_asset<
gfx::shader>(
"engine:/data/shaders/ssr/fs_ssr_temporal_resolve.sc");
25 auto fs_ssr_composite = am.get_asset<
gfx::shader>(
"engine:/data/shaders/ssr/fs_ssr_composite.sc");
28 auto cs_ssr_blur = am.get_asset<
gfx::shader>(
"engine:/data/shaders/ssr/cs_ssr_blur.sc");
31 fidelityfx_pixel_program_.program = std::make_unique<gpu_program>(vs_clip_quad, fs_ssr_fidelityfx);
32 fidelityfx_pixel_program_.cache_uniforms();
35 temporal_resolve_program_.program = std::make_unique<gpu_program>(vs_clip_quad, fs_ssr_temporal_resolve);
36 temporal_resolve_program_.cache_uniforms();
39 composite_program_.program = std::make_unique<gpu_program>(vs_clip_quad, fs_ssr_composite);
40 composite_program_.cache_uniforms();
43 blur_compute_program_.program = std::make_unique<gpu_program>(cs_ssr_blur);
44 blur_compute_program_.cache_uniforms();
47 bool all_valid = fidelityfx_pixel_program_.is_valid() && temporal_resolve_program_.is_valid() &&
48 composite_program_.is_valid() && blur_compute_program_.program &&
49 blur_compute_program_.program->is_valid();
65 auto ref_sz = reference->get_size();
66 auto ref_tex = reference->get_texture();
67 auto ref_format = ref_tex->info.format;
69 auto& ssr_output_tex = rview.tex_get_or_emplace(
"SSR_OUTPUT");
70 if(!ssr_output_tex || (ssr_output_tex && ssr_output_tex->get_size() != ref_sz) ||
71 (ssr_output_tex && ssr_output_tex->info.format != ref_format))
73 ssr_output_tex = std::make_shared<gfx::texture>(ref_sz.width,
82 auto& ssr_output_fbo = rview.fbo_get_or_emplace(
"SSR_OUTPUT");
83 if(!ssr_output_fbo || (ssr_output_fbo && ssr_output_fbo->get_size() != ref_sz))
85 ssr_output_fbo = std::make_shared<gfx::frame_buffer>();
86 ssr_output_fbo->populate({ssr_output_tex});
89 return ssr_output_fbo;
96 auto ref_sz = reference->get_size();
97 auto ref_tex = reference->get_texture();
98 auto ref_format = ref_tex->info.format;
101 uint32_t target_width =
static_cast<uint32_t
>(ref_sz.width * (enable_half_res ? 0.5f : 1.0f));
102 uint32_t target_height =
static_cast<uint32_t
>(ref_sz.height * (enable_half_res ? 0.5f : 1.0f));
105 target_width = target_width > 0 ? target_width : 1;
106 target_height = target_height > 0 ? target_height : 1;
108 auto& ssr_curr_tex = rview.tex_get_or_emplace(
"SSR_CURR");
110 (ssr_curr_tex && (ssr_curr_tex->info.width != target_width || ssr_curr_tex->info.height != target_height)) ||
111 (ssr_curr_tex && ssr_curr_tex->info.format != ref_format))
113 ssr_curr_tex = std::make_shared<gfx::texture>(target_width,
122 auto& ssr_curr_fbo = rview.fbo_get_or_emplace(
"SSR_CURR");
123 usize32_t target_size{target_width, target_height};
124 if(!ssr_curr_fbo || (ssr_curr_fbo && ssr_curr_fbo->get_size() != target_size))
126 ssr_curr_fbo = std::make_shared<gfx::frame_buffer>();
127 ssr_curr_fbo->populate({ssr_curr_tex});
137 auto ref_sz = reference->get_size();
138 auto ref_tex = reference->get_texture();
139 auto ref_format = ref_tex->info.format;
142 uint32_t target_width =
static_cast<uint32_t
>(ref_sz.width * (enable_half_res ? 0.5f : 1.0f));
143 uint32_t target_height =
static_cast<uint32_t
>(ref_sz.height * (enable_half_res ? 0.5f : 1.0f));
146 target_width = target_width > 0 ? target_width : 1;
147 target_height = target_height > 0 ? target_height : 1;
149 auto& history_tex = rview.tex_get_or_emplace(
"SSR_HISTORY");
151 (history_tex && (history_tex->info.width != target_width || history_tex->info.height != target_height)) ||
152 (history_tex && history_tex->info.format != ref_format))
154 history_tex = std::make_shared<gfx::texture>(target_width,
159 BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_RT | BGFX_SAMPLER_U_CLAMP |
160 BGFX_SAMPLER_V_CLAMP);
170 auto ref_sz = reference->get_size();
171 auto ref_tex = reference->get_texture();
172 auto ref_format = ref_tex->info.format;
175 uint32_t target_width =
static_cast<uint32_t
>(ref_sz.width * (enable_half_res ? 0.5f : 1.0f));
176 uint32_t target_height =
static_cast<uint32_t
>(ref_sz.height * (enable_half_res ? 0.5f : 1.0f));
179 target_width = target_width > 0 ? target_width : 1;
180 target_height = target_height > 0 ? target_height : 1;
182 auto& temp_tex = rview.tex_get_or_emplace(
"SSR_HISTORY_TEMP");
184 (temp_tex && (temp_tex->info.width != target_width || temp_tex->info.height != target_height)) ||
185 (temp_tex && temp_tex->info.format != ref_format))
187 temp_tex = std::make_shared<gfx::texture>(target_width,
192 BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_RT | BGFX_SAMPLER_U_CLAMP |
193 BGFX_SAMPLER_V_CLAMP);
196 auto& temp_fbo = rview.fbo_get_or_emplace(
"SSR_HISTORY_TEMP");
197 usize32_t target_size{target_width, target_height};
198 if(!temp_fbo || (temp_fbo && temp_fbo->get_size() != target_size))
200 temp_fbo = std::make_shared<gfx::frame_buffer>();
201 temp_fbo->populate({temp_tex});
216 return run_fidelityfx(rview, params);
222 return run_fidelityfx_three_pass(rview, params);
238 if(!blur_compute_program_.program || !blur_compute_program_.program->is_valid())
243 auto input_size = input_color->get_size();
246 auto& blurred_tex = rview.tex_get_or_emplace(
"SSR_BLURRED_COLOR");
247 if(!blurred_tex || blurred_tex->get_size() != input_size)
249 blurred_tex = std::make_shared<gfx::texture>(input_size.width,
253 gfx::texture_format::RGBA8,
254 BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP |
255 BGFX_TEXTURE_COMPUTE_WRITE | BGFX_TEXTURE_RT);
258 const uint32_t num_mips =
settings.cone_tracing.max_mip_level + 1;
262 for(
int mip = 0; mip < num_mips; ++mip)
265 int mip_width = (input_size.width >> mip) > 1 ? (input_size.width >> mip) : 1;
266 int mip_height = (input_size.height >> mip) > 1 ? (input_size.height >> mip) : 1;
269 float sigma =
settings.cone_tracing.blur_base_sigma;
272 blur_compute_program_.program->begin();
278 gfx::set_image(1, input_color->native_handle(), 0, bgfx::Access::Read);
283 gfx::set_image(1, blurred_tex->native_handle(), mip - 1, bgfx::Access::Read);
286 float blur_params[4] = {float(mip), sigma, 0.0f, 0.0f};
290 gfx::set_image(0, blurred_tex->native_handle(), mip, bgfx::Access::Write);
292 gfx::set_texture(blur_compute_program_.s_normal, 2, g_buffer->get_texture(1));
295 uint32_t num_groups_x = (mip_width + 7) / 8;
296 uint32_t num_groups_y = (mip_height + 7) / 8;
297 gfx::dispatch(pass.
id, blur_compute_program_.program->native_handle(), num_groups_x, num_groups_y, 1);
299 blur_compute_program_.program->end();
308 auto ssr_curr_fb = run_ssr_trace(rview, params);
315 auto ssr_history_fb =
316 run_temporal_resolve(rview, ssr_curr_fb, params.g_buffer, params.cam, params.settings.fidelityfx);
324 run_composite(rview, ssr_history_fb, ssr_curr_fb, params.output, params.g_buffer, params.output);
332 auto ssr_curr_fbo = create_or_update_ssr_curr_fb(rview, params.g_buffer, params.settings.fidelityfx.enable_half_res);
336 if(params.settings.fidelityfx.enable_cone_tracing && params.previous_frame)
338 blurred_color_buffer =
339 generate_blurred_color_buffer(rview, params.previous_frame, params.g_buffer, params.settings.fidelityfx);
348 pass.
bind(ssr_curr_fbo.get());
349 pass.
set_view_proj(params.cam->get_view(), params.cam->get_projection());
352 fidelityfx_pixel_program_.program->begin();
355 gfx::set_texture(fidelityfx_pixel_program_.s_color, 0, params.previous_frame);
356 gfx::set_texture(fidelityfx_pixel_program_.s_normal, 1, params.g_buffer->get_texture(1));
357 gfx::set_texture(fidelityfx_pixel_program_.s_depth, 2, params.g_buffer->get_texture(4));
361 auto cone_tracing_texture = blurred_color_buffer ? blurred_color_buffer : params.previous_frame;
362 gfx::set_texture(fidelityfx_pixel_program_.s_color_blurred, 4, cone_tracing_texture);
365 float ssr_params[4] = {float(params.settings.fidelityfx.max_steps),
366 params.settings.fidelityfx.depth_tolerance,
367 float(params.settings.fidelityfx.max_rays),
368 params.settings.fidelityfx.brightness};
373 auto ssr_size = ssr_curr_fbo->get_size();
374 auto g_buffer_size = params.g_buffer->get_size();
375 float ssr_resolution_scale = float(g_buffer_size.width) / float(ssr_size.width);
377 float hiz_params[4] = {
383 if(params.hiz_buffer)
385 hiz_params[0] = float(params.hiz_buffer->info.width);
386 hiz_params[1] = float(params.hiz_buffer->info.height);
387 hiz_params[2] = float(params.hiz_buffer->info.numMips);
393 float fade_params[4] = {params.settings.fidelityfx.fade_in_start,
394 params.settings.fidelityfx.fade_in_end,
395 params.settings.fidelityfx.roughness_depth_tolerance,
396 params.settings.fidelityfx.facing_reflections_fading};
400 float cone_params[4] = {
401 params.settings.fidelityfx.cone_tracing.cone_angle_bias,
402 float(params.settings.fidelityfx.cone_tracing.max_mip_level),
404 float(params.settings.fidelityfx.enable_cone_tracing ? 1.0f : 0.0f)
409 auto prev_view_proj = params.cam->get_prev_view_projection();
410 gfx::set_uniform(fidelityfx_pixel_program_.u_prev_view_proj, prev_view_proj.get_matrix());
414 gfx::set_state(topology | BGFX_STATE_DEPTH_TEST_NEVER | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A);
415 gfx::submit(pass.
id, fidelityfx_pixel_program_.program->native_handle());
419 fidelityfx_pixel_program_.program->end();
431 if(!temporal_resolve_program_.is_valid())
437 auto history_tex = create_or_update_ssr_history_tex(rview, ssr_curr,
settings.enable_half_res);
438 auto temp_fbo = create_or_update_ssr_history_temp_fb(rview, ssr_curr,
settings.enable_half_res);
446 pass.
bind(temp_fbo.get());
450 temporal_resolve_program_.program->begin();
453 gfx::set_texture(temporal_resolve_program_.s_ssr_curr, 0, ssr_curr->get_texture());
455 gfx::set_texture(temporal_resolve_program_.s_normal, 2, g_buffer->get_texture(1));
456 gfx::set_texture(temporal_resolve_program_.s_depth, 3, g_buffer->get_texture(4));
459 float temporal_params[4] = {
settings.enable_temporal_accumulation ? 1.0f : 0.0f,
462 settings.temporal.roughness_sensitivity};
463 gfx::set_uniform(temporal_resolve_program_.u_temporal_params, temporal_params);
466 float motion_params[4] = {
467 settings.temporal.motion_scale_pixels,
468 settings.temporal.normal_dot_threshold,
469 float(
settings.temporal.max_accum_frames),
475 auto history_size = history_tex->get_size();
476 auto g_buffer_size = g_buffer->get_size();
477 float ssr_resolution_scale = float(g_buffer_size.width) / float(history_size.width);
479 float fade_params[4] = {
settings.fade_in_start,
settings.fade_in_end, ssr_resolution_scale, 0.0f};
483 auto prev_view_proj = cam->get_prev_view_projection();
484 gfx::set_uniform(temporal_resolve_program_.u_prev_view_proj, prev_view_proj.get_matrix());
488 gfx::set_state(topology | BGFX_STATE_DEPTH_TEST_NEVER | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A);
489 gfx::submit(pass.
id, temporal_resolve_program_.program->native_handle());
493 temporal_resolve_program_.program->end();
500 gfx::blit(
blit_pass.id, history_tex->native_handle(), 0, 0, temp_fbo->get_texture()->native_handle(), 0, 0);
512 if(!composite_program_.is_valid())
518 auto actual_output = create_or_update_output_fb(rview, g_buffer, output);
526 pass.
bind(actual_output.get());
529 composite_program_.program->begin();
532 gfx::set_texture(composite_program_.s_ssr_history, 0, ssr_history->get_texture());
533 gfx::set_texture(composite_program_.s_ssr_curr, 1, ssr_curr->get_texture());
539 gfx::set_state(topology | BGFX_STATE_DEPTH_TEST_NEVER | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A |
540 BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
541 gfx::submit(pass.
id, composite_program_.program->native_handle());
545 composite_program_.program->end();
548 return actual_output;
std::shared_ptr< frame_buffer > ptr
Manages assets, including loading, unloading, and storage.
auto get_asset(const std::string &key, load_flags flags=load_flags::standard) -> asset_handle< T >
Gets an asset by its key.
Class representing a camera. Contains functionality for manipulating and updating a camera....
auto run_ssr_trace(gfx::render_view &rview, const run_params ¶ms) -> gfx::frame_buffer::ptr
Executes the SSR trace pass only. Returns SSR current frame buffer.
auto generate_blurred_color_buffer(gfx::render_view &rview, const gfx::texture::ptr &input_color, const gfx::frame_buffer::ptr &g_buffer, const fidelityfx_ssr_settings &settings) -> gfx::texture::ptr
Generates blurred color buffer with mip chain for cone tracing.
auto run_fidelityfx(gfx::render_view &rview, const run_params ¶ms) -> gfx::frame_buffer::ptr
Executes the FidelityFX SSR pass. Returns the actual output framebuffer.
auto run_fidelityfx_three_pass(gfx::render_view &rview, const run_params ¶ms) -> gfx::frame_buffer::ptr
Executes the three-pass SSR pipeline (trace, temporal resolve, composite)
auto run_composite(gfx::render_view &rview, const gfx::frame_buffer::ptr &ssr_history, const gfx::frame_buffer::ptr &ssr_curr, const gfx::frame_buffer::ptr &probe_buffer, const gfx::frame_buffer::ptr &g_buffer, const gfx::frame_buffer::ptr &output) -> gfx::frame_buffer::ptr
Executes the composite pass. Returns final blended output.
auto init(rtti::context &ctx) -> bool
Must be called once (after bgfx::init() and after asset_manager is registered in context).
auto run(gfx::render_view &rview, const run_params ¶ms) -> gfx::frame_buffer::ptr
Executes the SSR pass. Returns the actual output framebuffer.
auto run_temporal_resolve(gfx::render_view &rview, const gfx::frame_buffer::ptr &ssr_curr, const gfx::frame_buffer::ptr &g_buffer, const camera *cam, const fidelityfx_ssr_settings &settings) -> gfx::frame_buffer::ptr
Executes the temporal resolve pass. Returns updated SSR history buffer.
void dispatch(view_id _id, program_handle _handle, uint32_t _numX, uint32_t _numY, uint32_t _numZ)
void submit(view_id _id, program_handle _handle, int32_t _depth, bool _preserveState)
void set_state(uint64_t _state, uint32_t _rgba)
void blit(view_id _id, texture_handle _dst, uint16_t _dstX, uint16_t _dstY, texture_handle _src, uint16_t _srcX, uint16_t _srcY, uint16_t _width, uint16_t _height)
void discard(uint8_t _flags)
void set_image(uint8_t _stage, texture_handle _handle, uint8_t _mip, access _access, texture_format _format)
void set_uniform(uniform_handle _handle, const void *_value, uint16_t _num)
uint32_t get_render_frame()
auto clip_quad(float depth, float width, float height) -> uint64_t
void set_texture(uint8_t _stage, uniform_handle _sampler, texture_handle _handle, uint32_t _flags)
#define APP_SCOPE_PERF(name)
Create a scoped performance timer that only accepts string literals.
void set_view_proj(const float *v, const float *p)
void bind(const frame_buffer *fb=nullptr) const