diff --git a/src/CRE/Glitter/render_scene.cpp b/src/CRE/Glitter/render_scene.cpp index 31a77c80..f6fcec36 100644 --- a/src/CRE/Glitter/render_scene.cpp +++ b/src/CRE/Glitter/render_scene.cpp @@ -2240,6 +2240,7 @@ namespace Glitter { if (local) disp_manager.object_culling = false; disp_manager.set_texture_pattern(0, 0); + disp_manager.set_obj_flags((mdl::ObjFlags)0); RenderElement* elem = rend_group->elements; size_t disp = 0; @@ -2299,14 +2300,13 @@ namespace Glitter { mat4_mul(&mat, &rctx_ptr->camera->inv_view, &mat); elem->mat_draw = mat; - if (disp_manager.entry_obj_by_object_info( - mat, object_info, &elem->color, 0, local)) + if (local + ? disp_manager.entry_obj_by_object_info_local(mat, object_info, &elem->color) + : disp_manager.entry_obj_by_object_info(mat, object_info, &elem->color)) disp++; - - disp_manager.set_texture_transform(0, 0); } } - disp_manager.set_texture_pattern(0, 0); + disp_manager.set_texture_transform(0, 0); rend_group->disp = disp; if (local) disp_manager.object_culling = object_culling; diff --git a/src/CRE/mdl/disp_manager.cpp b/src/CRE/mdl/disp_manager.cpp index 2305944f..ad86081e 100644 --- a/src/CRE/mdl/disp_manager.cpp +++ b/src/CRE/mdl/disp_manager.cpp @@ -1973,6 +1973,86 @@ namespace mdl { } } + void DispManager::calc_obj_radius(const mat4* view, ObjTypeLocal type) { + for (ObjData*& i : obj_local[type]) { + vec3 center = 0.0f; + bool v50 = false; + switch (i->kind) { + case OBJ_KIND_NORMAL: { + mat4 mat = i->mat; + if (i->args.sub_mesh.mesh->attrib.m.billboard) + model_mat_face_camera_view(view, &mat, &mat); + else if (i->args.sub_mesh.mesh->attrib.m.billboard_y_axis) + model_mat_face_camera_position(view, &mat, &mat); + + get_obj_center(mat, &i->args.sub_mesh, center); + + v50 = !!i->args.sub_mesh.material->material.attrib.m.flag_30; + i->radius = i->args.sub_mesh.mesh->bounding_sphere.radius; + } break; + case OBJ_KIND_TRANSLUCENT: + vec3 center_sum = 0.0f; + for (int32_t j = 0; j < i->args.translucent.count; j++) { + vec3 _center = 0.0f; + get_obj_center(i->mat, i->args.translucent.sub_mesh[j], _center); + if (i->args.translucent.sub_mesh[j]->material->material.attrib.m.flag_30) { + v50 = true; + break; + } + + center_sum += _center; + } + + if (!v50) + center = center_sum * (1.0f / (float_t)i->args.translucent.count); + break; + } + + mat4_transform_point(view, ¢er, ¢er); + i->view_z = center.z; + } + } + + void DispManager::calc_obj_radius(const mat4* view, ObjTypeReflect type) { + for (ObjData*& i : obj_reflect[type]) { + vec3 center = 0.0f; + bool v50 = false; + switch (i->kind) { + case OBJ_KIND_NORMAL: { + mat4 mat = i->mat; + if (i->args.sub_mesh.mesh->attrib.m.billboard) + model_mat_face_camera_view(view, &mat, &mat); + else if (i->args.sub_mesh.mesh->attrib.m.billboard_y_axis) + model_mat_face_camera_position(view, &mat, &mat); + + get_obj_center(mat, &i->args.sub_mesh, center); + + v50 = !!i->args.sub_mesh.material->material.attrib.m.flag_30; + i->radius = i->args.sub_mesh.mesh->bounding_sphere.radius; + } break; + case OBJ_KIND_TRANSLUCENT: + vec3 center_sum = 0.0f; + for (int32_t j = 0; j < i->args.translucent.count; j++) { + vec3 _center = 0.0f; + get_obj_center(i->mat, i->args.translucent.sub_mesh[j], _center); + if (i->args.translucent.sub_mesh[j]->material->material.attrib.m.flag_30) { + v50 = true; + break; + } + + center_sum += _center; + } + + if (!v50) + center = center_sum * (1.0f / (float_t)i->args.translucent.count); + break; + } + + mat4_transform_point(view, ¢er, ¢er); + i->view_z = center.z; + } + } + void DispManager::check_index_buffer(GLuint buffer) { for (DispManager::vertex_array& i : vertex_array_cache) if (i.alive_time > 0 && i.index_buffer == buffer) @@ -2027,7 +2107,6 @@ namespace mdl { switch (type) { case OBJ_TYPE_TRANSLUCENT: case OBJ_TYPE_TRANSLUCENT_SORT_BY_RADIUS: - case OBJ_TYPE_TRANSLUCENT_LOCAL: if (depth_mask) func = draw_sub_mesh_translucent; else @@ -2038,7 +2117,6 @@ namespace mdl { alpha_threshold = 0.0f; break; case OBJ_TYPE_TRANSPARENT: - case OBJ_TYPE_TRANSPARENT_LOCAL: alpha_test = 1; min_alpha = 0.1f; alpha_threshold = 0.5f; @@ -2145,7 +2223,6 @@ namespace mdl { case OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_1: case OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2: case OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_3: - case OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2_LOCAL: alpha_test = 1; min_alpha = 0.1f; alpha_threshold = 0.5f; @@ -2153,7 +2230,6 @@ namespace mdl { case OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_1: case OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2: case OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_3: - case OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2_LOCAL: gl_state_set_depth_mask(GL_FALSE); alpha_test = 1; @@ -2163,18 +2239,6 @@ namespace mdl { case OBJ_TYPE_USER: func = draw_sub_mesh_translucent; break; - case OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS: - if (depth_mask) - func = draw_sub_mesh_translucent; - else - gl_state_set_depth_mask(GL_FALSE); - - alpha_test = 1; - min_alpha = 0.0f; - alpha_threshold = 0.0f; - - gl_state_set_cull_face_mode(GL_FRONT); - break; } rctx->set_batch_alpha_threshold(alpha_threshold); rctx->set_batch_min_alpha(min_alpha); @@ -2262,8 +2326,137 @@ namespace mdl { case OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_3: gl_state_set_depth_mask(GL_TRUE); break; + } + + uniform_value_reset(); + gl_state_bind_vertex_array(0); + 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(mdl::ObjTypeLocal type, int32_t depth_mask, bool reflect_texture_mask) { + if (type < 0 || type >= OBJ_TYPE_LOCAL_MAX || get_obj_count(type) < 1) + return; + + render_context* rctx = rctx_ptr; + + int32_t alpha_test = 0; + float_t min_alpha = 1.0f; + float_t alpha_threshold = 0.0f; + void(*func)(render_context * rctx, const ObjSubMeshArgs * args) = draw_sub_mesh_default; + + for (int32_t i = 0; i < 5; i++) + gl_state_active_bind_texture_2d(i, rctx->empty_texture_2d->glid); + gl_state_active_bind_texture_cube_map(5, rctx->empty_texture_cube_map->glid); + gl_state_active_texture(0); + gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + uniform_value_reset(); + gl_state_get(); + + switch (type) { + case OBJ_TYPE_LOCAL_TRANSLUCENT: + if (depth_mask) + func = draw_sub_mesh_translucent; + else + gl_state_set_depth_mask(GL_FALSE); + + alpha_test = 1; + min_alpha = 0.0f; + alpha_threshold = 0.0f; + break; + case OBJ_TYPE_LOCAL_TRANSPARENT: + alpha_test = 1; + min_alpha = 0.1f; + alpha_threshold = 0.5f; + break; + } + rctx->set_batch_alpha_threshold(alpha_threshold); + rctx->set_batch_min_alpha(min_alpha); + uniform_value[U_ALPHA_TEST] = alpha_test; + + for (ObjData*& i : obj_local[type]) { + switch (i->kind) { + case OBJ_KIND_NORMAL: { + draw_sub_mesh(rctx, &i->args.sub_mesh, &i->mat, func); + } break; + case OBJ_KIND_TRANSLUCENT: { + for (int32_t j = 0; j < i->args.translucent.count; j++) + draw_sub_mesh(rctx, i->args.translucent.sub_mesh[j], &i->mat, func); + } break; + } + } + + switch (type) { + case OBJ_TYPE_LOCAL_TRANSLUCENT: + if (!depth_mask) + gl_state_set_depth_mask(GL_TRUE); + break; + } + + uniform_value_reset(); + gl_state_bind_vertex_array(0); + 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(mdl::ObjTypeReflect type, int32_t depth_mask, bool reflect_texture_mask) { + if (type < 0 || type >= OBJ_TYPE_REFLECT_MAX || get_obj_count(type) < 1) + return; + + render_context* rctx = rctx_ptr; + + int32_t alpha_test = 0; + float_t min_alpha = 1.0f; + float_t alpha_threshold = 0.0f; + bool reflect = uniform_value[U_REFLECT] == 1; + void(*func)(render_context * rctx, const ObjSubMeshArgs * args) = draw_sub_mesh_default; + + for (int32_t i = 0; i < 5; i++) + gl_state_active_bind_texture_2d(i, rctx->empty_texture_2d->glid); + gl_state_active_bind_texture_cube_map(5, rctx->empty_texture_cube_map->glid); + gl_state_active_texture(0); + gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + uniform_value_reset(); + gl_state_get(); + + switch (type) { case OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS: - gl_state_set_cull_face_mode(GL_BACK); + if (depth_mask) + func = draw_sub_mesh_translucent; + else + gl_state_set_depth_mask(GL_FALSE); + + alpha_test = 1; + min_alpha = 0.0f; + alpha_threshold = 0.0f; + + gl_state_set_cull_face_mode(GL_FRONT); + break; + } + rctx->set_batch_alpha_threshold(alpha_threshold); + rctx->set_batch_min_alpha(min_alpha); + uniform_value[U_ALPHA_TEST] = alpha_test; + + for (ObjData*& i : obj_reflect[type]) { + switch (i->kind) { + case OBJ_KIND_NORMAL: { + draw_sub_mesh(rctx, &i->args.sub_mesh, &i->mat, func); + } break; + case OBJ_KIND_TRANSLUCENT: { + for (int32_t j = 0; j < i->args.translucent.count; j++) + draw_sub_mesh(rctx, i->args.translucent.sub_mesh[j], &i->mat, func); + } break; + } + } + + switch (type) { + case OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS: + if (!depth_mask) + gl_state_set_cull_face_mode(GL_BACK); break; } @@ -2309,6 +2502,14 @@ namespace mdl { obj[type].push_back(data); } + void DispManager::entry_list(ObjTypeLocal type, ObjData* data) { + obj_local[type].push_back(data); + } + + void DispManager::entry_list(ObjTypeReflect type, ObjData* data) { + obj_reflect[type].push_back(data); + } + static int32_t obj_bounding_sphere_check_visibility_default(const vec3& center, camera* cam, float_t radius) { vec3 _center; mat4_transform_point(&cam->view, ¢er, &_center); @@ -2405,7 +2606,7 @@ namespace mdl { obj_mesh_index_buffer* obj_index_buf, const std::vector* textures, const vec4* blend_color, const mat4* bone_mat, const ::obj* obj_morph, obj_mesh_vertex_buffer* obj_morph_vert_buf, int32_t instances_count, const mat4* instances_mat, - draw_func func, const ObjSubMeshArgs* func_data, bool enable_bone_mat, bool local) { + draw_func func, const ObjSubMeshArgs* func_data, bool enable_bone_mat) { if (!obj_vert_buf || !obj_index_buf) { printf_debug("mdl::DispManager::entry_obj: no vertex or index object buffer to draw;\n"); printf_debug(" Object: %s\n", obj->name); @@ -2414,7 +2615,7 @@ namespace mdl { ::camera* cam = rctx_ptr->camera; - if (!local && object_culling && !instances_count && !bone_mat && (!obj + if ( object_culling && !instances_count && !bone_mat && (!obj || !obj_bounding_sphere_check_visibility( obj->bounding_sphere, &culling, cam, mat))) { culling.culled.objects++; @@ -2433,7 +2634,7 @@ namespace mdl { mesh_morph = &obj_morph->mesh_array[i]; } - if (!local && object_culling && !instances_count && !bone_mat + if (object_culling && !instances_count && !bone_mat && !obj_bounding_sphere_check_visibility( mesh->bounding_sphere, &culling, cam, mat) && (!mesh_morph || !obj_bounding_sphere_check_visibility( @@ -2452,7 +2653,7 @@ namespace mdl { if (sub_mesh->attrib.m.cloth) continue; - if (!local && object_culling && !instances_count && !bone_mat) { + if (object_culling && !instances_count && !bone_mat) { int32_t v32 = obj_bounding_sphere_check_visibility( sub_mesh->bounding_sphere, &culling, cam, mat); if (v32 != 2 || (!mesh->attrib.m.billboard && !mesh->attrib.m.billboard_y_axis)) { @@ -2631,8 +2832,7 @@ namespace mdl { if (obj_flags & mdl::OBJ_ALPHA_ORDER_1) entry_list(OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_1, data); else if (obj_flags & mdl::OBJ_ALPHA_ORDER_2) - entry_list(local ? OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2_LOCAL - : OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2, data); + entry_list(OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2, data); else entry_list(OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_3, data); } @@ -2641,8 +2841,7 @@ namespace mdl { if (obj_flags & mdl::OBJ_ALPHA_ORDER_1) entry_list(OBJ_TYPE_OPAQUE_ALPHA_ORDER_1, data); else if (obj_flags & mdl::OBJ_ALPHA_ORDER_2) - entry_list(local ? OBJ_TYPE_OPAQUE_ALPHA_ORDER_2_LOCAL - : OBJ_TYPE_OPAQUE_ALPHA_ORDER_2, data); + entry_list(OBJ_TYPE_OPAQUE_ALPHA_ORDER_2, data); else entry_list(OBJ_TYPE_OPAQUE_ALPHA_ORDER_3, data); } @@ -2650,8 +2849,7 @@ namespace mdl { if (obj_flags & mdl::OBJ_ALPHA_ORDER_1) entry_list(OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_1, data); else if (obj_flags & mdl::OBJ_ALPHA_ORDER_2) - entry_list(local ? OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2_LOCAL - : OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2, data); + entry_list(OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2, data); else entry_list(OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_3, data); } @@ -2666,9 +2864,7 @@ namespace mdl { || sub_mesh->attrib.m.translucent)) { if (!(obj_flags & mdl::OBJ_NO_TRANSLUCENCY)) { if (!attrib.translucent_priority) - if (local) - entry_list(OBJ_TYPE_TRANSLUCENT_LOCAL, data); - else if (mesh->attrib.m.translucent_sort_by_radius + if (mesh->attrib.m.translucent_sort_by_radius || obj_flags & mdl::OBJ_TRANSLUCENT_SORT_BY_RADIUS) { entry_list(OBJ_TYPE_TRANSLUCENT_SORT_BY_RADIUS, data); } @@ -2687,8 +2883,7 @@ namespace mdl { if (attrib.punch_through) { if (!(obj_flags & mdl::OBJ_NO_TRANSLUCENCY)) - entry_list(local ? OBJ_TYPE_TRANSPARENT_LOCAL - : OBJ_TYPE_TRANSPARENT, data); + entry_list(OBJ_TYPE_TRANSPARENT, data); if (obj_flags & mdl::OBJ_CHARA_REFLECT) entry_list(OBJ_TYPE_REFLECT_CHARA_OPAQUE, data); @@ -2701,8 +2896,7 @@ namespace mdl { } else { if (!(obj_flags & mdl::OBJ_NO_TRANSLUCENCY)) - entry_list(local ? OBJ_TYPE_OPAQUE_LOCAL - : OBJ_TYPE_OPAQUE, data); + entry_list(OBJ_TYPE_OPAQUE, data); if (obj_flags & mdl::OBJ_20) entry_list(OBJ_TYPE_TYPE_6, data); @@ -2762,18 +2956,114 @@ namespace mdl { if (obj_flags & mdl::OBJ_ALPHA_ORDER_1) entry_list(OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_1, data); else if (obj_flags & mdl::OBJ_ALPHA_ORDER_2) - entry_list(local ? OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2_LOCAL - : OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2, data); + entry_list(OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2, data); else if (obj_flags & mdl::OBJ_ALPHA_ORDER_3) entry_list(OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_3, data); else - entry_list(local ? OBJ_TYPE_TRANSLUCENT_LOCAL - : OBJ_TYPE_TRANSLUCENT, data); + entry_list(OBJ_TYPE_TRANSLUCENT, data); } } return true; } + bool DispManager::entry_obj_local(const ::obj* obj, const mat4& mat, obj_mesh_vertex_buffer* obj_vert_buf, + obj_mesh_index_buffer* obj_index_buf, const std::vector* textures, const vec4* blend_color) { + if (!obj_vert_buf || !obj_index_buf) + return false; + + culling.passed.objects++; + + for (int32_t i = 0; i < obj->num_mesh; i++) { + const obj_mesh* mesh = &obj->mesh_array[i]; + + culling.passed.meshes++; + + ObjSubMeshArgs* translucent_priority[40]; + int32_t translucent_priority_count = 0; + + for (int32_t j = 0; j < mesh->num_submesh; j++) { + const obj_sub_mesh* sub_mesh = &mesh->submesh_array[j]; + if (sub_mesh->attrib.m.cloth) + continue; + + culling.passed.sub_meshes++; + + obj_material_data* material = &obj->material_array[sub_mesh->material_index]; + ObjData* data = alloc_obj_data(OBJ_KIND_NORMAL); + if (!data) + continue; + + GLuint index_buffer = 0; + if (obj_index_buf) + index_buffer = obj_index_buf[i].buffer; + + GLuint vertex_buffer = 0; + size_t vertex_buffer_offset = 0; + if (obj_vert_buf) { + vertex_buffer = obj_vert_buf[i].get_buffer(); + vertex_buffer_offset = obj_vert_buf[i].get_offset(); + } + + if (!vertex_buffer || !index_buffer) + continue; + + vec4 _blend_color = 1.0f; + if (blend_color) + _blend_color = *blend_color; + vec4 _emission = material->material.color.emission; + + data->init_sub_mesh(this, mat, obj->bounding_sphere.radius, sub_mesh, mesh, material, textures, + 0, 0, vertex_buffer, vertex_buffer_offset, index_buffer, _blend_color, _emission, + 0, 0, 0, 0, 0, 0); + + const obj_material_attrib_member attrib = material->material.attrib.m; + if (attrib.flag_28 || data->args.sub_mesh.blend_color.w >= 1.0f + && (attrib.punch_through || !(attrib.alpha_texture | attrib.alpha_material)) + && !sub_mesh->attrib.m.translucent) { + if (attrib.punch_through) { + if (!(obj_flags & mdl::OBJ_NO_TRANSLUCENCY)) + entry_list(OBJ_TYPE_LOCAL_TRANSPARENT, data); + } + else { + if (!(obj_flags & mdl::OBJ_NO_TRANSLUCENCY)) + entry_list(OBJ_TYPE_LOCAL_OPAQUE, data); + } + continue; + } + else if (!(obj_flags & mdl::OBJ_NO_TRANSLUCENCY)) { + if (!attrib.translucent_priority) + entry_list(OBJ_TYPE_LOCAL_TRANSLUCENT, data); + else if (translucent_priority_count < 40) + translucent_priority[translucent_priority_count++] = &data->args.sub_mesh; + } + } + + if (!translucent_priority_count) + continue; + + ObjTranslucentArgs translucent_args; + translucent_args.count = 0; + for (int32_t j = 62; j; j--) + for (int32_t k = 0; k < translucent_priority_count; k++) { + ObjSubMeshArgs* sub_mesh = translucent_priority[k]; + if (sub_mesh->material->material.attrib.m.translucent_priority != j) + continue; + + translucent_args.sub_mesh[translucent_args.count] = sub_mesh; + translucent_args.count++; + } + + ObjData* data = alloc_obj_data(OBJ_KIND_TRANSLUCENT); + if (data) { + data->init_translucent(mat, translucent_args); + + entry_list(OBJ_TYPE_TRANSLUCENT, data); + } + } + + return true; + } + void DispManager::entry_obj_by_obj(const mat4& mat, const ::obj* obj, const std::vector* textures, obj_mesh_vertex_buffer* obj_vert_buf, obj_mesh_index_buffer* obj_index_buf, const mat4* bone_mat, float_t alpha) { @@ -2798,7 +3088,7 @@ namespace mdl { bool DispManager::entry_obj_by_object_info(const mat4& mat, object_info obj_info, const vec4* blend_color, const mat4* bone_mat, int32_t instances_count, const mat4* instances_mat, - void(*func)(const ObjSubMeshArgs*), const ObjSubMeshArgs* func_data, bool enable_bone_mat, bool local) { + void(*func)(const ObjSubMeshArgs*), const ObjSubMeshArgs* func_data, bool enable_bone_mat) { if (obj_info.id == -1 && obj_info.set_id == -1) return false; @@ -2819,25 +3109,40 @@ namespace mdl { return entry_obj(obj, mat, obj_vert_buffer, obj_index_buffer, textures, blend_color, bone_mat, obj_morph, obj_morph_vert_buffer, - instances_count, instances_mat, func, func_data, enable_bone_mat, local); + instances_count, instances_mat, func, func_data, enable_bone_mat); + } + + bool DispManager::entry_obj_by_object_info_local(const mat4& mat, object_info obj_info, const vec4* blend_color) { + if (obj_info.id == (uint16_t)-1 && obj_info.set_id == (uint16_t)-1) + return false; + + ::obj* obj = objset_info_storage_get_obj(obj_info); + if (!obj) + return false; + + std::vector* textures = objset_info_storage_get_obj_set_gentex(obj_info.set_id); + obj_mesh_vertex_buffer* obj_vert_buffer = objset_info_storage_get_obj_mesh_vertex_buffer(obj_info); + obj_mesh_index_buffer* obj_index_buffer = objset_info_storage_get_obj_mesh_index_buffer(obj_info); + + return entry_obj_local(obj, mat, obj_vert_buffer, obj_index_buffer, textures, blend_color); } bool DispManager::entry_obj_by_object_info(const mat4& mat, object_info obj_info, float_t alpha, const mat4* bone_mat) { vec4 blend_color = 1.0f; blend_color.w = alpha; - return entry_obj_by_object_info(mat, obj_info, &blend_color, bone_mat, 0, 0, 0, 0, true); + return entry_obj_by_object_info(mat, obj_info, &blend_color, bone_mat, 0, 0, 0, 0, !!bone_mat); } bool DispManager::entry_obj_by_object_info(const mat4& mat, object_info obj_info, - float_t r, float_t g, float_t b, float_t a, const mat4* bone_mat, bool local) { + float_t r, float_t g, float_t b, float_t a, const mat4* bone_mat) { vec4 blend_color = { r, g, b, a }; - return entry_obj_by_object_info(mat, obj_info, &blend_color, bone_mat, 0, 0, 0, 0, true, local); + return entry_obj_by_object_info(mat, obj_info, &blend_color, bone_mat, 0, 0, 0, 0, !!bone_mat); } bool DispManager::entry_obj_by_object_info(const mat4& mat, object_info obj_info, - const vec4* blend_color, const mat4* bone_mat, bool local) { - return entry_obj_by_object_info(mat, obj_info, blend_color, 0, 0, 0, 0, 0, false, local); + const vec4* blend_color, const mat4* bone_mat) { + return entry_obj_by_object_info(mat, obj_info, blend_color, 0, 0, 0, 0, 0, !!bone_mat); } bool DispManager::entry_obj_by_object_info_instanced(object_info obj_info, @@ -2917,19 +3222,31 @@ namespace mdl { } } - void DispManager::entry_obj_etc(const mat4& mat, const EtcObj& etc, bool local) { - ObjData* data = alloc_obj_data(mdl::OBJ_KIND_ETC); + void DispManager::entry_obj_etc(const mat4& mat, const EtcObj& etc) { + ObjData* data = alloc_obj_data(OBJ_KIND_ETC); if (!data) return; data->init_etc(this, mat, etc); if (etc.color.a == 0xFF) { - if (!local && (obj_flags & OBJ_SHADOW)) + if (obj_flags & OBJ_SHADOW) entry_list((mdl::ObjType)(OBJ_TYPE_SHADOW_CHARA + shadow_type), data); - entry_list(local ? OBJ_TYPE_OPAQUE_LOCAL : OBJ_TYPE_OPAQUE, data); + entry_list(OBJ_TYPE_OPAQUE, data); } else - entry_list(local ? OBJ_TYPE_TRANSLUCENT_LOCAL : OBJ_TYPE_TRANSLUCENT, data); + entry_list(OBJ_TYPE_TRANSLUCENT, data); + } + + void DispManager::entry_obj_etc_local(const mat4& mat, const EtcObj& etc) { + ObjData* data = alloc_obj_data(OBJ_KIND_ETC); + if (!data) + return; + + data->init_etc(this, mat, etc); + if (etc.color.a == 0xFF) + entry_list(OBJ_TYPE_LOCAL_OPAQUE, data); + else + entry_list(OBJ_TYPE_LOCAL_TRANSLUCENT, data); } void DispManager::entry_obj_user(const mat4& mat, UserArgsFunc func, void* data, ObjType type) { @@ -3109,6 +3426,14 @@ namespace mdl { return (int32_t)obj[type].size(); } + int32_t DispManager::get_obj_count(ObjTypeLocal type) { + return (int32_t)obj_local[type].size(); + } + + int32_t DispManager::get_obj_count(ObjTypeReflect type) { + return (int32_t)obj_reflect[type].size(); + } + ObjFlags DispManager::get_obj_flags() { return obj_flags; } @@ -3180,6 +3505,58 @@ namespace mdl { } } + void DispManager::obj_sort(const mat4* view, ObjTypeLocal type, int32_t compare_func) { + std::list& list = obj[type]; + if (list.size() < 1) + return; + + calc_obj_radius(view, type); + + switch (compare_func) { + case 0: + list.sort([](const ObjData* left, const ObjData* right) { + return left->view_z > right->view_z; + }); + break; + case 1: + list.sort([](const ObjData* left, const ObjData* right) { + return left->view_z < right->view_z; + }); + break; + case 2: + list.sort([](const ObjData* left, const ObjData* right) { + return left->radius > right->radius; + }); + break; + } + } + + void DispManager::obj_sort(const mat4* view, ObjTypeReflect type, int32_t compare_func) { + std::list& list = obj[type]; + if (list.size() < 1) + return; + + calc_obj_radius(view, type); + + switch (compare_func) { + case 0: + list.sort([](const ObjData* left, const ObjData* right) { + return left->view_z > right->view_z; + }); + break; + case 1: + list.sort([](const ObjData* left, const ObjData* right) { + return left->view_z < right->view_z; + }); + break; + case 2: + list.sort([](const ObjData* left, const ObjData* right) { + return left->radius > right->radius; + }); + break; + } + } + void DispManager::refresh() { culling.passed_prev = culling.passed; culling.culled_prev = culling.culled; @@ -3202,6 +3579,12 @@ namespace mdl { for (std::list& i : obj) i.clear(); + for (std::list& i : obj_local) + i.clear(); + + for (std::list& i : obj_reflect) + i.clear(); + buffer_reset(); } diff --git a/src/CRE/mdl/disp_manager.hpp b/src/CRE/mdl/disp_manager.hpp index b641c199..3e0fbb0d 100644 --- a/src/CRE/mdl/disp_manager.hpp +++ b/src/CRE/mdl/disp_manager.hpp @@ -156,16 +156,21 @@ namespace mdl { OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_3, OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_3, OBJ_TYPE_USER, - OBJ_TYPE_OPAQUE_LOCAL, // X - OBJ_TYPE_TRANSLUCENT_LOCAL, - OBJ_TYPE_TRANSPARENT_LOCAL, - OBJ_TYPE_OPAQUE_ALPHA_ORDER_2_LOCAL, - OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2_LOCAL, - OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2_LOCAL, - OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS, // Reflect OBJ_TYPE_MAX, }; + enum ObjTypeLocal { + OBJ_TYPE_LOCAL_OPAQUE = 0, + OBJ_TYPE_LOCAL_TRANSLUCENT, + OBJ_TYPE_LOCAL_TRANSPARENT, + OBJ_TYPE_LOCAL_MAX + }; + + enum ObjTypeReflect { + OBJ_TYPE_REFLECT_TRANSLUCENT_SORT_BY_RADIUS = 0, + OBJ_TYPE_REFLECT_MAX, + }; + struct DispManager; struct ObjSubMeshArgs; @@ -415,6 +420,8 @@ namespace mdl { int32_t field_8; int32_t field_C; mdl::ObjList obj[mdl::OBJ_TYPE_MAX]; + mdl::ObjList obj_local[mdl::OBJ_TYPE_LOCAL_MAX]; + mdl::ObjList obj_reflect[mdl::OBJ_TYPE_REFLECT_MAX]; mdl::CullingCheck culling; int32_t put_index; bool show_alpha_center; @@ -450,18 +457,26 @@ namespace mdl { ObjData* alloc_obj_data(ObjKind kind); mat4* alloc_mat4_array(int32_t count); void buffer_reset(); - void calc_obj_radius(const mat4* view, mdl::ObjType type); + void calc_obj_radius(const mat4* view, ObjType type); + void calc_obj_radius(const mat4* view, ObjTypeLocal type); + void calc_obj_radius(const mat4* view, ObjTypeReflect type); void check_index_buffer(GLuint buffer); void check_vertex_arrays(); void check_vertex_buffer(GLuint buffer); - void draw(mdl::ObjType type, int32_t depth_mask = 0, bool reflect_texture_mask = true, int32_t alpha = -1); + void draw(ObjType type, int32_t depth_mask = 0, bool reflect_texture_mask = true, int32_t alpha = -1); + void draw(ObjTypeLocal type, int32_t depth_mask = 0, bool reflect_texture_mask = true); + void draw(ObjTypeReflect type, int32_t depth_mask = 0, bool reflect_texture_mask = true); /*void draw_show_vector(mdl::ObjType type, int32_t show_vector);*/ void entry_list(ObjType type, ObjData* data); + void entry_list(ObjTypeLocal type, ObjData* data); + void entry_list(ObjTypeReflect type, ObjData* data); bool entry_obj(const ::obj* obj, const mat4& mat, obj_mesh_vertex_buffer* obj_vert_buf, obj_mesh_index_buffer* obj_index_buf, const std::vector* textures, const vec4* blend_color, const mat4* bone_mat, const ::obj* obj_morph, obj_mesh_vertex_buffer* obj_morph_vert_buf, int32_t instances_count, const mat4* instances_mat, - draw_func func, const ObjSubMeshArgs* func_data, bool enable_bone_mat, bool local = false); + draw_func func, const ObjSubMeshArgs* func_data, bool enable_bone_mat); + bool entry_obj_local(const ::obj* obj, const mat4& mat, obj_mesh_vertex_buffer* obj_vert_buf, + obj_mesh_index_buffer* obj_index_buf, const std::vector* textures, const vec4* blend_color); void entry_obj_by_obj(const mat4& mat, const ::obj* obj, const std::vector* textures, obj_mesh_vertex_buffer* obj_vert_buf, obj_mesh_index_buffer* obj_index_buf, const mat4* bone_mat, float_t alpha); @@ -469,13 +484,13 @@ namespace mdl { bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, const mat4* bone_mat); bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, const vec4* blend_color, const mat4* bone_mat, int32_t instances_count, const mat4* instances_mat, - void(*func)(const mdl::ObjSubMeshArgs*), const ObjSubMeshArgs* func_data, - bool enable_bone_mat, bool local = false); + void(*func)(const mdl::ObjSubMeshArgs*), const ObjSubMeshArgs* func_data, bool enable_bone_mat); + bool entry_obj_by_object_info_local(const mat4& mat, object_info obj_info, const vec4* blend_color); bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, float_t alpha, const mat4* bone_mat = 0); bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, - float_t r, float_t g, float_t b, float_t a, const mat4* bone_mat = 0, bool local = false); + float_t r, float_t g, float_t b, float_t a, const mat4* bone_mat = 0); bool entry_obj_by_object_info(const mat4& mat, object_info obj_info, - const vec4* blend_color, const mat4* bone_mat = 0, bool local = false); + const vec4* blend_color, const mat4* bone_mat = 0); bool entry_obj_by_object_info_instanced(object_info obj_info, const std::vector& instances, float_t alpha); bool entry_obj_by_object_info_instanced(object_info obj_info, @@ -484,7 +499,8 @@ namespace mdl { const std::vector* texture_pattern, const texture_data_struct* texture_data, float_t alpha, const mat4* matrices, const mat4* ex_data_matrices, const mat4* mat, const mat4& global_mat); - void entry_obj_etc(const mat4& mat, const EtcObj& etc, bool local = false); + void entry_obj_etc(const mat4& mat, const EtcObj& etc); + void entry_obj_etc_local(const mat4& mat, const EtcObj& etc); void entry_obj_user(const mat4& mat, UserArgsFunc func, void* data, ObjType type); GLuint get_vertex_array(const ObjSubMeshArgs* args); GLuint get_vertex_array(const EtcObj* etc); @@ -493,6 +509,8 @@ namespace mdl { void get_morph(object_info& object, float_t& weight); void get_obj_center(const mat4& mat, const mdl::ObjSubMeshArgs* args, vec3& center); int32_t get_obj_count(ObjType type); + int32_t get_obj_count(ObjTypeLocal type); + int32_t get_obj_count(ObjTypeReflect type); ObjFlags get_obj_flags(); shadow_type_enum get_shadow_type(); void get_texture_color_coeff(vec4& value); @@ -503,6 +521,8 @@ namespace mdl { void get_texture_transform(int32_t& count, texture_transform_struct*& value); float_t get_wet_param(); void obj_sort(const mat4* view, ObjType type, int32_t compare_func, bool a3 = false); + void obj_sort(const mat4* view, ObjTypeLocal type, int32_t compare_func); + void obj_sort(const mat4* view, ObjTypeReflect type, int32_t compare_func); void refresh(); void set_chara_color(bool value = false); void set_culling_func(bool(*func)(const obj_bounding_sphere*, const mat4*) = 0); diff --git a/src/CRE/render_manager.cpp b/src/CRE/render_manager.cpp index 25f3f71c..e312317b 100644 --- a/src/CRE/render_manager.cpp +++ b/src/CRE/render_manager.cpp @@ -1083,27 +1083,22 @@ namespace rndr { gl_state_begin_event("local"); if (alpha_z_sort) - rctx->disp_manager->obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_TRANSLUCENT_LOCAL, 1); + rctx->disp_manager->obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_LOCAL_TRANSLUCENT, 1); if (opaque_z_sort) - rctx->disp_manager->obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_OPAQUE_LOCAL, 0); + rctx->disp_manager->obj_sort(&rctx->view_mat, mdl::OBJ_TYPE_LOCAL_OPAQUE, 0); camera* cam = rctx->camera; float_t fov = cam->get_fov(); cam->set_fov(32.2673416137695f); draw_pass_set_camera(); - rctx->disp_manager->draw(mdl::OBJ_TYPE_OPAQUE_LOCAL); - rctx->disp_manager->draw(mdl::OBJ_TYPE_TRANSPARENT_LOCAL); + rctx->disp_manager->draw(mdl::OBJ_TYPE_LOCAL_OPAQUE); + rctx->disp_manager->draw(mdl::OBJ_TYPE_LOCAL_TRANSPARENT); gl_state_enable_blend(); - rctx->disp_manager->draw(mdl::OBJ_TYPE_TRANSLUCENT_LOCAL); + rctx->disp_manager->draw(mdl::OBJ_TYPE_LOCAL_TRANSLUCENT); gl_state_disable_blend(); - draw_pass_3d_translucent(rctx, - mdl::OBJ_TYPE_OPAQUE_ALPHA_ORDER_2_LOCAL, - mdl::OBJ_TYPE_TRANSPARENT_ALPHA_ORDER_2_LOCAL, - mdl::OBJ_TYPE_TRANSLUCENT_ALPHA_ORDER_2_LOCAL); - gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); Glitter::glt_particle_manager->DispScenes(Glitter::DISP_LOCAL); gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); diff --git a/src/ReDIVA/data_edit/glitter_editor.cpp b/src/ReDIVA/data_edit/glitter_editor.cpp index e88ce62f..b6b44bbd 100644 --- a/src/ReDIVA/data_edit/glitter_editor.cpp +++ b/src/ReDIVA/data_edit/glitter_editor.cpp @@ -1947,7 +1947,10 @@ static void glitter_editor_draw_emitter_type_emitter_inst_f2( etc.constant = true; etc.data.cube.size = vec3::max(emit_inst->data.box.size * scale, 0.1f); etc.data.cube.wire = false; - rctx_ptr->disp_manager->entry_obj_etc(mat, etc, local); + if (local) + rctx_ptr->disp_manager->entry_obj_etc_local(mat, etc); + else + rctx_ptr->disp_manager->entry_obj_etc(mat, etc); } break; case Glitter::EMITTER_CYLINDER: { mdl::EtcObj etc(mdl::ETC_OBJ_CYLINDER); @@ -1958,7 +1961,10 @@ static void glitter_editor_draw_emitter_type_emitter_inst_f2( etc.data.cylinder.slices = 16; etc.data.cylinder.stacks = 1; etc.data.cylinder.wire = false; - rctx_ptr->disp_manager->entry_obj_etc(mat, etc, local); + if (local) + rctx_ptr->disp_manager->entry_obj_etc_local(mat, etc); + else + rctx_ptr->disp_manager->entry_obj_etc(mat, etc); } break; case Glitter::EMITTER_SPHERE: { mdl::EtcObj etc(mdl::ETC_OBJ_SPHERE); @@ -1968,7 +1974,10 @@ static void glitter_editor_draw_emitter_type_emitter_inst_f2( etc.data.sphere.slices = 16; etc.data.sphere.stacks = 16; etc.data.sphere.wire = false; - rctx_ptr->disp_manager->entry_obj_etc(mat, etc, local); + if (local) + rctx_ptr->disp_manager->entry_obj_etc_local(mat, etc); + else + rctx_ptr->disp_manager->entry_obj_etc(mat, etc); } break; case Glitter::EMITTER_POLYGON: { mdl::EtcObj etc(mdl::ETC_OBJ_LINE); @@ -1976,7 +1985,10 @@ static void glitter_editor_draw_emitter_type_emitter_inst_f2( etc.constant = true; etc.data.line.pos[0] = vec3(-emit_inst->data.polygon.size * scale.x * 0.5f, 0.0f, 0.0f); etc.data.line.pos[1] = vec3(emit_inst->data.polygon.size * scale.x * 0.5f, 0.0f, 0.0f); - rctx_ptr->disp_manager->entry_obj_etc(mat, etc, local); + if (local) + rctx_ptr->disp_manager->entry_obj_etc_local(mat, etc); + else + rctx_ptr->disp_manager->entry_obj_etc(mat, etc); } break; } } @@ -2013,7 +2025,10 @@ static void glitter_editor_draw_emitter_type_emitter_inst_x( etc.constant = true; etc.data.cube.size = vec3::max(emit_inst->data.box.size * scale, 0.1f); etc.data.cube.wire = false; - rctx_ptr->disp_manager->entry_obj_etc(mat, etc, local); + if (local) + rctx_ptr->disp_manager->entry_obj_etc_local(mat, etc); + else + rctx_ptr->disp_manager->entry_obj_etc(mat, etc); } break; case Glitter::EMITTER_CYLINDER: { mdl::EtcObj etc(mdl::ETC_OBJ_CYLINDER); @@ -2024,7 +2039,10 @@ static void glitter_editor_draw_emitter_type_emitter_inst_x( etc.data.cylinder.slices = 16; etc.data.cylinder.stacks = 1; etc.data.cylinder.wire = false; - rctx_ptr->disp_manager->entry_obj_etc(mat, etc, local); + if (local) + rctx_ptr->disp_manager->entry_obj_etc_local(mat, etc); + else + rctx_ptr->disp_manager->entry_obj_etc(mat, etc); } break; case Glitter::EMITTER_SPHERE: { mdl::EtcObj etc(mdl::ETC_OBJ_SPHERE); @@ -2034,7 +2052,10 @@ static void glitter_editor_draw_emitter_type_emitter_inst_x( etc.data.sphere.slices = 16; etc.data.sphere.stacks = 16; etc.data.sphere.wire = false; - rctx_ptr->disp_manager->entry_obj_etc(mat, etc, local); + if (local) + rctx_ptr->disp_manager->entry_obj_etc_local(mat, etc); + else + rctx_ptr->disp_manager->entry_obj_etc(mat, etc); } break; case Glitter::EMITTER_POLYGON: { mdl::EtcObj etc(mdl::ETC_OBJ_CYLINDER); @@ -2045,7 +2066,10 @@ static void glitter_editor_draw_emitter_type_emitter_inst_x( etc.data.cylinder.slices = 16; etc.data.cylinder.stacks = 0; etc.data.cylinder.wire = false; - rctx_ptr->disp_manager->entry_obj_etc(mat, etc, local); + if (local) + rctx_ptr->disp_manager->entry_obj_etc_local(mat, etc); + else + rctx_ptr->disp_manager->entry_obj_etc(mat, etc); } break; } }