mirror of
https://github.com/harfang3d/harfang3d.git
synced 2024-07-16 15:02:19 +00:00
158 lines
6.2 KiB
C++
158 lines
6.2 KiB
C++
// HARFANG(R) Copyright (C) 2021 Emmanuel Julien, NWNC HARFANG. Released under GPL/LGPL/Commercial Licence, see licence.txt for details.
|
|
|
|
#include "engine/sao.h"
|
|
|
|
#include "foundation/file_rw_interface.h"
|
|
#include "foundation/format.h"
|
|
#include "foundation/projection.h"
|
|
#include "foundation/rw_interface.h"
|
|
|
|
#include "engine/assets_rw_interface.h"
|
|
|
|
namespace hg {
|
|
|
|
bool IsValid(const SAO &sao) {
|
|
return bgfx::isValid(sao.compute_fb) && bgfx::isValid(sao.blur_fb) && bgfx::isValid(sao.prg_compute) && bgfx::isValid(sao.prg_blur) &&
|
|
bgfx::isValid(sao.u_attr0) && bgfx::isValid(sao.u_attr1) && bgfx::isValid(sao.u_noise) && bgfx::isValid(sao.u_input) &&
|
|
bgfx::isValid(sao.u_params) && bgfx::isValid(sao.u_projection_infos) && bgfx::isValid(sao.u_sample_count);
|
|
}
|
|
|
|
static void CreateSAOCommon(SAO &sao, const Reader &ir, const ReadProvider &ip, const char *path) {
|
|
sao.u_attr0 = bgfx::createUniform("u_attr0", bgfx::UniformType::Sampler);
|
|
sao.u_attr1 = bgfx::createUniform("u_attr1", bgfx::UniformType::Sampler);
|
|
sao.u_noise = bgfx::createUniform("u_noise", bgfx::UniformType::Sampler);
|
|
sao.u_input = bgfx::createUniform("u_input", bgfx::UniformType::Sampler);
|
|
sao.u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, 2);
|
|
sao.u_projection_infos = bgfx::createUniform("u_projection_infos", bgfx::UniformType::Vec4);
|
|
|
|
sao.prg_compute = LoadProgram(ir, ip, hg::format("%1/shader/sao_compute").arg(path));
|
|
sao.prg_blur = LoadProgram(ir, ip, hg::format("%1/shader/sao_blur").arg(path));
|
|
}
|
|
|
|
static SAO _CreateSAO(const Reader &ir, const ReadProvider &ip, const char *path, bgfx::BackbufferRatio::Enum ratio) {
|
|
SAO sao;
|
|
sao.ratio = ratio;
|
|
|
|
const uint64_t flags = 0 | BGFX_TEXTURE_RT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP;
|
|
|
|
sao.compute_fb = bgfx::createFrameBuffer(ratio, bgfx::TextureFormat::R8, flags);
|
|
sao.blur_fb = bgfx::createFrameBuffer(ratio, bgfx::TextureFormat::R8, flags);
|
|
|
|
CreateSAOCommon(sao, ir, ip, path);
|
|
|
|
if (!IsValid(sao)) {
|
|
DestroySAO(sao);
|
|
return sao;
|
|
}
|
|
|
|
bgfx::setName(sao.compute_fb, "SAO.compute_fb");
|
|
bgfx::setName(sao.blur_fb, "SAO.blur_fb");
|
|
return sao;
|
|
}
|
|
|
|
SAO CreateSAOFromFile(const char *path, bgfx::BackbufferRatio::Enum ratio) {
|
|
return _CreateSAO(g_file_reader, g_file_read_provider, path, ratio);
|
|
}
|
|
SAO CreateSAOFromAssets(const char *path, bgfx::BackbufferRatio::Enum ratio) {
|
|
return _CreateSAO(g_assets_reader, g_assets_read_provider, path, ratio);
|
|
}
|
|
|
|
void DestroySAO(SAO &sao) {
|
|
bgfx_Destroy(sao.compute_fb);
|
|
bgfx_Destroy(sao.blur_fb);
|
|
|
|
bgfx_Destroy(sao.u_attr0);
|
|
bgfx_Destroy(sao.u_attr1);
|
|
bgfx_Destroy(sao.u_noise);
|
|
bgfx_Destroy(sao.u_input);
|
|
bgfx_Destroy(sao.u_params);
|
|
bgfx_Destroy(sao.u_projection_infos);
|
|
|
|
bgfx_Destroy(sao.prg_compute);
|
|
bgfx_Destroy(sao.prg_blur);
|
|
}
|
|
|
|
void ComputeSAO(bgfx::ViewId &view_id, const iRect &rect, const Texture &attr0, const Texture &attr1, const Texture &noise, bgfx::FrameBufferHandle output, const SAO &sao,
|
|
const Mat44 &projection, float bias, float radius, int sample_count, float sharpness) {
|
|
__ASSERT__(IsValid(sao));
|
|
|
|
const bgfx::Caps *caps = bgfx::getCaps();
|
|
|
|
bgfx::TransientIndexBuffer idx;
|
|
bgfx::TransientVertexBuffer vtx;
|
|
CreateFullscreenQuad(idx, vtx);
|
|
|
|
float projection_infos[4] = {1.f / projection.m[0][0], 1.f / projection.m[1][1], projection.m[2][2], projection.m[2][3]};
|
|
|
|
float ortho[16];
|
|
memcpy(ortho, hg::to_bgfx(hg::Compute2DProjectionMatrix(0.f, 100.f, 1.f, 1.f, false)).data(), sizeof(float[16]));
|
|
|
|
float params[4];
|
|
memset(¶ms, 0, sizeof(float[4]));
|
|
params[0] = radius;
|
|
params[1] = GetHeight(rect) / (4.f * projection.m[1][1]);
|
|
params[2] = bias;
|
|
params[3] = sample_count;
|
|
|
|
// sao compute
|
|
bgfx::setViewName(view_id, "SAO compute");
|
|
bgfx::setViewRect(view_id, rect.sx, rect.sy, GetWidth(rect), GetHeight(rect));
|
|
bgfx::setViewFrameBuffer(view_id, sao.compute_fb);
|
|
bgfx::setViewTransform(view_id, NULL, ortho);
|
|
bgfx::setViewClear(view_id, BGFX_CLEAR_NONE, 0, 1.f, UINT8_MAX);
|
|
|
|
bgfx::setUniform(sao.u_params, ¶ms, 1);
|
|
bgfx::setUniform(sao.u_projection_infos, &projection_infos[0], 1);
|
|
bgfx::setTexture(0, sao.u_attr0, attr0.handle, uint32_t(attr0.flags));
|
|
bgfx::setTexture(1, sao.u_attr1, attr1.handle, uint32_t(attr1.flags));
|
|
bgfx::setTexture(2, sao.u_noise, noise.handle, uint32_t(noise.flags));
|
|
|
|
bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_DEPTH_TEST_ALWAYS);
|
|
bgfx::setIndexBuffer(&idx);
|
|
bgfx::setVertexBuffer(0, &vtx);
|
|
bgfx::submit(view_id, sao.prg_compute);
|
|
view_id++;
|
|
/*
|
|
if (sao.blur) {
|
|
// sao blur (horizontal)
|
|
bgfx::setViewName(view_id, "SAO horizontal blur");
|
|
bgfx::setViewRect(view_id, 0, 0, width, height);
|
|
bgfx::setViewFrameBuffer(view_id, sao.blur_fb);
|
|
bgfx::setViewTransform(view_id, NULL, ortho);
|
|
bgfx::setViewClear(view_id, BGFX_CLEAR_NONE, 0, 1.f, UINT8_MAX);
|
|
params.dx = 1.f / (float)width;
|
|
params.dy = 0.f;
|
|
params.spharpness = sharpness;
|
|
bgfx::setUniform(sao.u_params, ¶ms, 2);
|
|
bgfx::setUniform(sao.u_projection_infos, &projection_infos[0], 1);
|
|
bgfx::setTexture(0, sao.u_depth, bgfx::getTexture(sao.compute_fb), BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
|
|
bgfx::setTexture(1, sao.u_input, depth.handle, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
|
|
bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_DEPTH_TEST_ALWAYS);
|
|
bgfx::setIndexBuffer(&idx);
|
|
bgfx::setVertexBuffer(0, &vtx);
|
|
bgfx::submit(view_id, sao.prg_blur);
|
|
view_id++;
|
|
|
|
// sao blur (vertical)
|
|
bgfx::setViewName(view_id, "SAO vertical blur");
|
|
bgfx::setViewRect(view_id, 0, 0, width, height);
|
|
bgfx::setViewFrameBuffer(view_id, output);
|
|
bgfx::setViewTransform(view_id, NULL, ortho);
|
|
bgfx::setViewClear(view_id, BGFX_CLEAR_NONE, 0, 1.f, UINT8_MAX);
|
|
params.dx = 0.f;
|
|
params.dy = 1.f / (float)height;
|
|
bgfx::setUniform(sao.u_params, ¶ms, 2);
|
|
bgfx::setUniform(sao.u_projection_infos, &projection_infos[0], 1);
|
|
bgfx::setTexture(0, sao.u_depth, bgfx::getTexture(sao.blur_fb), BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
|
|
bgfx::setTexture(1, sao.u_input, depth.handle, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
|
|
bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_DEPTH_TEST_ALWAYS);
|
|
bgfx::setIndexBuffer(&idx);
|
|
bgfx::setVertexBuffer(0, &vtx);
|
|
bgfx::submit(view_id, sao.prg_blur);
|
|
view_id++;
|
|
}
|
|
*/
|
|
}
|
|
|
|
} // namespace hg
|