Files
korenkonder_ReDIVA/src/CRE/render_manager.cpp
T
2023-10-08 19:38:33 +03:00

1586 lines
62 KiB
C++

/*
by korenkonder
GitHub/GitLab: korenkonder
*/
#include "render_manager.hpp"
#include "../KKdLib/mat.hpp"
#include "Glitter/glitter.hpp"
#include "light_param/fog.hpp"
#include "light_param/light.hpp"
#include "rob/rob.hpp"
#include "clear_color.hpp"
#include "gl_state.hpp"
#include "post_process.hpp"
#include "render_texture.hpp"
#include "shader_ft.hpp"
#include "sprite.hpp"
#include "static_var.hpp"
#include "task_effect.hpp"
#include "texture.hpp"
static void blur_filter_apply(render_context* rctx, GLuint tex_0, GLuint tex_1,
blur_filter_mode filter, const vec2 res_scale, const vec4 scale, const vec4 offset);
static void draw_pass_shadow_begin_make_shadowmap(render_context* rctx,
Shadow* shad, int32_t index, int32_t a3);
static void draw_pass_shadow_end_make_shadowmap(render_context* rctx,
Shadow* shad, int32_t index, int32_t a3);
static void draw_pass_shadow_filter(render_context* rctx, RenderTexture* a1, RenderTexture* a2,
RenderTexture* a3, float_t sigma, float_t far_texel_offset, bool enable_lit_proj);
static void draw_pass_shadow_esm_filter(render_context* rctx,
RenderTexture* dst, RenderTexture* buf, RenderTexture* src);
static bool draw_pass_shadow_litproj(render_context* rctx, light_proj* litproj);
static void draw_pass_sss_contour(render_context* rctx, post_process* pp);
static void draw_pass_sss_filter(render_context* rctx, sss_data* sss);
static int32_t draw_pass_3d_get_translucent_count(render_context* rctx);
static void draw_pass_3d_shadow_reset(render_context* rctx);
static void draw_pass_3d_shadow_set(Shadow* shad, render_context* rctx);
extern void draw_pass_3d_translucent(render_context* rctx, bool opaque_enable,
bool transparent_enable, bool translucent_enable, mdl::ObjType opaque,
mdl::ObjType transparent, mdl::ObjType translucent);
static int32_t draw_pass_3d_translucent_count_layers(render_context* rctx,
int32_t* alpha_array, mdl::ObjType opaque,
mdl::ObjType transparent, mdl::ObjType translucent);
static void draw_pass_3d_translucent_has_objects(render_context* rctx, bool* arr, mdl::ObjType type);
extern bool draw_grid_3d;
extern void draw_pass_3d_grid(render_context* rctx);
extern light_param_data_storage* light_param_data_storage_data;
namespace rndr {
void RenderManager::render_all(render_context* rctx) {
static const int32_t ibl_texture_index[] = {
9, 10, 11, 12, 13
};
camera* cam = rctx->camera;
for (int32_t i = 0; i < 5; i++)
gl_state_active_bind_texture_cube_map(ibl_texture_index[i],
light_param_data_storage_data->textures[i]);
rctx->obj_scene.g_framebuffer_size = {
1.0f / (float_t)rctx->post_process.render_width,
1.0f / (float_t)rctx->post_process.render_height,
(float_t)rctx->post_process.render_width,
(float_t)rctx->post_process.render_height
};
gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
gl_state_enable_depth_test();
gl_state_set_depth_func(GL_LEQUAL);
gl_state_set_depth_mask(GL_TRUE);
gl_state_begin_event("rndpass_render_all_pass::Caller::execute_pre3d");
for (int32_t i = RND_PASSID_SHADOW; i <= RND_PASSID_CLEAR; i++)
RenderManager::render_single_pass((RenderPassID)i, rctx);
gl_state_end_event();
gl_state_begin_event("rndpass_render_all_pass::Caller::execute_3d");
for (int32_t i = RND_PASSID_PRE_SPRITE; i <= RND_PASSID_3D; i++)
RenderManager::render_single_pass((RenderPassID)i, rctx);
gl_state_end_event();
gl_state_begin_event("rndpass_render_all_pass::Caller::execute_2d");
for (int32_t i = RND_PASSID_SHOW_VECTOR; i <= RND_PASSID_12; i++)
RenderManager::render_single_pass((RenderPassID)i, rctx);
gl_state_end_event();
rctx->disp_manager.check_vertex_arrays();
gl_state_bind_vertex_array(0);
gl_state_disable_primitive_restart();
gl_state_bind_uniform_buffer_base(0, 0);
gl_state_bind_uniform_buffer_base(1, 0);
gl_state_bind_uniform_buffer_base(2, 0);
gl_state_bind_uniform_buffer_base(3, 0);
gl_state_bind_uniform_buffer_base(4, 0);
}
void RenderManager::render_single_pass(RenderPassID id, render_context* rctx) {
cpu_time[id] = 0.0;
gpu_time[id] = 0.0;
if (!pass_sw[id]) {
gl_state_get_error();
return;
}
render_pass_begin();
switch (id) {
case RND_PASSID_SHADOW:
pass_shadow(rctx);
break;
case RND_PASSID_SS_SSS:
pass_ss_sss(rctx);
break;
case RND_PASSID_REFLECT:
pass_reflect(rctx);
break;
case RND_PASSID_REFRACT:
pass_refract(rctx);
break;
case RND_PASSID_PRE_PROCESS:
pass_pre_process(rctx);
break;
case RND_PASSID_CLEAR:
pass_clear(rctx);
break;
case RND_PASSID_PRE_SPRITE:
pass_pre_sprite(rctx);
break;
case RND_PASSID_3D:
pass_3d(rctx);
break;
case RND_PASSID_SHOW_VECTOR:
pass_show_vector(rctx);
break;
case RND_PASSID_POST_PROCESS:
pass_post_process(rctx);
break;
case RND_PASSID_SPRITE:
pass_sprite(rctx);
break;
}
render_pass_end(id);
gl_state_get_error();
}
void RenderManager::render_pass_begin() {
if (sync_gpu)
glFinish();
time.get_timestamp();
}
void RenderManager::render_pass_end(RenderPassID id) {
cpu_time[id] = time.calc_time();
if (sync_gpu) {
time_struct t;
glFinish();
gpu_time[id] = t.calc_time();
}
else
gpu_time[id] = 0;
}
void RenderManager::pass_shadow(render_context* rctx) {
gl_state_begin_event("pass_shadow");
rctx->camera->update_data();
if (rctx->litproj->set(rctx)) {
rctx->obj_scene_ubo.WriteMemory(rctx->obj_scene);
rctx->disp_manager.draw(mdl::OBJ_TYPE_OPAQUE);
rctx->disp_manager.draw(mdl::OBJ_TYPE_TRANSPARENT);
rctx->disp_manager.draw(mdl::OBJ_TYPE_TRANSLUCENT);
rctx->draw_state.shader_index = -1;
uniform_value[U0A] = 0;
draw_pass_shadow_filter(rctx, &rctx->litproj->shadow_texture[0],
&rctx->litproj->shadow_texture[1], 0, 1.5f, 0.01f, true);
if (draw_pass_shadow_litproj(rctx, rctx->litproj)) {
draw_pass_set_camera(rctx);
for (int32_t i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++)
rctx->light_set[i].data_set(rctx->face, (light_set_id)i);
rctx->obj_scene_ubo.WriteMemory(rctx->obj_scene);
rctx->disp_manager.draw(mdl::OBJ_TYPE_OPAQUE);
rctx->disp_manager.draw(mdl::OBJ_TYPE_TRANSPARENT);
rctx->disp_manager.obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_TRANSLUCENT, 1);
gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_state_enable_blend();
rctx->disp_manager.draw(mdl::OBJ_TYPE_TRANSLUCENT);
gl_state_disable_blend();
rctx->draw_state.shader_index = -1;
gl_state_bind_framebuffer(0);
}
}
rctx->obj_scene_ubo.WriteMemory(rctx->obj_scene);
bool v3 = false;
int32_t v10[2];
for (int32_t i = 0; i < 2; i++) {
v10[i] = rctx->disp_manager.get_obj_count((mdl::ObjType)(mdl::OBJ_TYPE_SHADOW_CHARA + i));
if (v10[i])
v3 = true;
}
Shadow* shad = shadow_ptr;
if (shadow && v3) {
int32_t v11[2];
v11[0] = shad->field_200[0];
v11[1] = shad->field_200[1];
shad->curr_render_textures[0] = &shad->render_textures[0];
shad->curr_render_textures[1] = &shad->render_textures[1];
shad->curr_render_textures[2] = &shad->render_textures[2];
shad->curr_render_textures[3] = &shad->render_textures[7]; // Extra for buf
for (int32_t i = 0, j = 0; i < 2; i++) {
if (!v10[i])
continue;
draw_pass_shadow_begin_make_shadowmap(rctx, shad, v11[i], j);
rctx->disp_manager.draw((mdl::ObjType)(mdl::OBJ_TYPE_SHADOW_CHARA + v11[i]));
if (rctx->disp_manager.get_obj_count((mdl::ObjType)(mdl::OBJ_TYPE_SHADOW_OBJECT_CHARA + v11[i])) > 0) {
gl_state_set_color_mask(field_2F8 ? GL_TRUE : GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
rctx->disp_manager.draw((mdl::ObjType)(mdl::OBJ_TYPE_SHADOW_OBJECT_CHARA + i));
gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
draw_pass_shadow_end_make_shadowmap(rctx, shad, v11[i], j);
j++;
}
}
else {
shad->curr_render_textures[0] = &shad->render_textures[0];
shad->curr_render_textures[1] = &shad->render_textures[1];
shad->curr_render_textures[2] = &shad->render_textures[2];
shad->curr_render_textures[3] = &shad->render_textures[7]; // Extra for buf
for (int32_t i = 1; i < 3; i++)
for (int32_t j = 0; j < 4; j++) {
shad->curr_render_textures[i]->Bind(j);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
}
gl_state_bind_framebuffer(0);
gl_state_end_event();
}
void RenderManager::pass_ss_sss(render_context* rctx) {
::sss_data* sss = &sss_data;
if (!sss->init || !sss->enable)
return;
gl_state_begin_event("pass_ss_sss");
rctx->camera->update_data();
post_process* pp = &rctx->post_process;
//if (pp->render_width > 1280.0)
// sss->npr_contour = false;
//if (sss->npr_contour) {
pp->rend_texture.Bind();
glViewport(0, 0, pp->render_width, pp->render_height);
//}
//else {
// sss->textures[0].Bind();
// glViewport(0, 0, 640, 360);
//}
glClearColor(sss->param.x, sss->param.y, sss->param.z, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw_pass_set_camera(rctx);
for (int32_t i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++)
rctx->light_set[i].data_set(rctx->face, (light_set_id)i);
if (shadow)
draw_pass_3d_shadow_set(shadow_ptr, rctx);
else
draw_pass_3d_shadow_reset(rctx);
rctx->obj_scene_ubo.WriteMemory(rctx->obj_scene);
rctx->draw_state.shader_index = SHADER_FT_SSS_SKIN;
gl_state_enable_depth_test();
gl_state_set_depth_func(GL_LEQUAL);
gl_state_set_depth_mask(GL_TRUE);
rctx->disp_manager.draw(mdl::OBJ_TYPE_SSS);
gl_state_disable_depth_test();
rctx->draw_state.shader_index = -1;
draw_pass_3d_shadow_reset(rctx);
uniform_value[U_NPR] = 0;
if (npr_param == 1) {
if (sss->enable && sss->npr_contour) {
uniform_value[U_NPR] = 1;
draw_pass_sss_contour(rctx, pp);
}
else if (npr) {
rctx->obj_scene_ubo.WriteMemory(rctx->obj_scene);
pp->rend_texture.Bind();
glViewport(0, 0, pp->render_width, pp->render_height);
glClear(GL_DEPTH_BUFFER_BIT);
rctx->draw_state.shader_index = SHADER_FT_SSS_SKIN;
gl_state_enable_depth_test();
gl_state_set_depth_mask(GL_TRUE);
rctx->disp_manager.draw(mdl::OBJ_TYPE_SSS);
gl_state_disable_depth_test();
rctx->draw_state.shader_index = -1;
gl_state_bind_framebuffer(0);
uniform_value[U_NPR] = 1;
draw_pass_sss_contour(rctx, pp);
}
}
if (!sss->npr_contour) {
sss->textures[0].Bind();
glViewport(0, 0, 640, 360);
filter_scene_shader_data filter_scene = {};
filter_scene.g_transform = { 1.0f, 1.0f, 0.0f, 0.0f };
filter_scene.g_texcoord = { 1.0f, 1.0f, 0.0f, 0.0f };
rctx->filter_scene_ubo.WriteMemory(filter_scene);
imgfilter_batch_shader_data imgfilter_batch = {};
imgfilter_batch.g_color_scale = 1.0f;
imgfilter_batch.g_color_offset = 0.0f;
imgfilter_batch.g_texture_lod = 0.0f;
rctx->imgfilter_batch_ubo.WriteMemory(imgfilter_batch);
uniform_value[U_IMAGE_FILTER] = 5;
shaders_ft.set(SHADER_FT_IMGFILT);
rctx->filter_scene_ubo.Bind(0);
rctx->imgfilter_batch_ubo.Bind(1);
gl_state_active_bind_texture_2d(0, pp->rend_texture.color_texture->tex);
RenderTexture::DrawCustom();
}
draw_pass_sss_filter(rctx, sss);
gl_state_bind_framebuffer(0);
gl_state_end_event();
}
void RenderManager::pass_reflect(render_context* rctx) {
gl_state_begin_event("pass_reflect");
RenderTexture& refl_tex = rctx->render_manager.get_render_texture(0);
RenderTexture& refl_buf_tex = rctx->render_manager.get_render_texture(11);
refl_tex.Bind();
if (rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_REFLECT_OPAQUE)
|| rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_REFLECT_TRANSPARENT)
|| rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_REFLECT_TRANSLUCENT)
|| rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_REFLECT_CHARA_OPAQUE)
|| rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_REFLECT_CHARA_TRANSPARENT)
|| rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_REFLECT_CHARA_TRANSLUCENT)) {
glViewport(0, 0, refl_tex.color_texture->width, refl_tex.color_texture->height);
draw_pass_set_camera(rctx);
for (int32_t i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++)
rctx->light_set[i].data_set(rctx->face, (light_set_id)i);
for (int32_t i = FOG_DEPTH; i < FOG_BUMP; i++)
rctx->fog[i].data_set((fog_id)i);
rctx->obj_scene_ubo.WriteMemory(rctx->obj_scene);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
rctx->draw_state.shader_index = SHADER_FT_S_REFL;
light_set* set = &rctx->light_set[LIGHT_SET_MAIN];
light_clip_plane clip_plane;
set->lights[LIGHT_SPOT].get_clip_plane(clip_plane);
uniform_value[U_REFLECT] = 2;
uniform_value[U_CLIP_PLANE] = clip_plane.data[1];
gl_state_enable_depth_test();
gl_state_set_depth_func(GL_LEQUAL);
gl_state_set_depth_mask(GL_TRUE);
rctx->disp_manager.draw(mdl::OBJ_TYPE_REFLECT_OPAQUE, 0, field_31D);
if (reflect_type == STAGE_DATA_REFLECT_REFLECT_MAP) {
gl_state_enable_blend();
gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_state_set_blend_equation(GL_FUNC_ADD);
rctx->disp_manager.draw(mdl::OBJ_TYPE_REFLECT_TRANSLUCENT);
gl_state_disable_blend();
}
if (reflect_type == STAGE_DATA_REFLECT_REFLECT_MAP) {
uniform_value[U_REFLECT] = field_31E;
uniform_value[U_CLIP_PLANE] = clip_plane.data[0];
rctx->disp_manager.draw(mdl::OBJ_TYPE_REFLECT_CHARA_OPAQUE);
}
gl_state_disable_depth_test();
uniform_value[U_REFLECT] = 0;
rctx->draw_state.shader_index = -1;
for (int32_t i = reflect_blur_num, j = 0; i > 0; i--, j++)
if (j % 2) {
refl_tex.Bind();
blur_filter_apply(rctx, refl_tex.color_texture->tex,
refl_buf_tex.color_texture->tex, reflect_blur_filter, 1.0f, 1.0f, 0.0f);
}
else {
refl_buf_tex.Bind();
blur_filter_apply(rctx, refl_buf_tex.color_texture->tex,
refl_tex.color_texture->tex, reflect_blur_filter, 1.0f, 1.0f, 0.0f);
}
if (reflect_blur_num % 2)
fbo::blit(refl_buf_tex.fbos[0], refl_tex.fbos[0],
0, 0, refl_buf_tex.color_texture->width, refl_buf_tex.color_texture->height,
0, 0, refl_tex.color_texture->width, refl_tex.color_texture->height,
GL_COLOR_BUFFER_BIT, GL_LINEAR);
}
else {
vec4 clear_color;
glGetFloatv(GL_COLOR_CLEAR_VALUE, (GLfloat*)&clear_color);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
}
gl_state_bind_framebuffer(0);
gl_state_end_event();
}
void RenderManager::pass_refract(render_context* rctx) {
gl_state_begin_event("pass_refract");
RenderTexture& refract_texture = rctx->render_manager.get_render_texture(1);
refract_texture.Bind();
if (rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_REFRACT_OPAQUE)
|| rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_REFRACT_TRANSPARENT)
|| rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_REFRACT_TRANSLUCENT)) {
texture* refr_tex = refract_texture.color_texture;
glViewport(0, 0, refr_tex->width, refr_tex->height);
draw_pass_set_camera(rctx);
for (int32_t i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++)
rctx->light_set[i].data_set(rctx->face, (light_set_id)i);
for (int32_t i = FOG_DEPTH; i < FOG_BUMP; i++)
rctx->fog[i].data_set((fog_id)i);
rctx->obj_scene_ubo.WriteMemory(rctx->obj_scene);
vec4 clear_color;
glGetFloatv(GL_COLOR_CLEAR_VALUE, (GLfloat*)&clear_color);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
rctx->draw_state.shader_index = SHADER_FT_S_REFR;
gl_state_enable_depth_test();
gl_state_set_depth_func(GL_LEQUAL);
gl_state_set_depth_mask(GL_TRUE);
rctx->disp_manager.draw(mdl::OBJ_TYPE_REFRACT_OPAQUE);
rctx->disp_manager.draw(mdl::OBJ_TYPE_REFRACT_TRANSPARENT);
rctx->disp_manager.draw(mdl::OBJ_TYPE_REFRACT_TRANSLUCENT);
gl_state_disable_depth_test();
rctx->draw_state.shader_index = -1;
}
else {
vec4 clear_color;
glGetFloatv(GL_COLOR_CLEAR_VALUE, (GLfloat*)&clear_color);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
}
gl_state_bind_framebuffer(0);
gl_state_end_event();
}
void RenderManager::pass_pre_process(render_context* rctx) {
gl_state_begin_event("pass_pre_process");
for (draw_pre_process& i : pre_process)
if (i.func)
i.func(i.data);
gl_state_end_event();
}
void RenderManager::pass_clear(render_context* rctx) {
gl_state_begin_event("pass_clear");
if (clear) {
vec4 clear_color = get_clear_color();
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
post_process* pp = &rctx->post_process;
if (!sss_data.enable || !sss_data.npr_contour) {
pp->set_render_texture();
if (sprite_manager_get_reqlist_count(2)) {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gl_state_bind_framebuffer(0);
}
else {
vec4 clear_color = get_clear_color();
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClearDepth(1.0f);
if (clear)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
glClear(GL_DEPTH_BUFFER_BIT);
gl_state_bind_framebuffer(0);
}
}
else {
pp->set_render_texture();
if (sprite_manager_get_reqlist_count(2)) {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
gl_state_bind_framebuffer(0);
}
else if (clear) {
vec4 clear_color = get_clear_color();
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
gl_state_bind_framebuffer(0);
}
}
gl_state_get_error();
gl_state_end_event();
}
void RenderManager::pass_pre_sprite(render_context* rctx) {
if (!sprite_manager_get_reqlist_count(2))
return;
gl_state_begin_event("pass_pre_sprite");
post_process* pp = &rctx->post_process;
pp->set_render_texture(true);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
gl_state_set_depth_mask(GL_FALSE);
gl_state_disable_depth_test();
gl_state_enable_blend();
gl_state_disable_cull_face();
sprite_manager_draw(rctx, 2, true,
pp->aa->temp_buffer.color_texture,
rctx->camera->view_projection_aet_3d);
gl_state_enable_cull_face();
gl_state_disable_blend();
gl_state_enable_depth_test();
gl_state_set_depth_mask(GL_TRUE);
gl_state_bind_framebuffer(0);
gl_state_get_error();
gl_state_end_event();
}
void RenderManager::pass_3d(render_context* rctx) {
rctx->camera->update_data();
rctx->post_process.set_render_texture();
draw_pass_set_camera(rctx);
if (!sss_data.enable || !sss_data.npr_contour || draw_pass_3d_get_translucent_count(rctx))
glClear(GL_DEPTH_BUFFER_BIT);
gl_state_set_depth_func(GL_LEQUAL);
for (int32_t i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++)
rctx->light_set[i].data_set(rctx->face, (light_set_id)i);
for (int32_t i = FOG_DEPTH; i < FOG_MAX; i++)
rctx->fog[i].data_set((fog_id)i);
if (shadow)
draw_pass_3d_shadow_set(shadow_ptr, rctx);
else
draw_pass_3d_shadow_reset(rctx);
rctx->obj_scene_ubo.WriteMemory(rctx->obj_scene);
if (pass_sw[RND_PASSID_REFLECT] && reflect) {
RenderTexture& refl_tex = get_render_texture(0);
gl_state_active_bind_texture_2d(15, refl_tex.color_texture->tex);
uniform_value[U_WATER_REFLECT] = 1;
}
else {
gl_state_active_bind_texture_2d(15, rctx->empty_texture_2d);
uniform_value[U_WATER_REFLECT] = 0;
}
uniform_value[U12] = field_320 ? 1 : 0;
if (effect_texture)
gl_state_active_bind_texture_2d(14, effect_texture->tex);
else
gl_state_active_bind_texture_2d(14, rctx->empty_texture_2d);
gl_state_active_bind_texture_2d(16, sss_data.textures[1].color_texture->tex);
gl_state_active_texture(0);
if (alpha_z_sort) {
rctx->disp_manager.obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_TRANSLUCENT, 1);
rctx->disp_manager.obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_TRANSLUCENT_NO_SHADOW, 2);
rctx->disp_manager.obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_1, 1);
rctx->disp_manager.obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2, 1);
rctx->disp_manager.obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_3, 1);
rctx->disp_manager.obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2_LOCAL, 1);
}
if (opaque_z_sort)
rctx->disp_manager.obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_OPAQUE, 0);
if (draw_pass_3d[DRAW_PASS_3D_OPAQUE]) {
gl_state_enable_depth_test();
gl_state_set_depth_mask(GL_TRUE);
rctx->disp_manager.draw(mdl::OBJ_TYPE_OPAQUE);
gl_state_disable_depth_test();
}
Glitter::glt_particle_manager->DispScenes(Glitter::DISP_OPAQUE);
if (draw_grid_3d)
draw_pass_3d_grid(rctx);
gl_state_enable_depth_test();
gl_state_set_depth_mask(GL_TRUE);
if (draw_pass_3d[DRAW_PASS_3D_TRANSPARENT])
rctx->disp_manager.draw(mdl::OBJ_TYPE_TRANSPARENT);
/*if (rctx->render_manager.field_120)
rctx->disp_manager.draw(mdl::OBJ_TYPE_TYPE_7);*/
rctx->post_process.exposure->get_exposure_chara_data(&rctx->post_process, rctx->camera);
if (npr_param == 1)
pass_3d_contour(rctx);
rctx->post_process.draw_lens_flare(rctx->camera);
star_catalog_draw();
draw_pass_3d_translucent(rctx,
draw_pass_3d[DRAW_PASS_3D_OPAQUE],
draw_pass_3d[DRAW_PASS_3D_TRANSPARENT],
draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT],
mdl::OBJ_TYPE_OPAQUE_ALPHA_ORDER_3,
mdl::OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_3,
mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_3);
snow_particle_draw();
rain_particle_draw();
leaf_particle_draw();
particle_draw();
gl_state_disable_depth_test();
gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
Glitter::glt_particle_manager->DispScenes(Glitter::DISP_ALPHA);
gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
/*if (npr_param == 1) {
gl_state_set_color_mask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}*/
gl_state_enable_depth_test();
if (draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT]) {
gl_state_enable_blend();
gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_state_set_depth_mask(GL_FALSE);
rctx->disp_manager.draw(mdl::OBJ_TYPE_TRANSLUCENT_NO_SHADOW);
rctx->disp_manager.draw(mdl::OBJ_TYPE_TRANSLUCENT);
gl_state_disable_blend();
}
gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); // X
Glitter::glt_particle_manager->DispScenes(Glitter::DISP_TYPE_2);
gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
gl_state_set_depth_mask(GL_TRUE);
draw_pass_3d_translucent(rctx,
draw_pass_3d[DRAW_PASS_3D_OPAQUE],
draw_pass_3d[DRAW_PASS_3D_TRANSPARENT],
draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT],
mdl::OBJ_TYPE_OPAQUE_ALPHA_ORDER_2,
mdl::OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2,
mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2);
gl_state_disable_depth_test();
gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
Glitter::glt_particle_manager->DispScenes(Glitter::DISP_NORMAL);
gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
gl_state_enable_depth_test();
gl_state_set_depth_mask(GL_TRUE);
draw_pass_3d_translucent(rctx,
draw_pass_3d[DRAW_PASS_3D_OPAQUE],
draw_pass_3d[DRAW_PASS_3D_TRANSPARENT],
draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT],
mdl::OBJ_TYPE_OPAQUE_ALPHA_ORDER_1,
mdl::OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_1,
mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_1);
#if defined(CRE_DEV)
if (Glitter::glt_particle_manager->CheckHasLocalEffect()) { // X
camera* cam = rctx->camera;
double_t fov = cam->get_fov();
cam->set_fov(32.2673416137695);
draw_pass_set_camera(rctx);
rctx->obj_scene_ubo.WriteMemory(rctx->obj_scene);
rctx->disp_manager.draw(mdl::OBJ_TYPE_OPAQUE_LOCAL);
rctx->disp_manager.draw(mdl::OBJ_TYPE_TRANSPARENT_LOCAL);
gl_state_enable_blend();
rctx->disp_manager.draw(mdl::OBJ_TYPE_TRANSLUCENT_LOCAL);
gl_state_disable_blend();
draw_pass_3d_translucent(rctx,
draw_pass_3d[DRAW_PASS_3D_OPAQUE],
draw_pass_3d[DRAW_PASS_3D_TRANSPARENT],
draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT],
mdl::OBJ_TYPE_OPAQUE_ALPHA_ORDER_2_LOCAL,
mdl::OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2_LOCAL,
mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2_LOCAL);
gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
Glitter::glt_particle_manager->DispScenes(Glitter::DISP_LOCAL);
gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
cam->set_fov(fov);
draw_pass_set_camera(rctx);
}
#endif
gl_state_active_bind_texture_2d(14, 0);
gl_state_active_bind_texture_2d(15, 0);
gl_state_disable_depth_test();
if (shadow)
draw_pass_3d_shadow_reset(rctx);
shader::unbind();
pass_sprite_surf(rctx);
gl_state_bind_framebuffer(0);
}
void RenderManager::pass_show_vector(render_context* rctx) {
return;
/*if (!show_vector_flags)
return;
gl_state_begin_event("pass_show_vector");
rctx->camera->update_data();
rctx->view_mat = rctx->camera->view;
rctx->post_process.set_render_texture();
draw_pass_set_camera(rctx);
rctx->obj_scene_ubo.WriteMemory(rctx->obj_scene);
if (alpha_z_sort) {
rctx->disp_manager.obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_TRANSLUCENT, 1);
rctx->disp_manager.obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_TRANSLUCENT_NO_SHADOW, 2);
}
if (opaque_z_sort)
rctx->disp_manager.obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_OPAQUE, 0);
//shaders_ft.env_vert_set(20, show_vector_length, show_vector_z_offset, 0.0f, 0.0f);
for (int32_t i = 1; i < 4; i++) {
if (!(show_vector_flags & (1 << (i - 1))))
continue;
if (draw_pass_3d[DRAW_PASS_3D_OPAQUE])
draw_task_draw_objects_by_type_show_vector(rctx, mdl::OBJ_TYPE_OPAQUE, i);
if (draw_pass_3d[DRAW_PASS_3D_TRANSPARENT])
draw_task_draw_objects_by_type_show_vector(rctx, mdl::OBJ_TYPE_TRANSPARENT, i);
if (draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT]) {
draw_task_draw_objects_by_type_show_vector(rctx, mdl::OBJ_TYPE_TRANSLUCENT_NO_SHADOW, i);
draw_task_draw_objects_by_type_show_vector(rctx, mdl::OBJ_TYPE_TRANSLUCENT, i);
}
}
gl_state_end_event();*/
}
void RenderManager::pass_post_process(render_context* rctx) {
gl_state_begin_event("pass_post_process");
rctx->camera->update_data();
texture* light_proj_tex = 0;
light_proj* litproj = rctx->litproj;
if (litproj && litproj->enable) {
light_set* set = &rctx->light_set[LIGHT_SET_MAIN];
if (set->lights[LIGHT_PROJECTION].get_type() == LIGHT_SPOT
&& texture_storage_get_texture(litproj->texture_id))
light_proj_tex = litproj->draw_texture.color_texture;
}
rctx->post_process.apply(rctx->camera, light_proj_tex, npr_param);
gl_state_end_event();
}
void RenderManager::pass_sprite(render_context* rctx) {
if (!sprite_manager_get_reqlist_count(0))
return;
gl_state_begin_event("pass_sprite");
post_process* pp = &rctx->post_process;
glViewport(0, 0, pp->sprite_width, pp->sprite_height);
if (multisample && multisample_framebuffer) {
glBindFramebuffer(GL_FRAMEBUFFER, multisample_framebuffer);
gl_state_enable_multisample();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
else
rctx->post_process.screen_texture.Bind();
gl_state_disable_depth_test();
gl_state_enable_blend();
gl_state_disable_cull_face();
sprite_manager_draw(rctx, 0, true,
pp->aa->temp_buffer.color_texture,
rctx->camera->view_projection_aet_2d);
gl_state_enable_cull_face();
gl_state_disable_blend();
gl_state_enable_depth_test();
if (multisample && multisample_framebuffer) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
gl_state_disable_multisample();
gl_state_bind_read_framebuffer(multisample_framebuffer);
glBlitFramebuffer(0, 0, pp->sprite_width, pp->sprite_height,
0, 0, pp->sprite_width, pp->sprite_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
gl_state_bind_read_framebuffer(0);
}
gl_state_get_error();
gl_state_end_event();
}
void RenderManager::pass_3d_contour(render_context* rctx) {
RenderTexture* rt = &rctx->post_process.rend_texture;
RenderTexture* contour_rt = &rctx->post_process.sss_contour_texture;
gl_state_enable_blend();
gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gl_state_set_blend_equation(GL_FUNC_ADD);
gl_state_disable_depth_test();
quad_shader_data quad_data = {};
quad_data.g_texcoord_modifier = { 0.5f, 0.5f, 0.5f, 0.5f };
rctx->quad_ubo.WriteMemory(quad_data);
contour_params_shader_data contour_params_data = {};
contour_params_data.g_near_far = rctx->g_near_far;
rctx->contour_params_ubo.WriteMemory(contour_params_data);
shaders_ft.set(SHADER_FT_CONTOUR_NPR);
gl_state_active_bind_texture_2d(16, contour_rt->color_texture->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl_state_active_bind_texture_2d(17, contour_rt->depth_texture->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl_state_active_bind_texture_2d(14, rt->depth_texture->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
rctx->quad_ubo.Bind(0);
rctx->contour_params_ubo.Bind(2);
RenderTexture::Draw(&shaders_ft);
if (effect_texture)
gl_state_active_bind_texture_2d(14, effect_texture->tex);
else
gl_state_active_bind_texture_2d(14, rctx->empty_texture_2d);
gl_state_enable_depth_test();
gl_state_disable_blend();
}
void RenderManager::pass_sprite_surf(render_context* rctx) {
if (!sprite_manager_get_reqlist_count(1))
return;
post_process* pp = &rctx->post_process;
gl_state_set_depth_mask(GL_FALSE);
gl_state_disable_depth_test();
gl_state_disable_depth_test();
gl_state_enable_blend();
gl_state_disable_cull_face();
sprite_manager_draw(rctx, 1, true,
pp->aa->temp_buffer.color_texture,
rctx->camera->view_projection_aet_2d);
}
}
void image_filter_scale(render_context* rctx, GLuint dst, GLuint src, const vec4 scale) {
if (!dst || !src)
return;
texture_param tex_params[2];
texture_params_get(dst, &tex_params[0], src, &tex_params[1]);
filter_scene_shader_data filter_scene = {};
filter_scene.g_transform = { 1.0f, 1.0f, 0.0f, 0.0f };
filter_scene.g_texcoord = { 1.0f, 1.0f, 0.0f, 0.0f };
rctx->filter_scene_ubo.WriteMemory(filter_scene);
imgfilter_batch_shader_data imgfilter_batch = {};
imgfilter_batch.g_color_scale = 1.0f;
imgfilter_batch.g_color_offset = 0.0f;
imgfilter_batch.g_texture_lod = 0.0f;
rctx->imgfilter_batch_ubo.WriteMemory(imgfilter_batch);
uniform_value[U_IMAGE_FILTER] = 5;
shaders_ft.set(SHADER_FT_IMGFILT);
rctx->filter_scene_ubo.Bind(0);
rctx->imgfilter_batch_ubo.Bind(1);
gl_state_active_bind_texture_2d(0, src);
RenderTexture::DrawCustom();
texture_params_restore(&tex_params[0], &tex_params[1]);
}
void draw_pass_set_camera(render_context* rctx) {
camera* cam = rctx->camera;
cam->update_data();
rctx->view_mat = cam->view;
rctx->proj_mat = cam->projection;
rctx->vp_mat = cam->view_projection;
rctx->obj_scene.set_projection_view(cam->view, cam->projection);
cam->get_view_point(rctx->obj_scene.g_view_position);
rctx->g_near_far = {
(float_t)(cam->max_distance / (cam->max_distance - cam->min_distance)),
(float_t)(-(cam->max_distance * cam->min_distance) / (cam->max_distance - cam->min_distance)),
0.0f, 0.0f
};
}
static void draw_pass_shadow_begin_make_shadowmap(render_context* rctx,
Shadow* shad, int32_t index, int32_t a3) {
texture* tex = shad->curr_render_textures[0]->color_texture;
shad->curr_render_textures[0]->Bind();
glViewport(0, 0, tex->width, tex->height);
glScissor(0, 0, tex->width, tex->height);
gl_state_enable_depth_test();
gl_state_enable_scissor_test();
glClearColor(1.0, 1.0, 1.0, 1.0);
if (!a3)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else if (shad->field_2F5)
glClear(GL_COLOR_BUFFER_BIT);
glScissor(1, 1, tex->width - 2, tex->height - 2);
float_t offset = 0.0f;
float_t range = shad->view_region * shad->range;
vec3* interest;
vec3* view_point;
if (shad->field_2F5) {
offset = -0.5f;
if (index)
offset = 0.5f;
interest = &shad->interest[index];
view_point = &shad->view_point[index];
}
else {
interest = &shad->interest_shared;
view_point = &shad->view_point_shared;
}
mat4 temp;
mat4_translate(offset, 0.0f, 0.0f, &temp);
mat4 proj;
mat4_ortho(-range, range, -range, range, shad->z_near, shad->z_far, &proj);
mat4_mul(&proj, &temp, &rctx->proj_mat);
mat4_look_at(view_point, interest, &rctx->view_mat);
rctx->draw_state.shader_index = SHADER_FT_SIL;
uniform_value[U0A] = 0;
}
static void draw_pass_shadow_end_make_shadowmap(render_context* rctx,
Shadow* shad, int32_t index, int32_t a3) {
gl_state_disable_depth_test();
gl_state_disable_scissor_test();
rctx->draw_state.shader_index = -1;
if (a3 == shad->field_2EC - 1) {
draw_pass_shadow_filter(rctx, &shad->render_textures[3],
&shad->render_textures[4], shad->curr_render_textures[0],
shad->field_2DC, shad->field_2E0 / (shad->field_208 * 2.0f), false);
draw_pass_shadow_esm_filter(rctx, &shad->render_textures[5],
&shad->render_textures[6], &shad->render_textures[3]);
}
RenderTexture* rend_tex = shad->curr_render_textures[1 + index];
RenderTexture* rend_buf_tex = shad->curr_render_textures[3];
rend_tex->Bind();
image_filter_scale(rctx, rend_tex->color_texture->tex,
shad->curr_render_textures[0]->color_texture->tex, 1.0f);
if (shad->blur_filter_enable[index]) {
for (int32_t i = shad->near_blur, j = 0; i > 0; i--, j++)
if (j % 2) {
rend_tex->Bind();
blur_filter_apply(rctx, rend_tex->color_texture->tex,
rend_buf_tex->color_texture->tex, shad->blur_filter, 1.0f, 1.0f, 0.0f);
}
else {
rend_buf_tex->Bind();
blur_filter_apply(rctx, rend_buf_tex->color_texture->tex,
rend_tex->color_texture->tex, shad->blur_filter, 1.0f, 1.0f, 0.0f);
}
if (shad->near_blur % 2)
image_filter_scale(rctx, rend_buf_tex->color_texture->tex,
rend_tex->color_texture->tex, 1.0f);
}
else {
rend_tex->Bind();
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
gl_state_bind_framebuffer(0);
gl_state_bind_texture_2d(rend_tex->color_texture->tex);
glGenerateMipmap(GL_TEXTURE_2D);
gl_state_bind_texture_2d(0);
}
static void draw_pass_shadow_filter(render_context* rctx, RenderTexture* a1, RenderTexture* a2,
RenderTexture* a3, float_t sigma, float_t far_texel_offset, bool enable_lit_proj) {
GLuint v7 = a1->color_texture->tex;
GLuint v9 = a2->color_texture->tex;
GLuint v11 = v7;
if (a3)
v11 = a3->depth_texture->tex;
if (!v7 || !v9 || !v11)
return;
texture_param tex_params[2];
texture_params_get(v7, &tex_params[0], v9, &tex_params[1]);
if (tex_params[0].width != tex_params[1].width
|| tex_params[0].height != tex_params[1].height)
return;
filter_scene_shader_data filter_scene = {};
filter_scene.g_transform = 0.0f;
filter_scene.g_texcoord = { 1.0f, 1.0f, 0.0f, 0.0f };
rctx->filter_scene_ubo.WriteMemory(filter_scene);
esm_filter_batch_shader_data esm_filter_batch = {};
esm_filter_batch.g_params = { 1.0f / (float_t)tex_params[0].width, 0.0f, far_texel_offset, far_texel_offset };
double_t v6 = 1.0 / (sqrt(M_PI * 2.0) * sigma);
double_t v8 = -1.0 / (2.0 * sigma * sigma);
for (int32_t i = 0; i < 8; i++)
((float_t*)esm_filter_batch.g_gauss)[i] = (float_t)(exp((double_t)((ssize_t)i * i) * v8) * v6);
uniform_value[U_LIGHT_PROJ] = enable_lit_proj ? 1 : 0;
shaders_ft.set(SHADER_FT_ESMGAUSS);
rctx->filter_scene_ubo.Bind(0);
rctx->esm_filter_batch_ubo.Bind(1);
a2->Bind();
esm_filter_batch.g_params = { 1.0f / (float_t)tex_params[0].width, 0.0f, far_texel_offset, far_texel_offset };
rctx->esm_filter_batch_ubo.WriteMemory(esm_filter_batch);
gl_state_active_bind_texture_2d(0, v11);
if (a3) {
GLint swizzle[] = { GL_RED, GL_RED, GL_RED, GL_ONE };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
}
else {
GLint swizzle[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
}
RenderTexture::DrawCustom();
a1->Bind();
esm_filter_batch.g_params = { 0.0f, 1.0f / (float_t)tex_params[0].height, far_texel_offset, far_texel_offset };
rctx->esm_filter_batch_ubo.WriteMemory(esm_filter_batch);
gl_state_active_bind_texture_2d(0, v9);
RenderTexture::DrawCustom();
shader::unbind();
texture_params_restore(&tex_params[0], &tex_params[1]);
}
static void draw_pass_shadow_esm_filter(render_context* rctx,
RenderTexture* dst, RenderTexture* buf, RenderTexture* src) {
GLuint dst_tex = dst->color_texture->tex;
GLuint buf_tex = buf->color_texture->tex;
GLuint src_tex = src->color_texture->tex;
if (!dst_tex || !buf_tex || !src_tex)
return;
filter_scene_shader_data filter_scene = {};
filter_scene.g_transform = 0.0f;
filter_scene.g_texcoord = { 1.0f, 1.0f, 0.0f, 0.0f };
rctx->filter_scene_ubo.WriteMemory(filter_scene);
esm_filter_batch_shader_data esm_filter_batch = {};
esm_filter_batch.g_gauss[0] = 0.0f;
esm_filter_batch.g_gauss[1] = 0.0f;
rctx->filter_scene_ubo.Bind(0);
rctx->esm_filter_batch_ubo.Bind(1);
texture_param tex_params[3];
texture_params_get(dst_tex, &tex_params[0], src_tex, &tex_params[1], buf_tex, &tex_params[2]);
buf->Bind();
esm_filter_batch.g_params = { 1.0f / (float_t)tex_params[1].width,
1.0f / (float_t)tex_params[1].height, 0.0f, 0.0f };
rctx->esm_filter_batch_ubo.WriteMemory(esm_filter_batch);
uniform_value[U_ESM_FILTER] = 0;
shaders_ft.set(SHADER_FT_ESMFILT);
gl_state_active_bind_texture_2d(0, src_tex);
RenderTexture::Draw(&shaders_ft);
dst->Bind();
esm_filter_batch.g_params = { 0.75f / (float_t)tex_params[2].width,
0.75f / (float_t)tex_params[2].height, 0.0f, 0.0f };
rctx->esm_filter_batch_ubo.WriteMemory(esm_filter_batch);
uniform_value[U_ESM_FILTER] = 1;
shaders_ft.set(SHADER_FT_ESMFILT);
gl_state_active_bind_texture_2d(0, buf_tex);
RenderTexture::Draw(&shaders_ft);
texture_params_restore(&tex_params[0], &tex_params[1], &tex_params[2]);
}
static bool draw_pass_shadow_litproj(render_context* rctx, light_proj* litproj) {
if (!litproj)
return false;
texture* tex = texture_storage_get_texture(litproj->texture_id);
if (!tex)
return false;
litproj->draw_texture.Bind();
glViewport(0, 0, litproj->draw_texture.color_texture->width,
litproj->draw_texture.color_texture->height);
gl_state_enable_depth_test();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepthf(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (!light_proj::set_mat(rctx, 0)) {
gl_state_bind_framebuffer(0);
return false;
}
static const vec4 border_color = 0.0f;
rctx->draw_state.shader_index = SHADER_FT_LITPROJ;
gl_state_active_bind_texture_2d(17, tex->tex);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&border_color);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
gl_state_active_bind_texture_2d(18, litproj->shadow_texture[0].color_texture->tex);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&border_color);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
gl_state_active_texture(0);
return true;
}
static void draw_pass_sss_contour(render_context* rctx, post_process* pp) {
pp->sss_contour_texture.Bind();
gl_state_enable_depth_test();
gl_state_set_depth_func(GL_ALWAYS);
gl_state_set_depth_mask(GL_TRUE);
glViewport(0, 0, pp->render_width, pp->render_height);
gl_state_active_bind_texture_2d(0, pp->rend_texture.color_texture->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl_state_active_bind_texture_2d(1, pp->rend_texture.depth_texture->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl_state_active_texture(0);
camera* cam = rctx->camera;
float_t v3 = 1.0f / tanf((float_t)(cam->fov_rad * 0.5));
vec3 direction = cam->interest - cam->view_point;
float_t length = vec3::length(direction);
float_t v7 = direction.y;
if (length != 0.0f)
v7 /= length;
float_t v9 = fabsf(v7) - 0.1f;
if (v9 < 0.0f)
v9 = 0.0f;
contour_coef_shader_data shader_data = {};
shader_data.g_contour = { v9 * 0.004f + 0.0027f, 0.003f, v3 * 0.35f, 0.0008f };
shader_data.g_near_far = rctx->g_near_far;
rctx->contour_coef_ubo.WriteMemory(shader_data);
shaders_ft.set(SHADER_FT_CONTOUR);
rctx->contour_coef_ubo.Bind(2);
RenderTexture::DrawQuad(&shaders_ft, pp->render_width, pp->render_height);
}
static void draw_pass_sss_filter_calc_coef(double_t a1, size_t a2, double_t a3, size_t a4,
const double_t* a5, const double_t* a6, const double_t* a7, const double_t* a8, vec4 params[64]) {
if (a2 > 8)
return;
for (size_t i = a4; i; i--) {
float_t* v20 = (float_t*)params;
double_t v56[3];
v56[0] = *a6;
v56[1] = *a7;
v56[2] = *a8;
for (size_t j = 0; j < 3; j++) {
double_t v22 = 0.0;
double_t v23 = 0.0;
double_t v54[8];
double_t v24 = 1.0 / (a3 * v56[j]);
v24 *= v24;
for (size_t k = 0; k < a2; k++) {
double_t v25 = exp(-0.5 * (v23 * v23) * v24);
v54[k] = v25;
v23 += a1;
v22 += v25;
}
double_t v27 = 1.0 / v22;
for (size_t k = 0; k < a2; k++)
v54[k] *= v27;
float_t* v35 = v20;
for (size_t k = 0; k < a2; k++) {
double_t v37 = v54[k] * *a5;
for (size_t v36 = 0; v36 < a2; v36++) {
*v35 += (float_t)(v37 * v54[v36]);
v35 += 4;
}
}
v20++;
}
a5++;
a6++;
a7++;
a8++;
}
}
static void draw_pass_sss_filter(render_context* rctx, sss_data* sss) {
const int32_t sss_count = 6;
vec3 interest = rctx->camera->interest;
vec3 view_point = rctx->camera->view_point;
vec3 chara_position[2];
chara_position[0] = 0.0f;
chara_position[1] = 0.0f;
float_t chara_distance[2];
for (int32_t i = 0; i < 2; i++) {
chara_position[i] = interest;
chara_distance[i] = 999999.0f;
rob_chara_bone_data* v16 = rob_chara_array[i].bone_data;
if (rob_chara_pv_data_array[i].type != ROB_CHARA_TYPE_NONE && rob_chara_array[i].data.field_0 & 1) {
mat4* mat = rob_chara_bone_data_get_mats_mat(v16, MOTION_BONE_N_HARA_CP);
if (mat) {
mat4_get_translation(mat, &chara_position[i]);
chara_distance[i] = vec3::distance(view_point, chara_position[i]);
}
}
}
vec3 closest_chara_position;
if (chara_distance[0] > chara_distance[1]) {
closest_chara_position = chara_position[1];
chara_position[0] = chara_position[1];
}
else
closest_chara_position = chara_position[0];
float_t length = vec3::distance(interest, closest_chara_position);
if (length > 1.25f)
interest = chara_position[0];
float_t v29 = vec3::distance(view_point, interest);
if (v29 < 0.25f)
v29 = 0.25f;
float_t v31 = tanf((float_t)(rctx->camera->fov_rad * 0.5)) * 5.0f;
if (v31 < 0.25f)
v31 = 0.25f;
float_t v32 = v31 * v29;
float_t v33 = 0.6f;
float_t v34 = 1.0f / clamp_def(v32, 0.25f, 100.0f);
if (v34 < 0.145f) {
float_t v36 = v34 - 0.02f;
if (v34 < 0.0f)
v36 = 0.0f;
v33 = (v36 * 8.0f) * 0.6f;
}
rctx->obj_batch.g_sss_param = { v33, 0.0f, 0.0f, 0.0f };
gl_state_active_texture(0);
if (sss->npr_contour) {
sss->textures[0].Bind();
glViewport(0, 0, 640, 360);
post_process* pp = &rctx->post_process;
uniform_value[U_REDUCE] = 0;
shaders_ft.set(SHADER_FT_REDUCE);
gl_state_bind_texture_2d(pp->rend_texture.color_texture->tex);
RenderTexture::DrawQuad(&shaders_ft, 640, 360, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f);
}
sss->textures[2].Bind();
glViewport(0, 0, 320, 180);
uniform_value[U_SSS_FILTER] = 0;
shaders_ft.set(SHADER_FT_SSS_FILT);
gl_state_bind_texture_2d(sss->textures[0].color_texture->tex);
RenderTexture::DrawQuad(&shaders_ft, 640, 360, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f);
sss_filter_gaussian_coef_shader_data shader_data = {};
shader_data.g_param = { (float_t)(sss_count - 1), 0.0f, 1.0f, 1.0f };
const double_t a5[] = { 0.4, 0.3, 0.3 };
const double_t a6[] = { 1.0, 2.0, 5.0 };
const double_t a7[] = { 0.2, 0.4, 1.2 };
const double_t a8[] = { 0.3, 0.7, 2.0 };
draw_pass_sss_filter_calc_coef(1.0, sss_count, v34, 3, a5, a6, a7, a8, shader_data.g_coef);
rctx->sss_filter_gaussian_coef_ubo.WriteMemory(shader_data);
sss->textures[1].Bind();
glViewport(0, 0, 320, 180);
uniform_value[U_SSS_FILTER] = 3;
shaders_ft.set(SHADER_FT_SSS_FILT);
gl_state_bind_texture_2d(sss->textures[2].color_texture->tex);
rctx->sss_filter_gaussian_coef_ubo.Bind(1);
RenderTexture::DrawQuad(&shaders_ft, 320, 180, 1.0f, 1.0f, 0.96f, 1.0f, 0.0f);
gl_state_bind_texture_2d(0);
}
static int32_t draw_pass_3d_get_translucent_count(render_context* rctx) {
int32_t count = 0;
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_OPAQUE_ALPHA_ORDER_1);
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_1);
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_1);
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_OPAQUE_ALPHA_ORDER_2);
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2);
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2);
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_OPAQUE_ALPHA_ORDER_3);
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_3);
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_3);
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_OPAQUE_ALPHA_ORDER_2_LOCAL);
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2_LOCAL);
count += rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2_LOCAL);
return count;
}
static void draw_pass_3d_shadow_reset(render_context* rctx) {
gl_state_active_bind_texture_2d(6, 0);
gl_state_active_bind_texture_2d(7, 0);
rctx->obj_scene.set_g_self_shadow_receivers(0, mat4_identity);
rctx->obj_scene.set_g_self_shadow_receivers(1, mat4_identity);
rctx->draw_state.self_shadow = false;
rctx->draw_state.light = false;
}
static void draw_pass_3d_shadow_set(Shadow* shad, render_context* rctx) {
if (shad->self_shadow && shad->field_2EC > 0) {
gl_state_active_bind_texture_2d(19, shad->render_textures[3].color_texture->tex);
gl_state_active_bind_texture_2d(20, shad->render_textures[5].color_texture->tex);
gl_state_active_texture(0);
float_t esm_param = (shad->field_2D8 * shad->field_208 * 2.0f) * 1.442695f;
rctx->obj_scene.g_esm_param = { esm_param, 0.0f, 0.0f, 0.0f };
rctx->draw_state.self_shadow = true;
}
else {
gl_state_active_bind_texture_2d(19, rctx->empty_texture_2d);
gl_state_active_bind_texture_2d(20, rctx->empty_texture_2d);
gl_state_active_texture(0);
rctx->draw_state.self_shadow = false;
}
if (shad->field_2EC > 0) {
rctx->draw_state.light = true;
uniform_value[U_LIGHT_1] = shad->field_2EC > 1 ? 1 : 0;
float_t range = shad->view_region * shad->range;
for (int32_t i = 0; i < 2; i++) {
float_t v6 = 0.0f;
vec3* interest;
vec3* view_point;
if (shad->field_2F5) {
v6 = i ? 0.5f : -0.5f;
interest = &shad->interest[i];
view_point = &shad->view_point[i];
}
else {
interest = &shad->interest_shared;
view_point = &shad->view_point_shared;
}
mat4 temp;
mat4_translate(0.5f, 0.5f, 0.5f, &temp);
mat4_scale_rot(&temp, 0.5f, 0.5f, 0.5f, &temp);
mat4_mul_translate(&temp, v6, 0.0f, 0.0f, &temp);
mat4 proj;
mat4_ortho(-range, range, -range, range, shad->z_near, shad->z_far, &proj);
mat4_mul(&proj, &temp, &proj);
mat4 view;
mat4_look_at(view_point, interest, &view);
mat4_mul(&view, &proj, &view);
rctx->obj_scene.set_g_self_shadow_receivers(i, view);
}
for (int32_t i = 0, j = 0; i < 2; i++) {
if (!shad->field_2F0[i]) {
gl_state_active_bind_texture_2d(6 + j, rctx->empty_texture_2d);
continue;
}
gl_state_active_bind_texture_2d(6 + j, shad->curr_render_textures[1 + i]->color_texture->tex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f);
j++;
}
gl_state_active_texture(0);
light_set* set = &rctx->light_set[LIGHT_SET_MAIN];
light_data* data = &set->lights[LIGHT_SHADOW];
vec4 ambient;
if (data->get_type() == LIGHT_PARALLEL)
data->get_ambient(ambient);
else {
ambient.x = shad->ambient;
ambient.y = shad->ambient;
ambient.z = shad->ambient;
}
rctx->obj_scene.g_shadow_ambient = { ambient.x, ambient.y, ambient.z, 1.0f };
rctx->obj_scene.g_shadow_ambient1 = { 1.0f - ambient.x, 1.0f - ambient.y, 1.0f - ambient.z, 0.0f };
}
else {
rctx->draw_state.light = false;
for (int32_t i = 0; i < 2; i++)
gl_state_active_bind_texture_2d(6 + i, shad->curr_render_textures[1 + i]->color_texture->tex);
gl_state_active_texture(0);
rctx->obj_scene.g_shadow_ambient = 1.0f;
rctx->obj_scene.g_shadow_ambient1 = 0.0f;
}
}
static void draw_pass_3d_translucent(render_context* rctx, bool opaque_enable,
bool transparent_enable, bool translucent_enable, mdl::ObjType opaque,
mdl::ObjType transparent, mdl::ObjType translucent) {
if (rctx->disp_manager.get_obj_count(opaque) < 1
&& rctx->disp_manager.get_obj_count(transparent) < 1
&& rctx->disp_manager.get_obj_count(translucent) < 1)
return;
post_process* pp = &rctx->post_process;
int32_t alpha_array[256];
int32_t count = draw_pass_3d_translucent_count_layers(rctx,
alpha_array, opaque, transparent, translucent);
for (int32_t i = 0; i < count; i++) {
int32_t alpha = alpha_array[i];
fbo::blit(pp->rend_texture.fbos[0], pp->transparency_texture.fbos[0],
0, 0, pp->render_width, pp->render_height,
0, 0, pp->render_width, pp->render_height,
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
if (opaque_enable && rctx->disp_manager.get_obj_count(opaque))
rctx->disp_manager.draw_translucent(opaque, alpha);
if (transparent_enable && rctx->disp_manager.get_obj_count(transparent))
rctx->disp_manager.draw_translucent(transparent, alpha);
if (translucent_enable && rctx->disp_manager.get_obj_count(translucent)) {
gl_state_enable_blend();
rctx->disp_manager.draw_translucent(translucent, alpha);
gl_state_disable_blend();
}
transparency_batch_shader_data shader_data = {};
shader_data.g_opacity = { (float_t)alpha * (float_t)(1.0 / 255.0), 0.0f, 0.0f, 0.0f };
rctx->transparency_batch_ubo.WriteMemory(shader_data);
pp->buf_texture.Bind();
shaders_ft.set(SHADER_FT_TRANSPARENCY);
rctx->transparency_batch_ubo.Bind(0);
gl_state_active_bind_texture_2d(0, pp->transparency_texture.color_texture->tex);
gl_state_active_bind_texture_2d(1, pp->rend_texture.color_texture->tex);
RenderTexture::DrawCustom();
fbo::blit(pp->buf_texture.fbos[0], pp->rend_texture.fbos[0],
0, 0, pp->render_width, pp->render_height,
0, 0, pp->render_width, pp->render_height,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
}
static int32_t draw_pass_3d_translucent_count_layers(render_context* rctx,
int32_t* alpha_array, mdl::ObjType opaque,
mdl::ObjType transparent, mdl::ObjType translucent) {
bool arr[256] = { 0 };
draw_pass_3d_translucent_has_objects(rctx, arr, opaque);
draw_pass_3d_translucent_has_objects(rctx, arr, transparent);
draw_pass_3d_translucent_has_objects(rctx, arr, translucent);
int32_t count = 0;
for (int32_t i = 0xFF; i >= 1; i--)
if (arr[i]) {
count++;
*alpha_array++ = i;
}
return count;
}
static void draw_pass_3d_translucent_has_objects(render_context* rctx, bool* arr, mdl::ObjType type) {
std::vector<mdl::ObjData*>& vec = rctx->disp_manager.obj[type];
for (mdl::ObjData*& i : vec)
switch (i->kind) {
case mdl::OBJ_KIND_NORMAL: {
int32_t alpha = (int32_t)(i->args.sub_mesh.blend_color.w * 255.0f);
alpha = clamp_def(alpha, 0, 255);
arr[alpha] = true;
} break;
case mdl::OBJ_KIND_TRANSLUCENT: {
for (uint32_t j = 0; j < i->args.translucent.count; j++) {
int32_t alpha = (int32_t)(i->args.translucent.sub_mesh[j]->blend_color.w * 255.0f);
alpha = clamp_def(alpha, 0, 255);
arr[alpha] = true;
}
} break;
}
}
static void blur_filter_apply(render_context* rctx, GLuint dst, GLuint src,
blur_filter_mode filter, const vec2 res_scale, const vec4 scale, const vec4 offset) {
if (!dst || !src)
return;
texture_param tex_params[2];
texture_params_get(dst, &tex_params[0], src, &tex_params[1]);
filter_scene_shader_data filter_scene = {};
float_t w = res_scale.x / (float_t)tex_params[1].width;
float_t h = res_scale.y / (float_t)tex_params[1].height;
filter_scene.g_transform = { w, h, 0.0f, 0.0f };
filter_scene.g_texcoord = { 1.0f, 1.0f, 0.0f, 0.0f };
rctx->filter_scene_ubo.WriteMemory(filter_scene);
imgfilter_batch_shader_data imgfilter_batch = {};
if (filter == BLUR_FILTER_32)
imgfilter_batch.g_color_scale = scale * (float_t)(1.0 / 8.0);
else
imgfilter_batch.g_color_scale = scale * (float_t)(1.0 / 4.0);
imgfilter_batch.g_color_offset = offset;
imgfilter_batch.g_texture_lod = 0.0f;
rctx->imgfilter_batch_ubo.WriteMemory(imgfilter_batch);
uniform_value[U_IMAGE_FILTER] = filter == BLUR_FILTER_32 ? 1 : 0;
gl_state_bind_vertex_array(rctx->box_vao);
shaders_ft.set(SHADER_FT_IMGFILT);
rctx->filter_scene_ubo.Bind(0);
rctx->imgfilter_batch_ubo.Bind(1);
gl_state_active_bind_texture_2d(0, src);
glDrawArrays(GL_TRIANGLE_STRIP, (GLint)(filter * 4LL), 4);
texture_params_restore(&tex_params[0], &tex_params[1]);
}