diff --git a/src/CRE/render_context.cpp b/src/CRE/render_context.cpp index 72c6448a..238da4db 100644 --- a/src/CRE/render_context.cpp +++ b/src/CRE/render_context.cpp @@ -1135,6 +1135,8 @@ namespace mdl { uniform_value_reset(); shader::unbind(); gl_state_set_blend_func(GL_ONE, GL_ZERO); + for (int32_t i = 0; i < 5; i++) + gl_state_bind_sampler(i, 0); } void DispManager::draw_translucent(ObjType type, int32_t alpha) { @@ -2157,11 +2159,17 @@ namespace rndr { field_31C(), field_31D(), field_31E(), field_31F(), field_320(), npr(), samplers(), sprite_samplers() { for (bool& i : pass_sw) i = true; - reflect = true; - refract = true; + + set_pass_sw(RND_PASSID_2, false); + set_pass_sw(RND_PASSID_REFLECT, false); + set_pass_sw(RND_PASSID_REFRACT, false); + set_pass_sw(RND_PASSID_USER, false); + set_pass_sw(RND_PASSID_SHOW_VECTOR, false); + shadow = true; opaque_z_sort = true; alpha_z_sort = true; + for (bool& i : draw_pass_3d) i = true; @@ -2265,11 +2273,11 @@ namespace rndr { delete shadow_ptr; } - void RenderManager::add_user(int32_t type, void(*func)(void*), void* data) { + void RenderManager::add_user_func(int32_t type, void(*func)(void*), void* data) { user.push_back({ type, func, data }); } - void RenderManager::clear_user(int32_t type) { + void RenderManager::clear_user_func(int32_t type) { for (std::list::iterator i = user.begin(); i != user.end(); i++) if (i->type == type) { user.erase(i); diff --git a/src/CRE/render_context.hpp b/src/CRE/render_context.hpp index be1fbd30..f76024cf 100644 --- a/src/CRE/render_context.hpp +++ b/src/CRE/render_context.hpp @@ -614,8 +614,8 @@ namespace rndr { RenderManager(); ~RenderManager(); - void add_user(int32_t type, void(*func)(void*), void* data); - void clear_user(int32_t type); + void add_user_func(int32_t type, void(*func)(void*), void* data); + void clear_user_func(int32_t type); render_texture& get_render_texture(int32_t index); void resize(int32_t width, int32_t height); void set_effect_texture(texture* value); @@ -795,10 +795,6 @@ struct obj_skinning_shader_data { vec4 g_joint_transforms[768]; }; -struct transparency_batch_shader_data { - vec4 g_opacity; -}; - struct quad_shader_data { vec4 g_texcoord_modifier; vec4 g_texel_size; @@ -816,6 +812,10 @@ struct sss_filter_gaussian_coef_shader_data { vec4 g_coef[64]; }; +struct transparency_batch_shader_data { + vec4 g_opacity; +}; + struct render_context { ::camera* camera; draw_state draw_state; @@ -848,6 +848,8 @@ struct render_context { GL::UniformBuffer imgfilter_batch_ubo; GL::UniformBuffer glass_eye_batch_ubo; GL::UniformBuffer quad_ubo; + GL::UniformBuffer ripple_ubo; + GL::UniformBuffer ripple_emit_ubo; GL::UniformBuffer sprite_scene_ubo; GL::UniformBuffer sss_filter_gaussian_coef_ubo; GL::UniformBuffer transparency_batch_ubo; diff --git a/src/CRE/render_manager.cpp b/src/CRE/render_manager.cpp index 67cca8b9..a70e49b9 100644 --- a/src/CRE/render_manager.cpp +++ b/src/CRE/render_manager.cpp @@ -19,11 +19,6 @@ #include "task_effect.hpp" #include "texture.hpp" -struct texture_param { - GLint width; - GLint height; -}; - static void blur_filter_apply(render_context* rctx, GLuint tex_0, GLuint tex_1, blur_filter_mode filter, const vec2 res_scale, const vec4 scale, const vec4 offset); static void draw_pass_shadow_begin_make_shadowmap(render_context* rctx, @@ -47,11 +42,6 @@ static int32_t draw_pass_3d_translucent_count_layers(render_context* rctx, int32_t* alpha_array, mdl::ObjType opaque, mdl::ObjType transparent, mdl::ObjType translucent); static void draw_pass_3d_translucent_has_objects(render_context* rctx, bool* arr, mdl::ObjType type); -static void draw_pass_set_camera(render_context* rctx); -static void texture_params_get(GLuint tex_0, texture_param* tex_0_param, - GLuint tex_1, texture_param* tex_1_param, GLuint tex_2, texture_param* tex_2_param); -static void texture_params_restore(texture_param* tex_0_param, - texture_param* tex_1_param, texture_param* tex_2_param); extern bool draw_grid_3d; extern void draw_pass_3d_grid(render_context* rctx); @@ -875,7 +865,7 @@ void image_filter_scale(render_context* rctx, GLuint dst, GLuint src, const vec4 return; texture_param tex_params[2]; - texture_params_get(dst, &tex_params[0], src, &tex_params[1], 0, 0); + texture_params_get(dst, &tex_params[0], src, &tex_params[1]); filter_scene_shader_data filter_scene = {}; filter_scene.g_transform = { 1.0f, 1.0f, 0.0f, 0.0f }; @@ -894,7 +884,24 @@ void image_filter_scale(render_context* rctx, GLuint dst, GLuint src, const vec4 rctx->imgfilter_batch_ubo.Bind(1); gl_state_active_bind_texture_2d(0, src); render_texture::draw_custom(); - texture_params_restore(&tex_params[0], &tex_params[1], 0); + + texture_params_restore(&tex_params[0], &tex_params[1]); +} + +void draw_pass_set_camera(render_context* rctx) { + camera* cam = rctx->camera; + cam->update_data(); + rctx->view_mat = cam->view; + rctx->proj_mat = cam->projection; + rctx->vp_mat = cam->view_projection; + rctx->obj_scene.set_projection_view(cam->view, cam->projection); + cam->get_view_point(rctx->obj_scene.g_view_position); + + rctx->g_near_far = { + (float_t)(cam->max_distance / (cam->max_distance - cam->min_distance)), + (float_t)(-(cam->max_distance * cam->min_distance) / (cam->max_distance - cam->min_distance)), + 0.0f, 0.0f + }; } static void draw_pass_shadow_begin_make_shadowmap(render_context* rctx, @@ -1003,7 +1010,7 @@ static void draw_pass_shadow_filter(render_context* rctx, render_texture* a1, re return; texture_param tex_params[2]; - texture_params_get(v7, &tex_params[0], v9, &tex_params[1], 0, 0); + texture_params_get(v7, &tex_params[0], v9, &tex_params[1]); if (tex_params[0].width != tex_params[1].width || tex_params[0].height != tex_params[1].height) return; @@ -1048,7 +1055,8 @@ static void draw_pass_shadow_filter(render_context* rctx, render_texture* a1, re gl_state_active_bind_texture_2d(0, v9); render_texture::draw_custom(); shader::unbind(); - texture_params_restore(&tex_params[0], &tex_params[1], 0); + + texture_params_restore(&tex_params[0], &tex_params[1]); } static void draw_pass_shadow_esm_filter(render_context* rctx, @@ -1093,6 +1101,7 @@ static void draw_pass_shadow_esm_filter(render_context* rctx, shaders_ft.set(SHADER_FT_ESMFILT); gl_state_active_bind_texture_2d(0, buf_tex); render_texture::draw(&shaders_ft); + texture_params_restore(&tex_params[0], &tex_params[1], &tex_params[2]); } @@ -1342,8 +1351,12 @@ static void draw_pass_3d_shadow_set(shadow* shad, render_context* rctx) { rctx->obj_scene.g_esm_param = { esm_param, 0.0f, 0.0f, 0.0f }; rctx->draw_state.self_shadow = true; } - else + else { + gl_state_active_bind_texture_2d(19, rctx->empty_texture_2d); + gl_state_active_bind_texture_2d(20, rctx->empty_texture_2d); + gl_state_active_texture(0); rctx->draw_state.self_shadow = false; + } if (shad->field_2EC > 0) { rctx->draw_state.light = true; @@ -1495,73 +1508,13 @@ static void draw_pass_3d_translucent_has_objects(render_context* rctx, bool* arr } } -static void draw_pass_set_camera(render_context* rctx) { - camera* cam = rctx->camera; - cam->update_data(); - rctx->view_mat = cam->view; - rctx->proj_mat = cam->projection; - rctx->vp_mat = cam->view_projection; - rctx->obj_scene.set_projection_view(cam->view, cam->projection); - cam->get_view_point(rctx->obj_scene.g_view_position); - - rctx->g_near_far = { - (float_t)(cam->max_distance / (cam->max_distance - cam->min_distance)), - (float_t)(-(cam->max_distance * cam->min_distance) / (cam->max_distance - cam->min_distance)), - 0.0f, 0.0f - }; -} - -static void texture_params_get(GLuint tex_0, texture_param* tex_0_param, - GLuint tex_1, texture_param* tex_1_param, GLuint tex_2, texture_param* tex_2_param) { - gl_state_disable_depth_test(); - if (tex_0_param) { - tex_0_param->width = 0; - tex_0_param->height = 0; - if (tex_0) { - gl_state_bind_texture_2d(tex_0); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_0_param->width); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_0_param->height); - } - } - - if (tex_1_param) { - tex_1_param->width = 0; - tex_1_param->height = 0; - if (tex_1) { - gl_state_bind_texture_2d(tex_1); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_1_param->width); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_1_param->height); - } - } - - if (tex_2_param) { - tex_2_param->width = 0; - tex_2_param->height = 0; - if (tex_2) { - gl_state_bind_texture_2d(tex_2); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_2_param->width); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_2_param->height); - } - } - gl_state_bind_texture_2d(0); - - if (tex_0_param) - glViewport(0, 0, tex_0_param->width, tex_0_param->height); -} - -static void texture_params_restore(texture_param* tex_0_param, - texture_param* tex_1_param, texture_param* tex_2_param) { - for (int32_t i = 0; i < 4; i++) - gl_state_active_bind_texture_2d(i, 0); -} - static void blur_filter_apply(render_context* rctx, GLuint dst, GLuint src, blur_filter_mode filter, const vec2 res_scale, const vec4 scale, const vec4 offset) { if (!dst || !src) return; texture_param tex_params[2]; - texture_params_get(dst, &tex_params[0], src, &tex_params[1], 0, 0); + texture_params_get(dst, &tex_params[0], src, &tex_params[1]); filter_scene_shader_data filter_scene = {}; float_t w = res_scale.x / (float_t)tex_params[1].width; @@ -1587,5 +1540,5 @@ static void blur_filter_apply(render_context* rctx, GLuint dst, GLuint src, gl_state_active_bind_texture_2d(0, src); glDrawArrays(GL_TRIANGLE_STRIP, (GLint)(filter * 4LL), 4); - texture_params_restore(&tex_params[0], &tex_params[1], 0); + texture_params_restore(&tex_params[0], &tex_params[1]); } diff --git a/src/CRE/render_manager.hpp b/src/CRE/render_manager.hpp index 4ec15459..5caa55f6 100644 --- a/src/CRE/render_manager.hpp +++ b/src/CRE/render_manager.hpp @@ -11,3 +11,5 @@ #include "render_context.hpp" extern void image_filter_scale(render_context* rctx, GLuint dst, GLuint src, const vec4 scale); + +extern void draw_pass_set_camera(render_context* rctx); diff --git a/src/CRE/rob/rob.cpp b/src/CRE/rob/rob.cpp index a96cb019..8eff63d0 100644 --- a/src/CRE/rob/rob.cpp +++ b/src/CRE/rob/rob.cpp @@ -2407,13 +2407,6 @@ static void rob_chara_item_equip_ctrl(rob_chara_item_equip* rob_itm_equip) { rob_chara_item_equip_object_ctrl(&rob_itm_equip->item_equip_object[i]); } -static float_t rob_chara_get_trans_scale(rob_chara* rob_chr, int32_t bone, vec3* trans) { - if (bone > 26) - return 0.0f; - *trans = rob_chr->data.field_1E68.field_DF8[bone].trans; - return rob_chr->data.field_1E68.field_DF8[bone].scale; -} - mat4* rob_chara_bone_data_get_mats_mat(rob_chara_bone_data* rob_bone_data, size_t index) { if (index < rob_bone_data->mats.size()) return &rob_bone_data->mats[index]; @@ -2522,6 +2515,13 @@ int32_t rob_chara::get_rob_cmn_mottbl_motion_id(int32_t id) { return -1; } +float_t rob_chara::get_trans_scale(int32_t bone, vec3& trans) { + if (bone < 0 || bone > 26) + return 0.0f; + trans = data.field_1E68.field_DF8[bone].trans; + return data.field_1E68.field_DF8[bone].scale; +} + bool rob_chara::is_visible() { return !!(data.field_0 & 0x01); } @@ -7947,7 +7947,7 @@ static void rob_disp_rob_chara_ctrl_thread_main(rob_chara* rob_chr) { rob_chr->item_equip->set_opd_blend_data(&rob_chr->bone_data->motion_loaded); vec3 trans = 0.0f; - rob_chara_get_trans_scale(rob_chr, 0, &trans); + rob_chr->get_trans_scale(0, trans); rob_chr->item_equip->position = trans; rob_chara_item_equip_ctrl(rob_chr->item_equip); if (rob_chara_check_for_ageageagain_module(rob_chr->chara_index, rob_chr->module_index)) { diff --git a/src/CRE/rob/rob.hpp b/src/CRE/rob/rob.hpp index 310a4fa9..091c7e95 100644 --- a/src/CRE/rob/rob.hpp +++ b/src/CRE/rob/rob.hpp @@ -3415,6 +3415,7 @@ struct rob_chara { float_t get_frame_count(); float_t get_max_face_depth(); int32_t get_rob_cmn_mottbl_motion_id(int32_t id); + float_t get_trans_scale(int32_t bone, vec3& trans); bool is_visible(); void load_motion(int32_t motion_id, bool a3, float_t frame, MotionBlendType blend_type, const bone_database* bone_data, const motion_database* mot_db); diff --git a/src/CRE/shader_ft.cpp b/src/CRE/shader_ft.cpp index e3a37110..35a7e6a9 100644 --- a/src/CRE/shader_ft.cpp +++ b/src/CRE/shader_ft.cpp @@ -2764,9 +2764,9 @@ static const bool LAMBERT_permut[] = { false, false, false, + true, + true, false, - true, - true, false, // 8th added }; diff --git a/src/CRE/task_effect.cpp b/src/CRE/task_effect.cpp index ff96493e..9b4a035a 100644 --- a/src/CRE/task_effect.cpp +++ b/src/CRE/task_effect.cpp @@ -9,10 +9,11 @@ #include "GL/uniform_buffer.hpp" #include "auth_3d.hpp" #include "data.hpp" +#include "gl_state.hpp" #include "random.hpp" #include "render_context.hpp" +#include "render_manager.hpp" #include "shader_ft.hpp" -#include "stage_param.hpp" #include "texture.hpp" struct for_ring_vertex_data { @@ -97,6 +98,21 @@ struct rain_particle_batch_shader_data { vec4 g_color; }; +struct ripple_batch_shader_data { + vec4 g_params; +}; + +struct ripple_scene_shader_data { + vec4 g_transform; + vec4 g_texcoord; +}; + +struct ripple_emit_scene_shader_data { + vec4 g_size_in_projection; + vec4 g_transform; + vec4 g_framebuffer_size; +}; + struct struc_608 { const stage_effects* stage_effects; const stage_effects_modern* stage_effects_modern; @@ -160,6 +176,8 @@ static bool task_effect_array_parse_stage_param_data_star(stage_param_star* star static void draw_fog_particle(render_context* rctx, TaskEffectFogRing::Data* data); +static void draw_ripple_emit(render_context* rctx, struc_101* data); + static void leaf_particle_init(bool change_stage = false); static void leaf_particle_ctrl(); static int32_t leaf_particle_disp(); @@ -177,6 +195,12 @@ static void rain_particle_init(bool change_stage); static void rain_particle_ctrl(); static void rain_particle_free(); +static void ripple_emit_init(); +static void ripple_emit_free(); + +static void sub_1403B6ED0(render_texture* a1, render_texture* a2, render_texture* a3, ripple_emit_params& params); +static void sub_1403B6F60(GLuint a1, GLuint a2, GLuint a3, ripple_emit_params& params); + static TaskEffectAuth3D* task_effect_auth_3d; static TaskEffectLeaf* task_effect_leaf; static TaskEffectSnow* task_effect_snow; @@ -191,6 +215,8 @@ static TaskEffectStar* task_effect_star; static TaskEffectParent* task_effect_parent; +static ripple_emit* ripple_emit_data; + static TaskEffectFogAnim::Data* task_effect_fog_anim_data; static TaskEffectFogRing::Data* task_effect_fog_ring_data; static TaskEffectSplash::Data* task_effect_splash_data; @@ -242,6 +268,14 @@ static GL::UniformBuffer rain_particle_scene_ubo; static GL::UniformBuffer rain_particle_batch_ubo; static const size_t rain_ptcl_count = 0x8000; +static GLuint ripple_vao; +static GL::UniformBuffer ripple_batch_ubo; +static GL::UniformBuffer ripple_scene_ubo; + +static GLuint ripple_emit_vao; +static GLuint ripple_emit_vbo; +static GL::UniformBuffer ripple_emit_scene_ubo; + static TaskEffect** task_effect_data_array[] = { (TaskEffect**)&task_effect_auth_3d, 0, @@ -249,7 +283,7 @@ static TaskEffect** task_effect_data_array[] = { 0, 0/*(TaskEffect**)&task_effect_snow*/, 0, - 0/*(TaskEffect**)&task_effect_ripple*/, + (TaskEffect**)&task_effect_ripple, (TaskEffect**)&task_effect_rain, 0, 0, @@ -911,7 +945,7 @@ void TaskEffectFogRing::Data::Dest() { } rctx_ptr->render_manager.set_pass_sw(rndr::RND_PASSID_USER, false); - rctx_ptr->render_manager.clear_user(0); + rctx_ptr->render_manager.clear_user_func(0); rctx_ptr->draw_state.set_fog_height(false); } @@ -985,7 +1019,7 @@ void TaskEffectFogRing::Data::Reset() { } void TaskEffectFogRing::Data::SetStageIndices(std::vector& stage_indices) { - rctx_ptr->render_manager.clear_user(0); + rctx_ptr->render_manager.clear_user_func(0); rctx_ptr->render_manager.set_pass_sw(rndr::RND_PASSID_USER, false); disp = false; current_stage_index = -1; @@ -1091,7 +1125,7 @@ void TaskEffectFogRing::Data::SetStageIndices(std::vector& stage_indice InitParticleData(); rctx_ptr->render_manager.set_pass_sw(rndr::RND_PASSID_USER, true); - rctx_ptr->render_manager.add_user(0, TaskEffectFogRing::Data::DrawStatic, this); + rctx_ptr->render_manager.add_user_func(0, TaskEffectFogRing::Data::DrawStatic, this); } void TaskEffectFogRing::Data::DrawStatic(void* data) { @@ -1596,7 +1630,6 @@ bool TaskEffectRain::Ctrl() { bool TaskEffectRain::Dest() { if (stage_param_data_rain_current) { rain_particle_free(); - rain_ptcl_vbo = 0; stage_param_data_rain_current = 0; stage_param_data_rain_storage_clear(); stage_param_data_rain_set = false; @@ -1689,6 +1722,473 @@ void TaskEffectRain::Reset() { } } +ripple_emit_draw_data::ripple_emit_draw_data() : data() { + +} + +struc_192::struc_192() { + index = -1; +} + +struc_207::struc_207() { + +} + +ripple_emit_params::ripple_emit_params() { + wake_attn = 0.56f; + speed = 1.0f; + field_8 = 0.0005f; + field_C = 0.9f; +} + +ripple_emit::ripple_emit() : delta_frame(), update(), rain_ripple_num(), +rain_ripple_min_value(), rain_ripple_max_value(), field_14(), emit_pos_scale(), emit_pos_ofs_x(), +emit_pos_ofs_z(), ripple_tex_id(), use_float_ripplemap(), field_30(), rob_emitter_size(), +emitter_num(), emitter_size(), field_4C(), field_50(), field_178(), field_2A0(), field_3C8(), +field_4F0(), field_BB4(), counter(), field_BEC(), stage_set(), current_stage_index() { + ground_y = -1001.0f; + emitter_list = 0; +} + +ripple_emit::~ripple_emit() { + ground_y = -1001.0f; +} + +void ripple_emit::add_draw_ripple_emit(struc_101* data) { + if (data->count > 0) + rctx_ptr->disp_manager.entry_obj_user(&mat4_identity, + (mdl::UserArgsFunc)draw_ripple_emit, data, mdl::OBJ_TYPE_USER); +} + +void ripple_emit::clear_tex() { + vec4 clear_color; + glGetFloatv(GL_COLOR_CLEAR_VALUE, (GLfloat*)&clear_color); + + for (int32_t i = 0, j = 5; i < 3; i++, j++) { + render_texture* rt; + float_t v5; + if (use_float_ripplemap) { + rt = &rctx_ptr->render_manager.get_render_texture(j - 3); + v5 = -0.3f; + } + else { + rt = &rctx_ptr->render_manager.get_render_texture(j); + v5 = 0.5f; + } + + glClearColor(0.0f, 0.0f, 0.0f, v5); + rt->bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gl_state_bind_framebuffer(0); + } + + glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); +} + +void ripple_emit::ctrl() { + if (delta_frame > 0.0f) + update = true; +} + +void ripple_emit::dest() { + stage_param_data_ripple_storage_clear(); + rctx_ptr->render_manager.set_pass_sw(rndr::RND_PASSID_USER, false); + rctx_ptr->render_manager.clear_user_func(0); + this->ground_y = -1001.0; +} + +void ripple_emit::disp() { + if (!stage_set) + return; + + if (use_float_ripplemap) { + if (field_30 == 60) + sub_140358690(); + else + sub_14035AED0(); + if (field_30 > 0) + field_30--; + } + else { + sub_14035AED0(); + sub_14035AAE0(); + } +} + +void ripple_emit::draw() { + if (!stage_set) + return; + + gl_state_disable_cull_face(); + + render_context* rctx = rctx_ptr; + + render_texture* rt[3]; + for (int32_t i = 0, j = 2; i < 3; i++, j++) + rt[i] = &rctx->render_manager.get_render_texture( + use_float_ripplemap ? j : (j + 3)); + + if (update) { + int32_t counter = this->counter + 1; + if (counter >= 3) + counter = 0; + + rt[(counter + 1) % 3]->bind(); + + GLint v43[4]; + glGetIntegerv(GL_VIEWPORT, v43); + + int32_t width = rt[0]->color_texture->width; + int32_t height = rt[0]->color_texture->height; + + glViewport(1, 1, width - 2, height - 2); + + draw_pass_set_camera(rctx_ptr); + glClear(GL_DEPTH_BUFFER_BIT); + if (rctx->disp_manager.get_obj_count(mdl::OBJ_TYPE_USER)) { + gl_state_active_bind_texture_2d(7, rt[counter % 3]->color_texture->tex); + rctx->disp_manager.draw(mdl::OBJ_TYPE_USER, 0, true); + gl_state_active_bind_texture_2d(7, 0); + } + + gl_state_bind_framebuffer(0); + + params.field_8 = 0.0005f; + params.field_C = 0.97f; + if (field_30 > 0) { + params.field_8 = 0.00005f; + params.field_C = 0.999f; + } + + sub_1403B6ED0(rt[(counter + 2) % 3], rt[(counter + 1) % 3], rt[counter % 3], params); + + glViewport(v43[0], v43[1], v43[2], v43[3]); + + sub_1403584A0(rt[(counter + 2) % 3]); + + this->counter = counter; + } + + int32_t v11 = (counter + 2) % 3 + 2; + if (!use_float_ripplemap) + v11 += 3; + + rctx->render_manager.set_effect_texture( + rctx->render_manager.get_render_texture(v11).color_texture); + + update = false; + + gl_state_enable_cull_face(); +} + +void ripple_emit::reset() { + field_4F0 = 18; + for (struc_207& i : field_4F4) + for (int32_t j = 0; j < field_4F0; j++) + i.field_0[j].trans = 0.0f; + + field_30 = 60; + + clear_tex(); +} + +void ripple_emit::set_stage_index(int32_t stage_index) { + if (current_stage_index == stage_index) + return; + + current_stage_index = stage_index; + stage_set = false; + if (stage_index == -1) + return; + + for (int32_t& i : stage_indices) { + if (i != stage_index) + continue; + + stage_set = true; + set_stage_param(stage_param_data_ripple_storage_get_value(i)); + clear_tex(); + break; + } +} + +void ripple_emit::set_stage_indices(std::vector& stage_indices) { + static const int32_t dword_1409E5330[] = { + 0, 1, 2, 4, 10, 5, 12, 7, 14, 9, 21, 15, 23, 17, 25, 19, 26, 20 + }; + + stage_set = false; + current_stage_index = -1; + this->stage_indices.clear(); + + stage_param_data_ripple_storage_clear(); + for (int32_t& i : stage_indices) { + stage_param_ripple ripple; + if (task_effect_array_parse_stage_param_data_ripple(&ripple, i)) { + this->stage_indices.push_back(i); + stage_param_data_ripple_storage_set_stage_data(i, &ripple); + } + } + + if (!this->stage_indices.size()) + return; + + current_stage_index = this->stage_indices.front(); + stage_param_ripple* ripple = stage_param_data_ripple_storage_get_value(this->stage_indices.front()); + if (!ripple) + return; + + stage_set = true; + set_stage_param(ripple); + + delta_frame = 1.0f; + counter = 0; + field_BEC = 0; + + rctx_ptr->render_manager.set_pass_sw(rndr::RND_PASSID_USER, true); + rctx_ptr->render_manager.add_user_func(0, ripple_emit::draw_static, this); + + field_4F0 = 18; + for (struc_207& i : field_4F4) + for (int32_t j = 0; j < field_4F0; j++) { + i.field_0[j].index = dword_1409E5330[j]; + i.field_0[j].trans = 0.0f; + } + + update = false; + field_30 = 60; + + clear_tex(); +} + +void ripple_emit::set_stage_param(stage_param_ripple* ripple) { + data_struct* aft_data = &data_list[DATA_AFT]; + texture_database* aft_tex_db = &aft_data->data_ft.tex_db; + + params.wake_attn = ripple->wake_attn; + params.speed = ripple->speed; + rain_ripple_num = (int32_t)ripple->rain_ripple_num; + rain_ripple_min_value = ripple->rain_ripple_min_value; + rain_ripple_max_value = ripple->rain_ripple_max_value; + ground_y = ripple->ground_y; + emit_pos_scale = ripple->emit_pos_scale; + emit_pos_ofs_x = ripple->emit_pos_ofs_x; + emit_pos_ofs_z = ripple->emit_pos_ofs_z; + ripple_tex_id = aft_tex_db->get_texture_id(ripple->ripple_tex_name.c_str()); + use_float_ripplemap = ripple->use_float_ripplemap; + rob_emitter_size = ripple->rob_emitter_size; + emitter_num = ripple->emitter_num; + emitter_list = ripple->emitter_list.data(); + emitter_size = ripple->emitter_size; +} + +void ripple_emit::draw_static(void* data) { + ((ripple_emit*)data)->draw(); +} + +void ripple_emit::sub_1403584A0(render_texture* rt) { + if (ripple_tex_id == -1) + return; + + texture* ripple_tex = texture_storage_get_texture(ripple_tex_id); + if (!ripple_tex) + return; + + field_BB8.set_color_depth_textures(ripple_tex->tex, 0, 0); + field_BB8.bind(0); + + image_filter_scale(rctx_ptr, ripple_tex->tex, rt->color_texture->tex, 1.0f); + gl_state_bind_framebuffer(0); +} + + +void ripple_emit::sub_140358690() { + ripple_emit_draw_data& v1 = field_178; + v1.data.vertex = field_50.vertex; + v1.data.color = field_50.color; + + for (int32_t i = 0; i < 16; i++) { + v1.data.vertex[i].x = rand_state_array_get_float(4) * 1.8f - 0.9f; + v1.data.vertex[i].y = rand_state_array_get_float(4) * 1.8f - 0.9f; + rand_state_array_get_int(0x03, 0x07, 4); + v1.data.vertex[i].z = (float_t)rand_state_array_get_int(0x20, 0xA0, 4); + } + + v1.data.count = 16; + v1.data.ripple_uniform = 1; + v1.data.ripple_emit_uniform = 1; + + add_draw_ripple_emit(&v1.data); +} + +void ripple_emit::sub_1403587C0(const vec3 a2, const vec3 a3, float_t a4, struc_101& a5, struc_101& a6) { + vec3 v34 = a3 - a2; + + float_t v17 = ground_y - (a2.y - a4); + int32_t v19 = 1 - (int32_t)(min_def(v17, a4) * -30.0f); + int32_t v20 = v19 + 3; + + float_t v21 = sqrtf(v34.x * v34.x + v34.z * v34.z) * 0.8f; + if (v21 < 0.03f) + v21 = 0.0f; + + if (a3.y - a4 > ground_y) { + v21 += (float_t)(v34.y * 3.0f); + v20 += (int32_t)(float_t)(v34.y * 30.0f); + } + + float_t v23 = sqrtf(v34.x * v34.x + v34.z * v34.z); + if (v23 >= 0.01f) + v34 *= 1.0f / v23; + else + v34 = 0.0f; + + float_t v24 = min_def(v21, 0.2f); + if (v23 > 0.5f) { + v23 = 0.01f; + v24 = 0.0f; + } + + int32_t v33 = v20 - (int32_t)(v23 * -20.0f); + int32_t v37 = (int32_t)(a4 * 60.0f); + int32_t v27 = v33 >= v37 ? v37 : v33; + + vec4u8 v19a = { 0x08, 0x00, 0x00, (uint8_t)v19 }; + vec4u8 v29 = { (uint8_t)v27, 0x00, 0x00, (uint8_t)(int32_t)(v24 * 1275.0f) }; + + for (float_t i = 0.0f; i < v23; i += 0.03f) { + if (v24 > 0.0f) { + int32_t count = a6.count; + if (count < 16) { + a6.vertex[count].x = (a2.x - v34.x * 0.2f + i * v34.x) * emit_pos_scale; + a6.vertex[count].y = 0.0; + a6.vertex[count].z = (a2.z - v34.z * 0.2f + i * v34.z) * emit_pos_scale; + a6.color[count] = v29; + a6.count++; + } + } + + int32_t count = a5.count; + if (count < 16) { + a5.vertex[count].x = (a2.x + i * v34.x) * emit_pos_scale; + a5.vertex[count].y = 0.0f; + a5.vertex[count].z = (a2.z + i * v34.z) * emit_pos_scale; + a6.color[count] = v19a; + a5.count++; + } + } +} + +void ripple_emit::sub_14035AAE0() { + ripple_emit_draw_data& v1 = field_3C8; + + field_3C8.data.count = 0; + field_3C8.data.vertex = field_3C8.vertex; + field_3C8.data.color = field_3C8.color; + field_3C8.data.size = emitter_size; + + if (!update) + return; + + if (rain_ripple_num) { + int32_t min_value = (int32_t)(rain_ripple_min_value * 127.0f); + int32_t max_value = (int32_t)(rain_ripple_max_value * 127.0f - rain_ripple_min_value * 127.0f); + + max_value = max_def(max_value, 1); + min_value = min_def(min_value, 126); + + for (int32_t i = 0; i < rain_ripple_num; i++) { + v1.data.vertex[i].x = (float_t)(rand_state_array_get_int(4) % 1000) * 0.001f * 2.0f - 1.0f; + v1.data.vertex[i].y = 0.0f; + v1.data.vertex[i].y = (float_t)(rand_state_array_get_int(4) % 1000) * 0.001f * 2.0f - 1.0f; + v1.data.color[i] = { 0x00, 0x00, 0x00, + (uint8_t)(0x7F - rand_state_array_get_int(4) % max_value - min_value) }; + v1.data.count++; + } + } + + for (size_t i = 0; i < emitter_num; i++) { + float_t v10 = emitter_list[i].z; + v1.data.vertex[i].x = ((rand_state_array_get_float(4) - 0.5f) + * v10 + emitter_list[i].x) * emit_pos_scale; + v1.data.vertex[i].y = 0.0f; + v1.data.vertex[i].z = ((rand_state_array_get_float(4) - 0.5f) + * v10 + emitter_list[i].y) * emit_pos_scale; + v1.data.color[i] = rand_state_array_get_float(4) < 0.5f + ? vec4u8(0x00, 0x00, 0x00, 0xFF) : vec4u8(0x00, 0x00, 0x00, 0xFF); + v1.data.count++; + } + + v1.data.ripple_uniform = use_float_ripplemap ? 1 : 0; + v1.data.ripple_emit_uniform = 0; + + add_draw_ripple_emit(&v1.data); +} + +void ripple_emit::sub_14035AED0() { + field_178.data.count = 0; + field_178.data.vertex = field_178.vertex; + field_178.data.color = field_178.color; + field_178.data.size = rob_emitter_size; + + field_2A0.data.count = 0; + field_2A0.data.vertex = field_2A0.vertex; + field_2A0.data.color = field_2A0.color; + field_2A0.data.size = rob_emitter_size; + + if (!update) + return; + + ripple_emit_draw_data& v2 = field_178; + ripple_emit_draw_data& v3 = field_2A0; + + int32_t chara_id = 0; + for (struc_207& i : field_4F4) { + if (!rob_chara_array_check_visibility(chara_id)) { + chara_id++; + continue; + } + + rob_chara* rob_chr = rob_chara_array_get(chara_id); + if (!rob_chr) { + chara_id++; + continue; + } + + for (int32_t j = 0; j < field_4F0; j++) { + struc_192& v4 = i.field_0[j]; + vec3 trans = 0.0f; + float_t scale = rob_chr->get_trans_scale(v4.index, trans); + if (trans.y - ground_y < scale) { + if (use_float_ripplemap) + sub_1403587C0(trans, v4.trans, scale, v2.data, v3.data); + else if (v2.data.count < 16) { + v2.data.vertex[v2.data.count].x = ((rand_state_array_get_float(4) - 0.5f) + * 0.02f + trans.x) * emit_pos_scale + emit_pos_ofs_x; + v2.data.vertex[v2.data.count].y = trans.y; + v2.data.vertex[v2.data.count].z = ((rand_state_array_get_float(4) - 0.5f) + * 0.02f + trans.z) * emit_pos_scale + emit_pos_ofs_z; + v2.data.color[v2.data.count] = { 0x00, 0x00, 0x00, 0x00 }; + v2.data.count++; + } + } + v4.trans = trans; + } + + chara_id++; + } + + if (use_float_ripplemap) { + v3.data.ripple_uniform = !!use_float_ripplemap; + v3.data.ripple_emit_uniform = 1; + add_draw_ripple_emit(&v3.data); + } + + v2.data.ripple_uniform = !!use_float_ripplemap; + v2.data.ripple_emit_uniform = 0; + add_draw_ripple_emit(&v2.data); +} + TaskEffectRipple::TaskEffectRipple() : field_68(), frame_rate_control(), emit() { } @@ -1698,24 +2198,26 @@ TaskEffectRipple::~TaskEffectRipple() { } bool TaskEffectRipple::Init() { + ripple_emit_init(); //sub_1400DE640("TaskEffectRipple::init()\n"); return true; } bool TaskEffectRipple::Ctrl() { emit->delta_frame = frame_rate_control->GetDeltaFrame(); - //emit->ctrl(); + emit->ctrl(); return false; } bool TaskEffectRipple::Dest() { - //emit->dest(); + emit->dest(); //sub_1400DE640("TaskEffectRipple::dest()\n"); + ripple_emit_free(); return true; } void TaskEffectRipple::Disp() { - //emit->disp(); + emit->disp(); } void TaskEffectRipple::PreInit(int32_t stage_index) { @@ -1724,12 +2226,12 @@ void TaskEffectRipple::PreInit(int32_t stage_index) { void TaskEffectRipple::SetStageIndices(std::vector& stage_indices) { SetFrameRateControl(0); - //emit = &ripple_emit_data; - //emit->set_stage_indices(stage_indices); + emit = ripple_emit_data; + emit->set_stage_indices(stage_indices); } void TaskEffectRipple::SetCurrentStageIndex(int32_t value) { - //emit->set_stage_index(value); + emit->set_stage_index(value); } void TaskEffectRipple::SetFrameRateControl(FrameRateControl* value) { @@ -1740,9 +2242,9 @@ void TaskEffectRipple::SetFrameRateControl(FrameRateControl* value) { } void TaskEffectRipple::Reset() { - //if (!emit->use_float_ripplemap) - // ripple_emit_data.clear_tex(); - //ripple_emit_data.reset(); + if (!emit->use_float_ripplemap) + ripple_emit_data->clear_tex(); + ripple_emit_data->reset(); } void leaf_particle_draw() { @@ -1930,6 +2432,9 @@ void task_effect_init() { if (!task_effect_parent) task_effect_parent = new TaskEffectParent; + + if (!ripple_emit_data) + ripple_emit_data = new ripple_emit; task_effect_fog_anim_data = 0; task_effect_fog_ring_data = 0; @@ -1997,6 +2502,11 @@ void task_effect_free() { task_effect_parent = 0; } + if (ripple_emit_data) { + delete ripple_emit_data; + ripple_emit_data = 0; + } + task_effect_fog_anim_data = 0; task_effect_fog_ring_data = 0; task_effect_splash_data = 0; @@ -2527,6 +3037,71 @@ static void draw_fog_particle(render_context* rctx, TaskEffectFogRing::Data* dat gl_state_disable_blend(); } +static void draw_ripple_emit(render_context* rctx, struc_101* data) { + gl_state_set_color_mask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + + { + size_t count = data->count; + vec3* vertex = data->vertex; + vec4u8* color = data->color; + + const size_t vtx_count = (size_t)count * 0x06; + vec3* vtx_data = force_malloc_s(vec3, vtx_count); + + for (size_t i = count; i; i--, vtx_data += 6, vertex++, color++) { + vtx_data[0] = { vertex->x, vertex->z, (float_t)color->w }; + vtx_data[1] = { vertex->x, vertex->z, (float_t)color->w }; + vtx_data[2] = { vertex->x, vertex->z, (float_t)color->w }; + vtx_data[3] = { vertex->x, vertex->z, (float_t)color->w }; + vtx_data[4] = { vertex->x, vertex->z, (float_t)color->w }; + vtx_data[5] = { vertex->x, vertex->z, (float_t)color->w }; + } + + vtx_data -= vtx_count; + + if (GLAD_GL_VERSION_4_5) + glNamedBufferSubData(ripple_emit_vbo, 0, sizeof(vec3) * vtx_count, vtx_data); + else { + gl_state_bind_array_buffer(ripple_emit_vbo); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vec3) * vtx_count, vtx_data); + gl_state_bind_array_buffer(0); + } + free_def(vtx_data); + } + + int32_t size = (int32_t)(data->size + 0.5f); + + render_texture& rt = rctx->render_manager.get_render_texture( + ripple_emit_data->use_float_ripplemap ? 2 : 5); + int32_t width = rt.color_texture->width; + int32_t height = rt.color_texture->height; + + ripple_emit_scene_shader_data shader_data = {}; + shader_data.g_size_in_projection = { + (float_t)size / (float_t)width, + (float_t)size / (float_t)height, + 0.0f, 0.0f + }; + shader_data.g_transform.x = (float_t)width / (float_t)(width - 2); + shader_data.g_transform.y = (float_t)height / (float_t)(height - 2); + shader_data.g_transform.z = 0.0079498291f / (float_t)(width - 2); + shader_data.g_transform.w = -0.0079498291f / (float_t)(height - 2); + shader_data.g_framebuffer_size = { + 1.0f / (float_t)width, + 1.0f / (float_t)height, + 0.0f, 0.0f }; + ripple_emit_scene_ubo.WriteMapMemory(shader_data); + + uniform_value[U_RIPPLE] = data->ripple_uniform; + uniform_value[U_RIPPLE_EMIT] = data->ripple_emit_uniform; + gl_state_bind_vertex_array(ripple_emit_vao); + shaders_ft.set(SHADER_FT_RIPEMIT); + ripple_emit_scene_ubo.Bind(0); + shaders_ft.draw_arrays(GL_TRIANGLES, 0, data->count * 6); + + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); +} + static void leaf_particle_init(bool change_stage) { leaf_particle_emit_timer = 0.0f; leaf_particle_emit_interval = stage_param_data_leaf_current->emit_interval; @@ -3179,3 +3754,117 @@ static void rain_particle_free() { rain_particle_scene_ubo.Destroy(); rain_particle_batch_ubo.Destroy(); } + +static void ripple_emit_init() { + if (!ripple_vao) + glGenVertexArrays(1, &ripple_vao); + + ripple_batch_ubo.Create(sizeof(ripple_batch_shader_data)); + ripple_scene_ubo.Create(sizeof(ripple_scene_shader_data)); + + if (!ripple_emit_vao) + glGenVertexArrays(1, &ripple_emit_vao); + + if (!ripple_emit_vbo) + glGenBuffers(1, &ripple_emit_vbo); + + size_t max_count = 16; + + const size_t max_vtx_count = (size_t)max_count * 0x06; + + static const GLsizei buffer_size = sizeof(vec3); + + gl_state_bind_array_buffer(ripple_emit_vbo, true); + if (GLAD_GL_VERSION_4_4) + glBufferStorage(GL_ARRAY_BUFFER, + (GLsizeiptr)(buffer_size * max_vtx_count), + 0, GL_DYNAMIC_STORAGE_BIT | GL_MAP_WRITE_BIT); + else + glBufferData(GL_ARRAY_BUFFER, + (GLsizeiptr)(buffer_size * max_vtx_count), + 0, GL_DYNAMIC_DRAW); + + gl_state_bind_vertex_array(ripple_emit_vao); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, 0); + + gl_state_bind_vertex_array(0); + gl_state_bind_array_buffer(0); + + ripple_emit_scene_ubo.Create(sizeof(ripple_emit_scene_shader_data)); +} + +static void ripple_emit_free() { + if (ripple_vao) { + glDeleteVertexArrays(1, &ripple_vao); + ripple_vao = 0; + } + + ripple_batch_ubo.Destroy(); + ripple_scene_ubo.Destroy(); + + if (ripple_emit_vao) { + glDeleteVertexArrays(1, &ripple_emit_vao); + ripple_emit_vao = 0; + } + + if (ripple_emit_vbo) { + glDeleteBuffers(1, &ripple_emit_vbo); + ripple_emit_vbo = 0; + } + + ripple_emit_scene_ubo.Destroy(); +} + +static void sub_1403B6ED0(render_texture* a1, render_texture* a2, render_texture* a3, ripple_emit_params& params) { + a1->bind(); + if (a1->color_texture->internal_format == GL_RGBA32F + || a1->color_texture->internal_format == GL_RGBA16F) + uniform_value[U_RIPPLE] = 1; + else + uniform_value[U_RIPPLE] = 0; + sub_1403B6F60(a1->color_texture->tex, a2->color_texture->tex, a3->color_texture->tex, params); + gl_state_bind_framebuffer(0); +} + +static void sub_1403B6F60(GLuint a1, GLuint a2, GLuint a3, ripple_emit_params& params) { + if (!a1 || !a2 || !a3) + return; + + texture_param tex_params[2]; + texture_params_get(0, 0, a1, &tex_params[0], a2, &tex_params[1]); + + int32_t width = tex_params[1].width; + int32_t height = tex_params[1].height; + + GLint v43[4]; + glGetIntegerv(GL_VIEWPORT, v43); + glViewport(1, 1, width - 2, height - 2); + + ripple_scene_shader_data ripple_scene = {}; + ripple_scene.g_transform = { + params.speed / (float_t)width, params.speed / (float_t)height, + (float_t)width / (float_t)(width - 2), (float_t)height / (float_t)(height - 2) + }; + ripple_scene.g_texcoord = { 1.0f, 0.0f, 0.0f, 0.0f }; + ripple_scene_ubo.WriteMapMemory(ripple_scene); + + ripple_batch_shader_data ripple_batch = {}; + ripple_batch.g_params = { params.wake_attn, params.speed, params.field_8, params.field_C }; + ripple_batch_ubo.WriteMapMemory(ripple_batch); + + gl_state_bind_vertex_array(ripple_vao); + shaders_ft.set(SHADER_FT_RIPPLE); + ripple_scene_ubo.Bind(0); + ripple_batch_ubo.Bind(1); + gl_state_active_bind_texture_2d(0, a2); + gl_state_active_bind_texture_2d(1, a3); + shaders_ft.draw_arrays(GL_TRIANGLE_STRIP, 0, 4); + gl_state_active_bind_texture_2d(0, 0); + gl_state_active_bind_texture_2d(1, 0); + gl_state_active_texture(0); + + glViewport(v43[0], v43[1], v43[2], v43[3]); + + texture_params_restore(&tex_params[0], &tex_params[1]); +} diff --git a/src/CRE/task_effect.hpp b/src/CRE/task_effect.hpp index a83ef942..e142eec6 100644 --- a/src/CRE/task_effect.hpp +++ b/src/CRE/task_effect.hpp @@ -14,6 +14,7 @@ #include "frame_rate_control.hpp" #include "render_texture.hpp" #include "stage.hpp" +#include "stage_param.hpp" #include "task.hpp" enum TaskEffectType { @@ -361,19 +362,12 @@ public: virtual void Reset() override; }; -struct color4u8 { - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; -}; - struct struc_101 { int32_t ripple_uniform; int32_t ripple_emit_uniform; int32_t count; vec3* vertex; - color4u8* color; + vec4u8* color; float_t size; int32_t field_24; }; @@ -381,21 +375,36 @@ struct struc_101 { struct ripple_emit_draw_data { struc_101 data; vec3 vertex[16]; - color4u8 color[16]; + vec4u8 color[16]; + + ripple_emit_draw_data(); }; struct struc_192 { - int32_t field_0; - vec3 field_4; + int32_t index; + vec3 trans; + + struc_192(); }; struct struc_207 { struc_192 field_0[18]; + + struc_207(); +}; + +struct ripple_emit_params { + float_t wake_attn; + float_t speed; + float_t field_8; + float_t field_C; + + ripple_emit_params(); }; struct ripple_emit { float_t delta_frame; - int8_t field_4; + bool update; int32_t rain_ripple_num; float_t rain_ripple_min_value; float_t rain_ripple_max_value; @@ -409,7 +418,7 @@ struct ripple_emit { int32_t field_30; float_t rob_emitter_size; size_t emitter_num; - vec3* emitter_list; + const vec3* emitter_list; float_t emitter_size; int32_t field_4C; ripple_emit_draw_data field_50; @@ -420,15 +429,34 @@ struct ripple_emit { struc_207 field_4F4[6]; int32_t field_BB4; render_texture field_BB8; - int32_t field_BE8; + int32_t counter; int8_t field_BEC; - float_t wake_attn; - float_t speed; - float_t field_BF8; - float_t field_BFC; - int8_t field_C00; + ripple_emit_params params; + bool stage_set; int32_t current_stage_index; std::vector stage_indices; + + ripple_emit(); + ~ripple_emit(); + + void add_draw_ripple_emit(struc_101* data); + void clear_tex(); + void ctrl(); + void dest(); + void disp(); + void draw(); + void reset(); + void set_stage_index(int32_t stage_index); + void set_stage_indices(std::vector& stage_indices); + void set_stage_param(stage_param_ripple* ripple); + + static void draw_static(void* data); + + void sub_1403584A0(render_texture* rt); + void sub_140358690(); + void sub_1403587C0(const vec3 a2, const vec3 a3, float_t a4, struc_101& a5, struc_101& a6); + void sub_14035AAE0(); + void sub_14035AED0(); }; struct TaskEffectRipple : public TaskEffect { @@ -541,7 +569,7 @@ struct water_particle { int32_t tex_id; bool blink; std::vector field_48; - std::vector field_60; + std::vector field_60; struc_101 field_78; float_t ripple_emission; }; diff --git a/src/CRE/texture.cpp b/src/CRE/texture.cpp index c684e70f..368f6550 100644 --- a/src/CRE/texture.cpp +++ b/src/CRE/texture.cpp @@ -203,6 +203,50 @@ void texture_set_params(GLenum target, int32_t max_mipmap_level, bool use_high_a glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy); } +void texture_params_get(GLuint tex_0, texture_param* tex_0_param, + GLuint tex_1, texture_param* tex_1_param, GLuint tex_2, texture_param* tex_2_param) { + gl_state_disable_depth_test(); + if (tex_0_param) { + tex_0_param->width = 0; + tex_0_param->height = 0; + if (tex_0) { + gl_state_bind_texture_2d(tex_0); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_0_param->width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_0_param->height); + } + } + + if (tex_1_param) { + tex_1_param->width = 0; + tex_1_param->height = 0; + if (tex_1) { + gl_state_bind_texture_2d(tex_1); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_1_param->width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_1_param->height); + } + } + + if (tex_2_param) { + tex_2_param->width = 0; + tex_2_param->height = 0; + if (tex_2) { + gl_state_bind_texture_2d(tex_2); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_2_param->width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_2_param->height); + } + } + gl_state_bind_texture_2d(0); + + if (tex_0_param) + glViewport(0, 0, tex_0_param->width, tex_0_param->height); +} + +void texture_params_restore(texture_param* tex_0_param, + texture_param* tex_1_param, texture_param* tex_2_param) { + for (int32_t i = 0; i < 4; i++) + gl_state_active_bind_texture_2d(i, 0); +} + bool texture_txp_set_load(txp_set* t, texture*** texs, uint32_t* ids) { if (!t || !texs || !ids) return false; diff --git a/src/CRE/texture.hpp b/src/CRE/texture.hpp index 49c9388d..60f524ce 100644 --- a/src/CRE/texture.hpp +++ b/src/CRE/texture.hpp @@ -72,6 +72,11 @@ struct texture { uint32_t get_width_align_mip_level(uint8_t mip_level = 0); }; +struct texture_param { + GLint width; + GLint height; +}; + extern texture* texture_init(texture_id id); extern void texture_apply_color_tone(texture* chg_tex, texture* org_tex, const color_tone* col_tone); @@ -87,6 +92,11 @@ extern void texture_array_free(texture** arr); extern void texture_set_params(GLenum target, int32_t max_mipmap_level, bool use_high_anisotropy); +extern void texture_params_get(GLuint tex_0 = 0, texture_param* tex_0_param = 0, + GLuint tex_1 = 0, texture_param* tex_1_param = 0, GLuint tex_2 = 0, texture_param* tex_2_param = 0); +extern void texture_params_restore(texture_param* tex_0_param = 0, + texture_param* tex_1_param = 0, texture_param* tex_2_param = 0); + extern bool texture_txp_set_load(txp_set* t, texture*** texs, uint32_t* ids); extern bool texture_txp_set_load(txp_set* t, texture*** texs, texture_id* ids); diff --git a/src/KKdLib/stage_param/ripple.cpp b/src/KKdLib/stage_param/ripple.cpp index 58db265d..ed909625 100644 --- a/src/KKdLib/stage_param/ripple.cpp +++ b/src/KKdLib/stage_param/ripple.cpp @@ -158,9 +158,9 @@ static void stage_param_ripple_read_inner(stage_param_ripple* ripple, stream& s) ripple->ripple_tex_name.assign(buf + 16); } - else if (!str_utils_compare_length(buf, sizeof(buf), "use_float_ripplemap", 4)) { + else if (!str_utils_compare_length(buf, sizeof(buf), "use_float_ripplemap", 19)) { int32_t use_float_ripplemap = 0; - if (buf[4] != ' ' || sscanf_s(buf + 5, "%d", &use_float_ripplemap) != 1) + if (buf[19] != ' ' || sscanf_s(buf + 20, "%d", &use_float_ripplemap) != 1) goto End; ripple->use_float_ripplemap = !!use_float_ripplemap;