mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 12:09:19 +02:00
131 lines
4.6 KiB
C++
131 lines
4.6 KiB
C++
/*
|
|
This Source Code Form is subject to the
|
|
terms of the Mozilla Public License, v.
|
|
2.0. If a copy of the MPL was not
|
|
distributed with this file, You can
|
|
obtain one at
|
|
http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "rendering/opengl46/opengl46ao.h"
|
|
|
|
#include "model/Texture.h"
|
|
#include "utilities/Globals.h"
|
|
#include "utilities/utilities.h"
|
|
|
|
namespace
|
|
{
|
|
|
|
// work group of the compute passes, 8x8 (gtao_*.comp)
|
|
int const GROUP_SIZE{8};
|
|
|
|
} // namespace
|
|
|
|
void opengl46_ao::init()
|
|
{
|
|
auto const make_compute = [](std::string const &Name) {
|
|
gl::shader shader(Name);
|
|
return std::make_unique<gl::program>(std::vector<std::reference_wrapper<const gl::shader>>{shader});
|
|
};
|
|
m_main_program = make_compute("gtao_main.comp");
|
|
m_denoise_program = make_compute("gtao_denoise.comp");
|
|
{
|
|
gl::shader vertex("quad.vert");
|
|
gl::shader fragment("postfx_ssao_apply.frag");
|
|
m_apply_program = std::make_unique<gl::program>(std::vector<std::reference_wrapper<const gl::shader>>{vertex, fragment});
|
|
}
|
|
m_vao = std::make_unique<gl::vao>();
|
|
}
|
|
|
|
void opengl46_ao::compute(opengl_texture &Depth, opengl_texture &Raw, opengl_texture &Smooth, glm::mat4 const &Projection)
|
|
{
|
|
m_timer.begin();
|
|
m_timing = true;
|
|
|
|
auto const inverseprojection{glm::inverse(Projection)};
|
|
auto const groups_x{static_cast<GLuint>((Raw.get_width() + GROUP_SIZE - 1) / GROUP_SIZE)};
|
|
auto const groups_y{static_cast<GLuint>((Raw.get_height() + GROUP_SIZE - 1) / GROUP_SIZE)};
|
|
|
|
// horizon search
|
|
Depth.bind(0);
|
|
glProgramUniformMatrix4fv(*m_main_program, 0, 1, GL_FALSE, glm::value_ptr(inverseprojection));
|
|
glProgramUniform2f(*m_main_program, 1, Global.gfx_postfx_ao_radius, Projection[0][0] * 0.5f * static_cast<float>(Raw.get_width()));
|
|
glProgramUniform4f(*m_main_program, 2, Projection[0][3], Projection[1][3], Projection[2][3], Projection[3][3]);
|
|
glProgramUniform2i(*m_main_program, 3, Global.gfx_postfx_ao_slices, Global.gfx_postfx_ao_steps);
|
|
glBindImageTexture(0, Raw.id, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R8);
|
|
m_main_program->dispatch(groups_x, groups_y);
|
|
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
|
|
|
|
// smoothing
|
|
Raw.bind(1);
|
|
glProgramUniformMatrix4fv(*m_denoise_program, 0, 1, GL_FALSE, glm::value_ptr(inverseprojection));
|
|
glBindImageTexture(0, Smooth.id, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R8);
|
|
m_denoise_program->dispatch(groups_x, groups_y);
|
|
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
|
|
|
|
glBindImageTexture(0, 0, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R8);
|
|
opengl_texture::reset_unit_cache();
|
|
}
|
|
|
|
void opengl46_ao::apply(int const Mode, opengl_texture &Depth, opengl_texture &Occlusion, gl::framebuffer &Target, glm::mat4 const &Projection)
|
|
{
|
|
Target.bind();
|
|
m_apply_program->bind();
|
|
m_vao->bind();
|
|
Depth.bind(0);
|
|
Occlusion.bind(1);
|
|
glProgramUniformMatrix4fv(*m_apply_program, 0, 1, GL_FALSE, glm::value_ptr(glm::inverse(Projection)));
|
|
glProgramUniform4f(*m_apply_program, 1, (Mode == 1 ? 1.f : 0.f), Global.gfx_postfx_ao_strength, Global.gfx_postfx_ao_bounce, 0.f);
|
|
|
|
// result = image * occlusion; the blending state is put back as it was
|
|
auto const blending{glIsEnabled(GL_BLEND) == GL_TRUE};
|
|
GLint blendfunc[4];
|
|
glGetIntegerv(GL_BLEND_SRC_RGB, &blendfunc[0]);
|
|
glGetIntegerv(GL_BLEND_DST_RGB, &blendfunc[1]);
|
|
glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendfunc[2]);
|
|
glGetIntegerv(GL_BLEND_DST_ALPHA, &blendfunc[3]);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDepthMask(GL_FALSE);
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
glBlendFuncSeparate(blendfunc[0], blendfunc[1], blendfunc[2], blendfunc[3]);
|
|
if (!blending)
|
|
glDisable(GL_BLEND);
|
|
|
|
opengl_texture::reset_unit_cache();
|
|
|
|
if (m_timing)
|
|
{
|
|
m_timer.end();
|
|
m_timing = false;
|
|
}
|
|
}
|
|
|
|
std::string opengl46_ao::info_times()
|
|
{
|
|
std::string text;
|
|
if (auto const time = m_timer.result())
|
|
text += " ambient occlusion: " + to_string(static_cast<double>(*time) / 1000000.0, 3) + " ms\n";
|
|
return text;
|
|
}
|
|
|
|
void opengl46_ao::draw_debug_ui(bool const Available)
|
|
{
|
|
if (!Available)
|
|
{
|
|
ImGui::TextUnformatted("ambient occlusion: off at the start, set gfx.postfx.ao in eu07.ini");
|
|
return;
|
|
}
|
|
char const *modes[]{"off", "older ssao", "ground truth (gtao)"};
|
|
ImGui::Combo("ambient occlusion (gfx.postfx.ao)", &Global.gfx_postfx_ao, modes, IM_ARRAYSIZE(modes));
|
|
if (Global.gfx_postfx_ao != 2)
|
|
return;
|
|
ImGui::SliderFloat("ao radius (m)", &Global.gfx_postfx_ao_radius, 0.1f, 10.f, "%.2f", ImGuiSliderFlags_Logarithmic);
|
|
ImGui::SliderFloat("ao strength", &Global.gfx_postfx_ao_strength, 0.f, 4.f);
|
|
ImGui::SliderFloat("ao bounce albedo", &Global.gfx_postfx_ao_bounce, 0.f, 1.f);
|
|
ImGui::SliderInt("ao slices", &Global.gfx_postfx_ao_slices, 1, 8);
|
|
ImGui::SliderInt("ao steps per side", &Global.gfx_postfx_ao_steps, 1, 16);
|
|
}
|