2021-08-07 18:57:13 -04:00
|
|
|
#pragma once
|
|
|
|
|
2021-08-08 13:12:44 -04:00
|
|
|
#include <memory>
|
2022-06-22 23:37:46 -04:00
|
|
|
#include <string>
|
|
|
|
|
2021-10-31 13:12:50 -04:00
|
|
|
#include "common/dma/dma_chain_read.h"
|
2022-06-22 23:37:46 -04:00
|
|
|
|
2021-10-10 20:07:03 -04:00
|
|
|
#include "game/graphics/opengl_renderer/Profiler.h"
|
2022-06-22 23:37:46 -04:00
|
|
|
#include "game/graphics/opengl_renderer/Shader.h"
|
2022-03-06 19:56:43 -05:00
|
|
|
#include "game/graphics/opengl_renderer/buckets.h"
|
2022-06-22 23:37:46 -04:00
|
|
|
#include "game/graphics/opengl_renderer/loader/Loader.h"
|
|
|
|
#include "game/graphics/texture/TexturePool.h"
|
2021-08-07 18:57:13 -04:00
|
|
|
|
2023-05-04 18:34:09 -04:00
|
|
|
struct Fbo;
|
|
|
|
|
2022-01-20 00:22:03 -05:00
|
|
|
struct LevelVis {
|
|
|
|
bool valid = false;
|
|
|
|
u8 data[2048];
|
|
|
|
};
|
|
|
|
|
2022-03-02 21:40:52 -05:00
|
|
|
class EyeRenderer;
|
2021-08-07 18:57:13 -04:00
|
|
|
/*!
|
|
|
|
* The main renderer will contain a single SharedRenderState that's passed to all bucket renderers.
|
|
|
|
* This allows bucket renders to share textures and shaders.
|
|
|
|
*/
|
|
|
|
struct SharedRenderState {
|
2022-03-02 20:01:37 -05:00
|
|
|
explicit SharedRenderState(std::shared_ptr<TexturePool> _texture_pool,
|
2022-09-05 20:29:12 -04:00
|
|
|
std::shared_ptr<Loader> _loader,
|
|
|
|
GameVersion version)
|
|
|
|
: shaders(version), texture_pool(_texture_pool), loader(_loader) {}
|
2021-08-07 18:57:13 -04:00
|
|
|
ShaderLibrary shaders;
|
2021-08-08 13:12:44 -04:00
|
|
|
std::shared_ptr<TexturePool> texture_pool;
|
2022-03-02 20:01:37 -05:00
|
|
|
std::shared_ptr<Loader> loader;
|
2021-12-04 12:33:18 -05:00
|
|
|
|
2021-08-07 18:57:13 -04:00
|
|
|
u32 buckets_base = 0; // address of buckets array.
|
|
|
|
u32 next_bucket = 0; // address of next bucket that we haven't started rendering in buckets
|
|
|
|
u32 default_regs_buffer = 0; // address of the default regs chain.
|
2021-09-26 11:41:58 -04:00
|
|
|
|
|
|
|
void* ee_main_memory = nullptr;
|
|
|
|
u32 offset_of_s7;
|
2021-12-30 19:38:18 -05:00
|
|
|
|
|
|
|
bool use_sky_cpu = true;
|
2022-01-20 00:22:03 -05:00
|
|
|
bool use_occlusion_culling = true;
|
2022-09-25 12:50:51 -04:00
|
|
|
math::Vector<u8, 4> fog_color = math::Vector<u8, 4>{0, 0, 0, 0};
|
2022-02-25 23:25:49 -05:00
|
|
|
float fog_intensity = 1.f;
|
2022-05-28 19:28:19 -04:00
|
|
|
bool no_multidraw = false;
|
2022-01-15 16:52:47 -05:00
|
|
|
|
2022-01-20 00:22:03 -05:00
|
|
|
void reset();
|
2022-04-25 21:53:23 -04:00
|
|
|
bool has_pc_data = false;
|
2023-03-19 01:33:04 -04:00
|
|
|
|
|
|
|
// limit is arbitrary so let's go ham in case we want more levels in the future
|
|
|
|
LevelVis occlusion_vis[32];
|
2022-04-25 21:53:23 -04:00
|
|
|
|
2022-01-15 16:52:47 -05:00
|
|
|
math::Vector4f camera_planes[4];
|
2023-03-17 20:35:26 -04:00
|
|
|
|
|
|
|
// including transformation, rotation, perspective
|
2022-04-25 21:53:23 -04:00
|
|
|
math::Vector4f camera_matrix[4];
|
|
|
|
math::Vector4f camera_hvdf_off;
|
|
|
|
math::Vector4f camera_fog;
|
|
|
|
math::Vector4f camera_pos;
|
2022-03-02 20:01:37 -05:00
|
|
|
|
2022-03-02 21:40:52 -05:00
|
|
|
EyeRenderer* eye_renderer = nullptr;
|
|
|
|
|
2022-03-02 20:01:37 -05:00
|
|
|
std::string load_status_debug;
|
2022-07-08 21:56:38 -04:00
|
|
|
|
2022-07-17 14:45:00 -04:00
|
|
|
// Information for renderers that need to read framebuffers:
|
|
|
|
// Most renderers can just use the framebuffer/glViewport set up by OpenGLRenderer, but special
|
|
|
|
// effects like sprite distort that read the framebuffer will need to know the details of the
|
|
|
|
// framebuffer setup.
|
|
|
|
|
|
|
|
// the framebuffer that bucket renderers should render to.
|
2022-07-19 18:41:48 -04:00
|
|
|
int render_fb_x = 0;
|
|
|
|
int render_fb_y = 0;
|
2022-07-17 14:45:00 -04:00
|
|
|
int render_fb_w = 0;
|
|
|
|
int render_fb_h = 0;
|
|
|
|
GLuint render_fb = -1;
|
|
|
|
|
|
|
|
// the region within that framebuffer to draw to.
|
|
|
|
int draw_region_w = 0;
|
|
|
|
int draw_region_h = 0;
|
|
|
|
int draw_offset_x = 0;
|
|
|
|
int draw_offset_y = 0;
|
2022-09-05 20:29:12 -04:00
|
|
|
|
|
|
|
int bucket_for_vis_copy = 0;
|
2022-10-01 17:12:12 -04:00
|
|
|
int num_vis_to_copy = 0;
|
2022-09-05 20:29:12 -04:00
|
|
|
GameVersion version;
|
2023-03-17 20:35:26 -04:00
|
|
|
u64 frame_idx = 0;
|
2023-05-07 12:12:21 -04:00
|
|
|
|
|
|
|
bool stencil_dirty = false;
|
2021-08-07 18:57:13 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Interface for bucket renders. Each bucket will have its own BucketRenderer.
|
|
|
|
*/
|
|
|
|
class BucketRenderer {
|
|
|
|
public:
|
2022-09-05 20:29:12 -04:00
|
|
|
BucketRenderer(const std::string& name, int my_id) : m_name(name), m_my_id(my_id) {}
|
2021-10-10 20:07:03 -04:00
|
|
|
virtual void render(DmaFollower& dma,
|
|
|
|
SharedRenderState* render_state,
|
|
|
|
ScopedProfilerNode& prof) = 0;
|
2021-08-07 18:57:13 -04:00
|
|
|
std::string name_and_id() const;
|
|
|
|
virtual ~BucketRenderer() = default;
|
2021-08-29 14:54:16 -04:00
|
|
|
bool& enabled() { return m_enabled; }
|
|
|
|
virtual bool empty() const { return false; }
|
2021-09-26 11:41:58 -04:00
|
|
|
virtual void draw_debug_window() = 0;
|
2022-02-27 17:23:12 -05:00
|
|
|
virtual void init_shaders(ShaderLibrary&) {}
|
2023-01-22 18:07:46 -05:00
|
|
|
virtual void init_textures(TexturePool&, GameVersion) {}
|
2021-08-07 18:57:13 -04:00
|
|
|
|
|
|
|
protected:
|
|
|
|
std::string m_name;
|
2022-09-05 20:29:12 -04:00
|
|
|
int m_my_id;
|
2021-08-29 14:54:16 -04:00
|
|
|
bool m_enabled = true;
|
2021-08-07 18:57:13 -04:00
|
|
|
};
|
|
|
|
|
2022-01-21 21:11:57 -05:00
|
|
|
class RenderMux : public BucketRenderer {
|
|
|
|
public:
|
|
|
|
RenderMux(const std::string& name,
|
2022-09-05 20:29:12 -04:00
|
|
|
int my_id,
|
2022-01-21 21:11:57 -05:00
|
|
|
std::vector<std::unique_ptr<BucketRenderer>> renderers);
|
|
|
|
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
|
|
|
void draw_debug_window() override;
|
2022-05-28 19:28:19 -04:00
|
|
|
void init_shaders(ShaderLibrary&) override;
|
2023-01-22 18:07:46 -05:00
|
|
|
void init_textures(TexturePool&, GameVersion) override;
|
2022-05-28 19:28:19 -04:00
|
|
|
void set_idx(u32 i) { m_render_idx = i; };
|
2022-01-21 21:11:57 -05:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::vector<std::unique_ptr<BucketRenderer>> m_renderers;
|
|
|
|
int m_render_idx = 0;
|
|
|
|
std::vector<std::string> m_name_strs;
|
|
|
|
std::vector<const char*> m_name_str_ptrs;
|
|
|
|
};
|
|
|
|
|
2021-08-07 18:57:13 -04:00
|
|
|
/*!
|
|
|
|
* Renderer that makes sure the bucket is empty and ignores it.
|
|
|
|
*/
|
|
|
|
class EmptyBucketRenderer : public BucketRenderer {
|
|
|
|
public:
|
2022-09-05 20:29:12 -04:00
|
|
|
EmptyBucketRenderer(const std::string& name, int my_id);
|
2021-10-10 20:07:03 -04:00
|
|
|
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
2021-08-29 14:54:16 -04:00
|
|
|
bool empty() const override { return true; }
|
2021-09-26 11:41:58 -04:00
|
|
|
void draw_debug_window() override {}
|
2021-11-13 20:44:17 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
class SkipRenderer : public BucketRenderer {
|
|
|
|
public:
|
2022-09-05 20:29:12 -04:00
|
|
|
SkipRenderer(const std::string& name, int my_id);
|
2021-11-13 20:44:17 -05:00
|
|
|
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
|
|
|
bool empty() const override { return true; }
|
|
|
|
void draw_debug_window() override {}
|
2022-04-30 14:48:24 -04:00
|
|
|
};
|
2023-05-07 12:12:21 -04:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Renderer that ignores and prints all DMA transfers.
|
|
|
|
*/
|
|
|
|
class PrintRenderer : public BucketRenderer {
|
|
|
|
public:
|
|
|
|
PrintRenderer(const std::string& name, int my_id);
|
|
|
|
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
|
|
|
bool empty() const override { return true; }
|
|
|
|
void draw_debug_window() override {}
|
|
|
|
};
|