Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Most strange libGDX screenshots come from one of four issues: capturing the wrong render target or at the wrong time, mixing logical window dimensions with physical back-buffer pixels, the opposite Y-axis direction used by OpenGL and image files, or unexpected alpha in the rendered pixels. Start with a back-buffer capture on the graphics thread, after drawing, using the back buffer’s pixel dimensions. Then diagnose orientation, transparency, and device-specific behavior separately.

Start with a reliable back-buffer capture

For a full-screen screenshot, use Gdx.graphics.getBackBufferWidth() and getBackBufferHeight() to determine the pixel dimensions. Logical window dimensions can differ from the actual framebuffer dimensions on high-density displays. libGDX’s official screenshot guidance uses Pixmap.createFromFrameBuffer, writes the result with PixmapIO.writePNG, and disposes of the Pixmap afterward. See the official screenshot guidance.

Gdx.app.postRunnable(() -> {
    int w = Gdx.graphics.getBackBufferWidth();
    int h = Gdx.graphics.getBackBufferHeight();

    Pixmap pixmap = Pixmap.createFromFrameBuffer(0, 0, w, h);
    try {
        PixmapIO.writePNG(Gdx.files.external("screenshot.png"), pixmap);
    } finally {
        pixmap.dispose();
    }
});

Run the readback on libGDX’s graphics thread. If you request the capture from another thread, post it with Gdx.app.postRunnable as above. Schedule it after the scene’s drawing commands have completed; capturing too early can read a previous frame or content that has not yet been drawn. The PNG write can be expensive, so for a latency-sensitive render loop, separate readback from later encoding or processing where your application architecture permits.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The sample preserves the pixel alpha channel. That is normally right when transparency is meaningful. If you expect an opaque screenshot but see transparent areas or unexpectedly dark compositing, see the alpha fix below.

#1 Best Overall
GameSir X5 Lite Mobile Gaming Controller for Android,Hall Effect Joystick
  • WIDE SCREEN COMPATIBILITY — PHONE TO TABLET: X5 Lite is a versatile phone controller that stretches up to 213mm to fit iPhone 15/16, most Android phones, iPad mini 6/7, and compatible Android tablets. Secure Type-C connection keeps gameplay stable and responsive.
  • MOBILE, CLOUD & REMOTE GAMING: Play supported mobile games like Zenless Zone Zero, or stream console and PC games through Xbox Game Pass, Steam Link, Moonlight, and remote play. Enjoy physical controls wherever you play.
  • HALL EFFECT STICKS — PRECISE CONTROL: GameSir Hall Effect sensing sticks deliver smooth 360° control for accurate aiming, movement, and camera adjustments. Built for fast-paced mobile games and streamed console or PC titles.
  • LIGHTWEIGHT & ERGONOMIC — 135.4G: At just 135.4g, X5 Lite stays lightweight during extended gaming. Ergonomic, laser-engraved textured grips provide a secure, comfortable hold at home or on the go.
  • CUSHIONED MEMBRANE CONTROLS — COMFORTABLE & QUIETER: Cushioned membrane buttons and triggers provide comfortable feedback for repeated inputs while keeping operation quieter. Ideal for extended sessions or gaming in shared spaces.

Fix an upside-down screenshot

OpenGL uses a bottom-left origin for framebuffer coordinates, while common image formats conventionally present rows from the top. As a result, framebuffer-backed textures and raw framebuffer data may look vertically inverted when displayed as an image. This is an orientation mismatch, not necessarily a failed capture.

If rendering an FBO texture

Flip the texture region vertically when drawing it:

TextureRegion region = new TextureRegion(frameBuffer.getColorBufferTexture());
region.flip(false, true);

The flip changes how the texture is sampled; it does not alter the FBO’s stored pixels. The libGDX framebuffer guide demonstrates this convention. Avoid applying another Y flip later in the pipeline, or the image will be inverted again.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
Mocagen MC1 Phone Controller for iPhone & Android – Ergonomic Grip, Low Latency, Case Friendly, Bluetooth Mobile Controller with Hall Effect Joysticks, Turbo, Portable Travel Companion for Car/Leisure
  • Bluetooth Controller for iPhone & Android: Mocagen mobile gaming controller Compatible with all iPhone models (including 18/17 series) and Android devices. Pairing steps: 1. Turn on Bluetooth on your phone and go to the pairing screen. 2. Press and hold the Home button for 3 sec until LED4 flashes. 3. Find "XBOX Wireless Controller" on your phone and tap to pair. Quick reconnect: After first pairing, simply press the Home button once (with Bluetooth on) to reconnect
  • Play Most Controller-Compatible Games: This iPhone game controller supports cloud gaming (e.g., Xb*x Game Pass, GeForce NOW), Xbox Remote Play, emulator games, and native mobile games (e.g., Apple Arcade). Enjoy effortless control and play Fortnite, Call of Duty, Roblox, Genshin Impact, and many more anytime, anywhere. Note: Controller only works with games that support controller input, and does not support PS Remote Play
  • 5M-Cycle Lifespan & Zero Drift: MC1 mobile gaming controller features a Hall-effect joystick with a 5M cycle lifespan, 2.5x longer than standard carbon-film sticks. Its innovative electromagnetic induction technology ensures drift-free operation, enabling precise character control in intense games and significantly extending this phone game controller durability
  • Ergonomic Grip Design: The handle is ergonomically shaped with a l*ser-engraved texture for anti-slip and enhanced grip, effectively reducing fatigue during long gaming sessions. The scientifically designed joystick and button layout ensures smooth operation. Whether for personal use or as a gift, it delivers a more comfortable and healthier gaming experience
  • 7-Color RGB Light Ring & 600mAh Battery: The mobile game controller features a 7-color adjustable light ring on the joystick(ABXY button lights can be turned off, but their colors are not adjustable). The lighting is vibrant yet eye-friendly. The built-in 600mAh battery provides up to 6 hours of battery life in brightness mode — enough for a full day of gaming

If using raw glReadPixels

Copy rows in reverse order when building an image whose first row should be the top row. The official libGDX camera integration helper shows row reversal when its flipY option is requested. It also sets GL_PACK_ALIGNMENT to 1 before readback, which is useful when the row byte count is not aligned as OpenGL expects.

Do not reverse rows blindly. First identify whether the data is a framebuffer texture or a CPU-side readback, and whether an earlier stage already flipped it. Applying exactly one appropriate orientation correction is the goal.

Correct HDPI cropping, stretching, or offsets

OpenGL readback, viewport, and scissor operations work in framebuffer pixels. On an HDPI display, libGDX’s logical screen size can differ from the back buffer’s pixel size. Passing logical dimensions to a pixel-oriented operation can capture only part of the screen, stretch a region, or place the result at an unexpected offset.

Rank #3
Sale
8BitDo Ultimate Mobile Gaming Controller for Android devices, Bluetooth Mobile Game Controller with Hall Effect Joysticks and Hall Triggers (Black)
  • Compatible with Android devices and fits mobile devices ranging from 100mm to 170mm in length.
  • Hall Effect Joysticks and Triggers
  • Refined bumpers and D-pad. Light and tactile.
  • 2 Pro back paddle buttons
  • Profile button. Wear-resistant metal joystick rings. Turbo function.
  • For a full-screen back-buffer capture, use getBackBufferWidth() and getBackBufferHeight(), not logical width and height.
  • For glViewport, glScissor, and glReadPixels, convert logical coordinates to pixel coordinates when the API expects pixels.
  • For an FBO intended to match the display, size it from the actual pixel dimensions, or temporarily use pixel HDPI mode around the FBO’s begin()/end() operations.

Check both the dimensions and the origin of a capture rectangle: using the right width and height with a logical-coordinate x/y can still select the wrong pixels. The libGDX framebuffer guide and coordinate-systems guide explain the relevant framebuffer and coordinate behavior.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Make an opaque image when alpha is unintended

PNG supports alpha. If the scene contains layered rendering, some pixels can have transparency even though the screenshot is otherwise correct. When the desired file must be fully opaque, set the alpha byte of every RGBA pixel to 255 before writing:

ByteBuffer pixels = pixmap.getPixels();
for (int i = 3; i < w * h * 4; i += 4) {
    pixels.put(i, (byte) 255);
}

This assumes the Pixmap data is four bytes per pixel in RGBA order, as in the documented screenshot pattern. Apply it only when an opaque result is intended. If you need transparent output, preserve the alpha values instead; forcing them to 255 destroys that transparency. If a viewer shows dark fringes rather than transparency, also inspect how the image is composited and whether the intended background was rendered before capture.

Rank #4
abxylute M4 Snap-On Mobile Gaming Controller for Android & iPhone, Switch 1&2, Portable Bluetooth Controller, Pocket-Sized Retro Arcade Phone Gamepad Kickstand, Dual Joystick Turbo Pro Gaming Magnetic (Black)
  • Why Choose the abxylute M4 Snap-On Phone Controller? Designed exclusively for short quick retro gaming, like Game Boy, NES, SNES and etc. Trusted by 6000+ backers on a tech-focused crowdfunding platform. Pocket-sized play, perfect for your rest time. This compact clip-on controller is compatible with iOS and Android, features a Turbo function—crafted for short bursts of play vertically, horizontally or in detached mode, and ideal for packing in your pocket.
  • 【Easy Setup – Power On & Play Instantly!】We recommend attaching the magnetic stickers to a phone case for all phones, rather than using a bare phone. ✅ For Apple MagSafe Models: Snap the magnetic ring onto your MagSafe phone case, power on, and start gaming! ✅ For Non‑MagSafe Models: First attach the included magnetic sticker to your phone case, then snap the magnetic ring onto it. Power on and game right away!
  • 【Wide Compatibility – Android & iPhone】Compatible for Android devices, iPhones, and card-size phones (Android devices and iPhone 11/SE and earlier models; iPhone 12/13/14/15/16/17 with MagSafe). Works with all mainstream phones for smooth gaming. Fits iPhone Pro/Pro Max models but may feel top-heavy. Not compatible with foldable phones.
  • 【Compact Yet No Loss of Fun】Featuring HID, PS and NS modes, it seamlessly connects to gaming devices via Bluetooth.⚫ HID Mode: Local Games for Android⚫ PS Mode: CODM & PS Remote Play for Android & iOS⚫ NS Mode: All kinds of Emulators
  • 【Born for Retro Emulators on Mobile】Designed for retro gaming fans, the M4 Controller works smoothly with top emulators such as Delta, RetroArch and PPSSPP on both iOS and Android.It supports classic games for platforms including Game Boy, NES, SNES,3DS, FC, SFC, SS, N64, GBA, GBC, NDS, and more.

Choose between direct capture and an FBO

Approach Best fit Things to verify
Back-buffer capture The simplest way to save what the game rendered to the screen. Capture after drawing; use physical back-buffer dimensions; preserve or normalize alpha intentionally.
Intermediate FBO A game already rendering through post-processing, or a capture that needs a controlled off-screen target. Texture Y orientation; pixel-sized FBO dimensions on HDPI displays; framebuffer binding restoration after ending the FBO.

Use the back buffer unless you have a reason to capture another render target. An FBO gives control over what is rendered and can fit an existing post-processing pipeline, but it adds orientation, scaling, and binding-state details that do not arise in the same way for the direct screen capture.

Troubleshoot a completely black screenshot

  1. Confirm timing. Request the capture after the scene draw has completed. Verify that the rendered frame itself is visible before saving.
  2. Confirm the target. Check whether an FBO is still bound when you expect to read the screen, or whether the wrong target is active. For an FBO capture, confirm that the FBO received the scene.
  3. Confirm dimensions. Log back-buffer dimensions and the capture rectangle. A zero-sized or out-of-range rectangle cannot provide the intended image.
  4. Compare readback paths. If practical, compare the Pixmap path with direct glReadPixels on the affected backend. This can help distinguish a target/timing problem from a device-specific readback issue.
  5. Reproduce on the failing device. libGDX issue reports include an all-black PNG on a Samsung Galaxy S9 even though the same code worked on other devices. That report is evidence of a possible device/backend-specific problem, not proof that PNG encoding is generally broken. See the Galaxy S9 issue report.

If the capture is black only on one device after target, timing, and dimensions have been checked, test the smallest reproducible capture on that device and backend. The available report does not establish a universal workaround, so avoid assuming that changing the PNG writer or using a different byte buffer will solve every such case.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Restore framebuffer state after FBO rendering

If the scene itself turns black after using an FBO—particularly on iOS—check which framebuffer is bound after FrameBuffer.end(). An issue report for libGDX 1.12.0 describes a case where the default framebuffer handle led to restoration of the wrong target. Its reported workaround is to save the current binding before beginning the FBO and explicitly bind it again afterward:

Best Value
GameSir X5 Lite Mobile Gaming Controller for Android & iPhone 15/16 Series (USB-C), Hall Effect Joystick, Lightweight Ergonomic Phone Controller- Play Genshin Impact & Zenless Zone Zero (Renewed)
  • Expanded Screen Compatibility: Stretchable up to 213mm, fitting iPad Mini 6/7 and Android tablets; Compatible with iPhone 15/16 and Android devices; Ultra-stable Type-C connection ensures lag-free gaming across all supported screen
  • Mobile Gaming Compatibility: Lets you play most of the games you want. Supports Xbox Game Pass, Zenless Zone Zero, cloud gaming, Steam/Moonlight streaming games, and remote play
  • Hall Effect Sticks: GameSir Hall Effect sensing sticks deliver 360° seamless pinpoint control, provide the precision and durability that mobile gamers demand
  • Ergonomic and Lightweight Design: Stay comfortable during long gaming sessions with the X5 Lite. Weighing just 135.4g, its lightweight design and ergonomically laser-engraved textured grips ensure a secure, comfortable hold for hours of gameplay
  • Cushioned and Durable Membrane: The X5 Lite is equipped with cushioned and durable membrane triggers and buttons. The cushioned feedback provides a comfortable experience while ensuring quieter operation
int[] previous = new int[1];
Gdx.gl.glGetIntegerv(GL20.GL_FRAMEBUFFER_BINDING, previous, 0);

frameBuffer.begin();
try {
    // Render the content intended for the FBO.
} finally {
    frameBuffer.end();
    Gdx.gl.glBindFramebuffer(GL20.GL_FRAMEBUFFER, previous[0]);
}

The report says the workaround worked across platforms, but it is an issue-specific report, not a guarantee that every black-screen problem has the same cause. Check the framebuffer restoration issue for its context. Save and restore the binding around the operation that changes it; do not assume the default target is represented by the same handle on every platform.

Use raw readback carefully

Direct glReadPixels can be useful for isolating a problem or implementing a custom capture, but it leaves pixel layout and orientation work to your code. Make sure the bound target is the one you intend to capture, the rectangle is specified in pixels, and the destination buffer can hold the requested data. Account for row alignment and reverse row order if your output expects the top row first.

Readback can also stall the rendering pipeline while the GPU makes pixels available to the CPU. Keep it out of every-frame work unless the feature requires that cadence. For occasional screenshots, trigger it only when requested and defer file encoding or other expensive CPU work where possible. This does not eliminate the synchronization cost of readback itself.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common symptom-to-fix map

Symptom Likely issue First check
Image is upside down OpenGL and image row origins differ. Flip the FBO texture once, or reverse raw readback rows once.
Transparent or dark-looking result Alpha values are preserved from layered rendering or compositing differs. Decide whether transparency is wanted; set alpha to 255 only for intended opaque output.
Cropped, stretched, or offset on HDPI Logical coordinates are being used where pixel coordinates are required. Use back-buffer dimensions and pixel coordinates for GL operations.
Black file on one device Wrong timing/target, or device/backend-specific readback behavior. Verify render completion, binding and dimensions, then compare a direct readback on that device.
Game becomes black after FBO use The prior framebuffer may not have been restored. Save GL_FRAMEBUFFER_BINDING before the FBO and explicitly rebind it after ending.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers, not a libGDX framebuffer debugger. If the screenshot you need is of a web page rather than your game’s rendered frame, one GET request returns an image or PDF. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" 
  -d access_key=YOUR_API_KEY 
  --data-urlencode url=https://stripe.com 
  -o shot.webp

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the capture; bot checks, blank pages, and failed loads are not billed. Its MCP server lets AI agents take screenshots. The Free plan includes 1,000 shots per month with no card, and paid plans start at $5 for 3,000 shots. Learn about ScreenshotNeo, or sign up for 1,000 free screenshots a month with no card.

FAQ

Should I capture every rendered frame?

Usually not. A screenshot is typically an on-demand operation; continuous readback can impose synchronization and processing costs that are unnecessary for a single saved image.

Does ScreenshotNeo capture a libGDX game window?

No. It captures website pages. Use libGDX’s framebuffer or back-buffer APIs for an in-game screenshot.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.