Replace PCRTC framebuffer blit with screen quad draw (#3980)

Taking the suggestion from @Calinou
(https://github.com/open-goal/jak-project/pull/3943#issuecomment-3017359144),
this replaces the resolve/render framebuffer -> window framebuffer blit
with an actual drawn tri-strip which covers the entire viewport, which
the PCRTC blackout already does.

It appears we have no guarantee what state the internal window
framebuffer will be in, so drawing an actual primitive and letting the
fragment shader do all the work seems to be the more
compatible/functional solution here.

Thanks for the suggestion!
This commit is contained in:
Alex
2025-08-01 00:46:15 +01:00
committed by GitHub
parent c4585ef6fb
commit 070e233985
2 changed files with 58 additions and 19 deletions
@@ -81,7 +81,7 @@ OpenGLRenderer::OpenGLRenderer(std::shared_ptr<TexturePool> texture_pool,
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(opengl_error_callback, nullptr);
// disable specific errors
const GLuint gl_error_ignores_api_other[1] = {0x20071};
const GLuint gl_error_ignores_api_other[1] = {0x20071}; // some annoying nvidia message
glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_OTHER, GL_DONT_CARE, 1,
&gl_error_ignores_api_other[0], GL_FALSE);
#endif
@@ -92,6 +92,38 @@ OpenGLRenderer::OpenGLRenderer(std::shared_ptr<TexturePool> texture_pool,
lg::info("OpenGL context shading language version: {}",
(const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
// set up screen draw
glGenVertexArrays(1, &screen_vao);
glGenBuffers(1, &screen_vbo);
struct Vertex {
float x, y;
};
constexpr std::array<Vertex, 4> vertices = {
Vertex{-1, -1},
Vertex{-1, 1},
Vertex{1, -1},
Vertex{1, 1},
};
glBindVertexArray(screen_vao);
glBindBuffer(GL_ARRAY_BUFFER, screen_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * 4, vertices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, // location 0 in the shader
2, // 2 floats per vert
GL_FLOAT, // floats
GL_TRUE, // normalized, ignored,
sizeof(Vertex), //
nullptr //
);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// end set up screen draw
const tfrag3::Level* common_level = nullptr;
{
auto p = scoped_prof("load-common");
@@ -1595,30 +1627,33 @@ void OpenGLRenderer::do_pcrtc_effects(float alp,
window_blit_src = &m_fbo_state.resources.render_buffer;
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, window_blit_src->fbo_id);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, // srcX0
0, // srcY0
window_blit_src->width, // srcX1
window_blit_src->height, // srcY1
render_state->draw_offset_x, // dstX0
render_state->draw_offset_y, // dstY0
render_state->draw_offset_x + render_state->draw_region_w, // dstX1
render_state->draw_offset_y + render_state->draw_region_h, // dstY1
GL_COLOR_BUFFER_BIT, // mask
GL_LINEAR // filter
);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glViewport(render_state->draw_offset_x, render_state->draw_offset_y, render_state->draw_region_w,
render_state->draw_region_h);
glBindTexture(GL_TEXTURE_2D, *window_blit_src->tex_id);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindVertexArray(screen_vao);
glBindBuffer(GL_ARRAY_BUFFER, screen_vbo);
auto& shader = render_state->shaders[ShaderId::PLAIN_TEXTURE];
shader.activate();
glUniform1i(glGetUniformLocation(shader.id(), "tex_T0"), 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glActiveTexture(GL_TEXTURE0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glEnable(GL_BLEND);
if (alp < 1) {
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
glBlendEquation(GL_FUNC_ADD);
glViewport(0, 0, m_fbo_state.resources.window.width, m_fbo_state.resources.window.height);
m_blackout_renderer.draw(Vector4f(0, 0, 0, 1.f - alp), render_state, prof);
glEnable(GL_DEPTH_TEST);
}
glEnable(GL_DEPTH_TEST);
}
@@ -65,6 +65,7 @@ class OpenGLRenderer {
OpenGLRenderer(std::shared_ptr<TexturePool> texture_pool,
std::shared_ptr<Loader> loader,
GameVersion version);
// TODO delete
// rendering interface: takes the dma chain from the game, and some size/debug settings from
// the graphics system.
@@ -135,6 +136,9 @@ class OpenGLRenderer {
Fbo* render_fbo = nullptr; // the selected fbo from the three above to use for rendering
} m_fbo_state;
GLuint screen_vao = 0; // vertex array object for a screen-space draw
GLuint screen_vbo = 0; // vertex buffer object for a screen-space draw
std::unique_ptr<BucketRenderer> m_jak2_eye_renderer;
std::unique_ptr<BucketRenderer> m_jak3_eye_renderer;
GameVersion m_version;