File Renderer.cpp
File List > render > Renderer.cpp
Go to the documentation of this file
#include "Renderer.h"
#include "SDFField.h"
#include "SceneManager.h"
#include "Input.h"
#include "shaders/ComputeShader.h"
#include "xdz_math.h"
#include "events/EditorEvents.h"
#include "../app/Window.h"
GLint Renderer::max_resolution_w = 0;
GLint Renderer::max_resolution_h = 0;
Renderer::Renderer(EventPool& evt, [[maybe_unused]] Window& w)
:r_frame_width(SCREEN_W), r_frame_height(SCREEN_H)
{
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
std::cout << "glew error" << std::endl;
else
std::cout << "glew has no error" << std::endl;
if (glGetError() != GL_NO_ERROR)
std::cout << "OpenGL Error: " << glGetError() << std::endl;
else
std::cout << "OpenGL has no error " << std::endl;
DEBUG("Renderer Open");
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
glEnable(GL_MULTISAMPLE);
/* Stencil buffer (currently disabled). */
// glEnable(GL_STENCIL_TEST);
// glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
// glStencilFunc(GL_ALWAYS, 1, 0xff);
// glStencilMask(0xff);
/* Convolution (currently disabled). */
// glEnable(GL_CONVOLUTION_2D);
InitFrameBuffer();
r_shadow_system.Init();
ComputeShader::InitComputeLib(GetConfig());
r_shadow_system.EnableShadowMap();
glGetIntegerv(GL_MAX_FRAMEBUFFER_WIDTH, &max_resolution_w);
glGetIntegerv(GL_MAX_FRAMEBUFFER_HEIGHT, &max_resolution_h);
// TODO: move this to editor layer
evt.subscribe<RenderSurfaceResizedEvent>([this](const RenderSurfaceResizedEvent& e) {
this->FrameResize(e.width, e.height );
});
}
Renderer::~Renderer()
{}
void Renderer::InitFrameBuffer()
{
r_render_result = std::make_shared<FrameBuffer>(std::vector<FBType>RESULT_PASSES);
r_buffer_list.emplace_back(std::vector<FBType>AVAIL_PASSES);
r_buffer_list.emplace_back(std::vector<FBType>{ LIGHT_AO_FB, POS_B_FB, OPT_FLW_FB });
}
void Renderer::BindFrameBuffer(int slot)
{
r_buffer_list[slot].BindFrameBuffer();
}
void Renderer::EndFrameBuffer(int slot)
{
r_buffer_list[slot].UnbindFrameBuffer();
}
void Renderer::FrameBufferResize(const glm::vec2& size)
{
for (auto& buffer : r_buffer_list)
buffer.Resize(size);
r_render_result->Resize(size);
}
void Renderer::NewFrame()
{
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glViewport(0, 0, r_frame_width, r_frame_height);
}
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
void RenderShadowMap(Light* light, ShadowSystem& shadow_sys, Scene::ResPool<Mesh> mesh_list, const RenderConfigs& config)
{
/* TODO: not necessary for every frame update. */
Texture& shadow_map = shadow_sys.shadow_maps[light->GetObjectID()];
const glm::mat4& proj = shadow_sys.proj_matrices[light->GetObjectID()];
const GLuint map_w = shadow_map.GetW();
const GLuint map_h = shadow_map.GetH();
glViewport(0, 0, map_w, map_h);
shadow_sys.BindShadowMapBuffer(light, shadow_map);
shadow_sys.BindShadowMapShader(light, proj);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
for (const auto& [id, mesh] : mesh_list)
{
if (!mesh->using_shadow) continue;
if (!mesh->is_viewport) continue;
shadow_sys.BindTargetTrans(light, mesh->o_Transform);
mesh->RenderObjProxy();
}
FrameBuffer::UnbindFrameBuffer();
if (config.RequiresMomentShadow()) {
shadow_sys.ConstructSAT(light, &config);
}
}
void Renderer::Render(const Context& ctx, bool rend, bool buff) {
/* Check at least one camera and environment */
Scene* scene = dynamic_cast<Scene*>(ctx.scene.active_scene);
if (scene->cam_list.find(0) == scene->cam_list.end()) assert(false && "NONE ACTIVE CAMERA");
if (scene->envir_list.find(0) == scene->envir_list.end()) assert(false && "NONE ACTIVE ENVIRONMENT");
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
const Camera* cam = scene->GetActiveCamera();
glm::mat4 proj_trans_b = cam->cam_frustum * cam->o_InvTransform;
scene->UpdateObjTransforms();
if (scene->CheckStatus(Scene::SceneChanged) && r_config.r_sampling_average == RenderConfigs::SamplingType::Average)
r_sample_step = 1;
if (r_config.RequiresFwdOF())
{
ComputeShader& of = ComputeShader::ImportShader("Optical_Flow");
r_buffer_list[_AO_ELS].BindFrameBufferTexR(POS_B_FB, 0);
r_buffer_list[_AO_ELS].BindFrameBufferTexR(OPT_FLW_FB, 1);
of.UseShader();
of.SetValue("proj_trans", cam->cam_frustum * cam->o_InvTransform);
of.RunComputeShaderSCR(r_render_result->GetSize(), 16);
}
const bool requires_sdf = r_config.RequiresSDF();
const bool realtime_sdf = (!scene->CheckStatus(Scene::ObjectTransChanged)) || r_config.r_sampling_average == RenderConfigs::SamplingType::Average;
if (requires_sdf && scene->CheckStatus(Scene::SDFChanged) && realtime_sdf)
ConstructSDF(ctx);
for (auto& [id, light] : scene->light_list) {
if (!light->is_viewport) continue;
if (light->is_light_changed || light->is_Uniform_changed)
r_shadow_system.UpdateLight(light.get());
if (light->is_Uniform_changed)
r_shadow_system.UpdateProjMatrix(light.get());
if (light->is_light_changed || scene->CheckStatus(Scene::ObjectTransChanged))
RenderShadowMap(light.get(), r_shadow_system, scene->mesh_list, r_config);
}
if (buff) {
//GetActiveEnvironment()->BindFrameBuffer();
r_buffer_list[_RASTER].BindFrameBuffer();
}
NewFrame();
if (rend) {
//glEnable(GL_STENCIL_TEST);
;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
Environment* env = scene->GetActiveEnvironment();
env->RenderEnvironment(ctx);
glEnable(GL_DEPTH_TEST);
env->BindEnvironTexture();
scene->sdf_field->Bind();
for (const auto& [id, mesh] : scene->mesh_list)
{
if (!mesh->is_viewport)continue;
mesh->RenderMesh(ctx);
}
for (const auto& [id, polyLight] : scene->poly_light_list)
{
if (!polyLight->is_viewport)continue;
polyLight->RenderPolygon(ctx);
if (polyLight->is_Uniform_changed)
r_shadow_system.ParsePolygonLightData(scene->poly_light_list);
}
for (const auto& [id, dLine] : scene->dLine_list)
{
if (!dLine->is_viewport)continue;
dLine->RenderDdbugLine(ctx);
}
for (const auto& [id, dPoints] : scene->dPoints_list)
{
if (!dPoints->is_viewport)continue;
dPoints->RenderDebugPoint(ctx);
}
if (r_render_icons) {
glEnable(GL_BLEND);
for (const auto& [id, light] : scene->light_list)
{
if (!light->light_sprite.is_viewport)continue;
light->RenderLightSpr(ctx);
}
for (const auto& [id, envir] : scene->envir_list) {
if (!envir->envir_sprite.is_viewport)continue;
envir->RenderEnvirSpr(ctx);
}
for (const auto& pps : scene->pps_list) {
if (!pps->pps_sprite.is_viewport)continue;
pps->RenderPPSSpr(ctx);
}
}
}
if (buff) {
//GetActiveEnvironment()->UnbindFrameBuffer();
r_buffer_list[_RASTER].UnbindFrameBuffer();
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//GetActiveEnvironment()->envir_frameBuffer->BindFrameBufferTex(AVAIL_PASSES);
if (r_is_preview) {
ComputeShader& outline = ComputeShader::ImportShader("selection_outline");
r_buffer_list[_RASTER].BindFrameBufferTexR(MASK_FB, 0);
if (ctx.editor.selections.GetSelectedObjects() != nullptr)
outline.RunComputeShaderSCR(r_buffer_list[_RASTER].GetSize(), 16);
}
if (r_config.RequiresBwdOF())
{
ComputeShader& of_b = ComputeShader::ImportShader("Optical_Flow_Back");
r_buffer_list[_RASTER].BindFrameBufferTexR(POS_FB, 0);
r_buffer_list[_AO_ELS].BindFrameBufferTexR(OPT_FLW_FB, 1);
of_b.UseShader();
of_b.SetValue("proj_trans_b", proj_trans_b);
of_b.RunComputeShaderSCR(r_render_result->GetSize(), 16);
}
ComputeShader& ssao = ComputeShader::ImportShader(ComputeShader::GetAOShaderName(GetConfig()));
float ao_update_rate = r_config.r_sampling_average == RenderConfigs::SamplingType::IncrementAverage ? 0.05f : 1.0f / r_sample_step;
r_buffer_list[_AO_ELS].BindFrameBufferTex(OPT_FLW_FB, 1);
r_buffer_list[_AO_ELS].BindFrameBufferTexR(POS_B_FB, 2);
r_buffer_list[_RASTER].BindFrameBufferTexR(POS_FB, 3);
r_buffer_list[_RASTER].BindFrameBufferTexR(NORMAL_FB, 4);
r_buffer_list[_RASTER].BindFrameBufferTexR(MASK_FB, 5);
r_buffer_list[_AO_ELS].BindFrameBufferTexR(LIGHT_AO_FB, 6);
TextureLib::Noise_2D_16x16xN()->BindC(7);
ssao.UseShader();
if (cam->is_Uniform_changed) {
ssao.SetValue("Cam_pos", cam->o_position);
ssao.SetValue("Proj_Trans", cam->cam_frustum * cam->o_InvTransform);
}
ssao.SetValue("update_rate", ao_update_rate);
ssao.SetValue("noise_level", r_sample_step % 6);
ssao.RunComputeShaderSCR(r_render_result->GetSize(), 16);
const float shadow_update_rate = r_config.r_sampling_average == RenderConfigs::SamplingType::IncrementAverage ? 0 : 1.0f / r_sample_step;
r_buffer_list[_RASTER].BindFrameBufferTexR(NORMAL_FB, 2);
r_buffer_list[_RASTER].BindFrameBufferTexR(POS_FB, 3);
r_buffer_list[_RASTER].BindFrameBufferTexR(MASK_FB, 5);
r_buffer_list[_AO_ELS].BindFrameBufferTex(OPT_FLW_FB, 6);
if (r_config.RequiresSDF()) scene->sdf_field->Bind();
r_shadow_system.Update(r_sample_step, GetConfig());
//r_buffer_list[_RASTER].BindFrameBufferTex(AVAIL_PASSES);
scene->pps_list[_PBR_COMP_PPS]->SetShaderValue("point_far", Light::point_shaodow_far);
scene->pps_list[_PBR_COMP_PPS]->SetShaderValue("U_Shadow", r_shadow_system.GetTotalCount(), ShadowSystem::shadow_slot, VEC1_ARRAY);
r_buffer_list[_RASTER].BindFrameBufferTex(AVAIL_PASSES);
TextureLib::LTC1()->Bind(13);
TextureLib::LTC2()->Bind(14);
r_shadow_system.Bind();
r_buffer_list[_RASTER].BindFrameBufferTex(POS_FB, Texture::BUFFER_TEXTURE + POS_FB);
r_buffer_list[_RASTER].BindFrameBufferTex(NORMAL_FB, Texture::BUFFER_TEXTURE + NORMAL_FB);
r_buffer_list[_RASTER].BindFrameBufferTex(ALBEDO_FB, Texture::BUFFER_TEXTURE + ALBEDO_FB);
r_buffer_list[_RASTER].BindFrameBufferTex(MRSE_FB, Texture::BUFFER_TEXTURE + MRSE_FB);
r_buffer_list[_RASTER].BindFrameBufferTex(MASK_FB, Texture::BUFFER_TEXTURE + MASK_FB);
r_buffer_list[_RASTER].BindFrameBufferTex(EMIS_COL_FB, Texture::BUFFER_TEXTURE + EMIS_COL_FB);
r_render_result->BindFrameBufferTexR(COMBINE_FB, 0);
r_render_result->BindFrameBufferTexR(DIR_DIFF_FB, 1);
r_render_result->BindFrameBufferTexR(DIR_SPEC_FB, 2);
r_render_result->BindFrameBufferTexR(IND_DIFF_FB, 3);
r_render_result->BindFrameBufferTexR(IND_SPEC_FB, 4);
r_render_result->BindFrameBufferTexR(DIR_EMIS_FB, 5);
r_buffer_list[_RASTER].BindFrameBufferTexR(MASK_FB, 7);
scene->pps_list[_PBR_COMP_PPS]->SetShaderValue("Cam_pos", cam->o_position);
r_render_result->BindFrameBuffer();
scene->pps_list[_PBR_COMP_PPS]->RenderPPS(r_render_result->GetSize(), 16);
r_render_result->UnbindFrameBuffer();
if (r_config.RequiresSSR()) {
static std::vector<glm::vec3> noise = xdzm::rand3nv(32);
ComputeShader& ssr = ComputeShader::ImportShader(ComputeShader::GetSSRShaderName(GetConfig()));
r_render_result->BindFrameBufferTexR(COMBINE_FB, 0);
r_buffer_list[_RASTER].BindFrameBufferTex(POS_FB, 1);
r_buffer_list[_RASTER].BindFrameBufferTexR(NORMAL_FB, 2);
r_buffer_list[_RASTER].BindFrameBufferTexR(MRSE_FB, 3);
r_buffer_list[_RASTER].BindFrameBufferTexR(ALBEDO_FB, 4);
r_buffer_list[_RASTER].BindFrameBufferTexR(MASK_FB, 5);
r_buffer_list[_AO_ELS].BindFrameBufferTex(LIGHT_AO_FB, 6);
r_render_result->BindFrameBufferTex(DIR_DIFF_FB, 7);
r_render_result->BindFrameBufferTex(DIR_SPEC_FB, 8);
r_render_result->BindFrameBufferTex(IND_DIFF_FB, 9);
r_render_result->BindFrameBufferTex(IND_SPEC_FB, 10);
r_render_result->BindFrameBufferTex(DIR_EMIS_FB, 11);
scene->sdf_field->Bind();
ssr.UseShader();
ssr.SetValue("use_incr_aver", (bool)r_config.r_sampling_average);
ssr.SetValue("std_ud_rate", 1.0f / r_sample_step);
ssr.SetValue("cam_pos", cam->o_position);
ssr.SetValue("cam_trans", cam->cam_frustum * cam->o_InvTransform);
ssr.SetValue("noise", Input::GetRandomState().random_float1);
ssr.RunComputeShaderSCR(r_render_result->GetSize(), 16);
}
if (r_config.RequiresFXAA()) {
ComputeShader& fxaa = ComputeShader::ImportShader(ComputeShader::GetAAShaderName(GetConfig()));
r_render_result->BindFrameBufferTexR(COMBINE_FB, 0);
r_buffer_list[_RASTER].BindFrameBufferTexR(RAND_FB, 1);
r_buffer_list[_RASTER].BindFrameBufferTexR(NORMAL_FB, 2);
r_buffer_list[_RASTER].BindFrameBufferTexR(MASK_FB, 3);
fxaa.RunComputeShaderSCR(r_render_result->GetSize(), 16);
}
ComputeShader& tone = ComputeShader::ImportShader("pps/Compose", Uni("U_debugt", 3));
r_render_result->BindFrameBufferTexR(COMBINE_FB, 0);
r_buffer_list[_RASTER].BindFrameBufferTexR(MASK_FB, 1);
//r_buffer_list[_RASTER].BindFrameBufferTexR(RAND_FB, 3);
//r_render_result->BindFrameBufferTexR(DIR_DIFF_FB, 2);
//r_buffer_list[_RASTER].BindFrameBufferTex(MASK_FB, 1);
tone.UseShader();
tone.SetValue("gamma", r_config.r_gamma);
tone.RunComputeShaderSCR(r_render_result->GetSize(), 8);
if (r_is_preview)
{
ComputeShader& editing = ComputeShader::ImportShader("pps/Editing");
r_render_result->BindFrameBufferTexR(COMBINE_FB, 0);
r_buffer_list[_RASTER].BindFrameBufferTexR(MASK_FB, 1);
editing.RunComputeShaderSCR(r_render_result->GetSize(), 16);
}
}
r_sample_step++;
}
void Renderer::ConstructSDF(const Context& ctx)
{
Scene* scene = dynamic_cast<Scene*>(ctx.scene.active_scene);
scene->sdf_field->Bind();
scene->sdf_field->ResetDistance();
scene->sdf_field->BindShader();
for (const auto& [id, mesh] : scene->mesh_list)
{
if (!mesh->using_sdf) continue;
if (!mesh->is_viewport) continue;
scene->sdf_field->BindTargetTrans(mesh->o_Transform, mesh->is_closure);
mesh->RenderObjProxy(false);
}
scene->SetSceneStatus(Scene::SDFChanged, false);
scene->sdf_field->Unbind();
scene->sdf_field->UnbindShader();
}
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
//++++++++ ++++++++++//
void Renderer::Reset()
{
}
void Renderer::FrameResize(GLuint _w, GLuint _h)
{
r_frame_width = _w;
r_frame_height = _h;
FrameBufferResize({ (float)_w, (float)_h });
r_shadow_system.Resize(_w, _h);
}
void Renderer::ScreenShot()
{
std::string name = "result""-" + std::to_string(Input::GetRandomState().random_float1);
DEBUG("saving to: " + name);
r_render_result->GetFBTexturePtr(COMBINE_FB)->SaveTexture(name, true);
}