Files
jak-project/game/graphics/opengl_renderer/foreground/Generic2_OpenGL.cpp
T
ManDude 7b25afa697 add a bunch of new cheat codes & re-do all pc cheat codes (#1770)
* redo cheat encodings

* fix error

* add no texture cheat

* tiny cleanup + add sidekick stats button

* crappy implementation of big/small head mode

* more correct bone scaling

* redo bone manip code a bit

* jp text fixes

* improved matrix math!

* add big fist cheat, minor type cleanup, add some debug toggles

* move all this mess to a new file

* slightly rework joint scaling function

* add big head npc cheat

* subtitles typo

* WIP mirror mode

* fix mirrored hud sprites

* fix mirror mode sound pan

* add cheats to menu!

* split some subtitles
2022-08-20 10:30:37 -04:00

330 lines
13 KiB
C++

#include "Generic2.h"
void Generic2::opengl_setup() {
// create OpenGL objects
glGenBuffers(1, &m_ogl.vertex_buffer);
glGenBuffers(1, &m_ogl.index_buffer);
glGenVertexArrays(1, &m_ogl.vao);
// set up the vertex array
glBindVertexArray(m_ogl.vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof(u32), nullptr, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, m_ogl.vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, m_verts.size() * sizeof(Vertex), nullptr, GL_STREAM_DRAW);
// xyz
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, // location 0 in the shader
3, // 3 floats per vert
GL_FLOAT, // floats
GL_TRUE, // normalized, ignored,
sizeof(Vertex), //
(void*)offsetof(Vertex, xyz) // offset in array
);
// rgba
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, // location 1 in the shader
4, // 4 color components
GL_UNSIGNED_BYTE, // u8
GL_TRUE, // normalized (255 becomes 1)
sizeof(Vertex), //
(void*)offsetof(Vertex, rgba) //
);
// stq
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, // location 2 in the shader
2, // 2 floats per vert
GL_FLOAT, // floats
GL_FALSE, // normalized, ignored
sizeof(Vertex), //
(void*)offsetof(Vertex, st) // offset in array
);
// byte data
glEnableVertexAttribArray(3);
glVertexAttribIPointer(3, // location 3 in the shader
4, //
GL_UNSIGNED_BYTE, // u8's
sizeof(Vertex), //
(void*)offsetof(Vertex, tex_unit) // offset in array
);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Generic2::opengl_cleanup() {
glDeleteBuffers(1, &m_ogl.vertex_buffer);
glDeleteBuffers(1, &m_ogl.index_buffer);
glDeleteVertexArrays(1, &m_ogl.vao);
}
void Generic2::init_shaders(ShaderLibrary& shaders) {
const auto& shader = shaders[ShaderId::GENERIC];
auto id = shader.id();
shader.activate();
m_ogl.alpha_reject = glGetUniformLocation(id, "alpha_reject");
m_ogl.color_mult = glGetUniformLocation(id, "color_mult");
m_ogl.fog_color = glGetUniformLocation(id, "fog_color");
m_ogl.scale = glGetUniformLocation(id, "scale");
m_ogl.mat_23 = glGetUniformLocation(id, "mat_23");
m_ogl.mat_32 = glGetUniformLocation(id, "mat_32");
m_ogl.mat_33 = glGetUniformLocation(id, "mat_33");
m_ogl.fog_consts = glGetUniformLocation(id, "fog_constants");
m_ogl.hvdf_offset = glGetUniformLocation(id, "hvdf_offset");
m_ogl.gfx_hack_no_tex = glGetUniformLocation(id, "gfx_hack_no_tex");
}
void Generic2::opengl_bind_and_setup_proj(SharedRenderState* render_state) {
render_state->shaders[ShaderId::GENERIC].activate();
glUniform4f(m_ogl.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);
glUniform4f(m_ogl.scale, m_drawing_config.proj_scale[0], m_drawing_config.proj_scale[1],
m_drawing_config.proj_scale[2], 0);
glUniform1f(m_ogl.mat_23, m_drawing_config.proj_mat_23);
glUniform1f(m_ogl.mat_32, m_drawing_config.proj_mat_32);
glUniform1f(m_ogl.mat_33, 0);
glUniform3f(m_ogl.fog_consts, m_drawing_config.pfog0, m_drawing_config.fog_min,
m_drawing_config.fog_max);
glUniform4f(m_ogl.hvdf_offset, m_drawing_config.hvdf_offset[0], m_drawing_config.hvdf_offset[1],
m_drawing_config.hvdf_offset[2], m_drawing_config.hvdf_offset[3]);
glUniform1i(m_ogl.gfx_hack_no_tex, Gfx::g_global_settings.hack_no_tex);
}
void Generic2::setup_opengl_for_draw_mode(const DrawMode& draw_mode,
u8 fix,
SharedRenderState* render_state) {
// compute alpha_reject:
float alpha_reject = 0.f;
if (draw_mode.get_at_enable()) {
switch (draw_mode.get_alpha_test()) {
case DrawMode::AlphaTest::ALWAYS:
break;
case DrawMode::AlphaTest::GEQUAL:
alpha_reject = draw_mode.get_aref() / 128.f;
break;
case DrawMode::AlphaTest::NEVER:
break;
default:
ASSERT_MSG(false, fmt::format("unknown alpha test: {}", (int)draw_mode.get_alpha_test()));
}
}
// setup blending and color mult
float color_mult = 1.f;
if (!draw_mode.get_ab_enable()) {
glDisable(GL_BLEND);
} else {
glEnable(GL_BLEND);
glBlendColor(1, 1, 1, 1);
if (draw_mode.get_alpha_blend() == DrawMode::AlphaBlend::SRC_DST_SRC_DST) {
// (Cs - Cd) * As + Cd
// Cs * As + (1 - As) * Cd
// s, d
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
} else if (draw_mode.get_alpha_blend() == DrawMode::AlphaBlend::SRC_0_SRC_DST) {
// (Cs - 0) * As + Cd
// Cs * As + (1) * Cd
// s, d
ASSERT(fix == 0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
} else if (draw_mode.get_alpha_blend() == DrawMode::AlphaBlend::ZERO_SRC_SRC_DST) {
// (0 - Cs) * As + Cd
// Cd - Cs * As
// s, d
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
} else if (draw_mode.get_alpha_blend() == DrawMode::AlphaBlend::SRC_DST_FIX_DST) {
// (Cs - Cd) * fix + Cd
// Cs * fix + (1 - fx) * Cd
glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
glBlendColor(0, 0, 0, fix / 127.f);
glBlendEquation(GL_FUNC_ADD);
} else if (draw_mode.get_alpha_blend() == DrawMode::AlphaBlend::SRC_SRC_SRC_SRC) {
// this is very weird...
// Cs
glBlendFunc(GL_ONE, GL_ZERO);
glBlendEquation(GL_FUNC_ADD);
} else if (draw_mode.get_alpha_blend() == DrawMode::AlphaBlend::SRC_0_DST_DST) {
// (Cs - 0) * Ad + Cd
glBlendFunc(GL_DST_ALPHA, GL_ONE);
glBlendEquation(GL_FUNC_ADD);
color_mult = 0.5f;
} else if (draw_mode.get_alpha_blend() == DrawMode::AlphaBlend::SRC_0_FIX_DST) {
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ZERO);
} else {
ASSERT(false);
}
}
// setup ztest
if (draw_mode.get_zt_enable()) {
glEnable(GL_DEPTH_TEST);
switch (draw_mode.get_depth_test()) {
case GsTest::ZTest::NEVER:
glDepthFunc(GL_NEVER);
break;
case GsTest::ZTest::ALWAYS:
glDepthFunc(GL_ALWAYS);
break;
case GsTest::ZTest::GEQUAL:
glDepthFunc(GL_GEQUAL);
break;
case GsTest::ZTest::GREATER:
glDepthFunc(GL_GREATER);
break;
default:
ASSERT(false);
}
} else {
// you aren't supposed to turn off z test enable, the GS had some bugs
ASSERT(false);
}
if (draw_mode.get_depth_write_enable()) {
glDepthMask(GL_TRUE);
} else {
glDepthMask(GL_FALSE);
}
glUniform1f(m_ogl.alpha_reject, alpha_reject);
glUniform1f(m_ogl.color_mult, color_mult);
glUniform4f(m_ogl.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);
}
void Generic2::setup_opengl_tex(u16 unit,
u16 tbp,
bool filter,
bool clamp_s,
bool clamp_t,
SharedRenderState* render_state) {
// look up the texture
std::optional<u64> tex;
u32 tbp_to_lookup = tbp & 0x7fff;
bool use_mt4hh = tbp & 0x8000;
if (use_mt4hh) {
tex = render_state->texture_pool->lookup_mt4hh(tbp_to_lookup);
} else {
tex = render_state->texture_pool->lookup(tbp_to_lookup);
}
if (!tex) {
// TODO Add back
if (tbp_to_lookup >= 8160 && tbp_to_lookup <= 8600) {
fmt::print("Failed to find texture at {}, using random (eye zone)\n", tbp_to_lookup);
tex = render_state->texture_pool->get_placeholder_texture();
} else {
fmt::print("Failed to find texture at {}, using random\n", tbp_to_lookup);
tex = render_state->texture_pool->get_placeholder_texture();
}
}
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_2D, *tex);
if (clamp_s) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
}
if (clamp_t) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
if (filter) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
true ? GL_LINEAR : GL_LINEAR_MIPMAP_LINEAR); // todo
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
}
void Generic2::do_draws_for_alpha(SharedRenderState* render_state,
ScopedProfilerNode& prof,
DrawMode::AlphaBlend alpha,
bool hud) {
for (u32 i = 0; i < m_next_free_bucket; i++) {
auto& bucket = m_buckets[i];
auto& first = m_adgifs[bucket.start];
if (first.mode.get_alpha_blend() == alpha && first.uses_hud == hud) {
setup_opengl_for_draw_mode(first.mode, first.fix, render_state);
setup_opengl_tex(0, first.tbp, first.mode.get_filt_enable(), first.mode.get_clamp_s_enable(),
first.mode.get_clamp_t_enable(), render_state);
glDrawElements(GL_TRIANGLE_STRIP, bucket.idx_count, GL_UNSIGNED_INT,
(void*)(sizeof(u32) * bucket.idx_idx));
prof.add_draw_call();
prof.add_tri(bucket.tri_count);
}
}
}
void Generic2::do_hud_draws(SharedRenderState* render_state, ScopedProfilerNode& prof) {
for (u32 i = 0; i < m_next_free_bucket; i++) {
auto& bucket = m_buckets[i];
auto& first = m_adgifs[bucket.start];
if (first.uses_hud) {
setup_opengl_for_draw_mode(first.mode, first.fix, render_state);
setup_opengl_tex(0, first.tbp, first.mode.get_filt_enable(), first.mode.get_clamp_s_enable(),
first.mode.get_clamp_t_enable(), render_state);
glDrawElements(GL_TRIANGLE_STRIP, bucket.idx_count, GL_UNSIGNED_INT,
(void*)(sizeof(u32) * bucket.idx_idx));
prof.add_draw_call();
prof.add_tri(bucket.tri_count);
}
}
}
void Generic2::do_draws(SharedRenderState* render_state, ScopedProfilerNode& prof) {
glBindVertexArray(m_ogl.vao);
glBindBuffer(GL_ARRAY_BUFFER, m_ogl.vertex_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_next_free_idx * sizeof(u32), m_indices.data(),
GL_STREAM_DRAW);
glBufferData(GL_ARRAY_BUFFER, m_next_free_vert * sizeof(Vertex), m_verts.data(), GL_STREAM_DRAW);
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(UINT32_MAX);
opengl_bind_and_setup_proj(render_state);
constexpr DrawMode::AlphaBlend alpha_order[ALPHA_MODE_COUNT] = {
DrawMode::AlphaBlend::SRC_0_FIX_DST, DrawMode::AlphaBlend::SRC_SRC_SRC_SRC,
DrawMode::AlphaBlend::SRC_DST_SRC_DST, DrawMode::AlphaBlend::SRC_0_SRC_DST,
DrawMode::AlphaBlend::ZERO_SRC_SRC_DST, DrawMode::AlphaBlend::SRC_DST_FIX_DST,
DrawMode::AlphaBlend::SRC_0_DST_DST,
};
for (int i = 0; i < ALPHA_MODE_COUNT; i++) {
if (m_alpha_draw_enable[i]) {
do_draws_for_alpha(render_state, prof, alpha_order[i], false);
}
}
if (m_drawing_config.uses_hud) {
glUniform4f(m_ogl.scale, m_drawing_config.hud_scale[0], m_drawing_config.hud_scale[1],
m_drawing_config.hud_scale[2], 0);
glUniform1f(m_ogl.mat_23, m_drawing_config.hud_mat_23);
glUniform1f(m_ogl.mat_32, m_drawing_config.hud_mat_32);
glUniform1f(m_ogl.mat_33, m_drawing_config.hud_mat_33);
glUniform1i(m_ogl.gfx_hack_no_tex, false);
do_hud_draws(render_state, prof);
}
}