47 auto cs_shader = am.get_asset<
gfx::shader>(
"engine:/data/shaders/assao/" + cs +
".sc");
49 auto prog = std::make_shared<gpu_program>(cs_shader);
50 m_programs.emplace_back(prog);
55 u_rect = bgfx::createUniform(
"u_rect", bgfx::UniformType::Vec4);
59 s_normal = bgfx::createUniform(
"s_normal", bgfx::UniformType::Sampler);
60 s_depth = bgfx::createUniform(
"s_depth", bgfx::UniformType::Sampler);
63 s_ao = bgfx::createUniform(
"s_ao", bgfx::UniformType::Sampler);
64 s_blurInput = bgfx::createUniform(
"s_blurInput", bgfx::UniformType::Sampler);
65 s_finalSSAO = bgfx::createUniform(
"s_finalSSAO", bgfx::UniformType::Sampler);
66 s_depthSource = bgfx::createUniform(
"s_depthSource", bgfx::UniformType::Sampler);
67 s_viewspaceDepthSource = bgfx::createUniform(
"s_viewspaceDepthSource", bgfx::UniformType::Sampler);
68 s_viewspaceDepthSourceMirror = bgfx::createUniform(
"s_viewspaceDepthSourceMirror", bgfx::UniformType::Sampler);
69 s_importanceMap = bgfx::createUniform(
"s_importanceMap", bgfx::UniformType::Sampler);
75 m_prepareDepthsProgram =
loadProgram(
"cs_assao_prepare_depths");
76 m_prepareDepthsAndNormalsProgram =
loadProgram(
"cs_assao_prepare_depths_and_normals");
77 m_prepareDepthsHalfProgram =
loadProgram(
"cs_assao_prepare_depths_half");
78 m_prepareDepthsAndNormalsHalfProgram =
loadProgram(
"cs_assao_prepare_depths_and_normals_half");
79 m_prepareDepthMipProgram =
loadProgram(
"cs_assao_prepare_depth_mip");
80 m_generateQ0Program =
loadProgram(
"cs_assao_generate_q0");
81 m_generateQ1Program =
loadProgram(
"cs_assao_generate_q1");
82 m_generateQ2Program =
loadProgram(
"cs_assao_generate_q2");
83 m_generateQ3Program =
loadProgram(
"cs_assao_generate_q3");
84 m_generateQ3BaseProgram =
loadProgram(
"cs_assao_generate_q3base");
85 m_generateQ0ProgramRgba16f =
loadProgram(
"cs_assao_generate_q0_normal_rgba16f");
86 m_generateQ1ProgramRgba16f =
loadProgram(
"cs_assao_generate_q1_normal_rgba16f");
87 m_generateQ2ProgramRgba16f =
loadProgram(
"cs_assao_generate_q2_normal_rgba16f");
88 m_generateQ3ProgramRgba16f =
loadProgram(
"cs_assao_generate_q3_normal_rgba16f");
89 m_generateQ3BaseProgramRgba16f =
loadProgram(
"cs_assao_generate_q3base_normal_rgba16f");
90 m_smartBlurProgram =
loadProgram(
"cs_assao_smart_blur");
91 m_smartBlurWideProgram =
loadProgram(
"cs_assao_smart_blur_wide");
92 m_nonSmartBlurProgram =
loadProgram(
"cs_assao_non_smart_blur");
94 m_nonSmartApplyProgram =
loadProgram(
"cs_assao_non_smart_apply");
95 m_nonSmartHalfApplyProgram =
loadProgram(
"cs_assao_non_smart_half_apply");
96 m_generateImportanceMapProgram =
loadProgram(
"cs_assao_generate_importance_map");
97 m_postprocessImportanceMapAProgram =
loadProgram(
"cs_assao_postprocess_importance_map_a");
98 m_postprocessImportanceMapBProgram =
loadProgram(
"cs_assao_postprocess_importance_map_b");
99 m_loadCounterClearProgram =
loadProgram(
"cs_assao_load_counter_clear");
100 m_updateGBufferProgram =
loadProgram(
"cs_assao_update_g_buffer");
103 m_loadCounter = bgfx::createDynamicIndexBuffer(1, BGFX_BUFFER_COMPUTE_READ_WRITE | BGFX_BUFFER_INDEX32);
110 m_settings = params.
params;
117 const int32_t border = 0;
118 dims.size[0] =
width + 2 * border;
119 dims.size[1] =
height + 2 * border;
120 dims.halfSize[0] = (dims.size[0] + 1) / 2;
121 dims.halfSize[1] = (dims.size[1] + 1) / 2;
122 dims.quarterSize[0] = (dims.halfSize[0] + 1) / 2;
123 dims.quarterSize[1] = (dims.halfSize[1] + 1) / 2;
125 vec4iSet(dims.halfResOutScissorRect,
126 dims.fullResOutScissorRect[0] / 2,
127 dims.fullResOutScissorRect[1] / 2,
128 (dims.fullResOutScissorRect[2] + 1) / 2,
129 (dims.fullResOutScissorRect[3] + 1) / 2);
130 const int32_t blurEnlarge =
132 vec4iSet(dims.halfResOutScissorRect,
133 bx::max(0, dims.halfResOutScissorRect[0] - blurEnlarge),
134 bx::max(0, dims.halfResOutScissorRect[1] - blurEnlarge),
135 bx::min(dims.halfSize[0], dims.halfResOutScissorRect[2] + blurEnlarge),
136 bx::min(dims.halfSize[1], dims.halfResOutScissorRect[3] + blurEnlarge));
138 create_or_update_frame_buffers(rview, dims);
140 const float* viewMtx = cam.
get_view();
149 bx::mtxProj(projMtx, fovy,
float(dims.size[0]) /
float(dims.size[1]), n, f,
false);
154 const frect_t rect = {-(float(dims.size[0]) / 2.0f) * zoom,
155 (
float(dims.size[1]) / 2.0f) * zoom,
156 (float(dims.size[0]) / 2.0f) * zoom,
157 -(
float(dims.size[1]) / 2.0f) * zoom};
164 const auto& halfDepths0 = rview.
tex_get(
"ASSAO_HALF_DEPTH_0");
165 const auto& halfDepths1 = rview.
tex_get(
"ASSAO_HALF_DEPTH_1");
166 const auto& halfDepths2 = rview.
tex_get(
"ASSAO_HALF_DEPTH_2");
167 const auto& halfDepths3 = rview.
tex_get(
"ASSAO_HALF_DEPTH_3");
168 const gfx::texture::ptr halfDepthsArr[4] = {halfDepths0, halfDepths1, halfDepths2, halfDepths3};
169 const auto& pingPongA = rview.
tex_get(
"ASSAO_PING_PONG_A");
170 const auto& pingPongB = rview.
tex_get(
"ASSAO_PING_PONG_B");
171 const auto& finalResults = rview.
tex_get(
"ASSAO_FINAL_RESULTS");
172 const auto& normals = rview.
tex_get(
"ASSAO_NORMALS");
173 const auto& importanceMap = rview.
tex_get(
"ASSAO_IMPORTANCE_MAP");
174 const auto& importanceMapPong = rview.
tex_get(
"ASSAO_IMPORTANCE_MAP_PONG");
175 const auto& aoMap = rview.
tex_get(
"ASSAO_AO_MAP");
177 update_uniforms(0, viewMtx, projMtx, dims);
188 bgfx::setImage(5, normals->native_handle(), 0, bgfx::Access::Write);
193 for(int32_t j = 0; j < 2; ++j)
195 bgfx::setImage((uint8_t)(j + 1),
196 (j == 0 ? halfDepths0 : halfDepths3)->native_handle(),
198 bgfx::Access::Write);
203 : m_prepareDepthsHalfProgram,
204 (dims.halfSize[0] + 7) / 8,
205 (dims.halfSize[1] + 7) / 8);
209 bgfx::setImage(1, halfDepths0->native_handle(), 0, bgfx::Access::Write);
210 bgfx::setImage(2, halfDepths1->native_handle(), 0, bgfx::Access::Write);
211 bgfx::setImage(3, halfDepths2->native_handle(), 0, bgfx::Access::Write);
212 bgfx::setImage(4, halfDepths3->native_handle(), 0, bgfx::Access::Write);
215 m_settings.
generate_normals ? m_prepareDepthsAndNormalsProgram : m_prepareDepthsProgram,
216 (dims.halfSize[0] + 7) / 8,
217 (dims.halfSize[1] + 7) / 8);
224 uint16_t mipWidth = (uint16_t)dims.halfSize[0];
225 uint16_t mipHeight = (uint16_t)dims.halfSize[1];
229 mipWidth = (uint16_t)bx::max(1, mipWidth >> 1);
230 mipHeight = (uint16_t)bx::max(1, mipHeight >> 1);
232 bgfx::setImage(0, halfDepths0->native_handle(), i - 1, bgfx::Access::Read);
233 bgfx::setImage(4, halfDepths0->native_handle(), i, bgfx::Access::Write);
234 bgfx::setImage(1, halfDepths1->native_handle(), i - 1, bgfx::Access::Read);
235 bgfx::setImage(5, halfDepths1->native_handle(), i, bgfx::Access::Write);
236 bgfx::setImage(2, halfDepths2->native_handle(), i - 1, bgfx::Access::Read);
237 bgfx::setImage(6, halfDepths2->native_handle(), i, bgfx::Access::Write);
238 bgfx::setImage(3, halfDepths3->native_handle(), i - 1, bgfx::Access::Read);
239 bgfx::setImage(7, halfDepths3->native_handle(), i, bgfx::Access::Write);
242 float rect[4] = {0.0f, 0.0f, (float)mipWidth, (
float)mipHeight};
243 bgfx::setUniform(u_rect,
rect);
245 bgfx::dispatch(
view, m_prepareDepthMipProgram, (mipWidth + 7) / 8, (mipHeight + 7) / 8);
250 for(int32_t ssaoPass = 0; ssaoPass < 2; ++ssaoPass)
259 gfx::render_pass pass(fmt::format(
"ASSAO/Importance Map Pass {}", ssaoPass).c_str());
263 bool adaptiveBasePass = (ssaoPass == 0);
265 BX_UNUSED(adaptiveBasePass);
267 int32_t passCount = 4;
269 int32_t halfResNumX = (dims.halfResOutScissorRect[2] - dims.halfResOutScissorRect[0] + 7) / 8;
270 int32_t halfResNumY = (dims.halfResOutScissorRect[3] - dims.halfResOutScissorRect[1] + 7) / 8;
271 float halfResRect[4] = {(float)dims.halfResOutScissorRect[0],
272 (
float)dims.halfResOutScissorRect[1],
273 (float)dims.halfResOutScissorRect[2],
274 (
float)dims.halfResOutScissorRect[3]};
276 for(int32_t pass = 0; pass < passCount; pass++)
296 blurPasses = bx::max(1, blurPasses);
305 update_uniforms(pass, viewMtx, projMtx, dims);
307 bgfx::TextureHandle pPingRT = pingPongA->native_handle();
308 bgfx::TextureHandle pPongRT = pingPongB->native_handle();
313 blurPasses == 0 ? finalResults->native_handle() : pPingRT,
315 bgfx::Access::Write);
317 bgfx::setUniform(u_rect, halfResRect);
320 s_viewspaceDepthSource,
321 halfDepthsArr[pass]->native_handle(),
324 s_viewspaceDepthSourceMirror,
325 halfDepthsArr[pass]->native_handle(),
329 bgfx::setImage(2, normals->native_handle(), 0, bgfx::Access::Read);
338 bgfx::setBuffer(3, m_loadCounter, bgfx::Access::Read);
340 bgfx::setImage(5, finalResults->native_handle(), 0, bgfx::Access::Read);
343 bgfx::ProgramHandle programsNormal[5] = {m_generateQ0Program,
347 m_generateQ3BaseProgram};
349 bgfx::ProgramHandle programsRgba16f[5] = {m_generateQ0ProgramRgba16f,
350 m_generateQ1ProgramRgba16f,
351 m_generateQ2ProgramRgba16f,
352 m_generateQ3ProgramRgba16f,
353 m_generateQ3BaseProgramRgba16f};
355 bgfx::ProgramHandle* programs = programsNormal;
359 programs = programsRgba16f;
362 int32_t programIndex = bx::max(0, (!adaptiveBasePass) ? (m_settings.
quality_level) : (4));
364 m_uniforms.m_layer = blurPasses == 0 ? (float)pass : 0.0f;
366 bgfx::dispatch(
view, programs[programIndex], halfResNumX, halfResNumY);
372 int32_t wideBlursRemaining = bx::max(0, blurPasses - 2);
374 for(int32_t i = 0; i < blurPasses; i++)
376 bgfx::setViewFrameBuffer(
view, BGFX_INVALID_HANDLE);
379 m_uniforms.m_layer = ((i == (blurPasses - 1)) ? (float)pass : 0.0f);
382 bgfx::setUniform(u_rect, halfResRect);
385 i == (blurPasses - 1) ? finalResults->native_handle() : pPongRT,
387 bgfx::Access::Write);
395 if(wideBlursRemaining > 0)
397 bgfx::dispatch(
view, m_smartBlurWideProgram, halfResNumX, halfResNumY);
398 wideBlursRemaining--;
402 bgfx::dispatch(
view, m_smartBlurProgram, halfResNumX, halfResNumY);
408 m_nonSmartBlurProgram,
413 bgfx::TextureHandle temp = pPingRT;
423 bgfx::setImage(0, importanceMap->native_handle(), 0, bgfx::Access::Write);
426 m_generateImportanceMapProgram,
427 (dims.quarterSize[0] + 7) / 8,
428 (dims.quarterSize[1] + 7) / 8);
431 bgfx::setImage(0, importanceMapPong->native_handle(), 0, bgfx::Access::Write);
432 bgfx::setTexture(1, s_importanceMap, importanceMap->native_handle());
434 m_postprocessImportanceMapAProgram,
435 (dims.quarterSize[0] + 7) / 8,
436 (dims.quarterSize[1] + 7) / 8);
438 bgfx::setBuffer(0, m_loadCounter, bgfx::Access::ReadWrite);
439 bgfx::dispatch(
view, m_loadCounterClearProgram, 1, 1);
442 bgfx::setImage(0, importanceMap->native_handle(), 0, bgfx::Access::Write);
443 bgfx::setTexture(1, s_importanceMap, importanceMapPong->native_handle());
444 bgfx::setBuffer(2, m_loadCounter, bgfx::Access::ReadWrite);
446 m_postprocessImportanceMapBProgram,
447 (dims.quarterSize[0] + 7) / 8,
448 (dims.quarterSize[1] + 7) / 8);
454 bgfx::setImage(0, aoMap->native_handle(), 0, bgfx::Access::Write);
455 bgfx::setTexture(1, s_finalSSAO, finalResults->native_handle());
459 float rect[4] = {(float)dims.fullResOutScissorRect[0],
460 (
float)dims.fullResOutScissorRect[1],
461 (float)dims.fullResOutScissorRect[2],
462 (
float)dims.fullResOutScissorRect[3]};
463 bgfx::setUniform(u_rect,
rect);
465 bgfx::ProgramHandle program;
467 program = m_nonSmartHalfApplyProgram;
469 program = m_nonSmartApplyProgram;
471 program = m_applyProgram;
474 (dims.fullResOutScissorRect[2] - dims.fullResOutScissorRect[0] + 7) / 8,
475 (dims.fullResOutScissorRect[3] - dims.fullResOutScissorRect[1] + 7) / 8);
482 const auto& aoMapTex = rview.
tex_get(
"ASSAO_AO_MAP");
484 bgfx::setImage(1, aoMapTex->native_handle(), 0, bgfx::Access::Read);
486 bgfx::dispatch(pass.
id, m_updateGBufferProgram, (dims.size[0] + 7) / 8, (dims.size[1] + 7) / 8);