ReignEngine: Improve z-sorting

This fixes billboard rendering issue in some dungeons.

* For polygon models, use its AABB's center coordinates.
* Consider the camera angle, i.e. sort by view-space Z-coordinate
  instead of world-space Z-coordinate.
This commit is contained in:
kichikuou
2022-12-17 10:59:16 +09:00
parent 6cc0bd7cb4
commit 3ef252c68b
2 changed files with 30 additions and 5 deletions
+1
View File
@@ -165,6 +165,7 @@ struct RE_instance {
mat4 local_transform;
mat3 normal_transform;
mat4 *bone_transforms; // model->nr_bones elements
float z_from_camera;
};
struct RE_plugin *RE_plugin_new(void);
+29 -5
View File
@@ -773,11 +773,37 @@ static int cmp_instances_by_z(const void *lhs, const void *rhs)
{
struct RE_instance *l = *(struct RE_instance **)lhs;
struct RE_instance *r = *(struct RE_instance **)rhs;
float lz = l ? l->pos[2] : FLT_MAX;
float rz = r ? r->pos[2] : FLT_MAX;
float lz = l ? l->z_from_camera : FLT_MAX;
float rz = r ? r->z_from_camera : FLT_MAX;
return (lz > rz) - (lz < rz); // ascending order.
}
static struct RE_instance **sort_instances(struct RE_plugin *plugin, mat4 view_transform)
{
struct RE_instance **instances = xmalloc(plugin->nr_instances * sizeof(struct RE_instance *));
memcpy(instances, plugin->instances, plugin->nr_instances * sizeof(struct RE_instance *));
for (int i = 0; i < plugin->nr_instances; i++) {
struct RE_instance *inst = instances[i];
if (!inst)
continue;
vec3 center;
if (inst->model) {
glm_aabb_center(inst->model->aabb, center);
if (inst->local_transform_needs_update)
RE_instance_update_local_transform(inst);
glm_mat4_mulv3(inst->local_transform, center, 1.0, center);
} else {
glm_vec3_copy(inst->pos, center);
}
glm_mat4_mulv3(view_transform, center, 1.0f, center);
inst->z_from_camera = center[2];
}
qsort(instances, plugin->nr_instances, sizeof(struct RE_instance *), cmp_instances_by_z);
return instances;
}
void RE_render(struct sact_sprite *sp)
{
struct RE_plugin *plugin = (struct RE_plugin *)sp->plugin;
@@ -849,9 +875,7 @@ void RE_render(struct sact_sprite *sp)
setup_lights(plugin);
// Sort instances by z-order.
struct RE_instance **sorted_instances = xmalloc(plugin->nr_instances * sizeof(struct RE_instance *));
memcpy(sorted_instances, plugin->instances, plugin->nr_instances * sizeof(struct RE_instance *));
qsort(sorted_instances, plugin->nr_instances, sizeof(struct RE_instance *), cmp_instances_by_z);
struct RE_instance **sorted_instances = sort_instances(plugin, view_transform);
// Render opaque instances, from nearest to farthest.
for (int i = plugin->nr_instances - 1; i >= 0; i--) {