diff --git a/extern/src/PluginConfigApi/PluginConfigApi.h b/extern/src/PluginConfigApi/PluginConfigApi.h new file mode 100644 index 0000000..515732e --- /dev/null +++ b/extern/src/PluginConfigApi/PluginConfigApi.h @@ -0,0 +1,172 @@ +/* +PD Loader Launcher Plugin Information Structs +*/ + +#pragma once +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include + +// resolution class to store and sort the width and height easily +class resolution +{ +public: + unsigned int width; + unsigned int height; + + resolution() + { + width = 0; + height = 0; + } + + resolution(unsigned int width, unsigned int height) + { + resolution::width = width; + resolution::height = height; + } + + bool operator ==(const resolution &res2) + { + return width == res2.width && height == res2.height; + } + + // in comparisons width takes priority because it's usually displayed first + bool operator <(const resolution &res2) + { + if (width == res2.width) + return height < res2.height; + else + return width < res2.width; + } + bool operator >(const resolution &res2) + { + if (width == res2.width) + return height > res2.height; + else + return width > res2.width; + } +}; + +namespace PluginConfig +{ +#pragma pack(push, 1) + enum ConfigType { + CONFIG_BOOLEAN, + CONFIG_NUMERIC, + CONFIG_STRING, + CONFIG_DROPDOWN_INDEX, + CONFIG_DROPDOWN_TEXT, + CONFIG_DROPDOWN_NUMBER, + CONFIG_RESOLUTION, + CONFIG_GROUP_START, + CONFIG_GROUP_END, + CONFIG_BUTTON, + CONFIG_SPACER + }; + + struct PluginConfigBooleanData { + LPCWSTR iniVarName; + LPCWSTR iniSectionName; + LPCWSTR iniFilePath; + LPCWSTR friendlyName; + LPCWSTR description; + bool defaultVal; + bool saveAsString; + }; + + struct PluginConfigNumericData { + LPCWSTR iniVarName; + LPCWSTR iniSectionName; + LPCWSTR iniFilePath; + LPCWSTR friendlyName; + LPCWSTR description; + int defaultVal; + int minVal; + int maxVal; + }; + + struct PluginConfigStringData { + LPCWSTR iniVarName; + LPCWSTR iniSectionName; + LPCWSTR iniFilePath; + LPCWSTR friendlyName; + LPCWSTR description; + LPCWSTR defaultVal; + bool useUtf8; + }; + + struct PluginConfigDropdownIndexData { + LPCWSTR iniVarName; + LPCWSTR iniSectionName; + LPCWSTR iniFilePath; + LPCWSTR friendlyName; + LPCWSTR description; + int defaultVal; + std::vector valueStrings; + }; + + struct PluginConfigDropdownTextData { + LPCWSTR iniVarName; + LPCWSTR iniSectionName; + LPCWSTR iniFilePath; + LPCWSTR friendlyName; + LPCWSTR description; + LPCWSTR defaultVal; + std::vector valueStrings; + bool editable; + bool useUtf8; + }; + + struct PluginConfigDropdownNumberData { + LPCWSTR iniVarName; + LPCWSTR iniSectionName; + LPCWSTR iniFilePath; + LPCWSTR friendlyName; + LPCWSTR description; + int defaultVal; + std::vector valueInts; + bool editable; + }; + + struct PluginConfigResolutionData { + LPCWSTR iniVarName; + LPCWSTR iniVarName2; + LPCWSTR iniSectionName; + LPCWSTR iniFilePath; + LPCWSTR friendlyName; + LPCWSTR description; + resolution defaultVal; + std::vector valueResolutions; + bool editable; + }; + + struct PluginConfigGroupData + { + LPCWSTR name; + int height; + }; + + struct PluginConfigButtonData { + LPCWSTR friendlyName; + LPCWSTR description; + void(*func)(); + }; + + struct PluginConfigSpacerData { + int height; + }; + + struct PluginConfigOption + { + ConfigType cfgType; + void* data; + }; + + struct PluginConfigArray + { + int len; + PluginConfigOption* options; + }; +#pragma pack(pop) +} \ No newline at end of file diff --git a/src/DivaGL/auth_3d.cpp b/src/DivaGL/auth_3d.cpp index 393b327..21fc456 100644 --- a/src/DivaGL/auth_3d.cpp +++ b/src/DivaGL/auth_3d.cpp @@ -978,11 +978,15 @@ int32_t auth_3d_data_get_auth_3d_id(uint32_t uid, object_info obj_info, } HOOK(void, FASTCALL, auth_3d_parse, 0x00000001401C15B0, auth_3d* auth) { + const int32_t state_before = auth->state; originalauth_3d_parse(auth); - + const int32_t state_after = auth->state; extern bool reflect_full; + if (!reflect_full || state_before != 1 || state_after != 2) + return; + extern const firstread* firstread_ptr; - if (!reflect_full || !firstread_ptr || !firstread_ptr->auth_3d_array) + if (!firstread_ptr || !firstread_ptr->auth_3d_array) return; const firstread_auth_3d_array* auth_3d_array = firstread_ptr->auth_3d_array; diff --git a/src/DivaGL/dllmain.cpp b/src/DivaGL/dllmain.cpp index 9c8a19f..72d0aaa 100644 --- a/src/DivaGL/dllmain.cpp +++ b/src/DivaGL/dllmain.cpp @@ -11,6 +11,7 @@ #include #include #include +#include size_t diva_handle; size_t glut_handle; @@ -19,6 +20,13 @@ size_t dll_handle; bool cpu_caps_aes_ni; bool cpu_caps_f16c; bool config_reflect_full = true; +int32_t config_reflect_res_scale = 100; + +static std::wstring GetDirPath(); + +std::wstring CONFIG_FILE_STRING = GetDirPath() + L"\\plugins\\DivaGL.ini"; +LPCWSTR CONFIG_FILE = CONFIG_FILE_STRING.c_str(); + void FASTCALL divagl_main() { int32_t cpuid_data[4] = {}; @@ -47,6 +55,10 @@ void FASTCALL divagl_main() { bool APIENTRY DllMain(HMODULE handle, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: + config_reflect_full = GetPrivateProfileIntW(L"general", L"reflect_full", 0, CONFIG_FILE) > 0 ? true : false; + config_reflect_res_scale = GetPrivateProfileIntW(L"general", L"reflect_res_scale", 1, CONFIG_FILE); + config_reflect_res_scale = config_reflect_res_scale ? clamp_def(config_reflect_res_scale, 25, 100) : 100; + dll_handle = (size_t)handle; printf_divagl("Current version - v0.7.2.2"); printf_divagl("Attach"); @@ -67,3 +79,51 @@ extern "C" __declspec(dllexport) LPCWSTR GetPluginDescription(void) { extern "C" __declspec(dllexport) LPCWSTR GetBuildDate(void) { return L"v0.7.2.2"; } + +static std::wstring GetDirPath() { + wchar_t dll_file_path[MAX_PATH]; + GetModuleFileNameW((HMODULE)dll_handle, dll_file_path, MAX_PATH); + + wchar_t* dll_file_name = wcsrchr(dll_file_path, '\\'); + if (!dll_file_name) + dll_file_name = wcsrchr(dll_file_path, '/'); + + if (!dll_file_name) + return L""; + + WCHAR buffer[MAX_PATH]; + GetModuleFileNameW(NULL, buffer, MAX_PATH); + return std::wstring(dll_file_path, dll_file_name - dll_file_path); +} + +PluginConfig::PluginConfigOption config[] = { + { + PluginConfig::CONFIG_BOOLEAN, + new PluginConfig::PluginConfigBooleanData { + L"reflect_full", + L"general", + CONFIG_FILE, + L"Full Reflect", + L"Enables Full Reflect for PVs from X Pack (MPFX).", + false, + false, + } + }, + { + PluginConfig::CONFIG_NUMERIC, + new PluginConfig::PluginConfigNumericData { + L"reflect_res_scale", + L"general", + CONFIG_FILE, + L"Reflect Resolution Scale", + L"Sets resolution for Full Reflect as a percentage relative to the Internal Resolution values.\nImportant note! Scale doesn't apply can't go lower than 256x144 or Internal Resolution.", + 100, + 25, + 100, + } + }, +}; + +extern "C" __declspec(dllexport) PluginConfig::PluginConfigArray GetPluginOptions(void) { + return PluginConfig::PluginConfigArray{ _countof(config), config }; +} diff --git a/src/DivaGL/effect.cpp b/src/DivaGL/effect.cpp index 688c6b9..33f08cc 100644 --- a/src/DivaGL/effect.cpp +++ b/src/DivaGL/effect.cpp @@ -510,6 +510,8 @@ static void (FASTCALL* snow_particle_data_free)() = (void (FASTCALL*)())0x000000 extern render_context* rctx; +static void TaskEffectAuth3D__SetVisibility(size_t This, bool value); + static void draw_fog_particle(EffectFogRing* data, mat4* mat); static void draw_ripple_particles(ripple_struct* data, mat4* mat); @@ -781,6 +783,19 @@ void star_catalog_draw() { star_catalog_data.draw(); } +HOOK(void, FASTCALL, TaskEffectAuth3D__SetCurrentStageIndex, 0x00000001403459F0, size_t This, int32_t stage_index) { + if (*(int32_t*)(This + 0x138) != stage_index) { + TaskEffectAuth3D__SetVisibility(This, 0); + *(int32_t*)(This + 0x138) = stage_index; + TaskEffectAuth3D__SetVisibility(This, *(bool*)(This + 0x118)); + } +} + +HOOK(void, FASTCALL, TaskEffectAuth3D__SetEnable, 0x0000000140345B30, size_t This, bool value) { + *(bool*)(This + 0x118) = value; + TaskEffectAuth3D__SetVisibility(This, value); +} + HOOK(void, FASTCALL, EffectFogRing__dest, 0x0000000140348090, EffectFogRing* fog_ring) { auto elem = fog_ring_ssbo.find(fog_ring); if (elem != fog_ring_ssbo.end()) { @@ -934,63 +949,6 @@ HOOK(void, FASTCALL, leaf_particle_init, 0x000000014034C530, bool change_stage) leaf_particle_scene_ubo.Create(sizeof(leaf_particle_scene_shader_data)); } -HOOK(bool, FASTCALL, TaskEffectRain__dest, 0x0000000140353DA0, size_t task_eff_rain) { - if (stage_param_data_rain_current) { - implOfleaf_particle_free(); - stage_param_data_rain_current = 0; - void (FASTCALL * stage_param_data_rain_storage_clear)() - = (void (FASTCALL*)())0x0000000140353CD0; - stage_param_data_rain_storage_clear(); - stage_param_data_rain_set = 0; - *(int32_t*)(task_eff_rain + 0x70) = -1; - *(size_t*)(task_eff_rain + 0x80) = *(size_t*)(task_eff_rain + 0x78); - } - return true; -} - -HOOK(void, FASTCALL, rain_particle_init, 0x00000001403546A0, bool change_stage) { - vec3 velocity = stage_param_data_rain_current->velocity; - vec3 vel_range = stage_param_data_rain_current->vel_range; - - for (int32_t i = 0; i < 8; i++) { - particle_data& data = rain_ptcl_data[i]; - data.position.x = 0.0f; - data.position.y = ((float_t)i * -12.5f) - 5.0f; - data.position.z = 0.0f; - data.size = 1.0f; - data.alpha = 1.0f; - data.life_time = 1; - vec3 _velocity; - _velocity.x = rand_state_array_get_float(4); - _velocity.y = rand_state_array_get_float(4); - _velocity.z = rand_state_array_get_float(4); - *(vec3*)&data.velocity = (_velocity - 0.5f) * vel_range + velocity; - } - - if (change_stage) - return; - - rain_particle_free(); - - vec3* vtx_data = force_malloc(rain_ptcl_count); - for (int32_t i = 0; i < rain_ptcl_count; i++) { - vec3 position; - position.x = rand_state_array_get_float(4); - position.y = rand_state_array_get_float(4); - position.z = rand_state_array_get_float(4); - *vtx_data++ = position; - } - - vtx_data -= rain_ptcl_count; - - rain_ssbo.Create(sizeof(vec3) * rain_ptcl_count, vtx_data); - - free_def(vtx_data); - - rain_particle_scene_ubo.Create(sizeof(rain_particle_scene_shader_data)); - rain_particle_batch_ubo.Create(sizeof(rain_particle_batch_shader_data)); -} - HOOK(void, FASTCALL, particle_free, 0x0000000140351600) { if (ptcl_data) delete[] ptcl_data; @@ -1056,6 +1014,63 @@ HOOK(void, FASTCALL, particle_init, 0x0000000140351C50, vec3* offset) { particle_scene_ubo.Create(sizeof(particle_scene_shader_data)); } +HOOK(bool, FASTCALL, TaskEffectRain__dest, 0x0000000140353DA0, size_t task_eff_rain) { + if (stage_param_data_rain_current) { + implOfleaf_particle_free(); + stage_param_data_rain_current = 0; + void (FASTCALL * stage_param_data_rain_storage_clear)() + = (void (FASTCALL*)())0x0000000140353CD0; + stage_param_data_rain_storage_clear(); + stage_param_data_rain_set = 0; + *(int32_t*)(task_eff_rain + 0x70) = -1; + *(size_t*)(task_eff_rain + 0x80) = *(size_t*)(task_eff_rain + 0x78); + } + return true; +} + +HOOK(void, FASTCALL, rain_particle_init, 0x00000001403546A0, bool change_stage) { + vec3 velocity = stage_param_data_rain_current->velocity; + vec3 vel_range = stage_param_data_rain_current->vel_range; + + for (int32_t i = 0; i < 8; i++) { + particle_data& data = rain_ptcl_data[i]; + data.position.x = 0.0f; + data.position.y = ((float_t)i * -12.5f) - 5.0f; + data.position.z = 0.0f; + data.size = 1.0f; + data.alpha = 1.0f; + data.life_time = 1; + vec3 _velocity; + _velocity.x = rand_state_array_get_float(4); + _velocity.y = rand_state_array_get_float(4); + _velocity.z = rand_state_array_get_float(4); + *(vec3*)&data.velocity = (_velocity - 0.5f) * vel_range + velocity; + } + + if (change_stage) + return; + + rain_particle_free(); + + vec3* vtx_data = force_malloc(rain_ptcl_count); + for (int32_t i = 0; i < rain_ptcl_count; i++) { + vec3 position; + position.x = rand_state_array_get_float(4); + position.y = rand_state_array_get_float(4); + position.z = rand_state_array_get_float(4); + *vtx_data++ = position; + } + + vtx_data -= rain_ptcl_count; + + rain_ssbo.Create(sizeof(vec3) * rain_ptcl_count, vtx_data); + + free_def(vtx_data); + + rain_particle_scene_ubo.Create(sizeof(rain_particle_scene_shader_data)); + rain_particle_batch_ubo.Create(sizeof(rain_particle_batch_shader_data)); +} + HOOK(bool, FASTCALL, TaskEffectRipple__dest, 0x0000000140358600, size_t task_effect_ripple) { bool ret = originalTaskEffectRipple__dest(task_effect_ripple); ripple_emit_free(); @@ -1373,6 +1388,8 @@ HOOK(bool, FASTCALL, star_catalog__init, 0x000000014036CD50, star_catalog* star) } void effect_patch() { + INSTALL_HOOK(TaskEffectAuth3D__SetCurrentStageIndex); + INSTALL_HOOK(TaskEffectAuth3D__SetEnable); INSTALL_HOOK(EffectFogRing__dest); INSTALL_HOOK(EffectFogRing__disp); INSTALL_HOOK(EffectFogRing__set_stage_indices); @@ -1380,10 +1397,10 @@ void effect_patch() { INSTALL_HOOK(EffectFogRing__draw_static); INSTALL_HOOK(leaf_particle_free); INSTALL_HOOK(leaf_particle_init); - INSTALL_HOOK(TaskEffectRain__dest); - INSTALL_HOOK(rain_particle_init); INSTALL_HOOK(particle_free); INSTALL_HOOK(particle_init); + INSTALL_HOOK(TaskEffectRain__dest); + INSTALL_HOOK(rain_particle_init); INSTALL_HOOK(TaskEffectRipple__dest); INSTALL_HOOK(TaskEffectRipple__init); INSTALL_HOOK(EffectRipple__draw_static); @@ -1975,6 +1992,29 @@ void water_particle::draw(mat4* mat) { gl_state_enable_cull_face(); } +static void TaskEffectAuth3D__SetVisibility(size_t This, bool value) { + struct struc_621 { + int32_t stage_index; + prj::vector auth_3d_ids; + }; + + int32_t current_stage_index = *(int32_t*)(This + 0x138); + if (current_stage_index == -1) + return; + + for (struc_621& i : *(prj::vector*)(This + 0x120)) { + if (i.stage_index != current_stage_index) + continue; + + extern bool reflect_full; + for (auth_3d_id& j : i.auth_3d_ids) { + j.set_visibility(value); + j.set_reflect(reflect_full); + } + break; + } +} + static void draw_fog_particle(EffectFogRing* data, mat4* mat) { if (!data->num_vtx) return; diff --git a/src/DivaGL/mdl/disp_manager.cpp b/src/DivaGL/mdl/disp_manager.cpp index f69ad0d..cb4cc23 100644 --- a/src/DivaGL/mdl/disp_manager.cpp +++ b/src/DivaGL/mdl/disp_manager.cpp @@ -2279,8 +2279,52 @@ namespace mdl { get_obj_list(type).push_back(data); } - static int32_t obj_axis_aligned_bounding_box_check_visibility( - obj_axis_aligned_bounding_box* aabb, const mat4& mat) { + static int32_t obj_bounding_sphere_check_visibility_default(const vec3& center, float_t radius) { + mat4 view_mat; + mat4_transpose(&camera_data.view, &view_mat); + vec3 _center; + mat4_transform_point(&view_mat, ¢er, &_center); + + double_t min_depth = (double_t)_center.z - (double_t)radius; + double_t max_depth = (double_t)_center.z + (double_t)radius; + if (-camera_data.min_distance < min_depth || -camera_data.max_distance > max_depth) + return 0; + + float_t v5 = vec3::dot(camera_data.field_1E4, _center); + if (v5 < -radius) + return 0; + + float_t v6 = vec3::dot(camera_data.field_1F0, _center); + if (v6 < -radius) + return 0; + + float_t v7 = vec3::dot(camera_data.field_1FC, _center); + if (v7 < -radius) + return 0; + + float_t v8 = vec3::dot(camera_data.field_208, _center); + if (v8 < -radius) + return 0; + + if (-camera_data.min_distance >= max_depth && -camera_data.max_distance <= min_depth + && v5 >= radius && v6 >= radius && v7 >= radius && v8 >= radius) + return 1; + return 2; + } + + static int32_t obj_bounding_sphere_check_visibility(const obj_bounding_sphere& sphere, const mat4& mat) { + if (disp_manager->culling_func) + return disp_manager->culling_func(&sphere); + + vec3 center; + mat4 _mat; + mat4_transpose(&mat, &_mat); + mat4_transform_point(&_mat, &sphere.center, ¢er); + return obj_bounding_sphere_check_visibility_default(center, mat4_get_max_scale(&_mat) * sphere.radius); + } + + static int32_t obj_axis_aligned_bounding_box_check_visibility_default( + const obj_axis_aligned_bounding_box* aabb, const mat4& mat) { vec3 points[8]; points[0] = aabb->center + (aabb->size ^ vec3( 0.0f, 0.0f, 0.0f)); points[1] = aabb->center + (aabb->size ^ vec3(-0.0f, -0.0f, -0.0f)); @@ -2324,45 +2368,11 @@ namespace mdl { return 1; } - static int32_t obj_bounding_sphere_check_visibility(const obj_bounding_sphere& sphere, - CullingCheck* culling, const mat4& mat) { + static int32_t obj_axis_aligned_bounding_box_check_visibility( + const obj_axis_aligned_bounding_box* aabb, const mat4& mat) { if (disp_manager->culling_func) - return disp_manager->culling_func(&sphere); - - vec3 center; - mat4 _mat; - mat4_transpose(&mat, &_mat); - mat4_transform_point(&_mat, &sphere.center, ¢er); - float_t radius = mat4_get_max_scale(&_mat) * sphere.radius; - - mat4_transpose(&camera_data.view, &_mat); - mat4_transform_point(&_mat, ¢er, ¢er); - - double_t min_depth = (double_t)center.z - (double_t)radius; - double_t max_depth = (double_t)center.z + (double_t)radius; - if (-camera_data.min_distance < min_depth || -camera_data.max_distance > max_depth) - return 0; - - float_t v5 = vec3::dot(camera_data.field_1E4, center); - if (v5 < -radius) - return 0; - - float_t v6 = vec3::dot(camera_data.field_1F0, center); - if (v6 < -radius) - return 0; - - float_t v7 = vec3::dot(camera_data.field_1FC, center); - if (v7 < -radius) - return 0; - - float_t v8 = vec3::dot(camera_data.field_208, center); - if (v8 < -radius) - return 0; - - if (-camera_data.min_distance >= max_depth && -camera_data.max_distance <= min_depth - && v5 >= radius && v6 >= radius && v7 >= radius && v8 >= radius) return 1; - return 2; + return obj_axis_aligned_bounding_box_check_visibility_default(aabb, mat); } bool DispManager::entry_obj(const ::obj* obj, const mat4& mat, obj_mesh_vertex_buffer* obj_vert_buf, @@ -2383,10 +2393,9 @@ namespace mdl { } if (!local && object_culling && !instances_count && !bone_mat && (!obj - || !obj_bounding_sphere_check_visibility( - obj->bounding_sphere, &culling, mat) && !(mdl::obj_reflect_enable - && obj_bounding_sphere_check_visibility( - obj->bounding_sphere, &culling, _mat)))) { + || !obj_bounding_sphere_check_visibility(obj->bounding_sphere, mat) + && !(mdl::obj_reflect_enable + && obj_bounding_sphere_check_visibility(obj->bounding_sphere, _mat)))) { culling.culled.objects++; return false; } @@ -2404,10 +2413,8 @@ namespace mdl { } if (!local && object_culling && !instances_count && !bone_mat - && !obj_bounding_sphere_check_visibility( - mesh->bounding_sphere, &culling, mat) - && (!mesh_morph || !obj_bounding_sphere_check_visibility( - mesh_morph->bounding_sphere, &culling, mat))) { + && !obj_bounding_sphere_check_visibility(mesh->bounding_sphere, mat) + && (!mesh_morph || !obj_bounding_sphere_check_visibility(mesh_morph->bounding_sphere, mat))) { culling.culled.meshes++; continue; } @@ -2423,17 +2430,12 @@ namespace mdl { continue; if (!local && object_culling && !instances_count && !bone_mat) { - int32_t v32 = obj_bounding_sphere_check_visibility( - sub_mesh->bounding_sphere, &culling, mat); + int32_t v32 = obj_bounding_sphere_check_visibility(sub_mesh->bounding_sphere, mat); if (v32 != 2 || (!mesh->attrib.m.billboard && !mesh->attrib.m.billboard_y_axis && !mesh->attrib.m.disable_aabb_culling)) { - if (v32 == 2) { - if (disp_manager->culling_func) - v32 = 1; - else - v32 = obj_axis_aligned_bounding_box_check_visibility( - sub_mesh->axis_aligned_bounding_box, mat); - } + if (v32 == 2) + v32 = obj_axis_aligned_bounding_box_check_visibility( + sub_mesh->axis_aligned_bounding_box, mat); if (!v32) { if (!mesh_morph || j >= mesh_morph->num_submesh) { @@ -2447,15 +2449,10 @@ namespace mdl { continue; } - v32 = obj_bounding_sphere_check_visibility( - sub_mesh_morph->bounding_sphere, &culling, mat); - if (v32 == 2) { - if (disp_manager->culling_func) - v32 = 1; - else - v32 = obj_axis_aligned_bounding_box_check_visibility( - sub_mesh_morph->axis_aligned_bounding_box, mat); - } + int32_t v32 = obj_bounding_sphere_check_visibility(sub_mesh_morph->bounding_sphere, mat); + if (v32 == 2) + v32 = obj_axis_aligned_bounding_box_check_visibility( + sub_mesh_morph->axis_aligned_bounding_box, mat); if (!v32) { culling.culled.sub_meshes++; @@ -2771,10 +2768,8 @@ namespace mdl { } if (object_culling && !instances_count && !bone_mat - && !obj_bounding_sphere_check_visibility( - mesh->bounding_sphere, &culling, _mat) - && (!mesh_morph || !obj_bounding_sphere_check_visibility( - mesh_morph->bounding_sphere, &culling, _mat))) { + && !obj_bounding_sphere_check_visibility(mesh->bounding_sphere, _mat) + && (!mesh_morph || !obj_bounding_sphere_check_visibility(mesh_morph->bounding_sphere, _mat))) { culling.culled.meshes++; continue; } @@ -2792,20 +2787,12 @@ namespace mdl { continue; if (object_culling && !instances_count && !bone_mat) { - int32_t v32 = obj_bounding_sphere_check_visibility( - sub_mesh->bounding_sphere, &culling, _mat); + int32_t v32 = obj_bounding_sphere_check_visibility(sub_mesh->bounding_sphere, _mat); if (v32 != 2 || (!mesh->attrib.m.billboard && !mesh->attrib.m.billboard_y_axis && !mesh->attrib.m.disable_aabb_culling)) { - if (v32 == 2) { - if (culling_func) - v32 = 1; - else { - obj_axis_aligned_bounding_box aabb = *sub_mesh->axis_aligned_bounding_box; - mat4_transform_point(&reflect_mat, &aabb.center, &aabb.center); - mat4_transform_vector(&reflect_mat, &aabb.size, &aabb.size); - v32 = obj_axis_aligned_bounding_box_check_visibility(&aabb, mat); - } - } + if (v32 == 2) + v32 = obj_axis_aligned_bounding_box_check_visibility( + sub_mesh->axis_aligned_bounding_box, _mat); if (!v32) { if (!mesh_morph || j >= mesh_morph->num_submesh) { @@ -2819,18 +2806,10 @@ namespace mdl { continue; } - int32_t v32 = obj_bounding_sphere_check_visibility( - sub_mesh_morph->bounding_sphere, &culling, _mat); - if (v32 == 2) { - if (culling_func) - v32 = 1; - else { - obj_axis_aligned_bounding_box aabb = *sub_mesh_morph->axis_aligned_bounding_box; - mat4_transform_point(&reflect_mat, &aabb.center, &aabb.center); - mat4_transform_vector(&reflect_mat, &aabb.size, &aabb.size); - v32 = obj_axis_aligned_bounding_box_check_visibility(&aabb, mat); - } - } + int32_t v32 = obj_bounding_sphere_check_visibility(sub_mesh_morph->bounding_sphere, _mat); + if (v32 == 2) + v32 = obj_axis_aligned_bounding_box_check_visibility( + sub_mesh_morph->axis_aligned_bounding_box, mat); if (!v32) { culling.culled.sub_meshes++; diff --git a/src/DivaGL/render.cpp b/src/DivaGL/render.cpp index cdced59..62fc118 100644 --- a/src/DivaGL/render.cpp +++ b/src/DivaGL/render.cpp @@ -41,7 +41,7 @@ namespace rndr { gl_state_disable_depth_test(); gl_state_disable_blend(); - dof->apply(&rend_texture[0]); + dof->apply(&rend_texture[0], &rctx->render_buffer); draw_lens_ghost(); diff --git a/src/DivaGL/render_manager.cpp b/src/DivaGL/render_manager.cpp index d4e8dcc..39adf15 100644 --- a/src/DivaGL/render_manager.cpp +++ b/src/DivaGL/render_manager.cpp @@ -28,6 +28,7 @@ struct reflect_full_struct { RenderTexture reflect_texture; RenderTexture reflect_buffer_texture; RenderTexture reflect_contour_texture; + renderer::DOF3* dof; reflect_full_struct(); ~reflect_full_struct(); @@ -68,6 +69,9 @@ static void draw_pass_3d_translucent_has_objects(bool* arr, mdl::ObjType type); static void draw_pass_reflect_full(rndr::RenderManager& render_manager); +static bool draw_pass_reflect_get_obj_reflect_surface(); +static bool draw_pass_reflect_get_obj_reflect_surface(mdl::ObjType type); + static void blur_filter_apply(RenderTexture* dst, RenderTexture* src, blur_filter_mode filter, const vec2 res_scale, const vec4 scale, const vec4 offset); @@ -1285,7 +1289,7 @@ void render_manager_patch() { INSTALL_HOOK(render_manager_init_data); } -reflect_full_struct::reflect_full_struct() { +reflect_full_struct::reflect_full_struct() : dof() { } @@ -1294,6 +1298,8 @@ reflect_full_struct::~reflect_full_struct() { } void reflect_full_struct::free() { + delete dof; + reflect_contour_texture.Free(); reflect_buffer_texture.Free(); @@ -1303,12 +1309,20 @@ void reflect_full_struct::free() { void reflect_full_struct::init() { rndr::Render* render = render_manager.render; - reflect_texture.Init(render->render_width[0], render->render_height[0], - 0, GL_RGBA16F, GL_DEPTH_COMPONENT24); - reflect_buffer_texture.Init(render->render_width[0], render->render_height[0], - 0, GL_RGBA16F, GL_DEPTH_COMPONENT24); + extern int32_t config_reflect_res_scale; + const float_t res_scale = clamp_def((float_t)((double_t)config_reflect_res_scale / 100.0), 0.25f, 1.0f); + + int32_t render_width = (int32_t)prj::roundf((float_t)render->render_width[0] * res_scale); + render_width = min_def(max_def(render_width, 128), render->render_width[0]); + int32_t render_height = (int32_t)prj::roundf((float_t)render->render_height[0] * res_scale); + render_height = min_def(max_def(render_height, 72), render->render_height[0]); + + reflect_texture.Init(render_width, render_height, 0, GL_RGBA16F, GL_DEPTH_COMPONENT24); + reflect_buffer_texture.Init(render_width, render_height, 0, GL_RGBA16F, GL_DEPTH_COMPONENT24); reflect_contour_texture.SetColorDepthTextures(reflect_texture.GetColorTex()); + + dof = new renderer::DOF3(render_width, render_height); } void get_reflect_mat() { @@ -2024,10 +2038,11 @@ static void draw_pass_reflect_full(rndr::RenderManager& render_manager) { RenderTexture& refl_buf_tex = reflect_full_ptr->reflect_buffer_texture; refl_tex.Bind(); extern bool reflect_full; - if (disp_manager->get_obj_count(mdl::OBJ_TYPE_REFLECT_OPAQUE) + if (draw_pass_reflect_get_obj_reflect_surface() + && (disp_manager->get_obj_count(mdl::OBJ_TYPE_REFLECT_OPAQUE) || disp_manager->get_obj_count(mdl::OBJ_TYPE_REFLECT_TRANSPARENT) || disp_manager->get_obj_count(mdl::OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS) - || disp_manager->get_obj_count(mdl::OBJ_TYPE_REFLECT_TRANSLUCENT)) { + || disp_manager->get_obj_count(mdl::OBJ_TYPE_REFLECT_TRANSLUCENT))) { reflect_tex = &refl_tex; refl_tex.SetViewport(); @@ -2150,13 +2165,16 @@ static void draw_pass_reflect_full(rndr::RenderManager& render_manager) { if (render_manager.shadow) draw_pass_3d_shadow_reset(); + gl_state_set_cull_face_mode(GL_BACK); + gl_state_disable_depth_test(); + + reflect_full_ptr->dof->apply(&refl_tex, &refl_buf_tex); + rndr::Render* render = render_manager.render; rctx->set_scene_framebuffer_size(render->render_width[0], render->render_height[0], render->render_width[0], render->render_height[0]); reflect_draw = false; - gl_state_set_cull_face_mode(GL_BACK); - gl_state_disable_depth_test(); uniform->arr[U_REFLECT] = 0; for (int32_t i = render_manager.reflect_blur_num, j = 0; i > 0; i--, j++) { @@ -2177,6 +2195,39 @@ static void draw_pass_reflect_full(rndr::RenderManager& render_manager) { gl_state_end_event(); } +static bool draw_pass_reflect_get_obj_reflect_surface() { + return draw_pass_reflect_get_obj_reflect_surface(mdl::OBJ_TYPE_OPAQUE) + || draw_pass_reflect_get_obj_reflect_surface(mdl::OBJ_TYPE_TRANSLUCENT) + || draw_pass_reflect_get_obj_reflect_surface(mdl::OBJ_TYPE_TRANSLUCENT_SORT_BY_RADIUS) + || draw_pass_reflect_get_obj_reflect_surface(mdl::OBJ_TYPE_TRANSPARENT); +} + +static bool draw_pass_reflect_get_obj_reflect_surface(mdl::ObjType type) { + mdl::ObjList& list = disp_manager->get_obj_list(type); + + for (mdl::ObjData*& i : disp_manager->get_obj_list(type)) + switch (i->kind) { + case mdl::OBJ_KIND_NORMAL: { + switch (i->args.sub_mesh.material->material.shader.index) { + case SHADER_FT_WATER01: // _WATER01 + case SHADER_FT_FLOOR: // _FLOOR + case SHADER_FT_PUDDLE: // _PUDDLE + return true; + } + } break; + case mdl::OBJ_KIND_TRANSLUCENT: { + for (int32_t j = 0; j < i->args.translucent.count; j++) + switch (i->args.translucent.sub_mesh[j]->material->material.shader.index) { + case SHADER_FT_WATER01: // _WATER01 + case SHADER_FT_FLOOR: // _FLOOR + case SHADER_FT_PUDDLE: // _PUDDLE + return true; + } + } break; + } + return false; +} + static void blur_filter_apply(RenderTexture* dst, RenderTexture* src, blur_filter_mode filter, const vec2 res_scale, const vec4 scale, const vec4 offset) { if (!dst || !src) diff --git a/src/DivaGL/renderer/dof.cpp b/src/DivaGL/renderer/dof.cpp index 57bf332..9a49648 100644 --- a/src/DivaGL/renderer/dof.cpp +++ b/src/DivaGL/renderer/dof.cpp @@ -37,7 +37,7 @@ namespace renderer { } - void DOF3::apply(RenderTexture* rt) { + void DOF3::apply(RenderTexture* rt, RenderTexture* buf_rt) { if (dof_debug_data->flags & DOF_DEBUG_USE_UI_PARAMS) { if (dof_debug_data->flags & DOF_DEBUG_ENABLE_DOF) { if (dof_debug_data->flags & DOF_DEBUG_ENABLE_PHYS_DOF) { @@ -65,7 +65,7 @@ namespace renderer { } focus = max_def(focus, camera_data.min_distance); - apply_physical(rt, rt->GetColorTex(), rt->GetDepthTex(), + apply_physical(rt, buf_rt, rt->GetColorTex(), rt->GetDepthTex(), camera_data.min_distance, camera_data.max_distance, focus, dof_debug_data->focal_length, camera_data.fov * DEG_TO_RAD_FLOAT, @@ -73,7 +73,7 @@ namespace renderer { } else { float_t fuzzing_range = max_def(dof_debug_data->f2.fuzzing_range, 0.01f); - apply_f2(rt, rt->GetColorTex(), rt->GetDepthTex(), + apply_f2(rt, buf_rt, rt->GetColorTex(), rt->GetDepthTex(), camera_data.min_distance, camera_data.max_distance, camera_data.fov * DEG_TO_RAD_FLOAT, dof_debug_data->f2.focus, dof_debug_data->f2.focus_range, @@ -84,7 +84,7 @@ namespace renderer { else if (dof_pv_data->enable && dof_pv_data->f2.ratio > 0.0f) { float_t fuzzing_range = max_def(dof_pv_data->f2.fuzzing_range, 0.01f); if (dof_pv_data->f2.fuzzing_range >= 0.0099999998) - apply_f2(rt, rt->GetColorTex(), rt->GetDepthTex(), + apply_f2(rt, buf_rt, rt->GetColorTex(), rt->GetDepthTex(), camera_data.min_distance, camera_data.max_distance, camera_data.fov * DEG_TO_RAD_FLOAT, dof_pv_data->f2.focus, dof_pv_data->f2.focus_range, @@ -152,7 +152,7 @@ namespace renderer { glGenVertexArrays(1, &vao); } - void DOF3::apply_f2(RenderTexture* rt, GLuint color_texture, + void DOF3::apply_f2(RenderTexture* rt, RenderTexture* buf_rt, GLuint color_texture, GLuint depth_texture, float_t min_distance, float_t max_distance, float_t fov, float_t focus, float_t focus_range, float_t fuzzing_range, float_t ratio) { gl_state_begin_event("renderer::DOF3::apply_f2"); @@ -168,7 +168,7 @@ namespace renderer { render_tiles(depth_texture, true); downsample(color_texture, depth_texture, true); apply_main_filter(true); - upsample(rt, color_texture, depth_texture, true); + upsample(rt, buf_rt, color_texture, depth_texture, true); gl_state_use_program(0); for (int32_t i = 0; i < 8; i++) { @@ -179,7 +179,7 @@ namespace renderer { gl_state_end_event(); } - void DOF3::apply_physical(RenderTexture* rt, GLuint color_texture, + void DOF3::apply_physical(RenderTexture* rt, RenderTexture* buf_rt, GLuint color_texture, GLuint depth_texture, float_t min_distance, float_t max_distance, float_t focus, float_t focal_length, float_t fov, float_t f_number) { gl_state_begin_event("renderer::DOF3::apply_physical"); @@ -195,7 +195,7 @@ namespace renderer { render_tiles(depth_texture, false); downsample(color_texture, depth_texture, false); apply_main_filter(false); - upsample(rt, color_texture, depth_texture, false); + upsample(rt, buf_rt, color_texture, depth_texture, false); shader::unbind(); for (int32_t i = 0; i < 8; i++) { @@ -263,9 +263,10 @@ namespace renderer { gl_state_end_event(); } - void DOF3::upsample(RenderTexture* rt, GLuint color_texture, GLuint depth_texture, bool f2) { + void DOF3::upsample(RenderTexture* rt, RenderTexture* buf_rt, + GLuint color_texture, GLuint depth_texture, bool f2) { gl_state_begin_event("renderer::DOF3::upsample"); - rctx->render_buffer.Bind(); + buf_rt->Bind(); gl_state_set_viewport(0, 0, width, height); uniform->arr[U_DOF_STAGE] = 4; shaders_ft.set(SHADER_FT_DOF); @@ -283,7 +284,7 @@ namespace renderer { glDrawArraysDLL(GL_TRIANGLE_STRIP, 0, 4); glCopyImageSubData( - rctx->render_buffer.GetColorTex(), GL_TEXTURE_2D, 0, 0, 0, 0, + buf_rt->GetColorTex(), GL_TEXTURE_2D, 0, 0, 0, 0, rt->GetColorTex(), GL_TEXTURE_2D, 0, 0, 0, 0, width, height, 1); gl_state_end_event(); } diff --git a/src/DivaGL/renderer/dof.hpp b/src/DivaGL/renderer/dof.hpp index cb0961a..626889c 100644 --- a/src/DivaGL/renderer/dof.hpp +++ b/src/DivaGL/renderer/dof.hpp @@ -58,24 +58,25 @@ namespace renderer { DOF3(int32_t width, int32_t height); ~DOF3(); - void apply(RenderTexture* rt); + void apply(RenderTexture* rt, RenderTexture* buf_rt); void resize(int32_t width, int32_t height); private: void free(); void init(int32_t width, int32_t height); - void apply_f2(RenderTexture* rt, GLuint color_texture, + void apply_f2(RenderTexture* rt, RenderTexture* buf_rt, GLuint color_texture, GLuint depth_texture, float_t min_distance, float_t max_distance, float_t fov, float_t focus, float_t focus_range, float_t fuzzing_range, float_t ratio); - void apply_physical(RenderTexture* rt, GLuint color_texture, + void apply_physical(RenderTexture* rt, RenderTexture* buf_rt, GLuint color_texture, GLuint depth_texture, float_t min_distance, float_t max_distance, float_t focus, float_t focal_length, float_t fov, float_t f_number); void render_tiles(GLuint depth_texture, bool f2); void downsample(GLuint color_texture, GLuint depth_texture, bool f2); void apply_main_filter(bool f2); - void upsample(RenderTexture* rt, GLuint color_texture, GLuint depth_texture, bool f2); + void upsample(RenderTexture* rt, RenderTexture* buf_rt, + GLuint color_texture, GLuint depth_texture, bool f2); void init_textures(int32_t width, int32_t height); void update_data(float_t min_dist, float_t max_dist, float_t fov, float_t dist, float_t focal_length, diff --git a/src/DivaGL/stage.cpp b/src/DivaGL/stage.cpp index fb0564e..13f2478 100644 --- a/src/DivaGL/stage.cpp +++ b/src/DivaGL/stage.cpp @@ -112,7 +112,7 @@ HOOK(void, FASTCALL, stage__set, 0x0000000140647710, stage* prev, stage* curr) { render_manager.reflect_blur_num = reflect->blur_num; render_manager.reflect_blur_filter = (blur_filter_mode)reflect->blur_filter; render_manager.reflect = true; - reflect_refract_resolution_mode mode = REFLECT_REFRACT_RESOLUTION_512x512; + reflect_refract_resolution_mode mode = REFLECT_REFRACT_RESOLUTION_512x256; if (frg_stage_data->reflect_type != STAGE_DATA_REFLECT_REFLECT_MAP) mode = reflect->mode; render_manager.tex_index[0] = mode; diff --git a/thirdparty.txt b/thirdparty.txt index eabd9be..e585a04 100644 --- a/thirdparty.txt +++ b/thirdparty.txt @@ -108,3 +108,31 @@ Copyright notice: Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu + +------------------------------------------------------------------------------- + +PluginConfigApi/PluginConfigApi.h from PD-Loader + +PD Loader and the included plugins are distributed under MIT License: + + Copyright (c) Project DIVA Modding 2nd Community + Copyright (c) samyuu (nop) (original TLAC code) + Copyright (c) ThirteenAG (original Ultimate ASI Loader code) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE.