mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
5b04be2fa0
This adds hfrag, but with a few remaining issues: - The textures aren't animated. Instead, it just uses one texture. - The texture filtering isn't as good as at it could be. I also cleaned up a few issues with the background renderers: - Cleaned up some stuff that is common to hfrag, tie, tfrag, shrub - Moved time-of-day color packing stuff to FR3 creation, rather than at level load. This appears to reduce the frame time spikes when a level is first drawn by about 5 or 6 ms in big levels. - Cleaned up the x86 specific stuff used in time of day. Now there's only one place where we have an `ifdef`, rather than spreading it all over the rendering code.
85 lines
2.6 KiB
C++
85 lines
2.6 KiB
C++
#include "extract_common.h"
|
|
|
|
#include <cstddef>
|
|
|
|
namespace decompiler {
|
|
u32 clean_up_vertex_indices(std::vector<u32>& idx) {
|
|
std::vector<u32> fixed;
|
|
u32 num_tris = 0;
|
|
|
|
bool looking_for_start = true;
|
|
size_t i_of_start;
|
|
for (size_t i = 0; i < idx.size(); i++) {
|
|
if (looking_for_start) {
|
|
if (idx[i] != UINT32_MAX) {
|
|
looking_for_start = false;
|
|
i_of_start = i;
|
|
}
|
|
} else {
|
|
if (idx[i] == UINT32_MAX) {
|
|
looking_for_start = true;
|
|
size_t num_verts = i - i_of_start;
|
|
if (num_verts >= 3) {
|
|
if (!fixed.empty()) {
|
|
fixed.push_back(UINT32_MAX);
|
|
}
|
|
fixed.insert(fixed.end(), idx.begin() + i_of_start, idx.begin() + i);
|
|
num_tris += (num_verts - 2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!looking_for_start) {
|
|
size_t num_verts = idx.size() - i_of_start;
|
|
if (num_verts >= 3) {
|
|
if (!fixed.empty()) {
|
|
fixed.push_back(UINT32_MAX);
|
|
}
|
|
fixed.insert(fixed.end(), idx.begin() + i_of_start, idx.begin() + idx.size());
|
|
num_tris += (num_verts - 2);
|
|
}
|
|
}
|
|
|
|
idx = std::move(fixed);
|
|
|
|
return num_tris;
|
|
}
|
|
|
|
// we want to absolutely minimize the number of time we have to "cross lanes" in AVX (meaning X
|
|
// component of one vector interacts with Y component of another). We can make this a lot better by
|
|
// taking groups of 4 time of day colors (each containing 8x RGBAs) and rearranging them with this
|
|
// pattern. We want to compute:
|
|
// [rgba][0][0] * weights[0] + [rgba][0][1] * weights[1] + [rgba][0][2]... + rgba[0][7] * weights[7]
|
|
// RGBA is already a vector of 4 components, but with AVX we have vectors with 32 bytes which fit
|
|
// 16 colors in them.
|
|
|
|
// This makes each vector have:
|
|
// colors0 = [rgba][0][0], [rgba][1][0], [rgba][2][0], [rgba][3][0]
|
|
// colors1 = [rgba][0][1], [rgba][1][1], [rgba][2][1], [rgba][3][1]
|
|
// ...
|
|
// so we can basically add up the columns (multiplying by weights in between)
|
|
// and we'll end up with [final0, final1, final2, final3, final4]
|
|
tfrag3::PackedTimeOfDay pack_colors(const level_tools::TimeOfDayPalette& in) {
|
|
tfrag3::PackedTimeOfDay out;
|
|
out.color_count = (in.height + 3) & (~3);
|
|
out.data.resize(out.color_count * 8 * 4);
|
|
|
|
// we're rearranging per 4 colors (groups of 32 * 4 = 128)
|
|
// color (lots of these)
|
|
// component (8 of these)
|
|
// channel (4 of these, rgba)
|
|
|
|
for (u32 color = 0; color < in.height; color++) {
|
|
for (u32 palette = 0; palette < 8; palette++) {
|
|
for (u32 channel = 0; channel < 4; channel++) {
|
|
out.read(color, palette, channel) =
|
|
(in.colors[color * 8 + palette] >> (8 * channel)) & 0xff;
|
|
}
|
|
}
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
} // namespace decompiler
|