jak-project/game/graphics/opengl_renderer/OpenGLRenderer.h
Tyler Wilding 92c4390f0a
Some checks are pending
Build / 🖥️ Windows (push) Waiting to run
Build / 🐧 Linux (push) Waiting to run
Build / 🍎 MacOS (push) Waiting to run
Inform Pages Repo / Generate Documentation (push) Waiting to run
Lint / 📝 Formatting (push) Waiting to run
Lint / 📝 Required Checks (push) Waiting to run
Lint / 📝 Optional Checks (push) Waiting to run
jak1: Adjust sprite positioning or hide them where appropriate when using non-standard aspect ratios (#3596)
This attempts to do a best-effort quick fix for the sprite alignment in
the menus and first person views on higher aspect ratios. This:
- Hides the binocular borders completely when using a non-standard ratio
![Screenshot 2024-07-20
021430](https://github.com/user-attachments/assets/c56d3a6c-13b0-43e1-b99b-83292993728c)
- Hides the borders in jak's first person view when using a non-standard
ratio
![Screenshot 2024-07-20
021310](https://github.com/user-attachments/assets/fefca993-960b-4741-87b7-6d7c17efe89d)
- Uses a combination of manual alignment and approximation to get the
pause menu closer.
![Screenshot 2024-07-20
151725](https://github.com/user-attachments/assets/2c8aa759-b33a-4fbe-abc6-b5861fc33208)
> 32:9 screenshot.

I accomplished the last one by manually aligning all of the core sprites
and text for the most popular aspect ratios. This means that from a
practical standpoint, things should align "perfectly". However, I then
used all of those values to derive a polynomial for each adjustment
based on the aspect ratio. This allows the game to do a half-decent
approximation/interpolation for every aspect ratio in-between the common
ones. It won't be perfect, but it will be better than this:

![image](https://github.com/user-attachments/assets/420b1e38-6f88-436a-8e8c-21df6b49428e)
2024-07-26 23:15:51 -04:00

142 lines
5.2 KiB
C++

#pragma once
#include <array>
#include <memory>
#include "common/dma/dma_chain_read.h"
#include "game/graphics/opengl_renderer/BucketRenderer.h"
#include "game/graphics/opengl_renderer/CollideMeshRenderer.h"
#include "game/graphics/opengl_renderer/Fbo.h"
#include "game/graphics/opengl_renderer/Profiler.h"
#include "game/graphics/opengl_renderer/Shader.h"
#include "game/graphics/opengl_renderer/TextureAnimator.h"
#include "game/graphics/opengl_renderer/foreground/Generic2.h"
#include "game/graphics/opengl_renderer/foreground/Merc2.h"
#include "game/graphics/opengl_renderer/opengl_utils.h"
#include "game/tools/filter_menu/filter_menu.h"
#include "game/tools/subtitle_editor/subtitle_editor.h"
struct RenderOptions {
bool draw_render_debug_window = false;
bool draw_profiler_window = false;
bool draw_loader_window = false;
bool draw_small_profiler_window = false;
bool draw_subtitle_editor_window = false;
bool draw_filters_window = false;
// internal rendering settings - The OpenGLRenderer will internally use this resolution/format.
int msaa_samples = 2;
int game_res_w = 640;
int game_res_h = 480;
// size of the window's framebuffer (framebuffer 0)
// The renderer needs to know this to do an optimization to render directly to the window's
// framebuffer when possible.
int window_framebuffer_height = 0;
int window_framebuffer_width = 0;
// the part of the window that we should draw to. The rest is black. This value is determined by
// logic inside of the game - it needs to know the desired aspect ratio.
int draw_region_height = 0;
int draw_region_width = 0;
bool save_screenshot = false;
bool quick_screenshot = false;
bool internal_res_screenshot = false;
std::string screenshot_path;
float pmode_alp_register = 1.f;
// when enabled, does a `glFinish()` after each major rendering pass. This blocks until the GPU
// is done working, making it easier to profile GPU utilization.
bool gpu_sync = false;
};
/*!
* Main OpenGL renderer.
* This handles the glClear and all game rendering, but not actual setup, synchronization or imgui
* stuff.
*
* It is simply a collection of bucket renderers, and a few special case ones.
*/
class OpenGLRenderer {
public:
OpenGLRenderer(std::shared_ptr<TexturePool> texture_pool,
std::shared_ptr<Loader> loader,
GameVersion version);
// rendering interface: takes the dma chain from the game, and some size/debug settings from
// the graphics system.
void render(DmaFollower dma, const RenderOptions& settings);
private:
void setup_frame(const RenderOptions& settings);
void dispatch_buckets(DmaFollower dma, ScopedProfilerNode& prof, bool sync_after_buckets);
void dispatch_buckets_jak1(DmaFollower dma, ScopedProfilerNode& prof, bool sync_after_buckets);
void dispatch_buckets_jak2(DmaFollower dma, ScopedProfilerNode& prof, bool sync_after_buckets);
void dispatch_buckets_jak3(DmaFollower dma, ScopedProfilerNode& prof, bool sync_after_buckets);
void do_pcrtc_effects(float alp, SharedRenderState* render_state, ScopedProfilerNode& prof);
void blit_display();
void init_bucket_renderers_jak1();
void init_bucket_renderers_jak2();
void init_bucket_renderers_jak3();
void draw_renderer_selection_window();
void finish_screenshot(const std::string& output_name,
int px,
int py,
int x,
int y,
GLuint fbo,
int read_buffer,
bool quick_screenshot);
template <typename T, typename U, class... Args>
T* init_bucket_renderer(const std::string& name, BucketCategory cat, U id, Args&&... args) {
auto renderer = std::make_unique<T>(name, (int)id, std::forward<Args>(args)...);
T* ret = renderer.get();
m_bucket_renderers.at((int)id) = std::move(renderer);
m_bucket_categories.at((int)id) = cat;
return ret;
}
const std::vector<GLuint>* anim_slot_array() {
return m_texture_animator ? m_texture_animator->slots() : nullptr;
}
SharedRenderState m_render_state;
Profiler m_profiler;
SmallProfiler m_small_profiler;
SubtitleEditor* m_subtitle_editor = nullptr;
FiltersMenu m_filters_menu;
std::shared_ptr<Merc2> m_merc2;
std::shared_ptr<Generic2> m_generic2;
std::shared_ptr<TextureAnimator> m_texture_animator;
std::vector<std::unique_ptr<BucketRenderer>> m_bucket_renderers;
std::vector<BucketCategory> m_bucket_categories;
class BlitDisplays* m_blit_displays = nullptr;
std::array<float, (int)BucketCategory::MAX_CATEGORIES> m_category_times;
FullScreenDraw m_blackout_renderer;
CollideMeshRenderer m_collide_renderer;
float m_last_pmode_alp = 1.;
bool m_enable_fast_blackout_loads = true;
std::string m_renderer_filter = "";
struct FboState {
struct {
Fbo window; // provided by glfw
Fbo render_buffer; // temporary buffer to render to
Fbo resolve_buffer; // temporary buffer to resolve to
} resources;
Fbo* render_fbo = nullptr; // the selected fbo from the three above to use for rendering
} m_fbo_state;
std::unique_ptr<BucketRenderer> m_jak2_eye_renderer;
std::unique_ptr<BucketRenderer> m_jak3_eye_renderer;
GameVersion m_version;
};