DEV Community

IronSoftware
IronSoftware

Posted on

How to Render WebGL in PDF with C# (.NET Guide)

Our sales team needed PDFs of interactive 3D product configurators for offline presentations. The configurators used WebGL for rendering, and standard PDF conversion captured blank canvases—just loading spinners and error messages.

IronPDF's WebGL rendering mode solved this. Here's how to capture GPU-rendered graphics in PDFs.

Why Don't WebGL Sites Convert to PDF Normally?

WebGL renders graphics using the GPU via the browser's graphics context. Standard PDF rendering engines don't have GPU access, so WebGL canvases appear blank:

using IronPdf;
// Install via NuGet: Install-Package IronPdf

var renderer = new ChromePdfRenderer();

// Without WebGL config: canvas is blank in PDF
var pdf = renderer.RenderUrlAsPdf("https://example.com/3d-model");
pdf.SaveAs("blank-canvas.pdf");
Enter fullscreen mode Exit fullscreen mode

The PDF shows the page layout but the WebGL canvas is empty or shows a fallback error message.

How Do I Enable WebGL Rendering?

Configure IronPDF to use hardware GPU mode and single-process execution:

using IronPdf;

// Enable WebGL rendering
IronPdf.Installation.SingleProcess = true;
IronPdf.Installation.ChromeGpuMode = IronPdf.Engines.Chrome.ChromeGpuModes.Hardware;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.RenderDelay(5000); // Let WebGL finish rendering

var pdf = renderer.RenderUrlAsPdf("https://example.com/3d-model");
pdf.SaveAs("with-webgl.pdf");
Enter fullscreen mode Exit fullscreen mode

Now the PDF captures the fully-rendered WebGL content.

What Does SingleProcess Do?

SingleProcess = true forces Chrome to execute all operations in one process instead of spawning subprocesses. This is required because GPU access needs to be coordinated within a single process.

Without this, Chrome's multi-process architecture isolates the GPU context from the rendering engine, causing WebGL canvases to render as blank.

Why Hardware GPU Mode?

ChromeGpuMode.Hardware enables actual GPU acceleration. The default mode doesn't provide the graphics context WebGL requires.

Available modes:

  • Disabled: No GPU (WebGL won't work)
  • Hardware: Full GPU acceleration (required for WebGL)

Always use Hardware mode for WebGL sites.

How Much Delay Should I Set?

WebGL scenes can take time to load textures, compile shaders, and render frames. Use RenderDelay to wait:

renderer.RenderingOptions.WaitFor.RenderDelay(5000); // 5 seconds
Enter fullscreen mode Exit fullscreen mode

Guidelines:

  • Simple 3D models: 2-3 seconds
  • Complex scenes with textures: 5-10 seconds
  • Large datasets (maps with layers): 10-15 seconds

Test with your specific content and adjust. Too short = incomplete render. Too long = wasted time.

Can I Wait for a Specific Element Instead?

Yes. Add a marker element when WebGL finishes rendering:

<canvas id="webgl-canvas"></canvas>
<script>
  initWebGL().then(() => {
    // WebGL scene fully rendered
    document.body.insertAdjacentHTML('beforeend', '<div id="webgl-ready"></div>');
  });
</script>
Enter fullscreen mode Exit fullscreen mode

Then wait for that element:

IronPdf.Installation.SingleProcess = true;
IronPdf.Installation.ChromeGpuMode = IronPdf.Engines.Chrome.ChromeGpuModes.Hardware;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.HtmlElementById("webgl-ready");

var pdf = renderer.RenderUrlAsPdf("https://example.com/3d-model");
pdf.SaveAs("output.pdf");
Enter fullscreen mode Exit fullscreen mode

This is more reliable than fixed delays.

What WebGL Content Works?

Any WebGL-based graphics:

  • 3D models (Three.js, Babylon.js)
  • Interactive maps (Mapbox, Leaflet with WebGL layers)
  • Data visualizations (D3.js with WebGL, Deck.gl)
  • Games (if they render to a fixed state)
  • CAD viewers

I've successfully rendered Mapbox maps, Three.js product configurators, and engineering diagrams.

Does This Work with Three.js?

Yes. Three.js is one of the most common WebGL frameworks:

IronPdf.Installation.SingleProcess = true;
IronPdf.Installation.ChromeGpuMode = IronPdf.Engines.Chrome.ChromeGpuModes.Hardware;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.RenderDelay(3000);

var pdf = renderer.RenderUrlAsPdf("https://threejs.org/examples/webgl_geometry_cube.html");
pdf.SaveAs("threejs-cube.pdf");
Enter fullscreen mode Exit fullscreen mode

The rotating cube (or whatever scene) is captured at the moment rendering occurs.

Can I Control the Camera Angle?

If the WebGL app exposes URL parameters or JavaScript APIs for camera control, yes:

// URL with camera parameters
var url = "https://example.com/3d-viewer?camera=top&zoom=1.5";

var pdf = renderer.RenderUrlAsPdf(url);
pdf.SaveAs("top-view.pdf");
Enter fullscreen mode Exit fullscreen mode

Or inject JavaScript before rendering:

var html = @"
<script src='https://example.com/viewer.js'></script>
<script>
  viewer.setCamera({ position: [0, 10, 0], rotation: [90, 0, 0] });
</script>";

var pdf = renderer.RenderHtmlAsPdf(html);
Enter fullscreen mode Exit fullscreen mode

This sets the view before PDF capture.

Does This Work in Docker?

No. WebGL requires GPU access, and Docker containers are typically headless environments without GPU drivers.

Even with GPU passthrough, coordinating GPU access in a containerized environment is complex and unreliable for PDF rendering.

Run IronPDF with WebGL rendering on Windows or Linux systems with display capabilities, not in containers.

Can I Render Multiple WebGL PDFs Concurrently?

Be careful. GPU resources are limited. Rendering multiple WebGL scenes simultaneously can cause:

  • GPU memory exhaustion
  • Driver crashes
  • Blank canvases

Process WebGL PDFs sequentially or limit concurrency:

var urls = new[] { "url1", "url2", "url3" };

foreach (var url in urls)
{
    var pdf = renderer.RenderUrlAsPdf(url);
    pdf.SaveAs($"output-{Guid.NewGuid()}.pdf");

    // Give GPU time to recover
    System.Threading.Thread.Sleep(1000);
}
Enter fullscreen mode Exit fullscreen mode

I limit WebGL rendering to 2 concurrent operations max on our production servers.

What If the Canvas Is Still Blank?

Check GPU drivers: Ensure your system has up-to-date graphics drivers.

Increase delay: WebGL might need more time to load assets.

Verify SingleProcess: Without SingleProcess = true, WebGL won't work.

Check console errors: Enable JavaScript logging to see WebGL initialization errors:

renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.JavascriptMessageListener = msg => Console.WriteLine(msg);
Enter fullscreen mode Exit fullscreen mode

Common errors: WebGL context lost, shader compilation failures, texture loading errors.

How Do I Render Mapbox Maps?

Mapbox uses WebGL for vector tiles:

IronPdf.Installation.SingleProcess = true;
IronPdf.Installation.ChromeGpuMode = IronPdf.Engines.Chrome.ChromeGpuModes.Hardware;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.RenderDelay(8000); // Maps need time to load tiles

var pdf = renderer.RenderUrlAsPdf("https://www.mapbox.com/mapbox-gl-js/example/");
pdf.SaveAs("mapbox-map.pdf");
Enter fullscreen mode Exit fullscreen mode

Increase delay for maps with many layers or high zoom levels.

Can I Capture Animations?

No. PDFs are static. You capture a single frame at the moment rendering occurs.

For animated WebGL content, set the scene to a specific state before rendering:

// Pause animation
scene.stopAnimation();

// Set to desired frame
scene.setFrame(100);

// Signal ready for PDF capture
window.webglReady = true;
Enter fullscreen mode Exit fullscreen mode

Then use WaitFor.JavaScript("window.webglReady") to capture that frame.

What About WebGL 2?

WebGL 2 works the same way. Enable SingleProcess and Hardware GPU mode:

IronPdf.Installation.SingleProcess = true;
IronPdf.Installation.ChromeGpuMode = IronPdf.Engines.Chrome.ChromeGpuModes.Hardware;
Enter fullscreen mode Exit fullscreen mode

Both WebGL 1 and WebGL 2 contexts render correctly with these settings.

How Do I Test WebGL Rendering Locally?

Create a simple WebGL test page:

<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="800" height="600"></canvas>
<script>
  const canvas = document.getElementById('canvas');
  const gl = canvas.getContext('webgl');

  gl.clearColor(0.0, 0.5, 0.8, 1.0);
  gl.clear(gl.COLOR_BUFFER_BIT);

  // Draw a triangle
  // ... WebGL code ...

  document.body.insertAdjacentHTML('beforeend', '<div id="ready"></div>');
</script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Render it:

IronPdf.Installation.SingleProcess = true;
IronPdf.Installation.ChromeGpuMode = IronPdf.Engines.Chrome.ChromeGpuModes.Hardware;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.HtmlElementById("ready");

var pdf = renderer.RenderHtmlFileAsPdf("test-webgl.html");
pdf.SaveAs("test-output.pdf");
Enter fullscreen mode Exit fullscreen mode

If you see a blue canvas with a triangle, WebGL rendering works.


Written by Jacob Mellor, CTO at Iron Software. Jacob created IronPDF and leads a team of 50+ engineers building .NET document processing libraries.

Top comments (0)