mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-27 08:20:47 +00:00
optimize ocean renderer (#1240)
This commit is contained in:
parent
8574e10653
commit
da00b1ff13
@ -84,6 +84,7 @@ set(RUNTIME_SOURCE
|
||||
graphics/opengl_renderer/foreground/Generic2_DMA.cpp
|
||||
graphics/opengl_renderer/foreground/Generic2_Build.cpp
|
||||
graphics/opengl_renderer/foreground/Generic2_OpenGL.cpp
|
||||
graphics/opengl_renderer/ocean/CommonOceanRenderer.cpp
|
||||
graphics/opengl_renderer/ocean/OceanMid.cpp
|
||||
graphics/opengl_renderer/ocean/OceanMid_PS2.cpp
|
||||
graphics/opengl_renderer/ocean/OceanMidAndFar.cpp
|
||||
@ -91,7 +92,6 @@ set(RUNTIME_SOURCE
|
||||
graphics/opengl_renderer/ocean/OceanNear_PS2.cpp
|
||||
graphics/opengl_renderer/ocean/OceanTexture.cpp
|
||||
graphics/opengl_renderer/ocean/OceanTexture_PC.cpp
|
||||
graphics/opengl_renderer/ocean/OceanTexture_PS2.cpp
|
||||
graphics/opengl_renderer/BucketRenderer.cpp
|
||||
graphics/opengl_renderer/debug_gui.cpp
|
||||
graphics/opengl_renderer/DirectRenderer.cpp
|
||||
|
@ -113,7 +113,6 @@ void DirectRenderer::reset_state() {
|
||||
}
|
||||
|
||||
void DirectRenderer::draw_debug_window() {
|
||||
ImGui::SliderFloat("debug", &m_debug_tune, 0., 1.);
|
||||
ImGui::Checkbox("Wireframe", &m_debug_state.wireframe);
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("No-texture", &m_debug_state.disable_texture);
|
||||
@ -408,17 +407,6 @@ void DirectRenderer::update_gl_blend() {
|
||||
// ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_my_id == BucketId::OCEAN_NEAR) {
|
||||
if (state.a == GsAlpha::BlendMode::SOURCE && state.b == GsAlpha::BlendMode::DEST &&
|
||||
state.c == GsAlpha::BlendMode::SOURCE && state.d == GsAlpha::BlendMode::DEST) {
|
||||
if (m_prim_gl_state.fogging_enable) {
|
||||
m_ogl.alpha_mult = .5f;
|
||||
} else {
|
||||
glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_ONE, GL_ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DirectRenderer::update_gl_test() {
|
||||
@ -589,9 +577,6 @@ void DirectRenderer::render_gif(const u8* data,
|
||||
case GifTag::RegisterDescriptor::TEX0_1:
|
||||
handle_tex0_1_packed(data + offset);
|
||||
break;
|
||||
case GifTag::RegisterDescriptor::XYZ2:
|
||||
handle_xyz2_packed(data + offset, render_state, prof);
|
||||
break;
|
||||
default:
|
||||
fmt::print("Register {} is not supported in packed mode yet\n",
|
||||
reg_descriptor_name(reg_desc[reg]));
|
||||
@ -799,24 +784,6 @@ void DirectRenderer::handle_xyzf2_packed(const u8* data,
|
||||
handle_xyzf2_common(x << 16, y << 16, z << 8, f, render_state, prof, !adc);
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_xyz2_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
u32 x, y, z;
|
||||
memcpy(&x, data, 4);
|
||||
memcpy(&y, data + 4, 4);
|
||||
memcpy(&z, data + 8, 4);
|
||||
|
||||
u64 upper;
|
||||
memcpy(&upper, data + 8, 8);
|
||||
bool adc = upper & (1ull << 47);
|
||||
float un_mess_up = 448.f / 512.f;
|
||||
// TODO total hack
|
||||
s32 yy = (((s32)y - 1024) << 17) * un_mess_up;
|
||||
handle_xyzf2_common(((x << 2) + 32768 - 2048 * 2) << 16, ((32768) << 16) - yy, z, 0, render_state,
|
||||
prof, !adc);
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_zbuf1(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
|
@ -84,9 +84,6 @@ class DirectRenderer : public BucketRenderer {
|
||||
void handle_xyzf2_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_xyz2_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_tex0_1_packed(const u8* data);
|
||||
void handle_tex0_1(u64 val);
|
||||
void handle_tex1_1(u64 val);
|
||||
@ -153,7 +150,6 @@ class DirectRenderer : public BucketRenderer {
|
||||
|
||||
static constexpr int TEXTURE_STATE_COUNT = 1;
|
||||
|
||||
float m_debug_tune = 1;
|
||||
struct TextureState {
|
||||
GsTex0 current_register;
|
||||
u32 texture_base_ptr = 0;
|
||||
|
@ -80,4 +80,5 @@ ShaderLibrary::ShaderLibrary() {
|
||||
at(ShaderId::GENERIC) = {"generic"};
|
||||
at(ShaderId::OCEAN_TEXTURE) = {"ocean_texture"};
|
||||
at(ShaderId::OCEAN_TEXTURE_MIPMAP) = {"ocean_texture_mipmap"};
|
||||
at(ShaderId::OCEAN_COMMON) = {"ocean_common"};
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ enum class ShaderId {
|
||||
GENERIC = 12,
|
||||
OCEAN_TEXTURE = 13,
|
||||
OCEAN_TEXTURE_MIPMAP = 14,
|
||||
OCEAN_COMMON = 15,
|
||||
MAX_SHADERS
|
||||
};
|
||||
|
||||
|
337
game/graphics/opengl_renderer/ocean/CommonOceanRenderer.cpp
Normal file
337
game/graphics/opengl_renderer/ocean/CommonOceanRenderer.cpp
Normal file
@ -0,0 +1,337 @@
|
||||
#include "CommonOceanRenderer.h"
|
||||
|
||||
CommonOceanRenderer::CommonOceanRenderer() {
|
||||
m_vertices.resize(4096 * 10); // todo decrease
|
||||
for (auto& buf : m_indices) {
|
||||
buf.resize(4096 * 10);
|
||||
}
|
||||
|
||||
// create OpenGL objects
|
||||
glGenBuffers(1, &m_ogl.vertex_buffer);
|
||||
glGenBuffers(NUM_BUCKETS, m_ogl.index_buffer);
|
||||
glGenVertexArrays(1, &m_ogl.vao);
|
||||
|
||||
// set up the vertex array
|
||||
glBindVertexArray(m_ogl.vao);
|
||||
for (int i = 0; i < NUM_BUCKETS; i++) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer[i]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices[i].size() * sizeof(u32), nullptr,
|
||||
GL_STREAM_DRAW);
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_ogl.vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_vertices.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
|
||||
3, // 2 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // normalized, ignored
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, stq) // offset in array
|
||||
);
|
||||
|
||||
// byte data
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribIPointer(3, // location 3 in the shader
|
||||
1, //
|
||||
GL_UNSIGNED_BYTE, // u8's
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, fog) // offset in array
|
||||
);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
CommonOceanRenderer::~CommonOceanRenderer() {
|
||||
glDeleteBuffers(1, &m_ogl.vertex_buffer);
|
||||
glDeleteBuffers(3, m_ogl.index_buffer);
|
||||
glDeleteVertexArrays(1, &m_ogl.vao);
|
||||
}
|
||||
|
||||
void CommonOceanRenderer::init_for_near() {
|
||||
m_next_free_vertex = 0;
|
||||
for (auto& x : m_next_free_index) {
|
||||
x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CommonOceanRenderer::kick_from_near(const u8* data) {
|
||||
bool eop = false;
|
||||
|
||||
u32 offset = 0;
|
||||
while (!eop) {
|
||||
GifTag tag(data + offset);
|
||||
offset += 16;
|
||||
|
||||
if (tag.nreg() == 3) {
|
||||
ASSERT(tag.pre());
|
||||
if (GsPrim(tag.prim()).kind() == GsPrim::Kind::TRI_STRIP) {
|
||||
handle_near_vertex_gif_data_strip(data, offset, tag.nloop());
|
||||
} else {
|
||||
handle_near_vertex_gif_data_fan(data, offset, tag.nloop());
|
||||
}
|
||||
offset += 16 * 3 * tag.nloop();
|
||||
} else if (tag.nreg() == 1) {
|
||||
handle_near_adgif(data, offset, tag.nloop());
|
||||
offset += 16 * 1 * tag.nloop();
|
||||
} else {
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
eop = tag.eop();
|
||||
}
|
||||
}
|
||||
|
||||
void CommonOceanRenderer::handle_near_vertex_gif_data_strip(const u8* data, u32 offset, u32 loop) {
|
||||
m_indices[m_current_bucket][m_next_free_index[m_current_bucket]++] = UINT32_MAX;
|
||||
bool reset_last = false;
|
||||
for (u32 i = 0; i < loop; i++) {
|
||||
auto& dest_vert = m_vertices[m_next_free_vertex++];
|
||||
|
||||
// stq
|
||||
memcpy(dest_vert.stq.data(), data + offset, 12);
|
||||
offset += 16;
|
||||
|
||||
// rgba
|
||||
dest_vert.rgba[0] = data[offset];
|
||||
dest_vert.rgba[1] = data[offset + 4];
|
||||
dest_vert.rgba[2] = data[offset + 8];
|
||||
dest_vert.rgba[3] = data[offset + 12];
|
||||
offset += 16;
|
||||
|
||||
// xyz
|
||||
u32 x = 0, y = 0;
|
||||
memcpy(&x, data + offset, 4);
|
||||
memcpy(&y, data + offset + 4, 4);
|
||||
|
||||
u64 upper;
|
||||
memcpy(&upper, data + offset + 8, 8);
|
||||
u32 z = (upper >> 4) & 0xffffff;
|
||||
offset += 16;
|
||||
|
||||
dest_vert.xyz[0] = (float)(x << 16) / (float)UINT32_MAX;
|
||||
dest_vert.xyz[1] = (float)(y << 16) / (float)UINT32_MAX;
|
||||
dest_vert.xyz[2] = (float)(z << 8) / (float)UINT32_MAX;
|
||||
|
||||
u8 f = (upper >> 36);
|
||||
dest_vert.fog = f;
|
||||
|
||||
auto vidx = m_next_free_vertex - 1;
|
||||
bool adc = upper & (1ull << 47);
|
||||
if (!adc) {
|
||||
m_indices[m_current_bucket][m_next_free_index[m_current_bucket]++] = vidx;
|
||||
reset_last = false;
|
||||
} else {
|
||||
if (reset_last) {
|
||||
m_next_free_index[m_current_bucket] -= 3;
|
||||
}
|
||||
m_indices[m_current_bucket][m_next_free_index[m_current_bucket]++] = UINT32_MAX;
|
||||
m_indices[m_current_bucket][m_next_free_index[m_current_bucket]++] = vidx - 1;
|
||||
m_indices[m_current_bucket][m_next_free_index[m_current_bucket]++] = vidx;
|
||||
reset_last = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommonOceanRenderer::handle_near_vertex_gif_data_fan(const u8* data, u32 offset, u32 loop) {
|
||||
u32 ind_of_fan_start = UINT32_MAX;
|
||||
bool fan_running = false;
|
||||
// :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2 (gif-reg-id xyzf2)
|
||||
for (u32 i = 0; i < loop; i++) {
|
||||
auto& dest_vert = m_vertices[m_next_free_vertex++];
|
||||
|
||||
// stq
|
||||
memcpy(dest_vert.stq.data(), data + offset, 12);
|
||||
offset += 16;
|
||||
|
||||
// rgba
|
||||
dest_vert.rgba[0] = data[offset];
|
||||
dest_vert.rgba[1] = data[offset + 4];
|
||||
dest_vert.rgba[2] = data[offset + 8];
|
||||
dest_vert.rgba[3] = data[offset + 12];
|
||||
offset += 16;
|
||||
|
||||
// xyz
|
||||
u32 x = 0, y = 0;
|
||||
memcpy(&x, data + offset, 4);
|
||||
memcpy(&y, data + offset + 4, 4);
|
||||
|
||||
u64 upper;
|
||||
memcpy(&upper, data + offset + 8, 8);
|
||||
u32 z = (upper >> 4) & 0xffffff;
|
||||
offset += 16;
|
||||
|
||||
dest_vert.xyz[0] = (float)(x << 16) / (float)UINT32_MAX;
|
||||
dest_vert.xyz[1] = (float)(y << 16) / (float)UINT32_MAX;
|
||||
dest_vert.xyz[2] = (float)(z << 8) / (float)UINT32_MAX;
|
||||
|
||||
u8 f = (upper >> 36);
|
||||
dest_vert.fog = f;
|
||||
|
||||
auto vidx = m_next_free_vertex - 1;
|
||||
|
||||
if (ind_of_fan_start == UINT32_MAX) {
|
||||
ind_of_fan_start = vidx;
|
||||
} else {
|
||||
if (fan_running) {
|
||||
// hack to draw fans with strips. this isn't efficient, but fans happen extremely rarely
|
||||
// (you basically have to put the camera intersecting the ocean and looking fwd)
|
||||
m_indices[m_current_bucket][m_next_free_index[m_current_bucket]++] = UINT32_MAX;
|
||||
m_indices[m_current_bucket][m_next_free_index[m_current_bucket]++] = vidx;
|
||||
m_indices[m_current_bucket][m_next_free_index[m_current_bucket]++] = vidx - 1;
|
||||
m_indices[m_current_bucket][m_next_free_index[m_current_bucket]++] = ind_of_fan_start;
|
||||
} else {
|
||||
fan_running = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommonOceanRenderer::handle_near_adgif(const u8* data, u32 offset, u32 count) {
|
||||
u32 most_recent_tbp = 0;
|
||||
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
u64 value;
|
||||
GsRegisterAddress addr;
|
||||
memcpy(&value, data + offset + 16 * i, sizeof(u64));
|
||||
memcpy(&addr, data + offset + 16 * i + 8, sizeof(GsRegisterAddress));
|
||||
switch (addr) {
|
||||
case GsRegisterAddress::MIPTBP1_1:
|
||||
// ignore this, it's just mipmapping settings
|
||||
break;
|
||||
case GsRegisterAddress::TEX1_1: {
|
||||
GsTex1 reg(value);
|
||||
ASSERT(reg.mmag());
|
||||
} break;
|
||||
case GsRegisterAddress::CLAMP_1: {
|
||||
bool s = value & 0b001;
|
||||
bool t = value & 0b100;
|
||||
ASSERT(s == t);
|
||||
if (s) {
|
||||
m_current_bucket = VertexBucket::ENV_MAP;
|
||||
}
|
||||
} break;
|
||||
case GsRegisterAddress::TEX0_1: {
|
||||
GsTex0 reg(value);
|
||||
ASSERT(reg.tfx() == GsTex0::TextureFunction::MODULATE);
|
||||
if (!reg.tcc()) {
|
||||
m_current_bucket = VertexBucket::RGB_TEXTURE;
|
||||
}
|
||||
most_recent_tbp = reg.tbp0();
|
||||
} break;
|
||||
case GsRegisterAddress::ALPHA_1: {
|
||||
// ignore, we've hardcoded alphas.
|
||||
} break;
|
||||
case GsRegisterAddress::FRAME_1: {
|
||||
u32 mask = value >> 32;
|
||||
if (mask) {
|
||||
m_current_bucket = VertexBucket::ALPHA;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
fmt::print("reg: {}\n", register_address_name(addr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_current_bucket == VertexBucket::ENV_MAP) {
|
||||
m_envmap_tex = most_recent_tbp;
|
||||
}
|
||||
|
||||
if (m_vertices.size() - 128 < m_next_free_vertex) {
|
||||
ASSERT(false); // add more vertices.
|
||||
}
|
||||
}
|
||||
|
||||
void CommonOceanRenderer::flush(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
glBindVertexArray(m_ogl.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_ogl.vertex_buffer);
|
||||
glEnable(GL_PRIMITIVE_RESTART);
|
||||
glPrimitiveRestartIndex(UINT32_MAX);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_next_free_vertex * sizeof(Vertex), m_vertices.data(),
|
||||
GL_STREAM_DRAW);
|
||||
render_state->shaders[ShaderId::OCEAN_COMMON].activate();
|
||||
glUniform4f(glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_COMMON].id(), "fog_color"),
|
||||
render_state->fog_color[0], render_state->fog_color[1], render_state->fog_color[2],
|
||||
render_state->fog_intensity);
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
|
||||
for (int bucket = 0; bucket < 3; bucket++) {
|
||||
switch (bucket) {
|
||||
case 0: {
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
auto tex = render_state->texture_pool->lookup(8160);
|
||||
if (!tex) {
|
||||
tex = render_state->texture_pool->get_placeholder_texture();
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, *tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glUniform1i(
|
||||
glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_COMMON].id(), "tex_T0"), 0);
|
||||
glUniform1i(
|
||||
glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_COMMON].id(), "bucket"), 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
||||
break;
|
||||
case 1:
|
||||
glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_ONE, GL_ZERO);
|
||||
glUniform1f(
|
||||
glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_COMMON].id(), "alpha_mult"),
|
||||
1.f);
|
||||
glUniform1i(
|
||||
glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_COMMON].id(), "bucket"), 1);
|
||||
break;
|
||||
case 2:
|
||||
auto tex = render_state->texture_pool->lookup(m_envmap_tex);
|
||||
if (!tex) {
|
||||
tex = render_state->texture_pool->get_placeholder_texture();
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, *tex);
|
||||
|
||||
glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_ONE, GL_ZERO);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glUniform1i(
|
||||
glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_COMMON].id(), "bucket"), 2);
|
||||
break;
|
||||
}
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer[bucket]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_next_free_index[bucket] * sizeof(u32),
|
||||
m_indices[bucket].data(), GL_STREAM_DRAW);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, m_next_free_index[bucket], GL_UNSIGNED_INT, nullptr);
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(m_next_free_index[bucket]);
|
||||
}
|
||||
}
|
48
game/graphics/opengl_renderer/ocean/CommonOceanRenderer.h
Normal file
48
game/graphics/opengl_renderer/ocean/CommonOceanRenderer.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
|
||||
class CommonOceanRenderer {
|
||||
public:
|
||||
CommonOceanRenderer();
|
||||
~CommonOceanRenderer();
|
||||
|
||||
void init_for_near();
|
||||
void kick_from_near(const u8* data);
|
||||
void flush(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
private:
|
||||
void handle_near_vertex_gif_data_fan(const u8* data, u32 offset, u32 loop);
|
||||
void handle_near_vertex_gif_data_strip(const u8* data, u32 offset, u32 loop);
|
||||
|
||||
void handle_near_adgif(const u8* data, u32 offset, u32 count);
|
||||
|
||||
enum VertexBucket {
|
||||
RGB_TEXTURE = 0,
|
||||
ALPHA = 1,
|
||||
ENV_MAP = 2,
|
||||
};
|
||||
u32 m_current_bucket = VertexBucket::RGB_TEXTURE;
|
||||
|
||||
struct Vertex {
|
||||
math::Vector<float, 3> xyz;
|
||||
math::Vector<u8, 4> rgba;
|
||||
math::Vector<float, 3> stq;
|
||||
u8 fog;
|
||||
u8 pad[3];
|
||||
};
|
||||
static_assert(sizeof(Vertex) == 32);
|
||||
|
||||
static constexpr int NUM_BUCKETS = 3;
|
||||
|
||||
std::vector<Vertex> m_vertices;
|
||||
u32 m_next_free_vertex = 0;
|
||||
|
||||
std::vector<u32> m_indices[NUM_BUCKETS];
|
||||
u32 m_next_free_index[NUM_BUCKETS] = {0};
|
||||
|
||||
u32 m_envmap_tex = 0;
|
||||
|
||||
struct {
|
||||
GLuint vertex_buffer, index_buffer[NUM_BUCKETS], vao;
|
||||
} m_ogl;
|
||||
};
|
@ -1,4 +1,5 @@
|
||||
#include "OceanNear.h"
|
||||
#include "third-party/imgui/imgui.h"
|
||||
|
||||
OceanNear::OceanNear(const std::string& name, BucketId my_id)
|
||||
: BucketRenderer(name, my_id), m_texture_renderer(false), m_direct(name, my_id, 0x4000) {
|
||||
@ -8,6 +9,7 @@ OceanNear::OceanNear(const std::string& name, BucketId my_id)
|
||||
}
|
||||
|
||||
void OceanNear::draw_debug_window() {
|
||||
ImGui::Checkbox("New", &m_use_new);
|
||||
m_direct.draw_debug_window();
|
||||
}
|
||||
|
||||
@ -62,13 +64,20 @@ void OceanNear::render(DmaFollower& dma,
|
||||
}
|
||||
|
||||
// direct setup
|
||||
m_direct.reset_state();
|
||||
{
|
||||
if (m_use_new) {
|
||||
m_common_ocean_renderer.init_for_near();
|
||||
} else {
|
||||
m_direct.reset_state();
|
||||
}
|
||||
auto setup = dma.read_and_advance();
|
||||
ASSERT(setup.vifcode0().kind == VifCode::Kind::NOP);
|
||||
ASSERT(setup.vifcode1().kind == VifCode::Kind::DIRECT);
|
||||
ASSERT(setup.size_bytes == 32);
|
||||
m_direct.render_gif(setup.data, 32, render_state, prof);
|
||||
if (m_use_new) {
|
||||
} else {
|
||||
m_direct.render_gif(setup.data, 32, render_state, prof);
|
||||
}
|
||||
}
|
||||
|
||||
// oofset and base
|
||||
@ -113,5 +122,18 @@ void OceanNear::render(DmaFollower& dma,
|
||||
while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
m_direct.flush_pending(render_state, prof);
|
||||
|
||||
if (m_use_new) {
|
||||
m_common_ocean_renderer.flush(render_state, prof);
|
||||
} else {
|
||||
m_direct.flush_pending(render_state, prof);
|
||||
}
|
||||
}
|
||||
|
||||
void OceanNear::xgkick(u16 addr, SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
if (m_use_new) {
|
||||
m_common_ocean_renderer.kick_from_near((const u8*)&m_vu_data[addr]);
|
||||
} else {
|
||||
m_direct.render_gif((const u8*)&m_vu_data[addr], UINT32_MAX, render_state, prof);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/ocean/OceanTexture.h"
|
||||
#include "game/common/vu.h"
|
||||
#include "game/graphics/opengl_renderer/ocean/CommonOceanRenderer.h"
|
||||
|
||||
class OceanNear : public BucketRenderer {
|
||||
public:
|
||||
@ -23,11 +24,14 @@ class OceanNear : public BucketRenderer {
|
||||
|
||||
OceanTexture m_texture_renderer;
|
||||
DirectRenderer m_direct;
|
||||
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 = 0x10;
|
||||
|
||||
bool m_use_new = true;
|
||||
|
||||
void xgkick(u16 addr, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
u16 xtop() {
|
||||
|
@ -1,9 +1,5 @@
|
||||
#include "OceanNear.h"
|
||||
|
||||
void OceanNear::xgkick(u16 addr, SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
m_direct.render_gif((const u8*)&m_vu_data[addr], UINT32_MAX, render_state, prof);
|
||||
}
|
||||
|
||||
void OceanNear::run_call0_vu2c() {
|
||||
bool bc;
|
||||
// lq.xyzw vf01, 951(vi00) | nop 0
|
||||
|
@ -9,8 +9,7 @@ OceanTexture::OceanTexture(bool generate_mipmaps)
|
||||
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_hack_renderer("ocean-tex-unoptimized", BucketId::BUCKET0, 0x8000) {
|
||||
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;
|
||||
|
||||
@ -66,40 +65,6 @@ void OceanTexture::draw_debug_window() {
|
||||
if (m_tex0_gpu) {
|
||||
ImGui::Image((void*)m_tex0_gpu->gpu_textures.at(0).gl, ImVec2(m_tex0_gpu->w, m_tex0_gpu->h));
|
||||
}
|
||||
ImGui::Checkbox("Optimized Version", &m_use_ocean_specific);
|
||||
}
|
||||
|
||||
void OceanTexture::flush(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
if (m_use_ocean_specific) {
|
||||
flush_pc(render_state, prof);
|
||||
} else {
|
||||
m_hack_renderer.flush_pending(render_state, prof);
|
||||
}
|
||||
}
|
||||
|
||||
void OceanTexture::setup_renderer() {
|
||||
if (m_use_ocean_specific) {
|
||||
setup_pc();
|
||||
} else {
|
||||
m_hack_renderer.reset_state();
|
||||
}
|
||||
}
|
||||
|
||||
void OceanTexture::handle_tex_call_start(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
if (m_use_ocean_specific) {
|
||||
run_L1_PC();
|
||||
} else {
|
||||
run_L1(render_state, prof);
|
||||
}
|
||||
}
|
||||
|
||||
void OceanTexture::handle_tex_call_rest(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
if (m_use_ocean_specific) {
|
||||
run_L2_PC();
|
||||
} else {
|
||||
run_L2(render_state, prof);
|
||||
}
|
||||
}
|
||||
|
||||
void OceanTexture::handle_ocean_texture(DmaFollower& dma,
|
||||
@ -148,27 +113,8 @@ void OceanTexture::handle_ocean_texture(DmaFollower& dma,
|
||||
ASSERT(data.vifcode0().kind == VifCode::Kind::NOP);
|
||||
ASSERT(data.vifcode1().kind == VifCode::Kind::DIRECT);
|
||||
memcpy(&m_envmap_adgif, data.data + 16, sizeof(AdGifData));
|
||||
|
||||
// fmt::print("adgif is:\n{}\n\n", AdgifHelper(m_envmap_adgif).print());
|
||||
/*
|
||||
* adgif is:
|
||||
[0] TEX0_1
|
||||
tbp0: 10010 tbw: 2 psm: 19 tw: 6 th: 6 tcc: 1 tfx: 0 cbp: 10046 cpsm: 0 csm: 0
|
||||
[1] TEX1_1
|
||||
lcm: false mxl: 0 mmag: true mmin: 4 mtba: false l: 0 k: 0
|
||||
[2] MIPTBP1_1
|
||||
[3] CLAMP_1
|
||||
0x5
|
||||
[4] ALPHA_1
|
||||
(Cs - Cd) * As / 128.0 + Cd
|
||||
|
||||
*/
|
||||
|
||||
// HACK
|
||||
setup_renderer();
|
||||
if (!m_use_ocean_specific) {
|
||||
m_hack_renderer.render_gif(data.data, UINT32_MAX, render_state, prof);
|
||||
}
|
||||
}
|
||||
|
||||
// vertices are uploaded double buffered
|
||||
@ -197,7 +143,7 @@ void OceanTexture::handle_ocean_texture(DmaFollower& dma,
|
||||
ASSERT(data.vifcode0().kind == VifCode::Kind::MSCALF);
|
||||
ASSERT(data.vifcode0().immediate == TexVu1Prog::START);
|
||||
ASSERT(data.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
||||
handle_tex_call_start(render_state, prof);
|
||||
run_L1_PC();
|
||||
}
|
||||
|
||||
// loop over vertex groups
|
||||
@ -218,7 +164,7 @@ void OceanTexture::handle_ocean_texture(DmaFollower& dma,
|
||||
ASSERT(call.vifcode0().kind == VifCode::Kind::MSCALF);
|
||||
ASSERT(call.vifcode0().immediate == TexVu1Prog::REST);
|
||||
ASSERT(call.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
||||
handle_tex_call_rest(render_state, prof);
|
||||
run_L2_PC();
|
||||
}
|
||||
|
||||
// last upload does something weird...
|
||||
@ -254,7 +200,7 @@ void OceanTexture::handle_ocean_texture(DmaFollower& dma,
|
||||
ASSERT(data.vifcode0().kind == VifCode::Kind::MSCALF);
|
||||
ASSERT(data.vifcode0().immediate == TexVu1Prog::REST);
|
||||
ASSERT(data.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
||||
handle_tex_call_rest(render_state, prof);
|
||||
run_L2_PC();
|
||||
}
|
||||
|
||||
// last call
|
||||
|
@ -16,15 +16,6 @@ class OceanTexture {
|
||||
~OceanTexture();
|
||||
|
||||
private:
|
||||
void handle_tex_call_start(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_tex_call_rest(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
void run_L1(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void run_L2(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void run_L3();
|
||||
void run_L5(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void xgkick(Vf* src, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
void run_L1_PC();
|
||||
void run_L2_PC();
|
||||
void run_L3_PC();
|
||||
@ -34,14 +25,11 @@ class OceanTexture {
|
||||
void setup_renderer();
|
||||
void flush(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
void setup_pc();
|
||||
void flush_pc(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void init_pc();
|
||||
void destroy_pc();
|
||||
|
||||
void make_texture_with_mipmaps(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
bool m_use_ocean_specific = true;
|
||||
bool m_generate_mipmaps;
|
||||
|
||||
static constexpr int TEX0_SIZE = 128;
|
||||
@ -161,6 +149,4 @@ class OceanTexture {
|
||||
enum TexVu1Prog { START = 0, REST = 2, DONE = 4 };
|
||||
|
||||
static constexpr int NUM_FRAG_LOOPS = 9;
|
||||
|
||||
DirectRenderer m_hack_renderer;
|
||||
};
|
||||
|
@ -394,11 +394,11 @@ void OceanTexture::xgkick_PC(Vf* src) {
|
||||
}
|
||||
}
|
||||
|
||||
void OceanTexture::setup_pc() {
|
||||
void OceanTexture::setup_renderer() {
|
||||
m_pc.vtx_idx = 0;
|
||||
}
|
||||
|
||||
void OceanTexture::flush_pc(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
void OceanTexture::flush(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
ASSERT(m_pc.vtx_idx == 2112);
|
||||
glBindVertexArray(m_pc.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_pc.dynamic_vertex_buffer);
|
||||
|
@ -1,378 +0,0 @@
|
||||
#include "OceanTexture.h"
|
||||
|
||||
void OceanTexture::run_L1(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
// L1:
|
||||
// lq.xyzw vf14_startx, 988(vi00) | maxw.xyzw vf01_ones, vf00, vf00
|
||||
vu.startx = Vf(m_texture_constants.start);
|
||||
// lq.xyzw vf02_offset, 989(vi00)
|
||||
// lq.xyzw vf03_tbuf, 986(vi00)
|
||||
// lq.xyzw vf04_dbuf, 987(vi00)
|
||||
// lq.xyzw vf05_giftag, 985(vi00)
|
||||
// lq.xyzw vf06_cam_nrm, 991(vi00)
|
||||
// lq.xyzw vf07_constants, 990(vi00)
|
||||
// iaddiu vi11_0x80, vi00, 0x80
|
||||
// mtir vi08_tptr, vf03_tbuf.x
|
||||
vu.tptr = get_tbuf();
|
||||
// mtir vi09_tbase, vf03_tbuf.x
|
||||
vu.tbase = get_tbuf();
|
||||
// mr32.xyzw vf03_tbuf, vf03_tbuf
|
||||
swap_tbuf();
|
||||
// xtop vi05_in_ptr
|
||||
vu.in_ptr = swap_vu_upload_buffers();
|
||||
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3();
|
||||
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3();
|
||||
|
||||
// mtir vi03_dbuf_read_a, vf04_dbuf.x
|
||||
vu.dbuf_read_a = get_dbuf();
|
||||
// bal vi12_ra, L5
|
||||
// mtir vi04_dbuf_read_b, vf04_dbuf.y
|
||||
vu.dbuf_read_b = get_dbuf_other();
|
||||
run_L5(render_state, prof);
|
||||
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3();
|
||||
|
||||
// mtir vi03_dbuf_read_a, vf04_dbuf.x
|
||||
vu.dbuf_read_a = get_dbuf();
|
||||
// bal vi12_ra, L5
|
||||
// mtir vi04_dbuf_read_b, vf04_dbuf.y
|
||||
vu.dbuf_read_b = get_dbuf_other();
|
||||
run_L5(render_state, prof);
|
||||
|
||||
// nop :e
|
||||
// nop
|
||||
}
|
||||
|
||||
void OceanTexture::run_L2(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
// L2:
|
||||
// xtop vi05_in_ptr
|
||||
vu.in_ptr = swap_vu_upload_buffers();
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3();
|
||||
|
||||
// mtir vi03_dbuf_read_a, vf04_dbuf.x
|
||||
vu.dbuf_read_a = get_dbuf();
|
||||
// bal vi12_ra, L5
|
||||
// mtir vi04_dbuf_read_b, vf04_dbuf.y
|
||||
vu.dbuf_read_b = get_dbuf_other();
|
||||
run_L5(render_state, prof);
|
||||
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3();
|
||||
|
||||
// mtir vi03_dbuf_read_a, vf04_dbuf.x
|
||||
vu.dbuf_read_a = get_dbuf();
|
||||
// bal vi12_ra, L5
|
||||
// mtir vi04_dbuf_read_b, vf04_dbuf.y
|
||||
vu.dbuf_read_b = get_dbuf_other();
|
||||
run_L5(render_state, prof);
|
||||
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3();
|
||||
|
||||
// mtir vi03_dbuf_read_a, vf04_dbuf.x
|
||||
vu.dbuf_read_a = get_dbuf();
|
||||
// bal vi12_ra, L5
|
||||
// mtir vi04_dbuf_read_b, vf04_dbuf.y
|
||||
vu.dbuf_read_b = get_dbuf_other();
|
||||
run_L5(render_state, prof);
|
||||
|
||||
// nop :e
|
||||
// nop
|
||||
}
|
||||
|
||||
namespace {
|
||||
void lq_buffer(Mask mask, Vf& dest, Vf* src) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
dest.data[i] = src->data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sq_buffer(Mask mask, const Vf& src, Vf* dest) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
dest->data[i] = src.data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sq_buffer_giftag(const u8* src, Vf* dest) {
|
||||
memcpy(dest, src, 16);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void OceanTexture::run_L3() {
|
||||
Vf base_pos; // vf15
|
||||
u16 loop_idx;
|
||||
|
||||
Vf vtx0; // vf16
|
||||
Vf vtx1; // vf17
|
||||
Vf vtx2; // vf18
|
||||
Vf vtx3; // vf19
|
||||
|
||||
Vf res0; // vf20
|
||||
Vf res1; // vf21
|
||||
Vf res2; // vf22
|
||||
Vf res3; // vf23
|
||||
|
||||
Vf nrm0; // vf24
|
||||
Vf nrm1; // vf25
|
||||
Vf nrm2; // vf26
|
||||
|
||||
Vf reflect; // vf27
|
||||
|
||||
Vf cout0; // vf28
|
||||
Vf cout1; // vf29
|
||||
Vf cout2; // vf30
|
||||
Vf cout3; // vf31
|
||||
|
||||
Accumulator acc;
|
||||
const Vf ones(1, 1, 1, 1);
|
||||
const Vf vf00(0, 0, 0, 1);
|
||||
const u16 vi11 = 0x80;
|
||||
bool bc;
|
||||
|
||||
// clang-format off
|
||||
// L3:
|
||||
// ior vi07, vi06, vi00 | nop 56
|
||||
vu.dbuf_write_base = vu.dbuf_write;
|
||||
// move.xyzw vf15, vf14 | nop 57
|
||||
base_pos.move(Mask::xyzw, vu.startx);
|
||||
// iaddi vi01, vi00, 0x8 | nop 58
|
||||
loop_idx = 8;
|
||||
// lq.xyzw vf24, 1(vi05) | mulw.xyzw vf20, vf15, vf00 59 (?? what are they doing here)
|
||||
res0.mul(Mask::xyzw, base_pos, 1.f); lq_buffer(Mask::xyzw, nrm0, vu.in_ptr + 1);
|
||||
// lq.xyzw vf25, 3(vi05) | mulw.xyzw vf21, vf15, vf00 60
|
||||
res1.mul(Mask::xyzw, base_pos, 1.f); lq_buffer(Mask::xyzw, nrm1, vu.in_ptr + 3);
|
||||
// lq.xyzw vf26, 5(vi05) | mulw.xyzw vf22, vf15, vf00 61
|
||||
res2.mul(Mask::xyzw, base_pos, 1.f); lq_buffer(Mask::xyzw, nrm2, vu.in_ptr + 5);
|
||||
// nop | mulw.xyzw vf23, vf15, vf00 62
|
||||
res3.mul(Mask::xyzw, base_pos, 1.f);
|
||||
// nop | mulax.xyzw ACC, vf24, vf06 63
|
||||
acc.mula(Mask::xyzw, nrm0, m_texture_constants.cam_nrm.x());
|
||||
// nop | madday.xyzw ACC, vf25, vf06 64
|
||||
acc.madda(Mask::xyzw, nrm1, m_texture_constants.cam_nrm.y());
|
||||
// nop | maddz.xyzw vf27, vf26, vf06 65
|
||||
acc.madd(Mask::xyzw, reflect, nrm2, m_texture_constants.cam_nrm.z());
|
||||
// nop | addx.x vf21, vf21, vf02 66
|
||||
res1.add(Mask::x, res1, m_texture_constants.offsets.x());
|
||||
// nop | addy.x vf22, vf22, vf02 67
|
||||
res2.add(Mask::x, res2, m_texture_constants.offsets.y());
|
||||
L4:
|
||||
// nop | addz.x vf23, vf23, vf02 68
|
||||
res3.add(Mask::x, res3, m_texture_constants.offsets.z());
|
||||
// nop | addw.x vf15, vf15, vf02 69
|
||||
base_pos.add(Mask::x, base_pos, m_texture_constants.offsets.w());
|
||||
// sq.xyzw vf20, 2(vi06) | mulx.x vf28, vf01, vf24 70
|
||||
cout0.mul(Mask::x, ones, nrm0.x()); sq_buffer(Mask::xyzw, res0, vu.dbuf_write + 2);
|
||||
// sq.xyzw vf21, 5(vi06) | muly.x vf29, vf01, vf24 71
|
||||
cout1.mul(Mask::x, ones, nrm0.y()); sq_buffer(Mask::xyzw, res1, vu.dbuf_write + 5);
|
||||
// sq.xyzw vf22, 8(vi06) | mulz.x vf30, vf01, vf24 72
|
||||
cout2.mul(Mask::x, ones, nrm0.z()); sq_buffer(Mask::xyzw, res2, vu.dbuf_write + 8);
|
||||
// sq.xyzw vf23, 11(vi06) | mulw.x vf31, vf01, vf24 73
|
||||
cout3.mul(Mask::x, ones, nrm0.w()); sq_buffer(Mask::xyzw, res3, vu.dbuf_write + 11);
|
||||
// lq.xyzw vf16, 0(vi05) | mulx.y vf28, vf01, vf25 74
|
||||
cout0.mul(Mask::y, ones, nrm1.x()); lq_buffer(Mask::xyzw, vtx0, vu.in_ptr);
|
||||
// lq.xyzw vf17, 2(vi05) | muly.y vf29, vf01, vf25 75
|
||||
cout1.mul(Mask::y, ones, nrm1.y()); lq_buffer(Mask::xyzw, vtx1, vu.in_ptr + 2);
|
||||
// lq.xyzw vf18, 4(vi05) | mulz.y vf30, vf01, vf25 76
|
||||
cout2.mul(Mask::y, ones, nrm1.z()); lq_buffer(Mask::xyzw, vtx2, vu.in_ptr + 4);
|
||||
// lq.xyzw vf19, 6(vi05) | mulw.y vf31, vf01, vf25 77
|
||||
cout3.mul(Mask::y, ones, nrm1.w()); lq_buffer(Mask::xyzw, vtx3, vu.in_ptr + 6);
|
||||
// iaddi vi05, vi05, 0x8 | mulx.xy vf28, vf28, vf27 78
|
||||
cout0.mul(Mask::xy, cout0, reflect.x()); vu.in_ptr = vu.in_ptr + 8;
|
||||
// nop | muly.xy vf29, vf29, vf27 79
|
||||
cout1.mul(Mask::xy, cout1, reflect.y());
|
||||
// nop | mulz.xy vf30, vf30, vf27 80
|
||||
cout2.mul(Mask::xy, cout2, reflect.z());
|
||||
// nop | mulw.xy vf31, vf31, vf27 81
|
||||
cout3.mul(Mask::xy, cout3, reflect.w());
|
||||
// nop | mulw.xy vf28, vf28, vf16 82
|
||||
cout0.mul(Mask::xy, cout0, vtx0.w());
|
||||
// nop | mulw.xy vf29, vf29, vf17 83
|
||||
cout1.mul(Mask::xy, cout1, vtx1.w());
|
||||
// nop | mulw.xy vf30, vf30, vf18 84
|
||||
cout2.mul(Mask::xy, cout2, vtx2.w());
|
||||
// nop | mulw.xy vf31, vf31, vf19 85
|
||||
cout3.mul(Mask::xy, cout3, vtx3.w());
|
||||
// nop | ftoi0.xyzw vf16, vf16 86
|
||||
vtx0.ftoi0(Mask::xyzw, vtx0);
|
||||
// nop | ftoi0.xyzw vf17, vf17 87
|
||||
vtx1.ftoi0(Mask::xyzw, vtx1);
|
||||
// nop | ftoi0.xyzw vf18, vf18 88
|
||||
vtx2.ftoi0(Mask::xyzw, vtx2);
|
||||
// iaddi vi01, vi01, -0x1 | ftoi0.xyzw vf19, vf19 89
|
||||
vtx3.ftoi0(Mask::xyzw, vtx3); loop_idx = loop_idx + -1;
|
||||
// mfir.w vf16, vi11 | add.xyzw vf28, vf28, vf06 90
|
||||
cout0.add(Mask::xyzw, cout0, m_texture_constants.cam_nrm); vtx0.mfir(Mask::w, vi11);
|
||||
// mfir.w vf17, vi11 | add.xyzw vf29, vf29, vf06 91
|
||||
cout1.add(Mask::xyzw, cout1, m_texture_constants.cam_nrm); vtx1.mfir(Mask::w, vi11);
|
||||
// mfir.w vf18, vi11 | add.xyzw vf30, vf30, vf06 92
|
||||
cout2.add(Mask::xyzw, cout2, m_texture_constants.cam_nrm); vtx2.mfir(Mask::w, vi11);
|
||||
// mfir.w vf19, vi11 | add.xyzw vf31, vf31, vf06 93
|
||||
cout3.add(Mask::xyzw, cout3, m_texture_constants.cam_nrm); vtx3.mfir(Mask::w, vi11);
|
||||
// nop | mulx.xyzw vf28, vf28, vf07 94
|
||||
cout0.mul(Mask::xyzw, cout0, m_texture_constants.constants.x());
|
||||
// nop | mulx.xyzw vf29, vf29, vf07 95
|
||||
cout1.mul(Mask::xyzw, cout1, m_texture_constants.constants.x());
|
||||
// nop | mulx.xyzw vf30, vf30, vf07 96
|
||||
cout2.mul(Mask::xyzw, cout2, m_texture_constants.constants.x());
|
||||
// nop | mulx.xyzw vf31, vf31, vf07 97
|
||||
cout3.mul(Mask::xyzw, cout3, m_texture_constants.constants.x());
|
||||
// nop | addy.xyzw vf28, vf28, vf07 98
|
||||
cout0.add(Mask::xyzw, cout0, m_texture_constants.constants.y());
|
||||
// nop | addy.xyzw vf29, vf29, vf07 99
|
||||
cout1.add(Mask::xyzw, cout1, m_texture_constants.constants.y());
|
||||
// nop | addy.xyzw vf30, vf30, vf07 100
|
||||
cout2.add(Mask::xyzw, cout2, m_texture_constants.constants.y());
|
||||
// nop | addy.xyzw vf31, vf31, vf07 101
|
||||
cout3.add(Mask::xyzw, cout3, m_texture_constants.constants.y());
|
||||
// sq.xyzw vf16, 1(vi06) | sub.zw vf28, vf01, vf00 102
|
||||
cout0.sub(Mask::zw, ones, vf00); sq_buffer(Mask::xyzw, vtx0, vu.dbuf_write + 1);
|
||||
// sq.xyzw vf17, 4(vi06) | sub.zw vf29, vf01, vf00 103
|
||||
cout1.sub(Mask::zw, ones, vf00); sq_buffer(Mask::xyzw, vtx1, vu.dbuf_write + 4);
|
||||
// sq.xyzw vf18, 7(vi06) | sub.zw vf30, vf01, vf00 104
|
||||
cout2.sub(Mask::zw, ones, vf00); sq_buffer(Mask::xyzw, vtx2, vu.dbuf_write + 7);
|
||||
// sq.xyzw vf19, 10(vi06) | sub.zw vf31, vf01, vf00 105
|
||||
cout3.sub(Mask::zw, ones, vf00); sq_buffer(Mask::xyzw, vtx3, vu.dbuf_write + 10);
|
||||
// lq.xyzw vf24, 1(vi05) | mulw.xyzw vf20, vf15, vf00 106
|
||||
res0.mul(Mask::xyzw, base_pos, 1.f); lq_buffer(Mask::xyzw, nrm0, vu.in_ptr + 1);
|
||||
// lq.xyzw vf25, 3(vi05) | mulw.xyzw vf21, vf15, vf00 107
|
||||
res1.mul(Mask::xyzw, base_pos, 1.f); lq_buffer(Mask::xyzw, nrm1, vu.in_ptr + 3);
|
||||
// lq.xyzw vf26, 5(vi05) | mulw.xyzw vf22, vf15, vf00 108
|
||||
res2.mul(Mask::xyzw, base_pos, 1.f); lq_buffer(Mask::xyzw, nrm2, vu.in_ptr + 5);
|
||||
// sq.xyzw vf28, 0(vi06) | mulw.xyzw vf23, vf15, vf00 109
|
||||
res3.mul(Mask::xyzw, base_pos, 1.f); sq_buffer(Mask::xyzw, cout0, vu.dbuf_write);
|
||||
// sq.xyzw vf29, 3(vi06) | mulax.xyzw ACC, vf24, vf06 110
|
||||
acc.mula(Mask::xyzw, nrm0, m_texture_constants.cam_nrm.x()); sq_buffer(Mask::xyzw, cout1, vu.dbuf_write + 3);
|
||||
// sq.xyzw vf30, 6(vi06) | madday.xyzw ACC, vf25, vf06 111
|
||||
acc.madda(Mask::xyzw, nrm1, m_texture_constants.cam_nrm.y()); sq_buffer(Mask::xyzw, cout2, vu.dbuf_write + 6);
|
||||
// sq.xyzw vf31, 9(vi06) | maddz.xyzw vf27, vf26, vf06 112
|
||||
acc.madd(Mask::xyzw, reflect, nrm2, m_texture_constants.cam_nrm.z()); sq_buffer(Mask::xyzw, cout3, vu.dbuf_write + 9);
|
||||
// BRANCH!
|
||||
// ibgtz vi01, L4 | addx.x vf21, vf21, vf02 113
|
||||
res1.add(Mask::x, res1, m_texture_constants.offsets.x()); bc = ((s16)loop_idx) > 0;
|
||||
// iaddi vi06, vi06, 0xc | addy.x vf22, vf22, vf02 114
|
||||
res2.add(Mask::x, res2, m_texture_constants.offsets.y()); vu.dbuf_write = vu.dbuf_write + 12;
|
||||
if (bc) { goto L4; }
|
||||
|
||||
// lq.xyzw vf28, 0(vi07) | addx.y vf14, vf14, vf02 115
|
||||
vu.startx.add(Mask::y, vu.startx, m_texture_constants.offsets.x()); lq_buffer(Mask::xyzw, cout0, vu.dbuf_write_base);
|
||||
// lq.xyzw vf16, 1(vi07) | nop 116
|
||||
lq_buffer(Mask::xyzw, vtx0, vu.dbuf_write_base + 1);
|
||||
// sq.xyzw vf20, 2(vi06) | nop 117
|
||||
sq_buffer(Mask::xyzw, res0, vu.dbuf_write + 2);
|
||||
// sq.xyzw vf28, 0(vi06) | nop 118
|
||||
sq_buffer(Mask::xyzw, cout0, vu.dbuf_write);
|
||||
// jr vi12 | nop 119
|
||||
// sq.xyzw vf16, 1(vi06) | nop 120
|
||||
sq_buffer(Mask::xyzw, vtx0, vu.dbuf_write + 1);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void OceanTexture::run_L5(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
// clang-format off
|
||||
u16 loop_idx;
|
||||
Vf res0;
|
||||
Vf res1;
|
||||
Vf cout0;
|
||||
Vf cout1;
|
||||
Vf vtx0;
|
||||
Vf vtx1;
|
||||
bool bc;
|
||||
// L5:
|
||||
// iaddiu vi01, vi00, 0x21 | nop 121
|
||||
loop_idx = 0x21; /* 33 */
|
||||
// sq.xyzw vf05, 0(vi08) | nop 122
|
||||
sq_buffer_giftag(m_texture_constants.giftag, vu.tptr);
|
||||
// iaddi vi08, vi08, 0x1 | nop 123
|
||||
vu.tptr = vu.tptr + 1;
|
||||
L6:
|
||||
// iaddi vi01, vi01, -0x1 | nop 124
|
||||
loop_idx = loop_idx + -1;
|
||||
// lq.xyzw vf20, 2(vi03) | nop 125
|
||||
lq_buffer(Mask::xyzw, res0, vu.dbuf_read_a + 2);
|
||||
// lq.xyzw vf21, 2(vi04) | nop 126
|
||||
lq_buffer(Mask::xyzw, res1, vu.dbuf_read_b + 2);
|
||||
// lq.xyzw vf28, 0(vi03) | nop 127
|
||||
lq_buffer(Mask::xyzw, cout0, vu.dbuf_read_a);
|
||||
// lq.xyzw vf16, 1(vi03) | nop 128
|
||||
lq_buffer(Mask::xyzw, vtx0, vu.dbuf_read_a + 1);
|
||||
// lq.xyzw vf29, 0(vi04) | ftoi4.xyzw vf20, vf20 129
|
||||
res0.ftoi4(Mask::xyzw, res0); lq_buffer(Mask::xyzw, cout1, vu.dbuf_read_b);
|
||||
// lq.xyzw vf17, 1(vi04) | ftoi4.xyzw vf21, vf21 130
|
||||
res1.ftoi4(Mask::xyzw, res1); lq_buffer(Mask::xyzw, vtx1, vu.dbuf_read_b + 1);
|
||||
// sq.xyzw vf28, 0(vi08) | nop 131
|
||||
sq_buffer(Mask::xyzw, cout0, vu.tptr);
|
||||
// sq.xyzw vf16, 1(vi08) | nop 132
|
||||
sq_buffer(Mask::xyzw, vtx0, vu.tptr + 1);
|
||||
// sq.xyzw vf20, 2(vi08) | nop 133
|
||||
sq_buffer(Mask::xyzw, res0, vu.tptr + 2);
|
||||
// sq.xyzw vf29, 3(vi08) | nop 134
|
||||
sq_buffer(Mask::xyzw, cout1, vu.tptr + 3);
|
||||
// sq.xyzw vf17, 4(vi08) | nop 135
|
||||
sq_buffer(Mask::xyzw, vtx1, vu.tptr + 4);
|
||||
// sq.xyzw vf21, 5(vi08) | nop 136
|
||||
sq_buffer(Mask::xyzw, res1, vu.tptr + 5);
|
||||
|
||||
// iaddi vi03, vi03, 0x3 | nop 137
|
||||
vu.dbuf_read_a = vu.dbuf_read_a + 3;
|
||||
// iaddi vi04, vi04, 0x3 | nop 138
|
||||
vu.dbuf_read_b = vu.dbuf_read_b + 3;
|
||||
// BRANCH!
|
||||
// ibgtz vi01, L6 | nop 139
|
||||
bc = ((s16)loop_idx) > 0;
|
||||
// iaddi vi08, vi08, 0x6 | nop 140
|
||||
vu.tptr = vu.tptr + 6;
|
||||
if (bc) { goto L6; }
|
||||
|
||||
// xgkick vi09 | nop 141
|
||||
xgkick(vu.tbase, render_state, prof);
|
||||
// mtir vi08, vf03.x | nop 142
|
||||
// vu.tptr = vu.vf03.x_as_u16();
|
||||
vu.tptr = get_tbuf();
|
||||
// mtir vi09, vf03.x | nop 143
|
||||
// vu.vi09 = vu.vf03.x_as_u16();
|
||||
vu.tbase = get_tbuf();
|
||||
// jr vi12 | nop 144
|
||||
// ASSERT(false);
|
||||
// mr32.xyzw vf03, vf03 | nop 145
|
||||
// vu.vf03.mr32(Mask::xyzw, vu.vf03);
|
||||
swap_tbuf();
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void OceanTexture::xgkick(Vf* src, SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
// KICK
|
||||
m_hack_renderer.render_gif((const u8*)src, UINT32_MAX, render_state, prof);
|
||||
}
|
31
game/graphics/opengl_renderer/shaders/ocean_common.frag
Normal file
31
game/graphics/opengl_renderer/shaders/ocean_common.frag
Normal file
@ -0,0 +1,31 @@
|
||||
#version 430 core
|
||||
|
||||
out vec4 color;
|
||||
|
||||
in vec4 fragment_color;
|
||||
in vec3 tex_coord;
|
||||
uniform float color_mult;
|
||||
uniform float alpha_mult;
|
||||
|
||||
uniform vec4 fog_color;
|
||||
uniform int bucket;
|
||||
|
||||
in float fog;
|
||||
|
||||
uniform sampler2D tex_T0;
|
||||
|
||||
void main() {
|
||||
vec4 T0 = texture(tex_T0, tex_coord.xy / tex_coord.z);
|
||||
if (bucket == 0) {
|
||||
color.xyz = fragment_color.xyz * T0.xyz;
|
||||
color.w = fragment_color.w;
|
||||
color.xyz *= 2;
|
||||
color.xyz = mix(color.xyz, fog_color.xyz / 255., clamp(fog_color.w * (1 - fog), 0, 1));
|
||||
} else if (bucket == 1) {
|
||||
color = fragment_color * T0;
|
||||
color.xyzw *= 2;
|
||||
} else if (bucket == 2) {
|
||||
color = fragment_color * T0;
|
||||
}
|
||||
|
||||
}
|
19
game/graphics/opengl_renderer/shaders/ocean_common.vert
Normal file
19
game/graphics/opengl_renderer/shaders/ocean_common.vert
Normal file
@ -0,0 +1,19 @@
|
||||
#version 430 core
|
||||
|
||||
layout (location = 0) in vec3 position_in;
|
||||
layout (location = 1) in vec4 rgba_in;
|
||||
layout (location = 2) in vec3 tex_coord_in;
|
||||
layout (location = 3) in uint fog_in;
|
||||
|
||||
out vec4 fragment_color;
|
||||
out vec3 tex_coord;
|
||||
out float fog;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4((position_in.x - 0.5) * 16., -(position_in.y - 0.5) * 32, position_in.z * 2 - 1., 1.0);
|
||||
// scissoring area adjust
|
||||
gl_Position.y *= 512.0/448.0;
|
||||
fragment_color = vec4(rgba_in.x, rgba_in.y, rgba_in.z, rgba_in.w * 2.);
|
||||
tex_coord = tex_coord_in;
|
||||
fog = float(fog_in) / 255.;
|
||||
}
|
Loading…
Reference in New Issue
Block a user