mirror of
https://github.com/open-goal/jak-project
synced 2026-07-26 14:40:25 -04:00
[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. 
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user