Skip to content

Commit ff28a9c

Browse files
authored
fix HDR and Alpha issues in screenshots (scp-fs2open#7294)
1 parent 05054f8 commit ff28a9c

1 file changed

Lines changed: 19 additions & 1 deletion

File tree

code/graphics/opengl/gropengl.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,19 @@ void gr_opengl_print_screen(const char *filename)
286286
//Reading from the front buffer here seems to no longer work correctly; that just reads back all zeros
287287
glReadBuffer(Cmdline_window_res ? GL_COLOR_ATTACHMENT0 : GL_FRONT);
288288

289+
// Clamp float values to [0,1] when reading from the GL_RGBA16F back framebuffer.
290+
// The default GL_FIXED_ONLY only clamps fixed-point FBOs, leaving float FBO reads
291+
// with out-of-range values (HDR > 1.0) producing undefined behavior when converted
292+
// to integer types, which manifests as rainbow artifacts on bright areas.
293+
glClampColor(GL_CLAMP_READ_COLOR, GL_TRUE);
294+
289295
// now for the data
290296
if (Use_PBOs) {
291297
Assert( !pbo );
292298
glGenBuffers(1, &pbo);
293299

294300
if ( !pbo ) {
301+
glClampColor(GL_CLAMP_READ_COLOR, GL_FIXED_ONLY);
295302
return;
296303
}
297304

@@ -306,17 +313,28 @@ void gr_opengl_print_screen(const char *filename)
306313
pixels = (GLubyte*) vm_malloc(gr_screen.max_w * gr_screen.max_h * 4, memory::quiet_alloc);
307314

308315
if (pixels == NULL) {
316+
glClampColor(GL_CLAMP_READ_COLOR, GL_FIXED_ONLY);
309317
return;
310318
}
311319

312320
glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
313321
glFlush();
314322
}
315323

324+
glClampColor(GL_CLAMP_READ_COLOR, GL_FIXED_ONLY);
325+
326+
// Force alpha to fully opaque so screenshots are not saved with transparency.
327+
// The framebuffer alpha can be < 255 due to blending operations affecting the alpha
328+
// channel as a side effect, even though the rendered image itself is opaque.
329+
int num_pixels = gr_screen.max_w * gr_screen.max_h;
330+
for (int i = 0; i < num_pixels; i++) {
331+
pixels[i * 4 + 3] = 255;
332+
}
333+
316334
if (!png_write_bitmap(os_get_config_path(tmp).c_str(), gr_screen.max_w, gr_screen.max_h, true, pixels)) {
317335
ReleaseWarning(LOCATION, "Failed to write screenshot to \"%s\".", os_get_config_path(tmp).c_str());
318336
}
319-
337+
320338
if (pbo) {
321339
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
322340
pixels = NULL;

0 commit comments

Comments
 (0)