This commit is contained in:
water111 2022-02-25 23:25:49 -05:00 committed by GitHub
parent b55de36b27
commit 382ec1d1c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 199 additions and 158 deletions

View file

@ -92,6 +92,8 @@ struct SharedRenderState {
bool render_debug = false;
bool enable_merc_xgkick = true;
bool enable_generic_xgkick = true;
math::Vector<u8, 4> fog_color;
float fog_intensity = 1.f;
void reset();
bool has_camera_planes = false;

View file

@ -6,8 +6,8 @@
#include "third-party/imgui/imgui.h"
#include "common/util/Assert.h"
DirectRenderer::DirectRenderer(const std::string& name, BucketId my_id, int batch_size, Mode mode)
: BucketRenderer(name, my_id), m_prim_buffer(batch_size), m_mode(mode) {
DirectRenderer::DirectRenderer(const std::string& name, BucketId my_id, int batch_size)
: BucketRenderer(name, my_id), m_prim_buffer(batch_size) {
glGenBuffers(1, &m_ogl.vertex_buffer);
glGenVertexArrays(1, &m_ogl.vao);
glBindVertexArray(m_ogl.vao);
@ -17,12 +17,12 @@ DirectRenderer::DirectRenderer(const std::string& name, BucketId my_id, int batc
glBufferData(GL_ARRAY_BUFFER, m_ogl.vertex_buffer_bytes, nullptr,
GL_STREAM_DRAW); // todo stream?
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, // location 0 in the shader
4, // 4 floats per vert (w unused)
GL_FLOAT, // floats
GL_TRUE, // normalized, ignored,
sizeof(Vertex), //
(void*)offsetof(Vertex, xyz) // offset in array (why is this a pointer...)
glVertexAttribPointer(0, // location 0 in the shader
4, // 4 floats per vert (w unused)
GL_FLOAT, // floats
GL_TRUE, // normalized, ignored,
sizeof(Vertex), //
(void*)offsetof(Vertex, xyzf) // offset in array (why is this a pointer...)
);
glEnableVertexAttribArray(1);
@ -123,10 +123,6 @@ void DirectRenderer::draw_debug_window() {
ImGui::SameLine();
ImGui::Checkbox("no mip", &m_debug_state.disable_mipmap);
if (m_mode == Mode::SPRITE_CPU) {
ImGui::Checkbox("draw1", &m_sprite_mode.do_first_draw);
}
ImGui::Text("Triangles: %d", m_stats.triangles);
ImGui::SameLine();
ImGui::Text("Draws: %d", m_stats.draw_calls);
@ -193,6 +189,8 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state, ScopedProfil
if (m_debug_state.disable_texture) {
// a bit of a hack, this forces the non-textured shader always.
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
m_blend_state_needs_gl_update = true;
m_prim_gl_state_needs_gl_update = true;
}
if (m_debug_state.red) {
@ -216,23 +214,8 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state, ScopedProfil
m_prim_buffer.vertices.data(), GL_STREAM_DRAW);
int draw_count = 0;
if (m_mode == Mode::SPRITE_CPU) {
if (!m_prim_gl_state.texture_enable) {
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
} else {
// ASSERT(m_global_texture_state.tcc);
ASSERT(m_prim_gl_state.texture_enable);
render_state->shaders[ShaderId::SPRITE_CPU].activate();
}
if (m_sprite_mode.do_first_draw) {
glDrawArrays(GL_TRIANGLES, 0, m_prim_buffer.vert_count);
draw_count++;
}
} else {
glDrawArrays(GL_TRIANGLES, 0, m_prim_buffer.vert_count);
draw_count++;
}
glDrawArrays(GL_TRIANGLES, 0, m_prim_buffer.vert_count);
draw_count++;
if (m_debug_state.wireframe) {
render_state->shaders[ShaderId::DEBUG_RED].activate();
@ -240,6 +223,8 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state, ScopedProfil
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDrawArrays(GL_TRIANGLES, 0, m_prim_buffer.vert_count);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
m_blend_state_needs_gl_update = true;
m_prim_gl_state_needs_gl_update = true;
draw_count++;
}
@ -272,25 +257,21 @@ void DirectRenderer::update_gl_prim(SharedRenderState* render_state) {
ASSERT(false);
}
}
if (m_mode == Mode::SPRITE_CPU) {
render_state->shaders[ShaderId::SPRITE_CPU].activate();
} else if (m_mode == Mode::SKY) {
ASSERT(false);
} else {
render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].activate();
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
"alpha_reject"),
alpha_reject);
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
"color_mult"),
m_ogl.color_mult);
}
render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].activate();
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
"alpha_reject"),
alpha_reject);
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
"color_mult"),
m_ogl.color_mult);
glUniform4f(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
"fog_color"),
render_state->fog_color[0], render_state->fog_color[1], render_state->fog_color[2],
render_state->fog_intensity);
} else {
if (m_mode == Mode::SKY) {
render_state->shaders[ShaderId::SKY].activate();
} else {
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
}
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
}
if (state.fogging_enable) {
// ASSERT(false);
@ -932,7 +913,8 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
bool advance) {
ASSERT(z < (1 << 24));
(void)f; // TODO: do something with this.
if (m_my_id == BucketId::GENERIC_PRIS) {
if (m_my_id == BucketId::MERC_TFRAG_TEX_LEVEL0) {
// fmt::print("0x{:x}, 0x{:x}, 0x{:x}\n", x, y, z);
}
if (m_prim_buffer.is_full()) {
@ -945,13 +927,14 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
m_prim_building.st_reg.x(), m_prim_building.st_reg.y(), m_prim_building.Q);
m_prim_building.building_rgba.at(m_prim_building.building_idx) = m_prim_building.rgba_reg;
m_prim_building.building_vert.at(m_prim_building.building_idx) =
math::Vector<u32, 3>{x << 16, y << 16, z << 8};
math::Vector<u32, 4>{x << 16, y << 16, z << 8, f};
m_prim_building.building_idx++;
int tex_unit = get_texture_unit_for_current_reg(render_state, prof);
bool tcc = m_buffered_tex_state[tex_unit].tcc;
bool decal = m_buffered_tex_state[tex_unit].decal;
bool fge = m_prim_gl_state.fogging_enable;
switch (m_prim_building.kind) {
case GsPrim::Kind::SPRITE: {
@ -962,8 +945,8 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
auto& corner2_vert = m_prim_building.building_vert[1];
auto& corner2_rgba = m_prim_building.building_rgba[1];
// should use most recent vertex z.
math::Vector<u32, 3> corner3_vert{corner1_vert[0], corner2_vert[1], corner2_vert[2]};
math::Vector<u32, 3> corner4_vert{corner2_vert[0], corner1_vert[1], corner2_vert[2]};
math::Vector<u32, 4> corner3_vert{corner1_vert[0], corner2_vert[1], corner2_vert[2]};
math::Vector<u32, 4> corner4_vert{corner2_vert[0], corner1_vert[1], corner2_vert[2]};
if (m_prim_gl_state.gouraud_enable) {
// I'm not really sure what the GS does here.
@ -972,12 +955,12 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
auto& corner3_rgba = corner2_rgba;
auto& corner4_rgba = corner2_rgba;
m_prim_buffer.push(corner1_rgba, corner1_vert, {}, 0, tcc, decal);
m_prim_buffer.push(corner3_rgba, corner3_vert, {}, 0, tcc, decal);
m_prim_buffer.push(corner2_rgba, corner2_vert, {}, 0, tcc, decal);
m_prim_buffer.push(corner2_rgba, corner2_vert, {}, 0, tcc, decal);
m_prim_buffer.push(corner4_rgba, corner4_vert, {}, 0, tcc, decal);
m_prim_buffer.push(corner1_rgba, corner1_vert, {}, 0, tcc, decal);
m_prim_buffer.push(corner1_rgba, corner1_vert, {}, 0, tcc, decal, fge);
m_prim_buffer.push(corner3_rgba, corner3_vert, {}, 0, tcc, decal, fge);
m_prim_buffer.push(corner2_rgba, corner2_vert, {}, 0, tcc, decal, fge);
m_prim_buffer.push(corner2_rgba, corner2_vert, {}, 0, tcc, decal, fge);
m_prim_buffer.push(corner4_rgba, corner4_vert, {}, 0, tcc, decal, fge);
m_prim_buffer.push(corner1_rgba, corner1_vert, {}, 0, tcc, decal, fge);
m_prim_building.building_idx = 0;
}
} break;
@ -993,7 +976,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
if (advance) {
for (int i = 0; i < 3; i++) {
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
m_prim_building.building_stq[i], tex_unit, tcc, decal);
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
}
}
}
@ -1005,7 +988,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
m_prim_building.building_idx = 0;
for (int i = 0; i < 3; i++) {
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
m_prim_building.building_stq[i], tex_unit, tcc, decal);
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
}
}
break;
@ -1021,15 +1004,15 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
}
for (int i = 0; i < 3; i++) {
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
m_prim_building.building_stq[i], tex_unit, tcc, decal);
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
}
}
} break;
case GsPrim::Kind::LINE: {
if (m_prim_building.building_idx == 2) {
math::Vector<double, 3> pt0 = m_prim_building.building_vert[0].cast<double>();
math::Vector<double, 3> pt1 = m_prim_building.building_vert[1].cast<double>();
math::Vector<double, 3> pt0 = m_prim_building.building_vert[0].xyz().cast<double>();
math::Vector<double, 3> pt1 = m_prim_building.building_vert[1].xyz().cast<double>();
auto normal = (pt1 - pt0).normalized().cross(math::Vector<double, 3>{0, 0, 1});
double line_width = (1 << 19);
@ -1040,15 +1023,19 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
math::Vector<double, 3> b = pt1 + normal * line_width;
math::Vector<double, 3> c = pt0 - normal * line_width;
math::Vector<double, 3> d = pt1 - normal * line_width;
math::Vector<u32, 4> ai{a.x(), a.y(), a.z(), 0};
math::Vector<u32, 4> bi{b.x(), b.y(), b.z(), 0};
math::Vector<u32, 4> ci{c.x(), c.y(), c.z(), 0};
math::Vector<u32, 4> di{d.x(), d.y(), d.z(), 0};
// ACB:
m_prim_buffer.push(m_prim_building.building_rgba[0], a.cast<u32>(), {}, 0, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[0], c.cast<u32>(), {}, 0, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[1], b.cast<u32>(), {}, 0, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[0], ai, {}, 0, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false);
// b c d
m_prim_buffer.push(m_prim_building.building_rgba[1], b.cast<u32>(), {}, 0, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[0], c.cast<u32>(), {}, 0, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[1], d.cast<u32>(), {}, 0, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[1], di, {}, 0, false, false, false);
//
m_prim_building.building_idx = 0;
@ -1115,19 +1102,22 @@ DirectRenderer::PrimitiveBuffer::PrimitiveBuffer(int max_triangles) {
}
void DirectRenderer::PrimitiveBuffer::push(const math::Vector<u8, 4>& rgba,
const math::Vector<u32, 3>& vert,
const math::Vector<u32, 4>& vert,
const math::Vector<float, 3>& st,
int unit,
bool tcc,
bool decal) {
bool decal,
bool fog_enable) {
auto& v = vertices[vert_count];
v.rgba = rgba;
v.xyz[0] = (float)vert[0] / (float)UINT32_MAX;
v.xyz[1] = (float)vert[1] / (float)UINT32_MAX;
v.xyz[2] = (float)vert[2] / (float)UINT32_MAX;
v.xyzf[0] = (float)vert[0] / (float)UINT32_MAX;
v.xyzf[1] = (float)vert[1] / (float)UINT32_MAX;
v.xyzf[2] = (float)vert[2] / (float)UINT32_MAX;
v.xyzf[3] = (float)vert[3];
v.stq = st;
v.tex_unit = unit;
v.tcc = tcc;
v.decal = decal;
v.fog_enable = fog_enable;
vert_count++;
}

View file

@ -19,13 +19,7 @@
*/
class DirectRenderer : public BucketRenderer {
public:
// specializations of direct renderer to handle certain outputs.
enum class Mode {
NORMAL, // use for general debug drawing, font.
SPRITE_CPU, // use for sprites (does the appropriate alpha test tricks)
SKY // disables texture perspective correction
};
DirectRenderer(const std::string& name, BucketId my_id, int batch_size, Mode mode);
DirectRenderer(const std::string& name, BucketId my_id, int batch_size);
~DirectRenderer();
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
@ -199,7 +193,7 @@ class DirectRenderer : public BucketRenderer {
math::Vector<float, 2> st_reg;
std::array<math::Vector<u8, 4>, 3> building_rgba;
std::array<math::Vector<u32, 3>, 3> building_vert;
std::array<math::Vector<u32, 4>, 3> building_vert;
std::array<math::Vector<float, 3>, 3> building_stq;
int building_idx = 0;
int tri_strip_startup = 0;
@ -209,13 +203,14 @@ class DirectRenderer : public BucketRenderer {
} m_prim_building;
struct Vertex {
math::Vector<float, 4> xyz;
math::Vector<float, 4> xyzf;
math::Vector<float, 3> stq;
math::Vector<u8, 4> rgba;
u8 tex_unit;
u8 tcc;
u8 decal;
math::Vector<u8, 29> pad;
u8 fog_enable;
math::Vector<u8, 28> pad;
};
static_assert(sizeof(Vertex) == 64);
static_assert(offsetof(Vertex, tex_unit) == 32);
@ -229,11 +224,12 @@ class DirectRenderer : public BucketRenderer {
// leave 6 free on the end so we always have room to flush one last primitive.
bool is_full() { return max_verts < (vert_count + 18); }
void push(const math::Vector<u8, 4>& rgba,
const math::Vector<u32, 3>& vert,
const math::Vector<u32, 4>& vert,
const math::Vector<float, 3>& stq,
int unit,
bool tcc,
bool decal);
bool decal,
bool fog_enable);
} m_prim_buffer;
struct {
@ -273,6 +269,4 @@ class DirectRenderer : public BucketRenderer {
struct SpriteMode {
bool do_first_draw = true;
} m_sprite_mode;
Mode m_mode;
};

View file

@ -2,7 +2,7 @@
#include "third-party/imgui/imgui.h"
GenericRenderer::GenericRenderer(const std::string& name, BucketId my_id)
: BucketRenderer(name, my_id), m_direct(name, my_id, 0x4000, DirectRenderer::Mode::NORMAL) {}
: BucketRenderer(name, my_id), m_direct(name, my_id, 0x4000) {}
void GenericRenderer::render(DmaFollower& dma,
SharedRenderState* render_state,

View file

@ -3,8 +3,7 @@
#include "third-party/imgui/imgui.h"
MercRenderer::MercRenderer(const std::string& name, BucketId my_id)
: BucketRenderer(name, my_id),
m_direct(fmt::format("{}-dir", name), my_id, 0x30000, DirectRenderer::Mode::NORMAL) {
: BucketRenderer(name, my_id), m_direct(fmt::format("{}-dir", name), my_id, 0x30000) {
memset(m_buffer.data, 0, sizeof(m_buffer.data));
}

View file

@ -211,10 +211,8 @@ void OpenGLRenderer::init_bucket_renderers() {
sprite_renderers.push_back(std::make_unique<SpriteRenderer>("sprite-renderer", BucketId::SPRITE));
init_bucket_renderer<RenderMux>("sprite", BucketId::SPRITE, std::move(sprite_renderers)); // 66
init_bucket_renderer<DirectRenderer>("debug-draw-0", BucketId::DEBUG_DRAW_0, 0x20000,
DirectRenderer::Mode::NORMAL);
init_bucket_renderer<DirectRenderer>("debug-draw-1", BucketId::DEBUG_DRAW_1, 0x8000,
DirectRenderer::Mode::NORMAL);
init_bucket_renderer<DirectRenderer>("debug-draw-0", BucketId::DEBUG_DRAW_0, 0x20000);
init_bucket_renderer<DirectRenderer>("debug-draw-1", BucketId::DEBUG_DRAW_1, 0x8000);
// for now, for any unset renderers, just set them to an EmptyBucketRenderer.
for (size_t i = 0; i < m_bucket_renderers.size(); i++) {
@ -266,6 +264,10 @@ void OpenGLRenderer::render(DmaFollower dma, const RenderOptions& settings) {
m_profiler.draw();
}
if (settings.draw_small_profiler_window) {
m_profiler.draw_small_window();
}
if (settings.save_screenshot) {
finish_screenshot(settings.screenshot_path, settings.window_width_px, settings.window_height_px,
settings.lbox_width_px, settings.lbox_height_px);
@ -287,6 +289,7 @@ void OpenGLRenderer::serialize(Serializer& ser) {
void OpenGLRenderer::draw_renderer_selection_window() {
ImGui::Begin("Renderer Debug");
ImGui::SliderFloat("Fog Adjust", &m_render_state.fog_intensity, 0, 10);
ImGui::Checkbox("Sky CPU", &m_render_state.use_sky_cpu);
ImGui::Checkbox("Occlusion Cull", &m_render_state.use_occlusion_culling);
ImGui::Checkbox("Render Debug (slower)", &m_render_state.render_debug);
@ -348,7 +351,9 @@ void OpenGLRenderer::dispatch_buckets(DmaFollower dma, ScopedProfilerNode& prof)
ASSERT(default_regs_tag.kind == DmaTag::Kind::CNT);
ASSERT(default_regs_tag.qwc == 10);
// TODO verify data in here.
dma.read_and_advance();
auto default_data = dma.read_and_advance();
ASSERT(default_data.size_bytes > 148);
memcpy(m_render_state.fog_color.data(), default_data.data + 144, 4);
auto default_ret_tag = dma.current_tag();
ASSERT(default_ret_tag.qwc == 0);
ASSERT(default_ret_tag.kind == DmaTag::Kind::RET);

View file

@ -15,6 +15,7 @@ struct RenderOptions {
int lbox_width_px = 0;
bool draw_render_debug_window = false;
bool draw_profiler_window = false;
bool draw_small_profiler_window = false;
bool playing_from_dump = false;
bool save_screenshot = false;

View file

@ -88,6 +88,31 @@ void Profiler::draw() {
ImGui::End();
}
void Profiler::draw_small_window() {
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration |
ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
auto* p_open = &m_small_window_open;
const float PAD = 10.0f;
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
ImVec2 work_size = viewport->WorkSize;
ImVec2 window_pos, window_pos_pivot;
window_pos.x = (work_pos.x + PAD);
window_pos.y = (work_pos.y + work_size.y - PAD);
window_pos_pivot.x = 0.0f;
window_pos_pivot.y = 1.0f;
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
ImGui::SetNextWindowBgAlpha(0.85f); // Transparent background
if (ImGui::Begin("Profiler (short)", p_open, window_flags)) {
ImGui::Text(" tri: %7d\n", m_root.m_stats.triangles);
ImGui::Text(" DC: %4d\n", m_root.m_stats.draw_calls);
}
ImGui::End();
}
u32 name_to_color(const std::string& name) {
u64 val = std::hash<std::string>{}(name);
return colors::common_colors[val % colors::COLOR_COUNT] | 0xff000000;

View file

@ -67,6 +67,7 @@ class Profiler {
Profiler();
void clear();
void draw();
void draw_small_window();
void finish();
ProfilerNode* root() { return &m_root; }
@ -79,5 +80,6 @@ class Profiler {
};
int m_mode_selector = 0;
bool m_small_window_open = true;
ProfilerNode m_root;
};

View file

@ -25,19 +25,13 @@ enum class ShaderId {
TEST_SHADER = 0,
DIRECT_BASIC = 1,
DIRECT_BASIC_TEXTURED = 2,
// DIRECT_BASIC_TEXTURED_TCC0 = 3,
DEBUG_RED = 4,
SPRITE_CPU = 5,
// SPRITE_CPU_AFAIL = 6,
SKY = 7,
SKY_BLEND = 8,
// DEBUG_BUFFERED = 9,
// BUFFERED_TCC0 = 10,
// BUFFERED_TCC1 = 11,
TFRAG3 = 12,
TFRAG3_NO_TEX = 13,
SPRITE = 14,
SPRITE3 = 15,
DEBUG_RED = 3,
SKY = 4,
SKY_BLEND = 5,
TFRAG3 = 6,
TFRAG3_NO_TEX = 7,
SPRITE = 8,
SPRITE3 = 9,
MAX_SHADERS
};

View file

@ -120,8 +120,7 @@ void SkyBlendHandler::draw_debug_window() {
}
SkyRenderer::SkyRenderer(const std::string& name, BucketId my_id)
: BucketRenderer(name, my_id),
m_direct_renderer("sky-direct", my_id, 100, DirectRenderer::Mode::NORMAL) {}
: BucketRenderer(name, my_id), m_direct_renderer("sky-direct", my_id, 100) {}
void SkyRenderer::render(DmaFollower& dma,
SharedRenderState* render_state,

View file

@ -92,6 +92,7 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
ImGui::MenuItem("Frame Time Plot", nullptr, &m_draw_frame_time);
ImGui::MenuItem("Render Debug", nullptr, &m_draw_debug);
ImGui::MenuItem("Profiler", nullptr, &m_draw_profiler);
ImGui::MenuItem("Small Profiler", nullptr, &small_profiler);
ImGui::EndMenu();
}

View file

@ -67,6 +67,7 @@ class OpenGlDebugGui {
float target_fps = 60.f;
bool experimental_accurate_lag = false;
bool sleep_in_frame_limiter = true;
bool small_profiler = true;
private:
FrameTimeRecorder m_frame_timer;

View file

@ -6,8 +6,10 @@ in vec4 fragment_color;
in vec3 tex_coord;
uniform float alpha_reject;
uniform float color_mult;
uniform vec4 fog_color;
in flat uvec4 tex_info;
in float fog;
layout (binding = 20) uniform sampler2D tex_T0;
layout (binding = 21) uniform sampler2D tex_T1;
@ -21,49 +23,52 @@ layout (binding = 28) uniform sampler2D tex_T8;
layout (binding = 29) uniform sampler2D tex_T9;
vec4 sample_tex(vec2 coord, uint unit) {
switch (unit) {
case 0: return texture(tex_T0, coord);
case 1: return texture(tex_T1, coord);
case 2: return texture(tex_T2, coord);
case 3: return texture(tex_T3, coord);
case 4: return texture(tex_T4, coord);
case 5: return texture(tex_T5, coord);
case 6: return texture(tex_T6, coord);
case 7: return texture(tex_T7, coord);
case 8: return texture(tex_T8, coord);
case 9: return texture(tex_T9, coord);
default: return vec4(1.0, 0, 1.0, 1.0);
}
switch (unit) {
case 0: return texture(tex_T0, coord);
case 1: return texture(tex_T1, coord);
case 2: return texture(tex_T2, coord);
case 3: return texture(tex_T3, coord);
case 4: return texture(tex_T4, coord);
case 5: return texture(tex_T5, coord);
case 6: return texture(tex_T6, coord);
case 7: return texture(tex_T7, coord);
case 8: return texture(tex_T8, coord);
case 9: return texture(tex_T9, coord);
default : return vec4(1.0, 0, 1.0, 1.0);
}
}
void main() {
vec4 T0 = sample_tex(tex_coord.xy / tex_coord.z, tex_info.x);
// y is tcc
// z is decal
vec4 T0 = sample_tex(tex_coord.xy / tex_coord.z, tex_info.x);
// y is tcc
// z is decal
if (tex_info.y == 0) {
if (tex_info.z == 0) {
// modulate + no tcc
color.xyz = fragment_color.xyz * T0.xyz;
color.w = fragment_color.w;
if (tex_info.y == 0) {
if (tex_info.z == 0) {
// modulate + no tcc
color.xyz = fragment_color.xyz * T0.xyz;
color.w = fragment_color.w;
} else {
// decal + no tcc
color.xyz = T0.xyz * 0.5;
color.w = fragment_color.w;
}
} else {
// decal + no tcc
color.xyz = T0.xyz * 0.5;
color.w = fragment_color.w;
if (tex_info.z == 0) {
// modulate + tcc
color = fragment_color * T0;
} else {
// decal + tcc
color.xyz = T0.xyz * 0.5;
color.w = T0.w;
}
}
} else {
if (tex_info.z == 0) {
// modulate + tcc
color = fragment_color * T0;
} else {
// decal + tcc
color.xyz = T0.xyz * 0.5;
color.w = T0.w;
color *= 2;
color.xyz *= color_mult;
if (color.a < alpha_reject) {
discard;
}
if (tex_info.w == 1) {
color.xyz = mix(color.xyz, fog_color.xyz / 255., clamp(fog_color.w * (1 - fog), 0, 1));
}
}
color *= 2;
color.xyz *= color_mult;
if (color.a < alpha_reject) {
discard;
}
}

View file

@ -1,11 +1,12 @@
#version 430 core
layout (location = 0) in vec3 position_in;
layout (location = 0) in vec4 position_in;
layout (location = 1) in vec4 rgba_in;
layout (location = 2) in vec3 tex_coord_in;
out vec4 fragment_color;
out vec3 tex_coord;
out float fog;
// putting all texture info stuff here so it's easier to copy-paste
layout (location = 3) in uvec4 tex_info_in;
@ -18,4 +19,5 @@ void main() {
fragment_color = vec4(rgba_in.x, rgba_in.y, rgba_in.z, rgba_in.w * 2.);
tex_coord = tex_coord_in;
tex_info = tex_info_in;
fog = position_in.w / 255.;
}

View file

@ -4,10 +4,12 @@ out vec4 color;
in vec4 fragment_color;
in vec3 tex_coord;
in float fogginess;
uniform sampler2D tex_T0;
uniform float alpha_min;
uniform float alpha_max;
uniform vec4 fog_color;
void main() {
//vec4 T0 = texture(tex_T0, tex_coord);
@ -21,4 +23,6 @@ void main() {
if (color.a > alpha_max) {
discard;
}
color.xyz = mix(color.xyz, fog_color.xyz / 255., clamp(fogginess/255 * fog_color.w, 0., 1.));
}

View file

@ -7,10 +7,13 @@ layout (location = 2) in int time_of_day_index;
uniform vec4 hvdf_offset;
uniform mat4 camera;
uniform float fog_constant;
uniform float fog_min;
uniform float fog_max;
layout (binding = 10) uniform sampler1D tex_T1; // note, sampled in the vertex shader on purpose.
out vec4 fragment_color;
out vec3 tex_coord;
out float fogginess;
void main() {
@ -38,6 +41,11 @@ void main() {
// compute Q
float Q = fog_constant / transformed[3];
float fog1 = -transformed.w + hvdf_offset.w;
float fog2 = min(fog1, fog_max);
float fog3 = max(fog2, fog_min);
fogginess = 255 - fog3;
// perspective divide!
transformed.xyz *= Q;

View file

@ -119,7 +119,7 @@ void TFragment::render(DmaFollower& dma,
m_tfrag3.setup_for_level(m_tree_kinds, level_name, render_state);
TfragRenderSettings settings;
settings.hvdf_offset = m_tfrag_data.hvdf_offset;
settings.fog_x = m_tfrag_data.fog.x();
settings.fog = m_tfrag_data.fog;
memcpy(settings.math_camera.data(), &m_buffered_data[0].pad[TFragDataMem::TFragMatrix0 * 16],
64);
settings.tree_idx = 0;
@ -175,7 +175,7 @@ void TFragment::render(DmaFollower& dma,
m_many_level_render.tie_level_renderers[i]->setup_for_level(level_names[i], render_state);
TfragRenderSettings settings;
settings.hvdf_offset = m_tfrag_data.hvdf_offset;
settings.fog_x = m_tfrag_data.fog.x();
settings.fog = m_tfrag_data.fog;
memcpy(settings.math_camera.data(),
&m_buffered_data[0].pad[TFragDataMem::TFragMatrix0 * 16], 64);
settings.tree_idx = 0;

View file

@ -499,7 +499,7 @@ void Tfrag3::render_tree_cull_debug(const TfragRenderSettings& settings,
settings.hvdf_offset[3]);
glUniform1f(
glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3_NO_TEX].id(), "fog_constant"),
settings.fog_x);
settings.fog.x());
// glDisable(GL_DEPTH_TEST);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GEQUAL);

View file

@ -411,7 +411,7 @@ void Tie3::render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfi
TfragRenderSettings settings;
settings.hvdf_offset = m_pc_port_data.hvdf_off;
settings.fog_x = m_pc_port_data.fogx;
settings.fog = m_pc_port_data.fog;
memcpy(settings.math_camera.data(), m_pc_port_data.camera[0].data(), 64);
settings.tree_idx = 0;
@ -703,7 +703,7 @@ void Tie3::render_tree(int idx,
settings.hvdf_offset[3]);
glUniform1f(
glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3_NO_TEX].id(), "fog_constant"),
settings.fog_x);
settings.fog.x());
glDisable(GL_BLEND);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDrawElements(GL_TRIANGLE_STRIP, draw_size, GL_UNSIGNED_INT, (void*)offset);

View file

@ -150,7 +150,14 @@ void first_tfrag_draw_setup(const TfragRenderSettings& settings, SharedRenderSta
settings.hvdf_offset[0], settings.hvdf_offset[1], settings.hvdf_offset[2],
settings.hvdf_offset[3]);
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "fog_constant"),
settings.fog_x);
settings.fog.x());
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "fog_min"),
settings.fog.y());
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "fog_max"),
settings.fog.z());
glUniform4f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "fog_color"),
render_state->fog_color[0], render_state->fog_color[1], render_state->fog_color[2],
render_state->fog_intensity);
}
void interp_time_of_day_slow(const float weights[8],

View file

@ -6,7 +6,7 @@
struct TfragRenderSettings {
math::Matrix4f math_camera;
math::Vector4f hvdf_offset;
float fog_x;
math::Vector4f fog;
int tree_idx;
float time_of_day_weights[8] = {0};
math::Vector4f planes[4];
@ -53,8 +53,7 @@ struct TfragPcPortData {
math::Vector<s32, 4> itimes[4];
math::Vector4f camera[4];
math::Vector4f hvdf_off;
float fogx;
float unused[3];
math::Vector4f fog;
char level_name[12];
u32 tree_idx;
};

View file

@ -264,6 +264,7 @@ void render_game_frame(int width, int height, int lbox_width, int lbox_height) {
options.draw_profiler_window = g_gfx_data->debug_gui.should_draw_profiler();
options.playing_from_dump = false;
options.save_screenshot = g_gfx_data->debug_gui.get_screenshot_flag();
options.draw_small_profiler_window = g_gfx_data->debug_gui.small_profiler;
if (options.save_screenshot) {
options.screenshot_path = make_output_file_name(g_gfx_data->debug_gui.screenshot_name());
}

View file

@ -345,6 +345,8 @@
(set! (-> data-ptr 12) (-> *math-camera* hvdf-off quad))
(let ((vec (-> (the (inline-array vector) data-ptr) 13)))
(set! (-> vec x) (-> *math-camera* pfog0))
(set! (-> vec y) (-> *math-camera* fog-min))
(set! (-> vec z) (-> *math-camera* fog-max))
)
(charp<-string (the (pointer uint8) (&-> data-ptr 14)) (symbol->string (-> lev nickname)))
)