mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 21:27:52 -04:00
3d08d079c9
Initial implementation of the `ocean-mid`, `ocean-far` and `ocean-near` renderers for Jak 2. There's still a few things to sort out, mainly: - [x] ~Backwards compatibility with Jak 1. The only thing that currently stands in the way of that is figuring out a clean way to "un-hardcode" the texture base pointer in C++ without creating a completely separate `OceanTexture` class for Jak 2. One thing I thought of would be modifying `BucketRenderer`'s virtual `init_textures` method to also pass the `GameVersion`, but I'm not sure if there's a better way.~ - [x] ~The sudden transition from `ocean-near` to `ocean-mid`. Not sure why it's happening or how to fix it.~ - [x] The ocean has two new methods in Jak 2, `ocean::89` and `ocean::79`, one of which seems to be related to time of day sky colors. ~Even without them implemented, the end result looks quite close, so we may be able to skip them?~ `ocean::89` generates `ocean-mid` envmap textures, so it will likely be required, but will not be handled right now. Reverted the VU prologue removals because it made the tests fail.
193 lines
5.7 KiB
C++
193 lines
5.7 KiB
C++
#pragma once
|
|
|
|
#include "game/common/vu.h"
|
|
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
|
#include "game/graphics/opengl_renderer/DirectRenderer.h"
|
|
#include "game/graphics/opengl_renderer/ocean/CommonOceanRenderer.h"
|
|
|
|
class OceanMid {
|
|
public:
|
|
OceanMid();
|
|
void run(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
|
void run_jak2(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
|
|
|
private:
|
|
void run_call0();
|
|
void run_call0_vu2c();
|
|
void run_call41_vu2c();
|
|
void run_call43_vu2c();
|
|
void run_call46_vu2c();
|
|
void run_call73_vu2c();
|
|
void run_call73_vu2c_jak2();
|
|
void run_call107_vu2c();
|
|
void run_call107_vu2c_jak2();
|
|
void run_call275_vu2c();
|
|
void run_call275_vu2c_jak2();
|
|
void xgkick(u16 addr);
|
|
|
|
void run_L26_vu2c();
|
|
void run_L32_vu2c();
|
|
void run_L32_vu2c_jak2();
|
|
void run_L38_vu2c();
|
|
void run_L38_vu2c_jak2();
|
|
void run_L43_vu2c();
|
|
void run_L45_vu2c();
|
|
|
|
CommonOceanRenderer m_common_ocean_renderer;
|
|
bool m_buffer_toggle = false;
|
|
static constexpr int VU1_INPUT_BUFFER_BASE = 0;
|
|
static constexpr int VU1_INPUT_BUFFER_OFFSET = 0x76;
|
|
|
|
u16 xtop() {
|
|
m_buffer_toggle = !m_buffer_toggle;
|
|
return get_vu_buffer();
|
|
}
|
|
|
|
u16 get_upload_buffer() {
|
|
if (m_buffer_toggle) {
|
|
return VU1_INPUT_BUFFER_OFFSET;
|
|
} else {
|
|
return VU1_INPUT_BUFFER_BASE;
|
|
}
|
|
}
|
|
|
|
u16 get_vu_buffer() {
|
|
if (!m_buffer_toggle) {
|
|
return VU1_INPUT_BUFFER_OFFSET;
|
|
} else {
|
|
return VU1_INPUT_BUFFER_BASE;
|
|
}
|
|
}
|
|
|
|
// (deftype ocean-mid-constants (structure)
|
|
struct Constants {
|
|
// ((hmge-scale vector :inline :offset-assert 0)
|
|
math::Vector4f hmge_scale;
|
|
// (inv-hmge-scale vector :inline :offset-assert 16)
|
|
math::Vector4f inv_hmge_scale;
|
|
// (hvdf-offset vector :inline :offset-assert 32)
|
|
math::Vector4f hvdf_offset;
|
|
// (fog vector :inline :offset-assert 48)
|
|
math::Vector4f fog;
|
|
// (constants vector :inline :offset-assert 64)
|
|
math::Vector4f constants;
|
|
// (constants2 vector :inline :offset-assert 80)
|
|
math::Vector4f constants2;
|
|
// (drw-fan gs-gif-tag :inline :offset-assert 96) ;; was qword
|
|
u8 drw_fan[16];
|
|
// (env-fan gs-gif-tag :inline :offset-assert 112) ;; was qword
|
|
u8 env_fan[16];
|
|
// (drw-adgif gs-gif-tag :inline :offset-assert 128);; was qword
|
|
AdGifData drw_adgif;
|
|
// (drw-texture adgif-shader :inline :offset-assert 144)
|
|
u8 drw_texture[16];
|
|
// (drw-strip-0 gs-gif-tag :inline :offset-assert 224) ;; was qword
|
|
u8 drw_strip_0[16];
|
|
// (drw-strip-1 gs-gif-tag :inline :offset-assert 240) ;; was qword
|
|
u8 drw_strip_1[16];
|
|
// (env-adgif gs-gif-tag :inline :offset-assert 256) ;; was qword
|
|
u8 env_adgif[16];
|
|
// (env-texture adgif-shader :inline :offset-assert 272)
|
|
AdGifData env_texture;
|
|
// (env-strip gs-gif-tag :inline :offset-assert 352) ;; was qword
|
|
u8 env_strip[16];
|
|
// (env-color vector :inline :offset-assert 368)
|
|
math::Vector4f env_color;
|
|
// (index-table vector4w 8 :inline :offset-assert 384)
|
|
math::Vector<u32, 4> index_table[8];
|
|
// (pos0 vector :inline :offset-assert 512)
|
|
math::Vector4f pos0;
|
|
// (pos1 vector :inline :offset-assert 528)
|
|
math::Vector4f pos1;
|
|
// (pos2 vector :inline :offset-assert 544)
|
|
math::Vector4f pos2;
|
|
// (pos3 vector :inline :offset-assert 560)
|
|
math::Vector4f pos3;
|
|
// )
|
|
// :method-count-assert 9
|
|
// :size-assert #x240
|
|
// :flag-assert #x900000240
|
|
// )
|
|
} m_constants;
|
|
static_assert(sizeof(Constants) == 0x240);
|
|
|
|
enum Vu1Data {
|
|
IN_BUFFER_0 = VU1_INPUT_BUFFER_BASE, // 0
|
|
IN_BUFFER_1 = VU1_INPUT_BUFFER_OFFSET, // 0x76
|
|
|
|
CONSTANTS = 0x2dd,
|
|
};
|
|
|
|
Vf m_vu_data[1024];
|
|
|
|
void sq_buffer(Mask mask, const Vf& val, u16 addr) {
|
|
ASSERT(addr < 1024);
|
|
for (int i = 0; i < 4; i++) {
|
|
if ((u64)mask & (1 << i)) {
|
|
m_vu_data[addr].data[i] = val[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
void ilw_buffer(Mask mask, u16& dest, u16 addr) {
|
|
ASSERT(addr < 1024);
|
|
switch (mask) {
|
|
case Mask::x:
|
|
dest = m_vu_data[addr].x_as_u16();
|
|
break;
|
|
case Mask::y:
|
|
dest = m_vu_data[addr].y_as_u16();
|
|
break;
|
|
case Mask::z:
|
|
dest = m_vu_data[addr].z_as_u16();
|
|
break;
|
|
case Mask::w:
|
|
dest = m_vu_data[addr].w_as_u16();
|
|
break;
|
|
default:
|
|
ASSERT(false);
|
|
}
|
|
}
|
|
|
|
void isw_buffer(Mask mask, u16 src, u16 addr) {
|
|
ASSERT(addr < 1024);
|
|
u32 val32 = src;
|
|
switch (mask) {
|
|
case Mask::x:
|
|
memcpy(&m_vu_data[addr].data[0], &val32, 4);
|
|
break;
|
|
case Mask::y:
|
|
memcpy(&m_vu_data[addr].data[1], &val32, 4);
|
|
break;
|
|
case Mask::z:
|
|
memcpy(&m_vu_data[addr].data[2], &val32, 4);
|
|
break;
|
|
case Mask::w:
|
|
memcpy(&m_vu_data[addr].data[3], &val32, 4);
|
|
break;
|
|
default:
|
|
ASSERT(false);
|
|
}
|
|
}
|
|
|
|
void lq_buffer(Mask mask, Vf& dest, u16 addr) {
|
|
ASSERT(addr < 1024);
|
|
for (int i = 0; i < 4; i++) {
|
|
if ((u64)mask & (1 << i)) {
|
|
dest[i] = m_vu_data[addr].data[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
struct Vu {
|
|
const Vf vf00;
|
|
Accumulator acc;
|
|
Vf vf01, vf02, vf03, vf04, vf05, vf06, vf07, vf08, vf09, vf10, vf11, vf12, vf13, vf14, vf15,
|
|
vf16, vf17, vf18, vf19, vf20, vf21, vf22, vf23, vf24, vf25, vf26, vf27, vf28, vf29, vf30,
|
|
vf31;
|
|
u16 vi01, vi02, vi03, vi04, vi05, vi06, vi07, vi08, vi09, vi10, vi11, vi12, vi13, vi14, vi15;
|
|
float Q, P;
|
|
Vu() : vf00(0, 0, 0, 1) {}
|
|
} vu;
|
|
};
|