mirror of
https://github.com/open-goal/jak-project
synced 2026-06-30 11:51:55 -04:00
58a5440c8a
Makes a bunch of missions mostly playable, including: - `arena-training-1` - `arena-fight-1` - `wascity-chase` - `arena-fight-2` - `arena-fight-3` - `volcano-darkeco` - `desert-hover` - `nest-eggs` - `temple-climb` - `temple-oracle` - `temple-tests` - `desert-beast-battle` - `desert-turtle-training` - `desert-course-race` - `desert-artifact-race1` - `wascity-leaper-race` - `wascity-pre-game` - `sewer-met-hum` - `forest-kill-plants` - `forest-ring-chase` - `temple-defend` - `tower-destroy` - `desert-glide` --- Files: - `ripple` - `waswide-mood` - `sig-rider` - `nst-tasks` - `nst-part` - `nst-gas` - `nst-eggs-h` - `nst-obs` - `nst-mood` - `egg-spider` - `wasdoors-init` - `wasall-tasks` - `wvehicle-race` - `wcar-marauder` - `wcar-marauder-b` - `turret-control` - `was-squad-control` - `turtle-training` - `kleever-rider` - `course-race` - `artifact-race` - `desert-hover` - `desbeast-path-h` - `des-beast` - `desertg-obs` - `desertf-obs` - `desertd-obs` - `desert-dust-storm` - `des-cactus` - `race-hud` - `race-info` - `race-manager` - `tizard` - `flyingsaw` - `hover-training` - `temple-mood` - `temple-obs` - `temple-obs2` - `temple-part` - `temple-scenes` - `templex-mood` - `templex-obs` - `templex-part` - `tomb-baby-spider` - `target-turret-shot` - `target-turret` - `beast-battle-path` - `des-beast-2` - `mh-flyer` - `scorpion-gun` - `hover-enemy-h` - `hover-enemy` - `hover-formation-h` - `hover-formation` - `hover-nav-control-h` - `hover-nav-control` - `flamer-hover` - `hover-nav-templea` - `robo-hover` - `hover-nav-sewb` - `hover-nav-sewg` - `hover-nav-sewj` - `hover-nav-sewl` - `hover-nav-sewo` - `hover-nav-towera` - `tower-mood` - `tower-obs` - `tower-scenes` - `tower-part` - `eco-green-collider` - `forest-bridges` - `forest-kill-plants` - `forest-mood` - `forest-ring-chase` - `forest-tasks` - `forest-part` - `foresta-obs` - `hover-nav-foresta` - `mh-plant` - `dp-bipedal-part` - `dp-bipedal-shot` - `dp-bipedal` - `neo-spawner` - `for-turret` - `for-turret-shot` - `neo-wasp` - `neo-wasp-part` - `volcanox-scenes` - `volcanox-mood` - `volcano-scenes` - `volcano-mood` - `volcano-obs` - `volcano-obs2` - `chain-physics` - `rigid-body-plat` - `volcano-part` - `flamer-lava` - `flitter` - `spiky-frog` - `flut-wild` - `target-indax` - `target-indax-hang` - `mantis` - `volcanox-obs` - `spyder` - `wcar-faccar` - `mhcity-obs2` - `mhcity-part` - `mhcity-obs` - `dm-mine-spider` - `rapid-gunner` - `stadium-mood` - `stadium-scenes` - `stadiuma-mood` - `stadiuma-part` - `kanga-lizard` - `marauder` - `arena-scenes` - `wasstada-mood` - `wasstada-obs` - `wasstada-part` - `wasstadb-obs` - `wasstadc-obs` - `dm-flyer` - `maker-part` - `maker-projectile` - `skeet-part` - `wascity-turret` - `wasgun-h` - `wasgun-hud` - `wasgun-manager` - `nav-graph-h` - `traffic-engine-h` - `waswide-init` - `cty-borrow-manager-h` - `cty-borrow-manager` - `desert-part` - `height-map-h` - `height-map` - `traffic-height-map` - `vehicle-control` - `hvehicle-h` - `hvehicle` - `hvehicle-effects` - `hvehicle-physics` - `hvehicle-util` - `glider-h` - `glider-hud` - `glider-manager` - `glider-ring` - `glider-ring-part` - `h-glider` - `hanga-init` - `was-pre-game` - `was-leaper-race` - `flut-racer` - `desert-scenes` - `desert-lizard-h` - `desert-lizard-task` - `desert-lizard` - `throne-scenes` - `waspal-mood` - `waspala-obs` - `waspala-part` - `deswalk-obs` - `deswalk-part` - `terraformer-drone` - `terraformer-head` - `terraformer-part` - `terraformer-setup`
440 lines
16 KiB
C++
440 lines
16 KiB
C++
#include "OceanTexture.h"
|
|
|
|
#include "game/graphics/opengl_renderer/AdgifHandler.h"
|
|
|
|
#include "third-party/imgui/imgui.h"
|
|
|
|
constexpr int OCEAN_TEX_TBP_JAK1 = 8160; // todo
|
|
constexpr int OCEAN_TEX_TBP_JAK2 = 672;
|
|
|
|
OceanTexture::OceanTexture(bool generate_mipmaps)
|
|
: m_generate_mipmaps(generate_mipmaps),
|
|
m_result_texture(TEX0_SIZE,
|
|
TEX0_SIZE,
|
|
GL_UNSIGNED_INT_8_8_8_8_REV,
|
|
m_generate_mipmaps ? NUM_MIPS : 1),
|
|
m_temp_texture(TEX0_SIZE, TEX0_SIZE, GL_UNSIGNED_INT_8_8_8_8_REV) {
|
|
m_dbuf_x = m_dbuf_a;
|
|
m_dbuf_y = m_dbuf_b;
|
|
|
|
m_tbuf_x = m_tbuf_a;
|
|
m_tbuf_y = m_tbuf_b;
|
|
|
|
init_pc();
|
|
|
|
// initialize the mipmap drawing
|
|
glGenVertexArrays(1, &m_mipmap.vao);
|
|
glBindVertexArray(m_mipmap.vao);
|
|
glGenBuffers(1, &m_mipmap.vtx_buffer);
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_mipmap.vtx_buffer);
|
|
std::vector<MipMap::Vertex> vertices = {
|
|
{-1, -1, 0, 0}, {-1, 1, 0, 1}, {1, -1, 1, 0}, {1, 1, 1, 1}};
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(MipMap::Vertex) * 4, vertices.data(), GL_STATIC_DRAW);
|
|
glEnableVertexAttribArray(0);
|
|
glEnableVertexAttribArray(1);
|
|
glVertexAttribPointer(
|
|
0, // location 0 in the shader
|
|
2, // 4 color components
|
|
GL_FLOAT, // floats
|
|
GL_FALSE, // normalized, ignored,
|
|
sizeof(MipMap::Vertex), //
|
|
(void*)offsetof(MipMap::Vertex, x) // offset in array (why is this a pointer...)
|
|
);
|
|
glVertexAttribPointer(
|
|
1, // location 0 in the shader
|
|
2, // 4 color components
|
|
GL_FLOAT, // floats
|
|
GL_FALSE, // normalized, ignored,
|
|
sizeof(MipMap::Vertex), //
|
|
(void*)offsetof(MipMap::Vertex, s) // offset in array (why is this a pointer...)
|
|
);
|
|
glBindVertexArray(0);
|
|
}
|
|
|
|
OceanTexture::~OceanTexture() {
|
|
destroy_pc();
|
|
}
|
|
|
|
void OceanTexture::init_textures(TexturePool& pool, GameVersion version) {
|
|
TextureInput in;
|
|
in.gpu_texture = m_result_texture.texture();
|
|
in.w = TEX0_SIZE;
|
|
in.h = TEX0_SIZE;
|
|
in.debug_page_name = "PC-OCEAN";
|
|
in.debug_name = fmt::format("pc-ocean-mip-{}", m_generate_mipmaps);
|
|
in.id = pool.allocate_pc_port_texture(version);
|
|
switch (version) {
|
|
case GameVersion::Jak1:
|
|
m_tex0_gpu = pool.give_texture_and_load_to_vram(in, OCEAN_TEX_TBP_JAK1);
|
|
break;
|
|
case GameVersion::Jak2:
|
|
case GameVersion::Jak3:
|
|
m_tex0_gpu = pool.give_texture_and_load_to_vram(in, OCEAN_TEX_TBP_JAK2);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void OceanTexture::draw_debug_window() {
|
|
if (m_tex0_gpu) {
|
|
ImGui::Image((void*)(u64)m_tex0_gpu->gpu_textures.at(0).gl,
|
|
ImVec2(m_tex0_gpu->w, m_tex0_gpu->h));
|
|
}
|
|
}
|
|
|
|
void OceanTexture::handle_ocean_texture_jak1(DmaFollower& dma,
|
|
SharedRenderState* render_state,
|
|
ScopedProfilerNode& prof) {
|
|
// if we're doing mipmaps, render to temp.
|
|
// otherwise, render directly to target.
|
|
FramebufferTexturePairContext ctxt(m_generate_mipmaps ? m_temp_texture : m_result_texture);
|
|
// render to the first texture
|
|
{
|
|
// (set-display-gs-state arg0 ocean-tex-page-0 128 128 0 0)
|
|
auto data = dma.read_and_advance();
|
|
(void)data;
|
|
}
|
|
|
|
// set up VIF
|
|
{
|
|
// (new 'static 'vif-tag :cmd (vif-cmd base))
|
|
// (new 'static 'vif-tag :imm #xc0 :cmd (vif-cmd offset))
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == 0);
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::BASE);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::OFFSET);
|
|
ASSERT(data.vifcode0().immediate == 0);
|
|
ASSERT(data.vifcode1().immediate == 0xc0);
|
|
}
|
|
|
|
// load texture constants
|
|
{
|
|
// (ocean-texture-add-constants arg0)
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == sizeof(OceanTextureConstants));
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::STCYCL);
|
|
ASSERT(data.vifcode0().immediate == 0x404);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
|
ASSERT(data.vifcode1().num == data.size_bytes / 16);
|
|
ASSERT(data.vifcode1().immediate == TexVu1Data::CONSTANTS);
|
|
memcpy(&m_texture_constants, data.data, sizeof(OceanTextureConstants));
|
|
}
|
|
|
|
// set up GS for envmap texture drawing
|
|
{
|
|
// (ocean-texture-add-envmap arg0)
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == sizeof(AdGifData) + 16); // 16 for the giftag.
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::NOP);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::DIRECT);
|
|
memcpy(&m_envmap_adgif, data.data + 16, sizeof(AdGifData));
|
|
// HACK
|
|
setup_renderer();
|
|
}
|
|
|
|
// vertices are uploaded double buffered
|
|
m_texture_vertices_loading = m_texture_vertices_a;
|
|
m_texture_vertices_drawing = m_texture_vertices_b;
|
|
|
|
// add first group of vertices
|
|
{
|
|
// (ocean-texture-add-verts arg0 sv-16)
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == sizeof(m_texture_vertices_a));
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::STCYCL);
|
|
ASSERT(data.vifcode0().immediate == 0x404);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
|
ASSERT(data.vifcode1().num == data.size_bytes / 16);
|
|
VifCodeUnpack up(data.vifcode1());
|
|
ASSERT(up.addr_qw == 0);
|
|
ASSERT(up.use_tops_flag == true);
|
|
memcpy(m_texture_vertices_loading, data.data, sizeof(m_texture_vertices_a));
|
|
}
|
|
|
|
// first call
|
|
{
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == 0);
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::MSCALF);
|
|
ASSERT(data.vifcode0().immediate == TexVu1Prog::START);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
|
run_L1_PC();
|
|
}
|
|
|
|
// loop over vertex groups
|
|
for (int i = 0; i < NUM_FRAG_LOOPS; i++) {
|
|
auto verts = dma.read_and_advance();
|
|
ASSERT(verts.size_bytes == sizeof(m_texture_vertices_a));
|
|
ASSERT(verts.vifcode0().kind == VifCode::Kind::STCYCL);
|
|
ASSERT(verts.vifcode0().immediate == 0x404);
|
|
ASSERT(verts.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
|
ASSERT(verts.vifcode1().num == verts.size_bytes / 16);
|
|
VifCodeUnpack up(verts.vifcode1());
|
|
ASSERT(up.addr_qw == 0);
|
|
ASSERT(up.use_tops_flag == true);
|
|
memcpy(m_texture_vertices_loading, verts.data, sizeof(m_texture_vertices_a));
|
|
|
|
auto call = dma.read_and_advance();
|
|
ASSERT(call.size_bytes == 0);
|
|
ASSERT(call.vifcode0().kind == VifCode::Kind::MSCALF);
|
|
ASSERT(call.vifcode0().immediate == TexVu1Prog::REST);
|
|
ASSERT(call.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
|
run_L2_PC();
|
|
}
|
|
|
|
// last upload does something weird...
|
|
{
|
|
// (ocean-texture-add-verts-last arg0 (the-as (inline-array vector) sv-48) sv-64)
|
|
auto data0 = dma.read_and_advance();
|
|
ASSERT(data0.size_bytes == 128 * 16);
|
|
ASSERT(data0.vifcode0().kind == VifCode::Kind::STCYCL);
|
|
ASSERT(data0.vifcode0().immediate == 0x404);
|
|
ASSERT(data0.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
|
ASSERT(data0.vifcode1().num == data0.size_bytes / 16);
|
|
VifCodeUnpack up0(data0.vifcode1());
|
|
ASSERT(up0.addr_qw == 0);
|
|
ASSERT(up0.use_tops_flag == true);
|
|
memcpy(m_texture_vertices_loading, data0.data, 128 * 16);
|
|
|
|
auto data1 = dma.read_and_advance();
|
|
ASSERT(data1.size_bytes == 64 * 16);
|
|
ASSERT(data1.vifcode0().kind == VifCode::Kind::STCYCL);
|
|
ASSERT(data1.vifcode0().immediate == 0x404);
|
|
ASSERT(data1.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
|
ASSERT(data1.vifcode1().num == data1.size_bytes / 16);
|
|
VifCodeUnpack up1(data1.vifcode1());
|
|
ASSERT(up1.addr_qw == 128);
|
|
ASSERT(up1.use_tops_flag == true);
|
|
memcpy(m_texture_vertices_loading + 128, data1.data, 64 * 16);
|
|
}
|
|
|
|
// last rest call
|
|
{
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == 0);
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::MSCALF);
|
|
ASSERT(data.vifcode0().immediate == TexVu1Prog::REST);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
|
run_L2_PC();
|
|
}
|
|
|
|
// last call
|
|
{
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == 0);
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::MSCALF);
|
|
ASSERT(data.vifcode0().immediate == TexVu1Prog::DONE);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
|
// this program does nothing.
|
|
}
|
|
|
|
flush(render_state, prof);
|
|
if (m_generate_mipmaps) {
|
|
// if we did mipmaps, the above code rendered to temp, and now we need to generate mipmaps
|
|
// in the real output
|
|
make_texture_with_mipmaps(render_state, prof);
|
|
}
|
|
|
|
// give to gpu!
|
|
render_state->texture_pool->move_existing_to_vram(m_tex0_gpu, OCEAN_TEX_TBP_JAK1);
|
|
}
|
|
|
|
void OceanTexture::handle_ocean_texture_jak2(DmaFollower& dma,
|
|
SharedRenderState* render_state,
|
|
ScopedProfilerNode& prof) {
|
|
// if we're doing mipmaps, render to temp.
|
|
// otherwise, render directly to target.
|
|
FramebufferTexturePairContext ctxt(m_generate_mipmaps ? m_temp_texture : m_result_texture);
|
|
// render to the first texture
|
|
{
|
|
// (set-display-gs-state arg0 21 128 128 0 0)
|
|
auto data = dma.read_and_advance();
|
|
(void)data;
|
|
}
|
|
|
|
// set up GS for envmap texture drawing
|
|
{
|
|
// (ocean-texture-add-envmap arg0)
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == sizeof(AdGifData) + 16); // 16 for the giftag.
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::NOP);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::DIRECT);
|
|
memcpy(&m_envmap_adgif, data.data + 16, sizeof(AdGifData));
|
|
// HACK
|
|
setup_renderer();
|
|
}
|
|
|
|
// set up VIF
|
|
{
|
|
// (new 'static 'vif-tag)
|
|
// (new 'static 'vif-tag :imm #x4 :cmd (vif-cmd offset))
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == 64);
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::NOP);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::DIRECT);
|
|
ASSERT(data.vifcode0().immediate == 0);
|
|
ASSERT(data.vifcode1().immediate == 0x4);
|
|
}
|
|
|
|
// (dma-buffer-add-vu-function arg0 ocean-texture-vu1-block 1)
|
|
dma.read_and_advance();
|
|
|
|
{
|
|
// (ocean-texture-add-constants obj arg0)
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == sizeof(OceanTextureConstants));
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::STCYCL);
|
|
ASSERT(data.vifcode0().immediate == 0x404);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
|
ASSERT(data.vifcode1().num == data.size_bytes / 16);
|
|
ASSERT(data.vifcode1().immediate == TexVu1Data::CONSTANTS);
|
|
memcpy(&m_texture_constants, data.data, sizeof(OceanTextureConstants));
|
|
}
|
|
|
|
// vertices are uploaded double buffered
|
|
m_texture_vertices_loading = m_texture_vertices_a;
|
|
m_texture_vertices_drawing = m_texture_vertices_b;
|
|
|
|
// add first group of vertices
|
|
{
|
|
// (ocean-texture-add-verts arg0 sv-16)
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == sizeof(m_texture_vertices_a));
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::STCYCL);
|
|
ASSERT(data.vifcode0().immediate == 0x404);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
|
ASSERT(data.vifcode1().num == data.size_bytes / 16);
|
|
VifCodeUnpack up(data.vifcode1());
|
|
ASSERT(up.addr_qw == 0);
|
|
ASSERT(up.use_tops_flag == true);
|
|
memcpy(m_texture_vertices_loading, data.data, sizeof(m_texture_vertices_a));
|
|
}
|
|
|
|
// first call
|
|
{
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == 0);
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::MSCALF);
|
|
ASSERT(data.vifcode0().immediate == TexVu1Prog::START);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
|
run_L1_PC_jak2();
|
|
}
|
|
|
|
// loop over vertex groups
|
|
for (int i = 0; i < NUM_FRAG_LOOPS; i++) {
|
|
auto verts = dma.read_and_advance();
|
|
ASSERT(verts.size_bytes == sizeof(m_texture_vertices_a));
|
|
ASSERT(verts.vifcode0().kind == VifCode::Kind::STCYCL);
|
|
ASSERT(verts.vifcode0().immediate == 0x404);
|
|
ASSERT(verts.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
|
ASSERT(verts.vifcode1().num == verts.size_bytes / 16);
|
|
VifCodeUnpack up(verts.vifcode1());
|
|
ASSERT(up.addr_qw == 0);
|
|
ASSERT(up.use_tops_flag == true);
|
|
memcpy(m_texture_vertices_loading, verts.data, sizeof(m_texture_vertices_a));
|
|
|
|
auto call = dma.read_and_advance();
|
|
ASSERT(call.size_bytes == 0);
|
|
ASSERT(call.vifcode0().kind == VifCode::Kind::MSCALF);
|
|
ASSERT(call.vifcode0().immediate == TexVu1Prog::REST);
|
|
ASSERT(call.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
|
run_L2_PC_jak2();
|
|
}
|
|
|
|
// last upload does something weird...
|
|
{
|
|
// (ocean-texture-add-verts-last arg0 (the-as (inline-array vector) sv-48) sv-64)
|
|
auto data0 = dma.read_and_advance();
|
|
ASSERT(data0.size_bytes == 128 * 16);
|
|
ASSERT(data0.vifcode0().kind == VifCode::Kind::STCYCL);
|
|
ASSERT(data0.vifcode0().immediate == 0x404);
|
|
ASSERT(data0.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
|
ASSERT(data0.vifcode1().num == data0.size_bytes / 16);
|
|
VifCodeUnpack up0(data0.vifcode1());
|
|
ASSERT(up0.addr_qw == 0);
|
|
ASSERT(up0.use_tops_flag == true);
|
|
memcpy(m_texture_vertices_loading, data0.data, 128 * 16);
|
|
|
|
auto data1 = dma.read_and_advance();
|
|
ASSERT(data1.size_bytes == 64 * 16);
|
|
ASSERT(data1.vifcode0().kind == VifCode::Kind::STCYCL);
|
|
ASSERT(data1.vifcode0().immediate == 0x404);
|
|
ASSERT(data1.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
|
ASSERT(data1.vifcode1().num == data1.size_bytes / 16);
|
|
VifCodeUnpack up1(data1.vifcode1());
|
|
ASSERT(up1.addr_qw == 128);
|
|
ASSERT(up1.use_tops_flag == true);
|
|
memcpy(m_texture_vertices_loading + 128, data1.data, 64 * 16);
|
|
}
|
|
|
|
// last rest call
|
|
{
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == 0);
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::MSCALF);
|
|
ASSERT(data.vifcode0().immediate == TexVu1Prog::REST);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
|
run_L2_PC_jak2();
|
|
}
|
|
|
|
// last call
|
|
{
|
|
auto data = dma.read_and_advance();
|
|
ASSERT(data.size_bytes == 0);
|
|
ASSERT(data.vifcode0().kind == VifCode::Kind::MSCALF);
|
|
ASSERT(data.vifcode0().immediate == TexVu1Prog::DONE);
|
|
ASSERT(data.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
|
// this program does nothing.
|
|
}
|
|
|
|
flush(render_state, prof);
|
|
if (m_generate_mipmaps) {
|
|
// if we did mipmaps, the above code rendered to temp, and now we need to generate mipmaps
|
|
// in the real output
|
|
make_texture_with_mipmaps(render_state, prof);
|
|
}
|
|
|
|
// (reset-display-gs-state *display* arg0)
|
|
// dma.read_and_advance();
|
|
|
|
// give to gpu!
|
|
render_state->texture_pool->move_existing_to_vram(m_tex0_gpu, OCEAN_TEX_TBP_JAK2);
|
|
}
|
|
|
|
/*!
|
|
* Generate mipmaps for the ocean texture.
|
|
* There's a trick here - we reduce the intensity of alpha on the lower lods. This lets texture
|
|
* filtering slowly fade the alpha value out to 0 with distance.
|
|
*/
|
|
void OceanTexture::make_texture_with_mipmaps(SharedRenderState* render_state,
|
|
ScopedProfilerNode& prof) {
|
|
glBindVertexArray(m_mipmap.vao);
|
|
render_state->shaders[ShaderId::OCEAN_TEXTURE_MIPMAP].activate();
|
|
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_TEXTURE_MIPMAP].id(),
|
|
"alpha_intensity"),
|
|
1.0);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, m_temp_texture.texture());
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDisable(GL_BLEND);
|
|
glUniform1i(
|
|
glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_TEXTURE_MIPMAP].id(), "tex_T0"),
|
|
0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, m_mipmap.vtx_buffer);
|
|
|
|
for (int i = 0; i < NUM_MIPS; i++) {
|
|
FramebufferTexturePairContext ctxt(m_result_texture, i);
|
|
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_TEXTURE_MIPMAP].id(),
|
|
"alpha_intensity"),
|
|
std::max(0.f, 1.f - 0.51f * i));
|
|
glUniform1f(
|
|
glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_TEXTURE_MIPMAP].id(), "scale"),
|
|
1.f / (1 << i));
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
prof.add_draw_call();
|
|
prof.add_tri(2);
|
|
}
|
|
glBindVertexArray(0);
|
|
}
|