mirror of
https://github.com/open-goal/jak-project.git
synced 2025-04-01 08:31:41 +00:00
[graphics] Ocean Mid (in progress) (#1232)
* first pass at ocean mid * fix some bugs * fix seams * cleanup * temp * fix mipmap
This commit is contained in:
parent
b2131d43e3
commit
ef0f7635d3
@ -5,7 +5,7 @@
|
||||
namespace colors {
|
||||
// some reasonable colors that are different from each other
|
||||
constexpr int COLOR_COUNT = 131;
|
||||
u32 common_colors[COLOR_COUNT] = {
|
||||
constexpr u32 common_colors[COLOR_COUNT] = {
|
||||
0xF0F8FE, 0xFAEBD7, 0x00FFFF, 0x70DB93, 0xF0FFFF, 0xF5F5DC, 0x000000, 0x0000FF, 0x9F5F9F,
|
||||
0xB5A642, 0xD9D919, 0x8C7853, 0xA52A2A, 0x5F9EA0, 0xD2691E, 0xB87333, 0xFF7F50, 0xDC143C,
|
||||
0x00FFFF, 0x00008B, 0x5C4033, 0x008B8B, 0xB8860B, 0xA9A9A9, 0x006400, 0xBDB76B, 0x8B008B,
|
||||
|
@ -830,18 +830,25 @@ std::string VuDisassembler::to_cpp(const VuInstruction& instr, bool mips2c_forma
|
||||
vi_src(instr.src.at(1).to_string(m_label_names), mips2c_format));
|
||||
case VuInstrK::IOR:
|
||||
if (instr.src.at(1).is_int_reg(0)) {
|
||||
ASSERT(!instr.dst->is_int_reg(0));
|
||||
ASSERT(!instr.src.at(0).is_int_reg(0));
|
||||
if (mips2c_format) {
|
||||
return fmt::format("vis[{}] = vis[{}];", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
fmt::print("instr: {}\n", to_string(instr));
|
||||
if (instr.src.at(0).is_int_reg(0) && instr.src.at(1).is_int_reg(0)) {
|
||||
return fmt::format("vu.{} = 0;", instr.dst->to_string(m_label_names));
|
||||
} else {
|
||||
return fmt::format("vu.{} = vu.{};", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
ASSERT(!instr.dst->is_int_reg(0));
|
||||
ASSERT(!instr.src.at(0).is_int_reg(0));
|
||||
if (mips2c_format) {
|
||||
return fmt::format("vis[{}] = vis[{}];", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
} else {
|
||||
return fmt::format("vu.{} = vu.{};", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
goto unknown;
|
||||
return fmt::format("vu.{} = vu.{} | vu.{};", instr.dst->to_string(m_label_names),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
}
|
||||
|
||||
case VuInstrK::MFP:
|
||||
@ -865,8 +872,7 @@ std::string VuDisassembler::to_cpp(const VuInstruction& instr, bool mips2c_forma
|
||||
bc_to_part(*instr.second_src_field));
|
||||
|
||||
case VuInstrK::ERLENG:
|
||||
return fmt::format("vu.P = erleng(Mask::{}, vu.{}); /* TODO erleng */",
|
||||
mask_to_string(*instr.mask), instr.src.at(0).to_string(m_label_names));
|
||||
return fmt::format("vu.P = erleng(vu.{});", instr.src.at(0).to_string(m_label_names));
|
||||
case VuInstrK::RSQRT:
|
||||
return fmt::format(
|
||||
"c->Q = c->vf_src({}).vf.{}() / std::sqrt(c->vf_src({}).vf.{}());",
|
||||
@ -891,8 +897,11 @@ std::string VuDisassembler::to_cpp(const VuInstruction& instr, bool mips2c_forma
|
||||
vf_src(instr.src.at(0).to_string(m_label_names), mips2c_format),
|
||||
vf_src(instr.src.at(1).to_string(m_label_names), mips2c_format));
|
||||
case VuInstrK::FCAND:
|
||||
return fmt::format("ASSERT(false); vu.vi01 = cf & 0x{:x};\n", instr.src.at(0).value());
|
||||
|
||||
return fmt::format("fcand(vu.vi01, 0x{:x}, cf);\n", instr.src.at(0).value());
|
||||
case VuInstrK::FCOR:
|
||||
return fmt::format("fcor(vu.vi01, 0x{:x}, cf);\n", instr.src.at(0).value());
|
||||
case VuInstrK::FCSET:
|
||||
return fmt::format("cf = 0x{:x};\n", instr.src.at(0).value());
|
||||
case VuInstrK::ADDbc:
|
||||
case VuInstrK::SUBbc:
|
||||
case VuInstrK::MULbc:
|
||||
@ -971,6 +980,9 @@ std::string VuDisassembler::to_cpp(const VuInstruction& instr, bool mips2c_forma
|
||||
return fmt::format("vu.acc.mula(Mask::{}, vu.{}, vu.{});", mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names),
|
||||
instr.src.at(1).to_string(m_label_names));
|
||||
case VuInstrK::MULAq:
|
||||
return fmt::format("vu.acc.mula(Mask::{}, vu.{}, vu.Q);", mask_to_string(*instr.mask),
|
||||
instr.src.at(0).to_string(m_label_names));
|
||||
case VuInstrK::MULAbc:
|
||||
return fmt::format(mips2c_format
|
||||
? "c->acc.vf.mula(Mask::{}, c->vf_src({}).vf, c->vf_src({}).vf.{}());"
|
||||
@ -985,13 +997,17 @@ std::string VuDisassembler::to_cpp(const VuInstruction& instr, bool mips2c_forma
|
||||
return fmt::format("vu.{} = xtop();", instr.src.at(0).to_string(m_label_names));
|
||||
default:
|
||||
unk++;
|
||||
fmt::print("unknown 0 is {}\n", to_string(instr));
|
||||
|
||||
return "ASSERT(false);"; //"???";
|
||||
}
|
||||
|
||||
unknown:
|
||||
|
||||
unk++;
|
||||
return "???";
|
||||
fmt::print("unknown 1 is {}\n", to_string(instr));
|
||||
|
||||
return "ASSERT(false);";
|
||||
}
|
||||
|
||||
std::string VuDisassembler::to_string(const VuInstruction& instr) const {
|
||||
|
@ -84,6 +84,8 @@ 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/OceanMid.cpp
|
||||
graphics/opengl_renderer/ocean/OceanMid_PS2.cpp
|
||||
graphics/opengl_renderer/ocean/OceanMidAndFar.cpp
|
||||
graphics/opengl_renderer/ocean/OceanTexture.cpp
|
||||
graphics/opengl_renderer/ocean/OceanTexture_PC.cpp
|
||||
|
@ -64,6 +64,8 @@ class DirectRenderer : public BucketRenderer {
|
||||
m_blend_state.d = GsAlpha::BlendMode::SOURCE;
|
||||
}
|
||||
|
||||
void set_mipmap(bool en) { m_debug_state.disable_mipmap = !en; }
|
||||
|
||||
private:
|
||||
void handle_ad(const u8* data, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_zbuf1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
@ -79,4 +79,5 @@ ShaderLibrary::ShaderLibrary() {
|
||||
at(ShaderId::EYE) = {"eye"};
|
||||
at(ShaderId::GENERIC) = {"generic"};
|
||||
at(ShaderId::OCEAN_TEXTURE) = {"ocean_texture"};
|
||||
at(ShaderId::OCEAN_TEXTURE_MIPMAP) = {"ocean_texture_mipmap"};
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ enum class ShaderId {
|
||||
EYE = 11,
|
||||
GENERIC = 12,
|
||||
OCEAN_TEXTURE = 13,
|
||||
OCEAN_TEXTURE_MIPMAP = 14,
|
||||
MAX_SHADERS
|
||||
};
|
||||
|
||||
|
145
game/graphics/opengl_renderer/ocean/OceanMid.cpp
Normal file
145
game/graphics/opengl_renderer/ocean/OceanMid.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
#include "OceanMid.h"
|
||||
|
||||
static bool is_end_tag(const DmaTag& tag, const VifCode& v0, const VifCode& v1) {
|
||||
return tag.qwc == 2 && tag.kind == DmaTag::Kind::CNT && v0.kind == VifCode::Kind::NOP &&
|
||||
v1.kind == VifCode::Kind::DIRECT;
|
||||
}
|
||||
|
||||
OceanMid::OceanMid() {
|
||||
for (auto& x : m_vu_data) {
|
||||
x.fill(999.);
|
||||
}
|
||||
vu.vf25 = Vf(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
void OceanMid::run(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
DirectRenderer& direct) {
|
||||
// first is setting base and offset
|
||||
{
|
||||
auto base_offset_tag = dma.read_and_advance();
|
||||
ASSERT(base_offset_tag.size_bytes == 0);
|
||||
auto base = base_offset_tag.vifcode0();
|
||||
ASSERT(base.kind == VifCode::Kind::BASE);
|
||||
ASSERT(base.immediate == VU1_INPUT_BUFFER_BASE);
|
||||
auto offset = base_offset_tag.vifcode1();
|
||||
ASSERT(offset.kind == VifCode::Kind::OFFSET);
|
||||
ASSERT(offset.immediate == VU1_INPUT_BUFFER_OFFSET);
|
||||
}
|
||||
|
||||
// next is constants
|
||||
{
|
||||
auto constants = dma.read_and_advance();
|
||||
ASSERT(constants.size_bytes == sizeof(Constants));
|
||||
ASSERT(constants.vifcode0().kind == VifCode::Kind::STCYCL); // for whatever reason they do this
|
||||
auto unpack = constants.vifcode1();
|
||||
ASSERT(VifCodeUnpack(unpack).addr_qw == Vu1Data::CONSTANTS);
|
||||
memcpy(&m_constants, constants.data, sizeof(Constants));
|
||||
memcpy(m_vu_data + Vu1Data::CONSTANTS, &m_constants, sizeof(Constants));
|
||||
}
|
||||
|
||||
// next is call 0
|
||||
{
|
||||
auto call0 = dma.read_and_advance();
|
||||
ASSERT(call0.vifcode0().kind == VifCode::Kind::STCYCL);
|
||||
auto c = call0.vifcode1();
|
||||
ASSERT(c.kind == VifCode::Kind::MSCALF);
|
||||
ASSERT(c.immediate == 0);
|
||||
run_call0();
|
||||
}
|
||||
|
||||
while (!is_end_tag(dma.current_tag(), dma.current_tag_vif0(), dma.current_tag_vif1())) {
|
||||
auto data = dma.read_and_advance();
|
||||
auto v0 = data.vifcode0();
|
||||
auto v1 = data.vifcode1();
|
||||
if (v0.kind == VifCode::Kind::STCYCL && v0.immediate == 0x404 &&
|
||||
v1.kind == VifCode::Kind::UNPACK_V4_32) {
|
||||
auto up = VifCodeUnpack(v1);
|
||||
// ASSERT(up.use_tops_flag);
|
||||
u16 addr = up.addr_qw + (up.use_tops_flag ? get_upload_buffer() : 0);
|
||||
ASSERT(addr + v1.num <= 1024);
|
||||
memcpy(m_vu_data + addr, data.data, 16 * v1.num);
|
||||
ASSERT(16 * v1.num == data.size_bytes);
|
||||
} else if (v0.kind == VifCode::Kind::STCYCL && v0.immediate == 0x404 &&
|
||||
v1.kind == VifCode::Kind::UNPACK_V4_8) {
|
||||
auto up = VifCodeUnpack(v1);
|
||||
ASSERT(up.use_tops_flag);
|
||||
ASSERT(up.is_unsigned);
|
||||
u16 addr = up.addr_qw + get_upload_buffer();
|
||||
ASSERT(addr + v1.num <= 1024);
|
||||
|
||||
u32 temp[4];
|
||||
for (u32 i = 0; i < v1.num; i++) {
|
||||
for (u32 j = 0; j < 4; j++) {
|
||||
temp[j] = data.data[4 * i + j];
|
||||
}
|
||||
memcpy(m_vu_data + addr + i, temp, 16);
|
||||
}
|
||||
ASSERT(4 * v1.num == data.size_bytes);
|
||||
|
||||
} else if (v0.kind == VifCode::Kind::STCYCL && v0.immediate == 0x204 &&
|
||||
v1.kind == VifCode::Kind::UNPACK_V4_8) {
|
||||
auto up = VifCodeUnpack(v1);
|
||||
ASSERT(up.use_tops_flag);
|
||||
ASSERT(up.is_unsigned);
|
||||
u16 addr = up.addr_qw + get_upload_buffer();
|
||||
ASSERT(addr + v1.num <= 1024);
|
||||
|
||||
u32 temp[4];
|
||||
for (u32 i = 0; i < v1.num; i++) {
|
||||
for (u32 j = 0; j < 4; j++) {
|
||||
temp[j] = data.data[4 * i + j];
|
||||
}
|
||||
// cl = 4
|
||||
// wl = 2
|
||||
u32 addr_off = 4 * (i / 2) + i % 2;
|
||||
memcpy(m_vu_data + addr + addr_off, temp, 16);
|
||||
}
|
||||
ASSERT(8 * v1.num == data.size_bytes);
|
||||
// TODO
|
||||
} else if (v0.kind == VifCode::Kind::STCYCL && v0.immediate == 0x404 &&
|
||||
v1.kind == VifCode::Kind::MSCALF) {
|
||||
switch (v1.immediate) {
|
||||
case 46:
|
||||
run_call46_vu2c(render_state, prof, direct);
|
||||
break;
|
||||
case 73:
|
||||
run_call73_vu2c(render_state, prof, direct);
|
||||
break;
|
||||
case 107:
|
||||
run_call107_vu2c(render_state, prof, direct);
|
||||
break;
|
||||
case 275:
|
||||
run_call275_vu2c(render_state, prof, direct);
|
||||
break;
|
||||
default:
|
||||
fmt::print("unknown call1: {}\n", v1.immediate);
|
||||
}
|
||||
// TODO
|
||||
} else if (v0.kind == VifCode::Kind::MSCALF && v1.kind == VifCode::Kind::FLUSHA) {
|
||||
switch (v0.immediate) {
|
||||
case 41:
|
||||
run_call41_vu2c();
|
||||
break;
|
||||
case 43:
|
||||
run_call43_vu2c();
|
||||
break;
|
||||
default:
|
||||
fmt::print("unknown call2: {}\n", v0.immediate);
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
else {
|
||||
fmt::print("{} {}\n", data.vifcode0().print(), data.vifcode1().print());
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OceanMid::run_call0() {
|
||||
run_call0_vu2c();
|
||||
}
|
203
game/graphics/opengl_renderer/ocean/OceanMid.h
Normal file
203
game/graphics/opengl_renderer/ocean/OceanMid.h
Normal file
@ -0,0 +1,203 @@
|
||||
#pragma once
|
||||
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/DirectRenderer.h"
|
||||
#include "game/common/vu.h"
|
||||
|
||||
class OceanMid {
|
||||
public:
|
||||
OceanMid();
|
||||
void run(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
DirectRenderer& direct);
|
||||
|
||||
private:
|
||||
void run_call0();
|
||||
void run_call0_vu2c();
|
||||
void run_call41_vu2c();
|
||||
void run_call43_vu2c();
|
||||
void run_call46_vu2c(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
DirectRenderer& direct);
|
||||
|
||||
void run_call73_vu2c(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
DirectRenderer& direct);
|
||||
void run_call107_vu2c(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
DirectRenderer& direct);
|
||||
void run_call275_vu2c(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
DirectRenderer& direct);
|
||||
void xgkick(u16 addr,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
DirectRenderer& direct);
|
||||
|
||||
void run_L26_vu2c();
|
||||
void run_L32_vu2c();
|
||||
void run_L38_vu2c(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
DirectRenderer& direct);
|
||||
void run_L43_vu2c(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
DirectRenderer& direct);
|
||||
void run_L45_vu2c();
|
||||
|
||||
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;
|
||||
};
|
@ -47,7 +47,9 @@ void OceanMidAndFar::render(DmaFollower& dma,
|
||||
}
|
||||
|
||||
handle_ocean_far(dma, render_state, prof);
|
||||
m_direct.flush_pending(render_state, prof);
|
||||
|
||||
m_direct.set_mipmap(true);
|
||||
handle_ocean_mid(dma, render_state, prof);
|
||||
|
||||
auto final_next = dma.read_and_advance();
|
||||
@ -59,6 +61,7 @@ void OceanMidAndFar::render(DmaFollower& dma,
|
||||
ASSERT(dma.current_tag_offset() == render_state->next_bucket);
|
||||
|
||||
m_direct.flush_pending(render_state, prof);
|
||||
m_direct.set_mipmap(false);
|
||||
}
|
||||
|
||||
void OceanMidAndFar::handle_ocean_far(DmaFollower& dma,
|
||||
@ -93,6 +96,13 @@ bool is_end_tag(const DmaTag& tag, const VifCode& v0, const VifCode& v1) {
|
||||
void OceanMidAndFar::handle_ocean_mid(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
if (dma.current_tag_vifcode0().kind == VifCode::Kind::BASE) {
|
||||
m_mid_renderer.run(dma, render_state, prof, m_direct);
|
||||
} else {
|
||||
// not drawing
|
||||
return;
|
||||
}
|
||||
|
||||
while (!is_end_tag(dma.current_tag(), dma.current_tag_vifcode0(), dma.current_tag_vifcode1())) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
|
@ -4,10 +4,14 @@
|
||||
#include "game/graphics/opengl_renderer/DirectRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/opengl_utils.h"
|
||||
#include "game/graphics/opengl_renderer/ocean/OceanTexture.h"
|
||||
#include "game/graphics/opengl_renderer/ocean/OceanMid.h"
|
||||
|
||||
/*!
|
||||
* OceanMidAndFar is the handler for the first ocean bucket.
|
||||
*
|
||||
* This bucket runs three renderers:
|
||||
* - ocean-texture (handled by the OceanTexture C++ class)
|
||||
* - ocean-far (handled by this class, it's very simple)
|
||||
* - ocean-mid (handled by the C++ OceanMid class)
|
||||
*/
|
||||
class OceanMidAndFar : public BucketRenderer {
|
||||
public:
|
||||
@ -26,4 +30,5 @@ class OceanMidAndFar : public BucketRenderer {
|
||||
|
||||
DirectRenderer m_direct;
|
||||
OceanTexture m_texture_renderer;
|
||||
OceanMid m_mid_renderer;
|
||||
};
|
||||
|
3350
game/graphics/opengl_renderer/ocean/OceanMid_PS2.cpp
Normal file
3350
game/graphics/opengl_renderer/ocean/OceanMid_PS2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,8 @@
|
||||
|
||||
constexpr int OCEAN_TEX_TBP = 8160; // todo
|
||||
OceanTexture::OceanTexture()
|
||||
: m_tex0(TEX0_SIZE, TEX0_SIZE, GL_UNSIGNED_INT_8_8_8_8_REV),
|
||||
: m_result_texture(TEX0_SIZE, TEX0_SIZE, GL_UNSIGNED_INT_8_8_8_8_REV, 8),
|
||||
m_temp_texture(TEX0_SIZE, TEX0_SIZE, GL_UNSIGNED_INT_8_8_8_8_REV),
|
||||
m_hack_renderer("burp", BucketId::BUCKET0, 0x8000) {
|
||||
m_dbuf_x = m_dbuf_a;
|
||||
m_dbuf_y = m_dbuf_b;
|
||||
@ -13,6 +14,34 @@ OceanTexture::OceanTexture()
|
||||
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() {
|
||||
@ -21,10 +50,9 @@ OceanTexture::~OceanTexture() {
|
||||
|
||||
void OceanTexture::init_textures(TexturePool& pool) {
|
||||
TextureInput in;
|
||||
in.gpu_texture = m_tex0.texture();
|
||||
constexpr int boost = 2;
|
||||
in.w = 128 * boost;
|
||||
in.h = 128 * boost;
|
||||
in.gpu_texture = m_result_texture.texture();
|
||||
in.w = TEX0_SIZE;
|
||||
in.h = TEX0_SIZE;
|
||||
in.page_name = "PC-OCEAN";
|
||||
in.name = "pc-ocean";
|
||||
m_tex0_gpu = pool.give_texture_and_load_to_vram(in, OCEAN_TEX_TBP);
|
||||
@ -73,7 +101,7 @@ void OceanTexture::handle_tex_call_rest(SharedRenderState* render_state, ScopedP
|
||||
void OceanTexture::handle_ocean_texture(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
FramebufferTexturePairContext ctxt(m_tex0);
|
||||
FramebufferTexturePairContext ctxt(m_temp_texture);
|
||||
// render to the first texture
|
||||
{
|
||||
// (set-display-gs-state arg0 ocean-tex-page-0 128 128 0 0)
|
||||
@ -234,5 +262,43 @@ void OceanTexture::handle_ocean_texture(DmaFollower& dma,
|
||||
}
|
||||
|
||||
flush(render_state, prof);
|
||||
render_state->texture_pool->move_existing_to_vram(m_tex0_gpu, 8160);
|
||||
make_mipmaps(render_state, prof);
|
||||
}
|
||||
|
||||
/*!
|
||||
* 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_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 < 8; 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.5f * 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);
|
||||
}
|
||||
render_state->texture_pool->move_existing_to_vram(m_tex0_gpu, OCEAN_TEX_TBP);
|
||||
glBindVertexArray(0);
|
||||
}
|
@ -39,10 +39,13 @@ class OceanTexture {
|
||||
void init_pc();
|
||||
void destroy_pc();
|
||||
|
||||
void make_mipmaps(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
bool m_use_ocean_specific = true;
|
||||
|
||||
static constexpr int TEX0_SIZE = 256; // TODO actually 128
|
||||
FramebufferTexturePair m_tex0;
|
||||
static constexpr int TEX0_SIZE = 128;
|
||||
FramebufferTexturePair m_result_texture;
|
||||
FramebufferTexturePair m_temp_texture;
|
||||
GpuTexture* m_tex0_gpu = nullptr;
|
||||
|
||||
// (deftype ocean-texture-constants (structure)
|
||||
@ -136,6 +139,15 @@ class OceanTexture {
|
||||
GLuint vao, static_vertex_buffer, dynamic_vertex_buffer, gl_index_buffer;
|
||||
} m_pc;
|
||||
|
||||
struct MipMap {
|
||||
GLuint vao, vtx_buffer;
|
||||
struct Vertex {
|
||||
float x, y;
|
||||
float s, t;
|
||||
};
|
||||
static_assert(sizeof(Vertex) == 16);
|
||||
} m_mipmap;
|
||||
|
||||
enum TexVu1Data {
|
||||
BUF0 = 384,
|
||||
BUF1 = 583,
|
||||
|
@ -1,51 +1,89 @@
|
||||
#include "opengl_utils.h"
|
||||
|
||||
#include "common/util/Assert.h"
|
||||
#include <cstdio>
|
||||
|
||||
FramebufferTexturePair::FramebufferTexturePair(int w, int h, u64 texture_format) : m_w(w), m_h(h) {
|
||||
glGenFramebuffers(1, &m_framebuffer);
|
||||
FramebufferTexturePair::FramebufferTexturePair(int w, int h, u64 texture_format, int num_levels)
|
||||
: m_w(w), m_h(h) {
|
||||
m_framebuffers.resize(num_levels);
|
||||
glGenFramebuffers(num_levels, m_framebuffers.data());
|
||||
glGenTextures(1, &m_texture);
|
||||
|
||||
GLint old_framebuffer;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_framebuffer);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels);
|
||||
glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, w >> i, h >> i, 0, GL_RGBA, texture_format, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, texture_format, nullptr);
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[i]);
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||
// I don't know if we really need to do this. whatever uses this texture should figure it out.
|
||||
|
||||
// I don't know if we really need to do this. whatever uses this texture should figure it out.
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, m_texture, i);
|
||||
GLenum draw_buffers[1] = {GLenum(GL_COLOR_ATTACHMENT0 + i)};
|
||||
glDrawBuffers(1, draw_buffers);
|
||||
auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
switch (status) {
|
||||
case GL_FRAMEBUFFER_UNDEFINED:
|
||||
printf("GL_FRAMEBUFFER_UNDEFINED\n");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
||||
printf("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT\n");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
|
||||
printf("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\n");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
|
||||
printf("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER\n");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
|
||||
printf("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER\n");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED:
|
||||
printf("GL_FRAMEBUFFER_UNSUPPORTED\n");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
|
||||
printf("GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE\n");
|
||||
break;
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
|
||||
printf("GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS\n");
|
||||
break;
|
||||
}
|
||||
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture, 0);
|
||||
GLenum draw_buffers[1] = {GL_COLOR_ATTACHMENT0};
|
||||
glDrawBuffers(1, draw_buffers);
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
ASSERT(false);
|
||||
ASSERT(false);
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, old_framebuffer);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, old_framebuffer);
|
||||
}
|
||||
|
||||
FramebufferTexturePair::~FramebufferTexturePair() {
|
||||
glDeleteFramebuffers(1, &m_framebuffer);
|
||||
glDeleteFramebuffers(m_framebuffers.size(), m_framebuffers.data());
|
||||
glDeleteTextures(1, &m_texture);
|
||||
}
|
||||
|
||||
FramebufferTexturePairContext::FramebufferTexturePairContext(FramebufferTexturePair& fb)
|
||||
FramebufferTexturePairContext::FramebufferTexturePairContext(FramebufferTexturePair& fb, int level)
|
||||
: m_fb(&fb) {
|
||||
glGetIntegerv(GL_VIEWPORT, m_old_viewport);
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_old_framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fb->m_framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fb->m_framebuffers[level]);
|
||||
glViewport(0, 0, m_fb->m_w, m_fb->m_h);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_fb->m_texture, 0);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_fb->m_texture, level);
|
||||
}
|
||||
|
||||
void FramebufferTexturePairContext::switch_to(FramebufferTexturePair& fb) {
|
||||
if (&fb != m_fb) {
|
||||
m_fb = &fb;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fb->m_framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fb->m_framebuffers[0]);
|
||||
glViewport(0, 0, m_fb->m_w, m_fb->m_h);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_fb->m_texture, 0);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
class FramebufferTexturePair {
|
||||
public:
|
||||
FramebufferTexturePair(int w, int h, u64 texture_format);
|
||||
FramebufferTexturePair(int w, int h, u64 texture_format, int num_levels = 1);
|
||||
~FramebufferTexturePair();
|
||||
|
||||
GLuint texture() const { return m_texture; }
|
||||
@ -17,14 +17,14 @@ class FramebufferTexturePair {
|
||||
|
||||
private:
|
||||
friend class FramebufferTexturePairContext;
|
||||
GLuint m_framebuffer;
|
||||
std::vector<GLuint> m_framebuffers;
|
||||
GLuint m_texture;
|
||||
int m_w, m_h;
|
||||
};
|
||||
|
||||
class FramebufferTexturePairContext {
|
||||
public:
|
||||
FramebufferTexturePairContext(FramebufferTexturePair& fb);
|
||||
FramebufferTexturePairContext(FramebufferTexturePair& fb, int level = 0);
|
||||
~FramebufferTexturePairContext();
|
||||
|
||||
void switch_to(FramebufferTexturePair& fb);
|
||||
|
@ -8,5 +8,6 @@ uniform sampler2D tex_T0;
|
||||
|
||||
void main() {
|
||||
vec4 tex = texture(tex_T0, tex_coord);
|
||||
color = fragment_color * tex * 2;
|
||||
tex.xyz *= 2;
|
||||
color = fragment_color * tex;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#version 430 core
|
||||
|
||||
out vec4 color;
|
||||
in vec2 tex_coord;
|
||||
|
||||
uniform float alpha_intensity;
|
||||
uniform sampler2D tex_T0;
|
||||
|
||||
void main() {
|
||||
vec4 tex = texture(tex_T0, tex_coord);
|
||||
tex.w *= alpha_intensity;
|
||||
color = tex;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
#version 430 core
|
||||
|
||||
layout (location = 0) in vec2 position_in;
|
||||
layout (location = 1) in vec2 tex_coord_in;
|
||||
|
||||
out vec2 tex_coord;
|
||||
uniform float scale;
|
||||
void main() {
|
||||
gl_Position = vec4(position_in.x * scale - (1 - scale), position_in.y * scale - (1 - scale), 0.5, 1.0);
|
||||
tex_coord = tex_coord_in;
|
||||
}
|
@ -9,14 +9,21 @@
|
||||
|
||||
|
||||
(defun ocean-mid-setup-constants ((arg0 ocean-mid-constants))
|
||||
"Generate the ocean VU1 renderer constants in-place."
|
||||
|
||||
;; the usual camera math
|
||||
(let ((v1-0 *math-camera*))
|
||||
(set! (-> arg0 hmge-scale quad) (-> v1-0 hmge-scale quad))
|
||||
(set! (-> arg0 inv-hmge-scale quad) (-> v1-0 inv-hmge-scale quad))
|
||||
(set! (-> arg0 hvdf-offset quad) (-> v1-0 hvdf-off quad))
|
||||
(set-vector! (-> arg0 fog) (-> v1-0 pfog0) (-> v1-0 fog-min) (-> v1-0 fog-max) 3072.0)
|
||||
)
|
||||
|
||||
;; is this 393216 the size of a triangle? (96 meters)
|
||||
(set-vector! (-> arg0 constants) 0.5 0.5 0.0 393216.0)
|
||||
(set-vector! (-> arg0 constants2) 0.5 0.5 1.0 0.0)
|
||||
|
||||
|
||||
(let ((v1-3 *ocean-subdivide-draw-mode*))
|
||||
(cond
|
||||
((zero? v1-3)
|
||||
@ -258,6 +265,8 @@
|
||||
(set-vector! (-> arg0 index-table 5) 18 24 21 0)
|
||||
(set-vector! (-> arg0 index-table 6) 9 12 12 0)
|
||||
(set-vector! (-> arg0 index-table 7) 0 0 3 0)
|
||||
|
||||
|
||||
(set-vector! (-> arg0 pos0) 0.0 0.0 0.0 1.0)
|
||||
(set-vector! (-> arg0 pos1) 393216.0 0.0 0.0 1.0)
|
||||
(set-vector! (-> arg0 pos2) 0.0 0.0 393216.0 1.0)
|
||||
@ -265,9 +274,8 @@
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function ocean-mid-add-constants
|
||||
;; INFO: Return type mismatch pointer vs none.
|
||||
(defun ocean-mid-add-constants ((arg0 dma-buffer))
|
||||
"Generate DMA for loading ocean-mid constants to VU1 data memory."
|
||||
(let* ((a1-0 36)
|
||||
(v1-0 arg0)
|
||||
(a0-1 (the-as object (-> v1-0 base)))
|
||||
@ -279,6 +287,7 @@
|
||||
)
|
||||
(set! (-> v1-0 base) (&+ (the-as pointer a0-1) 16))
|
||||
)
|
||||
;; generate the constants in place.
|
||||
(ocean-mid-setup-constants (the-as ocean-mid-constants (-> arg0 base)))
|
||||
(&+! (-> arg0 base) 576)
|
||||
(none)
|
||||
@ -509,9 +518,10 @@
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function ocean-mid-add-upload
|
||||
;; Used lq/sq
|
||||
(defun ocean-mid-add-upload ((arg0 dma-buffer) (arg1 int) (arg2 int) (arg3 int) (arg4 int) (arg5 float))
|
||||
"Add DMA data to upload data needed to draw an ocean tile."
|
||||
|
||||
;; calculate the location of the tile.
|
||||
(let ((gp-0 (new-stack-vector0)))
|
||||
(let ((v1-1 (-> *ocean-map* start-corner)))
|
||||
(set! (-> gp-0 x) (+ (-> v1-1 x) (* 3145728.0 (the float arg2))))
|
||||
@ -519,7 +529,11 @@
|
||||
(set! (-> gp-0 z) (+ (-> v1-1 z) (* 3145728.0 (the float arg1))))
|
||||
)
|
||||
(set! (-> gp-0 w) 1.0)
|
||||
|
||||
;; compute combined matrix
|
||||
(ocean-mid-add-matrices arg0 gp-0)
|
||||
|
||||
;; upload color.
|
||||
(let ((v1-4 (+ (the-as uint (-> *ocean-map* ocean-colors)) (* (+ (* 416 arg1) (* arg2 8)) 4))))
|
||||
(dotimes (a0-6 9)
|
||||
(let* ((a1-3 arg0)
|
||||
@ -538,6 +552,10 @@
|
||||
(+! v1-4 208)
|
||||
)
|
||||
)
|
||||
|
||||
;; upload "mid masks".
|
||||
;; these allow some zones to be skipped.
|
||||
;; using 0 will draw, using 1 willl skip.
|
||||
(let* ((a2-3 1)
|
||||
(v1-7 arg0)
|
||||
(a0-7 (the-as object (-> v1-7 base)))
|
||||
@ -553,10 +571,15 @@
|
||||
(let ((a0-12 (-> *ocean-map* ocean-mid-masks data arg3)))
|
||||
(set! (-> *ocean-work* mid-mask-ptrs arg4) (the-as (pointer int64) v1-8))
|
||||
(set! (-> (the-as (pointer uint64) v1-8)) (-> a0-12 dword))
|
||||
;; (set! (-> (the-as (pointer uint64) v1-8)) #xffffffffffffffff)
|
||||
)
|
||||
(set! (-> (the-as (pointer uint64) v1-8) 1) (the-as uint 0))
|
||||
)
|
||||
(&+! (-> arg0 base) 16)
|
||||
|
||||
;; when the camera is very close, we need to do additional checking.
|
||||
;; I believe this checks which subtiles will be skipped by the renderer
|
||||
;; and adds them to the camera masks.
|
||||
(when (< arg5 556091.4)
|
||||
(let* ((v1-12 (-> *math-camera* trans))
|
||||
(s5-1 (&-> *ocean-work* mid-camera-masks arg4))
|
||||
@ -694,6 +717,7 @@
|
||||
(set! (-> a1-2 z) (+ (-> v1-1 z) (* 393216.0 (the float arg1))))
|
||||
)
|
||||
(set! (-> a1-2 w) 1.0)
|
||||
;; (format 0 "~`vector`P~%" (-> *ocean-map* start-corner))
|
||||
(ocean-mid-add-matrices arg0 a1-2)
|
||||
)
|
||||
(let* ((a1-3 9)
|
||||
@ -982,6 +1006,41 @@
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun sphere-cull-for-ocean ((arg0 vector))
|
||||
"NOTE: added in PC port"
|
||||
|
||||
(local-vars (v1-0 uint128) (v1-1 uint128) (v1-2 uint128))
|
||||
(rlet ((acc :class vf)
|
||||
(vf0 :class vf)
|
||||
(vf10 :class vf)
|
||||
(vf16 :class vf)
|
||||
(vf17 :class vf)
|
||||
(vf18 :class vf)
|
||||
(vf19 :class vf)
|
||||
(vf9 :class vf)
|
||||
)
|
||||
(init-vf0-vector)
|
||||
(let ((v1-5 *math-camera*))
|
||||
;; note: these are for sphere cull.
|
||||
(.lvf vf16 (&-> v1-5 plane 0 quad))
|
||||
(.lvf vf17 (&-> v1-5 plane 1 quad))
|
||||
(.lvf vf18 (&-> v1-5 plane 2 quad))
|
||||
(.lvf vf19 (&-> v1-5 plane 3 quad))
|
||||
)
|
||||
|
||||
(.lvf vf10 (&-> arg0 quad))
|
||||
(.mul.x.vf acc vf16 vf10)
|
||||
(.add.mul.y.vf acc vf17 vf10 acc)
|
||||
(.add.mul.z.vf acc vf18 vf10 acc)
|
||||
(.sub.mul.w.vf vf9 vf19 vf0 acc)
|
||||
(.add.w.vf vf9 vf9 vf10)
|
||||
(.mov v1-0 vf9)
|
||||
(.pcgtw v1-1 0 v1-0)
|
||||
(.ppach v1-2 (the-as uint128 0) v1-1)
|
||||
(zero? (the-as int v1-2))
|
||||
)
|
||||
)
|
||||
|
||||
;; definition for function draw-ocean-mid-seams
|
||||
;; INFO: Return type mismatch symbol vs none.
|
||||
(defun draw-ocean-mid-seams ((arg0 dma-buffer))
|
||||
@ -1004,7 +1063,7 @@
|
||||
(while (>= s2-0 s3-0)
|
||||
(set! (-> sv-36 x) (+ 196608.0 (* 393216.0 (the float s3-0)) (-> *ocean-map* start-corner x)))
|
||||
(set! (-> sv-36 z) (+ 196608.0 (* 393216.0 (the float s5-0)) (-> *ocean-map* start-corner z)))
|
||||
(when (sphere-cull sv-36)
|
||||
(when (sphere-cull-for-ocean sv-36)
|
||||
(cond
|
||||
((= s5-0 sv-34)
|
||||
(ocean-mid-add-upload-top arg0 s5-0 s3-0)
|
||||
@ -1031,10 +1090,60 @@
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function draw-ocean-mid
|
||||
;; INFO: Return type mismatch int vs none.
|
||||
;; Used lq/sq
|
||||
;; ADDED for PC Port
|
||||
(defun debug-draw-ocean-tile ((y int) (x int) (color0 rgba) (color1 rgba) (masks int))
|
||||
;;3145728.0
|
||||
(let* ((ps (-> *ocean-map* start-corner))
|
||||
(p0 (vector-copy! (new-stack-vector0) ps))
|
||||
(p1 (vector-copy! (new-stack-vector0) ps))
|
||||
(p2 (vector-copy! (new-stack-vector0) ps))
|
||||
(p1s (vector-copy! (new-stack-vector0) ps))
|
||||
(p2s (vector-copy! (new-stack-vector0) ps))
|
||||
(p3 (vector-copy! (new-stack-vector0) ps))
|
||||
(x0 (* 3145728.0 (the float x)))
|
||||
(y0 (* 3145728.0 (the float y)))
|
||||
|
||||
)
|
||||
(+! (-> p0 x) x0)
|
||||
(+! (-> p0 z) y0)
|
||||
|
||||
(+! (-> p1 x) (+ x0 3145728.0))
|
||||
(+! (-> p1 z) y0)
|
||||
|
||||
(+! (-> p2 x) x0)
|
||||
(+! (-> p2 z) (+ y0 3145728.0))
|
||||
|
||||
(+! (-> p1s x) (+ x0 314572.0))
|
||||
(+! (-> p1s z) y0)
|
||||
|
||||
(+! (-> p2s x) x0)
|
||||
(+! (-> p2s z) (+ y0 314572.0))
|
||||
|
||||
(+! (-> p3 x) (+ x0 3145728.0))
|
||||
(+! (-> p3 z) (+ y0 3145728.0))
|
||||
|
||||
(add-debug-flat-triangle #t (bucket-id debug-draw1) p0 p1s p2s color0)
|
||||
;; (add-debug-flat-triangle #t (bucket-id debug-draw1) p3 p1 p2 color0)
|
||||
(add-debug-outline-triangle #t (bucket-id debug-draw1) p0 p1 p2 color1)
|
||||
(add-debug-outline-triangle #t (bucket-id debug-draw1) p3 p1 p2 color1)
|
||||
(format (clear *temp-string*) "o: ~d ~d ~d ~b" x y (+ (* 6 y) x) masks)
|
||||
|
||||
(add-debug-text-3d
|
||||
#t
|
||||
(bucket-id debug-draw1)
|
||||
*temp-string*
|
||||
p0
|
||||
(font-color orange-red)
|
||||
(the vector2h #f)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun draw-ocean-mid ((arg0 dma-buffer))
|
||||
"Main function to draw the 'mid' ocean
|
||||
The mid ocean is used to draw the non-transparent ocean parts.
|
||||
There is a large 6x6 grid of tiles.
|
||||
Tiles that are closer to the camera have an environment mapping effect applied."
|
||||
(rlet ((vf16 :class vf)
|
||||
(vf17 :class vf)
|
||||
(vf18 :class vf)
|
||||
@ -1044,11 +1153,16 @@
|
||||
(vf22 :class vf)
|
||||
(vf23 :class vf)
|
||||
)
|
||||
|
||||
;; first, reset all masks to 0
|
||||
(dotimes (v1-0 36)
|
||||
(set! (-> *ocean-work* mid-mask-ptrs v1-0) (the-as (pointer int64) #f))
|
||||
(set! (-> *ocean-work* mid-camera-masks v1-0) (the-as uint 0))
|
||||
)
|
||||
;; upload VU1 program
|
||||
(dma-buffer-add-vu-function arg0 ocean-mid-block 1)
|
||||
|
||||
;; set up base+offset for the VU1 program uploads
|
||||
(let* ((v1-3 arg0)
|
||||
(a0-6 (the-as object (-> v1-3 base)))
|
||||
)
|
||||
@ -1057,8 +1171,14 @@
|
||||
(set! (-> (the-as dma-packet a0-6) vif1) (new 'static 'vif-tag :imm #x76 :cmd (vif-cmd offset)))
|
||||
(set! (-> v1-3 base) (&+ (the-as pointer a0-6) 16))
|
||||
)
|
||||
|
||||
;; upload ocean constants
|
||||
(ocean-mid-add-constants arg0)
|
||||
|
||||
;; run program to initialize VU1 renderer
|
||||
(ocean-mid-add-call arg0 0)
|
||||
|
||||
;; set up VF registers for sphere culling.
|
||||
(let ((v1-5 *math-camera*))
|
||||
(.lvf vf16 (&-> v1-5 plane 0 quad))
|
||||
(.lvf vf17 (&-> v1-5 plane 1 quad))
|
||||
@ -1070,21 +1190,30 @@
|
||||
(.lvf vf23 (&-> v1-5 guard-plane 3 quad))
|
||||
)
|
||||
(set! (-> (new 'stack-no-clear 'vector) quad) (the-as uint128 0))
|
||||
|
||||
;; draw tiles!
|
||||
(let ((s5-0 (-> *math-camera* trans)))
|
||||
(dotimes (s4-0 6)
|
||||
(dotimes (s3-0 6)
|
||||
(let* ((s2-0 (+ (* 6 s4-0) s3-0))
|
||||
(s1-0 (-> *ocean-map* ocean-spheres spheres s2-0))
|
||||
(dotimes (s4-0 6) ;; x?
|
||||
(dotimes (s3-0 6) ;; y?
|
||||
(let* ((s2-0 (+ (* 6 s4-0) s3-0)) ;; tile index
|
||||
(s1-0 (-> *ocean-map* ocean-spheres spheres s2-0)) ;; vis sphere of ocean
|
||||
(s0-0 (-> (the-as (pointer int16) (+ (* s2-0 2) (the-as int (-> *ocean-map* ocean-mid-indices))))))
|
||||
)
|
||||
(when (sphere-cull s1-0)
|
||||
;; (format 0 "draw ocean tile: ~d x ~d = ~d index ~d~%" s4-0 s3-0 s2-0 s0-0)
|
||||
;; (debug-draw-ocean-tile s4-0 s3-0 (new 'static 'rgba :r #x80 :a #x80) (new 'static 'rgba :g #x80 :a #x80) s0-0)
|
||||
(when (sphere-cull-for-ocean s1-0)
|
||||
;;(format 0 " vis!~%")
|
||||
(cond
|
||||
((< s0-0 0)
|
||||
;; (format 0 " skip tile.~%")
|
||||
)
|
||||
((let ((f30-0 (- (vector-vector-distance s1-0 s5-0) (-> s1-0 w))))
|
||||
(ocean-mid-add-upload arg0 s4-0 s3-0 s0-0 s2-0 f30-0)
|
||||
(< f30-0 786432.0)
|
||||
;; HACK
|
||||
;; #t
|
||||
)
|
||||
;; (format 0 " draw env map~%")
|
||||
(ocean-mid-add-call arg0 73)
|
||||
(+! (-> *terrain-stats* ocean-mid fragments) 1)
|
||||
(+! (-> *terrain-stats* ocean-mid tris) 256)
|
||||
@ -1102,6 +1231,13 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
; (dotimes (i 36)
|
||||
; (format 0 "tidx: ~d ~X~%" i (-> *ocean-work* mid-camera-masks i))
|
||||
; )
|
||||
|
||||
;; for now, skip seams.
|
||||
;; when it's both on and cam is low
|
||||
(when (not (or *ocean-near-off* (< 196608.0 (fabs (-> *math-camera* trans y)))))
|
||||
(let ((a1-11 48)
|
||||
(a2-2 0)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -667,7 +667,8 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
; (when (not (or *ocean-near-off* (or *ocean-mid-off* (< 196608.0 (fabs (-> *math-camera* trans y))))))
|
||||
(when (not (or *ocean-near-off* (or *ocean-mid-off* (< 196608.0 (fabs (-> *math-camera* trans y))))))
|
||||
; (format *stdcon* "draw near~%")
|
||||
; (let* ((s5-1 (-> *display* frames (-> *display* on-screen) frame global-buf))
|
||||
; (gp-2 (-> s5-1 base))
|
||||
; )
|
||||
@ -689,7 +690,7 @@
|
||||
; )
|
||||
; )
|
||||
; )
|
||||
; )
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user