From 3f040b47d795641f6ba66b7e4a77cd35cd83b953 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Wed, 27 May 2026 12:58:16 +0300 Subject: [PATCH] Overhaul of Shadow system Also fixed incorrect shadow with 3+ charas (Why it was like this?) --- src/CRE/auth_3d.cpp | 36 +- src/CRE/mdl/disp_manager.cpp | 20 +- src/CRE/mdl/disp_manager.hpp | 17 +- src/CRE/mdl/draw_object.cpp | 10 +- src/CRE/object.hpp | 1 - src/CRE/render_context.cpp | 5 +- src/CRE/render_manager.cpp | 316 ++----- src/CRE/render_manager.hpp | 8 +- src/CRE/rob/rob.cpp | 23 +- src/CRE/rob/rob.hpp | 2 +- src/CRE/shadow.cpp | 1035 ++++++++++++++++------- src/CRE/shadow.hpp | 262 ++++-- src/CRE/shared.hpp | 8 - src/CRE/stage.cpp | 53 +- src/CRE/stage_modern.cpp | 51 +- src/KKdLib/database/stage.cpp | 2 +- src/KKdLib/database/stage.hpp | 10 +- src/KKdLib/image.hpp | 7 + src/KKdLib/mat.cpp | 16 - src/KKdLib/mat.hpp | 1 - src/ReDIVA/data_test/auth_3d_test.cpp | 7 +- src/ReDIVA/data_test/object_test.cpp | 5 +- src/ReDIVA/graphics/reflect_refract.cpp | 4 +- src/ReDIVA/graphics/shadow.cpp | 101 +-- src/ReDIVA/pv_game/pv_game.cpp | 3 +- src/ReDIVA/pv_game/pv_game_pv_data.cpp | 24 +- src/ReDIVA/x_pv_game.cpp | 21 +- 27 files changed, 1154 insertions(+), 894 deletions(-) diff --git a/src/CRE/auth_3d.cpp b/src/CRE/auth_3d.cpp index cc32b20e..7caa8b7e 100644 --- a/src/CRE/auth_3d.cpp +++ b/src/CRE/auth_3d.cpp @@ -22,9 +22,10 @@ #include "effect.hpp" #include "object.hpp" #include "pv_db.hpp" -#include "task.hpp" +#include "shadow.hpp" #include "sound.hpp" #include "stage.hpp" +#include "task.hpp" namespace auth_3d_detail { class TaskAuth3d : public app::Task { @@ -2336,7 +2337,7 @@ namespace auth_3d_detail { enum_or(flag, in_scene.trnsl_state); disp_manager.set_obj_flags(flag); - disp_manager.set_shadow_group(SHADOW_GROUP_CHARA); + disp_manager.set_shadow_group(0); mat4 mat = mat4_identity; if (in_scene.M_assign_rob_id >= 0 && in_scene.M_assign_rob_id < ROB_ID_MAX) { @@ -2348,21 +2349,17 @@ namespace auth_3d_detail { ? &rob_chr->rob_base.adjust.item_mat : &rob_chr->rob_base.adjust.mat, &mat); if (in_scene.M_assign_rob_id) - disp_manager.set_shadow_group(SHADOW_GROUP_STAGE); + disp_manager.set_shadow_group(1); } } else if (flag & mdl::OBJ_SHADOW) { - disp_manager.set_shadow_group(SHADOW_GROUP_STAGE); + disp_manager.set_shadow_group(1); const mat4& root_matrix = get_root_matrix(); - Shadow* shad = shadow_ptr_get(); - if (shad) { - vec3 pos; - mat4_get_translation(&root_matrix, &pos); - pos.y -= 0.2f; - shad->positions[SHADOW_GROUP_STAGE].push_back(pos); - } + vec3 pos; + mat4_get_translation(&root_matrix, &pos); + get_shadow()->set_dist_base(1, &pos); } if (mats.size()) @@ -2370,7 +2367,7 @@ namespace auth_3d_detail { obj_uid, 0, 0, in_scene.trnsl, mats.data(), 0, 0, mat); disp_manager.set_obj_flags(); - disp_manager.set_shadow_group(SHADOW_GROUP_CHARA); + disp_manager.set_shadow_group(0); for (Object*& i : child_object_list) i->disp(in_scene, rctx); @@ -3405,10 +3402,10 @@ namespace auth_3d_detail { continue; mdl::ObjFlags flag = mdl::OBJ_SSS; - SHADOW_GROUP shadow_group = SHADOW_GROUP_CHARA; + int32_t shadow_group = 0; if (in_scene.M_shadow || i.shadow) { enum_or(flag, mdl::OBJ_4 | mdl::OBJ_SHADOW); - shadow_group = SHADOW_GROUP_STAGE; + shadow_group = 1; } if (in_scene.trnsl < 1.0f) enum_or(flag, in_scene.trnsl_state); @@ -3416,17 +3413,16 @@ namespace auth_3d_detail { disp_manager.set_obj_flags(flag); disp_manager.set_shadow_group(shadow_group); - Shadow* shad = shadow_ptr_get(); + Shadow* shad = get_shadow(); if (shad && (flag & mdl::OBJ_SHADOW)) { - disp_manager.set_shadow_group(SHADOW_GROUP_STAGE); + disp_manager.set_shadow_group(1); mat4 mat; mat4_mul(&i.motion_transform.matrix, &root_matrix, &mat); vec3 pos; mat4_get_translation(&mat, &pos); - pos.y -= 0.2f; - shad->positions[shadow_group].push_back(pos); + get_shadow()->set_dist_base(1, &pos); } if (i.mats.size()) @@ -3435,7 +3431,7 @@ namespace auth_3d_detail { } disp_manager.set_obj_flags(); - disp_manager.set_shadow_group(SHADOW_GROUP_CHARA); + disp_manager.set_shadow_group(0); } // 0x1401CAE40 @@ -3613,7 +3609,7 @@ namespace auth_3d_detail { ? &rob_chr->rob_base.adjust.item_mat : &rob_chr->rob_base.adjust.mat, &m); mat4_mul(&matrix, &m, &matrix); - disp_manager.set_shadow_group(in_scene.M_assign_rob_id ? SHADOW_GROUP_STAGE : SHADOW_GROUP_CHARA); + disp_manager.set_shadow_group(in_scene.M_assign_rob_id ? 1 : 0); } } diff --git a/src/CRE/mdl/disp_manager.cpp b/src/CRE/mdl/disp_manager.cpp index 79bc6fa1..7c7dc2c9 100644 --- a/src/CRE/mdl/disp_manager.cpp +++ b/src/CRE/mdl/disp_manager.cpp @@ -101,8 +101,8 @@ namespace mdl { int32_t slices, int32_t stacks, float_t radius); ObjSubMeshArgs::ObjSubMeshArgs() : sub_mesh(), mesh(), material(), textures(), mat_count(), mats(), - vb(), vb_offset(), ib(), set_blend_color(), chara_color(), self_shadow(), - shadow(), morph_vb(), morph_vb_offset(), morph_weight(), texture_pattern_count(), + vb(), vb_offset(), ib(), set_blend_color(), chara_color(), receive_shadow(), + shadow_group(), morph_vb(), morph_vb_offset(), morph_weight(), texture_pattern_count(), texture_transform_count(), instances_count(), instances_mat(), func(), func_data() { } @@ -345,12 +345,12 @@ namespace mdl { args->chara_color = disp_manager->chara_color; if (disp_manager->obj_flags & OBJ_4) - args->self_shadow = 1; + args->receive_shadow = RECEIVE_SHADOW_ENABLE; else if (disp_manager->obj_flags & mdl::OBJ_8) - args->self_shadow = 2; + args->receive_shadow = RECEIVE_SHADOW_DISABLE; else - args->self_shadow = 0; - args->shadow = disp_manager->shadow_group; + args->receive_shadow = RECEIVE_SHADOW_DEFAULT; + args->shadow_group = disp_manager->shadow_group; args->texture_color_coefficients = disp_manager->texture_color_coefficients; args->texture_color_coefficients.w = disp_manager->wet_param; args->texture_color_offset = disp_manager->texture_color_offset; @@ -2993,7 +2993,7 @@ namespace mdl { return obj_flags; } - SHADOW_GROUP DispManager::get_shadow_group() { + int32_t DispManager::get_shadow_group() { return shadow_group; } @@ -3248,9 +3248,9 @@ namespace mdl { morph.object = object; } - void DispManager::set_shadow_group(SHADOW_GROUP value) { - if (value >= 0 || value == SHADOW_GROUP_MAX) - shadow_group = value; + void DispManager::set_shadow_group(int32_t group) { + if (group >= 0 && group <= 2) + shadow_group = group; } void DispManager::set_texture_color_coefficients(const vec4& value) { diff --git a/src/CRE/mdl/disp_manager.hpp b/src/CRE/mdl/disp_manager.hpp index d12e52c6..34e1a465 100644 --- a/src/CRE/mdl/disp_manager.hpp +++ b/src/CRE/mdl/disp_manager.hpp @@ -12,7 +12,6 @@ #include "../GL/element_array_buffer.hpp" #include "../color.hpp" #include "../object.hpp" -#include "../shadow.hpp" #define MATERIAL_LIST_COUNT 24 #define TEXTURE_PATTERN_COUNT 24 @@ -180,6 +179,12 @@ namespace mdl { OBJ_TYPE_REFLECT_MAX, }; + enum ReceiveShadow { + RECEIVE_SHADOW_DEFAULT = 0, + RECEIVE_SHADOW_ENABLE, + RECEIVE_SHADOW_DISABLE, + }; + struct DispManager; struct ObjSubMeshArgs; @@ -197,8 +202,8 @@ namespace mdl { bool chara_color; vec4 blend_color; vec4 emission; - int32_t self_shadow; - SHADOW_GROUP shadow; + ReceiveShadow receive_shadow; + int32_t shadow_group; GLuint morph_vb; uint32_t morph_vb_offset; float_t morph_weight; @@ -485,7 +490,7 @@ namespace mdl { }; mdl::ObjFlags obj_flags; - SHADOW_GROUP shadow_group; + int32_t shadow_group; int32_t field_8; int32_t field_C; mdl::ObjList obj[mdl::OBJ_TYPE_MAX]; @@ -577,7 +582,7 @@ namespace mdl { int32_t get_obj_count(ObjTypeScreen type); int32_t get_obj_count(ObjTypeReflect type); ObjFlags get_obj_flags(); - SHADOW_GROUP get_shadow_group(); + int32_t get_shadow_group(); void get_texture_color_coeff(vec4& value); void get_texture_color_offset(vec4& value); void get_texture_pattern(int32_t& count, TexChange*& value); @@ -600,7 +605,7 @@ namespace mdl { void set_obj_flags(ObjFlags flags = (ObjFlags)0); void set_material_list(int32_t count = 0, const material_list_struct* value = 0); void set_morph(object_info object = {}, float_t weight = 0.0f); - void set_shadow_group(SHADOW_GROUP value = SHADOW_GROUP_CHARA); + void set_shadow_group(int32_t group = 0); void set_texture_color_coefficients(const vec4& value); void set_texture_color_offset(const vec4& value); void set_texture_pattern(int32_t count = 0, const TexChange* value = 0); diff --git a/src/CRE/mdl/draw_object.cpp b/src/CRE/mdl/draw_object.cpp index 1786672c..5f5f4c6b 100644 --- a/src/CRE/mdl/draw_object.cpp +++ b/src/CRE/mdl/draw_object.cpp @@ -662,14 +662,14 @@ static void draw_object_material_set_default(render_data_context& rend_data_ctx, draw_object_material_set_uniform(rend_data_ctx, material, false); if (!rctx_ptr->draw_state->rend_data[rend_data_ctx.index].shadow) rend_data_ctx.shader_flags.arr[U_STAGE_SHADOW] = 0; - else if (!args->self_shadow) + else if (args->receive_shadow == mdl::RECEIVE_SHADOW_DEFAULT) rend_data_ctx.shader_flags.arr[U_STAGE_SHADOW] = args->sub_mesh->attrib.m.receive_shadow ? 1 : 0; - else if (args->self_shadow != 1) - rend_data_ctx.shader_flags.arr[U_STAGE_SHADOW] = 0; - else + else if (args->receive_shadow == mdl::RECEIVE_SHADOW_ENABLE) rend_data_ctx.shader_flags.arr[U_STAGE_SHADOW] = 1; + else // mdl::RECEIVE_SHADOW_DISABLE + rend_data_ctx.shader_flags.arr[U_STAGE_SHADOW] = 0; - rend_data_ctx.shader_flags.arr[U_CHARA_SHADOW2] = args->shadow > SHADOW_GROUP_CHARA ? 1 : 0; + rend_data_ctx.shader_flags.arr[U_CHARA_SHADOW2] = args->shadow_group > 0 ? 1 : 0; rend_data_ctx.shader_flags.arr[U_CHARA_SHADOW] = rctx_ptr->draw_state->rend_data[rend_data_ctx.index].self_shadow ? 1 : 0; diff --git a/src/CRE/object.hpp b/src/CRE/object.hpp index acaca7f5..8aff19fc 100644 --- a/src/CRE/object.hpp +++ b/src/CRE/object.hpp @@ -16,7 +16,6 @@ #include "GL/buffer.hpp" #include "config.hpp" #include "file_handler.hpp" -#include "static_var.hpp" #include "texture.hpp" struct IndexBuffer; diff --git a/src/CRE/render_context.cpp b/src/CRE/render_context.cpp index 61890b72..bda5361f 100644 --- a/src/CRE/render_context.cpp +++ b/src/CRE/render_context.cpp @@ -8,6 +8,7 @@ #include "gl_rend_state.hpp" #include "gl_state.hpp" #include "shader_ft.hpp" +#include "shadow.hpp" #include "sound.hpp" #include "sprite.hpp" #include "task.hpp" @@ -1388,7 +1389,7 @@ void render_context::disp() { camera->update(); render_manager->cam.get(camera); app::disp_task(); - shadow_ptr_get()->ctrl(); + render_manager->calc_shadow(); spr::SPR_TARGET target = spr::getTarget(); //spr::setTarget(spr::SPR_TARGET_CSBACK); spr::setTarget(spr::SPR_TARGET_FRONT); @@ -1446,7 +1447,7 @@ void render_context::init() { RenderTexture& render_buffer = render.rend_texture[0]; RenderTexture& reflect_buffer = render_manager->get_render_texture(0); - RenderTexture& shadow_buffer = shadow_ptr_get()->render_textures[1]; + RenderTexture& shadow_buffer = get_shadow()->get_rtex(1); init_copy_buffer(reflect_buffer, this->reflect_buffer); init_copy_buffer(render_buffer, this->render_buffer); init_copy_buffer(shadow_buffer, this->shadow_buffer); diff --git a/src/CRE/render_manager.cpp b/src/CRE/render_manager.cpp index 55e0f8de..34b8009a 100644 --- a/src/CRE/render_manager.cpp +++ b/src/CRE/render_manager.cpp @@ -21,25 +21,20 @@ #include "render_context.hpp" #include "render_texture.hpp" #include "shader_ft.hpp" +#include "shadow.hpp" #include "sprite.hpp" #include "static_var.hpp" #include "texture.hpp" extern render_context* rctx_ptr; -static void draw_pass_shadow_begin_make_shadowmap(Shadow* shad, - render_data_context& rend_data_ctx, cam_data& cam, int32_t index, int32_t a3); -static void draw_pass_shadow_end_make_shadowmap(Shadow* shad, - render_data_context& rend_data_ctx, int32_t index, int32_t a3); -static void apply_esm_filter(render_data_context& rend_data_ctx, +void apply_esm_filter(render_data_context& rend_data_ctx, RenderTexture* dst, RenderTexture* buf, RenderTexture* src, - float_t sigma, float_t far_texel_offset, bool enable_lit_proj); -static void apply_esm_min_filter(render_data_context& rend_data_ctx, + float_t sigma, float_t offset, bool enable_lit_proj); +void apply_esm_min_filter(render_data_context& rend_data_ctx, RenderTexture* dst, RenderTexture* buf, RenderTexture* src); static bool litproj_clear(render_data_context& rend_data_ctx, light_proj* litproj, cam_data& cam); static int32_t draw_pass_3d_get_translucent_count(render_context* rctx); -static void draw_pass_3d_shadow_reset(render_data_context& rend_data_ctx, render_context* rctx); -static void draw_pass_3d_shadow_set(render_data_context& rend_data_ctx, Shadow* shad, render_context* rctx); extern void draw_pass_3d_translucent(render_data_context& rend_data_ctx, render_context* rctx, mdl::ObjType opaque, mdl::ObjType transparent, mdl::ObjType translucent, cam_data& cam); @@ -59,8 +54,8 @@ static void draw_pass_3d_translucent_has_objects( static void draw_pass_reflect_full(render_data_context& rend_data_ctx, rndr::RenderManager* render_manager); -static void apply_blur_filter_sub(render_data_context& rend_data_ctx, RenderTexture* dst, RenderTexture* src, - blur_filter_mode filter, const vec2 res_scale, const vec4 scale, const vec4 offset); +void apply_blur_filter_sub(render_data_context& rend_data_ctx, RenderTexture* dst, RenderTexture* src, + ImgfBoxSampl filter, const vec2 res_scale, const vec4 scale, const vec4 offset); static void render_manager_free_render_textures(); static void render_manager_init_render_textures(int32_t multisample); @@ -133,6 +128,34 @@ namespace rndr { pre_process.push_back({ type, func, data }); } + // 0x140502390 + void RenderManager::calc_shadow() { + shadow_ptr->reset_group(); + + if (shadow) { + shadow_ptr->set_view_mtx(&rctx_ptr->camera->view); + + light_data& light_chara = rctx_ptr->light_set[LIGHT_SET_MAIN].lights[LIGHT_CHARA]; + + vec3 dir; + light_chara.get_position(dir); + dir = -dir; + + float_t length = vec3::length(dir); + if (length < 0.000001f) + dir = { 0.0f, 1.0f, 0.0f }; + else if (length != 0.0) + dir *= (1.0f / length); + shadow_ptr->set_light_dir(&dir); + + for (int32_t i = 0; i < 2; i++) + if (rctx_ptr->disp_manager->get_obj_count((mdl::ObjType)((int32_t)mdl::OBJ_TYPE_SHADOW_CHARA + i))) + shadow_ptr->enable_group(i); + } + + shadow_ptr->calc_shadowmap(); + } + void RenderManager::clear_pre_process(int32_t type) { for (auto i = pre_process.begin(); i != pre_process.end(); i++) if (i->type == type) { @@ -177,7 +200,7 @@ namespace rndr { silhouette_high = false; reflect_blur_num = 1; - reflect_blur_filter = BLUR_FILTER_4; + reflect_blur_filter = IMGF_BOX_SAMPL_4; show_ref_map = false; reflect_type = STAGE_DATA_REFLECT_DISABLE; @@ -263,7 +286,7 @@ namespace rndr { reflect = value; } - void RenderManager::set_reflect_blur(int32_t reflect_blur_num, blur_filter_mode reflect_blur_filter) { + void RenderManager::set_reflect_blur(int32_t reflect_blur_num, ImgfBoxSampl reflect_blur_filter) { this->reflect_blur_num = reflect_blur_num; this->reflect_blur_filter = reflect_blur_filter; } @@ -482,35 +505,34 @@ namespace rndr { Shadow* shad = shadow_ptr; if (shadow && make_shadowmap) { - int32_t index[2]; - shad->set_curr_render_textures(index); + int32_t group[2]; + shad->begin_make_shadow_textures(group); cam_data cam; - for (int32_t i = 0, j = 0; i < 2; i++) { + for (int32_t i = 0, index = 0; i < 2; i++) { if (!obj_shadow_count[i]) continue; - draw_pass_shadow_begin_make_shadowmap(shad, rend_data_ctx, cam, index[i], j); + shad->begin_make_silhouette_map(rend_data_ctx, cam, group[i], index); rend_data_ctx.set_batch_scene_camera(cam); - rctx->disp_manager->draw(rend_data_ctx, (mdl::ObjType)(mdl::OBJ_TYPE_SHADOW_CHARA + index[i]), cam); + rctx->disp_manager->draw(rend_data_ctx, (mdl::ObjType)(mdl::OBJ_TYPE_SHADOW_CHARA + group[i]), cam); if (rctx->disp_manager->get_obj_count( - (mdl::ObjType)(mdl::OBJ_TYPE_SHADOW_OBJECT_CHARA + index[i])) > 0) { + (mdl::ObjType)(mdl::OBJ_TYPE_SHADOW_OBJECT_CHARA + group[i])) > 0) { rend_data_ctx.state.set_color_mask(show_stage_shadow ? GL_TRUE : GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); rctx->disp_manager->draw(rend_data_ctx, (mdl::ObjType)(mdl::OBJ_TYPE_SHADOW_OBJECT_CHARA + i), cam); rend_data_ctx.state.set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } - draw_pass_shadow_end_make_shadowmap(shad, rend_data_ctx, index[i], j); - j++; + shad->end_make_silhouette_map(rend_data_ctx, group[i], index); + index++; } } else { - shad->set_curr_render_textures(0); - shad->clear_textures(rend_data_ctx.state); + shad->begin_make_shadow_textures(0); + shad->clear(rend_data_ctx.state); } - shader::unbind(rend_data_ctx.state); - rend_data_ctx.state.bind_framebuffer(0); + shad->end_make_shadow_textures(rend_data_ctx.state); rend_data_ctx.state.end_event(); } @@ -539,9 +561,9 @@ namespace rndr { rctx->light_set[i].data_set(rend_data_ctx, rctx->face, (light_set_id)i); if (shadow) - draw_pass_3d_shadow_set(rend_data_ctx, shadow_ptr, rctx); + shadow_ptr->bind_shadow(rend_data_ctx, rctx); else - draw_pass_3d_shadow_reset(rend_data_ctx, rctx); + shadow_ptr->unbind_shadow(rend_data_ctx, rctx); cam_data reflect_cam = cam; set_reflect_mat(rend_data_ctx, reflect_cam); @@ -554,7 +576,7 @@ namespace rndr { rctx->disp_manager->draw(rend_data_ctx, mdl::OBJ_TYPE_SSS, reflect_cam); rend_data_ctx.state.disable_depth_test(); rctx->draw_state->rend_data[rend_data_ctx.index].shader_index = -1; - draw_pass_3d_shadow_reset(rend_data_ctx, rctx); + shadow_ptr->unbind_shadow(rend_data_ctx, rctx); rend_data_ctx.shader_flags.arr[U_NPR] = 0; if (npr_param == 1) { @@ -592,9 +614,9 @@ namespace rndr { rctx->light_set[i].data_set(rend_data_ctx, rctx->face, (light_set_id)i); if (shadow) - draw_pass_3d_shadow_set(rend_data_ctx, shadow_ptr, rctx); + shadow_ptr->bind_shadow(rend_data_ctx, rctx); else - draw_pass_3d_shadow_reset(rend_data_ctx, rctx); + shadow_ptr->unbind_shadow(rend_data_ctx, rctx); rend_data_ctx.set_batch_scene_camera(cam); @@ -605,7 +627,7 @@ namespace rndr { rctx->disp_manager->draw(rend_data_ctx, mdl::OBJ_TYPE_SSS, cam); rend_data_ctx.state.disable_depth_test(); rctx->draw_state->rend_data[rend_data_ctx.index].shader_index = -1; - draw_pass_3d_shadow_reset(rend_data_ctx, rctx); + shadow_ptr->unbind_shadow(rend_data_ctx, rctx); rend_data_ctx.shader_flags.arr[U_NPR] = 0; if (npr_param == 1) { @@ -694,9 +716,9 @@ namespace rndr { rctx->draw_state->rend_data[rend_data_ctx.index].shader_index = -1; if (shadow) - draw_pass_3d_shadow_set(rend_data_ctx, shadow_ptr, rctx); + shadow_ptr->bind_shadow(rend_data_ctx, rctx); else - draw_pass_3d_shadow_reset(rend_data_ctx, rctx); + shadow_ptr->unbind_shadow(rend_data_ctx, rctx); if (effect_texture) rend_data_ctx.state.active_bind_texture_2d(14, effect_texture->glid); @@ -740,7 +762,7 @@ namespace rndr { } if (shadow) - draw_pass_3d_shadow_reset(rend_data_ctx, rctx); + shadow_ptr->unbind_shadow(rend_data_ctx, rctx); reflect_draw = false; } else if (reflect_type == STAGE_DATA_REFLECT_REFLECT_MAP) { @@ -924,9 +946,9 @@ namespace rndr { rctx->fog[i].data_set(rend_data_ctx, (fog_id)i); if (shadow) - draw_pass_3d_shadow_set(rend_data_ctx, shadow_ptr, rctx); + shadow_ptr->bind_shadow(rend_data_ctx, rctx); else - draw_pass_3d_shadow_reset(rend_data_ctx, rctx); + shadow_ptr->unbind_shadow(rend_data_ctx, rctx); if (effect_texture) rend_data_ctx.state.active_bind_texture_2d(14, effect_texture->glid); @@ -1103,7 +1125,7 @@ namespace rndr { refl_tex->unbind_texture(rend_data_ctx.state); if (shadow) - draw_pass_3d_shadow_reset(rend_data_ctx, rctx); + shadow_ptr->unbind_shadow(rend_data_ctx, rctx); pass_sprite_surf(rend_data_ctx); shader::unbind(rend_data_ctx.state); render->end_render(rend_data_ctx.state); @@ -1309,9 +1331,9 @@ void render_manager_init_data(int32_t ssaa, int32_t hd_res, int32_t ss_alpha_mas render_manager_init_render_textures(1); render_manager.render->init_post_process_buffers(); - shadow_ptr_init(); - render_manager.shadow_ptr = shadow_ptr_get(); - render_manager.shadow_ptr->init(); + init_shadow(); + render_manager.shadow_ptr = get_shadow(); + render_manager.shadow_ptr->create(); rctx_ptr->sss_data->init(); gl_get_error_print(); @@ -1322,90 +1344,14 @@ void render_manager_free_data() { render_manager_free_render_textures(); render_manager.render->free(); - shadow_ptr_free(); + finish_shadow(); rctx_ptr->sss_data->free(); } -static void draw_pass_shadow_begin_make_shadowmap(Shadow* shad, - render_data_context& rend_data_ctx, cam_data& cam, int32_t index, int32_t a3) { - render_context* rctx = rctx_ptr; - shad->curr_render_textures[0]->begin_render(rend_data_ctx.state); - texture* tex = shad->curr_render_textures[0]->get_texture(); - rend_data_ctx.state.set_viewport(1, 1, tex->width - 2, tex->width - 2); - rend_data_ctx.state.enable_depth_test(); - rend_data_ctx.state.clear_color(1.0f, 1.0f, 1.0f, 1.0f); - if (!a3) - rend_data_ctx.state.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else if (shad->separate) - rend_data_ctx.state.clear(GL_COLOR_BUFFER_BIT); - - float_t shadow_range = shad->get_shadow_range(); - float_t offset; - vec3* interest; - vec3* view_point; - if (shad->separate) { - offset = index ? 0.5f : -0.5f; - interest = &shad->interest[index]; - view_point = &shad->view_point[index]; - } - else { - offset = 0.0f; - interest = &shad->interest_shared; - view_point = &shad->view_point_shared; - } - - const float_t scale = (float_t)(tex->width / 2) / (float_t)((tex->width - 2) / 2); - shad->calc_proj_view_mat(cam, *view_point, *interest, shadow_range, offset, scale); - rctx->draw_state->rend_data[rend_data_ctx.index].shader_index = SHADER_FT_SIL; - rend_data_ctx.shader_flags.arr[U_DEPTH] = 0; -} - -static void draw_pass_shadow_end_make_shadowmap(Shadow* shad, - render_data_context& rend_data_ctx, int32_t index, int32_t a3) { - render_context* rctx = rctx_ptr; - rend_data_ctx.state.disable_depth_test(); - - rctx->draw_state->rend_data[rend_data_ctx.index].shader_index = -1; - if (a3 == shad->num_shadow - 1) { - apply_esm_filter(rend_data_ctx, &shad->render_textures[3], - &shad->render_textures[4], shad->curr_render_textures[0], - shad->field_2DC, shad->field_2E0 / (shad->z_half_range * 2.0f), false); - apply_esm_min_filter(rend_data_ctx, &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 = rctx_ptr->shadow_buffer; - - image_filter_scale(rend_data_ctx, rend_tex, - shad->curr_render_textures[0]->get_texture()); - - if (shad->blur_filter_enable[index]) { - for (int32_t i = shad->near_blur, j = 0; i > 0; i--, j++) { - apply_blur_filter_sub(rend_data_ctx, &rend_buf_tex, rend_tex, - shad->blur_filter, 1.0f, 1.0f, 0.0f); - image_filter_scale(rend_data_ctx, rend_tex, rend_buf_tex.get_texture()); - } - } - else { - rend_buf_tex.begin_render(rend_data_ctx.state); - rend_data_ctx.state.clear_color(1.0f, 1.0f, 1.0f, 1.0f); - rend_data_ctx.state.clear(GL_COLOR_BUFFER_BIT); - } - rend_buf_tex.end_render(rend_data_ctx.state); - - if (GLAD_GL_VERSION_4_5) - rend_data_ctx.state.generate_texture_mipmap(rend_tex->get_texture_glid()); - else { - rend_data_ctx.state.bind_texture_2d(rend_tex->get_texture_glid()); - rend_data_ctx.state.generate_mipmap(GL_TEXTURE_2D); - rend_data_ctx.state.bind_texture_2d(0); - } -} - -static void apply_esm_filter(render_data_context& rend_data_ctx, +// 0x1403B6560 +void apply_esm_filter(render_data_context& rend_data_ctx, RenderTexture* dst, RenderTexture* buf, RenderTexture* src, - float_t sigma, float_t far_texel_offset, bool enable_lit_proj) { + float_t sigma, float_t offset, bool enable_lit_proj) { texture* dst_tex = dst->get_texture(); texture* buf_tex = buf->get_texture(); texture* src_tex = dst->get_texture(); @@ -1437,7 +1383,7 @@ static void apply_esm_filter(render_data_context& rend_data_ctx, rend_data_ctx.state.set_viewport(0, 0, dst_tex->width, dst_tex->height); buf->begin_render(rend_data_ctx.state); - esm_filter_batch.g_params = { 1.0f / (float_t)dst_tex->width, 0.0f, far_texel_offset, far_texel_offset }; + esm_filter_batch.g_params = { 1.0f / (float_t)dst_tex->width, 0.0f, offset, offset }; rend_data_ctx.state.write_uniform_buffer(rctx->esm_filter_batch_ubo, esm_filter_batch); rend_data_ctx.state.active_bind_texture_2d(0, src_tex->glid); @@ -1446,7 +1392,7 @@ static void apply_esm_filter(render_data_context& rend_data_ctx, rend_data_ctx.state.draw_arrays(GL_TRIANGLE_STRIP, 0, 4); dst->begin_render(rend_data_ctx.state); - esm_filter_batch.g_params = { 0.0f, 1.0f / (float_t)dst_tex->height, far_texel_offset, far_texel_offset }; + esm_filter_batch.g_params = { 0.0f, 1.0f / (float_t)dst_tex->height, offset, offset }; rend_data_ctx.state.write_uniform_buffer(rctx->esm_filter_batch_ubo, esm_filter_batch); rend_data_ctx.state.active_bind_texture_2d(0, buf_tex->glid); @@ -1457,7 +1403,8 @@ static void apply_esm_filter(render_data_context& rend_data_ctx, rend_data_ctx.state.end_event(); } -static void apply_esm_min_filter(render_data_context& rend_data_ctx, +// 0x1403B6950 +void apply_esm_min_filter(render_data_context& rend_data_ctx, RenderTexture* dst, RenderTexture* buf, RenderTexture* src) { texture* dst_tex = dst->get_texture(); texture* buf_tex = buf->get_texture(); @@ -1558,114 +1505,6 @@ static int32_t draw_pass_3d_get_translucent_count(render_context* rctx) { return count; } -static void draw_pass_3d_shadow_reset(render_data_context& rend_data_ctx, render_context* rctx) { - rend_data_ctx.state.active_bind_texture_2d(6, rctx->empty_texture_2d->glid); - rend_data_ctx.state.active_bind_texture_2d(7, rctx->empty_texture_2d->glid); - rend_data_ctx.set_self_shadow(false); - rend_data_ctx.set_shadow(false); -} - -static void draw_pass_3d_shadow_set(render_data_context& rend_data_ctx, Shadow* shad, render_context* rctx) { - float_t esm_param; - if (shad->self_shadow && shad->num_shadow > 0) { - rend_data_ctx.state.active_bind_texture_2d(19, shad->render_textures[3].get_texture_glid()); - rend_data_ctx.state.active_bind_texture_2d(20, shad->render_textures[5].get_texture_glid()); - rend_data_ctx.state.active_texture(0); - esm_param = (shad->field_2D8 * shad->z_half_range * 2.0f) * 1.442695f; - rend_data_ctx.set_self_shadow(true); - } - else { - rend_data_ctx.state.active_bind_texture_2d(19, rctx->empty_texture_2d->glid); - rend_data_ctx.state.active_bind_texture_2d(20, rctx->empty_texture_2d->glid); - rend_data_ctx.state.active_texture(0); - esm_param = 0.0f; - rend_data_ctx.set_self_shadow(false); - } - - rend_data_ctx.state.bind_sampler(19, rctx->render_samplers[0]); - rend_data_ctx.state.bind_sampler(20, rctx->render_samplers[0]); - - mat4 mats[2]; - mats[0] = mat4_identity; - mats[1] = mat4_identity; - vec4 shadow_ambient; - vec4 shadow_ambient1; - if (shad->num_shadow > 0) { - rctx->draw_state->rend_data[rend_data_ctx.index].shadow = true; - rend_data_ctx.shader_flags.arr[U_STAGE_SHADOW2] = shad->num_shadow > 1 ? 1 : 0; - - float_t shadow_range = shad->get_shadow_range(); - for (int32_t i = 0; i < 2; i++) { - float_t offset; - vec3* interest; - vec3* view_point; - if (shad->separate) { - offset = i ? 0.5f : -0.5f; - - interest = &shad->interest[i]; - view_point = &shad->view_point[i]; - } - else { - offset = 0.0f; - 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, offset, 0.0f, 0.0f, &temp); - - mat4 proj; - mat4_ortho(-shadow_range, shadow_range, - -shadow_range, shadow_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, &mats[i]); - } - - int32_t j = 0; - for (int32_t i = 0; i < 2; i++) - if (shad->shadow_enable[i]) { - rend_data_ctx.state.active_bind_texture_2d(6 + j, shad->curr_render_textures[1 + i]->get_texture_glid()); - j++; - } - - for (; j < 2; j++) - rend_data_ctx.state.active_bind_texture_2d(6 + j, rctx->empty_texture_2d->glid); - rend_data_ctx.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 - *(vec3*)&ambient.x = shad->shadow_ambient; - - shadow_ambient = { ambient.x, ambient.y, ambient.z, 1.0f }; - shadow_ambient1 = { 1.0f - ambient.x, 1.0f - ambient.y, 1.0f - ambient.z, 0.0f }; - } - else { - rctx->draw_state->rend_data[rend_data_ctx.index].shadow = false; - - for (int32_t i = 0; i < 2; i++) - shad->curr_render_textures[1 + i]->bind_texture(rend_data_ctx.state, 6 + i); - rend_data_ctx.state.active_texture(0); - - shadow_ambient = 1.0f; - shadow_ambient1 = 0.0f; - } - - rend_data_ctx.set_scene_shadow_params(esm_param, mats, shadow_ambient, shadow_ambient1); - - rend_data_ctx.state.bind_sampler(6, 0); - rend_data_ctx.state.bind_sampler(7, 0); -} - static void draw_pass_3d_translucent(render_data_context& rend_data_ctx, render_context* rctx, mdl::ObjType opaque, mdl::ObjType transparent, mdl::ObjType translucent, cam_data& cam) { @@ -1855,9 +1694,9 @@ static void draw_pass_reflect_full(render_data_context& rend_data_ctx, rndr::Ren rctx->draw_state->rend_data[rend_data_ctx.index].shader_index = -1; if (render_manager->shadow) - draw_pass_3d_shadow_set(rend_data_ctx, render_manager->shadow_ptr, rctx); + render_manager->shadow_ptr->bind_shadow(rend_data_ctx, rctx); else - draw_pass_3d_shadow_reset(rend_data_ctx, rctx); + render_manager->shadow_ptr->unbind_shadow(rend_data_ctx, rctx); if (render_manager->effect_texture) rend_data_ctx.state.active_bind_texture_2d(14, render_manager->effect_texture->glid); @@ -1948,7 +1787,7 @@ static void draw_pass_reflect_full(render_data_context& rend_data_ctx, rndr::Ren rend_data_ctx.state.active_bind_texture_2d(15, 0); if (render_manager->shadow) - draw_pass_3d_shadow_reset(rend_data_ctx, rctx); + render_manager->shadow_ptr->unbind_shadow(rend_data_ctx, rctx); reflect_draw = false; rend_data_ctx.state.set_cull_face_mode(GL_BACK); @@ -1975,8 +1814,9 @@ static void draw_pass_reflect_full(render_data_context& rend_data_ctx, rndr::Ren rend_data_ctx.state.end_event(); } -static void apply_blur_filter_sub(render_data_context& rend_data_ctx, RenderTexture* dst, RenderTexture* src, - blur_filter_mode filter, const vec2 res_scale, const vec4 scale, const vec4 offset) { +// Added +void apply_blur_filter_sub(render_data_context& rend_data_ctx, RenderTexture* dst, RenderTexture* src, + ImgfBoxSampl filter, const vec2 res_scale, const vec4 scale, const vec4 offset) { if (!dst || !src) return; @@ -1995,7 +1835,7 @@ static void apply_blur_filter_sub(render_data_context& rend_data_ctx, RenderText rend_data_ctx.state.write_uniform_buffer(rctx->image_filter_scene_ubo, filter_scene); image_filter_batch_shader_data image_filter_batch = {}; - if (filter == BLUR_FILTER_32) + if (filter == IMGF_BOX_SAMPL_32) image_filter_batch.g_color_scale = scale * (float_t)(1.0 / 8.0); else image_filter_batch.g_color_scale = scale * (float_t)(1.0 / 4.0); @@ -2003,7 +1843,7 @@ static void apply_blur_filter_sub(render_data_context& rend_data_ctx, RenderText image_filter_batch.g_texture_lod = 0.0f; rend_data_ctx.state.write_uniform_buffer(rctx->image_filter_batch_ubo, image_filter_batch); - rend_data_ctx.shader_flags.arr[U_IMAGE_FILTER] = filter == BLUR_FILTER_32 ? 1 : 0; + rend_data_ctx.shader_flags.arr[U_IMAGE_FILTER] = filter == IMGF_BOX_SAMPL_32 ? 1 : 0; rend_data_ctx.state.bind_vertex_array(rctx->box_vao); shaders_ft.set(rend_data_ctx.state, rend_data_ctx.shader_flags, SHADER_FT_IMGFILT); rend_data_ctx.state.bind_uniform_buffer_base(0, rctx->image_filter_scene_ubo); diff --git a/src/CRE/render_manager.hpp b/src/CRE/render_manager.hpp index 5d3ac4eb..4391b36d 100644 --- a/src/CRE/render_manager.hpp +++ b/src/CRE/render_manager.hpp @@ -6,10 +6,10 @@ #pragma once #include "../KKdLib/default.hpp" +#include "../KKdLib/time.hpp" #include "../KKdLib/vec.hpp" #include "gl.hpp" #include "render.hpp" -#include "shadow.hpp" #include enum reflect_refract_resolution_mode { @@ -28,6 +28,7 @@ struct draw_pre_process { void* data; }; +class Shadow; struct render_data_context; namespace rndr { @@ -54,7 +55,7 @@ namespace rndr { bool reflect; bool refract; int32_t reflect_blur_num; - blur_filter_mode reflect_blur_filter; + ImgfBoxSampl reflect_blur_filter; rndr::Render* render; bool sync_gpu; double_t cpu_time[RND_PASSID_NUM]; @@ -97,6 +98,7 @@ namespace rndr { ~RenderManager(); void add_pre_process(int32_t type, draw_pre_process_func func, void* data); + void calc_shadow(); void clear_pre_process(int32_t type); reflect_refract_resolution_mode get_reflect_resolution_mode(); reflect_refract_resolution_mode get_refract_resolution_mode(); @@ -109,7 +111,7 @@ namespace rndr { void set_npr_param(int32_t value); void set_pass_sw(rndr::RenderPassID id, bool value); void set_reflect(bool value); - void set_reflect_blur(int32_t reflect_blur_num, blur_filter_mode reflect_blur_filter); + void set_reflect_blur(int32_t reflect_blur_num, ImgfBoxSampl reflect_blur_filter); void set_reflect_resolution_mode(reflect_refract_resolution_mode mode); void set_reflect_type(int32_t type); void set_refract(bool value); diff --git a/src/CRE/rob/rob.cpp b/src/CRE/rob/rob.cpp index 6f2e0590..716cdb47 100644 --- a/src/CRE/rob/rob.cpp +++ b/src/CRE/rob/rob.cpp @@ -24,6 +24,7 @@ #include "../pv_expression.hpp" #include "../random.hpp" #include "../screen_param.hpp" +#include "../shadow.hpp" #include "../stage.hpp" #include "../stage_param.hpp" #include "../static_var.hpp" @@ -14008,16 +14009,14 @@ void RobDisp::disp(int32_t rob_id, render_context* rctx) { mdl::DispManager& disp_manager = *rctx->disp_manager; if (shadow_group != -1) { if (shadow_flag & 0x04) { - vec3 pos = position; - pos.y -= 0.2f; - shadow_ptr_get()->positions[shadow_group].push_back(pos); + get_shadow()->set_dist_base(shadow_group, &position); - float_t v9; + float_t ground_ypos; if (sub_140512F60(this) <= -0.2f) - v9 = -0.5f; + ground_ypos = -0.5f; else - v9 = 0.05f; - shadow_ptr_get()->field_1C0[shadow_group] = v9; + ground_ypos = 0.05f; + get_shadow()->set_ground_ypos(shadow_group, ground_ypos); disp_manager.set_shadow_group(shadow_group); enum_or(flags, mdl::OBJ_SHADOW); } @@ -14115,7 +14114,7 @@ void RobDisp::dest() { for (int32_t i = 0; i < RPK_MAX; i++) skin_disp[i].dest(); one_skin = false; - shadow_group = (SHADOW_GROUP)-1; + shadow_group = -1; shadow_flag = 0x05; hyoutan_texchg_list.clear(); hyoutan_obj = {}; @@ -14373,9 +14372,9 @@ void RobDisp::set_shadow(ROB_PARTS_KIND rpk, bool flag) { // 0x140514170 void RobDisp::set_shadow_group(int32_t group) { - if (group != SHADOW_GROUP_CHARA) - group = SHADOW_GROUP_STAGE; - shadow_group = (SHADOW_GROUP)group; + if (group != 0) + group = 1; + shadow_group = group; } // 0x1405141B0 @@ -18131,7 +18130,7 @@ void rob_chara_age_age_object::disp(render_context* rctx, size_t id, enum_or(flags, mdl::OBJ_CHARA_REFLECT); rctx->disp_manager->set_obj_flags(flags); rctx->disp_manager->set_chara_color(chara_color); - rctx->disp_manager->set_shadow_group(id ? SHADOW_GROUP_STAGE : SHADOW_GROUP_CHARA); + rctx->disp_manager->set_shadow_group(id ? 1 : 0); rctx->disp_manager->entry_obj_by_obj(mat4_identity, &obj, &get_obj_set_texture(), &vb, &ib, 0, 1.0f); } diff --git a/src/CRE/rob/rob.hpp b/src/CRE/rob/rob.hpp index cb38e58d..ba269bf5 100644 --- a/src/CRE/rob/rob.hpp +++ b/src/CRE/rob/rob.hpp @@ -3651,7 +3651,7 @@ public: int32_t disp_begin; int32_t disp_max; uint32_t shadow_flag; - SHADOW_GROUP shadow_group; + int32_t shadow_group; vec3 position; std::vector hyoutan_texchg_list; object_info hyoutan_obj; diff --git a/src/CRE/shadow.cpp b/src/CRE/shadow.cpp index 402d5bd4..6df25b04 100644 --- a/src/CRE/shadow.cpp +++ b/src/CRE/shadow.cpp @@ -6,135 +6,424 @@ #include "shadow.hpp" #include "gl_state.hpp" #include "render_context.hpp" - -Shadow* shadow_ptr; - -extern render_context* rctx_ptr; +#include "shader_ft.hpp" #define MIN_SHADOW_RANGE (1.2f) #define SHADOW_RANGE_SEPARATE (MIN_SHADOW_RANGE * 2.0f) -static void sub_1405E60E0(Shadow* shad); -static void sub_1405E63D0(Shadow* shad); -static void sub_1405E6840(Shadow* shad); -static void sub_1405E6910(Shadow* shad); -static void sub_1405E6B70(Shadow* shad); +struct ShadowTexParam { + GLenum target; + int32_t width; + int32_t height; + int32_t level; + GLenum pixel_format; + GLenum depth_format; +}; -Shadow::Shadow() : curr_render_textures(), shadow_range(), shadow_range_factor(), field_1C0(), field_1C8(), -index(), z_half_range(), near_blur(), blur_filter(), far_blur(), field_2BC(), distance(), field_2C4(), -z_near(), z_far(), field_2D0(), field_2D4(), field_2D8(), field_2DC(), field_2E0(), shadow_ambient(), -show_texture(), num_shadow(), shadow_enable(), self_shadow(), blur_filter_enable(), separate() { - reset(); -} +// 0x14CC587B8 +static Shadow* g_shadow; -Shadow::~Shadow() { - free(); -} +extern render_context* rctx_ptr; -void Shadow::calc_proj_view_mat(cam_data& cam, const vec3& view_point, - const vec3& interest, float_t range, float_t offset, float_t scale) { - cam.set_view_point(view_point); - cam.set_interest(interest); +// 0x140A81E00 +static const ShadowTexParam shadow_tex_param_table[] = { + { GL_TEXTURE_2D, 0x800, 0x800, 0, GL_RGBA8, GL_DEPTH_COMPONENT32F }, + { GL_TEXTURE_2D, 0x200, 0x200, 3, GL_RGBA8, GL_ZERO }, + { GL_TEXTURE_2D, 0x200, 0x200, 3, GL_RGBA8, GL_ZERO }, + { GL_TEXTURE_2D, 0x800, 0x800, 0, GL_R32F , GL_ZERO }, + { GL_TEXTURE_2D, 0x800, 0x800, 0, GL_R32F , GL_ZERO }, + { GL_TEXTURE_2D, 0x200, 0x200, 0, GL_R32F , GL_ZERO }, + { GL_TEXTURE_2D, 0x200, 0x200, 0, GL_R32F , GL_ZERO }, +}; - vec3 up = { 0.0f, 1.0f, 0.0f }; - const vec3 dir = interest - view_point; - if (vec3::length_squared(dir) <= 0.000001f) { - up.x = 0.0f; - up.y = 0.0f; - if (dir.z < 0.0f) - up.z = 1.0f; - else - up.z = -1.0f; +static void dbg_draw_texture(float_t x, float_t y, + float_t width, float_t height, GLuint texture); +static void dbg_draw_texture_uv(float_t x, float_t y, + float_t width, float_t height, float_t s, float_t t, GLuint texture); +static void dbg_draw_texture_uv_mm(float_t x, float_t y, + float_t width, float_t height, float_t s, float_t t, int32_t level, GLuint texture); +static void M_calc_light_up(vec3* light_up, const vec3* light_pos, const vec3* light_target); + +// 0x1405E8690 +void Shadow::init_members() { + m_view_region = MIN_SHADOW_RANGE; + m_shadow_range = 1.0f; + + for (int32_t i = 0; i < 2; i++) { + m_light_pos[i] = 1.0f; + m_light_target[i] = 0.0f; + m_ground_ypos[i] = 0.0f; + m_proj_dist_base_range[i] = 0.0f; + m_enable_group[i] = false; + m_enable[i] = true; + m_proj_dist_base_vec[i].clear(); + m_group[i] = i; } - cam.set_up(up); + + rtex_shadowmap = 0; + for (RenderTexture*& i : rtex_soft) + i = 0; + + m_view_mtx = mat4_identity; + m_iview_mtx = mat4_identity; + + m_proj_near_repeat = 1; + m_proj_near_sampl = IMGF_BOX_SAMPL_9; + m_proj_far_repeat = 1; + m_proj_far_sampl = IMGF_BOX_SAMPL_16; + + m_proj_dist_attn = 4.0f; + m_proj_dist_attn_offset = 0.4f; + m_shadowmap_near_clip = 0.1f; + m_shadowmap_far_clip = 20.0f; + m_polyoffset_factor = 1.4f; + m_polyoffset_unit = 10000.0f; + m_esm_exponent = 80.0f; + m_gauss_sigma = 2.0f; + m_gauss_offset = 0.05f; + m_shadow_ambient = 0.4f; + m_num_group = 0; + m_light_dir = vec3(0.0f, -1.0f, -1.0f) * (1.0f / sqrtf(2.0f)); + m_enable_show_textures = false; + m_enable_self_shadow = true; + m_separate = false; + m_shadow_depth_range = (m_shadowmap_far_clip - m_shadowmap_near_clip) * 0.5f; +} + +// 0x1405E7820 +bool Shadow::check_culling0(const obj_bounding_sphere* sphere, const mat4* view) { + Shadow* shad = get_shadow(); + mat4 lview; + vec3 light_up; + M_calc_light_up(&light_up, &shad->m_light_pos[0], &shad->m_light_target[0]); + mat4_look_at(&shad->m_light_pos[0], &shad->m_light_target[0], &light_up, &lview); + return check_culling_sub(sphere, view, &lview); +} + +// 0x1405E78C0 +bool Shadow::check_culling1(const obj_bounding_sphere* sphere, const mat4* view) { + Shadow* shad = get_shadow(); + mat4 lview; + vec3 light_up; + M_calc_light_up(&light_up, &shad->m_light_pos[1], &shad->m_light_target[1]); + mat4_look_at(&shad->m_light_pos[1], &shad->m_light_target[1], &light_up, &lview); + return check_culling_sub(sphere, view, &lview); +} + +// 0x1405E7960 +bool Shadow::check_culling_sub(const obj_bounding_sphere* sphere, const mat4* view, const mat4* lview) { + vec3 center; + mat4_transform_point(view, &sphere->center, ¢er); + mat4_transform_point(lview, ¢er, ¢er); + float_t radius = sphere->radius; + + Shadow* shad = get_shadow(); + float_t distance = shad->get_distance(); + if ((center.x + radius) < -distance + || (center.x - radius) > distance + || (center.y + radius) < -distance + || (center.y - radius) > distance + || (center.z - radius) > -shad->m_shadowmap_near_clip + || (center.z + radius) < -shad->m_shadowmap_far_clip) + return false; + return true; +} + +// 0x1405E8B90 +void Shadow::set_light_view_proj_mtx(cam_data& cam, const vec3* light_pos, + const vec3* light_target, float_t range, float_t offset, float_t scale) { + mat4 temp; + mat4_translate(offset, 0.0f, 0.0f, &temp); + + mat4 proj; + mat4_ortho(-range, range, -range, range, m_shadowmap_near_clip, m_shadowmap_far_clip, &proj); + mat4_mul(&proj, &temp, &proj); + + vec3 light_up; + M_calc_light_up(&light_up, light_pos, light_target); + + cam.set_view_point(*light_pos); + cam.set_interest(*light_target); + cam.set_up(light_up); cam.calc_view_mat(); - cam.set_min_distance(z_near); - cam.set_max_distance(z_far); + cam.set_min_distance(m_shadowmap_near_clip); + cam.set_max_distance(m_shadowmap_far_clip); cam.calc_ortho_proj_mat(-range, range, -range, range, scale, { offset, 0.0f }); cam.calc_view_proj_mat(); } -void Shadow::clear_textures(p_gl_rend_state& p_gl_rend_st) { - for (int32_t i = 1; i < 3; i++) - for (int32_t j = 0; j < 4; j++) { - curr_render_textures[i]->begin_render(p_gl_rend_st, j); - p_gl_rend_st.clear_color(1.0f, 1.0f, 1.0f, 1.0f); - p_gl_rend_st.clear(GL_COLOR_BUFFER_BIT); - } - p_gl_rend_st.bind_framebuffer(0); +// 0x1405E76D0 +void Shadow::calc_tex_mtx(const vec3* light_pos, + const vec3* light_target, float_t range, float_t offset, mat4* tex_mtx) { + 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, offset, 0.0f, 0.0f, &temp); + + mat4 proj; + mat4_ortho(-range, range, -range, range, m_shadowmap_near_clip, m_shadowmap_far_clip, &proj); + mat4_mul(&proj, &temp, &proj); + + mat4 view; + vec3 light_up; + M_calc_light_up(&light_up, light_pos, light_target); + mat4_look_at(light_pos, light_target, &light_up, &view); + mat4_mul(&view, &proj, tex_mtx); } -void Shadow::ctrl() { - for (int32_t i = 0; i < 2; i++) - shadow_enable[i] = false; +// 0x1405E60E0 +void Shadow::calc_dist_base() { + for (int32_t i = 0; i < 2; i++) { + m_proj_dist_base[i] = 0.0f; + m_proj_dist_base_range[i] = 0.0f; - if (rctx_ptr->render_manager->shadow) { - view_mat[0] = rctx_ptr->camera->view; - view_mat[1] = rctx_ptr->camera->inv_view; + if (!m_enable_group[i]) + continue; - light_data& light_chara = rctx_ptr->light_set[LIGHT_SET_MAIN].lights[LIGHT_CHARA]; + size_t num_pos_group = m_proj_dist_base_vec[i].size(); + if (!num_pos_group) + continue; - vec3 position; - light_chara.get_position(position); - float_t length = vec3::length(position); - if (length < 0.000001f) - direction = { 0.0f, 1.0f, 0.0f }; - else - direction = -position * (1.0f / length); + vec3 dist_base = 0.0f; + for (const vec3& pos : m_proj_dist_base_vec[i]) + dist_base += pos; + dist_base *= 1.0f / (float_t)num_pos_group; - for (int32_t i = 0; i < 2; i++) - if (rctx_ptr->disp_manager->get_obj_count((mdl::ObjType)((int32_t)mdl::OBJ_TYPE_SHADOW_CHARA + i))) - shadow_enable[i] = true; + float_t dist_base_range = 0.0f; + for (const vec3& pos : m_proj_dist_base_vec[i]) { + const vec3 pos_diff = dist_base - pos; + float_t range = vec3::distance(m_light_dir * vec3::dot(pos_diff, m_light_dir), pos_diff); + range = max_def(range - 0.25f, 0.0f); + dist_base_range = max_def(dist_base_range, range); + } + m_proj_dist_base[i] = dist_base; + m_proj_dist_base_range[i] = dist_base_range; } - sub_1405E6840(this); + for (std::vector& i : m_proj_dist_base_vec) + i.clear(); } -void Shadow::free() { - for (RenderTexture& i : render_textures) - i.destroy(); +// 0x1405E63D0 +void Shadow::calc_light_coord() { + if (m_num_group <= 0) + return; - reset(); + vec3 light_pos = 0.0f; + vec3 light_target = 0.0f; + for (int32_t i = 0; i < 2; i++) { + if (!m_enable_group[i]) + continue; + + const vec3 calc_light_pos = m_proj_dist_base[i] - m_light_dir * m_shadow_depth_range; + const float_t light_pos_dist = vec3::distance_squared(m_light_pos[i], calc_light_pos); + const float_t pos_target_dist = vec3::distance_squared(m_light_target[i], m_proj_dist_base[i]); + if (sqrt(light_pos_dist) > 0.1f || sqrt(pos_target_dist) > 0.1f) { + m_light_pos[i] = calc_light_pos; + m_light_target[i] = m_proj_dist_base[i]; + } + + light_pos += m_light_pos[i]; + light_target += m_light_target[i]; + } + + m_avg_light_pos = light_pos * (1.0f / (float_t)m_num_group); + m_avg_light_target = light_target * (1.0f / (float_t)m_num_group); } -float_t Shadow::get_shadow_range() { - return shadow_range * shadow_range_factor; +// 0x1405E6910 +void Shadow::calc_shadowmap_region() { + const float_t base_range = max_def(m_proj_dist_base_range[0], m_proj_dist_base_range[1]); + m_separate = false; + m_view_region = base_range + MIN_SHADOW_RANGE; + m_group[0] = 0; + m_group[1] = 1; + + if (m_num_group < 2) + return; + + const vec3 target_diff_0 = m_proj_dist_base[0] - m_avg_light_target; + const vec3 target_diff_1 = m_proj_dist_base[1] - m_avg_light_target; + + float_t range = vec3::distance(m_light_dir * vec3::dot(target_diff_0, m_light_dir), target_diff_0); + range = max_def(range - 0.25f, 0.0f); + + const float_t view_region = base_range + (MIN_SHADOW_RANGE + range); + m_view_region = view_region; + + const float_t view_region_separate = base_range + SHADOW_RANGE_SEPARATE; + if (view_region > view_region_separate) { + m_view_region = view_region_separate; + m_separate = true; + } + + if (vec3::dot(target_diff_0, m_light_dir) < vec3::dot(target_diff_1, m_light_dir)) { + m_group[0] = 1; + m_group[1] = 0; + } } -int32_t Shadow::init() { - struct shadow_texture_init_params { - int32_t width; - int32_t height; - int32_t max_level; - GLenum color_format; - GLenum depth_format; - } init_params[] = { - { 0x800, 0x800, 0, GL_RGBA8, GL_DEPTH_COMPONENT32F }, - { 0x200, 0x200, 3, GL_RGBA8, GL_ZERO }, - { 0x200, 0x200, 3, GL_RGBA8, GL_ZERO }, - { 0x800, 0x800, 0, GL_R32F , GL_ZERO }, - { 0x800, 0x800, 0, GL_R32F , GL_ZERO }, - { 0x200, 0x200, 0, GL_R32F , GL_ZERO }, - { 0x200, 0x200, 0, GL_R32F , GL_ZERO }, - }; +// 0x1405E6B70 +void Shadow::calc_shadowmap_region_multi() { + vec3 x_axis; + vec3 z_axis; + if ((float_t)(m_light_dir.y * m_light_dir.y) < 0.99f) { + x_axis = vec3::cross(m_light_dir, vec3(0.0f, 1.0f, 0.0f)); + z_axis = vec3::cross(x_axis, m_light_dir); + x_axis = vec3::normalize(x_axis); + z_axis = vec3::normalize(z_axis); + } + else { + x_axis = vec3(1.0f, 0.0f, 0.0f); + z_axis = vec3(0.0f, 0.0f, 1.0f); + } - shadow_texture_init_params* init_param = init_params; - for (int32_t i = 0; i < 7; i++, init_param++) - if (render_textures[i].create_texture(init_param->width, init_param->height, - init_param->max_level, init_param->color_format, init_param->depth_format) < 0) + // calc_dist_base + for (int32_t i = 0; i < 2; i++) { + m_proj_dist_base[i] = 0.0f; + m_proj_dist_base_range[i] = 0.0f; + + if (!m_enable_group[i]) + continue; + + size_t num_pos_group = m_proj_dist_base_vec[i].size(); + if (!num_pos_group) + continue; + + vec3 dist_base = 0.0f; + for (const vec3& pos : m_proj_dist_base_vec[i]) + dist_base += pos; + dist_base *= 1.0f / (float_t)num_pos_group; + + float_t dist_base_range = 0.0f; + for (const vec3& pos : m_proj_dist_base_vec[i]) { + const vec3 pos_diff = dist_base - pos; + const float_t x_range = vec3::dot(pos_diff, x_axis); + const float_t z_range = vec3::dot(pos_diff, z_axis); + dist_base_range = max_def(dist_base_range, max_def(fabsf(x_range), fabsf(z_range))); + } + m_proj_dist_base[i] = dist_base; + m_proj_dist_base_range[i] = dist_base_range; + } + + // calc_light_coord + if (m_num_group > 0) { + for (int32_t i = 0; i < 2; i++) { + if (!m_enable_group[i]) + continue; + + const vec3 calc_light_pos = m_proj_dist_base[i] - m_light_dir * m_shadow_depth_range; + const float_t light_pos_dist = vec3::distance_squared(m_light_pos[i], calc_light_pos); + const float_t pos_target_dist = vec3::distance_squared(m_light_target[i], m_proj_dist_base[i]); + if (sqrtf(light_pos_dist) > 0.1f || sqrtf(pos_target_dist) > 0.1f) { + m_light_pos[i] = calc_light_pos; + m_light_target[i] = m_proj_dist_base[i]; + } + } + + size_t num_pos = 0; + vec3 light_pos = 0.0f; + vec3 light_target = 0.0f; + for (int32_t i = 0; i < 2; i++) + if (m_enable_group[i]) { + size_t num_pos_group = m_proj_dist_base_vec[i].size(); + num_pos += num_pos_group; + light_pos += m_light_pos[i] * (float_t)num_pos_group; + light_target += m_light_target[i] * (float_t)num_pos_group; + } + + m_avg_light_pos = light_pos * (1.0f / (float_t)num_pos); + m_avg_light_target = light_target * (1.0f / (float_t)num_pos); + } + + // calc_shadowmap_region + const float_t base_range = max_def(m_proj_dist_base_range[0], m_proj_dist_base_range[1]); + m_separate = false; + m_view_region = base_range + MIN_SHADOW_RANGE; + m_group[0] = 0; + m_group[1] = 1; + + if (m_num_group >= 2) { + float_t x_range_neg = 0.0f; + float_t z_range_neg = 0.0f; + float_t x_range_pos = 0.0f; + float_t z_range_pos = 0.0f; + for (int32_t i = 0; i < 2; i++) { + if (!m_enable_group[i]) + continue; + + for (const vec3& pos : m_proj_dist_base_vec[i]) { + vec3 target_diff = pos - m_avg_light_target; + + const float_t x_range = vec3::dot(x_axis, target_diff); + if (x_range_neg > x_range) + x_range_neg = x_range; + else if (x_range_pos < x_range) + x_range_pos = x_range; + + const float_t z_range = vec3::dot(z_axis, target_diff); + if (z_range_neg > z_range) + z_range_neg = z_range; + else if (z_range_pos < z_range) + z_range_pos = z_range; + } + } + + const float_t range = max_def(max_def(max_def(-x_range_neg, x_range_pos), -z_range_neg), z_range_pos); + + const float_t view_region = range + MIN_SHADOW_RANGE; + m_view_region = view_region; + + const float_t view_region_separate = base_range + SHADOW_RANGE_SEPARATE; + if (view_region > view_region_separate) { + m_view_region = view_region_separate; + m_separate = true; + } + + if (vec3::dot(m_light_dir, m_proj_dist_base[0] - m_avg_light_target) + < vec3::dot(m_light_dir, m_proj_dist_base[1] - m_avg_light_target)) { + m_group[0] = 1; + m_group[1] = 0; + } + } + + for (std::vector& i : m_proj_dist_base_vec) + i.clear(); +} + +// 0x1405E5820 +Shadow::Shadow() : rtex_shadowmap(), rtex_soft(), m_view_region(), m_shadow_range(), m_ground_ypos(), +m_proj_dist_base_range(), m_group(), m_shadow_depth_range(), m_proj_dist_attn(), m_proj_dist_attn_offset(), +m_shadowmap_near_clip(), m_shadowmap_far_clip(), m_polyoffset_factor(), m_polyoffset_unit(), +m_esm_exponent(), m_gauss_sigma(), m_gauss_offset(), m_shadow_ambient(), m_enable_show_textures(), +m_num_group(), m_enable_group(), m_enable_self_shadow(), m_enable(), m_separate() { + init_members(); +} + +// 0x1405E5930 +Shadow::~Shadow() { + destroy(); +} + +// 0x1405E7BA0 +int32_t Shadow::create() { + const ShadowTexParam* param = shadow_tex_param_table; + for (int32_t i = 0; i < 7; i++, param++) + if (rtex_table[i].create_texture( + (int32_t)(float_t)param->width, (int32_t)(float_t)param->height, + param->level, param->pixel_format, param->depth_format) < 0) return -1; for (int32_t i = 0; i < 3; i++) { - gl_state.bind_texture_2d(render_textures[i].get_texture_glid()); + gl_state.bind_texture_2d(rtex_table[i].get_texture_glid()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f); static const vec4 border_color = 1.0f; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&border_color); } - gl_state.bind_texture_2d(render_textures[0].get_depth_texture_glid()); + gl_state.bind_texture_2d(rtex_table[0].get_depth_texture_glid()); GLint swizzle[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle); gl_state.bind_texture_2d(0); @@ -142,297 +431,385 @@ int32_t Shadow::init() { return 0; } -void Shadow::reset() { - shadow_range = MIN_SHADOW_RANGE; - shadow_range_factor = 1.0f; +// 0x1405E8350 +void Shadow::destroy() { + for (RenderTexture& i : rtex_table) + i.destroy(); - for (int32_t i = 0; i < 2; i++) { - view_point[i] = 1.0f; - field_1C0[i] = 0.0f; - field_1C8[i] = 0.0f; - index[i] = i; - } + init_members(); +} - for (RenderTexture*& i : curr_render_textures) - i = 0; +// 0x1405E8B70 +void Shadow::set_light_dir(const vec3* dir) { + m_light_dir = *dir; +} - view_mat[0] = mat4_identity; - view_mat[1] = mat4_identity; - blur_filter = BLUR_FILTER_9; - near_blur = 1; - field_2BC = 2; - far_blur = 1; - distance = 4.0f; - field_2C4 = 0.4f; - z_near = 0.1f; - z_far = 20.0f; - field_2D0 = 1.4f; - field_2D4 = 10000.0f; - field_2D8 = 80.0f; - field_2DC = 2.0f; - field_2E0 = 0.05f; - shadow_ambient = 0.4f; - num_shadow = 0; - direction = vec3(0.0f, -1.0f, -1.0f) * (1.0f / sqrtf(2.0f)); - show_texture = false; - self_shadow = true; - separate = false; - z_half_range = (z_far - z_near) * 0.5f; +// 0x1405E83A0 +void Shadow::enable_group(int32_t group) { + m_enable_group[group] = true; +} + +// 0x1405E8A20 +void Shadow::set_dist_base(int32_t group, const vec3* pos) { + if (group >= 0 && group < 2) + m_proj_dist_base_vec[group].push_back(vec3(pos->x, pos->y - 0.2f, pos->z)); +} + +// Missing +const vec3* Shadow::get_dist_base(int32_t group) const { + if (group >= 0 && group < 2) + return &m_proj_dist_base[group]; + return 0; +} + +// 0x1405E8C70 +void Shadow::set_view_mtx(const mat4* view_mtx) { + m_view_mtx = *view_mtx; + mat4_invert_fast(view_mtx, &m_iview_mtx); +} + +// 0x1405E89F0 +void Shadow::set_dist_attn(float_t dist_attn) { + if (fabs(dist_attn) > 0.000001f) + m_proj_dist_attn = dist_attn; + else + m_proj_dist_attn = 1.0f; +} + +// 0x1405E8C50 +void Shadow::set_polyoffset(float_t polyoffset_factor, float_t polyoffset_unit) { + m_polyoffset_factor = polyoffset_factor; + m_polyoffset_unit = polyoffset_unit; +} + +// 0x1405E8660 +void Shadow::get_polyoffset(float_t* polyoffset_factor, float_t* polyoffset_unit) { + if (polyoffset_factor) + *polyoffset_factor = m_polyoffset_factor; + if (polyoffset_unit) + *polyoffset_unit = m_polyoffset_unit; } // 0x1405E5A90 -void Shadow::set_curr_render_textures(int32_t index[2]) { - if (index) { - index[0] = this->index[0]; - index[1] = this->index[1]; +void Shadow::begin_make_shadow_textures(int32_t group[2]) { + if (group) { + group[0] = m_group[0]; + group[1] = m_group[1]; } - curr_render_textures[0] = &render_textures[0]; - curr_render_textures[1] = &render_textures[1]; - curr_render_textures[2] = &render_textures[2]; + rtex_shadowmap = &get_rtex(0); + rtex_soft[0] = &get_rtex(1); + rtex_soft[1] = &get_rtex(2); } -void Shadow::set_distance(float_t value) { - if (fabs(value) > 0.000001f) - distance = value; - else - distance = 1.0f; +// 0x1405E83B0 +void Shadow::end_make_shadow_textures(p_gl_rend_state& p_gl_rend_st) { + shader::unbind(p_gl_rend_st); + p_gl_rend_st.bind_framebuffer(0); } -void shadow_ptr_init() { - shadow_ptr = new Shadow; -} +// 0x1405E5AD0 +void Shadow::begin_make_silhouette_map(render_data_context& rend_data_ctx, + struct cam_data& cam, int32_t group, int32_t index) { + render_context* rctx = rctx_ptr; + rtex_shadowmap->begin_render(rend_data_ctx.state); + texture* tex = rtex_shadowmap->get_texture(); + rend_data_ctx.state.set_viewport(1, 1, tex->width - 2, tex->width - 2); + rend_data_ctx.state.enable_depth_test(); + rend_data_ctx.state.clear_color(1.0f, 1.0f, 1.0f, 1.0f); + if (!index) + rend_data_ctx.state.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + else if (m_separate) + rend_data_ctx.state.clear(GL_COLOR_BUFFER_BIT); -Shadow* shadow_ptr_get() { - return shadow_ptr; -} - -void shadow_ptr_free() { - if (shadow_ptr) { - delete shadow_ptr; - shadow_ptr = 0; + float_t shadow_range = get_distance(); + float_t offset; + const vec3* light_targe; + const vec3* light_pos; + if (m_separate) { + offset = group ? 0.5f : -0.5f; + light_targe = &m_light_target[group]; + light_pos = &m_light_pos[group]; } + else { + offset = 0.0f; + light_targe = &m_avg_light_target; + light_pos = &m_avg_light_pos; + } + + const float_t scale = (float_t)(tex->width / 2) / (float_t)((tex->width - 2) / 2); + set_light_view_proj_mtx(cam, light_pos, light_targe, shadow_range, offset, scale); + rctx->draw_state->rend_data[rend_data_ctx.index].shader_index = SHADER_FT_SIL; + rend_data_ctx.shader_flags.arr[U_DEPTH] = 0; } -static void sub_1405E60E0(Shadow* shad) { - for (int32_t i = 0; i < 2; i++) { - shad->position[i] = 0.0f; - shad->field_1C8[i] = 0.0f; +extern void apply_blur_filter_sub(render_data_context& rend_data_ctx, RenderTexture* dst, RenderTexture* src, + ImgfBoxSampl filter, const vec2 res_scale, const vec4 scale, const vec4 offset); +extern void apply_esm_filter(render_data_context& rend_data_ctx, + RenderTexture* dst, RenderTexture* buf, RenderTexture* src, + float_t sigma, float_t offset, bool enable_lit_proj); +extern void apply_esm_min_filter(render_data_context& rend_data_ctx, + RenderTexture* dst, RenderTexture* buf, RenderTexture* src); - if (!shad->shadow_enable[i] || !shad->positions[i].size()) - continue; +// 0x1405E83D0 +void Shadow::end_make_silhouette_map(render_data_context& rend_data_ctx, int32_t group, int32_t index) { + render_context* rctx = rctx_ptr; + rend_data_ctx.state.disable_depth_test(); - vec3 position = 0.0f; - for (vec3& j : shad->positions[i]) - position += j; + rctx->draw_state->rend_data[rend_data_ctx.index].shader_index = -1; + if (index == m_num_group - 1) { + apply_esm_filter(rend_data_ctx, &get_rtex(3), &get_rtex(4), rtex_shadowmap, + m_gauss_sigma, m_gauss_offset / (m_shadow_depth_range * 2.0f), false); + apply_esm_min_filter(rend_data_ctx, &get_rtex(5), &get_rtex(6), &get_rtex(3)); + } - float_t position_count = (float_t)(int64_t)shad->positions[i].size(); - if (position_count < 0.0f) - position_count += (float_t)UINT64_MAX; - position *= 1.0f / position_count; + RenderTexture* rend_tex = rtex_soft[group]; + RenderTexture& rend_buf_tex = rctx_ptr->shadow_buffer; - float_t v15 = 0.0f; - for (vec3& j : shad->positions[i]) { - vec3 position_diff = position - j; - float_t v23 = vec3::dot(position_diff, shad->direction); - float_t v24 = vec3::distance(shad->direction * v23, position_diff); - v15 = max_def(v15, max_def(v24 - 0.25f, 0.0f)); + image_filter_scale(rend_data_ctx, rend_tex, rtex_shadowmap->get_texture()); + + if (m_enable[group]) { + for (int32_t i = m_proj_near_repeat, j = 0; i > 0; i--, j++) { + apply_blur_filter_sub(rend_data_ctx, &rend_buf_tex, rend_tex, + m_proj_near_sampl, 1.0f, 1.0f, 0.0f); + image_filter_scale(rend_data_ctx, rend_tex, rend_buf_tex.get_texture()); } - shad->position[i] = position; - shad->field_1C8[i] = v15; } + else { + rend_buf_tex.begin_render(rend_data_ctx.state); + rend_data_ctx.state.clear_color(1.0f, 1.0f, 1.0f, 1.0f); + rend_data_ctx.state.clear(GL_COLOR_BUFFER_BIT); + } + rend_buf_tex.end_render(rend_data_ctx.state); - for (std::vector& i : shad->positions) - i.clear(); + if (GLAD_GL_VERSION_4_5) + rend_data_ctx.state.generate_texture_mipmap(rend_tex->get_texture_glid()); + else { + rend_data_ctx.state.bind_texture_2d(rend_tex->get_texture_glid()); + rend_data_ctx.state.generate_mipmap(GL_TEXTURE_2D); + rend_data_ctx.state.bind_texture_2d(0); + } } -static void sub_1405E63D0(Shadow* shad) { - if (shad->num_shadow <= 0) +// 0x1405E5CA0 +void Shadow::bind_shadow(render_data_context& rend_data_ctx, render_context* rctx) { + float_t esm_param; + if (m_enable_self_shadow && m_num_group > 0) { + rend_data_ctx.state.active_bind_texture_2d(19, get_rtex(3).get_texture_glid()); + rend_data_ctx.state.active_bind_texture_2d(20, get_rtex(5).get_texture_glid()); + rend_data_ctx.state.active_texture(0); + esm_param = (m_esm_exponent * m_shadow_depth_range * 2.0f) * 1.442695f; + rend_data_ctx.set_self_shadow(true); + } + else { + rend_data_ctx.state.active_bind_texture_2d(19, rctx->empty_texture_2d->glid); + rend_data_ctx.state.active_bind_texture_2d(20, rctx->empty_texture_2d->glid); + rend_data_ctx.state.active_texture(0); + esm_param = 0.0f; + rend_data_ctx.set_self_shadow(false); + } + + rend_data_ctx.state.bind_sampler(19, rctx->render_samplers[0]); + rend_data_ctx.state.bind_sampler(20, rctx->render_samplers[0]); + + mat4 mats[2]; + mats[0] = mat4_identity; + mats[1] = mat4_identity; + vec4 shadow_ambient; + vec4 shadow_ambient1; + if (m_num_group > 0) { + rctx->draw_state->rend_data[rend_data_ctx.index].shadow = true; + rend_data_ctx.shader_flags.arr[U_STAGE_SHADOW2] = m_num_group > 1 ? 1 : 0; + + float_t distance = get_distance(); + for (int32_t i = 0; i < 2; i++) { + float_t offset; + vec3* target; + vec3* pos; + if (m_separate) { + offset = i ? 0.5f : -0.5f; + + target = &m_light_target[i]; + pos = &m_light_pos[i]; + } + else { + offset = 0.0f; + target = &m_avg_light_target; + pos = &m_avg_light_pos; + } + + calc_tex_mtx(pos, target, distance, offset, &mats[i]); + } + + int32_t index = 0; + for (int32_t i = 0; i < 2; i++) + if (m_enable_group[i]) { + rend_data_ctx.state.active_bind_texture_2d(6 + index, rtex_soft[i]->get_texture_glid()); + index++; + } + + for (; index < 2; index++) + rend_data_ctx.state.active_bind_texture_2d(6 + index, rctx->empty_texture_2d->glid); + rend_data_ctx.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 + *(vec3*)&ambient.x = m_shadow_ambient; + + shadow_ambient = { ambient.x, ambient.y, ambient.z, 1.0f }; + shadow_ambient1 = { 1.0f - ambient.x, 1.0f - ambient.y, 1.0f - ambient.z, 0.0f }; + } + else { + rctx->draw_state->rend_data[rend_data_ctx.index].shadow = false; + + for (int32_t i = 0; i < 2; i++) + rtex_soft[i]->bind_texture(rend_data_ctx.state, 6 + i); + rend_data_ctx.state.active_texture(0); + + shadow_ambient = 1.0f; + shadow_ambient1 = 0.0f; + } + + rend_data_ctx.set_scene_shadow_params(esm_param, mats, shadow_ambient, shadow_ambient1); + + rend_data_ctx.state.bind_sampler(6, 0); + rend_data_ctx.state.bind_sampler(7, 0); +} + +// 0x1405E8D40 +void Shadow::unbind_shadow(render_data_context& rend_data_ctx, render_context* rctx) { + rend_data_ctx.state.active_bind_texture_2d(6, rctx->empty_texture_2d->glid); + rend_data_ctx.state.active_bind_texture_2d(7, rctx->empty_texture_2d->glid); + rend_data_ctx.set_self_shadow(false); + rend_data_ctx.set_shadow(false); +} + +// 0x1405E7AF0 +void Shadow::clear(p_gl_rend_state& p_gl_rend_st) { + for (int32_t i = 0; i < 2; i++) + for (int32_t j = 0; j < 4; j++) { + rtex_soft[i]->begin_render(p_gl_rend_st, j); + p_gl_rend_st.clear_color(1.0f, 1.0f, 1.0f, 1.0f); + p_gl_rend_st.clear(GL_COLOR_BUFFER_BIT); + } + p_gl_rend_st.bind_framebuffer(0); +} + +// 0x1405E89B0 +void Shadow::reset_group() { + for (int32_t i = 0; i < 2; i++) + m_enable_group[i] = false; +} + +// 0x1405E80C0 +void Shadow::dbg_show_textures() { + if (!m_enable_show_textures) return; - vec3 view_point = 0.0f; - vec3 interest = 0.0f; - for (int32_t i = 0; i < 2; i++) { - if (!shad->shadow_enable[i]) - continue; + GLuint gltex_self_work = rtex_shadowmap->get_texture_glid(); + dbg_draw_texture_uv_mm(0.0f, 0.0f, 256.0f, 256.0f, 1.0f, 1.0f, 0, gltex_self_work); - const vec3 v11 = shad->position[i] - shad->direction * shad->z_half_range; - const float_t v9 = vec3::distance(shad->view_point[i], v11); - const float_t v12 = vec3::distance(shad->interest[i], shad->position[i]); - if (v9 > 0.1f || v12 > 0.1f) { - shad->view_point[i] = v11; - shad->interest[i] = shad->position[i]; - } + GLuint gltex_self0 = rtex_soft[0]->get_texture_glid(); + dbg_draw_texture_uv_mm( 0.0f, 256.0f, 128.0f, 128.0f, 1.0f, 1.0f, 0, gltex_self0); + dbg_draw_texture_uv_mm(128.0f, 256.0f, 64.0f, 64.0f, 1.0f, 1.0f, 1, gltex_self0); + dbg_draw_texture_uv_mm(192.0f, 256.0f, 32.0f, 32.0f, 1.0f, 1.0f, 2, gltex_self0); + dbg_draw_texture_uv_mm(224.0f, 256.0f, 16.0f, 16.0f, 1.0f, 1.0f, 3, gltex_self0); - view_point += shad->view_point[i]; - interest += shad->interest[i]; - } - - shad->view_point_shared = view_point * (1.0f / (float_t)shad->num_shadow); - shad->interest_shared = interest * (1.0f / (float_t)shad->num_shadow); + GLuint gltex_self1 = rtex_soft[1]->get_texture_glid(); + dbg_draw_texture_uv_mm(256.0f, 256.0f, 128.0f, 128.0f, 1.0f, 1.0f, 0, gltex_self1); + dbg_draw_texture_uv_mm(384.0f, 256.0f, 64.0f, 64.0f, 1.0f, 1.0f, 1, gltex_self1); + dbg_draw_texture_uv_mm(448.0f, 256.0f, 32.0f, 32.0f, 1.0f, 1.0f, 2, gltex_self1); + dbg_draw_texture_uv_mm(480.0f, 256.0f, 16.0f, 16.0f, 1.0f, 1.0f, 3, gltex_self1); } -static void sub_1405E6840(Shadow* shad) { +// 0x1405E89C0 +void Shadow::set_cull_func(int32_t group) { + if (group >= 0 && group < 2) { + if (!group) + rctx_ptr->disp_manager->set_culling_func(check_culling0); + else + rctx_ptr->disp_manager->set_culling_func(check_culling1); + } +} + +// 0x1405E6840 +void Shadow::calc_shadowmap() { int32_t count = 0; - shad->num_shadow = 0; + m_num_group = 0; for (int32_t i = 0; i < 2; i++) { - if (shad->shadow_enable[i] && shad->positions[i].size()) { - ++shad->num_shadow; - count += (int32_t)shad->positions->size(); + if (m_enable_group[i] && m_proj_dist_base_vec[i].size()) { + m_num_group++; + count += (int32_t)m_proj_dist_base_vec[i].size(); } else - shad->shadow_enable[i] = false; + m_enable_group[i] = false; } if (count < 3) { - sub_1405E60E0(shad); - sub_1405E63D0(shad); - sub_1405E6910(shad); + calc_dist_base(); + calc_light_coord(); + calc_shadowmap_region(); } else - sub_1405E6B70(shad); + calc_shadowmap_region_multi(); } -static void sub_1405E6910(Shadow* shad) { - const float_t v2 = max_def(shad->field_1C8[0], shad->field_1C8[1]); - shad->separate = false; - shad->shadow_range = v2 + MIN_SHADOW_RANGE; - shad->index[0] = 0; - shad->index[1] = 1; +// 0x1405E8640 +float_t Shadow::get_distance() const { + return m_view_region * m_shadow_range; +} - if (shad->num_shadow < 2) - return; - - const vec3 v12 = shad->position[0] - shad->interest_shared; - const vec3 v14 = shad->position[1] - shad->interest_shared; - float_t v16 = vec3::distance((shad->direction * vec3::dot(v12, shad->direction)), v12); - v16 = max_def(v16 - 0.25f, 0.0f); - - if (v2 + MIN_SHADOW_RANGE + v16 > v2 + SHADOW_RANGE_SEPARATE) { - shad->shadow_range = v2 + SHADOW_RANGE_SEPARATE; - shad->separate = true; - } - else - shad->shadow_range = v2 + MIN_SHADOW_RANGE + v16; - - if (vec3::dot(v12, shad->direction) < vec3::dot(v14, shad->direction)) { - shad->index[0] = 1; - shad->index[1] = 0; +// 0x1405E8610 +void finish_shadow() { + if (g_shadow) { + delete g_shadow; + g_shadow = 0; } } -static void sub_1405E6B70(Shadow* shad) { - vec3 v3; - vec3 v86; - if (shad->direction.y * shad->direction.y < 0.99f) { - v86 = vec3::cross(shad->direction, vec3(0.0f, 1.0f, 0.0f)); - v3 = vec3::cross(v86, shad->direction); - v86 = vec3::normalize(v86); - v3 = vec3::normalize(v3); - } - else { - v3 = { 0.0f, 0.0f, 1.0f }; - v86 = { 1.0f, 0.0f, 0.0f }; - } +// 0x1405E8680 +Shadow* get_shadow() { + return g_shadow; +} - for (int32_t i = 0; i < 2; i++) { - shad->position[i] = 0.0f; - shad->field_1C8[i] = 0.0f; +// 0x1405E8890 +void init_shadow() { + g_shadow = new Shadow; +} - if (!shad->shadow_enable[i] || !shad->positions[i].size()) - continue; +// 0x1405E7D40 +static void dbg_draw_texture(float_t x, float_t y, + float_t width, float_t height, GLuint texture) { + dbg_draw_texture_uv_mm(x, y, width, height, 1.0f, 1.0f, 0, texture); +} - vec3 v22 = 0.0f; - for (vec3& j : shad->positions[i]) - v22 += j; +// 0x1405E7D80 +static void dbg_draw_texture_uv(float_t x, float_t y, + float_t width, float_t height, float_t s, float_t t, GLuint texture) { + dbg_draw_texture_uv_mm(x, y, width, height, s, t, 0, texture); +} - float_t v29 = (float_t)(int64_t)shad->positions[i].size(); - if (v29 < 0.0f) - v29 += (float_t)UINT64_MAX; - v22 *= 1.0f / v29; +// 0x1405E7DC0 +static void dbg_draw_texture_uv_mm(float_t x, float_t y, + float_t width, float_t height, float_t s, float_t t, int32_t level, GLuint texture) { + // NOT IMPL! +} - float_t v30 = 0.0f; - for (vec3& j : shad->positions[i]) { - const vec3 v35 = v22 - j; - const float_t v39 = fabsf(vec3::dot(v35, v86)); - const float_t v38 = fabsf(vec3::dot(v35, v3)); - v30 = max_def(v30, max_def(v38, v39)); - } - shad->position[i] = v22; - shad->field_1C8[i] = v30; - } - - if (shad->num_shadow > 0) { - vec3 view_point = 0.0f; - vec3 interest = 0.0f; - for (int32_t i = 0; i < 2; i++) { - if (!shad->shadow_enable[i]) - continue; - - const vec3 v41 = shad->position[0] - shad->direction * shad->z_half_range; - const float_t v42 = vec3::distance(shad->view_point[0], v41); - const float_t v45 = vec3::distance(shad->interest[0], shad->position[0]); - if (v42 > 0.1f || v45 > 0.1f) { - shad->view_point[0] = v41; - shad->interest[0] = shad->position[0]; - } - - view_point += shad->view_point[i]; - interest += shad->interest[i]; - } - - shad->view_point_shared = view_point * (1.0f / (float_t)shad->num_shadow); - shad->interest_shared = interest * (1.0f / (float_t)shad->num_shadow); - } - - const float_t v67 = max_def(shad->field_1C8[0], shad->field_1C8[1]); - shad->separate = 0; - shad->shadow_range = v67 + MIN_SHADOW_RANGE; - shad->index[0] = 0; - shad->index[1] = 1; - - if (shad->num_shadow >= 2) { - float_t v2 = 0.0f; - float_t v68 = 0.0f; - float_t v69 = 0.0f; - float_t v70 = 0.0f; - for (int32_t i = 0; i < 2; i++) { - if (!shad->shadow_enable[i]) - continue; - - for (vec3& j : shad->positions[i]) { - const vec3 interest_diff = j - shad->interest_shared; - - const float_t v77 = vec3::dot(v86, interest_diff); - if (v2 > v77) - v2 = v77; - else if (v69 < v77) - v69 = v77; - - const float_t v78 = vec3::dot(v3, interest_diff); - if (v68 > v78) - v68 = v78; - else if (v70 < v78) - v70 = v78; - } - } - - const float_t v79 = max_def(max_def(max_def(-v2, v69), -v68), v70); - - if (v79 + MIN_SHADOW_RANGE > v67 + SHADOW_RANGE_SEPARATE) { - shad->shadow_range = v67 + SHADOW_RANGE_SEPARATE; - shad->separate = true; - } +// 0x1405E56B0 +static void M_calc_light_up(vec3* light_up, const vec3* light_pos, const vec3* light_target) { + *light_up = { 0.0f, 1.0f, 0.0f }; + const vec3 dir = *light_target - *light_pos; + if (fabsf(dir.x * dir.x + dir.z * dir.z) <= 0.000001f) { + light_up->x = 0.0f; + light_up->y = 0.0f; + if (dir.y < 0.0f) + light_up->z = 1.0f; else - shad->shadow_range = v79 + MIN_SHADOW_RANGE; - - if (vec3::dot(shad->position[0] - shad->interest_shared, shad->direction) - < vec3::dot(shad->position[1] - shad->interest_shared, shad->direction)) { - shad->index[1] = 0; - shad->index[0] = 1; - } + light_up->z = -1.0f; } - - for (std::vector& i : shad->positions) - i.clear(); } diff --git a/src/CRE/shadow.hpp b/src/CRE/shadow.hpp index 1ebd2d3d..0bbe80f9 100644 --- a/src/CRE/shadow.hpp +++ b/src/CRE/shadow.hpp @@ -6,71 +6,221 @@ #pragma once #include "../KKdLib/default.hpp" +#include "../KKdLib/image.hpp" #include "../KKdLib/time.hpp" +#include "../KKdLib/mat.hpp" #include "../KKdLib/vec.hpp" #include "render_texture.hpp" -#include "static_var.hpp" #include -enum SHADOW_GROUP { - SHADOW_GROUP_CHARA = 0, - SHADOW_GROUP_STAGE, - SHADOW_GROUP_MAX, -}; +class Shadow { +private: + RenderTexture rtex_table[7]; + RenderTexture* rtex_shadowmap; + RenderTexture* rtex_soft[2]; + float_t m_view_region; + float_t m_shadow_range; + vec3 m_light_pos[2]; + vec3 m_light_target[2]; + vec3 m_proj_dist_base[2]; + float_t m_ground_ypos[2]; + float_t m_proj_dist_base_range[2]; + std::vector m_proj_dist_base_vec[2]; + int32_t m_group[2]; + float_t m_shadow_depth_range; + vec3 m_light_dir; + vec3 m_avg_light_pos; + vec3 m_avg_light_target; + mat4 m_view_mtx; + mat4 m_iview_mtx; + uint32_t m_proj_near_repeat; + ImgfBoxSampl m_proj_near_sampl; + uint32_t m_proj_far_repeat; + ImgfBoxSampl m_proj_far_sampl; + float_t m_proj_dist_attn; + float_t m_proj_dist_attn_offset; + float_t m_shadowmap_near_clip; + float_t m_shadowmap_far_clip; + float_t m_polyoffset_factor; + float_t m_polyoffset_unit; + float_t m_esm_exponent; + float_t m_gauss_sigma; + float_t m_gauss_offset; + float_t m_shadow_ambient; + bool m_enable_show_textures; + int32_t m_num_group; + bool m_enable_group[2]; + bool m_enable_self_shadow; + bool m_enable[2]; + bool m_separate; -struct Shadow { - RenderTexture render_textures[7]; - RenderTexture* curr_render_textures[3]; - float_t shadow_range; - float_t shadow_range_factor; - vec3 view_point[2]; - vec3 interest[2]; - vec3 position[2]; - float_t field_1C0[2]; - float_t field_1C8[2]; - std::vector positions[2]; - int32_t index[2]; - float_t z_half_range; - vec3 direction; - vec3 view_point_shared; - vec3 interest_shared; - mat4 view_mat[2]; - int32_t near_blur; - blur_filter_mode blur_filter; - int32_t far_blur; - int32_t field_2BC; - float_t distance; - float_t field_2C4; - float_t z_near; - float_t z_far; - float_t field_2D0; - float_t field_2D4; - float_t field_2D8; - float_t field_2DC; - float_t field_2E0; - float_t shadow_ambient; - bool show_texture; - int32_t num_shadow; - bool shadow_enable[2]; - bool self_shadow; - bool blur_filter_enable[2]; - bool separate; + void init_members(); + static bool check_culling0(const struct obj_bounding_sphere* sphere, const mat4* view); + static bool check_culling1(const struct obj_bounding_sphere* sphere, const mat4* view); + static bool check_culling_sub(const struct obj_bounding_sphere* sphere, const mat4* view, const mat4* lview); + +protected: + void set_light_view_proj_mtx(struct cam_data& cam, const vec3* light_pos, + const vec3* light_target, float_t range, float_t offset, float_t scale); + void calc_tex_mtx(const vec3* light_pos, + const vec3* light_target, float_t range, float_t offset, mat4* tex_mtx); + void calc_dist_base(); + void calc_light_coord(); + void calc_shadowmap_region(); + void calc_shadowmap_region_multi(); + +public: Shadow(); virtual ~Shadow(); - void calc_proj_view_mat(struct cam_data& cam, const vec3& view_point, - const vec3& interest, float_t range, float_t offset, float_t scale); - void clear_textures(struct p_gl_rend_state& p_gl_rend_st); - void ctrl(); - void free(); - float_t get_shadow_range(); - int32_t init(); - void reset(); - void set_curr_render_textures(int32_t index[2]); - void set_distance(float_t value); + int32_t create(); + void destroy(); + void set_light_dir(const vec3* dir); + void enable_group(int32_t group); + void set_dist_base(int32_t group, const vec3* pos); + const vec3* get_dist_base(int32_t group) const; + void set_ground_ypos(int32_t group, float_t ground_ypos); + void set_view_mtx(const mat4* view_mtx); + void set_dist_attn(float_t dist_attn); + float_t get_dist_attn() const; + void set_dist_attn_offset(float_t dist_attn_offset); + float_t get_dist_attn_offset() const; + void set_near_blur_repeat(uint32_t near_blur_repeat); + uint32_t get_near_blur_repeat() const; + void set_far_blur_repeat(uint32_t far_blur_repeat); + uint32_t get_far_blur_repeat() const; + void set_polyoffset(float_t polyoffset_factor, float_t polyoffset_unit); + void get_polyoffset(float_t* polyoffset_factor, float_t* polyoffset_unit); + void set_shadow_ambient(float_t shadow_ambient); + float_t get_shadow_ambient() const; + void set_shadow_range(float_t shadow_range); + float_t get_shadow_range() const; + void begin_make_shadow_textures(int32_t group[2]); + void end_make_shadow_textures(struct p_gl_rend_state& p_gl_rend_st); + void begin_make_silhouette_map(struct render_data_context& rend_data_ctx, struct cam_data& cam, int32_t group, int32_t index); + void end_make_silhouette_map(struct render_data_context& rend_data_ctx, int32_t group, int32_t index); + void bind_shadow(struct render_data_context& rend_data_ctx, struct render_context* rctx); + void unbind_shadow(struct render_data_context& rend_data_ctx, struct render_context* rctx); + void clear(struct p_gl_rend_state& p_gl_rend_st); + void reset_group(); + void set_enable(int32_t group, bool enable); + void reset_enable(); + void enable_show_textures(); + void disable_show_textures(); + bool is_enable_show_textures() const; + void dbg_show_textures(); + void set_cull_func(int32_t group); + void set_self_shadow_sw(bool sw); + bool get_self_shadow_sw() const; + + void calc_shadowmap(); + float_t get_distance() const; + RenderTexture& get_rtex(int32_t index); }; -extern void shadow_ptr_init(); -extern Shadow* shadow_ptr_get(); -extern void shadow_ptr_free(); +extern void finish_shadow(); +extern Shadow* get_shadow(); +extern void init_shadow(); + +// Inlined +inline void Shadow::set_ground_ypos(int32_t group, float_t ground_ypos) { + m_ground_ypos[group] = ground_ypos; +} + +// Inlined +inline float_t Shadow::get_dist_attn() const { + return m_proj_dist_attn; +} + +// Inlined +inline void Shadow::set_dist_attn_offset(float_t dist_attn_offset) { + m_proj_dist_attn_offset = dist_attn_offset; +} + +// Inlined +inline float_t Shadow::get_dist_attn_offset() const { + return m_proj_dist_attn_offset; +} + +// Inlined +inline void Shadow::set_near_blur_repeat(uint32_t near_blur_repeat) { + m_proj_near_repeat = near_blur_repeat; +} + +// Inlined +inline uint32_t Shadow::get_near_blur_repeat() const { + return m_proj_near_repeat; +} + +// Inlined +inline void Shadow::set_far_blur_repeat(uint32_t far_blur_repeat) { + m_proj_far_repeat = far_blur_repeat; +} + +// Inlined +inline uint32_t Shadow::get_far_blur_repeat() const { + return m_proj_far_repeat; +} + +// Inlined +inline void Shadow::set_shadow_ambient(float_t shadow_ambient) { + m_shadow_ambient = shadow_ambient; +} + +// Inlined +inline float_t Shadow::get_shadow_ambient() const { + return m_shadow_ambient; +} + +// Inlined +inline void Shadow::set_shadow_range(float_t shadow_range) { + m_shadow_range = shadow_range; +} + +// Inlined +inline float_t Shadow::get_shadow_range() const { + return m_shadow_range; +} + +// Inlined +inline void Shadow::set_enable(int32_t group, bool enable) { + if (group >= 0 && group < 2) + m_enable[group] = enable; +} + +// Inlined +inline void Shadow::reset_enable() { + for (int32_t i = 0; i < 2; i++) + m_enable[i] = true; +} + +// Inlined +inline void Shadow::enable_show_textures() { + m_enable_show_textures = true; +} + +// Inlined +inline void Shadow::disable_show_textures() { + m_enable_show_textures = false; +} + +// Inlined +inline bool Shadow::is_enable_show_textures() const { + return m_enable_show_textures; +} + +// Inlined +inline void Shadow::set_self_shadow_sw(bool sw) { + m_enable_self_shadow = sw; +} + +// Inlined +inline bool Shadow::get_self_shadow_sw() const { + return m_enable_self_shadow; +} + +// Inlined +inline RenderTexture& Shadow::get_rtex(int32_t index) { + return rtex_table[index]; +} diff --git a/src/CRE/shared.hpp b/src/CRE/shared.hpp index 440d1c42..51344d96 100644 --- a/src/CRE/shared.hpp +++ b/src/CRE/shared.hpp @@ -10,14 +10,6 @@ #include "../KKdLib/vec.hpp" #include "static_var.hpp" -enum blur_filter_mode { - BLUR_FILTER_4 = 0x00, - BLUR_FILTER_9 = 0x01, - BLUR_FILTER_16 = 0x02, - BLUR_FILTER_32 = 0x03, - BLUR_FILTER_MAX = 0x04, -}; - extern void fbo_blit(struct p_gl_rend_state& p_gl_rend_st, GLuint src_fbo, GLuint dst_fbo, GLint src_x, GLint src_y, GLint src_width, GLint src_height, GLint dst_x, GLint dst_y, GLint dst_width, GLint dst_height, GLbitfield mask, GLenum filter); diff --git a/src/CRE/stage.cpp b/src/CRE/stage.cpp index a75e41ca..d34846c4 100644 --- a/src/CRE/stage.cpp +++ b/src/CRE/stage.cpp @@ -12,6 +12,7 @@ #include "light_param.hpp" #include "stage_param.hpp" #include "render_context.hpp" +#include "shadow.hpp" namespace stage_detail { static void TaskStage_CtrlInner(stage_detail::TaskStage* a1); @@ -30,13 +31,6 @@ namespace stage_detail { static void TaskStage_Unload(stage_detail::TaskStage* a1); } -static bool object_bounding_sphere_check_visibility_shadow( - const obj_bounding_sphere* sphere, const mat4* view, const mat4* mat); -static bool object_bounding_sphere_check_visibility_shadow_chara( - const obj_bounding_sphere* sphere, const mat4* view); -static bool object_bounding_sphere_check_visibility_shadow_stage( - const obj_bounding_sphere* sphere, const mat4* view); - static bool stage_ctrl(stage* s); static void stage_disp(stage* s); static void stage_disp_shadow(stage* s); @@ -511,41 +505,6 @@ static void stage_detail::TaskStage_Unload(stage_detail::TaskStage* a1) { } } -static bool object_bounding_sphere_check_visibility_shadow( - const obj_bounding_sphere* sphere, const mat4* view, const mat4* mat) { - vec3 center; - mat4_transform_point(mat, &sphere->center, ¢er); - mat4_transform_point(view, ¢er, ¢er); - float_t radius = sphere->radius; - - Shadow* shad = shadow_ptr_get(); - float_t shadow_range = shad->get_shadow_range(); - if ((center.x + radius) < -shadow_range - || (center.x - radius) > shadow_range - || (center.y + radius) < -shadow_range - || (center.y - radius) > shadow_range - || (center.z - radius) > -shad->z_near - || (center.z + radius) < -shad->z_far) - return false; - return true; -} - -static bool object_bounding_sphere_check_visibility_shadow_chara( - const obj_bounding_sphere* sphere, const mat4* view) { - mat4 mat; - Shadow* shad = shadow_ptr_get(); - mat4_look_at(&shad->view_point[0], &shad->interest[0], &mat); - return object_bounding_sphere_check_visibility_shadow(sphere, view, &mat); -} - -static bool object_bounding_sphere_check_visibility_shadow_stage( - const obj_bounding_sphere* sphere, const mat4* view) { - mat4 mat; - Shadow* shad = shadow_ptr_get(); - mat4_look_at(&shad->view_point[1], &shad->interest[1], &mat); - return object_bounding_sphere_check_visibility_shadow(sphere, view, &mat); -} - static bool stage_ctrl(stage* s) { if (s->state >= 1 && s->state <= 5) { stage_load(s); @@ -620,11 +579,9 @@ static void stage_disp_shadow(stage* s) { static void stage_disp_shadow_object(object_info object, const mat4& mat) { mdl::DispManager& disp_manager = *rctx_ptr->disp_manager; - for (int32_t i = SHADOW_GROUP_CHARA; i < SHADOW_GROUP_MAX; i++) { - disp_manager.set_shadow_group((SHADOW_GROUP)i); - disp_manager.set_culling_func(i == SHADOW_GROUP_CHARA - ? object_bounding_sphere_check_visibility_shadow_chara - : object_bounding_sphere_check_visibility_shadow_stage); + for (int32_t i = 0; i < 2; i++) { + disp_manager.set_shadow_group(i); + get_shadow()->set_cull_func(i); disp_manager.set_obj_flags((mdl::ObjFlags)(mdl::OBJ_NO_TRANSLUCENCY | mdl::OBJ_SHADOW_OBJECT)); disp_manager.entry_obj_by_object_info(mat, object); } @@ -763,7 +720,7 @@ static void stage_set(stage* s, stage* other) { if (other->stage_data->reflect) { stage_data_reflect* reflect = &other->stage_data->reflect_data; render_manager->set_pass_sw(rndr::RND_PASSID_REFLECT, true); - render_manager->set_reflect_blur(reflect->blur_num, (blur_filter_mode)reflect->blur_filter); + render_manager->set_reflect_blur(reflect->blur_num, reflect->blur_filter); render_manager->set_reflect(true); reflect_refract_resolution_mode reflect_resolution_mode = REFLECT_REFRACT_RESOLUTION_512x512; if (other->stage_data->reflect_type != STAGE_DATA_REFLECT_REFLECT_MAP) diff --git a/src/CRE/stage_modern.cpp b/src/CRE/stage_modern.cpp index 66ce103f..96043af0 100644 --- a/src/CRE/stage_modern.cpp +++ b/src/CRE/stage_modern.cpp @@ -11,6 +11,7 @@ #include "effect.hpp" #include "light_param.hpp" #include "render_context.hpp" +#include "shadow.hpp" namespace stage_detail { static void TaskStageModern_CtrlInner(stage_detail::TaskStageModern* a1); @@ -32,13 +33,6 @@ namespace stage_detail { static void TaskStageModern_Unload(stage_detail::TaskStageModern* a1); } -static bool object_bounding_sphere_check_visibility_shadow( - const obj_bounding_sphere* sphere, const mat4* view, const mat4* mat); -static bool object_bounding_sphere_check_visibility_shadow_chara( - const obj_bounding_sphere* sphere, const mat4* view); -static bool object_bounding_sphere_check_visibility_shadow_stage( - const obj_bounding_sphere* sphere, const mat4* view); - static bool stage_modern_ctrl(stage_modern* s, void* data, object_database* obj_db, texture_database* tex_db); static void stage_modern_disp(stage_modern* s); static void stage_modern_disp_shadow(stage_modern* s); @@ -447,41 +441,6 @@ static void stage_detail::TaskStageModern_Unload(stage_detail::TaskStageModern* } } -static bool object_bounding_sphere_check_visibility_shadow( - const obj_bounding_sphere* sphere, const mat4* view, const mat4* mat) { - vec3 center; - mat4_transform_point(mat, &sphere->center, ¢er); - mat4_transform_point(view, ¢er, ¢er); - float_t radius = sphere->radius; - - Shadow* shad = shadow_ptr_get(); - float_t shadow_range = shad->get_shadow_range(); - if ((center.x + radius) < -shadow_range - || (center.x - radius) > shadow_range - || (center.y + radius) < -shadow_range - || (center.y - radius) > shadow_range - || (center.z - radius) > -shad->z_near - || (center.z + radius) < -shad->z_far) - return false; - return true; -} - -static bool object_bounding_sphere_check_visibility_shadow_chara( - const obj_bounding_sphere* sphere, const mat4* view) { - mat4 mat; - Shadow* shad = shadow_ptr_get(); - mat4_look_at(&shad->view_point[0], &shad->interest[0], &mat); - return object_bounding_sphere_check_visibility_shadow(sphere, view, &mat); -} - -static bool object_bounding_sphere_check_visibility_shadow_stage( - const obj_bounding_sphere* sphere, const mat4* view) { - mat4 mat; - Shadow* shad = shadow_ptr_get(); - mat4_look_at(&shad->view_point[1], &shad->interest[1], &mat); - return object_bounding_sphere_check_visibility_shadow(sphere, view, &mat); -} - static bool stage_modern_ctrl(stage_modern* s, void* data, object_database* obj_db, texture_database* tex_db) { if (s->state >= 1 && s->state <= 5) { stage_modern_load(s, data, obj_db, tex_db); @@ -538,11 +497,9 @@ static void stage_modern_disp_shadow(stage_modern* s) { static void stage_modern_disp_shadow_object(object_info object, const mat4& mat) { mdl::DispManager& disp_manager = *rctx_ptr->disp_manager; - for (int32_t i = SHADOW_GROUP_CHARA; i < SHADOW_GROUP_MAX; i++) { - disp_manager.set_shadow_group((SHADOW_GROUP)i); - disp_manager.set_culling_func(i == SHADOW_GROUP_CHARA - ? object_bounding_sphere_check_visibility_shadow_chara - : object_bounding_sphere_check_visibility_shadow_stage); + for (int32_t i = 0; i < 2; i++) { + disp_manager.set_shadow_group(i); + get_shadow()->set_cull_func(i); disp_manager.set_obj_flags((mdl::ObjFlags)(mdl::OBJ_NO_TRANSLUCENCY | mdl::OBJ_SHADOW_OBJECT)); disp_manager.entry_obj_by_object_info(mat, object); } diff --git a/src/KKdLib/database/stage.cpp b/src/KKdLib/database/stage.cpp index 1edfcbc3..d976207a 100644 --- a/src/KKdLib/database/stage.cpp +++ b/src/KKdLib/database/stage.cpp @@ -533,7 +533,7 @@ static void stage_database_file_classic_read_inner(stage_database_file* stage_da stage->reflect = true; stage->reflect_data.mode = (stage_data_reflect_resolution_mode)s.read_uint32_t(); stage->reflect_data.blur_num = s.read_int32_t(); - stage->reflect_data.blur_filter = (stage_data_blur_filter_mode)s.read_uint32_t(); + stage->reflect_data.blur_filter = (ImgfBoxSampl)s.read_uint32_t(); s.position_pop(); } else diff --git a/src/KKdLib/database/stage.hpp b/src/KKdLib/database/stage.hpp index eb32fe59..b3c1f523 100644 --- a/src/KKdLib/database/stage.hpp +++ b/src/KKdLib/database/stage.hpp @@ -9,6 +9,7 @@ #include #include "../default.hpp" #include "../prj/vector_pair.hpp" +#include "../image.hpp" #include "object.hpp" enum stage_data_format { @@ -43,17 +44,10 @@ enum stage_data_reflect_type { STAGE_DATA_REFLECT_REFLECT_MAP = 0x02, }; -enum stage_data_blur_filter_mode { - STAGE_DATA_BLUR_FILTER_4 = 0x00, - STAGE_DATA_BLUR_FILTER_9 = 0x01, - STAGE_DATA_BLUR_FILTER_16 = 0x02, - STAGE_DATA_BLUR_FILTER_32 = 0x03, -}; - struct stage_data_reflect { stage_data_reflect_resolution_mode mode; int32_t blur_num; - stage_data_blur_filter_mode blur_filter; + ImgfBoxSampl blur_filter; }; struct stage_data_refract { diff --git a/src/KKdLib/image.hpp b/src/KKdLib/image.hpp index fcbf1229..df5af399 100644 --- a/src/KKdLib/image.hpp +++ b/src/KKdLib/image.hpp @@ -8,6 +8,13 @@ #include "default.hpp" #include "vec.hpp" +enum ImgfBoxSampl { + IMGF_BOX_SAMPL_4 = 0, + IMGF_BOX_SAMPL_9, + IMGF_BOX_SAMPL_16, + IMGF_BOX_SAMPL_32, +}; + struct ImgfColorToneParam { vec3 blend_color; vec3 offset_color; diff --git a/src/KKdLib/mat.cpp b/src/KKdLib/mat.cpp index de0e5e6e..72bc24ff 100644 --- a/src/KKdLib/mat.cpp +++ b/src/KKdLib/mat.cpp @@ -2345,19 +2345,3 @@ inline void mat4_look_at(const vec3* eye, const vec3* target, const vec3* up, ma *(vec3*)&out_m->row3 = -xyz; out_m->row3.w = 1.0f; } - -inline void mat4_look_at(const vec3* eye, const vec3* target, mat4* out_m) { - vec3 up = { 0.0f, 1.0f, 0.0f }; - vec3 dir; - dir = *target - *eye; - if (vec3::length_squared(dir) <= 0.000001f) { - up.x = 0.0f; - up.y = 0.0f; - if (dir.z < 0.0f) - up.z = 1.0f; - else - up.z = -1.0f; - } - - mat4_look_at(eye, target, &up, out_m); -} diff --git a/src/KKdLib/mat.hpp b/src/KKdLib/mat.hpp index 7ce915ff..07e05352 100644 --- a/src/KKdLib/mat.hpp +++ b/src/KKdLib/mat.hpp @@ -243,7 +243,6 @@ extern void mat4_persp(float_t fov_y, float_t aspect, float_t z_near, float_t z_ extern void mat4_persp_offset(float_t fov_y, float_t aspect, float_t z_near, float_t z_far, const vec2* scale, const vec2* offset, mat4* out_m); extern void mat4_look_at(const vec3* eye, const vec3* target, const vec3* up, mat4* out_m); -extern void mat4_look_at(const vec3* eye, const vec3* target, mat4* out_m); inline void mat3_rotate_xyz(const vec3* rad, mat3* out_m) { mat3_rotate_xyz(rad->x, rad->y, rad->z, out_m); diff --git a/src/ReDIVA/data_test/auth_3d_test.cpp b/src/ReDIVA/data_test/auth_3d_test.cpp index 849a9991..43333f88 100644 --- a/src/ReDIVA/data_test/auth_3d_test.cpp +++ b/src/ReDIVA/data_test/auth_3d_test.cpp @@ -12,6 +12,7 @@ #include "../../CRE/debug_print.hpp" #include "../../CRE/effect.hpp" #include "../../CRE/render_context.hpp" +#include "../../CRE/shadow.hpp" #include "../../CRE/stage.hpp" #include "../dw.hpp" #include "../input_state.hpp" @@ -618,7 +619,7 @@ bool Auth3dTestTask::init() { obj_sets.clear(); obj_sets.shrink_to_fit(); - shadow_ptr_get()->self_shadow = true; + get_shadow()->set_self_shadow_sw(true); clear_color = 0x00999999; auth_3d_test_window_init(); @@ -711,7 +712,7 @@ bool Auth3dTestTask::dest() { data_event_listener.data.dest(); auth_3d_test_window->Hide(); clear_color = color_black; - shadow_ptr_get()->self_shadow = true; + get_shadow()->set_self_shadow_sw(true); if (category.size()) auth_3d_detail::category_free(category.c_str()); category.clear(); @@ -1414,7 +1415,7 @@ Auth3dTestWindow::SelectionButtonShadowType::~SelectionButtonShadowType() { void Auth3dTestWindow::SelectionButtonShadowType::Callback(dw::SelectionListener::CallbackData* data) { dw::Button* button = dynamic_cast(data->widget); if (button) - shadow_ptr_get()->self_shadow = !!button->callback_data.i64; + get_shadow()->set_self_shadow_sw(button->callback_data.i64); } Auth3dTestWindow::SelectionButtonSave::SelectionButtonSave() { diff --git a/src/ReDIVA/data_test/object_test.cpp b/src/ReDIVA/data_test/object_test.cpp index 97e3e057..438fb404 100644 --- a/src/ReDIVA/data_test/object_test.cpp +++ b/src/ReDIVA/data_test/object_test.cpp @@ -7,6 +7,7 @@ #include "../../CRE/clear_color.hpp" #include "../../CRE/data.hpp" #include "../../CRE/render_context.hpp" +#include "../../CRE/shadow.hpp" #include "../../CRE/stage.hpp" #include "../dw.hpp" #include "../input_state.hpp" @@ -313,9 +314,9 @@ void DataTestObjectManager::disp() { mat4_rotate_xyz(&rotation, &mat); vec3 pos = 0.0f; - shadow_ptr_get()->positions[SHADOW_GROUP_CHARA].push_back(pos); + get_shadow()->set_dist_base(0, &pos); - rctx_ptr->disp_manager->set_shadow_group(SHADOW_GROUP_CHARA); + rctx_ptr->disp_manager->set_shadow_group(0); rctx_ptr->disp_manager->entry_obj_by_object_info(mat, { obj_id, obj_set_id }); rctx_ptr->disp_manager->set_obj_flags((mdl::ObjFlags)0); } diff --git a/src/ReDIVA/graphics/reflect_refract.cpp b/src/ReDIVA/graphics/reflect_refract.cpp index 7e65715f..a81de307 100644 --- a/src/ReDIVA/graphics/reflect_refract.cpp +++ b/src/ReDIVA/graphics/reflect_refract.cpp @@ -46,7 +46,7 @@ ReflectRefractDw::ReflectRefractDw() { const reflect_refract_resolution_mode refract_resolution_mode = rctx_ptr->render_manager->get_reflect_resolution_mode(); // Intentional! const int32_t reflect_blur_num = rctx_ptr->render_manager->reflect_blur_num; - const blur_filter_mode reflect_blur_filter = rctx_ptr->render_manager->reflect_blur_filter; + const ImgfBoxSampl reflect_blur_filter = rctx_ptr->render_manager->reflect_blur_filter; SetText("REFLECT/REFRACT"); @@ -138,7 +138,7 @@ void ReflectRefractDw::Hide() { } void ReflectRefractDw::ReflectBlurFilterCallback(dw::ListBox* data) { - rctx_ptr->render_manager->reflect_blur_filter = (blur_filter_mode)(int32_t)data->list->selected_item; + rctx_ptr->render_manager->reflect_blur_filter = (ImgfBoxSampl)(int32_t)data->list->selected_item; } void ReflectRefractDw::ReflectBlurNumCallback(dw::Slider* data) { diff --git a/src/ReDIVA/graphics/shadow.cpp b/src/ReDIVA/graphics/shadow.cpp index eb254768..85124833 100644 --- a/src/ReDIVA/graphics/shadow.cpp +++ b/src/ReDIVA/graphics/shadow.cpp @@ -5,6 +5,7 @@ #include "shadow.hpp" #include "../../CRE/render_context.hpp" +#include "../../CRE/shadow.hpp" #include "../dw.hpp" extern render_context* rctx_ptr; @@ -14,14 +15,14 @@ public: dw::RowLayout* layout; dw::Slider* distance_slider; dw::Slider* shadow_ambient_slider; - dw::Slider* shadow_range_factor_slider; - float_t distance; - int32_t near_blur; - int32_t far_blur; - float_t field_1AC; - float_t field_1B0; + dw::Slider* shadow_range_slider; + float_t dist_attn; + int32_t near_blur_repeat; + int32_t far_blur_repeat; + float_t polyoffset_factor; + float_t polyoffset_unit; float_t shadow_ambient; - float_t shadow_range_factor; + float_t shadow_range; Shadow* shadow_ptr; ShadowDw(); @@ -36,7 +37,7 @@ public: static void FarBlurCallback(dw::Widget* data); static void NearBlurCallback(dw::Widget* data); static void ShadowAmbientCallback(dw::Widget* data); - static void ShadowRangeFactorCallback(dw::Widget* data); + static void ShadowRangeCallback(dw::Widget* data); static void ShowStageShadowCallback(dw::Widget* data); static void ShowTextureCallback(dw::Widget* data); }; @@ -54,14 +55,13 @@ void shadow_dw_init() { } ShadowDw::ShadowDw() { - shadow_ptr = shadow_ptr_get(); - distance = shadow_ptr->distance; - near_blur = shadow_ptr->near_blur; - far_blur = shadow_ptr->far_blur; - field_1AC = shadow_ptr->field_2D0; - field_1B0 = shadow_ptr->field_2D4; - shadow_ambient = shadow_ptr->shadow_ambient; - shadow_range_factor = shadow_ptr->shadow_range_factor; + shadow_ptr = get_shadow(); + dist_attn = shadow_ptr->get_dist_attn(); + near_blur_repeat = shadow_ptr->get_near_blur_repeat(); + far_blur_repeat = shadow_ptr->get_far_blur_repeat(); + shadow_ptr->get_polyoffset(&polyoffset_factor, &polyoffset_unit); + shadow_ambient = shadow_ptr->get_shadow_ambient(); + shadow_range = shadow_ptr->get_shadow_range(); SetText("SHADOW"); @@ -74,23 +74,23 @@ ShadowDw::ShadowDw() { distance_slider = dw::Slider::Create(this, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), 0.0f, 0.0f, 192.0f, glyph_height, "Distance"); - distance_slider->SetParams(distance, 0.01f, 20.0f, 1.0f, 0.1f, 1.0f); + distance_slider->SetParams(dist_attn, 0.01f, 20.0f, 1.0f, 0.1f, 1.0f); distance_slider->format = "%5.2f"; distance_slider->AddSelectionListener( new dw::SelectionListenerOnHook(ShadowDw::DistanceCallback)); dw::Slider* near_blur_slider = dw::Slider::Create(this, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), 0.0f, 0.0f, 192.0f, glyph_height, "Near Blur"); - near_blur_slider->SetParams((float_t)near_blur, 0.0f, 10.0f, 1.0f, 1.0f, 1.0f); + near_blur_slider->SetParams((float_t)near_blur_repeat, 0.0f, 10.0f, 1.0f, 1.0f, 1.0f); near_blur_slider->format = "%2.0f"; near_blur_slider->AddSelectionListener( new dw::SelectionListenerOnHook(ShadowDw::NearBlurCallback)); - dw::Slider* far_blur_slider = dw::Slider::Create(this, dw::Flags(dw::FLAG_800 + dw::Slider* far_blur_repeat_slider = dw::Slider::Create(this, dw::Flags(dw::FLAG_800 | dw::HORIZONTAL), 0.0f, 0.0f, 192.0f, glyph_height, "Far Blur"); - far_blur_slider->SetParams((float_t)far_blur, 1.0f, 10.0f, 1.0f, 1.0f, 1.0f); - far_blur_slider->format = "%2.0f"; - far_blur_slider->AddSelectionListener( + far_blur_repeat_slider->SetParams((float_t)far_blur_repeat, 1.0f, 10.0f, 1.0f, 1.0f, 1.0f); + far_blur_repeat_slider->format = "%2.0f"; + far_blur_repeat_slider->AddSelectionListener( new dw::SelectionListenerOnHook(ShadowDw::FarBlurCallback)); shadow_ambient_slider = dw::Slider::Create(this, (dw::Flags)(dw::FLAG_800 @@ -100,22 +100,22 @@ ShadowDw::ShadowDw() { shadow_ambient_slider->AddSelectionListener( new dw::SelectionListenerOnHook(ShadowDw::ShadowAmbientCallback)); - const char* shadow_range_factor_text; + const char* shadow_range_text; if (dw::translate) - shadow_range_factor_text = u8"Shadow Range Factor"; + shadow_range_text = u8"Shadow Range Factor"; else - shadow_range_factor_text = u8"シャドウ範囲係数"; + shadow_range_text = u8"シャドウ範囲係数"; - shadow_range_factor_slider = dw::Slider::Create(this, (dw::Flags)(dw::FLAG_800 - | dw::HORIZONTAL), 0.0f, 0.0f, 192.0f, glyph_height, shadow_range_factor_text); - shadow_range_factor_slider->SetParams(shadow_range_factor, 1.0f, 2.0f, 0.1f, 0.01f, 0.1f); - shadow_range_factor_slider->format = "%4.2f"; - shadow_range_factor_slider->AddSelectionListener( - new dw::SelectionListenerOnHook(ShadowDw::ShadowRangeFactorCallback)); + shadow_range_slider = dw::Slider::Create(this, (dw::Flags)(dw::FLAG_800 + | dw::HORIZONTAL), 0.0f, 0.0f, 192.0f, glyph_height, shadow_range_text); + shadow_range_slider->SetParams(shadow_range, 1.0f, 2.0f, 0.1f, 0.01f, 0.1f); + shadow_range_slider->format = "%4.2f"; + shadow_range_slider->AddSelectionListener( + new dw::SelectionListenerOnHook(ShadowDw::ShadowRangeCallback)); dw::Button* show_texture = new dw::Button(this, dw::CHECKBOX); show_texture->SetText("Show Texture"); - show_texture->SetValue(shadow_ptr->show_texture); + show_texture->SetValue(shadow_ptr->is_enable_show_textures()); show_texture->callback = ShadowDw::ShowTextureCallback; dw::Button* show_stage_shadow = new dw::Button(this, dw::CHECKBOX); @@ -130,7 +130,7 @@ ShadowDw::ShadowDw() { dw::Button* enable_self_shadow = new dw::Button(this, dw::CHECKBOX); enable_self_shadow->SetText("ENABLE SELF SHADOW"); - enable_self_shadow->SetValue(shadow_ptr_get()->self_shadow); + enable_self_shadow->SetValue(get_shadow()->get_self_shadow_sw()); enable_self_shadow->callback = ShadowDw::EnableSelfShadowCallback; } @@ -139,10 +139,10 @@ ShadowDw::~ShadowDw() { } void ShadowDw::Draw() { - shadow_ambient = shadow_ptr->shadow_ambient; + shadow_ambient = shadow_ptr->get_shadow_ambient(); shadow_ambient_slider->SetValue(shadow_ambient); - shadow_range_factor = shadow_ptr->shadow_range_factor; - shadow_range_factor_slider->SetValue(shadow_range_factor); + shadow_range = shadow_ptr->get_shadow_range(); + shadow_range_slider->SetValue(shadow_range); dw::Shell::Draw(); } @@ -153,7 +153,7 @@ void ShadowDw::Hide() { void ShadowDw::EnableSelfShadowCallback(dw::Widget* data) { dw::Button* button = dynamic_cast(data); if (button) - shadow_ptr_get()->self_shadow = button->value; + get_shadow()->set_self_shadow_sw(button->value); } void ShadowDw::EnableShadowCallback(dw::Widget* data) { @@ -166,8 +166,8 @@ void ShadowDw::DistanceCallback(dw::Widget* data) { dw::Slider* slider = dynamic_cast(data); if (slider) { const float_t value = slider->GetValue(); - shadow_dw->distance = value; - shadow_dw->shadow_ptr->set_distance(value); + shadow_dw->dist_attn = value; + shadow_dw->shadow_ptr->set_dist_attn(value); } } @@ -175,8 +175,8 @@ void ShadowDw::FarBlurCallback(dw::Widget* data) { dw::Slider* slider = dynamic_cast(data); if (slider) { const int32_t value = (int32_t)slider->GetValue(); - shadow_dw->far_blur = value; - shadow_dw->shadow_ptr->far_blur = value; + shadow_dw->far_blur_repeat = value; + shadow_dw->shadow_ptr->set_far_blur_repeat(value); } } @@ -184,8 +184,8 @@ void ShadowDw::NearBlurCallback(dw::Widget* data) { dw::Slider* slider = dynamic_cast(data); if (slider) { const int32_t value = (int32_t)slider->GetValue(); - shadow_dw->near_blur = value; - shadow_dw->shadow_ptr->near_blur = value; + shadow_dw->near_blur_repeat = value; + shadow_dw->shadow_ptr->set_near_blur_repeat(value); } } @@ -194,16 +194,16 @@ void ShadowDw::ShadowAmbientCallback(dw::Widget* data) { if (slider) { const float_t value = slider->GetValue(); shadow_dw->shadow_ambient = value; - shadow_dw->shadow_ptr->shadow_ambient = value; + shadow_dw->shadow_ptr->set_shadow_ambient(value); } } -void ShadowDw::ShadowRangeFactorCallback(dw::Widget* data) { +void ShadowDw::ShadowRangeCallback(dw::Widget* data) { dw::Slider* slider = dynamic_cast(data); if (slider) { const float_t value = slider->GetValue(); - shadow_dw->shadow_range_factor = value; - shadow_dw->shadow_ptr->shadow_range_factor = value; + shadow_dw->shadow_range = value; + shadow_dw->shadow_ptr->set_shadow_range(value); } } @@ -216,8 +216,11 @@ void ShadowDw::ShowStageShadowCallback(dw::Widget* data) { void ShadowDw::ShowTextureCallback(dw::Widget* data) { dw::Button* button = dynamic_cast(data); if (button) { - shadow_dw->shadow_ptr->show_texture = button->value; + if (button->value) + shadow_dw->shadow_ptr->enable_show_textures(); + else + shadow_dw->shadow_ptr->disable_show_textures(); render_data_context rend_data_ctx(GL_REND_STATE_PRE_3D); - shadow_dw->shadow_ptr->clear_textures(rend_data_ctx.state); + shadow_dw->shadow_ptr->clear(rend_data_ctx.state); } } diff --git a/src/ReDIVA/pv_game/pv_game.cpp b/src/ReDIVA/pv_game/pv_game.cpp index b2ef00ba..9c4bdb4a 100644 --- a/src/ReDIVA/pv_game/pv_game.cpp +++ b/src/ReDIVA/pv_game/pv_game.cpp @@ -15,6 +15,7 @@ #include "../../CRE/random.hpp" #include "../../CRE/pv_expression.hpp" #include "../../CRE/pv_param.hpp" +#include "../../CRE/shadow.hpp" #include "../../CRE/sound.hpp" #include "../../CRE/stage_param.hpp" #include "../../KKdLib/prj/algorithm.hpp" @@ -4899,7 +4900,7 @@ bool pv_game::unload() { rend.update_res(0, -1); rctx_ptr->disp_manager->object_culling = true; - shadow_ptr_get()->shadow_range_factor = 1.0f; + get_shadow()->set_shadow_range(1.0f); rctx_ptr->render_manager->set_effect_texture(0); sound_work_reset_all_se(); diff --git a/src/ReDIVA/pv_game/pv_game_pv_data.cpp b/src/ReDIVA/pv_game/pv_game_pv_data.cpp index 30022de5..fbc6fab7 100644 --- a/src/ReDIVA/pv_game/pv_game_pv_data.cpp +++ b/src/ReDIVA/pv_game/pv_game_pv_data.cpp @@ -8,6 +8,7 @@ #include "../../CRE/app_system_detail.hpp" #include "../../CRE/pv_expression.hpp" #include "../../CRE/pv_param.hpp" +#include "../../CRE/shadow.hpp" #include "../information/dw_console.hpp" #include "../mask_screen.hpp" #include "../task_movie.hpp" @@ -1323,12 +1324,12 @@ bool pv_game_pv_data::dsc_ctrl(float_t delta_time, int64_t curr_time, playdata->shadow = enable == 1; - Shadow* shad = shadow_ptr_get(); + Shadow* shad = get_shadow(); if (shad) if (rob_id == ROB_ID_2P) - shad->blur_filter_enable[1] = playdata->shadow; + shad->set_enable(1, playdata->shadow); else - shad->blur_filter_enable[0] = playdata->shadow; + shad->set_enable(0, playdata->shadow); } break; case DSC_FT_EDIT_EYELID: { int32_t v337 = data[0]; @@ -1876,9 +1877,9 @@ bool pv_game_pv_data::dsc_ctrl(float_t delta_time, int64_t curr_time, pv_game->set_data_itmpv_chara_id(rob_id, index, attach == 1); } break; case DSC_FT_SHADOW_RANGE: { - float_t shadow_range_factor = (float_t)data[0] * 0.001f; + float_t shadow_range = (float_t)data[0] * 0.001f; - shadow_ptr_get()->shadow_range_factor = shadow_range_factor; + get_shadow()->set_shadow_range(shadow_range); } break; case DSC_FT_HAND_SCALE: { rob_id = (ROB_ID)data[0]; @@ -2462,11 +2463,9 @@ void pv_game_pv_data::init(::pv_game* pv_game, bool music_play) { sub_14013C8C0()->difficulty, sub_14013C8C0()->edition); find_set_motion(diff); - Shadow* shad = shadow_ptr_get(); - if (shad) { - shad->blur_filter_enable[0] = true; - shad->blur_filter_enable[1] = true; - } + Shadow* shad = get_shadow(); + if (shad) + shad->reset_enable(); pv_game->data.play_data.lyric_color = 0xFFFFFFFF; @@ -2567,10 +2566,9 @@ void pv_game_pv_data::reset_camera_post_process() { rctx_ptr->render.reset_tone_trans(1); rctx_ptr->render.reset_saturate_coeff(1, 1); - Shadow* shad = shadow_ptr_get(); + Shadow* shad = get_shadow(); if (shad) - for (bool& i : shad->blur_filter_enable) - i = true; + shad->reset_enable(); branch_mode = false; diff --git a/src/ReDIVA/x_pv_game.cpp b/src/ReDIVA/x_pv_game.cpp index 72f434ad..3014983c 100644 --- a/src/ReDIVA/x_pv_game.cpp +++ b/src/ReDIVA/x_pv_game.cpp @@ -19,6 +19,7 @@ #include "../CRE/pv_param.hpp" #include "../CRE/random.hpp" #include "../CRE/shader_ft.hpp" +#include "../CRE/shadow.hpp" #include "../CRE/sound.hpp" #include "../CRE/sprite.hpp" #include "../KKdLib/io/file_stream.hpp" @@ -4286,11 +4287,9 @@ void x_pv_game_pv_data::init(class x_pv_game* pv_game, bool music_play) { find_change_fields(pv_game->get_data().change_fields); - Shadow* shad = shadow_ptr_get(); - if (shad) { - shad->blur_filter_enable[0] = true; - shad->blur_filter_enable[1] = true; - } + Shadow* shad = get_shadow(); + if (shad) + shad->reset_enable(); rob_id = ROB_ID_1P; } @@ -7100,11 +7099,9 @@ bool x_pv_game::ctrl() { get_data().pv_data.init(this, true); - Shadow* shad = shadow_ptr_get(); - if (shad) { - shad->blur_filter_enable[0] = true; - shad->blur_filter_enable[1] = true; - } + Shadow* shad = get_shadow(); + if (shad) + shad->reset_enable(); state_old = 9; } break; @@ -8293,7 +8290,7 @@ bool x_pv_game::unload() { rend.update_res(0, -1); rctx_ptr->disp_manager->object_culling = true; - shadow_ptr_get()->shadow_range_factor = 1.0f; + get_shadow()->set_shadow_range(1.0f); rctx_ptr->render_manager->set_effect_texture(0); sound_work_reset_all_se(); @@ -13553,7 +13550,7 @@ static void x_pv_game_write_stage_data_reflect(stream& s, stage_database_file* s = (stage_data_reflect_resolution_mode)reflect->read_int32_t("mode"); stage_reflect.reflect_data.blur_num = reflect->read_int32_t("blur_num"); stage_reflect.reflect_data.blur_filter - = (stage_data_blur_filter_mode)reflect->read_int32_t("blur_filter"); + = (ImgfBoxSampl)reflect->read_int32_t("blur_filter"); } stage_reflect.reflect_full = stage.read_bool("reflect_full"); break;