harfang3d/harfang/engine/sao.cpp
2021-12-15 20:23:12 +01:00

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(&params, 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, &params, 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, &params, 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, &params, 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