[gfx] Clean up background renderer matrices, fix "hole covers" (#2866)

The way we got/stored background matrices is a bit weird and full of
leftovers from the first attempts at porting renderers. This doesn't
work well with the Jak 2 "other camera" system where some stuff is
rendered with a different camera matrix.

This cleans most of it up. The exception is that the collide mesh
renderer and the additional sprite culling I added still need to peek at
some cached camera matrices.

This fixes the problem where etie uses the wrong matrices for "other
camera" levels. Now the "hole covers" go in the holes in the background
of the throne room.

![image](https://github.com/open-goal/jak-project/assets/48171810/73a88f7b-05d4-4e9c-bb34-5b45efffcb69)
This commit is contained in:
water111
2023-07-29 20:34:42 -04:00
committed by GitHub
parent 50c15f1a47
commit a918e2d9de
8 changed files with 62 additions and 107 deletions
@@ -55,12 +55,6 @@ struct SharedRenderState {
// including transformation, rotation, perspective
math::Vector4f camera_matrix[4];
// including transformation, rotation
math::Vector4f camera_no_persp[4];
// just the perspective
math::Vector4f camera_persp[4];
math::Vector4f camera_hvdf_off;
math::Vector4f camera_fog;
math::Vector4f camera_pos;
@@ -106,27 +106,20 @@ void CollideMeshRenderer::render(SharedRenderState* render_state, ScopedProfiler
render_state->shaders[ShaderId::COLLISION].activate();
glBindVertexArray(m_vao);
TfragRenderSettings settings;
memcpy(settings.math_camera.data(), render_state->camera_matrix[0].data(), 64);
settings.hvdf_offset = render_state->camera_hvdf_off;
settings.fog = render_state->camera_fog;
settings.tree_idx = 0;
for (int i = 0; i < 4; i++) {
settings.planes[i] = render_state->camera_planes[i];
}
auto shader = render_state->shaders[ShaderId::COLLISION].id();
glUniformBlockBinding(shader, glGetUniformBlockIndex(shader, "PatColors"), 0);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_ubo);
glUniformMatrix4fv(glGetUniformLocation(shader, "camera"), 1, GL_FALSE,
settings.math_camera.data());
glUniform4f(glGetUniformLocation(shader, "hvdf_offset"), settings.hvdf_offset[0],
settings.hvdf_offset[1], settings.hvdf_offset[2], settings.hvdf_offset[3]);
render_state->camera_matrix[0].data());
glUniform4f(glGetUniformLocation(shader, "hvdf_offset"), render_state->camera_hvdf_off[0],
render_state->camera_hvdf_off[1], render_state->camera_hvdf_off[2],
render_state->camera_hvdf_off[3]);
const auto& trans = render_state->camera_pos;
glUniform4f(glGetUniformLocation(shader, "camera_position"), trans[0], trans[1], trans[2],
trans[3]);
glUniform1f(glGetUniformLocation(shader, "fog_constant"), settings.fog.x());
glUniform1f(glGetUniformLocation(shader, "fog_min"), settings.fog.y());
glUniform1f(glGetUniformLocation(shader, "fog_max"), settings.fog.z());
glUniform1f(glGetUniformLocation(shader, "fog_constant"), render_state->camera_fog.x());
glUniform1f(glGetUniformLocation(shader, "fog_min"), render_state->camera_fog.y());
glUniform1f(glGetUniformLocation(shader, "fog_max"), render_state->camera_fog.z());
glUniform1i(glGetUniformLocation(shader, "version"), (GLint)render_state->version);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GEQUAL);
@@ -50,22 +50,12 @@ void Shrub::render(DmaFollower& dma, SharedRenderState* render_state, ScopedProf
}
TfragRenderSettings settings;
settings.hvdf_offset = m_pc_port_data.hvdf_off;
settings.fog = m_pc_port_data.fog;
settings.camera = m_pc_port_data.camera;
memcpy(settings.math_camera.data(), m_pc_port_data.camera[0].data(), 64);
settings.tree_idx = 0;
for (int i = 0; i < 4; i++) {
settings.itimes[i] = m_pc_port_data.itimes[i];
}
update_render_state_from_pc_settings(render_state, m_pc_port_data);
for (int i = 0; i < 4; i++) {
settings.planes[i] = m_pc_port_data.planes[i];
}
m_has_level = setup_for_level(m_pc_port_data.level_name, render_state);
render_all_trees(settings, render_state, prof);
}
@@ -245,9 +235,9 @@ void Shrub::render_tree(int idx,
Timer interp_timer;
#ifndef __aarch64__
if (m_use_fast_time_of_day) {
interp_time_of_day_fast(settings.itimes, tree.tod_cache, m_color_result.data());
interp_time_of_day_fast(settings.camera.itimes, tree.tod_cache, m_color_result.data());
} else {
interp_time_of_day_slow(settings.itimes, *tree.colors, m_color_result.data());
interp_time_of_day_slow(settings.camera.itimes, *tree.colors, m_color_result.data());
}
#else
interp_time_of_day_slow(settings.itimes, *tree.colors, m_color_result.data());
@@ -151,10 +151,8 @@ void TFragment::render(DmaFollower& dma,
{
setup_for_level(m_tree_kinds, level_name, render_state);
TfragRenderSettings settings;
settings.hvdf_offset = m_tfrag_data.hvdf_offset;
settings.fog = m_tfrag_data.fog;
memcpy(settings.math_camera.data(), &m_buffered_data[0].pad[TFragDataMem::TFragMatrix0 * 16],
64);
settings.camera = m_pc_port_data.camera;
settings.tree_idx = 0;
if (render_state->occlusion_vis[m_level_id].valid) {
settings.occlusion_culling = render_state->occlusion_vis[m_level_id].data;
@@ -162,11 +160,6 @@ void TFragment::render(DmaFollower& dma,
update_render_state_from_pc_settings(render_state, m_pc_port_data);
for (int i = 0; i < 4; i++) {
settings.planes[i] = m_pc_port_data.planes[i];
settings.itimes[i] = m_pc_port_data.itimes[i];
}
auto t3prof = prof.make_scoped_child("t3");
render_matching_trees(lod(), m_tree_kinds, settings, render_state, t3prof);
}
@@ -228,8 +221,7 @@ void TFragment::handle_initialization(DmaFollower& dma) {
// data
auto data_upload = dma.read_and_advance();
unpack_to_stcycl(&m_tfrag_data, data_upload, VifCode::Kind::UNPACK_V4_32, 4, 4, sizeof(TFragData),
TFragDataMem::TFragFrameData, false, false);
(void)data_upload;
// call the setup program
auto mscal_setup = dma.read_and_advance();
@@ -416,13 +408,13 @@ void TFragment::render_tree(int geom,
return;
}
auto& tree = m_cached_trees.at(geom).at(settings.tree_idx);
const auto* itimes = settings.itimes;
const auto* itimes = settings.camera.itimes;
if (tree.freeze_itimes) {
itimes = tree.itimes_debug;
} else {
for (int i = 0; i < 4; i++) {
tree.itimes_debug[i] = settings.itimes[i];
tree.itimes_debug[i] = settings.camera.itimes[i];
}
}
@@ -433,9 +425,9 @@ void TFragment::render_tree(int geom,
}
#ifndef __aarch64__
if (m_use_fast_time_of_day) {
interp_time_of_day_fast(settings.itimes, tree.tod_cache, m_color_result.data());
interp_time_of_day_fast(settings.camera.itimes, tree.tod_cache, m_color_result.data());
} else {
interp_time_of_day_slow(settings.itimes, *tree.colors, m_color_result.data());
interp_time_of_day_slow(settings.camera.itimes, *tree.colors, m_color_result.data());
}
#else
interp_time_of_day_slow(settings.itimes, *tree.colors, m_color_result.data());
@@ -455,7 +447,7 @@ void TFragment::render_tree(int geom,
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(UINT32_MAX);
cull_check_all_slow(settings.planes, tree.vis->vis_nodes, settings.occlusion_culling,
cull_check_all_slow(settings.camera.planes, tree.vis->vis_nodes, settings.occlusion_culling,
m_cache.vis_temp.data());
u32 total_tris;
@@ -687,14 +679,14 @@ void TFragment::render_tree_cull_debug(const TfragRenderSettings& settings,
render_state->shaders[ShaderId::TFRAG3_NO_TEX].activate();
glUniformMatrix4fv(
glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3_NO_TEX].id(), "camera"), 1,
GL_FALSE, settings.math_camera.data());
GL_FALSE, settings.camera.camera[0].data());
glUniform4f(
glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3_NO_TEX].id(), "hvdf_offset"),
settings.hvdf_offset[0], settings.hvdf_offset[1], settings.hvdf_offset[2],
settings.hvdf_offset[3]);
settings.camera.hvdf_off[0], settings.camera.hvdf_off[1], settings.camera.hvdf_off[2],
settings.camera.hvdf_off[3]);
glUniform1f(
glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3_NO_TEX].id(), "fog_constant"),
settings.fog.x());
settings.camera.fog.x());
// glDisable(GL_DEPTH_TEST);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GEQUAL);
@@ -88,8 +88,6 @@ class TFragment : public BucketRenderer {
u8 m_test_setup[32];
// VU data
TFragData m_tfrag_data;
TfragPcPortData m_pc_port_data;
// buffers
@@ -342,10 +342,8 @@ bool Tie3::set_up_common_data_from_dma(DmaFollower& dma, SharedRenderState* rend
dma.read_and_advance();
}
m_common_data.settings.hvdf_offset = m_pc_port_data.hvdf_off;
m_common_data.settings.fog = m_pc_port_data.fog;
m_common_data.settings.camera = m_pc_port_data.camera;
memcpy(m_common_data.settings.math_camera.data(), m_pc_port_data.camera[0].data(), 64);
m_common_data.settings.tree_idx = 0;
if (render_state->occlusion_vis[m_level_id].valid) {
@@ -356,11 +354,6 @@ bool Tie3::set_up_common_data_from_dma(DmaFollower& dma, SharedRenderState* rend
update_render_state_from_pc_settings(render_state, m_pc_port_data);
for (int i = 0; i < 4; i++) {
m_common_data.settings.planes[i] = m_pc_port_data.planes[i];
m_common_data.settings.itimes[i] = m_pc_port_data.itimes[i];
}
m_has_level = try_loading_level(m_pc_port_data.level_name, render_state);
return true;
}
@@ -436,9 +429,9 @@ void Tie3::setup_tree(int idx,
#ifndef __aarch64__
if (m_use_fast_time_of_day) {
interp_time_of_day_fast(settings.itimes, tree.tod_cache, m_color_result.data());
interp_time_of_day_fast(settings.camera.itimes, tree.tod_cache, m_color_result.data());
} else {
interp_time_of_day_slow(settings.itimes, *tree.colors, m_color_result.data());
interp_time_of_day_slow(settings.camera.itimes, *tree.colors, m_color_result.data());
}
#else
interp_time_of_day_slow(settings.itimes, *tree.colors, m_color_result.data());
@@ -456,7 +449,7 @@ void Tie3::setup_tree(int idx,
if (!m_debug_all_visible) {
// need culling data
cull_check_all_slow(settings.planes, tree.vis->vis_nodes, settings.occlusion_culling,
cull_check_all_slow(settings.camera.planes, tree.vis->vis_nodes, settings.occlusion_culling,
tree.vis_temp.data());
}
@@ -511,17 +504,17 @@ void set_uniform(GLuint uniform, const math::Vector4f& val) {
}
} // namespace
void init_etie_cam_uniforms(const EtieUniforms& uniforms, const SharedRenderState* render_state) {
glUniformMatrix4fv(uniforms.cam_no_persp, 1, GL_FALSE, render_state->camera_no_persp[0].data());
void init_etie_cam_uniforms(const EtieUniforms& uniforms, const GoalBackgroundCameraData& data) {
glUniformMatrix4fv(uniforms.cam_no_persp, 1, GL_FALSE, data.rot[0].data());
math::Vector4f perspective[2];
float inv_fog = 1.f / render_state->camera_fog[0];
auto& hvdf_off = render_state->camera_hvdf_off;
float pxx = render_state->camera_persp[0].x();
float pyy = render_state->camera_persp[1].y();
float pzz = render_state->camera_persp[2].z();
float pzw = render_state->camera_persp[2].w();
float pwz = render_state->camera_persp[3].z();
float inv_fog = 1.f / data.fog[0];
auto& hvdf_off = data.hvdf_off;
float pxx = data.perspective[0].x();
float pyy = data.perspective[1].y();
float pzz = data.perspective[2].z();
float pzw = data.perspective[2].w();
float pwz = data.perspective[3].z();
float scale = pzw * inv_fog;
perspective[0].x() = scale * hvdf_off.x();
perspective[0].y() = scale * hvdf_off.y();
@@ -557,7 +550,7 @@ void Tie3::draw_matching_draws_for_tree(int idx,
if (use_envmap) {
// if we use envmap, use the envmap-style math for the base draw to avoid rounding issue.
init_etie_cam_uniforms(m_etie_base_uniforms, render_state);
init_etie_cam_uniforms(m_etie_base_uniforms, m_common_data.settings.camera);
}
glBindVertexArray(tree.vao);
@@ -661,7 +654,7 @@ void Tie3::envmap_second_pass_draw(const Tree& tree,
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
render_state->no_multidraw ? tree.single_draw_index_buffer : tree.index_buffer);
init_etie_cam_uniforms(m_etie_uniforms, render_state);
init_etie_cam_uniforms(m_etie_uniforms, m_common_data.settings.camera);
set_uniform(m_etie_uniforms.envmap_tod_tint, m_common_data.envmap_color);
int last_texture = -1;
@@ -894,12 +887,10 @@ void Tie3::render_tree_wind(int idx,
// note: this isn't the most efficient because we might compute wind matrices for invisible
// instances. TODO: add vis ids to the instance info to avoid this
memset(tree.wind_matrix_cache.data(), 0, sizeof(float) * 16 * tree.wind_matrix_cache.size());
auto& cam_bad = settings.math_camera;
auto& cam_bad = settings.camera.camera;
std::array<math::Vector4f, 4> cam;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
cam[i][j] = cam_bad.data()[i * 4 + j];
}
cam[i] = cam_bad[i];
}
for (size_t inst_id = 0; inst_id < tree.instance_info->size(); inst_id++) {
@@ -179,14 +179,15 @@ void first_tfrag_draw_setup(const TfragRenderSettings& settings,
auto id = sh.id();
glUniform1i(glGetUniformLocation(id, "gfx_hack_no_tex"), Gfx::g_global_settings.hack_no_tex);
glUniform1i(glGetUniformLocation(id, "decal"), false);
glUniform1i(glGetUniformLocation(id, "tex_T0"), 0);
glUniformMatrix4fv(glGetUniformLocation(id, "camera"), 1, GL_FALSE, settings.math_camera.data());
glUniform4f(glGetUniformLocation(id, "hvdf_offset"), settings.hvdf_offset[0],
settings.hvdf_offset[1], settings.hvdf_offset[2], settings.hvdf_offset[3]);
glUniform1f(glGetUniformLocation(id, "fog_constant"), settings.fog.x());
glUniform1f(glGetUniformLocation(id, "fog_min"), settings.fog.y());
glUniform1f(glGetUniformLocation(id, "fog_max"), settings.fog.z());
glUniformMatrix4fv(glGetUniformLocation(id, "camera"), 1, GL_FALSE,
settings.camera.camera[0].data());
glUniform4f(glGetUniformLocation(id, "hvdf_offset"), settings.camera.hvdf_off[0],
settings.camera.hvdf_off[1], settings.camera.hvdf_off[2],
settings.camera.hvdf_off[3]);
glUniform1f(glGetUniformLocation(id, "fog_constant"), settings.camera.fog.x());
glUniform1f(glGetUniformLocation(id, "fog_min"), settings.camera.fog.y());
glUniform1f(glGetUniformLocation(id, "fog_max"), settings.camera.fog.z());
glUniform4f(glGetUniformLocation(id, "fog_color"), render_state->fog_color[0] / 255.f,
render_state->fog_color[1] / 255.f, render_state->fog_color[2] / 255.f,
render_state->fog_intensity / 255);
@@ -777,14 +778,12 @@ u32 make_all_visible_index_list(std::pair<int, int>* group_out,
void update_render_state_from_pc_settings(SharedRenderState* state, const TfragPcPortData& data) {
if (!state->has_pc_data) {
for (int i = 0; i < 4; i++) {
state->camera_planes[i] = data.planes[i];
state->camera_matrix[i] = data.camera[i];
state->camera_no_persp[i] = data.camera_rot[i];
state->camera_persp[i] = data.camera_perspective[i];
state->camera_planes[i] = data.camera.planes[i];
state->camera_matrix[i] = data.camera.camera[i];
}
state->camera_pos = data.cam_trans;
state->camera_hvdf_off = data.hvdf_off;
state->camera_fog = data.fog;
state->camera_pos = data.camera.trans;
state->camera_hvdf_off = data.camera.hvdf_off;
state->camera_fog = data.camera.fog;
state->has_pc_data = true;
}
}
@@ -4,31 +4,29 @@
#include "game/graphics/opengl_renderer/BucketRenderer.h"
// data passed from game to PC renderers
// the GOAL code assumes this memory layout.
struct TfragPcPortData {
struct GoalBackgroundCameraData {
math::Vector4f planes[4];
math::Vector<s32, 4> itimes[4];
math::Vector4f camera[4];
math::Vector4f hvdf_off;
math::Vector4f fog;
math::Vector4f cam_trans;
math::Vector4f camera_rot[4];
math::Vector4f camera_perspective[4];
math::Vector4f trans;
math::Vector4f rot[4];
math::Vector4f perspective[4];
};
// data passed from game to PC renderers
// the GOAL code assumes this memory layout.
struct TfragPcPortData {
GoalBackgroundCameraData camera;
char level_name[16];
};
static_assert(sizeof(TfragPcPortData) == 16 * 24);
// inputs to background renderers.
struct TfragRenderSettings {
math::Matrix4f math_camera;
math::Vector4f hvdf_offset;
math::Vector4f fog;
GoalBackgroundCameraData camera;
int tree_idx;
math::Vector<s32, 4> itimes[4];
math::Vector4f planes[4];
bool debug_culling = false;
const u8* occlusion_culling = nullptr;
};